diff options
Diffstat (limited to 'src/smlnode.cpp')
-rw-r--r-- | src/smlnode.cpp | 123 |
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 | |||
5 | using namespace Bu; | ||
6 | |||
7 | SmlNode::SmlNode( Type eType, const Bu::String &sText, SmlNode *pParent ) : | ||
8 | eType( eType ), | ||
9 | sText( sText ), | ||
10 | pParent( pParent ) | ||
11 | { | ||
12 | } | ||
13 | |||
14 | SmlNode::~SmlNode() | ||
15 | { | ||
16 | } | ||
17 | |||
18 | SmlNode *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 | |||
88 | SmlNode *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 | |||
95 | Bu::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 | |||