Line data Source code
1 : /*
2 : Original code by Lee Thomason (www.grinninglizard.com)
3 :
4 : This software is provided 'as-is', without any express or implied
5 : warranty. In no event will the authors be held liable for any
6 : damages arising from the use of this software.
7 :
8 : Permission is granted to anyone to use this software for any
9 : purpose, including commercial applications, and to alter it and
10 : redistribute it freely, subject to the following restrictions:
11 :
12 : 1. The origin of this software must not be misrepresented; you must
13 : not claim that you wrote the original software. If you use this
14 : software in a product, an acknowledgment in the product documentation
15 : would be appreciated but is not required.
16 :
17 : 2. Altered source versions must be plainly marked as such, and
18 : must not be misrepresented as being the original software.
19 :
20 : 3. This notice may not be removed or altered from any source
21 : distribution.
22 : */
23 :
24 : #ifndef TINYXML2_INCLUDED
25 : #define TINYXML2_INCLUDED
26 :
27 : #if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)
28 : #include <ctype.h>
29 : #include <limits.h>
30 : #include <stdio.h>
31 : #include <stdlib.h>
32 : #include <string.h>
33 : #if defined(__PS3__)
34 : #include <stddef.h>
35 : #endif
36 : #else
37 : #include <cctype>
38 : #include <climits>
39 : #include <cstdio>
40 : #include <cstdlib>
41 : #include <cstring>
42 : #endif
43 : #include <stdint.h>
44 :
45 : /*
46 : gcc:
47 : g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
48 :
49 : Formatting, Artistic Style:
50 : AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
51 : */
52 :
53 : #if defined(_DEBUG) || defined(__DEBUG__)
54 : #ifndef TINYXML2_DEBUG
55 : #define TINYXML2_DEBUG
56 : #endif
57 : #endif
58 :
59 : #ifdef _MSC_VER
60 : #pragma warning(push)
61 : #pragma warning(disable : 4251)
62 : #endif
63 :
64 : #ifdef _MSC_VER
65 : #ifdef TINYXML2_EXPORT
66 : #define TINYXML2_LIB __declspec(dllexport)
67 : #elif defined(TINYXML2_IMPORT)
68 : #define TINYXML2_LIB __declspec(dllimport)
69 : #else
70 : #define TINYXML2_LIB
71 : #endif
72 : #elif __GNUC__ >= 4
73 : #define TINYXML2_LIB __attribute__((visibility("default")))
74 : #else
75 : #define TINYXML2_LIB
76 : #endif
77 :
78 : #if !defined(TIXMLASSERT)
79 : #if defined(TINYXML2_DEBUG)
80 : #if defined(_MSC_VER)
81 : #// "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
82 : #define TIXMLASSERT(x) \
83 : do { \
84 : if (!((void)0, (x))) { \
85 : __debugbreak(); \
86 : } \
87 : } while (false)
88 : #elif defined(ANDROID_NDK)
89 : #include <android/log.h>
90 : #define TIXMLASSERT(x) \
91 : do { \
92 : if (!(x)) { \
93 : __android_log_assert("assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__); \
94 : } \
95 : } while (false)
96 : #else
97 : #include <assert.h>
98 : #define TIXMLASSERT assert
99 : #endif
100 : #else
101 : #define TIXMLASSERT(x) \
102 : do { \
103 : } while (false)
104 : #endif
105 : #endif
106 :
107 : /* Versioning, past 1.0.14:
108 : http://semver.org/
109 : */
110 : static const int TIXML2_MAJOR_VERSION = 10;
111 : static const int TIXML2_MINOR_VERSION = 0;
112 : static const int TIXML2_PATCH_VERSION = 0;
113 :
114 : #define TINYXML2_MAJOR_VERSION 10
115 : #define TINYXML2_MINOR_VERSION 0
116 : #define TINYXML2_PATCH_VERSION 0
117 :
118 : // A fixed element depth limit is problematic. There needs to be a
119 : // limit to avoid a stack overflow. However, that limit varies per
120 : // system, and the capacity of the stack. On the other hand, it's a trivial
121 : // attack that can result from ill, malicious, or even correctly formed XML,
122 : // so there needs to be a limit in place.
123 : static const int TINYXML2_MAX_ELEMENT_DEPTH = 500;
124 :
125 : namespace tinyxml2 {
126 : class XMLDocument;
127 : class XMLElement;
128 : class XMLAttribute;
129 : class XMLComment;
130 : class XMLText;
131 : class XMLDeclaration;
132 : class XMLUnknown;
133 : class XMLPrinter;
134 :
135 : /*
136 : A class that wraps strings. Normally stores the start and end
137 : pointers into the XML file itself, and will apply normalization
138 : and entity translation if actually read. Can also store (and memory
139 : manage) a traditional char[]
140 :
141 : Isn't clear why TINYXML2_LIB is needed; but seems to fix #719
142 : */
143 : class TINYXML2_LIB StrPair {
144 : public:
145 : enum Mode {
146 : NEEDS_ENTITY_PROCESSING = 0x01,
147 : NEEDS_NEWLINE_NORMALIZATION = 0x02,
148 : NEEDS_WHITESPACE_COLLAPSING = 0x04,
149 :
150 : TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
151 : TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
152 : ATTRIBUTE_NAME = 0,
153 : ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
154 : ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
155 : COMMENT = NEEDS_NEWLINE_NORMALIZATION
156 : };
157 :
158 : StrPair() : _flags(0), _start(0), _end(0) {}
159 : ~StrPair();
160 :
161 : void Set(char* start, char* end, int flags) {
162 : TIXMLASSERT(start);
163 : TIXMLASSERT(end);
164 : Reset();
165 : _start = start;
166 : _end = end;
167 : _flags = flags | NEEDS_FLUSH;
168 : }
169 :
170 : const char* GetStr();
171 :
172 : bool Empty() const { return _start == _end; }
173 :
174 : void SetInternedStr(const char* str) {
175 : Reset();
176 : _start = const_cast<char*>(str);
177 : }
178 :
179 : void SetStr(const char* str, int flags = 0);
180 :
181 : char* ParseText(char* in, const char* endTag, int strFlags, int* curLineNumPtr);
182 : char* ParseName(char* in);
183 :
184 : void TransferTo(StrPair* other);
185 : void Reset();
186 :
187 : private:
188 : void CollapseWhitespace();
189 :
190 : enum { NEEDS_FLUSH = 0x100, NEEDS_DELETE = 0x200 };
191 :
192 : int _flags;
193 : char* _start;
194 : char* _end;
195 :
196 : StrPair(const StrPair& other); // not supported
197 : void operator=(const StrPair& other); // not supported, use TransferTo()
198 : };
199 :
200 : /*
201 : A dynamic array of Plain Old Data. Doesn't support constructors, etc.
202 : Has a small initial memory pool, so that low or no usage will not
203 : cause a call to new/delete
204 : */
205 : template <class T, int INITIAL_SIZE> class DynArray {
206 : public:
207 : DynArray() : _mem(_pool), _allocated(INITIAL_SIZE), _size(0) {}
208 :
209 : ~DynArray() {
210 : if (_mem != _pool) {
211 : delete[] _mem;
212 : }
213 : }
214 :
215 : void Clear() { _size = 0; }
216 :
217 : void Push(T t) {
218 : TIXMLASSERT(_size < INT_MAX);
219 : EnsureCapacity(_size + 1);
220 : _mem[_size] = t;
221 : ++_size;
222 : }
223 :
224 : T* PushArr(int count) {
225 : TIXMLASSERT(count >= 0);
226 : TIXMLASSERT(_size <= INT_MAX - count);
227 : EnsureCapacity(_size + count);
228 : T* ret = &_mem[_size];
229 : _size += count;
230 : return ret;
231 : }
232 :
233 : T Pop() {
234 : TIXMLASSERT(_size > 0);
235 : --_size;
236 : return _mem[_size];
237 : }
238 :
239 : void PopArr(int count) {
240 : TIXMLASSERT(_size >= count);
241 : _size -= count;
242 : }
243 :
244 : bool Empty() const { return _size == 0; }
245 :
246 : T& operator[](int i) {
247 : TIXMLASSERT(i >= 0 && i < _size);
248 : return _mem[i];
249 : }
250 :
251 : const T& operator[](int i) const {
252 : TIXMLASSERT(i >= 0 && i < _size);
253 : return _mem[i];
254 : }
255 :
256 : const T& PeekTop() const {
257 : TIXMLASSERT(_size > 0);
258 : return _mem[_size - 1];
259 : }
260 :
261 : int Size() const {
262 : TIXMLASSERT(_size >= 0);
263 : return _size;
264 : }
265 :
266 : int Capacity() const {
267 : TIXMLASSERT(_allocated >= INITIAL_SIZE);
268 : return _allocated;
269 : }
270 :
271 : void SwapRemove(int i) {
272 : TIXMLASSERT(i >= 0 && i < _size);
273 : TIXMLASSERT(_size > 0);
274 : _mem[i] = _mem[_size - 1];
275 : --_size;
276 : }
277 :
278 : const T* Mem() const {
279 : TIXMLASSERT(_mem);
280 : return _mem;
281 : }
282 :
283 : T* Mem() {
284 : TIXMLASSERT(_mem);
285 : return _mem;
286 : }
287 :
288 : private:
289 : DynArray(const DynArray&); // not supported
290 : void operator=(const DynArray&); // not supported
291 :
292 : void EnsureCapacity(int cap) {
293 : TIXMLASSERT(cap > 0);
294 : if (cap > _allocated) {
295 : TIXMLASSERT(cap <= INT_MAX / 2);
296 : const int newAllocated = cap * 2;
297 : T* newMem = new T[static_cast<unsigned int>(newAllocated)];
298 : TIXMLASSERT(newAllocated >= _size);
299 : memcpy(newMem, _mem, sizeof(T) * static_cast<size_t>(_size)); // warning: not using constructors, only works for PODs
300 : if (_mem != _pool) {
301 : delete[] _mem;
302 : }
303 : _mem = newMem;
304 : _allocated = newAllocated;
305 : }
306 : }
307 :
308 : T* _mem;
309 : T _pool[static_cast<size_t>(INITIAL_SIZE)];
310 : int _allocated; // objects allocated
311 : int _size; // number objects in use
312 : };
313 :
314 : /*
315 : Parent virtual class of a pool for fast allocation
316 : and deallocation of objects.
317 : */
318 : class MemPool {
319 : public:
320 : MemPool() {}
321 : virtual ~MemPool() {}
322 :
323 : virtual int ItemSize() const = 0;
324 : virtual void* Alloc() = 0;
325 : virtual void Free(void*) = 0;
326 : virtual void SetTracked() = 0;
327 : };
328 :
329 : /*
330 : Template child class to create pools of the correct type.
331 : */
332 : template <int ITEM_SIZE> class MemPoolT : public MemPool {
333 : public:
334 : MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
335 : ~MemPoolT() { MemPoolT<ITEM_SIZE>::Clear(); }
336 :
337 : void Clear() {
338 : // Delete the blocks.
339 : while (!_blockPtrs.Empty()) {
340 : Block* lastBlock = _blockPtrs.Pop();
341 : delete lastBlock;
342 : }
343 : _root = 0;
344 : _currentAllocs = 0;
345 : _nAllocs = 0;
346 : _maxAllocs = 0;
347 : _nUntracked = 0;
348 : }
349 :
350 : virtual int ItemSize() const override { return ITEM_SIZE; }
351 : int CurrentAllocs() const { return _currentAllocs; }
352 :
353 : virtual void* Alloc() override {
354 : if (!_root) {
355 : // Need a new block.
356 : Block* block = new Block;
357 : _blockPtrs.Push(block);
358 :
359 : Item* blockItems = block->items;
360 : for (int i = 0; i < ITEMS_PER_BLOCK - 1; ++i) {
361 : blockItems[i].next = &(blockItems[i + 1]);
362 : }
363 : blockItems[ITEMS_PER_BLOCK - 1].next = 0;
364 : _root = blockItems;
365 : }
366 : Item* const result = _root;
367 : TIXMLASSERT(result != 0);
368 : _root = _root->next;
369 :
370 : ++_currentAllocs;
371 : if (_currentAllocs > _maxAllocs) {
372 : _maxAllocs = _currentAllocs;
373 : }
374 : ++_nAllocs;
375 : ++_nUntracked;
376 : return result;
377 : }
378 :
379 : virtual void Free(void* mem) override {
380 : if (!mem) {
381 : return;
382 : }
383 : --_currentAllocs;
384 : Item* item = static_cast<Item*>(mem);
385 : #ifdef TINYXML2_DEBUG
386 : memset(item, 0xfe, sizeof(*item));
387 : #endif
388 : item->next = _root;
389 : _root = item;
390 : }
391 : void Trace(const char* name) {
392 : printf("Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs, ITEM_SIZE,
393 : _nAllocs, _blockPtrs.Size());
394 : }
395 :
396 : void SetTracked() override { --_nUntracked; }
397 :
398 : int Untracked() const { return _nUntracked; }
399 :
400 : // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
401 : // The test file is large, 170k.
402 : // Release: VS2010 gcc(no opt)
403 : // 1k: 4000
404 : // 2k: 4000
405 : // 4k: 3900 21000
406 : // 16k: 5200
407 : // 32k: 4300
408 : // 64k: 4000 21000
409 : // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK
410 : // in private part if ITEMS_PER_BLOCK is private
411 : enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };
412 :
413 : private:
414 : MemPoolT(const MemPoolT&); // not supported
415 : void operator=(const MemPoolT&); // not supported
416 :
417 : union Item {
418 : Item* next;
419 : char itemData[static_cast<size_t>(ITEM_SIZE)];
420 : };
421 : struct Block {
422 : Item items[ITEMS_PER_BLOCK];
423 : };
424 : DynArray<Block*, 10> _blockPtrs;
425 : Item* _root;
426 :
427 : int _currentAllocs;
428 : int _nAllocs;
429 : int _maxAllocs;
430 : int _nUntracked;
431 : };
432 :
433 : /**
434 : Implements the interface to the "Visitor pattern" (see the Accept() method.)
435 : If you call the Accept() method, it requires being passed a XMLVisitor
436 : class to handle callbacks. For nodes that contain other nodes (Document, Element)
437 : you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
438 : are simply called with Visit().
439 :
440 : If you return 'true' from a Visit method, recursive parsing will continue. If you return
441 : false, <b>no children of this node or its siblings</b> will be visited.
442 :
443 : All flavors of Visit methods have a default implementation that returns 'true' (continue
444 : visiting). You need to only override methods that are interesting to you.
445 :
446 : Generally Accept() is called on the XMLDocument, although all nodes support visiting.
447 :
448 : You should never change the document from a callback.
449 :
450 : @sa XMLNode::Accept()
451 : */
452 : class TINYXML2_LIB XMLVisitor {
453 : public:
454 : virtual ~XMLVisitor() {}
455 :
456 : /// Visit a document.
457 : virtual bool VisitEnter(const XMLDocument& /*doc*/) { return true; }
458 : /// Visit a document.
459 : virtual bool VisitExit(const XMLDocument& /*doc*/) { return true; }
460 :
461 : /// Visit an element.
462 : virtual bool VisitEnter(const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/) { return true; }
463 : /// Visit an element.
464 : virtual bool VisitExit(const XMLElement& /*element*/) { return true; }
465 :
466 : /// Visit a declaration.
467 : virtual bool Visit(const XMLDeclaration& /*declaration*/) { return true; }
468 : /// Visit a text node.
469 : virtual bool Visit(const XMLText& /*text*/) { return true; }
470 : /// Visit a comment node.
471 : virtual bool Visit(const XMLComment& /*comment*/) { return true; }
472 : /// Visit an unknown node.
473 : virtual bool Visit(const XMLUnknown& /*unknown*/) { return true; }
474 : };
475 :
476 : // WARNING: must match XMLDocument::_errorNames[]
477 : enum XMLError {
478 : XML_SUCCESS = 0,
479 : XML_NO_ATTRIBUTE,
480 : XML_WRONG_ATTRIBUTE_TYPE,
481 : XML_ERROR_FILE_NOT_FOUND,
482 : XML_ERROR_FILE_COULD_NOT_BE_OPENED,
483 : XML_ERROR_FILE_READ_ERROR,
484 : XML_ERROR_PARSING_ELEMENT,
485 : XML_ERROR_PARSING_ATTRIBUTE,
486 : XML_ERROR_PARSING_TEXT,
487 : XML_ERROR_PARSING_CDATA,
488 : XML_ERROR_PARSING_COMMENT,
489 : XML_ERROR_PARSING_DECLARATION,
490 : XML_ERROR_PARSING_UNKNOWN,
491 : XML_ERROR_EMPTY_DOCUMENT,
492 : XML_ERROR_MISMATCHED_ELEMENT,
493 : XML_ERROR_PARSING,
494 : XML_CAN_NOT_CONVERT_TEXT,
495 : XML_NO_TEXT_NODE,
496 : XML_ELEMENT_DEPTH_EXCEEDED,
497 :
498 : XML_ERROR_COUNT
499 : };
500 :
501 : /*
502 : Utility functionality.
503 : */
504 : class TINYXML2_LIB XMLUtil {
505 : public:
506 : static const char* SkipWhiteSpace(const char* p, int* curLineNumPtr) {
507 : TIXMLASSERT(p);
508 :
509 : while (IsWhiteSpace(*p)) {
510 : if (curLineNumPtr && *p == '\n') {
511 : ++(*curLineNumPtr);
512 : }
513 : ++p;
514 : }
515 : TIXMLASSERT(p);
516 : return p;
517 : }
518 : static char* SkipWhiteSpace(char* const p, int* curLineNumPtr) { return const_cast<char*>(SkipWhiteSpace(const_cast<const char*>(p), curLineNumPtr)); }
519 :
520 : // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
521 : // correct, but simple, and usually works.
522 : static bool IsWhiteSpace(char p) { return !IsUTF8Continuation(p) && isspace(static_cast<unsigned char>(p)); }
523 :
524 : inline static bool IsNameStartChar(unsigned char ch) {
525 : if (ch >= 128) {
526 : // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
527 : return true;
528 : }
529 : if (isalpha(ch)) {
530 : return true;
531 : }
532 : return ch == ':' || ch == '_';
533 : }
534 :
535 : inline static bool IsNameChar(unsigned char ch) { return IsNameStartChar(ch) || isdigit(ch) || ch == '.' || ch == '-'; }
536 :
537 : inline static bool IsPrefixHex(const char* p) {
538 : p = SkipWhiteSpace(p, 0);
539 : return p && *p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X');
540 : }
541 :
542 : inline static bool StringEqual(const char* p, const char* q, int nChar = INT_MAX) {
543 : if (p == q) {
544 : return true;
545 : }
546 : TIXMLASSERT(p);
547 : TIXMLASSERT(q);
548 : TIXMLASSERT(nChar >= 0);
549 : return strncmp(p, q, static_cast<size_t>(nChar)) == 0;
550 : }
551 :
552 : inline static bool IsUTF8Continuation(const char p) { return (p & 0x80) != 0; }
553 :
554 : static const char* ReadBOM(const char* p, bool* hasBOM);
555 : // p is the starting location,
556 : // the UTF-8 value of the entity will be placed in value, and length filled in.
557 : static const char* GetCharacterRef(const char* p, char* value, int* length);
558 : static void ConvertUTF32ToUTF8(unsigned long input, char* output, int* length);
559 :
560 : // converts primitive types to strings
561 : static void ToStr(int v, char* buffer, int bufferSize);
562 : static void ToStr(unsigned v, char* buffer, int bufferSize);
563 : static void ToStr(bool v, char* buffer, int bufferSize);
564 : static void ToStr(float v, char* buffer, int bufferSize);
565 : static void ToStr(double v, char* buffer, int bufferSize);
566 : static void ToStr(int64_t v, char* buffer, int bufferSize);
567 : static void ToStr(uint64_t v, char* buffer, int bufferSize);
568 :
569 : // converts strings to primitive types
570 : static bool ToInt(const char* str, int* value);
571 : static bool ToUnsigned(const char* str, unsigned* value);
572 : static bool ToBool(const char* str, bool* value);
573 : static bool ToFloat(const char* str, float* value);
574 : static bool ToDouble(const char* str, double* value);
575 : static bool ToInt64(const char* str, int64_t* value);
576 : static bool ToUnsigned64(const char* str, uint64_t* value);
577 : // Changes what is serialized for a boolean value.
578 : // Default to "true" and "false". Shouldn't be changed
579 : // unless you have a special testing or compatibility need.
580 : // Be careful: static, global, & not thread safe.
581 : // Be sure to set static const memory as parameters.
582 : static void SetBoolSerialization(const char* writeTrue, const char* writeFalse);
583 :
584 : private:
585 : static const char* writeBoolTrue;
586 : static const char* writeBoolFalse;
587 : };
588 :
589 : /** XMLNode is a base class for every object that is in the
590 : XML Document Object Model (DOM), except XMLAttributes.
591 : Nodes have siblings, a parent, and children which can
592 : be navigated. A node is always in a XMLDocument.
593 : The type of a XMLNode can be queried, and it can
594 : be cast to its more defined type.
595 :
596 : A XMLDocument allocates memory for all its Nodes.
597 : When the XMLDocument gets deleted, all its Nodes
598 : will also be deleted.
599 :
600 : @verbatim
601 : A Document can contain: Element (container or leaf)
602 : Comment (leaf)
603 : Unknown (leaf)
604 : Declaration( leaf )
605 :
606 : An Element can contain: Element (container or leaf)
607 : Text (leaf)
608 : Attributes (not on tree)
609 : Comment (leaf)
610 : Unknown (leaf)
611 :
612 : @endverbatim
613 : */
614 : class TINYXML2_LIB XMLNode {
615 : friend class XMLDocument;
616 : friend class XMLElement;
617 :
618 : public:
619 : /// Get the XMLDocument that owns this XMLNode.
620 : const XMLDocument* GetDocument() const {
621 : TIXMLASSERT(_document);
622 : return _document;
623 : }
624 : /// Get the XMLDocument that owns this XMLNode.
625 20 : XMLDocument* GetDocument() {
626 20 : TIXMLASSERT(_document);
627 20 : return _document;
628 : }
629 :
630 : /// Safely cast to an Element, or null.
631 : virtual XMLElement* ToElement() { return 0; }
632 : /// Safely cast to Text, or null.
633 : virtual XMLText* ToText() { return 0; }
634 : /// Safely cast to a Comment, or null.
635 : virtual XMLComment* ToComment() { return 0; }
636 : /// Safely cast to a Document, or null.
637 : virtual XMLDocument* ToDocument() { return 0; }
638 : /// Safely cast to a Declaration, or null.
639 : virtual XMLDeclaration* ToDeclaration() { return 0; }
640 : /// Safely cast to an Unknown, or null.
641 : virtual XMLUnknown* ToUnknown() { return 0; }
642 :
643 : virtual const XMLElement* ToElement() const { return 0; }
644 : virtual const XMLText* ToText() const { return 0; }
645 : virtual const XMLComment* ToComment() const { return 0; }
646 : virtual const XMLDocument* ToDocument() const { return 0; }
647 : virtual const XMLDeclaration* ToDeclaration() const { return 0; }
648 : virtual const XMLUnknown* ToUnknown() const { return 0; }
649 :
650 : // ChildElementCount was originally suggested by msteiger on the sourceforge page for TinyXML and modified by KB1SPH for TinyXML-2.
651 :
652 : int ChildElementCount(const char* value) const;
653 :
654 : int ChildElementCount() const;
655 :
656 : /** The meaning of 'value' changes for the specific type.
657 : @verbatim
658 : Document: empty (NULL is returned, not an empty string)
659 : Element: name of the element
660 : Comment: the comment text
661 : Unknown: the tag contents
662 : Text: the text string
663 : @endverbatim
664 : */
665 : const char* Value() const;
666 :
667 : /** Set the Value of an XML node.
668 : @sa Value()
669 : */
670 : void SetValue(const char* val, bool staticMem = false);
671 :
672 : /// Gets the line number the node is in, if the document was parsed from a file.
673 : int GetLineNum() const { return _parseLineNum; }
674 :
675 : /// Get the parent of this node on the DOM.
676 : const XMLNode* Parent() const { return _parent; }
677 :
678 : XMLNode* Parent() { return _parent; }
679 :
680 : /// Returns true if this node has no children.
681 : bool NoChildren() const { return !_firstChild; }
682 :
683 : /// Get the first child node, or null if none exists.
684 : const XMLNode* FirstChild() const { return _firstChild; }
685 :
686 : XMLNode* FirstChild() { return _firstChild; }
687 :
688 : /** Get the first child element, or optionally the first child
689 : element with the specified name.
690 : */
691 : const XMLElement* FirstChildElement(const char* name = 0) const;
692 :
693 68 : XMLElement* FirstChildElement(const char* name = 0) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement(name)); }
694 :
695 : /// Get the last child node, or null if none exists.
696 : const XMLNode* LastChild() const { return _lastChild; }
697 :
698 : XMLNode* LastChild() { return _lastChild; }
699 :
700 : /** Get the last child element or optionally the last child
701 : element with the specified name.
702 : */
703 : const XMLElement* LastChildElement(const char* name = 0) const;
704 :
705 : XMLElement* LastChildElement(const char* name = 0) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name)); }
706 :
707 : /// Get the previous (left) sibling node of this node.
708 : const XMLNode* PreviousSibling() const { return _prev; }
709 :
710 : XMLNode* PreviousSibling() { return _prev; }
711 :
712 : /// Get the previous (left) sibling element of this node, with an optionally supplied name.
713 : const XMLElement* PreviousSiblingElement(const char* name = 0) const;
714 :
715 : XMLElement* PreviousSiblingElement(const char* name = 0) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement(name)); }
716 :
717 : /// Get the next (right) sibling node of this node.
718 : const XMLNode* NextSibling() const { return _next; }
719 :
720 : XMLNode* NextSibling() { return _next; }
721 :
722 : /// Get the next (right) sibling element of this node, with an optionally supplied name.
723 : const XMLElement* NextSiblingElement(const char* name = 0) const;
724 :
725 44 : XMLElement* NextSiblingElement(const char* name = 0) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement(name)); }
726 :
727 : /**
728 : Add a child node as the last (right) child.
729 : If the child node is already part of the document,
730 : it is moved from its old location to the new location.
731 : Returns the addThis argument or 0 if the node does not
732 : belong to the same document.
733 : */
734 : XMLNode* InsertEndChild(XMLNode* addThis);
735 :
736 : XMLNode* LinkEndChild(XMLNode* addThis) { return InsertEndChild(addThis); }
737 : /**
738 : Add a child node as the first (left) child.
739 : If the child node is already part of the document,
740 : it is moved from its old location to the new location.
741 : Returns the addThis argument or 0 if the node does not
742 : belong to the same document.
743 : */
744 : XMLNode* InsertFirstChild(XMLNode* addThis);
745 : /**
746 : Add a node after the specified child node.
747 : If the child node is already part of the document,
748 : it is moved from its old location to the new location.
749 : Returns the addThis argument or 0 if the afterThis node
750 : is not a child of this node, or if the node does not
751 : belong to the same document.
752 : */
753 : XMLNode* InsertAfterChild(XMLNode* afterThis, XMLNode* addThis);
754 :
755 : /**
756 : Delete all the children of this node.
757 : */
758 : void DeleteChildren();
759 :
760 : /**
761 : Delete a child of this node.
762 : */
763 : void DeleteChild(XMLNode* node);
764 :
765 : /**
766 : Make a copy of this node, but not its children.
767 : You may pass in a Document pointer that will be
768 : the owner of the new Node. If the 'document' is
769 : null, then the node returned will be allocated
770 : from the current Document. (this->GetDocument())
771 :
772 : Note: if called on a XMLDocument, this will return null.
773 : */
774 : virtual XMLNode* ShallowClone(XMLDocument* document) const = 0;
775 :
776 : /**
777 : Make a copy of this node and all its children.
778 :
779 : If the 'target' is null, then the nodes will
780 : be allocated in the current document. If 'target'
781 : is specified, the memory will be allocated is the
782 : specified XMLDocument.
783 :
784 : NOTE: This is probably not the correct tool to
785 : copy a document, since XMLDocuments can have multiple
786 : top level XMLNodes. You probably want to use
787 : XMLDocument::DeepCopy()
788 : */
789 : XMLNode* DeepClone(XMLDocument* target) const;
790 :
791 : /**
792 : Test if 2 nodes are the same, but don't test children.
793 : The 2 nodes do not need to be in the same Document.
794 :
795 : Note: if called on a XMLDocument, this will return false.
796 : */
797 : virtual bool ShallowEqual(const XMLNode* compare) const = 0;
798 :
799 : /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
800 : XML tree will be conditionally visited and the host will be called back
801 : via the XMLVisitor interface.
802 :
803 : This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
804 : the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
805 : interface versus any other.)
806 :
807 : The interface has been based on ideas from:
808 :
809 : - http://www.saxproject.org/
810 : - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
811 :
812 : Which are both good references for "visiting".
813 :
814 : An example of using Accept():
815 : @verbatim
816 : XMLPrinter printer;
817 : tinyxmlDoc.Accept( &printer );
818 : const char* xmlcstr = printer.CStr();
819 : @endverbatim
820 : */
821 : virtual bool Accept(XMLVisitor* visitor) const = 0;
822 :
823 : /**
824 : Set user data into the XMLNode. TinyXML-2 in
825 : no way processes or interprets user data.
826 : It is initially 0.
827 : */
828 : void SetUserData(void* userData) { _userData = userData; }
829 :
830 : /**
831 : Get user data set into the XMLNode. TinyXML-2 in
832 : no way processes or interprets user data.
833 : It is initially 0.
834 : */
835 : void* GetUserData() const { return _userData; }
836 :
837 : protected:
838 : explicit XMLNode(XMLDocument*);
839 : virtual ~XMLNode();
840 :
841 : virtual char* ParseDeep(char* p, StrPair* parentEndTag, int* curLineNumPtr);
842 :
843 : XMLDocument* _document;
844 : XMLNode* _parent;
845 : mutable StrPair _value;
846 : int _parseLineNum;
847 :
848 : XMLNode* _firstChild;
849 : XMLNode* _lastChild;
850 :
851 : XMLNode* _prev;
852 : XMLNode* _next;
853 :
854 : void* _userData;
855 :
856 : private:
857 : MemPool* _memPool;
858 : void Unlink(XMLNode* child);
859 : static void DeleteNode(XMLNode* node);
860 : void InsertChildPreamble(XMLNode* insertThis) const;
861 : const XMLElement* ToElementWithName(const char* name) const;
862 :
863 : XMLNode(const XMLNode&); // not supported
864 : XMLNode& operator=(const XMLNode&); // not supported
865 : };
866 :
867 : /** XML text.
868 :
869 : Note that a text node can have child element nodes, for example:
870 : @verbatim
871 : <root>This is <b>bold</b></root>
872 : @endverbatim
873 :
874 : A text node can have 2 ways to output the next. "normal" output
875 : and CDATA. It will default to the mode it was parsed from the XML file and
876 : you generally want to leave it alone, but you can change the output mode with
877 : SetCData() and query it with CData().
878 : */
879 : class TINYXML2_LIB XMLText : public XMLNode {
880 : friend class XMLDocument;
881 :
882 : public:
883 : virtual bool Accept(XMLVisitor* visitor) const override;
884 :
885 : virtual XMLText* ToText() override { return this; }
886 : virtual const XMLText* ToText() const override { return this; }
887 :
888 : /// Declare whether this should be CDATA or standard text.
889 : void SetCData(bool isCData) { _isCData = isCData; }
890 : /// Returns true if this is a CDATA text element.
891 : bool CData() const { return _isCData; }
892 :
893 : virtual XMLNode* ShallowClone(XMLDocument* document) const override;
894 : virtual bool ShallowEqual(const XMLNode* compare) const override;
895 :
896 : protected:
897 : explicit XMLText(XMLDocument* doc) : XMLNode(doc), _isCData(false) {}
898 : virtual ~XMLText() {}
899 :
900 : char* ParseDeep(char* p, StrPair* parentEndTag, int* curLineNumPtr) override;
901 :
902 : private:
903 : bool _isCData;
904 :
905 : XMLText(const XMLText&); // not supported
906 : XMLText& operator=(const XMLText&); // not supported
907 : };
908 :
909 : /** An XML Comment. */
910 : class TINYXML2_LIB XMLComment : public XMLNode {
911 : friend class XMLDocument;
912 :
913 : public:
914 : virtual XMLComment* ToComment() override { return this; }
915 : virtual const XMLComment* ToComment() const override { return this; }
916 :
917 : virtual bool Accept(XMLVisitor* visitor) const override;
918 :
919 : virtual XMLNode* ShallowClone(XMLDocument* document) const override;
920 : virtual bool ShallowEqual(const XMLNode* compare) const override;
921 :
922 : protected:
923 : explicit XMLComment(XMLDocument* doc);
924 : virtual ~XMLComment();
925 :
926 : char* ParseDeep(char* p, StrPair* parentEndTag, int* curLineNumPtr) override;
927 :
928 : private:
929 : XMLComment(const XMLComment&); // not supported
930 : XMLComment& operator=(const XMLComment&); // not supported
931 : };
932 :
933 : /** In correct XML the declaration is the first entry in the file.
934 : @verbatim
935 : <?xml version="1.0" standalone="yes"?>
936 : @endverbatim
937 :
938 : TinyXML-2 will happily read or write files without a declaration,
939 : however.
940 :
941 : The text of the declaration isn't interpreted. It is parsed
942 : and written as a string.
943 : */
944 : class TINYXML2_LIB XMLDeclaration : public XMLNode {
945 : friend class XMLDocument;
946 :
947 : public:
948 : virtual XMLDeclaration* ToDeclaration() override { return this; }
949 : virtual const XMLDeclaration* ToDeclaration() const override { return this; }
950 :
951 : virtual bool Accept(XMLVisitor* visitor) const override;
952 :
953 : virtual XMLNode* ShallowClone(XMLDocument* document) const override;
954 : virtual bool ShallowEqual(const XMLNode* compare) const override;
955 :
956 : protected:
957 : explicit XMLDeclaration(XMLDocument* doc);
958 : virtual ~XMLDeclaration();
959 :
960 : char* ParseDeep(char* p, StrPair* parentEndTag, int* curLineNumPtr) override;
961 :
962 : private:
963 : XMLDeclaration(const XMLDeclaration&); // not supported
964 : XMLDeclaration& operator=(const XMLDeclaration&); // not supported
965 : };
966 :
967 : /** Any tag that TinyXML-2 doesn't recognize is saved as an
968 : unknown. It is a tag of text, but should not be modified.
969 : It will be written back to the XML, unchanged, when the file
970 : is saved.
971 :
972 : DTD tags get thrown into XMLUnknowns.
973 : */
974 : class TINYXML2_LIB XMLUnknown : public XMLNode {
975 : friend class XMLDocument;
976 :
977 : public:
978 : virtual XMLUnknown* ToUnknown() override { return this; }
979 : virtual const XMLUnknown* ToUnknown() const override { return this; }
980 :
981 : virtual bool Accept(XMLVisitor* visitor) const override;
982 :
983 : virtual XMLNode* ShallowClone(XMLDocument* document) const override;
984 : virtual bool ShallowEqual(const XMLNode* compare) const override;
985 :
986 : protected:
987 : explicit XMLUnknown(XMLDocument* doc);
988 : virtual ~XMLUnknown();
989 :
990 : char* ParseDeep(char* p, StrPair* parentEndTag, int* curLineNumPtr) override;
991 :
992 : private:
993 : XMLUnknown(const XMLUnknown&); // not supported
994 : XMLUnknown& operator=(const XMLUnknown&); // not supported
995 : };
996 :
997 : /** An attribute is a name-value pair. Elements have an arbitrary
998 : number of attributes, each with a unique name.
999 :
1000 : @note The attributes are not XMLNodes. You may only query the
1001 : Next() attribute in a list.
1002 : */
1003 : class TINYXML2_LIB XMLAttribute {
1004 : friend class XMLElement;
1005 :
1006 : public:
1007 : /// The name of the attribute.
1008 : const char* Name() const;
1009 :
1010 : /// The value of the attribute.
1011 : const char* Value() const;
1012 :
1013 : /// Gets the line number the attribute is in, if the document was parsed from a file.
1014 : int GetLineNum() const { return _parseLineNum; }
1015 :
1016 : /// The next attribute in the list.
1017 : const XMLAttribute* Next() const { return _next; }
1018 :
1019 : /** IntValue interprets the attribute as an integer, and returns the value.
1020 : If the value isn't an integer, 0 will be returned. There is no error checking;
1021 : use QueryIntValue() if you need error checking.
1022 : */
1023 : int IntValue() const {
1024 : int i = 0;
1025 : QueryIntValue(&i);
1026 : return i;
1027 : }
1028 :
1029 : int64_t Int64Value() const {
1030 : int64_t i = 0;
1031 : QueryInt64Value(&i);
1032 : return i;
1033 : }
1034 :
1035 : uint64_t Unsigned64Value() const {
1036 : uint64_t i = 0;
1037 : QueryUnsigned64Value(&i);
1038 : return i;
1039 : }
1040 :
1041 : /// Query as an unsigned integer. See IntValue()
1042 : unsigned UnsignedValue() const {
1043 : unsigned i = 0;
1044 : QueryUnsignedValue(&i);
1045 : return i;
1046 : }
1047 : /// Query as a boolean. See IntValue()
1048 : bool BoolValue() const {
1049 : bool b = false;
1050 : QueryBoolValue(&b);
1051 : return b;
1052 : }
1053 : /// Query as a double. See IntValue()
1054 : double DoubleValue() const {
1055 : double d = 0;
1056 : QueryDoubleValue(&d);
1057 : return d;
1058 : }
1059 : /// Query as a float. See IntValue()
1060 : float FloatValue() const {
1061 : float f = 0;
1062 : QueryFloatValue(&f);
1063 : return f;
1064 : }
1065 :
1066 : /** QueryIntValue interprets the attribute as an integer, and returns the value
1067 : in the provided parameter. The function will return XML_SUCCESS on success,
1068 : and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1069 : */
1070 : XMLError QueryIntValue(int* value) const;
1071 : /// See QueryIntValue
1072 : XMLError QueryUnsignedValue(unsigned int* value) const;
1073 : /// See QueryIntValue
1074 : XMLError QueryInt64Value(int64_t* value) const;
1075 : /// See QueryIntValue
1076 : XMLError QueryUnsigned64Value(uint64_t* value) const;
1077 : /// See QueryIntValue
1078 : XMLError QueryBoolValue(bool* value) const;
1079 : /// See QueryIntValue
1080 : XMLError QueryDoubleValue(double* value) const;
1081 : /// See QueryIntValue
1082 : XMLError QueryFloatValue(float* value) const;
1083 :
1084 : /// Set the attribute to a string value.
1085 : void SetAttribute(const char* value);
1086 : /// Set the attribute to value.
1087 : void SetAttribute(int value);
1088 : /// Set the attribute to value.
1089 : void SetAttribute(unsigned value);
1090 : /// Set the attribute to value.
1091 : void SetAttribute(int64_t value);
1092 : /// Set the attribute to value.
1093 : void SetAttribute(uint64_t value);
1094 : /// Set the attribute to value.
1095 : void SetAttribute(bool value);
1096 : /// Set the attribute to value.
1097 : void SetAttribute(double value);
1098 : /// Set the attribute to value.
1099 : void SetAttribute(float value);
1100 :
1101 : private:
1102 : enum { BUF_SIZE = 200 };
1103 :
1104 : XMLAttribute() : _name(), _value(), _parseLineNum(0), _next(0), _memPool(0) {}
1105 : virtual ~XMLAttribute() {}
1106 :
1107 : XMLAttribute(const XMLAttribute&); // not supported
1108 : void operator=(const XMLAttribute&); // not supported
1109 : void SetName(const char* name);
1110 :
1111 : char* ParseDeep(char* p, bool processEntities, int* curLineNumPtr);
1112 :
1113 : mutable StrPair _name;
1114 : mutable StrPair _value;
1115 : int _parseLineNum;
1116 : XMLAttribute* _next;
1117 : MemPool* _memPool;
1118 : };
1119 :
1120 : /** The element is a container class. It has a value, the element name,
1121 : and can contain other elements, text, comments, and unknowns.
1122 : Elements also contain an arbitrary number of attributes.
1123 : */
1124 : class TINYXML2_LIB XMLElement : public XMLNode {
1125 : friend class XMLDocument;
1126 :
1127 : public:
1128 : /// Get the name of an element (which is the Value() of the node.)
1129 0 : const char* Name() const { return Value(); }
1130 : /// Set the name of the element.
1131 : void SetName(const char* str, bool staticMem = false) { SetValue(str, staticMem); }
1132 :
1133 : virtual XMLElement* ToElement() override { return this; }
1134 : virtual const XMLElement* ToElement() const override { return this; }
1135 : virtual bool Accept(XMLVisitor* visitor) const override;
1136 :
1137 : /** Given an attribute name, Attribute() returns the value
1138 : for the attribute of that name, or null if none
1139 : exists. For example:
1140 :
1141 : @verbatim
1142 : const char* value = ele->Attribute( "foo" );
1143 : @endverbatim
1144 :
1145 : The 'value' parameter is normally null. However, if specified,
1146 : the attribute will only be returned if the 'name' and 'value'
1147 : match. This allow you to write code:
1148 :
1149 : @verbatim
1150 : if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1151 : @endverbatim
1152 :
1153 : rather than:
1154 : @verbatim
1155 : if ( ele->Attribute( "foo" ) ) {
1156 : if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1157 : }
1158 : @endverbatim
1159 : */
1160 : const char* Attribute(const char* name, const char* value = 0) const;
1161 :
1162 : /** Given an attribute name, IntAttribute() returns the value
1163 : of the attribute interpreted as an integer. The default
1164 : value will be returned if the attribute isn't present,
1165 : or if there is an error. (For a method with error
1166 : checking, see QueryIntAttribute()).
1167 : */
1168 : int IntAttribute(const char* name, int defaultValue = 0) const;
1169 : /// See IntAttribute()
1170 : unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;
1171 : /// See IntAttribute()
1172 : int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;
1173 : /// See IntAttribute()
1174 : uint64_t Unsigned64Attribute(const char* name, uint64_t defaultValue = 0) const;
1175 : /// See IntAttribute()
1176 : bool BoolAttribute(const char* name, bool defaultValue = false) const;
1177 : /// See IntAttribute()
1178 : double DoubleAttribute(const char* name, double defaultValue = 0) const;
1179 : /// See IntAttribute()
1180 : float FloatAttribute(const char* name, float defaultValue = 0) const;
1181 :
1182 : /** Given an attribute name, QueryIntAttribute() returns
1183 : XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1184 : can't be performed, or XML_NO_ATTRIBUTE if the attribute
1185 : doesn't exist. If successful, the result of the conversion
1186 : will be written to 'value'. If not successful, nothing will
1187 : be written to 'value'. This allows you to provide default
1188 : value:
1189 :
1190 : @verbatim
1191 : int value = 10;
1192 : QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1193 : @endverbatim
1194 : */
1195 56 : XMLError QueryIntAttribute(const char* name, int* value) const {
1196 56 : const XMLAttribute* a = FindAttribute(name);
1197 56 : if (!a) {
1198 : return XML_NO_ATTRIBUTE;
1199 : }
1200 56 : return a->QueryIntValue(value);
1201 : }
1202 :
1203 : /// See QueryIntAttribute()
1204 : XMLError QueryUnsignedAttribute(const char* name, unsigned int* value) const {
1205 : const XMLAttribute* a = FindAttribute(name);
1206 : if (!a) {
1207 : return XML_NO_ATTRIBUTE;
1208 : }
1209 : return a->QueryUnsignedValue(value);
1210 : }
1211 :
1212 : /// See QueryIntAttribute()
1213 : XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1214 : const XMLAttribute* a = FindAttribute(name);
1215 : if (!a) {
1216 : return XML_NO_ATTRIBUTE;
1217 : }
1218 : return a->QueryInt64Value(value);
1219 : }
1220 :
1221 : /// See QueryIntAttribute()
1222 : XMLError QueryUnsigned64Attribute(const char* name, uint64_t* value) const {
1223 : const XMLAttribute* a = FindAttribute(name);
1224 : if (!a) {
1225 : return XML_NO_ATTRIBUTE;
1226 : }
1227 : return a->QueryUnsigned64Value(value);
1228 : }
1229 :
1230 : /// See QueryIntAttribute()
1231 : XMLError QueryBoolAttribute(const char* name, bool* value) const {
1232 : const XMLAttribute* a = FindAttribute(name);
1233 : if (!a) {
1234 : return XML_NO_ATTRIBUTE;
1235 : }
1236 : return a->QueryBoolValue(value);
1237 : }
1238 : /// See QueryIntAttribute()
1239 36 : XMLError QueryDoubleAttribute(const char* name, double* value) const {
1240 36 : const XMLAttribute* a = FindAttribute(name);
1241 36 : if (!a) {
1242 : return XML_NO_ATTRIBUTE;
1243 : }
1244 36 : return a->QueryDoubleValue(value);
1245 : }
1246 : /// See QueryIntAttribute()
1247 : XMLError QueryFloatAttribute(const char* name, float* value) const {
1248 : const XMLAttribute* a = FindAttribute(name);
1249 : if (!a) {
1250 : return XML_NO_ATTRIBUTE;
1251 : }
1252 : return a->QueryFloatValue(value);
1253 : }
1254 :
1255 : /// See QueryIntAttribute()
1256 : XMLError QueryStringAttribute(const char* name, const char** value) const {
1257 : const XMLAttribute* a = FindAttribute(name);
1258 : if (!a) {
1259 : return XML_NO_ATTRIBUTE;
1260 : }
1261 : *value = a->Value();
1262 : return XML_SUCCESS;
1263 : }
1264 :
1265 : /** Given an attribute name, QueryAttribute() returns
1266 : XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1267 : can't be performed, or XML_NO_ATTRIBUTE if the attribute
1268 : doesn't exist. It is overloaded for the primitive types,
1269 : and is a generally more convenient replacement of
1270 : QueryIntAttribute() and related functions.
1271 :
1272 : If successful, the result of the conversion
1273 : will be written to 'value'. If not successful, nothing will
1274 : be written to 'value'. This allows you to provide default
1275 : value:
1276 :
1277 : @verbatim
1278 : int value = 10;
1279 : QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1280 : @endverbatim
1281 : */
1282 : XMLError QueryAttribute(const char* name, int* value) const { return QueryIntAttribute(name, value); }
1283 :
1284 : XMLError QueryAttribute(const char* name, unsigned int* value) const { return QueryUnsignedAttribute(name, value); }
1285 :
1286 : XMLError QueryAttribute(const char* name, int64_t* value) const { return QueryInt64Attribute(name, value); }
1287 :
1288 : XMLError QueryAttribute(const char* name, uint64_t* value) const { return QueryUnsigned64Attribute(name, value); }
1289 :
1290 : XMLError QueryAttribute(const char* name, bool* value) const { return QueryBoolAttribute(name, value); }
1291 :
1292 : XMLError QueryAttribute(const char* name, double* value) const { return QueryDoubleAttribute(name, value); }
1293 :
1294 : XMLError QueryAttribute(const char* name, float* value) const { return QueryFloatAttribute(name, value); }
1295 :
1296 : XMLError QueryAttribute(const char* name, const char** value) const { return QueryStringAttribute(name, value); }
1297 :
1298 : /// Sets the named attribute to value.
1299 : void SetAttribute(const char* name, const char* value) {
1300 : XMLAttribute* a = FindOrCreateAttribute(name);
1301 : a->SetAttribute(value);
1302 : }
1303 : /// Sets the named attribute to value.
1304 : void SetAttribute(const char* name, int value) {
1305 : XMLAttribute* a = FindOrCreateAttribute(name);
1306 : a->SetAttribute(value);
1307 : }
1308 : /// Sets the named attribute to value.
1309 : void SetAttribute(const char* name, unsigned value) {
1310 : XMLAttribute* a = FindOrCreateAttribute(name);
1311 : a->SetAttribute(value);
1312 : }
1313 :
1314 : /// Sets the named attribute to value.
1315 : void SetAttribute(const char* name, int64_t value) {
1316 : XMLAttribute* a = FindOrCreateAttribute(name);
1317 : a->SetAttribute(value);
1318 : }
1319 :
1320 : /// Sets the named attribute to value.
1321 : void SetAttribute(const char* name, uint64_t value) {
1322 : XMLAttribute* a = FindOrCreateAttribute(name);
1323 : a->SetAttribute(value);
1324 : }
1325 :
1326 : /// Sets the named attribute to value.
1327 : void SetAttribute(const char* name, bool value) {
1328 : XMLAttribute* a = FindOrCreateAttribute(name);
1329 : a->SetAttribute(value);
1330 : }
1331 : /// Sets the named attribute to value.
1332 : void SetAttribute(const char* name, double value) {
1333 : XMLAttribute* a = FindOrCreateAttribute(name);
1334 : a->SetAttribute(value);
1335 : }
1336 : /// Sets the named attribute to value.
1337 : void SetAttribute(const char* name, float value) {
1338 : XMLAttribute* a = FindOrCreateAttribute(name);
1339 : a->SetAttribute(value);
1340 : }
1341 :
1342 : /**
1343 : Delete an attribute.
1344 : */
1345 : void DeleteAttribute(const char* name);
1346 :
1347 : /// Return the first attribute in the list.
1348 : const XMLAttribute* FirstAttribute() const { return _rootAttribute; }
1349 : /// Query a specific attribute in the list.
1350 : const XMLAttribute* FindAttribute(const char* name) const;
1351 :
1352 : /** Convenience function for easy access to the text inside an element. Although easy
1353 : and concise, GetText() is limited compared to getting the XMLText child
1354 : and accessing it directly.
1355 :
1356 : If the first child of 'this' is a XMLText, the GetText()
1357 : returns the character string of the Text node, else null is returned.
1358 :
1359 : This is a convenient method for getting the text of simple contained text:
1360 : @verbatim
1361 : <foo>This is text</foo>
1362 : const char* str = fooElement->GetText();
1363 : @endverbatim
1364 :
1365 : 'str' will be a pointer to "This is text".
1366 :
1367 : Note that this function can be misleading. If the element foo was created from
1368 : this XML:
1369 : @verbatim
1370 : <foo><b>This is text</b></foo>
1371 : @endverbatim
1372 :
1373 : then the value of str would be null. The first child node isn't a text node, it is
1374 : another element. From this XML:
1375 : @verbatim
1376 : <foo>This is <b>text</b></foo>
1377 : @endverbatim
1378 : GetText() will return "This is ".
1379 : */
1380 : const char* GetText() const;
1381 :
1382 : /** Convenience function for easy access to the text inside an element. Although easy
1383 : and concise, SetText() is limited compared to creating an XMLText child
1384 : and mutating it directly.
1385 :
1386 : If the first child of 'this' is a XMLText, SetText() sets its value to
1387 : the given string, otherwise it will create a first child that is an XMLText.
1388 :
1389 : This is a convenient method for setting the text of simple contained text:
1390 : @verbatim
1391 : <foo>This is text</foo>
1392 : fooElement->SetText( "Hullaballoo!" );
1393 : <foo>Hullaballoo!</foo>
1394 : @endverbatim
1395 :
1396 : Note that this function can be misleading. If the element foo was created from
1397 : this XML:
1398 : @verbatim
1399 : <foo><b>This is text</b></foo>
1400 : @endverbatim
1401 :
1402 : then it will not change "This is text", but rather prefix it with a text element:
1403 : @verbatim
1404 : <foo>Hullaballoo!<b>This is text</b></foo>
1405 : @endverbatim
1406 :
1407 : For this XML:
1408 : @verbatim
1409 : <foo />
1410 : @endverbatim
1411 : SetText() will generate
1412 : @verbatim
1413 : <foo>Hullaballoo!</foo>
1414 : @endverbatim
1415 : */
1416 : void SetText(const char* inText);
1417 : /// Convenience method for setting text inside an element. See SetText() for important limitations.
1418 : void SetText(int value);
1419 : /// Convenience method for setting text inside an element. See SetText() for important limitations.
1420 : void SetText(unsigned value);
1421 : /// Convenience method for setting text inside an element. See SetText() for important limitations.
1422 : void SetText(int64_t value);
1423 : /// Convenience method for setting text inside an element. See SetText() for important limitations.
1424 : void SetText(uint64_t value);
1425 : /// Convenience method for setting text inside an element. See SetText() for important limitations.
1426 : void SetText(bool value);
1427 : /// Convenience method for setting text inside an element. See SetText() for important limitations.
1428 : void SetText(double value);
1429 : /// Convenience method for setting text inside an element. See SetText() for important limitations.
1430 : void SetText(float value);
1431 :
1432 : /**
1433 : Convenience method to query the value of a child text node. This is probably best
1434 : shown by example. Given you have a document is this form:
1435 : @verbatim
1436 : <point>
1437 : <x>1</x>
1438 : <y>1.4</y>
1439 : </point>
1440 : @endverbatim
1441 :
1442 : The QueryIntText() and similar functions provide a safe and easier way to get to the
1443 : "value" of x and y.
1444 :
1445 : @verbatim
1446 : int x = 0;
1447 : float y = 0; // types of x and y are contrived for example
1448 : const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1449 : const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1450 : xElement->QueryIntText( &x );
1451 : yElement->QueryFloatText( &y );
1452 : @endverbatim
1453 :
1454 : @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1455 : to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
1456 :
1457 : */
1458 : XMLError QueryIntText(int* ival) const;
1459 : /// See QueryIntText()
1460 : XMLError QueryUnsignedText(unsigned* uval) const;
1461 : /// See QueryIntText()
1462 : XMLError QueryInt64Text(int64_t* uval) const;
1463 : /// See QueryIntText()
1464 : XMLError QueryUnsigned64Text(uint64_t* uval) const;
1465 : /// See QueryIntText()
1466 : XMLError QueryBoolText(bool* bval) const;
1467 : /// See QueryIntText()
1468 : XMLError QueryDoubleText(double* dval) const;
1469 : /// See QueryIntText()
1470 : XMLError QueryFloatText(float* fval) const;
1471 :
1472 : int IntText(int defaultValue = 0) const;
1473 :
1474 : /// See QueryIntText()
1475 : unsigned UnsignedText(unsigned defaultValue = 0) const;
1476 : /// See QueryIntText()
1477 : int64_t Int64Text(int64_t defaultValue = 0) const;
1478 : /// See QueryIntText()
1479 : uint64_t Unsigned64Text(uint64_t defaultValue = 0) const;
1480 : /// See QueryIntText()
1481 : bool BoolText(bool defaultValue = false) const;
1482 : /// See QueryIntText()
1483 : double DoubleText(double defaultValue = 0) const;
1484 : /// See QueryIntText()
1485 : float FloatText(float defaultValue = 0) const;
1486 :
1487 : /**
1488 : Convenience method to create a new XMLElement and add it as last (right)
1489 : child of this node. Returns the created and inserted element.
1490 : */
1491 : XMLElement* InsertNewChildElement(const char* name);
1492 : /// See InsertNewChildElement()
1493 : XMLComment* InsertNewComment(const char* comment);
1494 : /// See InsertNewChildElement()
1495 : XMLText* InsertNewText(const char* text);
1496 : /// See InsertNewChildElement()
1497 : XMLDeclaration* InsertNewDeclaration(const char* text);
1498 : /// See InsertNewChildElement()
1499 : XMLUnknown* InsertNewUnknown(const char* text);
1500 :
1501 : // internal:
1502 : enum ElementClosingType {
1503 : OPEN, // <foo>
1504 : CLOSED, // <foo/>
1505 : CLOSING // </foo>
1506 : };
1507 : ElementClosingType ClosingType() const { return _closingType; }
1508 : virtual XMLNode* ShallowClone(XMLDocument* document) const override;
1509 : virtual bool ShallowEqual(const XMLNode* compare) const override;
1510 :
1511 : protected:
1512 : char* ParseDeep(char* p, StrPair* parentEndTag, int* curLineNumPtr) override;
1513 :
1514 : private:
1515 : XMLElement(XMLDocument* doc);
1516 : virtual ~XMLElement();
1517 : XMLElement(const XMLElement&); // not supported
1518 : void operator=(const XMLElement&); // not supported
1519 :
1520 : XMLAttribute* FindOrCreateAttribute(const char* name);
1521 : char* ParseAttributes(char* p, int* curLineNumPtr);
1522 : static void DeleteAttribute(XMLAttribute* attribute);
1523 : XMLAttribute* CreateAttribute();
1524 :
1525 : enum { BUF_SIZE = 200 };
1526 : ElementClosingType _closingType;
1527 : // The attribute list is ordered; there is no 'lastAttribute'
1528 : // because the list needs to be scanned for dupes before adding
1529 : // a new attribute.
1530 : XMLAttribute* _rootAttribute;
1531 : };
1532 :
1533 : enum Whitespace { PRESERVE_WHITESPACE, COLLAPSE_WHITESPACE, PEDANTIC_WHITESPACE };
1534 :
1535 : /** A Document binds together all the functionality.
1536 : It can be saved, loaded, and printed to the screen.
1537 : All Nodes are connected and allocated to a Document.
1538 : If the Document is deleted, all its Nodes are also deleted.
1539 : */
1540 : class TINYXML2_LIB XMLDocument : public XMLNode {
1541 : friend class XMLElement;
1542 : // Gives access to SetError and Push/PopDepth, but over-access for everything else.
1543 : // Wishing C++ had "internal" scope.
1544 : friend class XMLNode;
1545 : friend class XMLText;
1546 : friend class XMLComment;
1547 : friend class XMLDeclaration;
1548 : friend class XMLUnknown;
1549 :
1550 : public:
1551 : /// constructor
1552 : XMLDocument(bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE);
1553 : ~XMLDocument();
1554 :
1555 : virtual XMLDocument* ToDocument() override {
1556 : TIXMLASSERT(this == _document);
1557 : return this;
1558 : }
1559 : virtual const XMLDocument* ToDocument() const override {
1560 : TIXMLASSERT(this == _document);
1561 : return this;
1562 : }
1563 :
1564 : /**
1565 : Parse an XML file from a character string.
1566 : Returns XML_SUCCESS (0) on success, or
1567 : an errorID.
1568 :
1569 : You may optionally pass in the 'nBytes', which is
1570 : the number of bytes which will be parsed. If not
1571 : specified, TinyXML-2 will assume 'xml' points to a
1572 : null terminated string.
1573 : */
1574 : XMLError Parse(const char* xml, size_t nBytes = static_cast<size_t>(-1));
1575 :
1576 : /**
1577 : Load an XML file from disk.
1578 : Returns XML_SUCCESS (0) on success, or
1579 : an errorID.
1580 : */
1581 : XMLError LoadFile(const char* filename);
1582 :
1583 : /**
1584 : Load an XML file from disk. You are responsible
1585 : for providing and closing the FILE*.
1586 :
1587 : NOTE: The file should be opened as binary ("rb")
1588 : not text in order for TinyXML-2 to correctly
1589 : do newline normalization.
1590 :
1591 : Returns XML_SUCCESS (0) on success, or
1592 : an errorID.
1593 : */
1594 : XMLError LoadFile(FILE*);
1595 :
1596 : /**
1597 : Save the XML file to disk.
1598 : Returns XML_SUCCESS (0) on success, or
1599 : an errorID.
1600 : */
1601 : XMLError SaveFile(const char* filename, bool compact = false);
1602 :
1603 : /**
1604 : Save the XML file to disk. You are responsible
1605 : for providing and closing the FILE*.
1606 :
1607 : Returns XML_SUCCESS (0) on success, or
1608 : an errorID.
1609 : */
1610 : XMLError SaveFile(FILE* fp, bool compact = false);
1611 :
1612 : bool ProcessEntities() const { return _processEntities; }
1613 : Whitespace WhitespaceMode() const { return _whitespaceMode; }
1614 :
1615 : /**
1616 : Returns true if this document has a leading Byte Order Mark of UTF8.
1617 : */
1618 : bool HasBOM() const { return _writeBOM; }
1619 : /** Sets whether to write the BOM when writing the file.
1620 : */
1621 : void SetBOM(bool useBOM) { _writeBOM = useBOM; }
1622 :
1623 : /** Return the root element of DOM. Equivalent to FirstChildElement().
1624 : To get the first node, use FirstChild().
1625 : */
1626 : XMLElement* RootElement() { return FirstChildElement(); }
1627 : const XMLElement* RootElement() const { return FirstChildElement(); }
1628 :
1629 : /** Print the Document. If the Printer is not provided, it will
1630 : print to stdout. If you provide Printer, this can print to a file:
1631 : @verbatim
1632 : XMLPrinter printer( fp );
1633 : doc.Print( &printer );
1634 : @endverbatim
1635 :
1636 : Or you can use a printer to print to memory:
1637 : @verbatim
1638 : XMLPrinter printer;
1639 : doc.Print( &printer );
1640 : // printer.CStr() has a const char* to the XML
1641 : @endverbatim
1642 : */
1643 : void Print(XMLPrinter* streamer = 0) const;
1644 : virtual bool Accept(XMLVisitor* visitor) const override;
1645 :
1646 : /**
1647 : Create a new Element associated with
1648 : this Document. The memory for the Element
1649 : is managed by the Document.
1650 : */
1651 : XMLElement* NewElement(const char* name);
1652 : /**
1653 : Create a new Comment associated with
1654 : this Document. The memory for the Comment
1655 : is managed by the Document.
1656 : */
1657 : XMLComment* NewComment(const char* comment);
1658 : /**
1659 : Create a new Text associated with
1660 : this Document. The memory for the Text
1661 : is managed by the Document.
1662 : */
1663 : XMLText* NewText(const char* text);
1664 : /**
1665 : Create a new Declaration associated with
1666 : this Document. The memory for the object
1667 : is managed by the Document.
1668 :
1669 : If the 'text' param is null, the standard
1670 : declaration is used.:
1671 : @verbatim
1672 : <?xml version="1.0" encoding="UTF-8"?>
1673 : @endverbatim
1674 : */
1675 : XMLDeclaration* NewDeclaration(const char* text = 0);
1676 : /**
1677 : Create a new Unknown associated with
1678 : this Document. The memory for the object
1679 : is managed by the Document.
1680 : */
1681 : XMLUnknown* NewUnknown(const char* text);
1682 :
1683 : /**
1684 : Delete a node associated with this document.
1685 : It will be unlinked from the DOM.
1686 : */
1687 : void DeleteNode(XMLNode* node);
1688 :
1689 : /// Clears the error flags.
1690 : void ClearError();
1691 :
1692 : /// Return true if there was an error parsing the document.
1693 : bool Error() const { return _errorID != XML_SUCCESS; }
1694 : /// Return the errorID.
1695 : XMLError ErrorID() const { return _errorID; }
1696 : const char* ErrorName() const;
1697 : static const char* ErrorIDToName(XMLError errorID);
1698 :
1699 : /** Returns a "long form" error description. A hopefully helpful
1700 : diagnostic with location, line number, and/or additional info.
1701 : */
1702 : const char* ErrorStr() const;
1703 :
1704 : /// A (trivial) utility function that prints the ErrorStr() to stdout.
1705 : void PrintError() const;
1706 :
1707 : /// Return the line where the error occurred, or zero if unknown.
1708 : int ErrorLineNum() const { return _errorLineNum; }
1709 :
1710 : /// Clear the document, resetting it to the initial state.
1711 : void Clear();
1712 :
1713 : /**
1714 : Copies this document to a target document.
1715 : The target will be completely cleared before the copy.
1716 : If you want to copy a sub-tree, see XMLNode::DeepClone().
1717 :
1718 : NOTE: that the 'target' must be non-null.
1719 : */
1720 : void DeepCopy(XMLDocument* target) const;
1721 :
1722 : // internal
1723 : char* Identify(char* p, XMLNode** node, bool first);
1724 :
1725 : // internal
1726 : void MarkInUse(const XMLNode* const);
1727 :
1728 : virtual XMLNode* ShallowClone(XMLDocument* /*document*/) const override { return 0; }
1729 : virtual bool ShallowEqual(const XMLNode* /*compare*/) const override { return false; }
1730 :
1731 : private:
1732 : XMLDocument(const XMLDocument&); // not supported
1733 : void operator=(const XMLDocument&); // not supported
1734 :
1735 : bool _writeBOM;
1736 : bool _processEntities;
1737 : XMLError _errorID;
1738 : Whitespace _whitespaceMode;
1739 : mutable StrPair _errorStr;
1740 : int _errorLineNum;
1741 : char* _charBuffer;
1742 : int _parseCurLineNum;
1743 : int _parsingDepth;
1744 : // Memory tracking does add some overhead.
1745 : // However, the code assumes that you don't
1746 : // have a bunch of unlinked nodes around.
1747 : // Therefore it takes less memory to track
1748 : // in the document vs. a linked list in the XMLNode,
1749 : // and the performance is the same.
1750 : DynArray<XMLNode*, 10> _unlinked;
1751 :
1752 : MemPoolT<sizeof(XMLElement)> _elementPool;
1753 : MemPoolT<sizeof(XMLAttribute)> _attributePool;
1754 : MemPoolT<sizeof(XMLText)> _textPool;
1755 : MemPoolT<sizeof(XMLComment)> _commentPool;
1756 :
1757 : static const char* _errorNames[XML_ERROR_COUNT];
1758 :
1759 : void Parse();
1760 :
1761 : void SetError(XMLError error, int lineNum, const char* format, ...);
1762 :
1763 : // Something of an obvious security hole, once it was discovered.
1764 : // Either an ill-formed XML or an excessively deep one can overflow
1765 : // the stack. Track stack depth, and error out if needed.
1766 : class DepthTracker {
1767 : public:
1768 : explicit DepthTracker(XMLDocument* document) {
1769 : this->_document = document;
1770 : document->PushDepth();
1771 : }
1772 : ~DepthTracker() { _document->PopDepth(); }
1773 :
1774 : private:
1775 : XMLDocument* _document;
1776 : };
1777 : void PushDepth();
1778 : void PopDepth();
1779 :
1780 : template <class NodeType, int PoolElementSize> NodeType* CreateUnlinkedNode(MemPoolT<PoolElementSize>& pool);
1781 : };
1782 :
1783 : template <class NodeType, int PoolElementSize> inline NodeType* XMLDocument::CreateUnlinkedNode(MemPoolT<PoolElementSize>& pool) {
1784 : TIXMLASSERT(sizeof(NodeType) == PoolElementSize);
1785 : TIXMLASSERT(sizeof(NodeType) == pool.ItemSize());
1786 : NodeType* returnNode = new (pool.Alloc()) NodeType(this);
1787 : TIXMLASSERT(returnNode);
1788 : returnNode->_memPool = &pool;
1789 :
1790 : _unlinked.Push(returnNode);
1791 : return returnNode;
1792 : }
1793 :
1794 : /**
1795 : A XMLHandle is a class that wraps a node pointer with null checks; this is
1796 : an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
1797 : DOM structure. It is a separate utility class.
1798 :
1799 : Take an example:
1800 : @verbatim
1801 : <Document>
1802 : <Element attributeA = "valueA">
1803 : <Child attributeB = "value1" />
1804 : <Child attributeB = "value2" />
1805 : </Element>
1806 : </Document>
1807 : @endverbatim
1808 :
1809 : Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1810 : easy to write a *lot* of code that looks like:
1811 :
1812 : @verbatim
1813 : XMLElement* root = document.FirstChildElement( "Document" );
1814 : if ( root )
1815 : {
1816 : XMLElement* element = root->FirstChildElement( "Element" );
1817 : if ( element )
1818 : {
1819 : XMLElement* child = element->FirstChildElement( "Child" );
1820 : if ( child )
1821 : {
1822 : XMLElement* child2 = child->NextSiblingElement( "Child" );
1823 : if ( child2 )
1824 : {
1825 : // Finally do something useful.
1826 : @endverbatim
1827 :
1828 : And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
1829 : of such code. A XMLHandle checks for null pointers so it is perfectly safe
1830 : and correct to use:
1831 :
1832 : @verbatim
1833 : XMLHandle docHandle( &document );
1834 : XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
1835 : if ( child2 )
1836 : {
1837 : // do something useful
1838 : @endverbatim
1839 :
1840 : Which is MUCH more concise and useful.
1841 :
1842 : It is also safe to copy handles - internally they are nothing more than node pointers.
1843 : @verbatim
1844 : XMLHandle handleCopy = handle;
1845 : @endverbatim
1846 :
1847 : See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
1848 : */
1849 : class TINYXML2_LIB XMLHandle {
1850 : public:
1851 : /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
1852 : explicit XMLHandle(XMLNode* node) : _node(node) {}
1853 : /// Create a handle from a node.
1854 : explicit XMLHandle(XMLNode& node) : _node(&node) {}
1855 : /// Copy constructor
1856 : XMLHandle(const XMLHandle& ref) : _node(ref._node) {}
1857 : /// Assignment
1858 : XMLHandle& operator=(const XMLHandle& ref) {
1859 : _node = ref._node;
1860 : return *this;
1861 : }
1862 :
1863 : /// Get the first child of this handle.
1864 : XMLHandle FirstChild() { return XMLHandle(_node ? _node->FirstChild() : 0); }
1865 : /// Get the first child element of this handle.
1866 : XMLHandle FirstChildElement(const char* name = 0) { return XMLHandle(_node ? _node->FirstChildElement(name) : 0); }
1867 : /// Get the last child of this handle.
1868 : XMLHandle LastChild() { return XMLHandle(_node ? _node->LastChild() : 0); }
1869 : /// Get the last child element of this handle.
1870 : XMLHandle LastChildElement(const char* name = 0) { return XMLHandle(_node ? _node->LastChildElement(name) : 0); }
1871 : /// Get the previous sibling of this handle.
1872 : XMLHandle PreviousSibling() { return XMLHandle(_node ? _node->PreviousSibling() : 0); }
1873 : /// Get the previous sibling element of this handle.
1874 : XMLHandle PreviousSiblingElement(const char* name = 0) { return XMLHandle(_node ? _node->PreviousSiblingElement(name) : 0); }
1875 : /// Get the next sibling of this handle.
1876 : XMLHandle NextSibling() { return XMLHandle(_node ? _node->NextSibling() : 0); }
1877 : /// Get the next sibling element of this handle.
1878 : XMLHandle NextSiblingElement(const char* name = 0) { return XMLHandle(_node ? _node->NextSiblingElement(name) : 0); }
1879 :
1880 : /// Safe cast to XMLNode. This can return null.
1881 : XMLNode* ToNode() { return _node; }
1882 : /// Safe cast to XMLElement. This can return null.
1883 : XMLElement* ToElement() { return (_node ? _node->ToElement() : 0); }
1884 : /// Safe cast to XMLText. This can return null.
1885 : XMLText* ToText() { return (_node ? _node->ToText() : 0); }
1886 : /// Safe cast to XMLUnknown. This can return null.
1887 : XMLUnknown* ToUnknown() { return (_node ? _node->ToUnknown() : 0); }
1888 : /// Safe cast to XMLDeclaration. This can return null.
1889 : XMLDeclaration* ToDeclaration() { return (_node ? _node->ToDeclaration() : 0); }
1890 :
1891 : private:
1892 : XMLNode* _node;
1893 : };
1894 :
1895 : /**
1896 : A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1897 : same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
1898 : */
1899 : class TINYXML2_LIB XMLConstHandle {
1900 : public:
1901 : explicit XMLConstHandle(const XMLNode* node) : _node(node) {}
1902 : explicit XMLConstHandle(const XMLNode& node) : _node(&node) {}
1903 : XMLConstHandle(const XMLConstHandle& ref) : _node(ref._node) {}
1904 :
1905 : XMLConstHandle& operator=(const XMLConstHandle& ref) {
1906 : _node = ref._node;
1907 : return *this;
1908 : }
1909 :
1910 : const XMLConstHandle FirstChild() const { return XMLConstHandle(_node ? _node->FirstChild() : 0); }
1911 : const XMLConstHandle FirstChildElement(const char* name = 0) const { return XMLConstHandle(_node ? _node->FirstChildElement(name) : 0); }
1912 : const XMLConstHandle LastChild() const { return XMLConstHandle(_node ? _node->LastChild() : 0); }
1913 : const XMLConstHandle LastChildElement(const char* name = 0) const { return XMLConstHandle(_node ? _node->LastChildElement(name) : 0); }
1914 : const XMLConstHandle PreviousSibling() const { return XMLConstHandle(_node ? _node->PreviousSibling() : 0); }
1915 : const XMLConstHandle PreviousSiblingElement(const char* name = 0) const { return XMLConstHandle(_node ? _node->PreviousSiblingElement(name) : 0); }
1916 : const XMLConstHandle NextSibling() const { return XMLConstHandle(_node ? _node->NextSibling() : 0); }
1917 : const XMLConstHandle NextSiblingElement(const char* name = 0) const { return XMLConstHandle(_node ? _node->NextSiblingElement(name) : 0); }
1918 :
1919 : const XMLNode* ToNode() const { return _node; }
1920 : const XMLElement* ToElement() const { return (_node ? _node->ToElement() : 0); }
1921 : const XMLText* ToText() const { return (_node ? _node->ToText() : 0); }
1922 : const XMLUnknown* ToUnknown() const { return (_node ? _node->ToUnknown() : 0); }
1923 : const XMLDeclaration* ToDeclaration() const { return (_node ? _node->ToDeclaration() : 0); }
1924 :
1925 : private:
1926 : const XMLNode* _node;
1927 : };
1928 :
1929 : /**
1930 : Printing functionality. The XMLPrinter gives you more
1931 : options than the XMLDocument::Print() method.
1932 :
1933 : It can:
1934 : -# Print to memory.
1935 : -# Print to a file you provide.
1936 : -# Print XML without a XMLDocument.
1937 :
1938 : Print to Memory
1939 :
1940 : @verbatim
1941 : XMLPrinter printer;
1942 : doc.Print( &printer );
1943 : SomeFunction( printer.CStr() );
1944 : @endverbatim
1945 :
1946 : Print to a File
1947 :
1948 : You provide the file pointer.
1949 : @verbatim
1950 : XMLPrinter printer( fp );
1951 : doc.Print( &printer );
1952 : @endverbatim
1953 :
1954 : Print without a XMLDocument
1955 :
1956 : When loading, an XML parser is very useful. However, sometimes
1957 : when saving, it just gets in the way. The code is often set up
1958 : for streaming, and constructing the DOM is just overhead.
1959 :
1960 : The Printer supports the streaming case. The following code
1961 : prints out a trivially simple XML file without ever creating
1962 : an XML document.
1963 :
1964 : @verbatim
1965 : XMLPrinter printer( fp );
1966 : printer.OpenElement( "foo" );
1967 : printer.PushAttribute( "foo", "bar" );
1968 : printer.CloseElement();
1969 : @endverbatim
1970 : */
1971 : class TINYXML2_LIB XMLPrinter : public XMLVisitor {
1972 : public:
1973 : /** Construct the printer. If the FILE* is specified,
1974 : this will print to the FILE. Else it will print
1975 : to memory, and the result is available in CStr().
1976 : If 'compact' is set to true, then output is created
1977 : with only required whitespace and newlines.
1978 : */
1979 : XMLPrinter(FILE* file = 0, bool compact = false, int depth = 0);
1980 : virtual ~XMLPrinter() {}
1981 :
1982 : /** If streaming, write the BOM and declaration. */
1983 : void PushHeader(bool writeBOM, bool writeDeclaration);
1984 : /** If streaming, start writing an element.
1985 : The element must be closed with CloseElement()
1986 : */
1987 : void OpenElement(const char* name, bool compactMode = false);
1988 : /// If streaming, add an attribute to an open element.
1989 : void PushAttribute(const char* name, const char* value);
1990 : void PushAttribute(const char* name, int value);
1991 : void PushAttribute(const char* name, unsigned value);
1992 : void PushAttribute(const char* name, int64_t value);
1993 : void PushAttribute(const char* name, uint64_t value);
1994 : void PushAttribute(const char* name, bool value);
1995 : void PushAttribute(const char* name, double value);
1996 : /// If streaming, close the Element.
1997 : virtual void CloseElement(bool compactMode = false);
1998 :
1999 : /// Add a text node.
2000 : void PushText(const char* text, bool cdata = false);
2001 : /// Add a text node from an integer.
2002 : void PushText(int value);
2003 : /// Add a text node from an unsigned.
2004 : void PushText(unsigned value);
2005 : /// Add a text node from a signed 64bit integer.
2006 : void PushText(int64_t value);
2007 : /// Add a text node from an unsigned 64bit integer.
2008 : void PushText(uint64_t value);
2009 : /// Add a text node from a bool.
2010 : void PushText(bool value);
2011 : /// Add a text node from a float.
2012 : void PushText(float value);
2013 : /// Add a text node from a double.
2014 : void PushText(double value);
2015 :
2016 : /// Add a comment
2017 : void PushComment(const char* comment);
2018 :
2019 : void PushDeclaration(const char* value);
2020 : void PushUnknown(const char* value);
2021 :
2022 : virtual bool VisitEnter(const XMLDocument& /*doc*/) override;
2023 : virtual bool VisitExit(const XMLDocument& /*doc*/) override { return true; }
2024 :
2025 : virtual bool VisitEnter(const XMLElement& element, const XMLAttribute* attribute) override;
2026 : virtual bool VisitExit(const XMLElement& element) override;
2027 :
2028 : virtual bool Visit(const XMLText& text) override;
2029 : virtual bool Visit(const XMLComment& comment) override;
2030 : virtual bool Visit(const XMLDeclaration& declaration) override;
2031 : virtual bool Visit(const XMLUnknown& unknown) override;
2032 :
2033 : /**
2034 : If in print to memory mode, return a pointer to
2035 : the XML file in memory.
2036 : */
2037 : const char* CStr() const { return _buffer.Mem(); }
2038 : /**
2039 : If in print to memory mode, return the size
2040 : of the XML file in memory. (Note the size returned
2041 : includes the terminating null.)
2042 : */
2043 : int CStrSize() const { return _buffer.Size(); }
2044 : /**
2045 : If in print to memory mode, reset the buffer to the
2046 : beginning.
2047 : */
2048 : void ClearBuffer(bool resetToFirstElement = true) {
2049 : _buffer.Clear();
2050 : _buffer.Push(0);
2051 : _firstElement = resetToFirstElement;
2052 : }
2053 :
2054 : protected:
2055 : virtual bool CompactMode(const XMLElement&) { return _compactMode; }
2056 :
2057 : /** Prints out the space before an element. You may override to change
2058 : the space and tabs used. A PrintSpace() override should call Print().
2059 : */
2060 : virtual void PrintSpace(int depth);
2061 : virtual void Print(const char* format, ...);
2062 : virtual void Write(const char* data, size_t size);
2063 : virtual void Putc(char ch);
2064 :
2065 : inline void Write(const char* data) { Write(data, strlen(data)); }
2066 :
2067 : void SealElementIfJustOpened();
2068 : bool _elementJustOpened;
2069 : DynArray<const char*, 10> _stack;
2070 :
2071 : private:
2072 : /**
2073 : Prepares to write a new node. This includes sealing an element that was
2074 : just opened, and writing any whitespace necessary if not in compact mode.
2075 : */
2076 : void PrepareForNewNode(bool compactMode);
2077 : void PrintString(const char*, bool restrictedEntitySet); // prints out, after detecting entities.
2078 :
2079 : bool _firstElement;
2080 : FILE* _fp;
2081 : int _depth;
2082 : int _textDepth;
2083 : bool _processEntities;
2084 : bool _compactMode;
2085 :
2086 : enum { ENTITY_RANGE = 64, BUF_SIZE = 200 };
2087 : bool _entityFlag[ENTITY_RANGE];
2088 : bool _restrictedEntityFlag[ENTITY_RANGE];
2089 :
2090 : DynArray<char, 20> _buffer;
2091 :
2092 : // Prohibit cloning, intentionally not implemented
2093 : XMLPrinter(const XMLPrinter&);
2094 : XMLPrinter& operator=(const XMLPrinter&);
2095 : };
2096 :
2097 : } // namespace tinyxml2
2098 :
2099 : #if defined(_MSC_VER)
2100 : #pragma warning(pop)
2101 : #endif
2102 :
2103 : #endif // TINYXML2_INCLUDED
|