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