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