IECore::ConstInternedStringVectorDataPtr DeleteSets::computeSetNames( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstInternedStringVectorDataPtr inputSetNamesData = inPlug()->setNamesPlug()->getValue(); const std::vector<InternedString> &inputSetNames = inputSetNamesData->readable(); if( inputSetNames.empty() ) { return inputSetNamesData; } InternedStringVectorDataPtr outputSetNamesData = new InternedStringVectorData; std::vector<InternedString> &outputSetNames = outputSetNamesData->writable(); const std::string names = namesPlug()->getValue(); const bool invert = invertNamesPlug()->getValue(); for( std::vector<InternedString>::const_iterator it = inputSetNames.begin(); it != inputSetNames.end(); ++it ) { if( StringAlgo::matchMultiple( *it, names ) != (!invert) ) { outputSetNames.push_back( *it ); } } return outputSetNamesData; }
IECore::ConstInternedStringVectorDataPtr Isolate::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { ContextPtr tmpContext = filterContext( context ); Context::Scope scopedContext( tmpContext.get() ); if( mayPruneChildren( path, filterPlug()->getValue() ) ) { // we may need to delete one or more of our children ConstInternedStringVectorDataPtr inputChildNamesData = inPlug()->childNamesPlug()->getValue(); const vector<InternedString> &inputChildNames = inputChildNamesData->readable(); InternedStringVectorDataPtr outputChildNamesData = new InternedStringVectorData; vector<InternedString> &outputChildNames = outputChildNamesData->writable(); ScenePath childPath = path; childPath.push_back( InternedString() ); // for the child name for( vector<InternedString>::const_iterator it = inputChildNames.begin(), eIt = inputChildNames.end(); it != eIt; it++ ) { childPath[path.size()] = *it; tmpContext->set( ScenePlug::scenePathContextName, childPath ); if( filterPlug()->getValue() != Filter::NoMatch ) { outputChildNames.push_back( *it ); } } return outputChildNamesData; } else { // pass through return inPlug()->childNamesPlug()->getValue(); } }
IECore::ConstInternedStringVectorDataPtr Instancer::computeBranchChildNames( const ScenePath &parentPath, const ScenePath &branchPath, const Gaffer::Context *context ) const { if( branchPath.size() == 0 ) { std::string name = namePlug()->getValue(); if( !name.size() ) { return outPlug()->childNamesPlug()->defaultValue(); } ConstV3fVectorDataPtr p = sourcePoints( parentPath ); if( !p || !p->readable().size() ) { return outPlug()->childNamesPlug()->defaultValue(); } InternedStringVectorDataPtr result = new InternedStringVectorData(); for( size_t i=0; i<p->readable().size(); i++ ) { result->writable().push_back( boost::lexical_cast<string>( i ) ); } return result; } else { ContextPtr ic = instanceContext( context, branchPath ); Context::Scope scopedContext( ic ); return instancePlug()->childNamesPlug()->getValue(); } }
IECore::CompoundDataPtr LinkedScene::linkAttributeData( const SceneInterface *scene ) { std::string f = scene->fileName(); InternedStringVectorDataPtr r = new InternedStringVectorData(); scene->path( r->writable() ); CompoundDataPtr d = new CompoundData(); d->writable()[g_fileName] = new StringData(f); d->writable()[g_root] = r; return d; }
void Duplicate::compute( ValuePlug *output, const Context *context ) const { if( output == outParentPlug() ) { ScenePath target; ScenePlug::stringToPath( targetPlug()->getValue(), target ); string parent; for( size_t i = 0; i < target.size(); ++i ) { parent += "/"; if( i < target.size() - 1 ) { parent += target[i]; } } static_cast<StringPlug *>( output )->setValue( parent ); return; } else if( output == childNamesPlug() ) { // get the path to our target. ScenePath target; ScenePlug::stringToPath( targetPlug()->getValue(), target ); // throw if the target path doesn't exist in the input. we need to compute the input child names at the // parent for this, but it's not necessary to represent that in the hash, because it doesn't actually // affect our result (if we throw we will have no result). ScenePath parent( target ); parent.pop_back(); ConstInternedStringVectorDataPtr parentChildNamesData = inPlug()->childNames( parent ); vector<InternedString> parentChildNames = parentChildNamesData->readable(); if( find( parentChildNames.begin(), parentChildNames.end(), target.back() ) == parentChildNames.end() ) { throw Exception( boost::str( boost::format( "Target \"%s\" does not exist" ) % target.back().string() ) ); } // go ahead and generate our childnames by incrementing a numeric suffix on // the target name. std::string stem; int suffix = numericSuffix( target.back(), 0, &stem ); InternedStringVectorDataPtr childNames = new InternedStringVectorData; boost::format formatter( "%s%d" ); int copies = copiesPlug()->getValue(); for( int i = 0; i < copies; ++i ) { childNames->writable().push_back( boost::str( formatter % stem % ++suffix ) ); } static_cast<InternedStringVectorDataPlug *>( output )->setValue( childNames ); return; } BranchCreator::compute( output, context ); }
IECore::ConstInternedStringVectorDataPtr SceneReader::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { ConstSceneInterfacePtr s = scene( path ); if( !s ) { return parent->childNamesPlug()->defaultValue(); } // get the child names InternedStringVectorDataPtr resultData = new InternedStringVectorData; vector<InternedString> &result = resultData->writable(); s->childNames( result ); // filter out any which don't have the right tags std::string tagsString = tagsPlug()->getValue(); if( !tagsString.empty() ) { typedef boost::tokenizer<boost::char_separator<char> > Tokenizer; Tokenizer tagsTokenizer( tagsString, boost::char_separator<char>( " " ) ); vector<InternedString> tags; std::copy( tagsTokenizer.begin(), tagsTokenizer.end(), back_inserter( tags ) ); vector<InternedString>::iterator newResultEnd = result.begin(); SceneInterface::NameList childTags; for( vector<InternedString>::const_iterator cIt = result.begin(), cEIt = result.end(); cIt != cEIt; ++cIt ) { ConstSceneInterfacePtr child = s->child( *cIt ); childTags.clear(); child->readTags( childTags, IECore::SceneInterface::EveryTag ); bool childMatches = false; for( SceneInterface::NameList::const_iterator tIt = childTags.begin(), tEIt = childTags.end(); tIt != tEIt; ++tIt ) { if( find( tags.begin(), tags.end(), *tIt ) != tags.end() ) { childMatches = true; break; } } if( childMatches ) { *newResultEnd++ = *cIt; } } result.erase( newResultEnd, result.end() ); } return resultData; }
IECore::ConstInternedStringVectorDataPtr SceneReader::computeSetNames( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstSceneInterfacePtr s = scene( ScenePath() ); if( !s ) { return parent->setNamesPlug()->defaultValue(); } InternedStringVectorDataPtr result = new InternedStringVectorData(); s->readTags( result->writable(), SceneInterface::LocalTag | SceneInterface::DescendantTag ); return result; }
IECore::ConstInternedStringVectorDataPtr AlembicSource::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { if( AlembicInputPtr i = inputForPath( path ) ) { ConstStringVectorDataPtr c = i->childNames(); InternedStringVectorDataPtr result = new InternedStringVectorData; result->writable().insert( result->writable().end(), c->readable().begin(), c->readable().end() ); return result; } else { return parent->childNamesPlug()->defaultValue(); } }
IECore::ConstInternedStringVectorDataPtr CompoundObjectSource::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const { ConstCompoundObjectPtr entry = entryForPath( path ); ConstCompoundObjectPtr children = entry->member<CompoundObject>( "children" ); if( !children ) { return outPlug()->childNamesPlug()->defaultValue(); } InternedStringVectorDataPtr result = new InternedStringVectorData; for( CompoundObject::ObjectMap::const_iterator it = children->members().begin(); it!=children->members().end(); it++ ) { result->writable().push_back( it->first.value() ); } return result; }
IECore::ConstInternedStringVectorDataPtr SceneReader::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { std::string fileName = fileNamePlug()->getValue(); if( !fileName.size() ) { return parent->childNamesPlug()->defaultValue(); } ConstSceneInterfacePtr s = SharedSceneInterfaces::get( fileName ); s = s->scene( path ); InternedStringVectorDataPtr result = new InternedStringVectorData; s->childNames( result->writable() ); return result; }
Gaffer::ContextPtr Instancer::instanceContext( const Gaffer::Context *parentContext, const ScenePath &branchPath ) const { if( branchPath.size() == 0 ) { return 0; } ContextPtr result = new Context( *parentContext ); InternedStringVectorDataPtr instancePath = new InternedStringVectorData; instancePath->writable().insert( instancePath->writable().end(), branchPath.begin() + 1, branchPath.end() ); result->set( ScenePlug::scenePathContextName, instancePath.get() ); result->set( "instancer:id", instanceIndex( branchPath ) ); return result; }
IECore::ConstInternedStringVectorDataPtr CompoundObjectSource::computeSetNames( const Gaffer::Context *context, const GafferScene::ScenePlug *parent ) const { ConstCompoundObjectPtr compoundObject = inObject(); if( ConstCompoundObjectPtr sets = compoundObject->member<CompoundObject>( "sets" ) ) { InternedStringVectorDataPtr resultData = new InternedStringVectorData; std::vector<InternedString> &result = resultData->writable(); for( CompoundObject::ObjectMap::const_iterator it = sets->members().begin(), eIt = sets->members().end(); it != eIt; ++it ) { result.push_back( it->first ); } return resultData; } return outPlug()->setNamesPlug()->defaultValue(); }
IECore::ConstInternedStringVectorDataPtr Set::computeSetNames( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstInternedStringVectorDataPtr inNamesData = inPlug()->setNamesPlug()->getValue(); const std::string &names = namePlug()->getValue(); if( !names.size() ) { return inNamesData; } if( modePlug()->getValue() == Remove ) { return inNamesData; } vector<InternedString> tokenizedNames; StringAlgo::tokenize( names, ' ', tokenizedNames ); // specific logic if we have only one item, to avoid the more complex logic of adding two lists together if( tokenizedNames.size() == 1 ) { const std::vector<InternedString> &inNames = inNamesData->readable(); if( std::find( inNames.begin(), inNames.end(), tokenizedNames[0] ) != inNames.end() ) { return inNamesData; } InternedStringVectorDataPtr resultData = inNamesData->copy(); resultData->writable().push_back( tokenizedNames[0] ); return resultData; } // inserting the new names into the vector // while making sure we don't have duplicates InternedStringVectorDataPtr resultData = inNamesData->copy(); std::vector<InternedString> &result = resultData->writable(); result.reserve( result.size() + tokenizedNames.size() ); std::copy( tokenizedNames.begin(), tokenizedNames.end(), std::back_inserter( result ) ); std::sort( result.begin(), result.end() ); std::vector<InternedString>::iterator it; it = std::unique( result.begin(), result.end() ); result.resize( std::distance( result.begin(), it ) ); return resultData; }
IECore::ConstInternedStringVectorDataPtr Seeds::computeBranchChildNames( const ScenePath &parentPath, const ScenePath &branchPath, const Gaffer::Context *context ) const { if( branchPath.size() == 0 ) { std::string name = namePlug()->getValue(); if( name.empty() ) { return outPlug()->childNamesPlug()->defaultValue(); } InternedStringVectorDataPtr result = new InternedStringVectorData(); result->writable().push_back( name ); return result; } else { return outPlug()->childNamesPlug()->defaultValue(); } }
IECore::ConstInternedStringVectorDataPtr Grid::computeChildNames( const SceneNode::ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { if( path.size() <= 1 ) { InternedStringVectorDataPtr resultData = new InternedStringVectorData; std::vector<InternedString> &result = resultData->writable(); if( path.size() == 0 ) { result.push_back( namePlug()->getValue() ); } else { result.push_back( g_gridLinesName ); result.push_back( g_centerLinesName ); result.push_back( g_borderLinesName ); } return resultData; } return outPlug()->childNamesPlug()->defaultValue(); }
IECore::ConstInternedStringVectorDataPtr Instancer::computeBranchChildNames( const ScenePath &parentPath, const ScenePath &branchPath, const Gaffer::Context *context ) const { if( branchPath.size() == 0 ) { // "/" std::string name = namePlug()->getValue(); if( name.empty() ) { return outPlug()->childNamesPlug()->defaultValue(); } InternedStringVectorDataPtr result = new InternedStringVectorData(); result->writable().push_back( name ); return result; } else if( branchPath.size() == 1 ) { ConstV3fVectorDataPtr p = sourcePoints( parentPath ); if( !p || !p->readable().size() ) { return outPlug()->childNamesPlug()->defaultValue(); } const size_t s = p->readable().size(); InternedStringVectorDataPtr resultData = new InternedStringVectorData(); vector<InternedString> &result = resultData->writable(); result.resize( s ); for( size_t i = 0; i < s ; ++i ) { result[i] = InternedString( i ); } return resultData; } else { InstanceScope instanceScope( context, branchPath ); return instancePlug()->childNamesPlug()->getValue(); } }
IECore::ConstInternedStringVectorDataPtr Group::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { std::string groupName = namePlug()->getValue(); if( path.size() == 0 ) { InternedStringVectorDataPtr result = new InternedStringVectorData(); result->writable().push_back( groupName ); return result; } else if( path.size() == 1 ) { ConstCompoundObjectPtr mapping = boost::static_pointer_cast<const CompoundObject>( mappingPlug()->getValue() ); return mapping->member<InternedStringVectorData>( "__GroupChildNames" ); } else { const ScenePlug *sourcePlug = 0; ScenePath source = sourcePath( path, groupName, &sourcePlug ); return sourcePlug->childNames( source ); } }
IECore::ConstInternedStringVectorDataPtr Group::computeSetNames( const Gaffer::Context *context, const ScenePlug *parent ) const { InternedStringVectorDataPtr resultData = new InternedStringVectorData; vector<InternedString> &result = resultData->writable(); for( ScenePlugIterator it( inPlugs() ); it != it.end(); ++it ) { // This naive approach to merging set names preserves the order of the incoming names, // but at the expense of using linear search. We assume that the number of sets is small // enough and the InternedString comparison fast enough that this is OK. ConstInternedStringVectorDataPtr inputSetNamesData = (*it)->setNamesPlug()->getValue(); const vector<InternedString> &inputSetNames = inputSetNamesData->readable(); for( vector<InternedString>::const_iterator it = inputSetNames.begin(), eIt = inputSetNames.end(); it != eIt; ++it ) { if( std::find( result.begin(), result.end(), *it ) == result.end() ) { result.push_back( *it ); } } } return resultData; }
IECore::ConstInternedStringVectorDataPtr BranchCreator::computeSetNames( const Gaffer::Context *context, const ScenePlug *parent ) const { ConstInternedStringVectorDataPtr inputSetNamesData = inPlug()->setNamesPlug()->getValue(); ConstCompoundDataPtr mapping = boost::static_pointer_cast<const CompoundData>( mappingPlug()->getValue() ); if( !mapping->readable().size() ) { return inputSetNamesData; } ConstInternedStringVectorDataPtr branchSetNamesData = computeBranchSetNames( mapping->member<InternedStringVectorData>( g_parentKey )->readable(), context ); if( !branchSetNamesData ) { return inputSetNamesData; } const vector<InternedString> &branchSetNames = branchSetNamesData->readable(); if( !branchSetNames.size() ) { return inputSetNamesData; } InternedStringVectorDataPtr resultData = inputSetNamesData->copy(); vector<InternedString> &result = resultData->writable(); // This naive approach to merging set names preserves the order of the incoming names, // but at the expense of using linear search. We assume that the number of sets is small // enough and the InternedString comparison fast enough that this is OK. for( vector<InternedString>::const_iterator it = branchSetNames.begin(), eIt = branchSetNames.end(); it != eIt; ++it ) { if( std::find( result.begin(), result.end(), *it ) == result.end() ) { result.push_back( *it ); } } return resultData; }
IECore::ConstInternedStringVectorDataPtr Prune::computeChildNames( const ScenePath &path, const Gaffer::Context *context, const ScenePlug *parent ) const { FilterPlug::SceneScope sceneScope( context, inPlug() ); const Filter::Result m = (Filter::Result)filterPlug()->getValue(); if( m & Filter::ExactMatch ) { return inPlug()->childNamesPlug()->defaultValue(); } else if( m & Filter::DescendantMatch ) { // we may need to delete one or more of our children ConstInternedStringVectorDataPtr inputChildNamesData = inPlug()->childNamesPlug()->getValue(); const vector<InternedString> &inputChildNames = inputChildNamesData->readable(); InternedStringVectorDataPtr outputChildNamesData = new InternedStringVectorData; vector<InternedString> &outputChildNames = outputChildNamesData->writable(); ScenePath childPath = path; childPath.push_back( InternedString() ); // for the child name for( vector<InternedString>::const_iterator it = inputChildNames.begin(), eIt = inputChildNames.end(); it != eIt; ++it ) { childPath[path.size()] = *it; sceneScope.set( ScenePlug::scenePathContextName, childPath ); if( !(filterPlug()->getValue() & Filter::ExactMatch) ) { outputChildNames.push_back( *it ); } } return outputChildNamesData; } else { // pass through return inPlug()->childNamesPlug()->getValue(); } }
void Duplicate::compute( ValuePlug *output, const Context *context ) const { if( output == outParentPlug() ) { ScenePath target; ScenePlug::stringToPath( targetPlug()->getValue(), target ); string parent; for( size_t i = 0; i < target.size(); ++i ) { parent += "/"; if( i < target.size() - 1 ) { parent += target[i]; } } static_cast<StringPlug *>( output )->setValue( parent ); return; } else if( output == childNamesPlug() ) { // get the path to our target. ScenePath target; ScenePlug::stringToPath( targetPlug()->getValue(), target ); // throw if the target path doesn't exist in the input. we need to compute the input child names at the // parent for this, but it's not necessary to represent that in the hash, because it doesn't actually // affect our result (if we throw we will have no result). ScenePath parent( target ); parent.pop_back(); ConstInternedStringVectorDataPtr parentChildNamesData = inPlug()->childNames( parent ); vector<InternedString> parentChildNames = parentChildNamesData->readable(); if( find( parentChildNames.begin(), parentChildNames.end(), target.back() ) == parentChildNames.end() ) { throw Exception( boost::str( boost::format( "Target \"%s\" does not exist" ) % target.back().string() ) ); } // go ahead and generate our childnames. // these are composed of a stem and possibly // a numeric suffix. we default to deriving // these from the name of the target. std::string stem; int suffix = StringAlgo::numericSuffix( target.back(), 0, &stem ); suffix++; const int copies = copiesPlug()->getValue(); const std::string name = namePlug()->getValue(); // if a name is provided explicitly, then // it overrides the name and suffix derived // from the target. if( name.size() ) { std::string nameStem; const int nameSuffix = StringAlgo::numericSuffix( name, &nameStem ); stem = nameStem; suffix = copies == 1 ? nameSuffix : max( nameSuffix, 1 ); } InternedStringVectorDataPtr childNamesData = new InternedStringVectorData; std::vector<InternedString> &childNames = childNamesData->writable(); childNames.reserve( copies ); if( suffix == -1 ) { assert( copies == 1 ); childNames.push_back( stem ); } else { boost::format formatter( "%s%d" ); for( int i = 0; i < copies; ++i ) { childNames.push_back( boost::str( formatter % stem % suffix++ ) ); } } static_cast<InternedStringVectorDataPlug *>( output )->setValue( childNamesData ); return; } BranchCreator::compute( output, context ); }
IECore::ObjectPtr Group::computeMapping( const Gaffer::Context *context ) const { /// \todo It might be more optimal to make our own Object subclass better tailored /// for passing the information we want. CompoundObjectPtr result = new CompoundObject(); InternedStringVectorDataPtr childNamesData = new InternedStringVectorData(); vector<InternedString> &childNames = childNamesData->writable(); result->members()["__GroupChildNames"] = childNamesData; ObjectVectorPtr forwardMappings = new ObjectVector; result->members()["__GroupForwardMappings"] = forwardMappings; boost::regex namePrefixSuffixRegex( "^(.*[^0-9]+)([0-9]+)$" ); boost::format namePrefixSuffixFormatter( "%s%d" ); set<InternedString> allNames; for( ScenePlugIterator it( inPlugs() ); it != it.end(); ++it ) { ConstInternedStringVectorDataPtr inChildNamesData = (*it)->childNames( ScenePath() ); CompoundDataPtr forwardMapping = new CompoundData; forwardMappings->members().push_back( forwardMapping ); const vector<InternedString> &inChildNames = inChildNamesData->readable(); for( vector<InternedString>::const_iterator cIt = inChildNames.begin(), ceIt = inChildNames.end(); cIt!=ceIt; cIt++ ) { InternedString name = *cIt; if( allNames.find( name ) != allNames.end() ) { // uniqueify the name /// \todo This code is almost identical to code in GraphComponent::setName(), /// is there a sensible place it can be shared? The primary obstacle is that /// each use has a different method of storing the existing names. string prefix = name; int suffix = 1; boost::cmatch match; if( regex_match( name.value().c_str(), match, namePrefixSuffixRegex ) ) { prefix = match[1]; suffix = boost::lexical_cast<int>( match[2] ); } do { name = boost::str( namePrefixSuffixFormatter % prefix % suffix ); suffix++; } while( allNames.find( name ) != allNames.end() ); } allNames.insert( name ); childNames.push_back( name ); forwardMapping->writable()[*cIt] = new InternedStringData( name ); CompoundObjectPtr entry = new CompoundObject; entry->members()["n"] = new InternedStringData( *cIt ); entry->members()["i"] = new IntData( it.base() - inPlugs()->children().begin() ); result->members()[name] = entry; } } return result; }
/// \todo This mapping is very similar to the one created by the Group node. Perhaps /// some generalisation of the two could form the basis for a nice unified HierarchyProcessor? /// In this case I think we would have a custom mapping class rather than just pass around /// CompoundData, and then parentAndBranchPaths() (or the future version of it) could be a method /// on the mapping object. IECore::ConstCompoundDataPtr BranchCreator::computeMapping( const Gaffer::Context *context ) const { // get the parent. currently this is simply retrieving the value of parentPlug(), // but if we wanted to support multiple parents in future, here we would find the // parent appropriate to the current "scene:path" context entry. /// \todo We should introduce a plug type which stores its values as a ScenePath directly. ScenePlug::ScenePath parent; string parentAsString = parentPlug()->getValue(); if( parentAsString.empty() ) { // no parent specified so no mapping needed return static_cast<const CompoundData *>( mappingPlug()->defaultValue() ); } ScenePlug::stringToPath( parentAsString, parent ); // see if we're interested in creating children or not. if we're not // we can early out. no innuendo intended. ConstInternedStringVectorDataPtr branchChildNamesData = computeBranchChildNames( parent, ScenePath(), context ); if( !branchChildNamesData->readable().size() ) { return static_cast<const CompoundData *>( mappingPlug()->defaultValue() ); } // create our result. in future it might be useful to create our datatype for this, // but for now we're just packing everything into a CompoundData. CompoundDataPtr result = new CompoundData; result->writable()["__BranchCreatorParent"] = new InternedStringVectorData( parent ); // calculate the child names for the result. this is the full list of child names // immediately below the parent. we need to be careful to ensure that we rename any // branch names which conflict with existing children of the parent. ConstInternedStringVectorDataPtr inChildNamesData = inPlug()->childNames( parent ); InternedStringVectorDataPtr childNamesData = new InternedStringVectorData(); const vector<InternedString> &inChildNames = inChildNamesData->readable(); const vector<InternedString> &branchChildNames = branchChildNamesData->readable(); vector<InternedString> &childNames = childNamesData->writable(); result->writable()["__BranchCreatorChildNames"] = childNamesData; set<InternedString> allNames; for( vector<InternedString>::const_iterator it = inChildNames.begin(); it != inChildNames.end(); ++it ) { allNames.insert( *it ); childNames.push_back( *it ); } boost::regex namePrefixSuffixRegex( "^(.*[^0-9]+)([0-9]+)$" ); boost::format namePrefixSuffixFormatter( "%s%d" ); for( vector<InternedString>::const_iterator it = branchChildNames.begin(); it != branchChildNames.end(); ++it ) { InternedString name = *it; if( allNames.find( name ) != allNames.end() ) { // uniqueify the name string prefix = name; int suffix = 1; boost::cmatch match; if( regex_match( name.value().c_str(), match, namePrefixSuffixRegex ) ) { prefix = match[1]; suffix = boost::lexical_cast<int>( match[2] ); } do { name = boost::str( namePrefixSuffixFormatter % prefix % suffix ); suffix++; } while( allNames.find( name ) != allNames.end() ); } allNames.insert( name ); childNames.push_back( name ); result->writable()[name] = new InternedStringData( *it ); } return result; }