X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fprops%2Fprops.cxx;h=09b71fb44c6b91a158fdefd0a86707d65f665cd7;hb=e24e3c06122dcba0d15a3d01be8957bb6b96d739;hp=fce6e8ab31c54c0ec0c3db3f2dbccb593e9cadb5;hpb=ce67657e0a69faef0ac8ab7660b12beb97cd6799;p=simgear.git diff --git a/simgear/props/props.cxx b/simgear/props/props.cxx index fce6e8ab..09b71fb4 100644 --- a/simgear/props/props.cxx +++ b/simgear/props/props.cxx @@ -11,9 +11,12 @@ #endif #include "props.hxx" +#include "vectorPropTemplates.hxx" #include +#include +#include #include #include #include @@ -27,8 +30,6 @@ #include #include -#include - #if PROPS_STANDALONE #include #else @@ -217,6 +218,26 @@ find_last_child (const char * name, const PropertyList& nodes) return index; } +/** + * Get first unused index for child nodes with the given name + */ +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::max(); ++index ) + { + if( find_child(name, nameEnd, index, nodes) < 0 ) + return index; + } + + SG_LOG(SG_GENERAL, SG_ALERT, "Too much nodes: " << name); + return -1; +} + template inline SGPropertyNode* SGPropertyNode::getExistingChild (Itr begin, Itr end, int index, bool create) @@ -642,7 +663,7 @@ SGPropertyNode::trace_read () const * Last used attribute * Update as needed when enum Attribute is changed */ -const int SGPropertyNode::LAST_USED_ATTRIBUTE = USERARCHIVE; +const int SGPropertyNode::LAST_USED_ATTRIBUTE = PRESERVE; /** * Default constructor: always creates a root node. @@ -664,7 +685,8 @@ SGPropertyNode::SGPropertyNode () * Copy constructor. */ SGPropertyNode::SGPropertyNode (const SGPropertyNode &node) - : _index(node._index), + : SGReferenced(node), + _index(node._index), _name(node._name), _parent(0), // don't copy the parent _type(node._type), @@ -777,13 +799,41 @@ SGPropertyNode::~SGPropertyNode () bool SGPropertyNode::alias (SGPropertyNode * target) { - if (target == 0 || _type == props::ALIAS || _tied) - return false; - clearValue(); - get(target); - _value.alias = target; - _type = props::ALIAS; - return true; + if (target && (_type != props::ALIAS) && (!_tied)) + { + clearValue(); + get(target); + _value.alias = target; + _type = props::ALIAS; + return true; + } + +#if PROPS_STANDALONE +#else + if (!target) + { + SG_LOG(SG_GENERAL, SG_ALERT, + "Failed to create alias for " << getPath() << ". " + "The target property does not exist."); + } + else + if (_type == props::ALIAS) + { + if (_value.alias == target) + return true; // ok, identical alias requested + SG_LOG(SG_GENERAL, SG_ALERT, + "Failed to create alias at " << target->getPath() << ". " + "Source "<< getPath() << " is already aliasing another property."); + } + else + if (_tied) + { + SG_LOG(SG_GENERAL, SG_ALERT, "Failed to create alias at " << target->getPath() << ". " + "Source " << getPath() << " is a tied property."); + } +#endif + + return false; } @@ -830,9 +880,11 @@ SGPropertyNode::getAliasTarget () const * create a non-const child by name after the last node with the same name. */ SGPropertyNode * -SGPropertyNode::addChild (const char * name) +SGPropertyNode::addChild(const char * name, int min_index, bool append) { - int pos = find_last_child(name, _children)+1; + int pos = append + ? std::max(find_last_child(name, _children) + 1, min_index) + : first_unused_index(name, _children, min_index); SGPropertyNode_ptr node; node = new SGPropertyNode(name, name + strlen(name), pos, this); @@ -841,6 +893,52 @@ SGPropertyNode::addChild (const char * name) return node; } +/** + * Create multiple children with unused indices + */ +simgear::PropertyList +SGPropertyNode::addChildren( const std::string& name, + size_t count, + int min_index, + bool append ) +{ + simgear::PropertyList nodes; + std::set used_indices; + + if( !append ) + { + // First grab all used indices. This saves us of testing every index if it + // is used for every element to be created + for( size_t i = 0; i < nodes.size(); i++ ) + { + const SGPropertyNode* node = nodes[i]; + + if( node->getNameString() == name && node->getIndex() >= min_index ) + used_indices.insert(node->getIndex()); + } + } + else + { + // If we don't want to fill the holes just find last node + min_index = std::max(find_last_child(name.c_str(), _children) + 1, min_index); + } + + for( int index = min_index; + index < std::numeric_limits::max() && nodes.size() < count; + ++index ) + { + if( used_indices.find(index) == used_indices.end() ) + { + SGPropertyNode_ptr node; + node = new SGPropertyNode(name, index, this); + _children.push_back(node); + fireChildAdded(node); + nodes.push_back(node); + } + } + + return nodes; +} /** * Get a non-const child by index. @@ -1615,8 +1713,12 @@ bool SGPropertyNode::tie (const SGRawValue &rawValue, _tied = true; _value.val = rawValue.clone(); - if (useDefault) + if (useDefault) { + int save_attributes = getAttributes(); + setAttribute( WRITE, true ); setStringValue(old_val.c_str()); + setAttributes( save_attributes ); + } return true; }