#include "smlnode.h" #include using namespace Bu; SmlNode::SmlNode( Type eType, const Bu::String &sText, SmlNode *pParent ) : eType( eType ), sText( sText ), pParent( pParent ) { } SmlNode::~SmlNode() { for( SmlNodeList::iterator i = lChildren.begin(); i; i++ ) { delete *i; } } SmlNode *SmlNode::parse( const Bu::String &sSrc ) { SmlNode *pRoot = new SmlNode( SmlNode::typeRoot ); SmlNode *pCur = pRoot; pRoot->eType = typeRoot; enum Mode { mText, mStartTag, mEndTag, }; Bu::String sTmp; Mode mode = mText; for( Bu::String::const_iterator i = sSrc.begin(); i; i++ ) { if( *i == '\\' ) { i++; if( !i ) sTmp += '\\'; else if( *i == '[' || *i == ']' || *i == '<' || *i == '>' ) sTmp += *i; } else if( *i == '[' && mode == mText ) { if( !sTmp.isEmpty() ) pCur->append( typeText, sTmp ); sTmp.clear(); mode = mStartTag; } else if( *i == '<' && mode == mText ) { if( !sTmp.isEmpty() ) pCur->append( typeText, sTmp ); sTmp.clear(); mode = mEndTag; } else if( *i == '>' && mode == mStartTag ) { pCur = pCur->append( typeTag, sTmp ); sTmp.clear(); mode = mText; } else if( *i == ']' && mode == mStartTag ) { pCur->append( typeTag, sTmp ); sTmp.clear(); mode = mText; } else if( *i == ']' && mode == mEndTag ) { if( sTmp != pCur->getText() ) throw Bu::ExceptionBase("Tag mismatch: [%s> != <%s]\n", pCur->getText().getStr(), sTmp.getStr() ); pCur = pCur->getParent(); sTmp.clear(); mode = mText; } else { sTmp += *i; } } if( !sTmp.isEmpty() ) pCur->append( typeText, sTmp ); return pRoot; } SmlNode *SmlNode::append( SmlNode::Type eType, const Bu::String &sText ) { SmlNode *pChild = new SmlNode( eType, sText, this ); lChildren.append( pChild ); return pChild; } Bu::Formatter &operator<<( Bu::Formatter &f, const SmlNode &n ) { switch( n.eType ) { case SmlNode::typeRoot: f.incIndent(); f << "Root {" << f.nl; break; case SmlNode::typeText: return f << "Text: >>" << n.sText << "<<" << f.nl; break; case SmlNode::typeTag: f.incIndent(); f << "Tag[" << n.sText << "] {" << f.nl; break; } for( SmlNode::SmlNodeList::const_iterator i = n.lChildren.begin(); i; i++ ) { f << *(*i); } f.decIndent(); f << "}" << f.nl; return f; }