summaryrefslogtreecommitdiff
path: root/src/smlnode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/smlnode.cpp')
-rw-r--r--src/smlnode.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/smlnode.cpp b/src/smlnode.cpp
new file mode 100644
index 0000000..a9e533d
--- /dev/null
+++ b/src/smlnode.cpp
@@ -0,0 +1,123 @@
1#include "smlnode.h"
2
3#include <bu/sio.h>
4
5using namespace Bu;
6
7SmlNode::SmlNode( Type eType, const Bu::String &sText, SmlNode *pParent ) :
8 eType( eType ),
9 sText( sText ),
10 pParent( pParent )
11{
12}
13
14SmlNode::~SmlNode()
15{
16}
17
18SmlNode *SmlNode::parse( const Bu::String &sSrc )
19{
20 SmlNode *pRoot = new SmlNode( SmlNode::typeRoot );
21 SmlNode *pCur = pRoot;
22 pRoot->eType = typeRoot;
23
24 enum Mode
25 {
26 mText,
27 mStartTag,
28 mEndTag,
29 };
30 Bu::String sTmp;
31 Mode mode = mText;
32 for( Bu::String::const_iterator i = sSrc.begin(); i; i++ )
33 {
34 if( *i == '\\' )
35 {
36 i++;
37 if( !i )
38 sTmp += '\\';
39 else if( *i == '[' || *i == ']' || *i == '<' || *i == '>' )
40 sTmp += *i;
41 }
42 else if( *i == '[' && mode == mText )
43 {
44 if( !sTmp.isEmpty() )
45 pCur->append( typeText, sTmp );
46 sTmp.clear();
47 mode = mStartTag;
48 }
49 else if( *i == '<' && mode == mText )
50 {
51 if( !sTmp.isEmpty() )
52 pCur->append( typeText, sTmp );
53 sTmp.clear();
54 mode = mEndTag;
55 }
56 else if( *i == '>' && mode == mStartTag )
57 {
58 pCur = pCur->append( typeTag, sTmp );
59 sTmp.clear();
60 mode = mText;
61 }
62 else if( *i == ']' && mode == mStartTag )
63 {
64 pCur->append( typeTag, sTmp );
65 sTmp.clear();
66 mode = mText;
67 }
68 else if( *i == ']' && mode == mEndTag )
69 {
70 if( sTmp != pCur->getText() )
71 throw Bu::ExceptionBase("Tag mismatch: [%s> != <%s]\n",
72 pCur->getText().getStr(), sTmp.getStr() );
73 pCur = pCur->getParent();
74 sTmp.clear();
75 mode = mText;
76 }
77 else
78 {
79 sTmp += *i;
80 }
81 }
82 if( !sTmp.isEmpty() )
83 pCur->append( typeText, sTmp );
84
85 return pRoot;
86}
87
88SmlNode *SmlNode::append( SmlNode::Type eType, const Bu::String &sText )
89{
90 SmlNode *pChild = new SmlNode( eType, sText, this );
91 lChildren.append( pChild );
92 return pChild;
93}
94
95Bu::Formatter &operator<<( Bu::Formatter &f, const SmlNode &n )
96{
97 switch( n.eType )
98 {
99 case SmlNode::typeRoot:
100 f.incIndent();
101 f << "Root {" << f.nl;
102 break;
103
104 case SmlNode::typeText:
105 return f << "Text: >>" << n.sText << "<<" << f.nl;
106 break;
107
108 case SmlNode::typeTag:
109 f.incIndent();
110 f << "Tag[" << n.sText << "] {" << f.nl;
111 break;
112 }
113
114 for( SmlNode::SmlNodeList::const_iterator i = n.lChildren.begin(); i; i++ )
115 {
116 f << *(*i);
117 }
118 f.decIndent();
119 f << "}" << f.nl;
120
121 return f;
122}
123