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