X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmisc%2Fprops.cxx;h=83a2ef320b3a28b509d5f0dba144e3f408f906ed;hb=2d1b2ca93836bbb6498e67445dfbf5d5a3593331;hp=5c835c50cb84f8e82554af7ef6d6b5ddf3c3ddef;hpb=d063b319e8084847bcec80f3778f5493d356227c;p=simgear.git diff --git a/simgear/misc/props.cxx b/simgear/misc/props.cxx index 5c835c50..83a2ef32 100644 --- a/simgear/misc/props.cxx +++ b/simgear/misc/props.cxx @@ -7,6 +7,7 @@ // $Id$ #include +#include #include #include @@ -42,6 +43,9 @@ public: #define TEST_READ(dflt) if (!getAttribute(READ)) return dflt #define TEST_WRITE if (!getAttribute(WRITE)) return false +#define DO_TRACE_READ(type) if(getAttribute(TRACE_READ)) trace_read(type) +#define DO_TRACE_WRITE(type) if (getAttribute(TRACE_WRITE)) trace_write(type) + #define GET_BOOL (_value.bool_val->getValue()) #define GET_INT (_value.int_val->getValue()) #define GET_LONG (_value.long_val->getValue()) @@ -295,9 +299,10 @@ SGPropertyNode::SGPropertyNode () : _name(""), _index(0), _parent(0), + _path_cache(0), _type(NONE), _tied(false), - _attr(READ|WRITE|ARCHIVE) + _attr(READ|WRITE) { } @@ -309,6 +314,7 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node) : _name(node._name), _index(node._index), _parent(0), // don't copy the parent + _path_cache(0), _type(node._type), _tied(node._tied), _attr(node._attr) @@ -347,8 +353,13 @@ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node) */ SGPropertyNode::SGPropertyNode (const string &name, int index, SGPropertyNode * parent) - : _name(name), _index(index), _parent(parent), _type(NONE), - _tied(false), _attr(READ|WRITE|ARCHIVE) + : _name(name), + _index(index), + _parent(parent), + _path_cache(0), + _type(NONE), + _tied(false), + _attr(READ|WRITE) { } @@ -358,8 +369,10 @@ SGPropertyNode::SGPropertyNode (const string &name, */ SGPropertyNode::~SGPropertyNode () { - for (int i = 0; i < (int)_children.size(); i++) + for (int i = 0; i < (int)_children.size(); i++) { delete _children[i]; + } + delete _path_cache; clear_value(); } @@ -405,6 +418,67 @@ SGPropertyNode::clear_value () } +/** + * Get the value as a string. + */ +string +SGPropertyNode::get_string () const +{ + TEST_READ(""); + char buf[128]; + + switch (_type) { + case ALIAS: + return _value.alias->getStringValue(); + case BOOL: + if (GET_BOOL) + return "true"; + else + return "false"; + case INT: + sprintf(buf, "%d", GET_INT); + return buf; + case LONG: + sprintf(buf, "%ld", GET_LONG); + return buf; + case FLOAT: + sprintf(buf, "%f", GET_FLOAT); + return buf; + case DOUBLE: + sprintf(buf, "%f", GET_DOUBLE); + return buf; + case STRING: + case UNSPECIFIED: + return GET_STRING; + case NONE: + default: + return ""; + } +} + + +/** + * Trace a read access for a property. + */ +void +SGPropertyNode::trace_read (SGPropertyNode::Type accessType) const +{ + SG_LOG(SG_GENERAL, SG_INFO, "TRACE: Read node " << getPath() + << ", value \"" << get_string() << '"'); +} + + +/** + * Trace a write access for a property. + */ +void +SGPropertyNode::trace_write (SGPropertyNode::Type accessType) const +{ + SG_LOG(SG_GENERAL, SG_INFO, "TRACE: Write node " << getPath() + << ", value\"" << get_string() << '"'); +} + + /** * Alias to another node. */ @@ -585,6 +659,7 @@ SGPropertyNode::getType () const bool SGPropertyNode::getBoolValue () const { + DO_TRACE_READ(BOOL); TEST_READ(false); switch (_type) { case ALIAS: @@ -602,14 +677,16 @@ SGPropertyNode::getBoolValue () const case STRING: case UNSPECIFIED: return (GET_STRING == "true" || getDoubleValue() != 0.0L); + case NONE: + default: + return false; } - - return false; // if NONE } int SGPropertyNode::getIntValue () const { + DO_TRACE_READ(INT); TEST_READ(0); switch (_type) { case ALIAS: @@ -627,14 +704,16 @@ SGPropertyNode::getIntValue () const case STRING: case UNSPECIFIED: return atoi(GET_STRING.c_str()); + case NONE: + default: + return 0; } - - return 0; // if NONE } long SGPropertyNode::getLongValue () const { + DO_TRACE_READ(LONG); TEST_READ(0L); switch (_type) { case ALIAS: @@ -652,14 +731,16 @@ SGPropertyNode::getLongValue () const case STRING: case UNSPECIFIED: return strtol(GET_STRING.c_str(), 0, 0); + case NONE: + default: + return 0L; } - - return 0L; // if NONE } float SGPropertyNode::getFloatValue () const { + DO_TRACE_READ(FLOAT); TEST_READ(0.0); switch (_type) { case ALIAS: @@ -677,14 +758,16 @@ SGPropertyNode::getFloatValue () const case STRING: case UNSPECIFIED: return atof(GET_STRING.c_str()); + case NONE: + default: + return 0.0; } - - return 0.0; // if NONE } double SGPropertyNode::getDoubleValue () const { + DO_TRACE_READ(DOUBLE); TEST_READ(0.0L); switch (_type) { case ALIAS: @@ -702,48 +785,23 @@ SGPropertyNode::getDoubleValue () const case STRING: case UNSPECIFIED: return strtod(GET_STRING.c_str(), 0); + case NONE: + default: + return 0.0L; } - - return 0.0L; // if NONE } string SGPropertyNode::getStringValue () const { - TEST_READ(""); - char buf[128]; - - switch (_type) { - case ALIAS: - return _value.alias->getStringValue(); - case BOOL: - if (GET_BOOL) - return "true"; - else - return "false"; - case INT: - sprintf(buf, "%d", GET_INT); - return buf; - case LONG: - sprintf(buf, "%ld", GET_LONG); - return buf; - case FLOAT: - sprintf(buf, "%f", GET_FLOAT); - return buf; - case DOUBLE: - sprintf(buf, "%f", GET_DOUBLE); - return buf; - case STRING: - case UNSPECIFIED: - return GET_STRING; - } - - return ""; // if NONE + DO_TRACE_READ(STRING); + return get_string(); } bool SGPropertyNode::setBoolValue (bool value) { + bool result = false; TEST_WRITE; if (_type == NONE || _type == UNSPECIFIED) { clear_value(); @@ -753,27 +811,40 @@ SGPropertyNode::setBoolValue (bool value) switch (_type) { case ALIAS: - return _value.alias->setBoolValue(value); + result = _value.alias->setBoolValue(value); + break; case BOOL: - return SET_BOOL(value); + result = SET_BOOL(value); + break; case INT: - return SET_INT(int(value)); + result = SET_INT(int(value)); + break; case LONG: - return SET_LONG(long(value)); + result = SET_LONG(long(value)); + break; case FLOAT: - return SET_FLOAT(float(value)); + result = SET_FLOAT(float(value)); + break; case DOUBLE: - return SET_DOUBLE(double(value)); + result = SET_DOUBLE(double(value)); + break; case STRING: - return SET_STRING(value ? "true" : "false"); + case UNSPECIFIED: + result = SET_STRING(value ? "true" : "false"); + break; + case NONE: + default: + break; } - return false; // should never happen + DO_TRACE_WRITE(BOOL); + return result; } bool SGPropertyNode::setIntValue (int value) { + bool result = false; TEST_WRITE; if (_type == NONE || _type == UNSPECIFIED) { clear_value(); @@ -783,30 +854,43 @@ SGPropertyNode::setIntValue (int value) switch (_type) { case ALIAS: - return _value.alias->setIntValue(value); + result = _value.alias->setIntValue(value); + break; case BOOL: - return SET_BOOL(value == 0 ? false : true); + result = SET_BOOL(value == 0 ? false : true); + break; case INT: - return SET_INT(value); + result = SET_INT(value); + break; case LONG: - return SET_LONG(long(value)); + result = SET_LONG(long(value)); + break; case FLOAT: - return SET_FLOAT(float(value)); + result = SET_FLOAT(float(value)); + break; case DOUBLE: - return SET_DOUBLE(double(value)); - case STRING: { + result = SET_DOUBLE(double(value)); + break; + case STRING: + case UNSPECIFIED: { char buf[128]; sprintf(buf, "%d", value); - return SET_STRING(buf); + result = SET_STRING(buf); + break; } + case NONE: + default: + break; } - return false; // should never happen + DO_TRACE_WRITE(INT); + return result; } bool SGPropertyNode::setLongValue (long value) { + bool result = false; TEST_WRITE; if (_type == NONE || _type == UNSPECIFIED) { clear_value(); @@ -816,30 +900,43 @@ SGPropertyNode::setLongValue (long value) switch (_type) { case ALIAS: - return _value.alias->setLongValue(value); + result = _value.alias->setLongValue(value); + break; case BOOL: - return SET_BOOL(value == 0L ? false : true); + result = SET_BOOL(value == 0L ? false : true); + break; case INT: - return SET_INT(int(value)); + result = SET_INT(int(value)); + break; case LONG: - return SET_LONG(value); + result = SET_LONG(value); + break; case FLOAT: - return SET_FLOAT(float(value)); + result = SET_FLOAT(float(value)); + break; case DOUBLE: - return SET_DOUBLE(double(value)); - case STRING: { + result = SET_DOUBLE(double(value)); + break; + case STRING: + case UNSPECIFIED: { char buf[128]; - sprintf(buf, "%d", value); - return SET_STRING(buf); + sprintf(buf, "%ld", value); + result = SET_STRING(buf); + break; } + case NONE: + default: + break; } - return false; // should never happen + DO_TRACE_WRITE(LONG); + return result; } bool SGPropertyNode::setFloatValue (float value) { + bool result = false; TEST_WRITE; if (_type == NONE || _type == UNSPECIFIED) { clear_value(); @@ -849,30 +946,43 @@ SGPropertyNode::setFloatValue (float value) switch (_type) { case ALIAS: - return _value.alias->setFloatValue(value); + result = _value.alias->setFloatValue(value); + break; case BOOL: - return SET_BOOL(value == 0.0 ? false : true); + result = SET_BOOL(value == 0.0 ? false : true); + break; case INT: - return SET_INT(int(value)); + result = SET_INT(int(value)); + break; case LONG: - return SET_LONG(long(value)); + result = SET_LONG(long(value)); + break; case FLOAT: - return SET_FLOAT(value); + result = SET_FLOAT(value); + break; case DOUBLE: - return SET_DOUBLE(double(value)); - case STRING: { + result = SET_DOUBLE(double(value)); + break; + case STRING: + case UNSPECIFIED: { char buf[128]; sprintf(buf, "%f", value); - return SET_STRING(buf); + result = SET_STRING(buf); + break; } + case NONE: + default: + break; } - return false; // should never happen + DO_TRACE_WRITE(FLOAT); + return result; } bool SGPropertyNode::setDoubleValue (double value) { + bool result = false; TEST_WRITE; if (_type == NONE || _type == UNSPECIFIED) { clear_value(); @@ -882,30 +992,43 @@ SGPropertyNode::setDoubleValue (double value) switch (_type) { case ALIAS: - return _value.alias->setDoubleValue(value); + result = _value.alias->setDoubleValue(value); + break; case BOOL: - return SET_BOOL(value == 0.0L ? false : true); + result = SET_BOOL(value == 0.0L ? false : true); + break; case INT: - return SET_INT(int(value)); + result = SET_INT(int(value)); + break; case LONG: - return SET_LONG(long(value)); + result = SET_LONG(long(value)); + break; case FLOAT: - return SET_FLOAT(float(value)); + result = SET_FLOAT(float(value)); + break; case DOUBLE: - return SET_DOUBLE(value); - case STRING: { + result = SET_DOUBLE(value); + break; + case STRING: + case UNSPECIFIED: { char buf[128]; - sprintf(buf, "%lf", value); - return SET_STRING(buf); + sprintf(buf, "%f", value); + result = SET_STRING(buf); + break; } + case NONE: + default: + break; } - return false; // should never happen + DO_TRACE_WRITE(DOUBLE); + return result; } bool SGPropertyNode::setStringValue (string value) { + bool result = false; TEST_WRITE; if (_type == NONE || _type == UNSPECIFIED) { clear_value(); @@ -915,27 +1038,40 @@ SGPropertyNode::setStringValue (string value) switch (_type) { case ALIAS: - return _value.alias->setStringValue(value); + result = _value.alias->setStringValue(value); + break; case BOOL: - return SET_BOOL((value == "true" || atoi(value.c_str())) ? true : false); + result = SET_BOOL((value == "true" || atoi(value.c_str())) ? true : false); + break; case INT: - return SET_INT(atoi(value.c_str())); + result = SET_INT(atoi(value.c_str())); + break; case LONG: - return SET_LONG(strtol(value.c_str(), 0, 0)); + result = SET_LONG(strtol(value.c_str(), 0, 0)); + break; case FLOAT: - return SET_FLOAT(atof(value.c_str())); + result = SET_FLOAT(atof(value.c_str())); + break; case DOUBLE: - return SET_DOUBLE(strtod(value.c_str(), 0)); + result = SET_DOUBLE(strtod(value.c_str(), 0)); + break; case STRING: - return SET_STRING(value); + case UNSPECIFIED: + result = SET_STRING(value); + break; + case NONE: + default: + break; } - return false; // should never happen + DO_TRACE_WRITE(STRING); + return result; } bool SGPropertyNode::setUnspecifiedValue (string value) { + bool result = false; TEST_WRITE; if (_type == NONE) { clear_value(); @@ -945,23 +1081,34 @@ SGPropertyNode::setUnspecifiedValue (string value) switch (_type) { case ALIAS: - return _value.alias->setUnspecifiedValue(value); + result = _value.alias->setUnspecifiedValue(value); + break; case BOOL: - return SET_BOOL((value == "true" || atoi(value.c_str())) ? true : false); + result = SET_BOOL((value == "true" || atoi(value.c_str())) ? true : false); + break; case INT: - return SET_INT(atoi(value.c_str())); + result = SET_INT(atoi(value.c_str())); + break; case LONG: - return SET_LONG(strtol(value.c_str(), 0, 0)); + result = SET_LONG(strtol(value.c_str(), 0, 0)); + break; case FLOAT: - return SET_FLOAT(atof(value.c_str())); + result = SET_FLOAT(atof(value.c_str())); + break; case DOUBLE: - return SET_DOUBLE(strtod(value.c_str(), 0)); + result = SET_DOUBLE(strtod(value.c_str(), 0)); + break; case STRING: case UNSPECIFIED: - return SET_STRING(value); + result = SET_STRING(value); + break; + case NONE: + default: + break; } - return false; // should never happen + DO_TRACE_WRITE(UNSPECIFIED); + return result; } bool @@ -1138,7 +1285,8 @@ SGPropertyNode::untie () SET_DOUBLE(val); break; } - case STRING: { + case STRING: + case UNSPECIFIED: { string val = getStringValue(); clear_value(); _type = STRING; @@ -1146,6 +1294,9 @@ SGPropertyNode::untie () SET_STRING(val); break; } + case NONE: + default: + break; } _tied = false; @@ -1172,21 +1323,42 @@ SGPropertyNode::getRootNode () const SGPropertyNode * SGPropertyNode::getNode (const string &relative_path, bool create) +{ + if (_path_cache == 0) + _path_cache = new cache_map; + + SGPropertyNode * result = (*_path_cache)[relative_path]; + if (result == 0) { + vector components; + parse_path(relative_path, components); + result = find_node(this, components, 0, create); + (*_path_cache)[relative_path] = result; + } + + return result; +} + +SGPropertyNode * +SGPropertyNode::getNode (const string &relative_path, int index, bool create) { vector components; parse_path(relative_path, components); + if (components.size() > 0) + components[components.size()-1].index = index; return find_node(this, components, 0, create); } const SGPropertyNode * SGPropertyNode::getNode (const string &relative_path) const { - vector components; - parse_path(relative_path, components); - // FIXME: cast away const - return find_node((SGPropertyNode *)this, components, 0, false); + return ((SGPropertyNode *)this)->getNode(relative_path, false); } +const SGPropertyNode * +SGPropertyNode::getNode (const string &relative_path, int index) const +{ + return ((SGPropertyNode *)this)->getNode(relative_path, index, false); +} ////////////////////////////////////////////////////////////////////////