+static int
+first_unused_index( const char * name,
+ const PropertyList& nodes,
+ int min_index )
+{
+ const char* nameEnd = name + strlen(name);
+
+ for( int index = min_index; index < std::numeric_limits<int>::max(); ++index )
+ {
+ if( find_child(name, nameEnd, index, nodes) < 0 )
+ return index;
+ }
+
+ SG_LOG(SG_GENERAL, SG_ALERT, "Too many nodes: " << name);
+ return -1;
+}
+
+template<typename Itr>
+inline SGPropertyNode*
+SGPropertyNode::getExistingChild (Itr begin, Itr end, int index)
+{
+ int pos = find_child(begin, end, index, _children);
+ if (pos >= 0)
+ return _children[pos];
+ return 0;
+}
+
+template<typename Itr>
+SGPropertyNode *
+SGPropertyNode::getChildImpl (Itr begin, Itr end, int index, bool create)
+{
+ SGPropertyNode* node = getExistingChild(begin, end, index);
+
+ if (node) {
+ return node;
+ } else if (create) {
+ node = new SGPropertyNode(begin, end, index, this);
+ _children.push_back(node);
+ fireChildAdded(node);
+ return node;
+ } else {
+ return 0;
+ }
+}
+
+template<typename SplitItr>
+SGPropertyNode*
+find_node_aux(SGPropertyNode * current, SplitItr& itr, bool create,
+ int last_index)
+{
+ typedef typename SplitItr::value_type Range;
+ // Run off the end of the list
+ if (current == 0) {
+ return 0;
+ }
+
+ // Success! This is the one we want.
+ if (itr.eof())
+ return current;
+ Range token = *itr;
+ // Empty name at this point is empty, not root.
+ if (token.empty())
+ return find_node_aux(current, ++itr, create, last_index);
+ Range name = parse_name(current, token);
+ if (equals(name, "."))
+ return find_node_aux(current, ++itr, create, last_index);
+ if (equals(name, "..")) {
+ SGPropertyNode * parent = current->getParent();
+ if (parent == 0)
+ throw std::string("attempt to move past root with '..'");
+ return find_node_aux(parent, ++itr, create, last_index);
+ }
+ int index = -1;
+ if (last_index >= 0) {
+ // If we are at the last token and last_index is valid, use
+ // last_index as the index value
+ bool lastTok = true;
+ while (!(++itr).eof()) {
+ if (!itr->empty()) {
+ lastTok = false;
+ break;
+ }
+ }
+ if (lastTok)
+ index = last_index;
+ } else {
+ ++itr;
+ }
+
+ if (index < 0) {
+ index = 0;
+ if (name.end() != token.end()) {
+ if (*name.end() == '[') {
+ typename Range::iterator i = name.end() + 1, end = token.end();
+ for (;i != end; ++i) {
+ if (isdigit(*i)) {
+ index = (index * 10) + (*i - '0');
+ } else {
+ break;
+ }
+ }
+ if (i == token.end() || *i != ']')
+ throw std::string("unterminated index (looking for ']')");
+ } else {
+ throw std::string("illegal characters in token: ")
+ + std::string(name.begin(), name.end());
+ }
+ }
+ }
+ return find_node_aux(current->getChildImpl(name.begin(), name.end(),
+ index, create), itr, create,
+ last_index);
+}
+
+// Internal function for parsing property paths. last_index provides
+// and index value for the last node name token, if supplied.
+#if PROPS_STANDALONE