2 www.sourceforge.net/projects/tinyxml
\r
3 Original code by Lee Thomason (www.grinninglizard.com)
\r
5 This software is provided 'as-is', without any express or implied
\r
6 warranty. In no event will the authors be held liable for any
\r
7 damages arising from the use of this software.
\r
9 Permission is granted to anyone to use this software for any
\r
10 purpose, including commercial applications, and to alter it and
\r
11 redistribute it freely, subject to the following restrictions:
\r
13 1. The origin of this software must not be misrepresented; you must
\r
14 not claim that you wrote the original software. If you use this
\r
15 software in a product, an acknowledgment in the product documentation
\r
16 would be appreciated but is not required.
\r
18 2. Altered source versions must be plainly marked as such, and
\r
19 must not be misrepresented as being the original software.
\r
21 3. This notice may not be removed or altered from any source
\r
27 #ifdef TIXML_USE_STL
\r
32 #include "tinyxml.h"
\r
34 FILE *TiXmlFOpen(const char *filename, const char *mode);
\r
36 bool TiXmlBase::condenseWhiteSpace = true;
\r
38 // Microsoft compiler security
\r
39 FILE *TiXmlFOpen(const char *filename, const char *mode)
\r
41 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
\r
43 errno_t err = fopen_s(&fp, filename, mode);
\r
48 return fopen(filename, mode);
\r
52 void TiXmlBase::EncodeString(const TIXML_STRING &str, TIXML_STRING *outString)
\r
56 while (i < (int)str.length())
\r
58 unsigned char c = (unsigned char)str[i];
\r
60 if (c == '&' && i < ((int)str.length() - 2) && str[i + 1] == '#' && str[i + 2] == 'x')
\r
62 // Hexadecimal character reference.
\r
63 // Pass through unchanged.
\r
64 // © -- copyright symbol, for example.
\r
66 // The -1 is a bug fix from Rob Laveaux. It keeps
\r
67 // an overflow from happening if there is no ';'.
\r
68 // There are actually 2 ways to exit this loop -
\r
69 // while fails (error case) and break (semicolon found).
\r
70 // However, there is no mechanism (currently) for
\r
71 // this function to return an error.
\r
72 while (i < (int)str.length() - 1)
\r
74 outString->append(str.c_str() + i, 1);
\r
82 outString->append(entity[0].str, entity[0].strLength);
\r
87 outString->append(entity[1].str, entity[1].strLength);
\r
92 outString->append(entity[2].str, entity[2].strLength);
\r
97 outString->append(entity[3].str, entity[3].strLength);
\r
100 else if (c == '\'')
\r
102 outString->append(entity[4].str, entity[4].strLength);
\r
107 // Easy pass at non-alpha/numeric/symbol
\r
108 // Below 32 is symbolic.
\r
111 #if defined(TIXML_SNPRINTF)
\r
112 TIXML_SNPRINTF(buf, sizeof(buf), "&#x%02X;", (unsigned)(c & 0xff));
\r
114 sprintf(buf, "&#x%02X;", (unsigned)(c & 0xff));
\r
117 //*ME: warning C4267: convert 'size_t' to 'int'
\r
118 //*ME: Int-Cast to make compiler happy ...
\r
119 outString->append(buf, (int)strlen(buf));
\r
124 //char realc = (char) c;
\r
125 //outString->append( &realc, 1 );
\r
126 *outString += (char)c; // somewhat more efficient function call.
\r
132 TiXmlNode::TiXmlNode(NodeType _type)
\r
143 TiXmlNode::~TiXmlNode()
\r
145 TiXmlNode *node = firstChild;
\r
146 TiXmlNode *temp = 0;
\r
156 void TiXmlNode::CopyTo(TiXmlNode *target) const
\r
158 target->SetValue(value.c_str());
\r
159 target->userData = userData;
\r
160 target->location = location;
\r
163 void TiXmlNode::Clear()
\r
165 TiXmlNode *node = firstChild;
\r
166 TiXmlNode *temp = 0;
\r
179 TiXmlNode *TiXmlNode::LinkEndChild(TiXmlNode *node)
\r
181 assert(node->parent == 0 || node->parent == this);
\r
182 assert(node->GetDocument() == 0 || node->GetDocument() == this->GetDocument());
\r
184 if (node->Type() == TiXmlNode::TINYXML_DOCUMENT)
\r
188 GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN);
\r
192 node->parent = this;
\r
194 node->prev = lastChild;
\r
198 lastChild->next = node;
\r
200 firstChild = node; // it was an empty list.
\r
206 TiXmlNode *TiXmlNode::InsertEndChild(const TiXmlNode &addThis)
\r
208 if (addThis.Type() == TiXmlNode::TINYXML_DOCUMENT)
\r
211 GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN);
\r
214 TiXmlNode *node = addThis.Clone();
\r
218 return LinkEndChild(node);
\r
221 TiXmlNode *TiXmlNode::InsertBeforeChild(TiXmlNode *beforeThis, const TiXmlNode &addThis)
\r
223 if (!beforeThis || beforeThis->parent != this)
\r
227 if (addThis.Type() == TiXmlNode::TINYXML_DOCUMENT)
\r
230 GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN);
\r
234 TiXmlNode *node = addThis.Clone();
\r
237 node->parent = this;
\r
239 node->next = beforeThis;
\r
240 node->prev = beforeThis->prev;
\r
241 if (beforeThis->prev)
\r
243 beforeThis->prev->next = node;
\r
247 assert(firstChild == beforeThis);
\r
250 beforeThis->prev = node;
\r
254 TiXmlNode *TiXmlNode::InsertAfterChild(TiXmlNode *afterThis, const TiXmlNode &addThis)
\r
256 if (!afterThis || afterThis->parent != this)
\r
260 if (addThis.Type() == TiXmlNode::TINYXML_DOCUMENT)
\r
263 GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN);
\r
267 TiXmlNode *node = addThis.Clone();
\r
270 node->parent = this;
\r
272 node->prev = afterThis;
\r
273 node->next = afterThis->next;
\r
274 if (afterThis->next)
\r
276 afterThis->next->prev = node;
\r
280 assert(lastChild == afterThis);
\r
283 afterThis->next = node;
\r
287 TiXmlNode *TiXmlNode::ReplaceChild(TiXmlNode *replaceThis, const TiXmlNode &withThis)
\r
292 if (replaceThis->parent != this)
\r
295 if (withThis.ToDocument())
\r
297 // A document can never be a child. Thanks to Noam.
\r
298 TiXmlDocument *document = GetDocument();
\r
300 document->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN);
\r
304 TiXmlNode *node = withThis.Clone();
\r
308 node->next = replaceThis->next;
\r
309 node->prev = replaceThis->prev;
\r
311 if (replaceThis->next)
\r
312 replaceThis->next->prev = node;
\r
316 if (replaceThis->prev)
\r
317 replaceThis->prev->next = node;
\r
321 delete replaceThis;
\r
322 node->parent = this;
\r
326 bool TiXmlNode::RemoveChild(TiXmlNode *removeThis)
\r
333 if (removeThis->parent != this)
\r
339 if (removeThis->next)
\r
340 removeThis->next->prev = removeThis->prev;
\r
342 lastChild = removeThis->prev;
\r
344 if (removeThis->prev)
\r
345 removeThis->prev->next = removeThis->next;
\r
347 firstChild = removeThis->next;
\r
353 const TiXmlNode *TiXmlNode::FirstChild(const char *_value) const
\r
355 const TiXmlNode *node;
\r
356 for (node = firstChild; node; node = node->next)
\r
358 if (strcmp(node->Value(), _value) == 0)
\r
364 const TiXmlNode *TiXmlNode::LastChild(const char *_value) const
\r
366 const TiXmlNode *node;
\r
367 for (node = lastChild; node; node = node->prev)
\r
369 if (strcmp(node->Value(), _value) == 0)
\r
375 const TiXmlNode *TiXmlNode::IterateChildren(const TiXmlNode *previous) const
\r
379 return FirstChild();
\r
383 assert(previous->parent == this);
\r
384 return previous->NextSibling();
\r
388 const TiXmlNode *TiXmlNode::IterateChildren(const char *val, const TiXmlNode *previous) const
\r
392 return FirstChild(val);
\r
396 assert(previous->parent == this);
\r
397 return previous->NextSibling(val);
\r
401 const TiXmlNode *TiXmlNode::NextSibling(const char *_value) const
\r
403 const TiXmlNode *node;
\r
404 for (node = next; node; node = node->next)
\r
406 if (strcmp(node->Value(), _value) == 0)
\r
412 const TiXmlNode *TiXmlNode::PreviousSibling(const char *_value) const
\r
414 const TiXmlNode *node;
\r
415 for (node = prev; node; node = node->prev)
\r
417 if (strcmp(node->Value(), _value) == 0)
\r
423 void TiXmlElement::RemoveAttribute(const char *name)
\r
425 #ifdef TIXML_USE_STL
\r
426 TIXML_STRING str(name);
\r
427 TiXmlAttribute *node = attributeSet.Find(str);
\r
429 TiXmlAttribute *node = attributeSet.Find(name);
\r
433 attributeSet.Remove(node);
\r
438 const TiXmlElement *TiXmlNode::FirstChildElement() const
\r
440 const TiXmlNode *node;
\r
442 for (node = FirstChild();
\r
444 node = node->NextSibling())
\r
446 if (node->ToElement())
\r
447 return node->ToElement();
\r
452 const TiXmlElement *TiXmlNode::FirstChildElement(const char *_value) const
\r
454 const TiXmlNode *node;
\r
456 for (node = FirstChild(_value);
\r
458 node = node->NextSibling(_value))
\r
460 if (node->ToElement())
\r
461 return node->ToElement();
\r
466 const TiXmlElement *TiXmlNode::NextSiblingElement() const
\r
468 const TiXmlNode *node;
\r
470 for (node = NextSibling();
\r
472 node = node->NextSibling())
\r
474 if (node->ToElement())
\r
475 return node->ToElement();
\r
480 const TiXmlElement *TiXmlNode::NextSiblingElement(const char *_value) const
\r
482 const TiXmlNode *node;
\r
484 for (node = NextSibling(_value);
\r
486 node = node->NextSibling(_value))
\r
488 if (node->ToElement())
\r
489 return node->ToElement();
\r
494 const TiXmlDocument *TiXmlNode::GetDocument() const
\r
496 const TiXmlNode *node;
\r
498 for (node = this; node; node = node->parent)
\r
500 if (node->ToDocument())
\r
501 return node->ToDocument();
\r
506 TiXmlElement::TiXmlElement(const char *_value)
\r
507 : TiXmlNode(TiXmlNode::TINYXML_ELEMENT)
\r
509 firstChild = lastChild = 0;
\r
513 #ifdef TIXML_USE_STL
\r
514 TiXmlElement::TiXmlElement(const std::string &_value)
\r
515 : TiXmlNode(TiXmlNode::TINYXML_ELEMENT)
\r
517 firstChild = lastChild = 0;
\r
522 TiXmlElement::TiXmlElement(const TiXmlElement ©)
\r
523 : TiXmlNode(TiXmlNode::TINYXML_ELEMENT)
\r
525 firstChild = lastChild = 0;
\r
529 TiXmlElement &TiXmlElement::operator=(const TiXmlElement &base)
\r
536 TiXmlElement::~TiXmlElement()
\r
541 void TiXmlElement::ClearThis()
\r
544 while (attributeSet.First())
\r
546 TiXmlAttribute *node = attributeSet.First();
\r
547 attributeSet.Remove(node);
\r
552 const char *TiXmlElement::Attribute(const char *name) const
\r
554 const TiXmlAttribute *node = attributeSet.Find(name);
\r
556 return node->Value();
\r
560 #ifdef TIXML_USE_STL
\r
561 const std::string *TiXmlElement::Attribute(const std::string &name) const
\r
563 const TiXmlAttribute *attrib = attributeSet.Find(name);
\r
565 return &attrib->ValueStr();
\r
570 const char *TiXmlElement::Attribute(const char *name, int *i) const
\r
572 const TiXmlAttribute *attrib = attributeSet.Find(name);
\r
573 const char *result = 0;
\r
577 result = attrib->Value();
\r
580 attrib->QueryIntValue(i);
\r
586 #ifdef TIXML_USE_STL
\r
587 const std::string *TiXmlElement::Attribute(const std::string &name, int *i) const
\r
589 const TiXmlAttribute *attrib = attributeSet.Find(name);
\r
590 const std::string *result = 0;
\r
594 result = &attrib->ValueStr();
\r
597 attrib->QueryIntValue(i);
\r
604 const char *TiXmlElement::Attribute(const char *name, double *d) const
\r
606 const TiXmlAttribute *attrib = attributeSet.Find(name);
\r
607 const char *result = 0;
\r
611 result = attrib->Value();
\r
614 attrib->QueryDoubleValue(d);
\r
620 #ifdef TIXML_USE_STL
\r
621 const std::string *TiXmlElement::Attribute(const std::string &name, double *d) const
\r
623 const TiXmlAttribute *attrib = attributeSet.Find(name);
\r
624 const std::string *result = 0;
\r
628 result = &attrib->ValueStr();
\r
631 attrib->QueryDoubleValue(d);
\r
638 int TiXmlElement::QueryIntAttribute(const char *name, int *ival) const
\r
640 const TiXmlAttribute *attrib = attributeSet.Find(name);
\r
642 return TIXML_NO_ATTRIBUTE;
\r
643 return attrib->QueryIntValue(ival);
\r
646 int TiXmlElement::QueryUnsignedAttribute(const char *name, unsigned *value) const
\r
648 const TiXmlAttribute *node = attributeSet.Find(name);
\r
650 return TIXML_NO_ATTRIBUTE;
\r
653 int result = node->QueryIntValue(&ival);
\r
654 *value = (unsigned)ival;
\r
658 int TiXmlElement::QueryBoolAttribute(const char *name, bool *bval) const
\r
660 const TiXmlAttribute *node = attributeSet.Find(name);
\r
662 return TIXML_NO_ATTRIBUTE;
\r
664 int result = TIXML_WRONG_TYPE;
\r
665 if (StringEqual(node->Value(), "true", true, TIXML_ENCODING_UNKNOWN) || StringEqual(node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN) || StringEqual(node->Value(), "1", true, TIXML_ENCODING_UNKNOWN))
\r
668 result = TIXML_SUCCESS;
\r
670 else if (StringEqual(node->Value(), "false", true, TIXML_ENCODING_UNKNOWN) || StringEqual(node->Value(), "no", true, TIXML_ENCODING_UNKNOWN) || StringEqual(node->Value(), "0", true, TIXML_ENCODING_UNKNOWN))
\r
673 result = TIXML_SUCCESS;
\r
678 #ifdef TIXML_USE_STL
\r
679 int TiXmlElement::QueryIntAttribute(const std::string &name, int *ival) const
\r
681 const TiXmlAttribute *attrib = attributeSet.Find(name);
\r
683 return TIXML_NO_ATTRIBUTE;
\r
684 return attrib->QueryIntValue(ival);
\r
688 int TiXmlElement::QueryDoubleAttribute(const char *name, double *dval) const
\r
690 const TiXmlAttribute *attrib = attributeSet.Find(name);
\r
692 return TIXML_NO_ATTRIBUTE;
\r
693 return attrib->QueryDoubleValue(dval);
\r
696 #ifdef TIXML_USE_STL
\r
697 int TiXmlElement::QueryDoubleAttribute(const std::string &name, double *dval) const
\r
699 const TiXmlAttribute *attrib = attributeSet.Find(name);
\r
701 return TIXML_NO_ATTRIBUTE;
\r
702 return attrib->QueryDoubleValue(dval);
\r
706 void TiXmlElement::SetAttribute(const char *name, int val)
\r
708 TiXmlAttribute *attrib = attributeSet.FindOrCreate(name);
\r
711 attrib->SetIntValue(val);
\r
715 #ifdef TIXML_USE_STL
\r
716 void TiXmlElement::SetAttribute(const std::string &name, int val)
\r
718 TiXmlAttribute *attrib = attributeSet.FindOrCreate(name);
\r
721 attrib->SetIntValue(val);
\r
726 void TiXmlElement::SetDoubleAttribute(const char *name, double val)
\r
728 TiXmlAttribute *attrib = attributeSet.FindOrCreate(name);
\r
731 attrib->SetDoubleValue(val);
\r
735 #ifdef TIXML_USE_STL
\r
736 void TiXmlElement::SetDoubleAttribute(const std::string &name, double val)
\r
738 TiXmlAttribute *attrib = attributeSet.FindOrCreate(name);
\r
741 attrib->SetDoubleValue(val);
\r
746 void TiXmlElement::SetAttribute(const char *cname, const char *cvalue)
\r
748 TiXmlAttribute *attrib = attributeSet.FindOrCreate(cname);
\r
751 attrib->SetValue(cvalue);
\r
755 #ifdef TIXML_USE_STL
\r
756 void TiXmlElement::SetAttribute(const std::string &_name, const std::string &_value)
\r
758 TiXmlAttribute *attrib = attributeSet.FindOrCreate(_name);
\r
761 attrib->SetValue(_value);
\r
766 void TiXmlElement::Print(FILE *cfile, int depth) const
\r
770 for (i = 0; i < depth; i++)
\r
772 fprintf(cfile, " ");
\r
775 fprintf(cfile, "<%s", value.c_str());
\r
777 const TiXmlAttribute *attrib;
\r
778 for (attrib = attributeSet.First(); attrib; attrib = attrib->Next())
\r
780 fprintf(cfile, " ");
\r
781 attrib->Print(cfile, depth);
\r
784 // There are 3 different formatting approaches:
\r
785 // 1) An element without children is printed as a <foo /> node
\r
786 // 2) An element with only a text child is printed as <foo> text </foo>
\r
787 // 3) An element with children is printed on multiple lines.
\r
791 fprintf(cfile, " />");
\r
793 else if (firstChild == lastChild && firstChild->ToText())
\r
795 fprintf(cfile, ">");
\r
796 firstChild->Print(cfile, depth + 1);
\r
797 fprintf(cfile, "</%s>", value.c_str());
\r
801 fprintf(cfile, ">");
\r
803 for (node = firstChild; node; node = node->NextSibling())
\r
805 if (!node->ToText())
\r
807 fprintf(cfile, "\n");
\r
809 node->Print(cfile, depth + 1);
\r
811 fprintf(cfile, "\n");
\r
812 for (i = 0; i < depth; ++i)
\r
814 fprintf(cfile, " ");
\r
816 fprintf(cfile, "</%s>", value.c_str());
\r
820 void TiXmlElement::CopyTo(TiXmlElement *target) const
\r
823 TiXmlNode::CopyTo(target);
\r
826 // Clone the attributes, then clone the children.
\r
827 const TiXmlAttribute *attribute = 0;
\r
828 for (attribute = attributeSet.First();
\r
830 attribute = attribute->Next())
\r
832 target->SetAttribute(attribute->Name(), attribute->Value());
\r
835 TiXmlNode *node = 0;
\r
836 for (node = firstChild; node; node = node->NextSibling())
\r
838 target->LinkEndChild(node->Clone());
\r
842 bool TiXmlElement::Accept(TiXmlVisitor *visitor) const
\r
844 if (visitor->VisitEnter(*this, attributeSet.First()))
\r
846 for (const TiXmlNode *node = FirstChild(); node; node = node->NextSibling())
\r
848 if (!node->Accept(visitor))
\r
852 return visitor->VisitExit(*this);
\r
855 TiXmlNode *TiXmlElement::Clone() const
\r
857 TiXmlElement *clone = new TiXmlElement(Value());
\r
865 const char *TiXmlElement::GetText() const
\r
867 const TiXmlNode *child = this->FirstChild();
\r
870 const TiXmlText *childText = child->ToText();
\r
873 return childText->Value();
\r
879 TiXmlDocument::TiXmlDocument()
\r
880 : TiXmlNode(TiXmlNode::TINYXML_DOCUMENT)
\r
883 useMicrosoftBOM = false;
\r
887 TiXmlDocument::TiXmlDocument(const char *documentName)
\r
888 : TiXmlNode(TiXmlNode::TINYXML_DOCUMENT)
\r
891 useMicrosoftBOM = false;
\r
892 value = documentName;
\r
896 #ifdef TIXML_USE_STL
\r
897 TiXmlDocument::TiXmlDocument(const std::string &documentName)
\r
898 : TiXmlNode(TiXmlNode::TINYXML_DOCUMENT)
\r
901 useMicrosoftBOM = false;
\r
902 value = documentName;
\r
907 TiXmlDocument::TiXmlDocument(const TiXmlDocument ©)
\r
908 : TiXmlNode(TiXmlNode::TINYXML_DOCUMENT)
\r
913 TiXmlDocument &TiXmlDocument::operator=(const TiXmlDocument ©)
\r
920 bool TiXmlDocument::LoadFile(TiXmlEncoding encoding)
\r
922 return LoadFile(Value(), encoding);
\r
925 bool TiXmlDocument::SaveFile() const
\r
927 return SaveFile(Value());
\r
930 bool TiXmlDocument::LoadFile(const char *_filename, TiXmlEncoding encoding)
\r
932 TIXML_STRING filename(_filename);
\r
935 // reading in binary mode so that tinyxml can normalize the EOL
\r
936 FILE *file = TiXmlFOpen(value.c_str(), "rb");
\r
940 bool result = LoadFile(file, encoding);
\r
946 SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN);
\r
951 bool TiXmlDocument::LoadFile(FILE *file, TiXmlEncoding encoding)
\r
955 SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN);
\r
959 // Delete the existing data:
\r
963 // Get the file size, so we can pre-allocate the string. HUGE speed impact.
\r
965 fseek(file, 0, SEEK_END);
\r
966 length = ftell(file);
\r
967 fseek(file, 0, SEEK_SET);
\r
969 // Strange case, but good to handle up front.
\r
972 SetError(TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN);
\r
976 // Subtle bug here. TinyXml did use fgets. But from the XML spec:
\r
977 // 2.11 End-of-Line Handling
\r
980 // ...the XML processor MUST behave as if it normalized all line breaks in external
\r
981 // parsed entities (including the document entity) on input, before parsing, by translating
\r
982 // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
\r
983 // a single #xA character.
\r
986 // It is not clear fgets does that, and certainly isn't clear it works cross platform.
\r
987 // Generally, you expect fgets to translate from the convention of the OS to the c/unix
\r
988 // convention, and not work generally.
\r
991 while( fgets( buf, sizeof(buf), file ) )
\r
997 char *buf = new char[length + 1];
\r
1000 if (fread(buf, length, 1, file) != 1)
\r
1003 SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN);
\r
1007 // Process the buffer in place to normalize new lines. (See comment above.)
\r
1008 // Copies from the 'p' to 'q' pointer, where p can advance faster if
\r
1009 // a newline-carriage return is hit.
\r
1012 // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or
\r
1013 // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)...
\r
1014 // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others
\r
1015 // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS
\r
1016 // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9
\r
1018 const char *p = buf; // the read head
\r
1019 char *q = buf; // the write head
\r
1020 const char CR = 0x0d;
\r
1021 const char LF = 0x0a;
\r
1026 assert(p < (buf + length));
\r
1027 assert(q <= (buf + length));
\r
1034 if (*p == LF) // check for CR+LF (and skip LF)
\r
1044 assert(q <= (buf + length));
\r
1047 Parse(buf, 0, encoding);
\r
1053 bool TiXmlDocument::SaveFile(const char *filename) const
\r
1055 // The old c stuff lives on...
\r
1056 FILE *fp = TiXmlFOpen(filename, "w");
\r
1059 bool result = SaveFile(fp);
\r
1066 bool TiXmlDocument::SaveFile(FILE *fp) const
\r
1068 if (useMicrosoftBOM)
\r
1070 const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
\r
1071 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
\r
1072 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
\r
1074 fputc(TIXML_UTF_LEAD_0, fp);
\r
1075 fputc(TIXML_UTF_LEAD_1, fp);
\r
1076 fputc(TIXML_UTF_LEAD_2, fp);
\r
1079 return (ferror(fp) == 0);
\r
1082 void TiXmlDocument::CopyTo(TiXmlDocument *target) const
\r
1084 TiXmlNode::CopyTo(target);
\r
1086 target->error = error;
\r
1087 target->errorId = errorId;
\r
1088 target->errorDesc = errorDesc;
\r
1089 target->tabsize = tabsize;
\r
1090 target->errorLocation = errorLocation;
\r
1091 target->useMicrosoftBOM = useMicrosoftBOM;
\r
1093 TiXmlNode *node = 0;
\r
1094 for (node = firstChild; node; node = node->NextSibling())
\r
1096 target->LinkEndChild(node->Clone());
\r
1100 TiXmlNode *TiXmlDocument::Clone() const
\r
1102 TiXmlDocument *clone = new TiXmlDocument();
\r
1110 void TiXmlDocument::Print(FILE *cfile, int depth) const
\r
1113 for (const TiXmlNode *node = FirstChild(); node; node = node->NextSibling())
\r
1115 node->Print(cfile, depth);
\r
1116 fprintf(cfile, "\n");
\r
1120 bool TiXmlDocument::Accept(TiXmlVisitor *visitor) const
\r
1122 if (visitor->VisitEnter(*this))
\r
1124 for (const TiXmlNode *node = FirstChild(); node; node = node->NextSibling())
\r
1126 if (!node->Accept(visitor))
\r
1130 return visitor->VisitExit(*this);
\r
1133 const TiXmlAttribute *TiXmlAttribute::Next() const
\r
1135 // We are using knowledge of the sentinel. The sentinel
\r
1136 // have a value or name.
\r
1137 if (next->value.empty() && next->name.empty())
\r
1143 TiXmlAttribute* TiXmlAttribute::Next()
\r
1145 // We are using knowledge of the sentinel. The sentinel
\r
1146 // have a value or name.
\r
1147 if ( next->value.empty() && next->name.empty() )
\r
1153 const TiXmlAttribute *TiXmlAttribute::Previous() const
\r
1155 // We are using knowledge of the sentinel. The sentinel
\r
1156 // have a value or name.
\r
1157 if (prev->value.empty() && prev->name.empty())
\r
1163 TiXmlAttribute* TiXmlAttribute::Previous()
\r
1165 // We are using knowledge of the sentinel. The sentinel
\r
1166 // have a value or name.
\r
1167 if ( prev->value.empty() && prev->name.empty() )
\r
1173 void TiXmlAttribute::Print(FILE *cfile, int /*depth*/, TIXML_STRING *str) const
\r
1175 TIXML_STRING n, v;
\r
1177 EncodeString(name, &n);
\r
1178 EncodeString(value, &v);
\r
1180 if (value.find('\"') == TIXML_STRING::npos)
\r
1184 fprintf(cfile, "%s=\"%s\"", n.c_str(), v.c_str());
\r
1198 fprintf(cfile, "%s='%s'", n.c_str(), v.c_str());
\r
1210 int TiXmlAttribute::QueryIntValue(int *ival) const
\r
1212 if (TIXML_SSCANF(value.c_str(), "%d", ival) == 1)
\r
1213 return TIXML_SUCCESS;
\r
1214 return TIXML_WRONG_TYPE;
\r
1217 int TiXmlAttribute::QueryDoubleValue(double *dval) const
\r
1219 if (TIXML_SSCANF(value.c_str(), "%lf", dval) == 1)
\r
1220 return TIXML_SUCCESS;
\r
1221 return TIXML_WRONG_TYPE;
\r
1224 void TiXmlAttribute::SetIntValue(int _value)
\r
1227 #if defined(TIXML_SNPRINTF)
\r
1228 TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
\r
1230 sprintf(buf, "%d", _value);
\r
1235 void TiXmlAttribute::SetDoubleValue(double _value)
\r
1238 #if defined(TIXML_SNPRINTF)
\r
1239 TIXML_SNPRINTF(buf, sizeof(buf), "%g", _value);
\r
1241 sprintf(buf, "%g", _value);
\r
1246 int TiXmlAttribute::IntValue() const
\r
1248 return atoi(value.c_str());
\r
1251 double TiXmlAttribute::DoubleValue() const
\r
1253 return atof(value.c_str());
\r
1256 TiXmlComment::TiXmlComment(const TiXmlComment ©)
\r
1257 : TiXmlNode(TiXmlNode::TINYXML_COMMENT)
\r
1259 copy.CopyTo(this);
\r
1262 TiXmlComment &TiXmlComment::operator=(const TiXmlComment &base)
\r
1265 base.CopyTo(this);
\r
1269 void TiXmlComment::Print(FILE *cfile, int depth) const
\r
1272 for (int i = 0; i < depth; i++)
\r
1274 fprintf(cfile, " ");
\r
1276 fprintf(cfile, "<!--%s-->", value.c_str());
\r
1279 void TiXmlComment::CopyTo(TiXmlComment *target) const
\r
1281 TiXmlNode::CopyTo(target);
\r
1284 bool TiXmlComment::Accept(TiXmlVisitor *visitor) const
\r
1286 return visitor->Visit(*this);
\r
1289 TiXmlNode *TiXmlComment::Clone() const
\r
1291 TiXmlComment *clone = new TiXmlComment();
\r
1300 void TiXmlText::Print(FILE *cfile, int depth) const
\r
1306 fprintf(cfile, "\n");
\r
1307 for (i = 0; i < depth; i++)
\r
1309 fprintf(cfile, " ");
\r
1311 fprintf(cfile, "<![CDATA[%s]]>\n", value.c_str()); // unformatted output
\r
1315 TIXML_STRING buffer;
\r
1316 EncodeString(value, &buffer);
\r
1317 fprintf(cfile, "%s", buffer.c_str());
\r
1321 void TiXmlText::CopyTo(TiXmlText *target) const
\r
1323 TiXmlNode::CopyTo(target);
\r
1324 target->cdata = cdata;
\r
1327 bool TiXmlText::Accept(TiXmlVisitor *visitor) const
\r
1329 return visitor->Visit(*this);
\r
1332 TiXmlNode *TiXmlText::Clone() const
\r
1334 TiXmlText *clone = 0;
\r
1335 clone = new TiXmlText("");
\r
1344 TiXmlDeclaration::TiXmlDeclaration(const char *_version,
\r
1345 const char *_encoding,
\r
1346 const char *_standalone)
\r
1347 : TiXmlNode(TiXmlNode::TINYXML_DECLARATION)
\r
1349 version = _version;
\r
1350 encoding = _encoding;
\r
1351 standalone = _standalone;
\r
1354 #ifdef TIXML_USE_STL
\r
1355 TiXmlDeclaration::TiXmlDeclaration(const std::string &_version,
\r
1356 const std::string &_encoding,
\r
1357 const std::string &_standalone)
\r
1358 : TiXmlNode(TiXmlNode::TINYXML_DECLARATION)
\r
1360 version = _version;
\r
1361 encoding = _encoding;
\r
1362 standalone = _standalone;
\r
1366 TiXmlDeclaration::TiXmlDeclaration(const TiXmlDeclaration ©)
\r
1367 : TiXmlNode(TiXmlNode::TINYXML_DECLARATION)
\r
1369 copy.CopyTo(this);
\r
1372 TiXmlDeclaration &TiXmlDeclaration::operator=(const TiXmlDeclaration ©)
\r
1375 copy.CopyTo(this);
\r
1379 void TiXmlDeclaration::Print(FILE *cfile, int /*depth*/, TIXML_STRING *str) const
\r
1382 fprintf(cfile, "<?xml ");
\r
1384 (*str) += "<?xml ";
\r
1386 if (!version.empty())
\r
1389 fprintf(cfile, "version=\"%s\" ", version.c_str());
\r
1392 (*str) += "version=\"";
\r
1393 (*str) += version;
\r
1397 if (!encoding.empty())
\r
1400 fprintf(cfile, "encoding=\"%s\" ", encoding.c_str());
\r
1403 (*str) += "encoding=\"";
\r
1404 (*str) += encoding;
\r
1408 if (!standalone.empty())
\r
1411 fprintf(cfile, "standalone=\"%s\" ", standalone.c_str());
\r
1414 (*str) += "standalone=\"";
\r
1415 (*str) += standalone;
\r
1420 fprintf(cfile, "?>");
\r
1425 void TiXmlDeclaration::CopyTo(TiXmlDeclaration *target) const
\r
1427 TiXmlNode::CopyTo(target);
\r
1429 target->version = version;
\r
1430 target->encoding = encoding;
\r
1431 target->standalone = standalone;
\r
1434 bool TiXmlDeclaration::Accept(TiXmlVisitor *visitor) const
\r
1436 return visitor->Visit(*this);
\r
1439 TiXmlNode *TiXmlDeclaration::Clone() const
\r
1441 TiXmlDeclaration *clone = new TiXmlDeclaration();
\r
1450 void TiXmlUnknown::Print(FILE *cfile, int depth) const
\r
1452 for (int i = 0; i < depth; i++)
\r
1453 fprintf(cfile, " ");
\r
1454 fprintf(cfile, "<%s>", value.c_str());
\r
1457 void TiXmlUnknown::CopyTo(TiXmlUnknown *target) const
\r
1459 TiXmlNode::CopyTo(target);
\r
1462 bool TiXmlUnknown::Accept(TiXmlVisitor *visitor) const
\r
1464 return visitor->Visit(*this);
\r
1467 TiXmlNode *TiXmlUnknown::Clone() const
\r
1469 TiXmlUnknown *clone = new TiXmlUnknown();
\r
1478 TiXmlAttributeSet::TiXmlAttributeSet()
\r
1480 sentinel.next = &sentinel;
\r
1481 sentinel.prev = &sentinel;
\r
1484 TiXmlAttributeSet::~TiXmlAttributeSet()
\r
1486 assert(sentinel.next == &sentinel);
\r
1487 assert(sentinel.prev == &sentinel);
\r
1490 void TiXmlAttributeSet::Add(TiXmlAttribute *addMe)
\r
1492 #ifdef TIXML_USE_STL
\r
1493 assert(!Find(TIXML_STRING(addMe->Name()))); // Shouldn't be multiply adding to the set.
\r
1495 assert(!Find(addMe->Name())); // Shouldn't be multiply adding to the set.
\r
1498 addMe->next = &sentinel;
\r
1499 addMe->prev = sentinel.prev;
\r
1501 sentinel.prev->next = addMe;
\r
1502 sentinel.prev = addMe;
\r
1505 void TiXmlAttributeSet::Remove(TiXmlAttribute *removeMe)
\r
1507 TiXmlAttribute *node;
\r
1509 for (node = sentinel.next; node != &sentinel; node = node->next)
\r
1511 if (node == removeMe)
\r
1513 node->prev->next = node->next;
\r
1514 node->next->prev = node->prev;
\r
1520 assert(0); // we tried to remove a non-linked attribute.
\r
1523 #ifdef TIXML_USE_STL
\r
1524 TiXmlAttribute *TiXmlAttributeSet::Find(const std::string &name) const
\r
1526 for (TiXmlAttribute *node = sentinel.next; node != &sentinel; node = node->next)
\r
1528 if (node->name == name)
\r
1534 TiXmlAttribute *TiXmlAttributeSet::FindOrCreate(const std::string &_name)
\r
1536 TiXmlAttribute *attrib = Find(_name);
\r
1539 attrib = new TiXmlAttribute();
\r
1541 attrib->SetName(_name);
\r
1547 TiXmlAttribute *TiXmlAttributeSet::Find(const char *name) const
\r
1549 for (TiXmlAttribute *node = sentinel.next; node != &sentinel; node = node->next)
\r
1551 if (strcmp(node->name.c_str(), name) == 0)
\r
1557 TiXmlAttribute *TiXmlAttributeSet::FindOrCreate(const char *_name)
\r
1559 TiXmlAttribute *attrib = Find(_name);
\r
1562 attrib = new TiXmlAttribute();
\r
1564 attrib->SetName(_name);
\r
1569 #ifdef TIXML_USE_STL
\r
1570 std::istream &operator>>(std::istream &in, TiXmlNode &base)
\r
1573 tag.reserve(8 * 1000);
\r
1574 base.StreamIn(&in, &tag);
\r
1576 base.Parse(tag.c_str(), 0, TIXML_DEFAULT_ENCODING);
\r
1581 #ifdef TIXML_USE_STL
\r
1582 std::ostream &operator<<(std::ostream &out, const TiXmlNode &base)
\r
1584 TiXmlPrinter printer;
\r
1585 printer.SetStreamPrinting();
\r
1586 base.Accept(&printer);
\r
1587 out << printer.Str();
\r
1592 std::string &operator<<(std::string &out, const TiXmlNode &base)
\r
1594 TiXmlPrinter printer;
\r
1595 printer.SetStreamPrinting();
\r
1596 base.Accept(&printer);
\r
1597 out.append(printer.Str());
\r
1603 TiXmlHandle TiXmlHandle::FirstChild() const
\r
1607 TiXmlNode *child = node->FirstChild();
\r
1609 return TiXmlHandle(child);
\r
1611 return TiXmlHandle(0);
\r
1614 TiXmlHandle TiXmlHandle::FirstChild(const char *value) const
\r
1618 TiXmlNode *child = node->FirstChild(value);
\r
1620 return TiXmlHandle(child);
\r
1622 return TiXmlHandle(0);
\r
1625 TiXmlHandle TiXmlHandle::FirstChildElement() const
\r
1629 TiXmlElement *child = node->FirstChildElement();
\r
1631 return TiXmlHandle(child);
\r
1633 return TiXmlHandle(0);
\r
1636 TiXmlHandle TiXmlHandle::FirstChildElement(const char *value) const
\r
1640 TiXmlElement *child = node->FirstChildElement(value);
\r
1642 return TiXmlHandle(child);
\r
1644 return TiXmlHandle(0);
\r
1647 TiXmlHandle TiXmlHandle::Child(int count) const
\r
1652 TiXmlNode *child = node->FirstChild();
\r
1654 child && i < count;
\r
1655 child = child->NextSibling(), ++i)
\r
1660 return TiXmlHandle(child);
\r
1662 return TiXmlHandle(0);
\r
1665 TiXmlHandle TiXmlHandle::Child(const char *value, int count) const
\r
1670 TiXmlNode *child = node->FirstChild(value);
\r
1672 child && i < count;
\r
1673 child = child->NextSibling(value), ++i)
\r
1678 return TiXmlHandle(child);
\r
1680 return TiXmlHandle(0);
\r
1683 TiXmlHandle TiXmlHandle::ChildElement(int count) const
\r
1688 TiXmlElement *child = node->FirstChildElement();
\r
1690 child && i < count;
\r
1691 child = child->NextSiblingElement(), ++i)
\r
1696 return TiXmlHandle(child);
\r
1698 return TiXmlHandle(0);
\r
1701 TiXmlHandle TiXmlHandle::ChildElement(const char *value, int count) const
\r
1706 TiXmlElement *child = node->FirstChildElement(value);
\r
1708 child && i < count;
\r
1709 child = child->NextSiblingElement(value), ++i)
\r
1714 return TiXmlHandle(child);
\r
1716 return TiXmlHandle(0);
\r
1719 bool TiXmlPrinter::VisitEnter(const TiXmlDocument &)
\r
1724 bool TiXmlPrinter::VisitExit(const TiXmlDocument &)
\r
1729 bool TiXmlPrinter::VisitEnter(const TiXmlElement &element, const TiXmlAttribute *firstAttribute)
\r
1733 buffer += element.Value();
\r
1735 for (const TiXmlAttribute *attrib = firstAttribute; attrib; attrib = attrib->Next())
\r
1738 attrib->Print(0, 0, &buffer);
\r
1741 if (!element.FirstChild())
\r
1749 if (element.FirstChild()->ToText() && element.LastChild() == element.FirstChild() && element.FirstChild()->ToText()->CDATA() == false)
\r
1751 simpleTextPrint = true;
\r
1752 // no DoLineBreak()!
\r
1763 bool TiXmlPrinter::VisitExit(const TiXmlElement &element)
\r
1766 if (!element.FirstChild())
\r
1772 if (simpleTextPrint)
\r
1774 simpleTextPrint = false;
\r
1781 buffer += element.Value();
\r
1788 bool TiXmlPrinter::Visit(const TiXmlText &text)
\r
1793 buffer += "<![CDATA[";
\r
1794 buffer += text.Value();
\r
1798 else if (simpleTextPrint)
\r
1801 TiXmlBase::EncodeString(text.ValueTStr(), &str);
\r
1808 TiXmlBase::EncodeString(text.ValueTStr(), &str);
\r
1815 bool TiXmlPrinter::Visit(const TiXmlDeclaration &declaration)
\r
1818 declaration.Print(0, 0, &buffer);
\r
1823 bool TiXmlPrinter::Visit(const TiXmlComment &comment)
\r
1827 buffer += comment.Value();
\r
1833 bool TiXmlPrinter::Visit(const TiXmlUnknown &unknown)
\r
1837 buffer += unknown.Value();
\r