diff options
Diffstat (limited to 'plugins/UserInfoEx/src/ex_import/tinyxml.cpp')
-rw-r--r-- | plugins/UserInfoEx/src/ex_import/tinyxml.cpp | 1978 |
1 files changed, 1978 insertions, 0 deletions
diff --git a/plugins/UserInfoEx/src/ex_import/tinyxml.cpp b/plugins/UserInfoEx/src/ex_import/tinyxml.cpp new file mode 100644 index 0000000000..2eba13a7ea --- /dev/null +++ b/plugins/UserInfoEx/src/ex_import/tinyxml.cpp @@ -0,0 +1,1978 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier)copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. + +=============================================================================== + +UserinfoEx plugin for Miranda IM + +Copyright: + 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol + +File name : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/ex_import/tinyxml.cpp $ +Revision : $Revision: 196 $ +Last change on : $Date: 2010-09-21 03:24:30 +0400 (Вт, 21 сен 2010) $ +Last change by : $Author: ing.u.horn $ + +=============================================================================== + */ +#include "tinyxml.h" + +#include <ctype.h> + +#ifdef TIXML_USE_STL +#include <sstream> +#include <iostream> +#endif + +#ifdef USE_MMGR +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "mmgr.h" +#endif + + +bool TiXmlBase::condenseWhiteSpace = true; + +void TiXmlBase::StreamDepth(TIXML_OSTREAM* stream, int depth) const +{ + for (int i = 0; i < depth; ++i) + { + (*stream) << " "; + } +} + +void TiXmlBase::PutString(const TIXML_STRING& str, TIXML_OSTREAM* stream) +{ + TIXML_STRING buffer; + PutString(str, &buffer); + (*stream) << buffer; +} + +void TiXmlBase::PutString(const TIXML_STRING& str, TIXML_STRING* outString) +{ + int i=0; + + while (i<(int)str.length()) + { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ((int)str.length() - 2) + && str[i+1] == '#' + && str[i+2] == 'x') + { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while (i<(int)str.length()-1) + { + outString->append(str.c_str() + i, 1); + ++i; + if (str[i] == ';') + break; + } + } + else if (c == '&') + { + outString->append(entity[0].str, entity[0].strLength); + ++i; + } + else if (c == '<') + { + outString->append(entity[1].str, entity[1].strLength); + ++i; + } + else if (c == '>') + { + outString->append(entity[2].str, entity[2].strLength); + ++i; + } + else if (c == '\"') + { + outString->append(entity[3].str, entity[3].strLength); + ++i; + } + else if (c == '\'') + { + outString->append(entity[4].str, entity[4].strLength); + ++i; + } + else if (c < 32) + { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "&#x%02X;", (unsigned) (c & 0xff)); + #else + sprintf(buf, "&#x%02X;", (unsigned) (c & 0xff)); + #endif + + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append(buf, (int)strlen(buf)); + ++i; + } + else + { + //char realc = (char) c; + //outString->append(&realc, 1); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } +} + + +// <-- Strange class for a bug fix. Search for STL_STRING_BUG +TiXmlBase::StringToBuffer::StringToBuffer(const TIXML_STRING& str) +{ + buffer = new char[ str.length()+1 ]; + if (buffer) + { + strcpy(buffer, str.c_str()); + } +} + + +TiXmlBase::StringToBuffer::~StringToBuffer() +{ + delete [] buffer; +} +// End strange bug fix. --> + + +TiXmlNode::TiXmlNode(NodeType _type) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while (node) + { + temp = node; + node = node->next; + + delete temp; + } +} + + +void TiXmlNode::CopyTo(TiXmlNode* target) const +{ + target->SetValue (value.c_str()); + target->userData = userData; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while (node) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild(TiXmlNode* node) +{ + assert(node->parent == 0 || node->parent == this); + assert(node->GetDocument() == 0 || node->GetDocument() == this->GetDocument()); + + if (node->Type() == TiXmlNode::DOCUMENT) + { + delete node; + if (GetDocument()) GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN); + return 0; + } + + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if (lastChild) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + lastChild = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertEndChild(const TiXmlNode& addThis) +{ + if (addThis.Type() == TiXmlNode::DOCUMENT) + { + if (GetDocument()) GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN); + return 0; + } + TiXmlNode* node = addThis.Clone(); + if (!node) + return 0; + + return LinkEndChild(node); +} + + +TiXmlNode* TiXmlNode::InsertBeforeChild(TiXmlNode* beforeThis, const TiXmlNode& addThis) +{ + if (!beforeThis || beforeThis->parent != this) { + return 0; + } + if (addThis.Type() == TiXmlNode::DOCUMENT) + { + if (GetDocument()) GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if (!node) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if (beforeThis->prev) + { + beforeThis->prev->next = node; + } + else + { + assert(firstChild == beforeThis); + firstChild = node; + } + beforeThis->prev = node; + return node; +} + + +TiXmlNode* TiXmlNode::InsertAfterChild(TiXmlNode* afterThis, const TiXmlNode& addThis) +{ + if (!afterThis || afterThis->parent != this) { + return 0; + } + if (addThis.Type() == TiXmlNode::DOCUMENT) + { + if (GetDocument()) GetDocument()->SetError(TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if (!node) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if (afterThis->next) + { + afterThis->next->prev = node; + } + else + { + assert(lastChild == afterThis); + lastChild = node; + } + afterThis->next = node; + return node; +} + + +TiXmlNode* TiXmlNode::ReplaceChild(TiXmlNode* replaceThis, const TiXmlNode& withThis) +{ + if (replaceThis->parent != this) + return 0; + + TiXmlNode* node = withThis.Clone(); + if (!node) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if (replaceThis->next) + replaceThis->next->prev = node; + else + lastChild = node; + + if (replaceThis->prev) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild(TiXmlNode* removeThis) +{ + if (removeThis->parent != this) + { + assert(0); + return false; + } + + if (removeThis->next) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if (removeThis->prev) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + delete removeThis; + return true; +} + +const TiXmlNode* TiXmlNode::FirstChild(const char * _value) const +{ + const TiXmlNode* node; + for (node = firstChild; node; node = node->next) + { + if (strcmp(node->Value(), _value) == 0) + return node; + } + return 0; +} + + +TiXmlNode* TiXmlNode::FirstChild(const char * _value) +{ + TiXmlNode* node; + for (node = firstChild; node; node = node->next) + { + if (strcmp(node->Value(), _value) == 0) + return node; + } + return 0; +} + + +const TiXmlNode* TiXmlNode::LastChild(const char * _value) const +{ + const TiXmlNode* node; + for (node = lastChild; node; node = node->prev) + { + if (strcmp(node->Value(), _value) == 0) + return node; + } + return 0; +} + +TiXmlNode* TiXmlNode::LastChild(const char * _value) +{ + TiXmlNode* node; + for (node = lastChild; node; node = node->prev) + { + if (strcmp(node->Value(), _value) == 0) + return node; + } + return 0; +} + +const TiXmlNode* TiXmlNode::IterateChildren(const TiXmlNode* previous) const +{ + if (!previous) + { + return FirstChild(); + } + else + { + assert(previous->parent == this); + return previous->NextSibling(); + } +} + +TiXmlNode* TiXmlNode::IterateChildren(TiXmlNode* previous) +{ + if (!previous) + { + return FirstChild(); + } + else + { + assert(previous->parent == this); + return previous->NextSibling(); + } +} + +const TiXmlNode* TiXmlNode::IterateChildren(const char * val, const TiXmlNode* previous) const +{ + if (!previous) + { + return FirstChild(val); + } + else + { + assert(previous->parent == this); + return previous->NextSibling(val); + } +} + +TiXmlNode* TiXmlNode::IterateChildren(const char * val, TiXmlNode* previous) +{ + if (!previous) + { + return FirstChild(val); + } + else + { + assert(previous->parent == this); + return previous->NextSibling(val); + } +} + +const TiXmlNode* TiXmlNode::NextSibling(const char * _value) const +{ + const TiXmlNode* node; + for (node = next; node; node = node->next) + { + if (strcmp(node->Value(), _value) == 0) + return node; + } + return 0; +} + +TiXmlNode* TiXmlNode::NextSibling(const char * _value) +{ + TiXmlNode* node; + for (node = next; node; node = node->next) + { + if (strcmp(node->Value(), _value) == 0) + return node; + } + return 0; +} + +const TiXmlNode* TiXmlNode::PreviousSibling(const char * _value) const +{ + const TiXmlNode* node; + for (node = prev; node; node = node->prev) + { + if (strcmp(node->Value(), _value) == 0) + return node; + } + return 0; +} + +TiXmlNode* TiXmlNode::PreviousSibling(const char * _value) +{ + TiXmlNode* node; + for (node = prev; node; node = node->prev) + { + if (strcmp(node->Value(), _value) == 0) + return node; + } + return 0; +} + +void TiXmlElement::RemoveAttribute(const char * name) +{ + TIXML_STRING str(name); + TiXmlAttribute* node = attributeSet.Find(str); + if (node) + { + attributeSet.Remove(node); + delete node; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling()) + { + if (node->ToElement()) + return node->ToElement(); + } + return 0; +} + +TiXmlElement* TiXmlNode::FirstChildElement() +{ + TiXmlNode* node; + + for ( node = FirstChild(); + node; + node = node->NextSibling()) + { + if (node->ToElement()) + return node->ToElement(); + } + return 0; +} + +const TiXmlElement* TiXmlNode::FirstChildElement(const char * _value) const +{ + const TiXmlNode* node; + + for ( node = FirstChild(_value); + node; + node = node->NextSibling(_value)) + { + if (node->ToElement()) + return node->ToElement(); + } + return 0; +} + +TiXmlElement* TiXmlNode::FirstChildElement(const char * _value) +{ + TiXmlNode* node; + + for ( node = FirstChild(_value); + node; + node = node->NextSibling(_value)) + { + if (node->ToElement()) + return node->ToElement(); + } + return 0; +} + +const TiXmlElement* TiXmlNode::NextSiblingElement() const +{ + const TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling()) + { + if (node->ToElement()) + return node->ToElement(); + } + return 0; +} + +TiXmlElement* TiXmlNode::NextSiblingElement() +{ + TiXmlNode* node; + + for ( node = NextSibling(); + node; + node = node->NextSibling()) + { + if (node->ToElement()) + return node->ToElement(); + } + return 0; +} + +const TiXmlElement* TiXmlNode::NextSiblingElement(const char * _value) const +{ + const TiXmlNode* node; + + for ( node = NextSibling(_value); + node; + node = node->NextSibling(_value)) + { + if (node->ToElement()) + return node->ToElement(); + } + return 0; +} + +TiXmlElement* TiXmlNode::NextSiblingElement(const char * _value) +{ + TiXmlNode* node; + + for ( node = NextSibling(_value); + node; + node = node->NextSibling(_value)) + { + if (node->ToElement()) + return node->ToElement(); + } + return 0; +} + + +const TiXmlDocument* TiXmlNode::GetDocument() const +{ + const TiXmlNode* node; + + for (node = this; node; node = node->parent) + { + if (node->ToDocument()) + return node->ToDocument(); + } + return 0; +} + +TiXmlDocument* TiXmlNode::GetDocument() +{ + TiXmlNode* node; + + for (node = this; node; node = node->parent) + { + if (node->ToDocument()) + return node->ToDocument(); + } + return 0; +} + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode(TiXmlNode::ELEMENT) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement(const std::string& _value) + : TiXmlNode(TiXmlNode::ELEMENT) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement(const TiXmlElement& copy) + : TiXmlNode(TiXmlNode::ELEMENT) +{ + firstChild = lastChild = 0; + copy.CopyTo(this); +} + + +void TiXmlElement::operator=(const TiXmlElement& base) +{ + ClearThis(); + base.CopyTo(this); +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + Clear(); + while (attributeSet.First()) + { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove(node); + delete node; + } +} + + +const char * TiXmlElement::Attribute(const char * name) const +{ + TIXML_STRING str(name); + const TiXmlAttribute* node = attributeSet.Find(str); + + if (node) + return node->Value(); + + return 0; +} + + +const char * TiXmlElement::Attribute(const char * name, int* i) const +{ + const char * s = Attribute(name); + if (i) + { + if (s) + *i = (int)_atoi64(s); + else + *i = 0; + } + return s; +} + + +const char * TiXmlElement::Attribute(const char * name, double* d) const +{ + const char * s = Attribute(name); + if (d) + { + if (s) + *d = atof(s); + else + *d = 0; + } + return s; +} + + +int TiXmlElement::QueryIntAttribute(const char* name, int* ival) const +{ + TIXML_STRING str(name); + const TiXmlAttribute* node = attributeSet.Find(str); + if (!node) + return TIXML_NO_ATTRIBUTE; + + return node->QueryIntValue(ival); +} + + +int TiXmlElement::QueryDoubleAttribute(const char* name, double* dval) const +{ + TIXML_STRING str(name); + const TiXmlAttribute* node = attributeSet.Find(str); + if (!node) + return TIXML_NO_ATTRIBUTE; + + return node->QueryDoubleValue(dval); +} + + +void TiXmlElement::SetAttribute(const char * name, int val) +{ + char buf[64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", val); + #else + sprintf(buf, "%d", val); + #endif + SetAttribute(name, buf); +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute(const std::string& name, int val) +{ + std::ostringstream oss; + oss << val; + SetAttribute(name, oss.str()); +} +#endif + + +void TiXmlElement::SetDoubleAttribute(const char * name, double val) +{ + char buf[256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%f", val); + #else + sprintf(buf, "%f", val); + #endif + SetAttribute(name, buf); +} + + +void TiXmlElement::SetAttribute(const char * cname, const char * cvalue) +{ + TIXML_STRING _name(cname); + TIXML_STRING _value(cvalue); + + TiXmlAttribute* node = attributeSet.Find(_name); + if (node) + { + node->SetValue(cvalue); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute(cname, cvalue); + if (attrib) + { + attributeSet.Add(attrib); + } + else + { + TiXmlDocument* document = GetDocument(); + if (document) document->SetError(TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN); + } +} + + +#ifdef TIXML_USE_STL +void TiXmlElement::SetAttribute(const std::string& name, const std::string& _value) +{ + TiXmlAttribute* node = attributeSet.Find(name); + if (node) + { + node->SetValue(_value); + return; + } + + TiXmlAttribute* attrib = new TiXmlAttribute(name, _value); + if (attrib) + { + attributeSet.Add(attrib); + } + else + { + TiXmlDocument* document = GetDocument(); + if (document) document->SetError(TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN); + } +} +#endif + + +void TiXmlElement::Print(FILE* cfile, int depth) const +{ + int i; + for (i=0; i<depth; i++) + { + fprintf(cfile, " "); + } + + fprintf(cfile, "<%s", value.c_str()); + + const TiXmlAttribute* attrib; + for (attrib = attributeSet.First(); attrib; attrib = attrib->Next()) + { + fprintf(cfile, " "); + attrib->Print(cfile, depth); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a <foo /> node + // 2) An element with only a text child is printed as <foo> text </foo> + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if (!firstChild) + { + fprintf(cfile, " />"); + } + else if (firstChild == lastChild && firstChild->ToText()) + { + fprintf(cfile, ">"); + firstChild->Print(cfile, depth + 1); + fprintf(cfile, "</%s>", value.c_str()); + } + else + { + fprintf(cfile, ">"); + + for (node = firstChild; node; node=node->NextSibling()) + { + if (!node->ToText()) + { + fprintf(cfile, "\n"); + } + node->Print(cfile, depth+1); + } + fprintf(cfile, "\n"); + for (i=0; i<depth; ++i) + fprintf(cfile, " "); + fprintf(cfile, "</%s>", value.c_str()); + } +} + +void TiXmlElement::StreamOut(TIXML_OSTREAM * stream) const +{ + (*stream) << "<" << value; + + const TiXmlAttribute* attrib; + for (attrib = attributeSet.First(); attrib; attrib = attrib->Next()) + { + (*stream) << " "; + attrib->StreamOut(stream); + } + + // If this node has children, give it a closing tag. Else + // make it an empty tag. + TiXmlNode* node; + if (firstChild) + { + (*stream) << ">"; + + for (node = firstChild; node; node=node->NextSibling()) + { + node->StreamOut(stream); + } + (*stream) << "</" << value << ">"; + } + else + { + (*stream) << " />"; + } +} + +void TiXmlElement::FormattedStreamOut(TIXML_OSTREAM * stream, int depth) const +{ + // Adding tabs to get the proper tree format + int oldDepth = depth; + StreamDepth(stream, depth); + + // Element name + (*stream) << "<" << value; + + // Attributes + const TiXmlAttribute* attrib; + for (attrib = attributeSet.First(); attrib; attrib = attrib->Next()) + { + (*stream) << " "; + attrib->StreamOut(stream); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a <foo /> node + // 2) An element with only a text child is printed as <foo> text </foo> + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if (!firstChild) + { + (*stream) << " />" << TIXML_ENDL; + } + else if (firstChild == lastChild && firstChild->ToText()) + { + (*stream) << ">"; + firstChild->FormattedStreamOut(stream, depth + 1); + (*stream) << "</" << value << ">" << TIXML_ENDL; + } + else + { + (*stream) << ">" << TIXML_ENDL; + + // Children + depth++; + for (node = firstChild; node; node=node->NextSibling()) + { + node->FormattedStreamOut(stream, depth); + } + StreamDepth(stream, oldDepth); + (*stream) << "</" << value << ">" << TIXML_ENDL; + } +} + +void TiXmlElement::CopyTo(TiXmlElement* target) const +{ + // superclass: + TiXmlNode::CopyTo(target); + + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for ( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next()) + { + target->SetAttribute(attribute->Name(), attribute->Value()); + } + + TiXmlNode* node = 0; + for (node = firstChild; node; node = node->NextSibling()) + { + target->LinkEndChild(node->Clone()); + } +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement(Value()); + if (!clone) + return 0; + + CopyTo(clone); + return clone; +} + + +const char* TiXmlElement::GetText() const +{ + const TiXmlNode* child = this->FirstChild(); + if (child) { + const TiXmlText* childText = child->ToText(); + if (childText) { + return childText->Value(); + } + } + return 0; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode(TiXmlNode::DOCUMENT) +{ + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); +} + +TiXmlDocument::TiXmlDocument(const char * documentName) : TiXmlNode(TiXmlNode::DOCUMENT) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument(const std::string& documentName) : TiXmlNode(TiXmlNode::DOCUMENT) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument(const TiXmlDocument& copy) : TiXmlNode(TiXmlNode::DOCUMENT) +{ + copy.CopyTo(this); +} + + +void TiXmlDocument::operator=(const TiXmlDocument& copy) +{ + Clear(); + copy.CopyTo(this); +} + + +bool TiXmlDocument::LoadFile(TiXmlEncoding encoding) +{ + // See STL_STRING_BUG below. + StringToBuffer buf(value); + + if (buf.buffer && LoadFile(buf.buffer, encoding)) + return true; + + return false; +} + + +bool TiXmlDocument::SaveFile() const +{ + // See STL_STRING_BUG below. + StringToBuffer buf(value); + + if (buf.buffer && SaveFile(buf.buffer)) + return true; + + return false; +} + +#ifdef TIXML_USE_STL +std::string TiXmlDocument::GetAsString() +{ + std::stringstream out; + FormattedStreamOut(&out, 0); + return out.str(); +} +#endif + +bool TiXmlDocument::GetAsCharBuffer(char* buffer, size_t bufferSize) +{ + #ifdef TIXML_USE_STL + std::string data = GetAsString(); + #else + TIXML_OSTREAM data; + FormattedStreamOut(&data, 0); + #endif + + if (bufferSize < data.length()) + { + return false; + } + else + { + strcpy(buffer, data.c_str()); + return true; + } +} + +bool TiXmlDocument::LoadFile(const char* filename, TiXmlEncoding encoding) +{ + // There was a really terrifying little bug here. The code: + // value = filename + // in the STL case, cause the assignment method of the std::string to + // be called. What is strange, is that the std::string had the same + // address as it's c_str() method, and so bad things happen. Looks + // like a bug in the Microsoft STL implementation. + // See STL_STRING_BUG above. + // Fixed with the StringToBuffer class. + value = filename; + + // reading in binary mode so that tinyxml can normalize the EOL + FILE* file = fopen(value.c_str (), "rb"); + + if (file) + { + bool result = LoadFile(file, encoding); + fclose(file); + return result; + } + else + { + SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN); + return false; + } +} + +bool TiXmlDocument::LoadFile(FILE* file, TiXmlEncoding encoding) +{ + if (!file) + { + SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN); + return false; + } + + // Delete the existing data: + Clear(); + location.Clear(); + + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek(file, 0, SEEK_END); + length = ftell(file); + fseek(file, 0, SEEK_SET); + + // Strange case, but good to handle up front. + if (length == 0) + { + SetError(TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN); + return false; + } + + // If we have a file, assume it is all one big XML file, and read it in. + // The document parser may decide the document ends sooner than the entire file, however. + TIXML_STRING data; + data.reserve(length); + + // Subtle bug here. TinyXml did use fgets. But from the XML spec: + // 2.11 End-of-Line Handling + // <snip> + // <quote> + // ...the XML processor MUST behave as if it normalized all line breaks in external + // parsed entities (including the document entity) on input, before parsing, by translating + // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to + // a single #xA character. + // </quote> + // + // It is not clear fgets does that, and certainly isn't clear it works cross platform. + // Generally, you expect fgets to translate from the convention of the OS to the c/unix + // convention, and not work generally. + + /* + while (fgets(buf, sizeof(buf), file)) + { + data += buf; + } + */ + + char* buf = new char[ length+1 ]; + buf[0] = 0; + + if (fread(buf, length, 1, file) != 1) { + delete [] buf; + SetError(TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN); + return false; + } + + const char* lastPos = buf; + const char* p = buf; + + buf[length] = 0; + while (*p) { + assert(p < (buf+length)); + if (*p == 0xa) { + // Newline character. No special rules for this. Append all the characters + // since the last string, and include the newline. + data.append(lastPos, (p-lastPos+1)); // append, include the newline + ++p; // move past the newline + lastPos = p; // and point to the new buffer (may be 0) + assert(p <= (buf+length)); + } + else if (*p == 0xd) { + // Carriage return. Append what we have so far, then + // handle moving forward in the buffer. + if ((p-lastPos) > 0) { + data.append(lastPos, p-lastPos); // do not add the CR + } + data += (char)0xa; // a proper newline + + if (*(p+1) == 0xa) { + // Carriage return - new line sequence + p += 2; + lastPos = p; + assert(p <= (buf+length)); + } + else { + // it was followed by something else...that is presumably characters again. + ++p; + lastPos = p; + assert(p <= (buf+length)); + } + } + else { + ++p; + } + } + // Handle any left over characters. + if (p-lastPos) { + data.append(lastPos, p-lastPos); + } + delete [] buf; + buf = 0; + + Parse(data.c_str(), 0, encoding); + + if ( Error()) + return false; + else + return true; +} + + +bool TiXmlDocument::SaveFile(const char * filename) const +{ + // The old c stuff lives on... + FILE* fp = fopen(filename, "w"); + if (fp) + { + bool result = SaveFile(fp); + fclose(fp); + return result; + } + return false; +} + + +bool TiXmlDocument::SaveFile(FILE* fp) const +{ + if (useMicrosoftBOM) + { + const unsigned char TIXML_UTF_LEAD_0 = 0xefU; + const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; + const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + + fputc(TIXML_UTF_LEAD_0, fp); + fputc(TIXML_UTF_LEAD_1, fp); + fputc(TIXML_UTF_LEAD_2, fp); + } + Print(fp, 0); + return true; +} + + +void TiXmlDocument::CopyTo(TiXmlDocument* target) const +{ + TiXmlNode::CopyTo(target); + + target->error = error; + target->errorDesc = errorDesc.c_str (); + + TiXmlNode* node = 0; + for (node = firstChild; node; node = node->NextSibling()) + { + target->LinkEndChild(node->Clone()); + } +} + + +TiXmlNode* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if (!clone) + return 0; + + CopyTo(clone); + return clone; +} + + +void TiXmlDocument::Print(FILE* cfile, int depth) const +{ + const TiXmlNode* node; + for (node=FirstChild(); node; node=node->NextSibling()) + { + node->Print(cfile, depth); + fprintf(cfile, "\n"); + } +} + +void TiXmlDocument::StreamOut(TIXML_OSTREAM * out) const +{ + const TiXmlNode* node; + for (node=FirstChild(); node; node=node->NextSibling()) + { + node->StreamOut(out); + + // Special rule for streams: stop after the root element. + // The stream in code will only read one element, so don't + // write more than one. + if (node->ToElement()) + break; + } +} + +void TiXmlDocument::FormattedStreamOut(TIXML_OSTREAM * out, int depth) const +{ + const TiXmlNode* node; + for (node=FirstChild(); node; node=node->NextSibling()) + { + node->FormattedStreamOut(out, depth); + + // Special rule for streams: stop after the root element. + // The stream in code will only read one element, so don't + // write more than one. + if (node->ToElement()) + break; + } +} + +const TiXmlAttribute* TiXmlAttribute::Next() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if (next->value.empty() && next->name.empty()) + return 0; + return next; +} + +TiXmlAttribute* TiXmlAttribute::Next() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if (next->value.empty() && next->name.empty()) + return 0; + return next; +} + +const TiXmlAttribute* TiXmlAttribute::Previous() const +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if (prev->value.empty() && prev->name.empty()) + return 0; + return prev; +} + +TiXmlAttribute* TiXmlAttribute::Previous() +{ + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if (prev->value.empty() && prev->name.empty()) + return 0; + return prev; +} + +void TiXmlAttribute::Print(FILE* cfile, int /*depth*/) const +{ + TIXML_STRING n, v; + + PutString(name, &n); + PutString(value, &v); + + if (value.find ('\"') == TIXML_STRING::npos) + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str()); + else + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str()); +} + + +void TiXmlAttribute::StreamOut(TIXML_OSTREAM * stream) const +{ + if (value.find('\"') != TIXML_STRING::npos) + { + PutString(name, stream); + (*stream) << "=" << "'"; + PutString(value, stream); + (*stream) << "'"; + } + else + { + PutString(name, stream); + (*stream) << "=" << "\""; + PutString(value, stream); + (*stream) << "\""; + } +} + +int TiXmlAttribute::QueryIntValue(int* ival) const +{ + if (sscanf(value.c_str(), "%d", ival) == 1) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +int TiXmlAttribute::QueryDoubleValue(double* dval) const +{ + if (sscanf(value.c_str(), "%lf", dval) == 1) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; +} + +void TiXmlAttribute::SetIntValue(int _value) +{ + char buf [64]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); + #else + sprintf (buf, "%d", _value); + #endif + SetValue (buf); +} + +void TiXmlAttribute::SetDoubleValue(double _value) +{ + char buf [256]; + #if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%lf", _value); + #else + sprintf (buf, "%lf", _value); + #endif + SetValue (buf); +} + +int TiXmlAttribute::IntValue() const +{ + return (int)_atoi64(value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment(const TiXmlComment& copy) : TiXmlNode(TiXmlNode::COMMENT) +{ + copy.CopyTo(this); +} + + +void TiXmlComment::operator=(const TiXmlComment& base) +{ + Clear(); + base.CopyTo(this); +} + + +void TiXmlComment::Print(FILE* cfile, int depth) const +{ + for (int i=0; i<depth; i++) + { + fputs(" ", cfile); + } + fprintf(cfile, "<!--%s-->", value.c_str()); +} + +void TiXmlComment::StreamOut(TIXML_OSTREAM * stream) const +{ + (*stream) << "<!--"; + //PutString(value, stream); + (*stream) << value; + (*stream) << "-->"; +} + +void TiXmlComment::FormattedStreamOut(TIXML_OSTREAM * stream, int depth) const +{ + StreamDepth(stream, depth); + + StreamOut(stream); + + (*stream) << TIXML_ENDL; +} + +void TiXmlComment::CopyTo(TiXmlComment* target) const +{ + TiXmlNode::CopyTo(target); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if (!clone) + return 0; + + CopyTo(clone); + return clone; +} + + +void TiXmlText::Print(FILE* cfile, int depth) const +{ + if (cdata) + { + int i; + fprintf(cfile, "\n"); + for (i=0; i<depth; i++) { + fprintf(cfile, " "); + } + fprintf(cfile, "<![CDATA["); + fprintf(cfile, "%s", value.c_str()); // unformatted output + fprintf(cfile, "]]>\n"); + } + else + { + TIXML_STRING buffer; + PutString(value, &buffer); + fprintf(cfile, "%s", buffer.c_str()); + } +} + + +void TiXmlText::StreamOut(TIXML_OSTREAM * stream) const +{ + if (cdata) + { + (*stream) << "<![CDATA[" << value << "]]>"; + } + else + { + PutString(value, stream); + } +} + +void TiXmlText::FormattedStreamOut(TIXML_OSTREAM * stream, int depth) const +{ + if (cdata) + { + (*stream) << TIXML_ENDL; + StreamDepth(stream, depth); + (*stream) << "<![CDATA[" << value << "]]>" << TIXML_ENDL; + } + else + { + PutString(value, stream); + } +} + +void TiXmlText::CopyTo(TiXmlText* target) const +{ + TiXmlNode::CopyTo(target); + target->cdata = cdata; +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText(""); + + if (!clone) + return 0; + + CopyTo(clone); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration(const char * _version, + const char * _encoding, + const char * _standalone) + : TiXmlNode(TiXmlNode::DECLARATION) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} + + +#ifdef TIXML_USE_STL +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone) + : TiXmlNode(TiXmlNode::DECLARATION) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration(const TiXmlDeclaration& copy) + : TiXmlNode(TiXmlNode::DECLARATION) +{ + copy.CopyTo(this); +} + + +void TiXmlDeclaration::operator=(const TiXmlDeclaration& copy) +{ + Clear(); + copy.CopyTo(this); +} + + +void TiXmlDeclaration::Print(FILE* cfile, int /*depth*/) const +{ + fprintf (cfile, "<?xml "); + + if (!version.empty()) + fprintf (cfile, "version=\"%s\" ", version.c_str ()); + if (!encoding.empty()) + fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ()); + if (!standalone.empty()) + fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ()); + fprintf (cfile, "?>"); +} + +void TiXmlDeclaration::StreamOut(TIXML_OSTREAM * stream) const +{ + (*stream) << "<?xml "; + + if (!version.empty()) + { + (*stream) << "version=\""; + PutString(version, stream); + (*stream) << "\" "; + } + if (!encoding.empty()) + { + (*stream) << "encoding=\""; + PutString(encoding, stream); + (*stream) << "\" "; + } + if (!standalone.empty()) + { + (*stream) << "standalone=\""; + PutString(standalone, stream); + (*stream) << "\" "; + } + (*stream) << "?>"; +} + +void TiXmlDeclaration::FormattedStreamOut(TIXML_OSTREAM * stream, int depth) const +{ + StreamDepth(stream, depth); + StreamOut(stream); + (*stream) << TIXML_ENDL; +} + +void TiXmlDeclaration::CopyTo(TiXmlDeclaration* target) const +{ + TiXmlNode::CopyTo(target); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if (!clone) + return 0; + + CopyTo(clone); + return clone; +} + + +void TiXmlUnknown::Print(FILE* cfile, int depth) const +{ + for (int i=0; i<depth; i++) + fprintf(cfile, " "); + fprintf(cfile, "<%s>", value.c_str()); +} + + +void TiXmlUnknown::StreamOut(TIXML_OSTREAM * stream) const +{ + (*stream) << "<" << value << ">"; // Don't use entities here! It is unknown. +} + +void TiXmlUnknown::FormattedStreamOut(TIXML_OSTREAM * stream, int depth) const +{ + StreamDepth(stream, depth); + (*stream) << "<" << value << ">" << TIXML_ENDL; // Don't use entities here! It is unknown. +} + +void TiXmlUnknown::CopyTo(TiXmlUnknown* target) const +{ + TiXmlNode::CopyTo(target); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if (!clone) + return 0; + + CopyTo(clone); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + assert(sentinel.next == &sentinel); + assert(sentinel.prev == &sentinel); +} + + +void TiXmlAttributeSet::Add(TiXmlAttribute* addMe) +{ + assert(!Find(TIXML_STRING(addMe->Name()))); // Shouldn't be multiply adding to the set. + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove(TiXmlAttribute* removeMe) +{ + TiXmlAttribute* node; + + for (node = sentinel.next; node != &sentinel; node = node->next) + { + if (node == removeMe) + { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert(0); // we tried to remove a non-linked attribute. +} + +const TiXmlAttribute* TiXmlAttributeSet::Find(const TIXML_STRING& name) const +{ + const TiXmlAttribute* node; + + for (node = sentinel.next; node != &sentinel; node = node->next) + { + if (node->name == name) + return node; + } + return 0; +} + +TiXmlAttribute* TiXmlAttributeSet::Find(const TIXML_STRING& name) +{ + TiXmlAttribute* node; + + for (node = sentinel.next; node != &sentinel; node = node->next) + { + if (node->name == name) + return node; + } + return 0; +} + +#ifdef TIXML_USE_STL +TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve(8 * 1000); + base.StreamIn(&in, &tag); + + base.Parse(tag.c_str(), 0, TIXML_DEFAULT_ENCODING); + return in; +} +#endif + + +TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base) +{ + base.StreamOut (& out); + return out; +} + + +#ifdef TIXML_USE_STL +std::string & operator<< (std::string& out, const TiXmlNode& base) +{ + std::ostringstream os_stream(std::ostringstream::out); + base.StreamOut(&os_stream); + + out.append(os_stream.str()); + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + if (node) + { + TiXmlNode* child = node->FirstChild(); + if (child) + return TiXmlHandle(child); + } + return TiXmlHandle(0); +} + + +TiXmlHandle TiXmlHandle::FirstChild(const char * value) const +{ + if (node) + { + TiXmlNode* child = node->FirstChild(value); + if (child) + return TiXmlHandle(child); + } + return TiXmlHandle(0); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + if (node) + { + TiXmlElement* child = node->FirstChildElement(); + if (child) + return TiXmlHandle(child); + } + return TiXmlHandle(0); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement(const char * value) const +{ + if (node) + { + TiXmlElement* child = node->FirstChildElement(value); + if (child) + return TiXmlHandle(child); + } + return TiXmlHandle(0); +} + + +TiXmlHandle TiXmlHandle::Child(int count) const +{ + if (node) + { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && i<count; + child = child->NextSibling(), ++i) + { + // nothing + } + if (child) + return TiXmlHandle(child); + } + return TiXmlHandle(0); +} + + +TiXmlHandle TiXmlHandle::Child(const char* value, int count) const +{ + if (node) + { + int i; + TiXmlNode* child = node->FirstChild(value); + for ( i=0; + child && i<count; + child = child->NextSibling(value), ++i) + { + // nothing + } + if (child) + return TiXmlHandle(child); + } + return TiXmlHandle(0); +} + + +TiXmlHandle TiXmlHandle::ChildElement(int count) const +{ + if (node) + { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && i<count; + child = child->NextSiblingElement(), ++i) + { + // nothing + } + if (child) + return TiXmlHandle(child); + } + return TiXmlHandle(0); +} + + +TiXmlHandle TiXmlHandle::ChildElement(const char* value, int count) const +{ + if (node) + { + int i; + TiXmlElement* child = node->FirstChildElement(value); + for ( i=0; + child && i<count; + child = child->NextSiblingElement(value), ++i) + { + // nothing + } + if (child) + return TiXmlHandle(child); + } + return TiXmlHandle(0); +} |