CDataNode* CDataNode::Structure( const CString& nodeName , const CString& attribName , const CString& attribSequence , const char seperator ) {GUCEF_TRACE; // Prepare some variables for the first loop iteration CDataNode* node = this; CString attSeqRemnant = attribSequence; CString attValue = attSeqRemnant.SubstrToChar( seperator ); bool childExists = true; CDataNode* childNode = NULL; do { // First we check if we can skip the search for a child node // This is a minor optimization if ( childExists ) { // See if there already is a node of the given type childNode = node->FindChild( nodeName , attribName , attValue ); if ( childNode == NULL ) { childExists = false; } } // Check if we have to create a new node if ( childNode == NULL ) { // No such node exists, we will create it CDataNode newChild( nodeName ); newChild.AddAttribute( attribName, attValue ); childNode = node->AddChild( newChild ); } node = childNode; // Get the next segment attSeqRemnant = attSeqRemnant.CutChars( attValue.Length()+1, true ); attValue = attSeqRemnant.SubstrToChar( seperator ); } while ( attSeqRemnant.Length() > 0 ); return childNode; }
CDataNode* CDataNode::Structure( const CString& sequence , char seperator ) {GUCEF_TRACE; // walk the tree CString buildseg; TDataNodeVector walkResults = WalkTree( sequence , seperator , buildseg ); // do we need to add nodes ? if ( 0 < buildseg.Length() ) { CDataNode* parentNode = this; if ( !walkResults.empty() ) parentNode = *walkResults.begin(); CDataNode child; CString name; while ( buildseg.Length() ) { name = buildseg.SubstrToChar( seperator, true ); child.SetName( name ); buildseg = buildseg.CutChars( name.Length()+1, true ); parentNode = parentNode->AddChild( child ); } return parentNode; } if ( walkResults.empty() ) return nullptr; return *walkResults.begin(); }
CDataNode::TDataNodeVector CDataNode::WalkTreeImp( CString& sleftover , char seperator ) const {GUCEF_TRACE; if ( !m_children.empty() ) { TDataNodeVector resultSet; CDataNode* sn = (CDataNode*) this; CString searchseg( sleftover.SubstrToChar( seperator, true ) ); CString left( sleftover.CutChars( searchseg.Length()+1, true ) ); CString bestMatchLeftover( left ); CDataNode* n = m_children.front(); while ( n ) { // Are we looking for more nesting or a leaf node? if ( 0 == left.Length() ) { // We are looking for a leaf node. Check if the current child matches if ( n->_name == searchseg ) { // nothing left to search for, so // no point in continuing resultSet.push_back( n ); } } else { // check if this node could be a link in the search chain if ( n->_name == searchseg ) { // search the tree for our leftover CString childLeftover = left; TDataNodeVector childResultSet = n->WalkTreeImp( childLeftover, seperator ); // if what we found is better then what we found so far then // substitute the current deepest nodes with the new deeper nodes. if ( bestMatchLeftover.Length() > childLeftover.Length() ) { // We found a better match, switch to that one resultSet = childResultSet; bestMatchLeftover = childLeftover; } else if ( bestMatchLeftover.Length() == childLeftover.Length() ) { // We found more equally good matches TDataNodeVector::iterator m = childResultSet.begin(); while ( m != childResultSet.end() ) { resultSet.push_back( (*m) ); ++m; } } } } n = n->_pnext; } if ( !resultSet.empty() ) sleftover = bestMatchLeftover; return resultSet; } TDataNodeVector resultSet; resultSet.push_back( const_cast<CDataNode*>( this ) ); return resultSet; }
CDataNode::TDataNodeVector CDataNode::SearchForAll( const CString& query , char seperator , bool fromcurrent , bool treatChildAsCurrent ) const {GUCEF_TRACE; if ( fromcurrent ) { CString thisname( query.SubstrToChar( seperator, true ) ); if ( thisname == _name ) { CString remnant( query.CutChars( thisname.Length()+1, true ) ); if ( remnant.Length() > 0 ) { CString leftover; TDataNodeVector results = WalkTree( remnant , seperator , leftover ); if ( 0 == leftover.Length() ) { return results; } } else { // this node is the leaf node we are searching for TDataNodeVector result; result.push_back( const_cast< CDataNode* >( this ) ); return result; } } else if ( treatChildAsCurrent ) { TDataNodeVector results; TDataNodeList::const_iterator i = m_children.begin(); while ( i != m_children.end() ) { TDataNodeVector childResults = (*i)->SearchForAll( query , seperator , fromcurrent , false ); TDataNodeVector::iterator n = childResults.begin(); while ( n != childResults.end() ) { results.push_back( (*n) ); ++n; } ++i; } return results; } return TDataNodeVector(); } else { CString leftover; TDataNodeVector results = WalkTree( query , seperator , leftover ); if ( 0 == leftover.Length() ) { return results; } return TDataNodeVector(); } }