reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
XMLCursor.hxx
Go to the documentation of this file.
1#if !defined(RESIP_XMLCURSOR_HXX)
2#define RESIP_XMLCURSOR_HXX
3
4#include <iosfwd>
5#include <memory>
6#include <vector>
7
9#include "rutil/HashMap.hxx"
11
12namespace resip
13{
14
15/*
16// XML tree traversal.
17// XMLCursor starts at the root.
18// The attributes and value of the cursor are those of the root.
19// To descend to the first child of the root, call firstChild().
20// To traverse the children of root from root, call firstChild();nextSibling();nextSibling();...
21// To descend into the first child of the current element, call firstChild.
22// To return to the parent of the current element, call parent.
23// The traversal state among the siblings of the parent is maintained.
24//
25// root
26// / \
27// P1 P2
28// / \ / \
29// A1 A2 B1 B2
30//
31// atRoot() == true;
32// firstChild(); // P1
33// firstChild(); // A1
34// nextSibling(); // A2
35// parent(); // P1
36// nextSibling(); // P2
37// firstChild(); // B1
38// nextSibling(); // B2
39// parent(); // P2
40// nextSibling(); // false, stay at P2
41// parent(); // root
42// nextSibling(); // false, stay at root
43// parent(); // false, stay at root
44// firstChild(); // P1
45
46// E.g.: Depth first traversal
47//
48// void traverse(XMLCursor& c)
49// {
50// if (c.firstChild())
51// {
52// traverse(c);
53// c.parent();
54// }
55//
56// process(c);
57//
58// if (c.nextSibling())
59// {
60// traverse(c);
61// }
62// }
63//
64// E.g.: Lexical Order traversal
65//
66// void
67// traverse(XMLCursor& c, int i = 0)
68// {
69// for (int ii = 0; ii < i; ++ii)
70// {
71// cerr << " ";
72// }
73
74// cerr << c.getTag();
75// if (c.atLeaf())
76// {
77// cerr << "[" << c.getValue() << "]" << endl;
78// }
79// else
80// {
81// cerr << endl;
82// }
83
84// if (c.firstChild())
85// {
86// traverse(c, i+2);
87// c.parent();
88// }
89
90// if (c.nextSibling())
91// {
92// traverse(c, i+2);
93// }
94// }
95
96*/
97
99{
100 public:
101 // !dlb! should be determined by the document
102 // see http://www.w3.org/TR/1998/REC-xml-19980210#sec-white-space
103 enum {WhitespaceSignificant = false};
104
105 XMLCursor(const ParseBuffer& pb);
106 ~XMLCursor();
107
108 bool nextSibling();
109 bool firstChild();
110 bool parent();
111 void reset();
112
113 bool atRoot() const;
114 bool atLeaf() const;
115
116 const Data& getTag() const;
117 // Iterates in document order, so attributes encode back out as they were read.
118 // Attribute names come from the network (PIDF, dialog-info, etc. bodies). With
119 // a plain HashMap a sender could pick names that all hash alike, turning parsing
120 // one element into quadratic work; the keyed hash prevents that (see KeyedDataHash).
123 static constexpr size_t MaxAttributes = 256;
130 static constexpr unsigned int MaxNestingDepth = 100;
131 const AttributeMap& getAttributes() const;
132 const Data& getValue() const;
133
134 static EncodeStream& encode(EncodeStream& strm, const AttributeMap& attrs);
135 class Node;
136
138 {
139 Data data_;
140 public:
141 AttributeValueEqual(const Data& data) : data_(data) {};
142 bool operator()(const std::pair<const Data, Data>& data) { return data.second == data_; }
143 };
144
145 private:
146 static void skipProlog(ParseBuffer& pb);
147 static void decode(Data&);
148 static void decodeName(Data&);
149
150 void parseNextRootChild();
151
152
153 std::unique_ptr<Node> mRoot;
154 Node* mCursor;
155
156 //bool isEmpty;
157
158 // store for undecoded root tag
159 Data mTag;
160
161 // store for copy of input if commented
162 Data mData;
163
164 // store date for decoding
165 mutable Data mValue;
166 // store attributes for reference
167 mutable AttributeMap mAttributes;
168 mutable bool mAttributesSet;
169
170public:
171 class Node
172 {
173 public:
174 Node(const ParseBuffer& pb);
175 ~Node();
176
177 void addChild(Node*);
178 // return true if <foo/>
179 bool extractTag();
180 // depth: levels below the root element, 1 for a child of the root
181 void skipToEndTag(unsigned int depth);
182 static const char* skipComments(ParseBuffer& pb);
183
186 std::vector<Node*> mChildren;
187 std::vector<Node*>::const_iterator mNext;
188
191
192 private:
193 Node(const Node&);
194 Node& operator=(const Node&);
195
196 friend EncodeStream& operator<<(EncodeStream& str, const XMLCursor& cursor);
197 // friend EncodeStream& operator<<(EncodeStream& str, const XMLCursor::Node& cursor); // this line won't compile in windows
198 };
199 private:
202
203 // no value semantics
204 XMLCursor(const XMLCursor&);
205 XMLCursor& operator=(const XMLCursor&);
206 friend class Node;
207};
208
211
214
215}
216
217#endif
218
219/* ====================================================================
220 * The Vovida Software License, Version 1.0
221 *
222 * Copyright (c) 2026 SIP Spectrum, Inc. https://www.sipspectrum.com
223 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
224 *
225 * Redistribution and use in source and binary forms, with or without
226 * modification, are permitted provided that the following conditions
227 * are met:
228 *
229 * 1. Redistributions of source code must retain the above copyright
230 * notice, this list of conditions and the following disclaimer.
231 *
232 * 2. Redistributions in binary form must reproduce the above copyright
233 * notice, this list of conditions and the following disclaimer in
234 * the documentation and/or other materials provided with the
235 * distribution.
236 *
237 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
238 * and "Vovida Open Communication Application Library (VOCAL)" must
239 * not be used to endorse or promote products derived from this
240 * software without prior written permission. For written
241 * permission, please contact vocal@vovida.org.
242 *
243 * 4. Products derived from this software may not be called "VOCAL", nor
244 * may "VOCAL" appear in their name, without prior written
245 * permission of Vovida Networks, Inc.
246 *
247 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
248 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
249 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
250 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
251 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
252 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
253 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
254 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
255 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
256 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
258 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
259 * DAMAGE.
260 *
261 * ====================================================================
262 *
263 * This software consists of voluntary contributions made by Vovida
264 * Networks, Inc. and many individuals on behalf of Vovida Networks,
265 * Inc. For more information on Vovida Networks, Inc., please see
266 * <http://www.vovida.org/>.
267 *
268 */
Wraps your platform's implementation of hash_map, hash_multimap, and hash_set.
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
A hash map that iterates in insertion order, so a container filled while parsing (eg.
Provides string-parsing functionality with protection from buffer overflow.
bool operator()(const std::pair< const Data, Data > &data)
void skipToEndTag(unsigned int depth)
std::vector< Node * > mChildren
friend EncodeStream & operator<<(EncodeStream &str, const XMLCursor &cursor)
static const char * skipComments(ParseBuffer &pb)
std::vector< Node * >::const_iterator mNext
const Data & getValue() const
friend EncodeStream & operator<<(EncodeStream &, const XMLCursor::Node &)
static constexpr size_t MaxAttributes
getAttributes() fails (ParseException) an element with more attributes than this
bool atLeaf() const
const Data & getTag() const
const AttributeMap & getAttributes() const
LinkedHashMap< Data, Data, KeyedDataHash > AttributeMap
static EncodeStream & encode(EncodeStream &strm, const AttributeMap &attrs)
bool atRoot() const
friend EncodeStream & operator<<(EncodeStream &, const XMLCursor &)
static constexpr unsigned int MaxNestingDepth
Parsing fails (ParseException) a document with elements nested more than this many levels below the r...
dcm! – add UnusedChecking(_enum) below;
EncodeStream & operator<<(EncodeStream &strm, const BaseException &e)
#define EncodeStream
void list()
Definition userAdmin.cxx:66