CMS 3D CMS Logo

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