/src/resiprocate/rutil/XMLCursor.hxx
Line | Count | Source |
1 | | #if !defined(RESIP_XMLCURSOR_HXX) |
2 | | #define RESIP_XMLCURSOR_HXX |
3 | | |
4 | | #include <iosfwd> |
5 | | #include <memory> |
6 | | #include <vector> |
7 | | |
8 | | #include "rutil/ParseBuffer.hxx" |
9 | | #include "rutil/HashMap.hxx" |
10 | | |
11 | | namespace resip |
12 | | { |
13 | | |
14 | | /* |
15 | | // XML tree traversal. |
16 | | // XMLCursor starts at the root. |
17 | | // The attributes and value of the cursor are those of the root. |
18 | | // To descend to the first child of the root, call firstChild(). |
19 | | // To traverse the children of root from root, call firstChild();nextSibling();nextSibling();... |
20 | | // To descend into the first child of the current element, call firstChild. |
21 | | // To return to the parent of the current element, call parent. |
22 | | // The traversal state among the siblings of the parent is maintained. |
23 | | // |
24 | | // root |
25 | | // / \ |
26 | | // P1 P2 |
27 | | // / \ / \ |
28 | | // A1 A2 B1 B2 |
29 | | // |
30 | | // atRoot() == true; |
31 | | // firstChild(); // P1 |
32 | | // firstChild(); // A1 |
33 | | // nextSibling(); // A2 |
34 | | // parent(); // P1 |
35 | | // nextSibling(); // P2 |
36 | | // firstChild(); // B1 |
37 | | // nextSibling(); // B2 |
38 | | // parent(); // P2 |
39 | | // nextSibling(); // false, stay at P2 |
40 | | // parent(); // root |
41 | | // nextSibling(); // false, stay at root |
42 | | // parent(); // false, stay at root |
43 | | // firstChild(); // P1 |
44 | | |
45 | | // E.g.: Depth first traversal |
46 | | // |
47 | | // void traverse(XMLCursor& c) |
48 | | // { |
49 | | // if (c.firstChild()) |
50 | | // { |
51 | | // traverse(c); |
52 | | // c.parent(); |
53 | | // } |
54 | | // |
55 | | // process(c); |
56 | | // |
57 | | // if (c.nextSibling()) |
58 | | // { |
59 | | // traverse(c); |
60 | | // } |
61 | | // } |
62 | | // |
63 | | // E.g.: Lexical Order traversal |
64 | | // |
65 | | // void |
66 | | // traverse(XMLCursor& c, int i = 0) |
67 | | // { |
68 | | // for (int ii = 0; ii < i; ++ii) |
69 | | // { |
70 | | // cerr << " "; |
71 | | // } |
72 | | |
73 | | // cerr << c.getTag(); |
74 | | // if (c.atLeaf()) |
75 | | // { |
76 | | // cerr << "[" << c.getValue() << "]" << endl; |
77 | | // } |
78 | | // else |
79 | | // { |
80 | | // cerr << endl; |
81 | | // } |
82 | | |
83 | | // if (c.firstChild()) |
84 | | // { |
85 | | // traverse(c, i+2); |
86 | | // c.parent(); |
87 | | // } |
88 | | |
89 | | // if (c.nextSibling()) |
90 | | // { |
91 | | // traverse(c, i+2); |
92 | | // } |
93 | | // } |
94 | | |
95 | | */ |
96 | | |
97 | | class XMLCursor |
98 | | { |
99 | | public: |
100 | | // !dlb! should be determined by the document |
101 | | // see http://www.w3.org/TR/1998/REC-xml-19980210#sec-white-space |
102 | | enum {WhitespaceSignificant = false}; |
103 | | |
104 | | XMLCursor(const ParseBuffer& pb); |
105 | | ~XMLCursor(); |
106 | | |
107 | | bool nextSibling(); |
108 | | bool firstChild(); |
109 | | bool parent(); |
110 | | void reset(); |
111 | | |
112 | | bool atRoot() const; |
113 | | bool atLeaf() const; |
114 | | |
115 | | const Data& getTag() const; |
116 | | typedef HashMap<Data, Data> AttributeMap; |
117 | | const AttributeMap& getAttributes() const; |
118 | | const Data& getValue() const; |
119 | | |
120 | | static EncodeStream& encode(EncodeStream& strm, const AttributeMap& attrs); |
121 | | class Node; |
122 | | |
123 | | class AttributeValueEqual |
124 | | { |
125 | | Data data_; |
126 | | public: |
127 | 0 | AttributeValueEqual(const Data& data) : data_(data) {}; |
128 | 0 | bool operator()(const std::pair<const Data, Data>& data) { return data.second == data_; } |
129 | | }; |
130 | | |
131 | | private: |
132 | | static void skipProlog(ParseBuffer& pb); |
133 | | static void decode(Data&); |
134 | | static void decodeName(Data&); |
135 | | |
136 | | void parseNextRootChild(); |
137 | | |
138 | | |
139 | | std::unique_ptr<Node> mRoot; |
140 | | Node* mCursor; |
141 | | |
142 | | //bool isEmpty; |
143 | | |
144 | | // store for undecoded root tag |
145 | | Data mTag; |
146 | | |
147 | | // store for copy of input if commented |
148 | | Data mData; |
149 | | |
150 | | // store date for decoding |
151 | | mutable Data mValue; |
152 | | // store attributes for reference |
153 | | mutable AttributeMap mAttributes; |
154 | | mutable bool mAttributesSet; |
155 | | |
156 | | public: |
157 | | class Node |
158 | | { |
159 | | public: |
160 | | Node(const ParseBuffer& pb); |
161 | | ~Node(); |
162 | | |
163 | | void addChild(Node*); |
164 | | // return true if <foo/> |
165 | | bool extractTag(); |
166 | | void skipToEndTag(); |
167 | | static const char* skipComments(ParseBuffer& pb); |
168 | | |
169 | | ParseBuffer mPb; |
170 | | Node* mParent; |
171 | | std::vector<Node*> mChildren; |
172 | | std::vector<Node*>::const_iterator mNext; |
173 | | |
174 | | bool mIsLeaf; |
175 | | Data mTag; |
176 | | |
177 | | private: |
178 | | Node(const Node&); |
179 | | Node& operator=(const Node&); |
180 | | |
181 | | friend EncodeStream& operator<<(EncodeStream& str, const XMLCursor& cursor); |
182 | | // friend EncodeStream& operator<<(EncodeStream& str, const XMLCursor::Node& cursor); // this line won't compile in windows |
183 | | }; |
184 | | private: |
185 | | friend EncodeStream& operator<<(EncodeStream&, const XMLCursor&); |
186 | | friend EncodeStream& operator<<(EncodeStream&, const XMLCursor::Node&); |
187 | | |
188 | | // no value semantics |
189 | | XMLCursor(const XMLCursor&); |
190 | | XMLCursor& operator=(const XMLCursor&); |
191 | | friend class Node; |
192 | | }; |
193 | | |
194 | | EncodeStream& |
195 | | operator<<(EncodeStream& str, const XMLCursor& cursor); |
196 | | |
197 | | EncodeStream& |
198 | | operator<<(EncodeStream& str, const XMLCursor::Node& cursor); |
199 | | |
200 | | } |
201 | | |
202 | | #endif |
203 | | |
204 | | /* ==================================================================== |
205 | | * The Vovida Software License, Version 1.0 |
206 | | * |
207 | | * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. |
208 | | * |
209 | | * Redistribution and use in source and binary forms, with or without |
210 | | * modification, are permitted provided that the following conditions |
211 | | * are met: |
212 | | * |
213 | | * 1. Redistributions of source code must retain the above copyright |
214 | | * notice, this list of conditions and the following disclaimer. |
215 | | * |
216 | | * 2. Redistributions in binary form must reproduce the above copyright |
217 | | * notice, this list of conditions and the following disclaimer in |
218 | | * the documentation and/or other materials provided with the |
219 | | * distribution. |
220 | | * |
221 | | * 3. The names "VOCAL", "Vovida Open Communication Application Library", |
222 | | * and "Vovida Open Communication Application Library (VOCAL)" must |
223 | | * not be used to endorse or promote products derived from this |
224 | | * software without prior written permission. For written |
225 | | * permission, please contact vocal@vovida.org. |
226 | | * |
227 | | * 4. Products derived from this software may not be called "VOCAL", nor |
228 | | * may "VOCAL" appear in their name, without prior written |
229 | | * permission of Vovida Networks, Inc. |
230 | | * |
231 | | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
232 | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
233 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND |
234 | | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA |
235 | | * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES |
236 | | * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, |
237 | | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
238 | | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
239 | | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
240 | | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
241 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
242 | | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
243 | | * DAMAGE. |
244 | | * |
245 | | * ==================================================================== |
246 | | * |
247 | | * This software consists of voluntary contributions made by Vovida |
248 | | * Networks, Inc. and many individuals on behalf of Vovida Networks, |
249 | | * Inc. For more information on Vovida Networks, Inc., please see |
250 | | * <http://www.vovida.org/>. |
251 | | * |
252 | | */ |