diff --git a/simgear/misc/props.cxx b/simgear/misc/props.cxx index 2a66fba5..2ab7ad14 100644 --- a/simgear/misc/props.cxx +++ b/simgear/misc/props.cxx @@ -299,6 +299,7 @@ SGPropertyNode::SGPropertyNode () : _name(""), _index(0), _parent(0), + _path_cache(0), _type(NONE), _tied(false), _attr(READ|WRITE) @@ -313,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) @@ -351,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) + : _name(name), + _index(index), + _parent(parent), + _path_cache(0), + _type(NONE), + _tied(false), + _attr(READ|WRITE) { } @@ -365,6 +372,7 @@ SGPropertyNode::~SGPropertyNode () for (int i = 0; i < (int)_children.size(); i++) { delete _children[i]; } + delete _path_cache; clear_value(); } @@ -1278,21 +1286,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); +} //////////////////////////////////////////////////////////////////////// diff --git a/simgear/misc/props.hxx b/simgear/misc/props.hxx index b9a0157a..5ac1e5b3 100644 --- a/simgear/misc/props.hxx +++ b/simgear/misc/props.hxx @@ -18,10 +18,12 @@ #include STL_STRING #include +#include #include STL_IOSTREAM SG_USING_STD(string); SG_USING_STD(vector); +SG_USING_STD(map); #if !defined(SG_HAVE_NATIVE_SGI_COMPILERS) SG_USING_STD(istream); SG_USING_STD(ostream); @@ -688,12 +690,36 @@ public: SGPropertyNode * getNode (const string &relative_path, bool create = false); + /** + * Get a pointer to another node by relative path. + * + * This method leaves the index off the last member of the path, + * so that the user can specify it separately (and save some + * string building). For example, getNode("/bar[1]/foo", 3) is + * exactly equivalent to getNode("bar[1]/foo[3]"). The index + * provided overrides any given in the path itself for the last + * component. + */ + SGPropertyNode * getNode (const string &relative_path, int index, + bool create = false); + + /** * Get a const pointer to another node by relative path. */ const SGPropertyNode * getNode (const string &relative_path) const; + /** + * Get a const pointer to another node by relative path. + * + * This method leaves the index off the last member of the path, + * so that the user can specify it separate. + */ + const SGPropertyNode * getNode (const string &relative_path, + int index) const; + + // // Access Mode. // @@ -1062,8 +1088,8 @@ private: int _index; SGPropertyNode * _parent; vector _children; - - + typedef map cache_map; + cache_map * _path_cache; Type _type; bool _tied; int _attr;