DD4hep - The AIDA detector description toolkit for high energy physics experiments
DD4hep  Rev:Unversioneddirectory
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tinyxmlparser_inl.h
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  F.Gaede, DESY : changed extension to .cc for use with marlin
25  and include from "marlin/tinyxml.h"
26 
27 */
28 
29 #include <ctype.h>
30 #include <stddef.h>
31 
32 #include "XML/tinyxml.h"
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  //FIXME: workaround for processor conditions of type &&
50  //needs to be tested if there are no adverse effects due to this change!!
51  { "&", 1, '&' },
52  //{ "&amp;", 5, '&' },
53 
54  { "&lt;", 4, '<' },
55  { "&gt;", 4, '>' },
56  { "&quot;", 6, '\"' },
57  { "&apos;", 6, '\'' }
58  };
59 
60 // Bunch of unicode info at:
61 // http://www.unicode.org/faq/utf_bom.html
62 // Including the basic of this table, which determines the #bytes in the
63 // sequence from the lead byte. 1 placed for invalid sequences --
64 // although the result will be junk, pass it through as much as possible.
65 // Beware of the non-characters in UTF-8:
66 // ef bb bf (Microsoft "lead bytes")
67 // ef bf be
68 // ef bf bf
69 
70 const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
71 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
72 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
73 
74 const int TiXmlBase::utf8ByteTable[256] =
75  {
76  // 0 1 2 3 4 5 6 7 8 9 a b c d e f
77  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
78  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
79  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20
80  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30
81  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40
82  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50
83  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60
84  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range
85  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid
86  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
87  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
88  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
89  1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte
90  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
91  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte
92  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
93  };
94 
95 
96 void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
97 {
98  const unsigned long BYTE_MASK = 0xBF;
99  const unsigned long BYTE_MARK = 0x80;
100  const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
101 
102  if (input < 0x80)
103  *length = 1;
104  else if ( input < 0x800 )
105  *length = 2;
106  else if ( input < 0x10000 )
107  *length = 3;
108  else if ( input < 0x200000 )
109  *length = 4;
110  else
111  { *length = 0; return; } // This code won't covert this correctly anyway.
112 
113  output += *length;
114 
115  // Scary scary fall throughs.
116  switch (*length)
117  {
118  case 4:
119  --output;
120  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
121  input >>= 6;
122  case 3:
123  --output;
124  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
125  input >>= 6;
126  case 2:
127  --output;
128  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
129  input >>= 6;
130  case 1:
131  --output;
132  *output = (char)(input | FIRST_BYTE_MARK[*length]);
133  }
134 }
135 
136 
137 /*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
138 {
139  // This will only work for low-ascii, everything else is assumed to be a valid
140  // letter. I'm not sure this is the best approach, but it is quite tricky trying
141  // to figure out alhabetical vs. not across encoding. So take a very
142  // conservative approach.
143 
144  // if ( encoding == TIXML_ENCODING_UTF8 )
145  // {
146  if ( anyByte < 127 )
147  return isalpha( anyByte );
148  else
149  return 1; // What else to do? The unicode set is huge...get the english ones right.
150  // }
151  // else
152  // {
153  // return isalpha( anyByte );
154  // }
155 }
156 
157 
158 /*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
159 {
160  // This will only work for low-ascii, everything else is assumed to be a valid
161  // letter. I'm not sure this is the best approach, but it is quite tricky trying
162  // to figure out alhabetical vs. not across encoding. So take a very
163  // conservative approach.
164 
165  // if ( encoding == TIXML_ENCODING_UTF8 )
166  // {
167  if ( anyByte < 127 )
168  return isalnum( anyByte );
169  else
170  return 1; // What else to do? The unicode set is huge...get the english ones right.
171  // }
172  // else
173  // {
174  // return isalnum( anyByte );
175  // }
176 }
177 
178 
180 {
181  friend class TiXmlDocument;
182 public:
183  void Stamp( const char* now, TiXmlEncoding encoding );
184 
185  const TiXmlCursor& Cursor() { return cursor; }
186 
187 private:
188  // Only used by the document!
189  TiXmlParsingData( const char* start, int _tabsize, int row, int col )
190  {
191  assert( start );
192  stamp = start;
193  tabsize = _tabsize;
194  cursor.row = row;
195  cursor.col = col;
196  }
197 
199  const char* stamp;
200  int tabsize;
201 };
202 
203 
204 void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding )
205 {
206  assert( now );
207 
208  // Do nothing if the tabsize is 0.
209  if ( tabsize < 1 )
210  {
211  return;
212  }
213 
214  // Get the current row, column.
215  int row = cursor.row;
216  int col = cursor.col;
217  const char* p = stamp;
218  assert( p );
219 
220  while ( p < now )
221  {
222  // Treat p as unsigned, so we have a happy compiler.
223  const unsigned char* pU = (const unsigned char*)p;
224 
225  // Code contributed by Fletcher Dunn: (modified by lee)
226  switch (*pU) {
227  case 0:
228  // We *should* never get here, but in case we do, don't
229  // advance past the terminating null character, ever
230  return;
231 
232  case '\r':
233  // bump down to the next line
234  ++row;
235  col = 0;
236  // Eat the character
237  ++p;
238 
239  // Check for \r\n sequence, and treat this as a single character
240  if (*p == '\n') {
241  ++p;
242  }
243  break;
244 
245  case '\n':
246  // bump down to the next line
247  ++row;
248  col = 0;
249 
250  // Eat the character
251  ++p;
252 
253  // Check for \n\r sequence, and treat this as a single
254  // character. (Yes, this bizarre thing does occur still
255  // on some arcane platforms...)
256  if (*p == '\r') {
257  ++p;
258  }
259  break;
260 
261  case '\t':
262  // Eat the character
263  ++p;
264 
265  // Skip to next tab stop
266  col = (col / tabsize + 1) * tabsize;
267  break;
268 
269  case TIXML_UTF_LEAD_0:
270  if ( encoding == TIXML_ENCODING_UTF8 )
271  {
272  if ( *(p+1) && *(p+2) )
273  {
274  // In these cases, don't advance the column. These are
275  // 0-width spaces.
276  if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 )
277  p += 3;
278  else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU )
279  p += 3;
280  else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU )
281  p += 3;
282  else
283  { p +=3; ++col; } // A normal character.
284  }
285  }
286  else
287  {
288  ++p;
289  ++col;
290  }
291  break;
292 
293  default:
294  if ( encoding == TIXML_ENCODING_UTF8 )
295  {
296  // Eat the 1 to 4 byte utf8 character.
297  int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)];
298  if ( step == 0 )
299  step = 1; // Error case from bad encoding, but handle gracefully.
300  p += step;
301 
302  // Just advance one column, of course.
303  ++col;
304  }
305  else
306  {
307  ++p;
308  ++col;
309  }
310  break;
311  }
312  }
313  cursor.row = row;
314  cursor.col = col;
315  assert( cursor.row >= -1 );
316  assert( cursor.col >= -1 );
317  stamp = p;
318  assert( stamp );
319 }
320 
321 
322 const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
323 {
324  if ( !p || !*p )
325  {
326  return 0;
327  }
328  if ( encoding == TIXML_ENCODING_UTF8 )
329  {
330  while ( *p )
331  {
332  const unsigned char* pU = (const unsigned char*)p;
333 
334  // Skip the stupid Microsoft UTF-8 Byte order marks
335  if ( *(pU+0)==TIXML_UTF_LEAD_0
336  && *(pU+1)==TIXML_UTF_LEAD_1
337  && *(pU+2)==TIXML_UTF_LEAD_2 )
338  {
339  p += 3;
340  continue;
341  }
342  else if(*(pU+0)==TIXML_UTF_LEAD_0
343  && *(pU+1)==0xbfU
344  && *(pU+2)==0xbeU )
345  {
346  p += 3;
347  continue;
348  }
349  else if(*(pU+0)==TIXML_UTF_LEAD_0
350  && *(pU+1)==0xbfU
351  && *(pU+2)==0xbfU )
352  {
353  p += 3;
354  continue;
355  }
356 
357  if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space.
358  ++p;
359  else
360  break;
361  }
362  }
363  else
364  {
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( node );
769  }
770  else
771  {
772  break;
773  }
774 
775  // Did we get encoding info?
776  if ( encoding == TIXML_ENCODING_UNKNOWN
777  && node->ToDeclaration() )
778  {
779  TiXmlDeclaration* dec = node->ToDeclaration();
780  const char* enc = dec->Encoding();
781  assert( enc );
782 
783  if ( *enc == 0 )
784  encoding = TIXML_ENCODING_UTF8;
785  else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
786  encoding = TIXML_ENCODING_UTF8;
787  else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
788  encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice
789  else
790  encoding = TIXML_ENCODING_LEGACY;
791  }
792 
793  p = SkipWhiteSpace( p, encoding );
794  }
795 
796  // Was this empty?
797  if ( !firstChild ) {
798  SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding );
799  return 0;
800  }
801 
802  // All is well.
803  return p;
804 }
805 
806 void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
807 {
808  // The first error in a chain is more accurate - don't set again!
809  if ( error )
810  return;
811 
812  assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
813  error = true;
814  errorId = err;
816 
818  if ( pError && data )
819  {
820  data->Stamp( pError, encoding );
821  errorLocation = data->Cursor();
822  }
823 }
824 
825 
826 TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
827 {
828  TiXmlNode* returnNode = 0;
829 
830  p = SkipWhiteSpace( p, encoding );
831  if( !p || !*p || *p != '<' )
832  {
833  return 0;
834  }
835 
836  TiXmlDocument* doc = GetDocument();
837  p = SkipWhiteSpace( p, encoding );
838 
839  if ( !p || !*p )
840  {
841  return 0;
842  }
843 
844  // What is this thing?
845  // - Elements start with a letter or underscore, but xml is reserved.
846  // - Comments: <!--
847  // - Decleration: <?xml
848  // - Everthing else is unknown to tinyxml.
849  //
850 
851  const char* xmlHeader = { "<?xml" };
852  const char* commentHeader = { "<!--" };
853  const char* dtdHeader = { "<!" };
854  const char* cdataHeader = { "<![CDATA[" };
855 
856  if ( StringEqual( p, xmlHeader, true, encoding ) )
857  {
858 #ifdef DEBUG_PARSER
859  TIXML_LOG( "XML parsing Declaration\n" );
860 #endif
861  returnNode = new TiXmlDeclaration();
862  }
863  else if ( StringEqual( p, commentHeader, false, encoding ) )
864  {
865 #ifdef DEBUG_PARSER
866  TIXML_LOG( "XML parsing Comment\n" );
867 #endif
868  returnNode = new TiXmlComment();
869  }
870  else if ( StringEqual( p, cdataHeader, false, encoding ) )
871  {
872 #ifdef DEBUG_PARSER
873  TIXML_LOG( "XML parsing CDATA\n" );
874 #endif
875  TiXmlText* text = new TiXmlText( "" );
876  text->SetCDATA( true );
877  returnNode = text;
878  }
879  else if ( StringEqual( p, dtdHeader, false, encoding ) )
880  {
881 #ifdef DEBUG_PARSER
882  TIXML_LOG( "XML parsing Unknown(1)\n" );
883 #endif
884  returnNode = new TiXmlUnknown();
885  }
886  else if ( IsAlpha( *(p+1), encoding )
887  || *(p+1) == '_' )
888  {
889 #ifdef DEBUG_PARSER
890  TIXML_LOG( "XML parsing Element\n" );
891 #endif
892  returnNode = new TiXmlElement( "" );
893  }
894  else
895  {
896 #ifdef DEBUG_PARSER
897  TIXML_LOG( "XML parsing Unknown(2)\n" );
898 #endif
899  returnNode = new TiXmlUnknown();
900  }
901 
902  if ( returnNode )
903  {
904  // Set the parent, so it can report errors
905  returnNode->parent = this;
906  }
907  else
908  {
909  if ( doc )
911  }
912  return returnNode;
913 }
914 
915 #ifdef TIXML_USE_STL
916 
917 void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag)
918 {
919  // We're called with some amount of pre-parsing. That is, some of "this"
920  // element is in "tag". Go ahead and stream to the closing ">"
921  while( in->good() )
922  {
923  int c = in->get();
924  if ( c <= 0 )
925  {
926  TiXmlDocument* document = GetDocument();
927  if ( document )
929  return;
930  }
931  (*tag) += (char) c ;
932 
933  if ( c == '>' )
934  break;
935  }
936 
937  if ( tag->length() < 3 ) return;
938 
939  // Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
940  // If not, identify and stream.
941 
942  if ( tag->at( tag->length() - 1 ) == '>'
943  && tag->at( tag->length() - 2 ) == '/' )
944  {
945  // All good!
946  return;
947  }
948  else if ( tag->at( tag->length() - 1 ) == '>' )
949  {
950  // There is more. Could be:
951  // text
952  // cdata text (which looks like another node)
953  // closing tag
954  // another node.
955  for ( ;; )
956  {
957  StreamWhiteSpace( in, tag );
958 
959  // Do we have text?
960  if ( in->good() && in->peek() != '<' )
961  {
962  // Yep, text.
963  TiXmlText text( "" );
964  text.StreamIn( in, tag );
965 
966  // What follows text is a closing tag or another node.
967  // Go around again and figure it out.
968  continue;
969  }
970 
971  // We now have either a closing tag...or another node.
972  // We should be at a "<", regardless.
973  if ( !in->good() ) return;
974  assert( in->peek() == '<' );
975  int tagIndex = (int) tag->length();
976 
977  bool closingTag = false;
978  bool firstCharFound = false;
979 
980  for( ;; )
981  {
982  if ( !in->good() )
983  return;
984 
985  int c = in->peek();
986  if ( c <= 0 )
987  {
988  TiXmlDocument* document = GetDocument();
989  if ( document )
991  return;
992  }
993 
994  if ( c == '>' )
995  break;
996 
997  *tag += (char) c;
998  in->get();
999 
1000  // Early out if we find the CDATA id.
1001  if ( c == '[' && tag->size() >= 9 )
1002  {
1003  size_t len = tag->size();
1004  const char* start = tag->c_str() + len - 9;
1005  if ( strcmp( start, "<![CDATA[" ) == 0 ) {
1006  assert( !closingTag );
1007  break;
1008  }
1009  }
1010 
1011  if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
1012  {
1013  firstCharFound = true;
1014  if ( c == '/' )
1015  closingTag = true;
1016  }
1017  }
1018  // If it was a closing tag, then read in the closing '>' to clean up the input stream.
1019  // If it was not, the streaming will be done by the tag.
1020  if ( closingTag )
1021  {
1022  if ( !in->good() )
1023  return;
1024 
1025  int c = in->get();
1026  if ( c <= 0 )
1027  {
1028  TiXmlDocument* document = GetDocument();
1029  if ( document )
1031  return;
1032  }
1033  assert( c == '>' );
1034  *tag += (char) c;
1035 
1036  // We are done, once we've found our closing tag.
1037  return;
1038  }
1039  else
1040  {
1041  // If not a closing tag, id it, and stream.
1042  const char* tagloc = tag->c_str() + tagIndex;
1043  TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
1044  if ( !node )
1045  return;
1046  node->StreamIn( in, tag );
1047  delete node;
1048  node = 0;
1049 
1050  // No return: go around from the beginning: text, closing tag, or node.
1051  }
1052  }
1053  }
1054 }
1055 #endif
1056 
1057 const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1058 {
1059  p = SkipWhiteSpace( p, encoding );
1060  TiXmlDocument* document = GetDocument();
1061 
1062  if ( !p || !*p )
1063  {
1064  if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
1065  return 0;
1066  }
1067 
1068  if ( data )
1069  {
1070  data->Stamp( p, encoding );
1071  location = data->Cursor();
1072  }
1073 
1074  if ( *p != '<' )
1075  {
1076  if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
1077  return 0;
1078  }
1079 
1080  p = SkipWhiteSpace( p+1, encoding );
1081 
1082  // Read the name.
1083  const char* pErr = p;
1084 
1085  p = ReadName( p, &value, encoding );
1086  if ( !p || !*p )
1087  {
1088  if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
1089  return 0;
1090  }
1091 
1092  TIXML_STRING endTag ("</");
1093  endTag += value;
1094  endTag += ">";
1095 
1096  // Check for and read attributes. Also look for an empty
1097  // tag or an end tag.
1098  while ( p && *p )
1099  {
1100  pErr = p;
1101  p = SkipWhiteSpace( p, encoding );
1102  if ( !p || !*p )
1103  {
1104  if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
1105  return 0;
1106  }
1107  if ( *p == '/' )
1108  {
1109  ++p;
1110  // Empty tag.
1111  if ( *p != '>' )
1112  {
1113  if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
1114  return 0;
1115  }
1116  return (p+1);
1117  }
1118  else if ( *p == '>' )
1119  {
1120  // Done with attributes (if there were any.)
1121  // Read the value -- which can include other
1122  // elements -- read the end tag, and return.
1123  ++p;
1124  p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens.
1125  if ( !p || !*p )
1126  return 0;
1127 
1128  // We should find the end tag now
1129  if ( StringEqual( p, endTag.c_str(), false, encoding ) )
1130  {
1131  p += endTag.length();
1132  return p;
1133  }
1134  else
1135  {
1136  if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
1137  return 0;
1138  }
1139  }
1140  else
1141  {
1142  // Try to read an attribute:
1143  TiXmlAttribute* attrib = new TiXmlAttribute();
1144  if ( !attrib )
1145  {
1146  if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding );
1147  return 0;
1148  }
1149 
1150  attrib->SetDocument( document );
1151  pErr = p;
1152  p = attrib->Parse( p, data, encoding );
1153 
1154  if ( !p || !*p )
1155  {
1156  if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
1157  delete attrib;
1158  return 0;
1159  }
1160 
1161  // Handle the strange case of double attributes:
1162 #ifdef TIXML_USE_STL
1163  TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() );
1164 #else
1165  TiXmlAttribute* node = attributeSet.Find( attrib->Name() );
1166 #endif
1167  if ( node )
1168  {
1169  node->SetValue( attrib->Value() );
1170  delete attrib;
1171  return 0;
1172  }
1173 
1174  attributeSet.Add( attrib );
1175  }
1176  }
1177  return p;
1178 }
1179 
1180 
1181 const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1182 {
1183  TiXmlDocument* document = GetDocument();
1184 
1185  // Read in text and elements in any order.
1186  const char* pWithWhiteSpace = p;
1187  p = SkipWhiteSpace( p, encoding );
1188 
1189  while ( p && *p )
1190  {
1191  if ( *p != '<' )
1192  {
1193  // Take what we have, make a text element.
1194  TiXmlText* textNode = new TiXmlText( "" );
1195 
1196  if ( !textNode )
1197  {
1198  if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding );
1199  return 0;
1200  }
1201 
1203  {
1204  p = textNode->Parse( p, data, encoding );
1205  }
1206  else
1207  {
1208  // Special case: we want to keep the white space
1209  // so that leading spaces aren't removed.
1210  p = textNode->Parse( pWithWhiteSpace, data, encoding );
1211  }
1212 
1213  if ( !textNode->Blank() )
1214  LinkEndChild( textNode );
1215  else
1216  delete textNode;
1217  }
1218  else
1219  {
1220  // We hit a '<'
1221  // Have we hit a new element or an end tag? This could also be
1222  // a TiXmlText in the "CDATA" style.
1223  if ( StringEqual( p, "</", false, encoding ) )
1224  {
1225  return p;
1226  }
1227  else
1228  {
1229  TiXmlNode* node = Identify( p, encoding );
1230  if ( node )
1231  {
1232  p = node->Parse( p, data, encoding );
1233  LinkEndChild( node );
1234  }
1235  else
1236  {
1237  return 0;
1238  }
1239  }
1240  }
1241  pWithWhiteSpace = p;
1242  p = SkipWhiteSpace( p, encoding );
1243  }
1244 
1245  if ( !p )
1246  {
1247  if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
1248  }
1249  return p;
1250 }
1251 
1252 
1253 #ifdef TIXML_USE_STL
1254 void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag )
1255 {
1256  while ( in->good() )
1257  {
1258  int c = in->get();
1259  if ( c <= 0 )
1260  {
1261  TiXmlDocument* document = GetDocument();
1262  if ( document )
1264  return;
1265  }
1266  (*tag) += (char) c;
1267 
1268  if ( c == '>' )
1269  {
1270  // All is well.
1271  return;
1272  }
1273  }
1274 }
1275 #endif
1276 
1277 
1278 const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1279 {
1280  TiXmlDocument* document = GetDocument();
1281  p = SkipWhiteSpace( p, encoding );
1282 
1283  if ( data )
1284  {
1285  data->Stamp( p, encoding );
1286  location = data->Cursor();
1287  }
1288  if ( !p || !*p || *p != '<' )
1289  {
1290  if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
1291  return 0;
1292  }
1293  ++p;
1294  value = "";
1295 
1296  while ( p && *p && *p != '>' )
1297  {
1298  value += *p;
1299  ++p;
1300  }
1301 
1302  if ( !p )
1303  {
1304  if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
1305  }
1306  if ( *p == '>' )
1307  return p+1;
1308  return p;
1309 }
1310 
1311 #ifdef TIXML_USE_STL
1312 void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag )
1313 {
1314  while ( in->good() )
1315  {
1316  int c = in->get();
1317  if ( c <= 0 )
1318  {
1319  TiXmlDocument* document = GetDocument();
1320  if ( document )
1322  return;
1323  }
1324 
1325  (*tag) += (char) c;
1326 
1327  if ( c == '>'
1328  && tag->at( tag->length() - 2 ) == '-'
1329  && tag->at( tag->length() - 3 ) == '-' )
1330  {
1331  // All is well.
1332  return;
1333  }
1334  }
1335 }
1336 #endif
1337 
1338 
1339 const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1340 {
1341  TiXmlDocument* document = GetDocument();
1342  value = "";
1343 
1344  p = SkipWhiteSpace( p, encoding );
1345 
1346  if ( data )
1347  {
1348  data->Stamp( p, encoding );
1349  location = data->Cursor();
1350  }
1351  const char* startTag = "<!--";
1352  const char* endTag = "-->";
1353 
1354  if ( !StringEqual( p, startTag, false, encoding ) )
1355  {
1356  document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
1357  return 0;
1358  }
1359  p += strlen( startTag );
1360  p = ReadText( p, &value, false, endTag, false, encoding );
1361  return p;
1362 }
1363 
1364 
1365 const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1366 {
1367  p = SkipWhiteSpace( p, encoding );
1368  if ( !p || !*p ) return 0;
1369 
1370  // int tabsize = 4;
1371  // if ( document )
1372  // tabsize = document->TabSize();
1373 
1374  if ( data )
1375  {
1376  data->Stamp( p, encoding );
1377  location = data->Cursor();
1378  }
1379  // Read the name, the '=' and the value.
1380  const char* pErr = p;
1381  p = ReadName( p, &name, encoding );
1382  if ( !p || !*p )
1383  {
1384  if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
1385  return 0;
1386  }
1387  p = SkipWhiteSpace( p, encoding );
1388  if ( !p || !*p || *p != '=' )
1389  {
1390  if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
1391  return 0;
1392  }
1393 
1394  ++p; // skip '='
1395  p = SkipWhiteSpace( p, encoding );
1396  if ( !p || !*p )
1397  {
1398  if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
1399  return 0;
1400  }
1401 
1402  const char* end;
1403  const char SINGLE_QUOTE = '\'';
1404  const char DOUBLE_QUOTE = '\"';
1405 
1406  if ( *p == SINGLE_QUOTE )
1407  {
1408  ++p;
1409  end = "\'"; // single quote in string
1410  p = ReadText( p, &value, false, end, false, encoding );
1411  }
1412  else if ( *p == DOUBLE_QUOTE )
1413  {
1414  ++p;
1415  end = "\""; // double quote in string
1416  p = ReadText( p, &value, false, end, false, encoding );
1417  }
1418  else
1419  {
1420  // All attribute values should be in single or double quotes.
1421  // But this is such a common error that the parser will try
1422  // its best, even without them.
1423  value = "";
1424  while ( p && *p // existence
1425  && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace
1426  && *p != '/' && *p != '>' ) // tag end
1427  {
1428  if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) {
1429  // [ 1451649 ] Attribute values with trailing quotes not handled correctly
1430  // We did not have an opening quote but seem to have a
1431  // closing one. Give up and throw an error.
1432  if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
1433  return 0;
1434  }
1435  value += *p;
1436  ++p;
1437  }
1438  }
1439  return p;
1440 }
1441 
1442 #ifdef TIXML_USE_STL
1443 void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag )
1444 {
1445  while ( in->good() )
1446  {
1447  int c = in->peek();
1448  if ( !cdata && (c == '<' ) )
1449  {
1450  return;
1451  }
1452  if ( c <= 0 )
1453  {
1454  TiXmlDocument* document = GetDocument();
1455  if ( document )
1457  return;
1458  }
1459 
1460  (*tag) += (char) c;
1461  in->get(); // "commits" the peek made above
1462 
1463  if ( cdata && c == '>' && tag->size() >= 3 ) {
1464  size_t len = tag->size();
1465  if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) {
1466  // terminator of cdata.
1467  return;
1468  }
1469  }
1470  }
1471 }
1472 #endif
1473 
1474 const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
1475 {
1476  value = "";
1477  TiXmlDocument* document = GetDocument();
1478 
1479  if ( data )
1480  {
1481  data->Stamp( p, encoding );
1482  location = data->Cursor();
1483  }
1484 
1485  const char* const startTag = "<![CDATA[";
1486  const char* const endTag = "]]>";
1487 
1488  if ( cdata || StringEqual( p, startTag, false, encoding ) )
1489  {
1490  cdata = true;
1491 
1492  if ( !StringEqual( p, startTag, false, encoding ) )
1493  {
1494  document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding );
1495  return 0;
1496  }
1497  p += strlen( startTag );
1498 
1499  // Keep all the white space, ignore the encoding, etc.
1500  while ( p && *p
1501  && !StringEqual( p, endTag, false, encoding )
1502  )
1503  {
1504  value += *p;
1505  ++p;
1506  }
1507 
1508  TIXML_STRING dummy;
1509  p = ReadText( p, &dummy, false, endTag, false, encoding );
1510  return p;
1511  }
1512  else
1513  {
1514  bool ignoreWhite = true;
1515 
1516  const char* end = "<";
1517  p = ReadText( p, &value, ignoreWhite, end, false, encoding );
1518  if ( p )
1519  return p-1; // don't truncate the '<'
1520  return 0;
1521  }
1522 }
1523 
1524 #ifdef TIXML_USE_STL
1525 void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag )
1526 {
1527  while ( in->good() )
1528  {
1529  int c = in->get();
1530  if ( c <= 0 )
1531  {
1532  TiXmlDocument* document = GetDocument();
1533  if ( document )
1535  return;
1536  }
1537  (*tag) += (char) c;
1538 
1539  if ( c == '>' )
1540  {
1541  // All is well.
1542  return;
1543  }
1544  }
1545 }
1546 #endif
1547 
1548 const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
1549 {
1550  p = SkipWhiteSpace( p, _encoding );
1551  // Find the beginning, find the end, and look for
1552  // the stuff in-between.
1553  TiXmlDocument* document = GetDocument();
1554  if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) )
1555  {
1556  if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
1557  return 0;
1558  }
1559  if ( data )
1560  {
1561  data->Stamp( p, _encoding );
1562  location = data->Cursor();
1563  }
1564  p += 5;
1565 
1566  version = "";
1567  encoding = "";
1568  standalone = "";
1569 
1570  while ( p && *p )
1571  {
1572  if ( *p == '>' )
1573  {
1574  ++p;
1575  return p;
1576  }
1577 
1578  p = SkipWhiteSpace( p, _encoding );
1579  if ( StringEqual( p, "version", true, _encoding ) )
1580  {
1581  TiXmlAttribute attrib;
1582  p = attrib.Parse( p, data, _encoding );
1583  version = attrib.Value();
1584  }
1585  else if ( StringEqual( p, "encoding", true, _encoding ) )
1586  {
1587  TiXmlAttribute attrib;
1588  p = attrib.Parse( p, data, _encoding );
1589  encoding = attrib.Value();
1590  }
1591  else if ( StringEqual( p, "standalone", true, _encoding ) )
1592  {
1593  TiXmlAttribute attrib;
1594  p = attrib.Parse( p, data, _encoding );
1595  standalone = attrib.Value();
1596  }
1597  else
1598  {
1599  // Read over whatever it is.
1600  while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
1601  ++p;
1602  }
1603  }
1604  return 0;
1605 }
1606 
1607 bool TiXmlText::Blank() const
1608 {
1609  for ( unsigned i=0; i<value.length(); i++ )
1610  if ( !IsWhiteSpace( value[i] ) )
1611  return false;
1612  return true;
1613 }
1614 
void ClearError()
Definition: tinyxml.h:1684
TIXML_STRING encoding
Definition: tinyxml.h:1485
TinyXML class. See http://www.grinninglizard.com/tinyxml.
Definition: tinyxml.h:1544
static bool StreamTo(std::istream *in, int character, TIXML_STRING *tag)
TiXmlNode * LinkEndChild(TiXmlNode *addThis)
Definition: tinyxml_inl.h:171
static const char * ReadName(const char *p, TIXML_STRING *name, TiXmlEncoding encoding)
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
const TIXML_STRING & NameTStr() const
Definition: tinyxml.h:921
static const char * GetChar(const char *p, char *_value, int *length, TiXmlEncoding encoding)
Definition: tinyxml.h:346
void SetCDATA(bool _cdata)
Turns on or off a CDATA representation of text.
Definition: tinyxml.h:1376
TIXML_STRING value
Definition: tinyxml.h:1003
static const char * SkipWhiteSpace(const char *, TiXmlEncoding encoding)
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
TiXmlNode * firstChild
Definition: tinyxml.h:857
TinyXML class. See http://www.grinninglizard.com/tinyxml.
Definition: tinyxml.h:1495
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
static bool IsWhiteSpace(char c)
Definition: tinyxml.h:311
static void ConvertUTF32ToUTF8(unsigned long input, char *output, int *length)
TIXML_STRING value
Definition: tinyxml.h:860
static int IsAlpha(unsigned char anyByte, TiXmlEncoding encoding)
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)=0
TIXML_STRING version
Definition: tinyxml.h:1485
TinyXML class. See http://www.grinninglizard.com/tinyxml.
Definition: tinyxml.h:102
static int IsAlphaNum(unsigned char anyByte, TiXmlEncoding encoding)
const char * ReadValue(const char *in, TiXmlParsingData *prevData, TiXmlEncoding encoding)
void Clear()
Definition: tinyxml.h:106
TIXML_STRING errorDesc
Definition: tinyxml.h:1729
const char * Name() const
Return the name of this attribute.
Definition: tinyxml.h:906
TinyXML class. See http://www.grinninglizard.com/tinyxml.
Definition: tinyxml.h:431
static const char * GetEntity(const char *in, char *value, int *length, TiXmlEncoding encoding)
const TiXmlCursor & Cursor()
TIXML_STRING standalone
Definition: tinyxml.h:1485
void Add(TiXmlAttribute *attribute)
Definition: tinyxml_inl.h:1538
bool useMicrosoftBOM
Definition: tinyxml.h:1732
TiXmlAttributeSet attributeSet
Definition: tinyxml.h:1275
const TiXmlEncoding TIXML_DEFAULT_ENCODING
Definition: tinyxml.h:183
virtual const char * Parse(const char *p, TiXmlParsingData *data=0, TiXmlEncoding encoding=TIXML_DEFAULT_ENCODING)
TinyXML class. See http://www.grinninglizard.com/tinyxml.
Definition: tinyxml.h:877
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
TIXML_STRING name
Definition: tinyxml.h:1003
TinyXML class. See http://www.grinninglizard.com/tinyxml.
Definition: tinyxml.h:1280
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
TinyXML class. See http://www.grinninglizard.com/tinyxml.
TinyXML class. See http://www.grinninglizard.com/tinyxml.
Definition: tinyxml.h:1421
bool Blank() const
static const int utf8ByteTable[256]
Definition: tinyxml.h:282
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
TinyXML class. See http://www.grinninglizard.com/tinyxml.
Definition: tinyxml.h:412
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
TiXmlEncoding
Definition: tinyxml.h:179
const unsigned char TIXML_UTF_LEAD_2
static const char * ReadText(const char *in, TIXML_STRING *text, bool ignoreWhiteSpace, const char *endTag, bool ignoreCase, TiXmlEncoding encoding)
static Entity entity[NUM_ENTITY]
Definition: tinyxml.h:421
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
void SetValue(const char *_value)
Set the value.
Definition: tinyxml.h:941
bool cdata
Definition: tinyxml.h:1405
void SetError(int err, const char *errorLocation, TiXmlParsingData *prevData, TiXmlEncoding encoding)
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)=0
static int ToLower(int v, TiXmlEncoding encoding)
Definition: tinyxml.h:396
friend class TiXmlElement
Definition: tinyxml.h:433
virtual const TiXmlElement * ToElement() const
Cast to a more defined type. Will return null if not of the requested type.
Definition: tinyxml.h:775
TinyXML class. See http://www.grinninglizard.com/tinyxml.
Definition: tinyxml.h:1336
const char * Encoding() const
Encoding. Will return an empty string if none was found.
Definition: tinyxml.h:1447
void Stamp(const char *now, TiXmlEncoding encoding)
static bool IsWhiteSpaceCondensed()
Return the current white space setting.
Definition: tinyxml.h:241
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
const unsigned char TIXML_UTF_LEAD_0
static bool StringEqual(const char *p, const char *endTag, bool ignoreCase, TiXmlEncoding encoding)
int TabSize() const
Definition: tinyxml.h:1677
const unsigned char TIXML_UTF_LEAD_1
void SetDocument(TiXmlDocument *doc)
Definition: tinyxml.h:994
virtual const TiXmlDeclaration * ToDeclaration() const
Cast to a more defined type. Will return null if not of the requested type.
Definition: tinyxml.h:787
TiXmlNode * parent
Definition: tinyxml.h:854
TiXmlNode * Identify(const char *start, TiXmlEncoding encoding)
static const char * errorString[TIXML_ERROR_STRING_COUNT]
Definition: tinyxml.h:385
static bool condenseWhiteSpace
Definition: tinyxml.h:422
const char * Value() const
Return the value of this attribute.
Definition: tinyxml.h:909
virtual void StreamIn(std::istream *in, TIXML_STRING *tag)
TiXmlCursor errorLocation
Definition: tinyxml.h:1731
const TiXmlDocument * GetDocument() const
Definition: tinyxml_inl.h:507
TiXmlCursor location
Definition: tinyxml.h:387
const TiXmlAttribute * Find(const char *_name) const
Definition: tinyxml_inl.h:1597
virtual const char * Parse(const char *p, TiXmlParsingData *data, TiXmlEncoding encoding)
TiXmlParsingData(const char *start, int _tabsize, int row, int col)
#define TIXML_STRING
Definition: tinyxml.h:56
static bool StreamWhiteSpace(std::istream *in, TIXML_STRING *tag)