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


inertial_sense_ros
Author(s):
autogenerated on Sun Feb 28 2021 03:17:58