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