aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
tinyxmlparser.cpp
Go to the documentation of this file.
1/*
2www.sourceforge.net/projects/tinyxml
3Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason
4(www.grinninglizard.com)
5
6This software is provided 'as-is', without any express or implied
7warranty. In no event will the authors be held liable for any
8damages arising from the use of this software.
9
10Permission is granted to anyone to use this software for any
11purpose, including commercial applications, and to alter it and
12redistribute it freely, subject to the following restrictions:
13
141. The origin of this software must not be misrepresented; you must
15not claim that you wrote the original software. If you use this
16software in a product, an acknowledgment in the product documentation
17would be appreciated but is not required.
18
192. Altered source versions must be plainly marked as such, and
20must not be misrepresented as being the original software.
21
223. This notice may not be removed or altered from any source
23distribution.
24*/
25
26#include <ctype.h>
27#include <stddef.h>
28
29#include "tinyxml.h"
30
31//#define DEBUG_PARSER
32#if defined(DEBUG_PARSER)
33#if defined(DEBUG) && defined(_MSC_VER)
34#include <windows.h>
35#define TIXML_LOG OutputDebugString
36#else
37#define TIXML_LOG printf
38#endif
39#endif
40
41// Note tha "PutString" hardcodes the same list. This
42// is less flexible than it appears. Changing the entries
43// or order will break putstring.
44TiXmlBase::Entity TiXmlBase::entity[NUM_ENTITY] = {{"&amp;", 5, '&'},
45 {"&lt;", 4, '<'},
46 {"&gt;", 4, '>'},
47 {"&quot;", 6, '\"'},
48 {"&apos;", 6, '\''}};
49
50// Bunch of unicode info at:
51// http://www.unicode.org/faq/utf_bom.html
52// Including the basic of this table, which determines the #bytes in the
53// sequence from the lead byte. 1 placed for invalid sequences --
54// although the result will be junk, pass it through as much as possible.
55// Beware of the non-characters in UTF-8:
56// ef bb bf (Microsoft "lead bytes")
57// ef bf be
58// ef bf bf
59
60const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
61const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
62const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
63
64const int TiXmlBase::utf8ByteTable[256] = {
65 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
66 1, 1, 1, 1, 1, 1, 1, 1,
67 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
68 1, 1, 1, 1, 1, 1, 1, 1,
69 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
70 1, 1, 1, 1, 1, 1, 1, 1,
71 1, 1, 1, 1, 1, 1, 1, 1, // 0x20
72 1, 1, 1, 1, 1, 1, 1, 1,
73 1, 1, 1, 1, 1, 1, 1, 1, // 0x30
74 1, 1, 1, 1, 1, 1, 1, 1,
75 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
76 1, 1, 1, 1, 1, 1, 1, 1,
77 1, 1, 1, 1, 1, 1, 1, 1, // 0x50
78 1, 1, 1, 1, 1, 1, 1, 1,
79 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
80 1, 1, 1, 1, 1, 1, 1, 1,
81 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range
82 1, 1, 1, 1, 1, 1, 1, 1,
83 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid
84 1, 1, 1, 1, 1, 1, 1, 1,
85 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
86 1, 1, 1, 1, 1, 1, 1, 1,
87 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
88 1, 1, 1, 1, 1, 1, 1, 1,
89 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
90 1, 1, 2, 2, 2, 2, 2, 2,
91 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte
92 2, 2, 2, 2, 2, 2, 2, 2,
93 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
94 3, 3, 3, 3, 3, 3, 3, 3,
95 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte
96 4, 4, 4, 4, 4, 1, 1, 1,
97 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
98};
99
100void TiXmlBase::ConvertUTF32ToUTF8(unsigned long input,
101 char* output,
102 int* length) {
103 const unsigned long BYTE_MASK = 0xBF;
104 const unsigned long BYTE_MARK = 0x80;
105 const unsigned long FIRST_BYTE_MARK[7] = {
106 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
107
108 if (input < 0x80)
109 *length = 1;
110 else if (input < 0x800)
111 *length = 2;
112 else if (input < 0x10000)
113 *length = 3;
114 else if (input < 0x200000)
115 *length = 4;
116 else {
117 *length = 0;
118 return;
119 } // This code won't covert this correctly anyway.
120
121 output += *length;
122
123 // Scary scary fall throughs.
124 switch (*length) {
125 case 4:
126 --output;
127 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
128 input >>= 6;
129
130 case 3:
131 --output;
132 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
133 input >>= 6;
134
135 case 2:
136 --output;
137 *output = (char)((input | BYTE_MARK) & BYTE_MASK);
138 input >>= 6;
139
140 case 1:
141 --output;
142 *output = (char)(input | FIRST_BYTE_MARK[*length]);
143 }
144}
145
146/*static*/ int TiXmlBase::IsAlpha(unsigned char anyByte,
147 TiXmlEncoding /*encoding*/) {
148 // This will only work for low-ascii, everything else is assumed to be a valid
149 // letter. I'm not sure this is the best approach, but it is quite tricky
150 // trying
151 // to figure out alhabetical vs. not across encoding. So take a very
152 // conservative approach.
153
154 // if ( encoding == TIXML_ENCODING_UTF8 )
155 // {
156 if (anyByte < 127)
157 return isalpha(anyByte);
158 else
159 return 1; // What else to do? The unicode set is huge...get the english
160 // ones
161 // right.
162
163 // }
164 // else
165 // {
166 // return isalpha( anyByte );
167 // }
168}
169
170/*static*/ int TiXmlBase::IsAlphaNum(unsigned char anyByte,
171 TiXmlEncoding /*encoding*/) {
172 // This will only work for low-ascii, everything else is assumed to be a valid
173 // letter. I'm not sure this is the best approach, but it is quite tricky
174 // trying
175 // to figure out alhabetical vs. not across encoding. So take a very
176 // conservative approach.
177
178 // if ( encoding == TIXML_ENCODING_UTF8 )
179 // {
180 if (anyByte < 127)
181 return isalnum(anyByte);
182 else
183 return 1; // What else to do? The unicode set is huge...get the english
184 // ones
185 // right.
186
187 // }
188 // else
189 // {
190 // return isalnum( anyByte );
191 // }
192}
193
195 friend class TiXmlDocument;
196
197 public:
198 void Stamp(const char* now, TiXmlEncoding encoding);
199
200 const TiXmlCursor& Cursor() { return cursor; }
201
202 private:
203 // Only used by the document!
204 TiXmlParsingData(const char* start, int _tabsize, int row, int col) {
205 assert(start);
206 stamp = start;
207 tabsize = _tabsize;
208 cursor.row = row;
209 cursor.col = col;
210 }
211
213 const char* stamp;
215};
216
217void TiXmlParsingData::Stamp(const char* now, TiXmlEncoding encoding) {
218 assert(now);
219
220 // Do nothing if the tabsize is 0.
221 if (tabsize < 1) {
222 return;
223 }
224
225 // Get the current row, column.
226 int row = cursor.row;
227 int col = cursor.col;
228 const char* p = stamp;
229 assert(p);
230
231 while (p < now) {
232 // Treat p as unsigned, so we have a happy compiler.
233 const unsigned char* pU = (const unsigned char*)p;
234
235 // Code contributed by Fletcher Dunn: (modified by lee)
236 switch (*pU) {
237 case 0:
238 // We *should* never get here, but in case we do, don't
239 // advance past the terminating null character, ever
240 return;
241
242 case '\r':
243 // bump down to the next line
244 ++row;
245 col = 0;
246 // Eat the character
247 ++p;
248
249 // Check for \r\n sequence, and treat this as a single character
250 if (*p == '\n') {
251 ++p;
252 }
253
254 break;
255
256 case '\n':
257 // bump down to the next line
258 ++row;
259 col = 0;
260
261 // Eat the character
262 ++p;
263
264 // Check for \n\r sequence, and treat this as a single
265 // character. (Yes, this bizarre thing does occur still
266 // on some arcane platforms...)
267 if (*p == '\r') {
268 ++p;
269 }
270
271 break;
272
273 case '\t':
274 // Eat the character
275 ++p;
276
277 // Skip to next tab stop
278 col = (col / tabsize + 1) * tabsize;
279 break;
280
281 case TIXML_UTF_LEAD_0:
282 if (encoding == TIXML_ENCODING_UTF8) {
283 if (*(p + 1) && *(p + 2)) {
284 // In these cases, don't advance the column. These are
285 // 0-width spaces.
286 if (*(pU + 1) == TIXML_UTF_LEAD_1 && *(pU + 2) == TIXML_UTF_LEAD_2)
287 p += 3;
288 else if (*(pU + 1) == 0xbfU && *(pU + 2) == 0xbeU)
289 p += 3;
290 else if (*(pU + 1) == 0xbfU && *(pU + 2) == 0xbfU)
291 p += 3;
292 else {
293 p += 3;
294 ++col;
295 } // A normal character.
296 }
297 } else {
298 ++p;
299 ++col;
300 }
301
302 break;
303
304 default:
305 if (encoding == TIXML_ENCODING_UTF8) {
306 // Eat the 1 to 4 byte utf8 character.
307 int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)];
308
309 if (step == 0)
310 step = 1; // Error case from bad encoding, but handle gracefully.
311
312 p += step;
313
314 // Just advance one column, of course.
315 ++col;
316 } else {
317 ++p;
318 ++col;
319 }
320
321 break;
322 }
323 }
324
325 cursor.row = row;
326 cursor.col = col;
327 assert(cursor.row >= -1);
328 assert(cursor.col >= -1);
329 stamp = p;
330 assert(stamp);
331}
332
333const char* TiXmlBase::SkipWhiteSpace(const char* p, TiXmlEncoding encoding) {
334 if (!p || !*p) {
335 return 0;
336 }
337
338 if (encoding == TIXML_ENCODING_UTF8) {
339 while (*p) {
340 const unsigned char* pU = (const unsigned char*)p;
341
342 // Skip the stupid Microsoft UTF-8 Byte order marks
343 if (*(pU + 0) == TIXML_UTF_LEAD_0 && *(pU + 1) == TIXML_UTF_LEAD_1 &&
344 *(pU + 2) == TIXML_UTF_LEAD_2) {
345 p += 3;
346 continue;
347 } else if (*(pU + 0) == TIXML_UTF_LEAD_0 && *(pU + 1) == 0xbfU &&
348 *(pU + 2) == 0xbeU) {
349 p += 3;
350 continue;
351 } else if (*(pU + 0) == TIXML_UTF_LEAD_0 && *(pU + 1) == 0xbfU &&
352 *(pU + 2) == 0xbfU) {
353 p += 3;
354 continue;
355 }
356
357 if (IsWhiteSpace(*p) || *p == '\n' ||
358 *p == '\r') // Still using old rules for white space.
359 ++p;
360 else
361 break;
362 }
363 } else {
364 while ((*p && IsWhiteSpace(*p)) || *p == '\n' || *p == '\r')
365 ++p;
366 }
367
368 return p;
369}
370
371#ifdef TIXML_USE_STL
372/*static*/ bool TiXmlBase::StreamWhiteSpace(std::istream* in, TIXML_STRING* tag) {
373 for (;;) {
374 if (!in->good()) return false;
375
376 int c = in->peek();
377
378 // At this scope, we can't get to a document. So fail silently.
379 if (!IsWhiteSpace(c) || c <= 0) return true;
380
381 *tag += (char)in->get();
382 }
383}
384
385/*static*/ bool
386TiXmlBase::StreamTo(std::istream* in, int character, TIXML_STRING* tag) {
387 // assert( character > 0 && character < 128 ); // else it won't work in utf-8
388 while (in->good()) {
389 int c = in->peek();
390
391 if (c == character) return true;
392
393 if (c <= 0) // Silent failure: can't get document at this scope
394 return false;
395
396 in->get();
397 *tag += (char)c;
398 }
399
400 return false;
401}
402#endif
403
404// One of TinyXML's more performance demanding functions. Try to keep the memory
405// overhead down. The
406// "assign" optimization removes over 10% of the execution time.
407//
408const char*
409TiXmlBase::ReadName(const char* p, TIXML_STRING* name, TiXmlEncoding encoding) {
410 // Oddly, not supported on some comilers,
411 // name->clear();
412 // So use this:
413 *name = "";
414 assert(p);
415
416 // Names start with letters or underscores.
417 // Of course, in unicode, tinyxml has no idea what a letter *is*. The
418 // algorithm is generous.
419 //
420 // After that, they can be letters, underscores, numbers,
421 // hyphens, or colons. (Colons are valid ony for namespaces,
422 // but tinyxml can't tell namespaces from names.)
423 if (p && *p && (IsAlpha((unsigned char)*p, encoding) || *p == '_')) {
424 const char* start = p;
425
426 while (p && *p && (IsAlphaNum((unsigned char)*p, encoding) || *p == '_' ||
427 *p == '-' || *p == '.' || *p == ':')) {
428 //(*name) += *p; // expensive
429 ++p;
430 }
431
432 if (p - start > 0) {
433 name->assign(start, p - start);
434 }
435
436 return p;
437 }
438
439 return 0;
440}
441
442const char* TiXmlBase::GetEntity(const char* p,
443 char* value,
444 int* length,
445 TiXmlEncoding encoding) {
446 // Presume an entity, and pull it out.
447 TIXML_STRING ent;
448 int i;
449 *length = 0;
450
451 if (*(p + 1) && *(p + 1) == '#' && *(p + 2)) {
452 unsigned long ucs = 0;
453 ptrdiff_t delta = 0;
454 unsigned mult = 1;
455
456 if (*(p + 2) == 'x') {
457 // Hexadecimal.
458 if (!*(p + 3)) return 0;
459
460 const char* q = p + 3;
461 q = strchr(q, ';');
462
463 if (!q || !*q) return 0;
464
465 delta = q - p;
466 --q;
467
468 while (*q != 'x') {
469 if (*q >= '0' && *q <= '9')
470 ucs += mult * (*q - '0');
471 else if (*q >= 'a' && *q <= 'f')
472 ucs += mult * (*q - 'a' + 10);
473 else if (*q >= 'A' && *q <= 'F')
474 ucs += mult * (*q - 'A' + 10);
475 else
476 return 0;
477
478 mult *= 16;
479 --q;
480 }
481 } else {
482 // Decimal.
483 if (!*(p + 2)) return 0;
484
485 const char* q = p + 2;
486 q = strchr(q, ';');
487
488 if (!q || !*q) return 0;
489
490 delta = q - p;
491 --q;
492
493 while (*q != '#') {
494 if (*q >= '0' && *q <= '9')
495 ucs += mult * (*q - '0');
496 else
497 return 0;
498
499 mult *= 10;
500 --q;
501 }
502 }
503
504 if (encoding == TIXML_ENCODING_UTF8) {
505 // convert the UCS to UTF-8
506 ConvertUTF32ToUTF8(ucs, value, length);
507 } else {
508 *value = (char)ucs;
509 *length = 1;
510 }
511
512 return p + delta + 1;
513 }
514
515 // Now try to match it.
516 for (i = 0; i < NUM_ENTITY; ++i) {
517 if (strncmp(entity[i].str, p, entity[i].strLength) == 0) {
518 assert(strlen(entity[i].str) == entity[i].strLength);
519 *value = entity[i].chr;
520 *length = 1;
521 return (p + entity[i].strLength);
522 }
523 }
524
525 // So it wasn't an entity, its unrecognized, or something like that.
526 *value = *p; // Don't put back the last one, since we return it!
527 //*length = 1; // Leave unrecognized entities - this doesn't really work.
528 // Just writes strange XML.
529 return p + 1;
530}
531
532bool TiXmlBase::StringEqual(const char* p,
533 const char* tag,
534 bool ignoreCase,
535 TiXmlEncoding encoding) {
536 assert(p);
537 assert(tag);
538
539 if (!p || !*p) {
540 assert(0);
541 return false;
542 }
543
544 const char* q = p;
545
546 if (ignoreCase) {
547 while (*q && *tag && ToLower(*q, encoding) == ToLower(*tag, encoding)) {
548 ++q;
549 ++tag;
550 }
551
552 if (*tag == 0) return true;
553 } else {
554 while (*q && *tag && *q == *tag) {
555 ++q;
556 ++tag;
557 }
558
559 if (*tag == 0) // Have we found the end of the tag, and everything equal?
560 return true;
561 }
562
563 return false;
564}
565
566const char* TiXmlBase::ReadText(const char* p,
567 TIXML_STRING* text,
568 bool trimWhiteSpace,
569 const char* endTag,
570 bool caseInsensitive,
571 TiXmlEncoding encoding) {
572 *text = "";
573
574 if (!trimWhiteSpace // certain tags always keep whitespace
575 ||
576 !condenseWhiteSpace) { // if true, whitespace is always kept
577 // Keep all the white space.
578 while (p && *p && !StringEqual(p, endTag, caseInsensitive, encoding)) {
579 int len;
580 char cArr[4] = {0, 0, 0, 0};
581 p = GetChar(p, cArr, &len, encoding);
582 text->append(cArr, len);
583 }
584 } else {
585 bool whitespace = false;
586
587 // Remove leading white space:
588 p = SkipWhiteSpace(p, encoding);
589
590 while (p && *p && !StringEqual(p, endTag, caseInsensitive, encoding)) {
591 if (*p == '\r' || *p == '\n') {
592 whitespace = true;
593 ++p;
594 } else if (IsWhiteSpace(*p)) {
595 whitespace = true;
596 ++p;
597 } else {
598 // If we've found whitespace, add it before the
599 // new character. Any whitespace just becomes a space.
600 if (whitespace) {
601 (*text) += ' ';
602 whitespace = false;
603 }
604
605 int len;
606 char cArr[4] = {0, 0, 0, 0};
607 p = GetChar(p, cArr, &len, encoding);
608
609 if (len == 1)
610 (*text) += cArr[0]; // more efficient
611 else
612 text->append(cArr, len);
613 }
614 }
615 }
616
617 if (p) p += strlen(endTag);
618
619 return p;
620}
621
622#ifdef TIXML_USE_STL
623
624void TiXmlDocument::StreamIn(std::istream* in, TIXML_STRING* tag) {
625 // The basic issue with a document is that we don't know what we're
626 // streaming. Read something presumed to be a tag (and hope), then
627 // identify it, and call the appropriate stream method on the tag.
628 //
629 // This "pre-streaming" will never read the closing ">" so the
630 // sub-tag can orient itself.
631
632 if (!StreamTo(in, '<', tag)) {
634 return;
635 }
636
637 while (in->good()) {
638 int tagIndex = (int)tag->length();
639
640 while (in->good() && in->peek() != '>') {
641 int c = in->get();
642
643 if (c <= 0) {
645 break;
646 }
647
648 (*tag) += (char)c;
649 }
650
651 if (in->good()) {
652 // We now have something we presume to be a node of
653 // some sort. Identify it, and call the node to
654 // continue streaming.
655 TiXmlNode* node = Identify(tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING);
656
657 if (node) {
658 node->StreamIn(in, tag);
659 bool isElement = node->ToElement() != 0;
660 delete node;
661 node = 0;
662
663 // If this is the root element, we're done. Parsing will be
664 // done by the >> operator.
665 if (isElement) {
666 return;
667 }
668 } else {
670 return;
671 }
672 }
673 }
674
675 // We should have returned sooner.
677}
678
679#endif
680
681const char* TiXmlDocument::Parse(const char* p,
682 TiXmlParsingData* prevData,
683 TiXmlEncoding encoding) {
684 ClearError();
685
686 // Parse away, at the document level. Since a document
687 // contains nothing but other tags, most of what happens
688 // here is skipping white space.
689 if (!p || !*p) {
691 return 0;
692 }
693
694 // Note that, for a document, this needs to come
695 // before the while space skip, so that parsing
696 // starts from the pointer we are given.
697 location.Clear();
698
699 if (prevData) {
700 location.row = prevData->cursor.row;
701 location.col = prevData->cursor.col;
702 } else {
703 location.row = 0;
704 location.col = 0;
705 }
706
707 TiXmlParsingData data(p, TabSize(), location.row, location.col);
708 location = data.Cursor();
709
710 if (encoding == TIXML_ENCODING_UNKNOWN) {
711 // Check for the Microsoft UTF-8 lead bytes.
712 const unsigned char* pU = (const unsigned char*)p;
713
714 if (*(pU + 0) && *(pU + 0) == TIXML_UTF_LEAD_0 && *(pU + 1) &&
715 *(pU + 1) == TIXML_UTF_LEAD_1 && *(pU + 2) &&
716 *(pU + 2) == TIXML_UTF_LEAD_2) {
717 encoding = TIXML_ENCODING_UTF8;
718 useMicrosoftBOM = true;
719 }
720 }
721
722 p = SkipWhiteSpace(p, encoding);
723
724 if (!p) {
726 return 0;
727 }
728
729 while (p && *p) {
730 TiXmlNode* node = Identify(p, encoding);
731
732 if (node) {
733 p = node->Parse(p, &data, encoding);
734 LinkEndChild(node);
735 } else {
736 break;
737 }
738
739 // Did we get encoding info?
740 if (encoding == TIXML_ENCODING_UNKNOWN && node->ToDeclaration()) {
741 TiXmlDeclaration* dec = node->ToDeclaration();
742 const char* enc = dec->Encoding();
743 assert(enc);
744
745 if (*enc == 0)
746 encoding = TIXML_ENCODING_UTF8;
747 else if (StringEqual(enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN))
748 encoding = TIXML_ENCODING_UTF8;
749 else if (StringEqual(enc, "UTF8", true, TIXML_ENCODING_UNKNOWN))
750 encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice
751 else
752 encoding = TIXML_ENCODING_LEGACY;
753 }
754
755 p = SkipWhiteSpace(p, encoding);
756 }
757
758 // Was this empty?
759 if (!firstChild) {
760 SetError(TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding);
761 return 0;
762 }
763
764 // All is well.
765 return p;
766}
767
769 const char* pError,
770 TiXmlParsingData* data,
771 TiXmlEncoding encoding) {
772 // The first error in a chain is more accurate - don't set again!
773 if (error) return;
774
775 assert(err > 0 && err < TIXML_ERROR_STRING_COUNT);
776 error = true;
777 errorId = err;
779
780 errorLocation.Clear();
781
782 if (pError && data) {
783 data->Stamp(pError, encoding);
784 errorLocation = data->Cursor();
785 }
786}
787
788TiXmlNode* TiXmlNode::Identify(const char* p, TiXmlEncoding encoding) {
789 TiXmlNode* returnNode = 0;
790
791 p = SkipWhiteSpace(p, encoding);
792
793 if (!p || !*p || *p != '<') {
794 return 0;
795 }
796
797 TiXmlDocument* doc = GetDocument();
798 p = SkipWhiteSpace(p, encoding);
799
800 if (!p || !*p) {
801 return 0;
802 }
803
804 // What is this thing?
805 // - Elements start with a letter or underscore, but xml is reserved.
806 // - Comments: <!--
807 // - Decleration: <?xml
808 // - StylesheetReference <?xml-stylesheet
809 // - Everthing else is unknown to tinyxml.
810 //
811
812 const char* xmlHeader = {"<?xml"};
813 const char* xmlSSHeader = {"<?xml-stylesheet"};
814 const char* commentHeader = {"<!--"};
815 const char* dtdHeader = {"<!"};
816 const char* cdataHeader = {"<![CDATA["};
817
818 if (StringEqual(p, xmlSSHeader, true, encoding)) {
819#ifdef DEBUG_PARSER
820 TIXML_LOG("XML parsing Stylesheet Reference\n");
821#endif
822 returnNode = new TiXmlStylesheetReference();
823 } else if (StringEqual(p, xmlHeader, true, encoding)) {
824#ifdef DEBUG_PARSER
825 TIXML_LOG("XML parsing Declaration\n");
826#endif
827 returnNode = new TiXmlDeclaration();
828 } else if (StringEqual(p, commentHeader, false, encoding)) {
829#ifdef DEBUG_PARSER
830 TIXML_LOG("XML parsing Comment\n");
831#endif
832 returnNode = new TiXmlComment();
833 } else if (StringEqual(p, cdataHeader, false, encoding)) {
834#ifdef DEBUG_PARSER
835 TIXML_LOG("XML parsing CDATA\n");
836#endif
837 TiXmlText* text = new TiXmlText("");
838 text->SetCDATA(true);
839 returnNode = text;
840 } else if (StringEqual(p, dtdHeader, false, encoding)) {
841#ifdef DEBUG_PARSER
842 TIXML_LOG("XML parsing Unknown(1)\n");
843#endif
844 returnNode = new TiXmlUnknown();
845 } else if (IsAlpha(*(p + 1), encoding) || *(p + 1) == '_') {
846#ifdef DEBUG_PARSER
847 TIXML_LOG("XML parsing Element\n");
848#endif
849 returnNode = new TiXmlElement("");
850 } else {
851#ifdef DEBUG_PARSER
852 TIXML_LOG("XML parsing Unknown(2)\n");
853#endif
854 returnNode = new TiXmlUnknown();
855 }
856
857 if (returnNode) {
858 // Set the parent, so it can report errors
859 returnNode->parent = this;
860 } else {
861 if (doc)
863 }
864
865 return returnNode;
866}
867
868#ifdef TIXML_USE_STL
869
870void TiXmlElement::StreamIn(std::istream* in, TIXML_STRING* tag) {
871 // We're called with some amount of pre-parsing. That is, some of "this"
872 // element is in "tag". Go ahead and stream to the closing ">"
873 while (in->good()) {
874 int c = in->get();
875
876 if (c <= 0) {
877 TiXmlDocument* document = GetDocument();
878
879 if (document)
880 document->SetError(
882
883 return;
884 }
885
886 (*tag) += (char)c;
887
888 if (c == '>') break;
889 }
890
891 if (tag->length() < 3) return;
892
893 // Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
894 // If not, identify and stream.
895
896 if (tag->at(tag->length() - 1) == '>' && tag->at(tag->length() - 2) == '/') {
897 // All good!
898 return;
899 } else if (tag->at(tag->length() - 1) == '>') {
900 // There is more. Could be:
901 // text
902 // cdata text (which looks like another node)
903 // closing tag
904 // another node.
905 for (;;) {
906 StreamWhiteSpace(in, tag);
907
908 // Do we have text?
909 if (in->good() && in->peek() != '<') {
910 // Yep, text.
911 TiXmlText text("");
912 text.StreamIn(in, tag);
913
914 // What follows text is a closing tag or another node.
915 // Go around again and figure it out.
916 continue;
917 }
918
919 // We now have either a closing tag...or another node.
920 // We should be at a "<", regardless.
921 if (!in->good()) return;
922
923 assert(in->peek() == '<');
924 int tagIndex = (int)tag->length();
925
926 bool closingTag = false;
927 bool firstCharFound = false;
928
929 for (;;) {
930 if (!in->good()) return;
931
932 int c = in->peek();
933
934 if (c <= 0) {
935 TiXmlDocument* document = GetDocument();
936
937 if (document)
938 document->SetError(
940
941 return;
942 }
943
944 if (c == '>') break;
945
946 *tag += (char)c;
947 in->get();
948
949 // Early out if we find the CDATA id.
950 if (c == '[' && tag->size() >= 9) {
951 size_t len = tag->size();
952 const char* start = tag->c_str() + len - 9;
953
954 if (strcmp(start, "<![CDATA[") == 0) {
955 assert(!closingTag);
956 break;
957 }
958 }
959
960 if (!firstCharFound && c != '<' && !IsWhiteSpace(c)) {
961 firstCharFound = true;
962
963 if (c == '/') closingTag = true;
964 }
965 }
966
967 // If it was a closing tag, then read in the closing '>' to clean up the
968 // input
969 // stream.
970 // If it was not, the streaming will be done by the tag.
971 if (closingTag) {
972 if (!in->good()) return;
973
974 int c = in->get();
975
976 if (c <= 0) {
977 TiXmlDocument* document = GetDocument();
978
979 if (document)
980 document->SetError(
982
983 return;
984 }
985
986 assert(c == '>');
987 *tag += (char)c;
988
989 // We are done, once we've found our closing tag.
990 return;
991 } else {
992 // If not a closing tag, id it, and stream.
993 const char* tagloc = tag->c_str() + tagIndex;
995
996 if (!node) return;
997
998 node->StreamIn(in, tag);
999 delete node;
1000 node = 0;
1001
1002 // No return: go around from the beginning: text, closing tag, or node.
1003 }
1004 }
1005 }
1006}
1007#endif
1008
1009const char* TiXmlElement::Parse(const char* p,
1010 TiXmlParsingData* data,
1011 TiXmlEncoding encoding) {
1012 p = SkipWhiteSpace(p, encoding);
1013 TiXmlDocument* document = GetDocument();
1014
1015 if (!p || !*p) {
1016 if (document) document->SetError(TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding);
1017
1018 return 0;
1019 }
1020
1021 if (data) {
1022 data->Stamp(p, encoding);
1023 location = data->Cursor();
1024 }
1025
1026 if (*p != '<') {
1027 if (document)
1028 document->SetError(TIXML_ERROR_PARSING_ELEMENT, p, data, encoding);
1029
1030 return 0;
1031 }
1032
1033 p = SkipWhiteSpace(p + 1, encoding);
1034
1035 // Read the name.
1036 const char* pErr = p;
1037
1038 p = ReadName(p, &value, encoding);
1039
1040 if (!p || !*p) {
1041 if (document)
1042 document->SetError(
1043 TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding);
1044
1045 return 0;
1046 }
1047
1048 TIXML_STRING endTag("</");
1049 endTag += value;
1050 endTag += ">";
1051
1052 // Check for and read attributes. Also look for an empty
1053 // tag or an end tag.
1054 while (p && *p) {
1055 pErr = p;
1056 p = SkipWhiteSpace(p, encoding);
1057
1058 if (!p || !*p) {
1059 if (document)
1060 document->SetError(TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding);
1061
1062 return 0;
1063 }
1064
1065 if (*p == '/') {
1066 ++p;
1067
1068 // Empty tag.
1069 if (*p != '>') {
1070 if (document)
1071 document->SetError(TIXML_ERROR_PARSING_EMPTY, p, data, encoding);
1072
1073 return 0;
1074 }
1075
1076 return (p + 1);
1077 } else if (*p == '>') {
1078 // Done with attributes (if there were any.)
1079 // Read the value -- which can include other
1080 // elements -- read the end tag, and return.
1081 ++p;
1082 p = ReadValue(p,
1083 data,
1084 encoding); // Note this is an Element method, and will
1085 // set the error if one happens.
1086
1087 if (!p || !*p) {
1088 // We were looking for the end tag, but found nothing.
1089 // Fix for [ 1663758 ] Failure to report error on bad XML
1090 if (document)
1091 document->SetError(TIXML_ERROR_READING_END_TAG, p, data, encoding);
1092
1093 return 0;
1094 }
1095
1096 // We should find the end tag now
1097 if (StringEqual(p, endTag.c_str(), false, encoding)) {
1098 p += endTag.length();
1099 return p;
1100 } else {
1101 if (document)
1102 document->SetError(TIXML_ERROR_READING_END_TAG, p, data, encoding);
1103
1104 return 0;
1105 }
1106 } else {
1107 // Try to read an attribute:
1108 TiXmlAttribute* attrib = new TiXmlAttribute();
1109
1110 if (!attrib) {
1111 if (document)
1112 document->SetError(TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding);
1113
1114 return 0;
1115 }
1116
1117 attrib->SetDocument(document);
1118 pErr = p;
1119 p = attrib->Parse(p, data, encoding);
1120
1121 if (!p || !*p) {
1122 if (document)
1123 document->SetError(TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding);
1124
1125 delete attrib;
1126 return 0;
1127 }
1128
1129// Handle the strange case of double attributes:
1130#ifdef TIXML_USE_STL
1131 TiXmlAttribute* node = attributeSet.Find(attrib->NameTStr());
1132#else
1133 TiXmlAttribute* node = attributeSet.Find(attrib->Name());
1134#endif
1135
1136 if (node) {
1137 node->SetValue(attrib->Value());
1138 delete attrib;
1139 return 0;
1140 }
1141
1142 attributeSet.Add(attrib);
1143 }
1144 }
1145
1146 return p;
1147}
1148
1149const char* TiXmlElement::ReadValue(const char* p,
1150 TiXmlParsingData* data,
1151 TiXmlEncoding encoding) {
1152 TiXmlDocument* document = GetDocument();
1153
1154 // Read in text and elements in any order.
1155 const char* pWithWhiteSpace = p;
1156 p = SkipWhiteSpace(p, encoding);
1157
1158 while (p && *p) {
1159 if (*p != '<') {
1160 // Take what we have, make a text element.
1161 TiXmlText* textNode = new TiXmlText("");
1162
1163 if (!textNode) {
1164 if (document)
1165 document->SetError(TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding);
1166
1167 return 0;
1168 }
1169
1171 p = textNode->Parse(p, data, encoding);
1172 } else {
1173 // Special case: we want to keep the white space
1174 // so that leading spaces aren't removed.
1175 p = textNode->Parse(pWithWhiteSpace, data, encoding);
1176 }
1177
1178 if (!textNode->Blank())
1179 LinkEndChild(textNode);
1180 else
1181 delete textNode;
1182 } else {
1183 // We hit a '<'
1184 // Have we hit a new element or an end tag? This could also be
1185 // a TiXmlText in the "CDATA" style.
1186 if (StringEqual(p, "</", false, encoding)) {
1187 return p;
1188 } else {
1189 TiXmlNode* node = Identify(p, encoding);
1190
1191 if (node) {
1192 p = node->Parse(p, data, encoding);
1193 LinkEndChild(node);
1194 } else {
1195 return 0;
1196 }
1197 }
1198 }
1199
1200 pWithWhiteSpace = p;
1201 p = SkipWhiteSpace(p, encoding);
1202 }
1203
1204 if (!p) {
1205 if (document)
1206 document->SetError(TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding);
1207 }
1208
1209 return p;
1210}
1211
1212#ifdef TIXML_USE_STL
1213void TiXmlUnknown::StreamIn(std::istream* in, TIXML_STRING* tag) {
1214 while (in->good()) {
1215 int c = in->get();
1216
1217 if (c <= 0) {
1218 TiXmlDocument* document = GetDocument();
1219
1220 if (document)
1221 document->SetError(
1223
1224 return;
1225 }
1226
1227 (*tag) += (char)c;
1228
1229 if (c == '>') {
1230 // All is well.
1231 return;
1232 }
1233 }
1234}
1235#endif
1236
1237const char* TiXmlUnknown::Parse(const char* p,
1238 TiXmlParsingData* data,
1239 TiXmlEncoding encoding) {
1240 TiXmlDocument* document = GetDocument();
1241 p = SkipWhiteSpace(p, encoding);
1242
1243 if (data) {
1244 data->Stamp(p, encoding);
1245 location = data->Cursor();
1246 }
1247
1248 if (!p || !*p || *p != '<') {
1249 if (document)
1250 document->SetError(TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding);
1251
1252 return 0;
1253 }
1254
1255 ++p;
1256 value = "";
1257
1258 while (p && *p && *p != '>') {
1259 value += *p;
1260 ++p;
1261 }
1262
1263 if (!p) {
1264 if (document) document->SetError(TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding);
1265 }
1266
1267 if (*p == '>') return p + 1;
1268
1269 return p;
1270}
1271
1272#ifdef TIXML_USE_STL
1273void TiXmlComment::StreamIn(std::istream* in, TIXML_STRING* tag) {
1274 while (in->good()) {
1275 int c = in->get();
1276
1277 if (c <= 0) {
1278 TiXmlDocument* document = GetDocument();
1279
1280 if (document)
1281 document->SetError(
1283
1284 return;
1285 }
1286
1287 (*tag) += (char)c;
1288
1289 if (c == '>' && tag->at(tag->length() - 2) == '-' &&
1290 tag->at(tag->length() - 3) == '-') {
1291 // All is well.
1292 return;
1293 }
1294 }
1295}
1296#endif
1297
1298const char* TiXmlComment::Parse(const char* p,
1299 TiXmlParsingData* data,
1300 TiXmlEncoding encoding) {
1301 TiXmlDocument* document = GetDocument();
1302 value = "";
1303
1304 p = SkipWhiteSpace(p, encoding);
1305
1306 if (data) {
1307 data->Stamp(p, encoding);
1308 location = data->Cursor();
1309 }
1310
1311 const char* startTag = "<!--";
1312 const char* endTag = "-->";
1313
1314 if (!StringEqual(p, startTag, false, encoding)) {
1315 document->SetError(TIXML_ERROR_PARSING_COMMENT, p, data, encoding);
1316 return 0;
1317 }
1318
1319 p += strlen(startTag);
1320
1321 // [ 1475201 ] TinyXML parses entities in comments
1322 // Oops - ReadText doesn't work, because we don't want to parse the entities.
1323 // p = ReadText( p, &value, false, endTag, false, encoding );
1324 //
1325 // from the XML spec:
1326 /*
1327 [Definition: Comments may appear anywhere in a document outside other markup;
1328 in
1329 addition,
1330 they may appear within the document type declaration at places
1331 allowed by the grammar.
1332 They are not part of the document's character data; an XML processor
1333 MAY,
1334 but need not,
1335 make it possible for an application to retrieve the text of comments.
1336 For
1337 compatibility,
1338 the string "--" (double-hyphen) MUST NOT occur within comments.]
1339 Parameter
1340 entity
1341 references MUST NOT be recognized within comments.
1342
1343 An example of a comment:
1344
1345 <!-- declarations for <head> & <body> -->
1346 */
1347
1348 value = "";
1349
1350 // Keep all the white space.
1351 while (p && *p && !StringEqual(p, endTag, false, encoding)) {
1352 value.append(p, 1);
1353 ++p;
1354 }
1355
1356 if (p) p += strlen(endTag);
1357
1358 return p;
1359}
1360
1361const char* TiXmlAttribute::Parse(const char* p,
1362 TiXmlParsingData* data,
1363 TiXmlEncoding encoding) {
1364 p = SkipWhiteSpace(p, encoding);
1365
1366 if (!p || !*p) return 0;
1367
1368 // int tabsize = 4;
1369 // if ( document )
1370 // tabsize = document->TabSize();
1371
1372 if (data) {
1373 data->Stamp(p, encoding);
1374 location = data->Cursor();
1375 }
1376
1377 // Read the name, the '=' and the value.
1378 const char* pErr = p;
1379 p = ReadName(p, &name, encoding);
1380
1381 if (!p || !*p) {
1382 if (document)
1383 document->SetError(TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding);
1384
1385 return 0;
1386 }
1387
1388 p = SkipWhiteSpace(p, encoding);
1389
1390 if (!p || !*p || *p != '=') {
1391 if (document)
1392 document->SetError(TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding);
1393
1394 return 0;
1395 }
1396
1397 ++p; // skip '='
1398 p = SkipWhiteSpace(p, encoding);
1399
1400 if (!p || !*p) {
1401 if (document)
1402 document->SetError(TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding);
1403
1404 return 0;
1405 }
1406
1407 const char* end;
1408 const char SINGLE_QUOTE = '\'';
1409 const char DOUBLE_QUOTE = '\"';
1410
1411 if (*p == SINGLE_QUOTE) {
1412 ++p;
1413 end = "\'"; // single quote in string
1414 p = ReadText(p, &value, false, end, false, encoding);
1415 } else if (*p == DOUBLE_QUOTE) {
1416 ++p;
1417 end = "\""; // double quote in string
1418 p = ReadText(p, &value, false, end, false, encoding);
1419 } else {
1420 // All attribute values should be in single or double quotes.
1421 // But this is such a common error that the parser will try
1422 // its best, even without them.
1423 value = "";
1424
1425 while (p && *p // existence
1426 &&
1427 !IsWhiteSpace(*p) && *p != '\n' && *p != '\r' // whitespace
1428 &&
1429 *p != '/' && *p != '>') { // tag end
1430 if (*p == SINGLE_QUOTE || *p == DOUBLE_QUOTE) {
1431 // [ 1451649 ] Attribute values with trailing quotes not handled
1432 // correctly
1433 // We did not have an opening quote but seem to have a
1434 // closing one. Give up and throw an error.
1435 if (document)
1436 document->SetError(TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding);
1437
1438 return 0;
1439 }
1440
1441 value += *p;
1442 ++p;
1443 }
1444 }
1445
1446 return p;
1447}
1448
1449#ifdef TIXML_USE_STL
1450void TiXmlText::StreamIn(std::istream* in, TIXML_STRING* tag) {
1451 while (in->good()) {
1452 int c = in->peek();
1453
1454 if (!cdata && (c == '<')) {
1455 return;
1456 }
1457
1458 if (c <= 0) {
1459 TiXmlDocument* document = GetDocument();
1460
1461 if (document)
1462 document->SetError(
1464
1465 return;
1466 }
1467
1468 (*tag) += (char)c;
1469 in->get(); // "commits" the peek made above
1470
1471 if (cdata && c == '>' && tag->size() >= 3) {
1472 size_t len = tag->size();
1473
1474 if ((*tag)[len - 2] == ']' && (*tag)[len - 3] == ']') {
1475 // terminator of cdata.
1476 return;
1477 }
1478 }
1479 }
1480}
1481#endif
1482
1483const char*
1484TiXmlText::Parse(const char* p, TiXmlParsingData* data, TiXmlEncoding encoding) {
1485 value = "";
1486 TiXmlDocument* document = GetDocument();
1487
1488 if (data) {
1489 data->Stamp(p, encoding);
1490 location = data->Cursor();
1491 }
1492
1493 const char* const startTag = "<![CDATA[";
1494 const char* const endTag = "]]>";
1495
1496 if (cdata || StringEqual(p, startTag, false, encoding)) {
1497 cdata = true;
1498
1499 if (!StringEqual(p, startTag, false, encoding)) {
1500 document->SetError(TIXML_ERROR_PARSING_CDATA, p, data, encoding);
1501 return 0;
1502 }
1503
1504 p += strlen(startTag);
1505
1506 // Keep all the white space, ignore the encoding, etc.
1507 while (p && *p && !StringEqual(p, endTag, false, encoding)) {
1508 value += *p;
1509 ++p;
1510 }
1511
1512 TIXML_STRING dummy;
1513 p = ReadText(p, &dummy, false, endTag, false, encoding);
1514 return p;
1515 } else {
1516 bool ignoreWhite = true;
1517
1518 const char* end = "<";
1519 p = ReadText(p, &value, ignoreWhite, end, false, encoding);
1520
1521 if (p) return p - 1; // don't truncate the '<'
1522
1523 return 0;
1524 }
1525}
1526
1527#ifdef TIXML_USE_STL
1528void TiXmlDeclaration::StreamIn(std::istream* in, TIXML_STRING* tag) {
1529 while (in->good()) {
1530 int c = in->get();
1531
1532 if (c <= 0) {
1533 TiXmlDocument* document = GetDocument();
1534
1535 if (document)
1536 document->SetError(
1538
1539 return;
1540 }
1541
1542 (*tag) += (char)c;
1543
1544 if (c == '>') {
1545 // All is well.
1546 return;
1547 }
1548 }
1549}
1550#endif
1551
1552const char* TiXmlDeclaration::Parse(const char* p,
1553 TiXmlParsingData* data,
1554 TiXmlEncoding _encoding) {
1555 p = SkipWhiteSpace(p, _encoding);
1556 // Find the beginning, find the end, and look for
1557 // the stuff in-between.
1558 TiXmlDocument* document = GetDocument();
1559
1560 if (!p || !*p || !StringEqual(p, "<?xml", true, _encoding)) {
1561 if (document)
1562 document->SetError(TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding);
1563
1564 return 0;
1565 }
1566
1567 if (data) {
1568 data->Stamp(p, _encoding);
1569 location = data->Cursor();
1570 }
1571
1572 p += 5;
1573
1574 version = "";
1575 encoding = "";
1576 standalone = "";
1577
1578 while (p && *p) {
1579 if (*p == '>') {
1580 ++p;
1581 return p;
1582 }
1583
1584 p = SkipWhiteSpace(p, _encoding);
1585
1586 if (StringEqual(p, "version", true, _encoding)) {
1587 TiXmlAttribute attrib;
1588 p = attrib.Parse(p, data, _encoding);
1589 version = attrib.Value();
1590 } else if (StringEqual(p, "encoding", true, _encoding)) {
1591 TiXmlAttribute attrib;
1592 p = attrib.Parse(p, data, _encoding);
1593 encoding = attrib.Value();
1594 } else if (StringEqual(p, "standalone", true, _encoding)) {
1595 TiXmlAttribute attrib;
1596 p = attrib.Parse(p, data, _encoding);
1597 standalone = attrib.Value();
1598 } else {
1599 // Read over whatever it is.
1600 while (p && *p && *p != '>' && !IsWhiteSpace(*p))
1601 ++p;
1602 }
1603 }
1604
1605 return 0;
1606}
1607
1608bool TiXmlText::Blank() const {
1609 for (unsigned i = 0; i < value.length(); i++)
1610 if (!IsWhiteSpace(value[i])) return false;
1611
1612 return true;
1613}
1614
1615#ifdef TIXML_USE_STL
1617 while (in->good()) {
1618 int c = in->get();
1619
1620 if (c <= 0) {
1621 TiXmlDocument* document = GetDocument();
1622
1623 if (document)
1624 document->SetError(
1626
1627 return;
1628 }
1629
1630 (*tag) += (char)c;
1631
1632 if (c == '>') {
1633 // All is well.
1634 return;
1635 }
1636 }
1637}
1638#endif
1639
1640const char* TiXmlStylesheetReference::Parse(const char* p,
1641 TiXmlParsingData* data,
1642 TiXmlEncoding _encoding) {
1643 p = SkipWhiteSpace(p, _encoding);
1644 // Find the beginning, find the end, and look for
1645 // the stuff in-between.
1646 TiXmlDocument* document = GetDocument();
1647
1648 if (!p || !*p || !StringEqual(p, "<?xml-stylesheet", true, _encoding)) {
1649 if (document)
1650 document->SetError(TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding);
1651
1652 return 0;
1653 }
1654
1655 if (data) {
1656 data->Stamp(p, _encoding);
1657 location = data->Cursor();
1658 }
1659
1660 p += 5;
1661
1662 type = "";
1663 href = "";
1664
1665 while (p && *p) {
1666 if (*p == '>') {
1667 ++p;
1668 return p;
1669 }
1670
1671 p = SkipWhiteSpace(p, _encoding);
1672
1673 if (StringEqual(p, "type", true, _encoding)) {
1674 TiXmlAttribute attrib;
1675 p = attrib.Parse(p, data, _encoding);
1676 type = attrib.Value();
1677 } else if (StringEqual(p, "href", true, _encoding)) {
1678 TiXmlAttribute attrib;
1679 p = attrib.Parse(p, data, _encoding);
1680 href = attrib.Value();
1681 } else {
1682 // Read over whatever it is.
1683 while (p && *p && *p != '>' && !IsWhiteSpace(*p))
1684 ++p;
1685 }
1686 }
1687
1688 return 0;
1689}
An attribute is a name-value pair.
Definition tinyxml.h:915
const char * Value() const
Return the value of this attribute.
Definition tinyxml.h:947
void SetValue(const char *_value)
Set the value.
Definition tinyxml.h:979
const TIXML_STRING & NameTStr() const
Definition tinyxml.h:961
const char * Name() const
Return the name of this attribute.
Definition tinyxml.h:944
void SetDocument(TiXmlDocument *doc)
Definition tinyxml.h:1021
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
TiXmlDocument * document
Definition tinyxml.h:1027
TIXML_STRING value
Definition tinyxml.h:1029
TIXML_STRING name
Definition tinyxml.h:1028
static void ConvertUTF32ToUTF8(unsigned long input, char *output, int *length)
@ NUM_ENTITY
Definition tinyxml.h:440
TiXmlCursor location
Definition tinyxml.h:410
static bool StreamWhiteSpace(std::istream *in, TIXML_STRING *tag)
static const char * ReadName(const char *p, TIXML_STRING *name, TiXmlEncoding encoding)
static int IsAlphaNum(unsigned char anyByte, TiXmlEncoding encoding)
static bool condenseWhiteSpace
Definition tinyxml.h:445
static bool StringEqual(const char *p, const char *endTag, bool ignoreCase, TiXmlEncoding encoding)
static const char * GetChar(const char *p, char *_value, int *length, TiXmlEncoding encoding)
Definition tinyxml.h:368
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)=0
@ TIXML_ERROR_STRING_COUNT
Definition tinyxml.h:323
@ TIXML_ERROR_READING_END_TAG
Definition tinyxml.h:314
@ TIXML_ERROR_PARSING_UNKNOWN
Definition tinyxml.h:315
@ TIXML_ERROR_PARSING_DECLARATION
Definition tinyxml.h:317
@ TIXML_ERROR_PARSING_ELEMENT
Definition tinyxml.h:309
@ TIXML_ERROR_PARSING_EMPTY
Definition tinyxml.h:313
@ TIXML_ERROR_READING_ATTRIBUTES
Definition tinyxml.h:312
@ TIXML_ERROR_PARSING_COMMENT
Definition tinyxml.h:316
@ TIXML_ERROR_OUT_OF_MEMORY
Definition tinyxml.h:308
@ TIXML_ERROR_PARSING_CDATA
Definition tinyxml.h:320
@ TIXML_ERROR_DOCUMENT_EMPTY
Definition tinyxml.h:318
@ TIXML_ERROR
Definition tinyxml.h:306
@ TIXML_ERROR_EMBEDDED_nullptr
Definition tinyxml.h:319
@ TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME
Definition tinyxml.h:310
@ TIXML_ERROR_READING_ELEMENT_VALUE
Definition tinyxml.h:311
static int ToLower(int v, TiXmlEncoding encoding)
Definition tinyxml.h:419
static const char * errorString[TIXML_ERROR_STRING_COUNT]
Definition tinyxml.h:35
static const char * ReadText(const char *in, TIXML_STRING *text, bool ignoreWhiteSpace, const char *endTag, bool ignoreCase, TiXmlEncoding encoding)
static bool StreamTo(std::istream *in, int character, TIXML_STRING *tag)
static Entity entity[NUM_ENTITY]
Definition tinyxml.h:44
static const char * SkipWhiteSpace(const char *, TiXmlEncoding encoding)
static const char * GetEntity(const char *in, char *value, int *length, TiXmlEncoding encoding)
static const int utf8ByteTable[256]
Definition tinyxml.h:64
static bool IsWhiteSpaceCondensed()
Return the current white space setting.
Definition tinyxml.h:247
static int IsAlpha(unsigned char anyByte, TiXmlEncoding encoding)
static bool IsWhiteSpace(char c)
Definition tinyxml.h:328
An XML comment.
Definition tinyxml.h:1330
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
In correct XML the declaration is the first entry in the file.
Definition tinyxml.h:1469
TIXML_STRING encoding
Definition tinyxml.h:1530
TIXML_STRING standalone
Definition tinyxml.h:1531
const char * Encoding() const
Encoding. Will return an empty string if none was found.
Definition tinyxml.h:1495
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
TIXML_STRING version
Definition tinyxml.h:1529
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
TIXML_STRING errorDesc
Definition tinyxml.h:1852
bool useMicrosoftBOM
Definition tinyxml.h:1855
void SetError(int err, const char *errorLocation, TiXmlParsingData *prevData, TiXmlEncoding encoding)
virtual const char * Parse(const char *p, TiXmlParsingData *data=0, TiXmlEncoding encoding=TIXML_DEFAULT_ENCODING)
Parse the given null terminated block of xml data.
int TabSize() const
Definition tinyxml.h:1794
TiXmlCursor errorLocation
Definition tinyxml.h:1854
void ClearError()
If you have handled the error, it can be reset with this call.
Definition tinyxml.h:1799
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
TiXmlAttributeSet attributeSet
Definition tinyxml.h:1325
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
const char * ReadValue(const char *in, TiXmlParsingData *prevData, TiXmlEncoding encoding)
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
friend class TiXmlDocument
Definition tinyxml.h:455
TiXmlNode * LinkEndChild(TiXmlNode *addThis)
Add a new node related to this.
Definition tinyxml.cpp:153
TiXmlNode(NodeType _type)
Definition tinyxml.cpp:113
virtual const TiXmlDeclaration * ToDeclaration() const
Cast to a more defined type. Will return null if not of the requested type.
Definition tinyxml.h:804
TiXmlNode * parent
Definition tinyxml.h:892
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)=0
friend class TiXmlElement
Definition tinyxml.h:456
TiXmlNode * Identify(const char *start, TiXmlEncoding encoding)
virtual const TiXmlElement * ToElement() const
Cast to a more defined type. Will return null if not of the requested type.
Definition tinyxml.h:788
const TiXmlDocument * GetDocument() const
Return a pointer to the Document this node lives in.
Definition tinyxml.cpp:424
TIXML_STRING value
Definition tinyxml.h:898
TiXmlNode * firstChild
Definition tinyxml.h:895
friend class TiXmlDocument
const TiXmlCursor & Cursor()
void Stamp(const char *now, TiXmlEncoding encoding)
TiXmlParsingData(const char *start, int _tabsize, int row, int col)
A stylesheet reference looks like this:
Definition tinyxml.h:1543
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
XML text.
Definition tinyxml.h:1386
bool Blank() const
bool cdata
Definition tinyxml.h:1452
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
void SetCDATA(bool _cdata)
Turns on or off a CDATA representation of text.
Definition tinyxml.h:1422
Any tag that tinyXml doesn't recognize is saved as an unknown.
Definition tinyxml.h:1608
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
TiXmlEncoding
Definition tinyxml.h:179
@ TIXML_ENCODING_UNKNOWN
Definition tinyxml.h:180
@ TIXML_ENCODING_LEGACY
Definition tinyxml.h:182
@ TIXML_ENCODING_UTF8
Definition tinyxml.h:181
#define TIXML_STRING
Definition tinyxml.h:60
const TiXmlEncoding TIXML_DEFAULT_ENCODING
Definition tinyxml.h:185
const unsigned char TIXML_UTF_LEAD_0
const unsigned char TIXML_UTF_LEAD_1
const unsigned char TIXML_UTF_LEAD_2