├── README ├── Xml ├── XmlNode.h ├── XmlNode.cpp ├── XmlStream.h ├── XmlAttribute.h ├── XmlFileBridge.h ├── XmlStream.cpp ├── XmlAttribute.cpp └── TinyXml │ ├── tinystr.cpp │ ├── tinyxmlerror.cpp │ ├── tinystr.h │ ├── tinyxmlparser.cpp │ └── tinyxml.cpp └── XmlEdit ├── stdafx.h ├── ReadMe.txt ├── XmlEdit.aps ├── XmlEdit.cpp ├── XmlEdit.h ├── XmlEdit.ncb ├── XmlEdit.rc ├── XmlEdit.suo ├── res ├── app.ico ├── CLSDFOLD.ICO ├── OPENFOLD.ICO ├── XmlEdit.ico ├── XmlEdit.rc2 └── XmlEdit.manifest ├── stdafx.cpp ├── Xml ├── XmlNode.h ├── XmlNode.cpp ├── XmlStream.h ├── XmlAttribute.h ├── XmlStream.cpp ├── XmlAttribute.cpp ├── XmlFileBridge.h └── TinyXml │ ├── tinystr.cpp │ ├── tinyxmlerror.cpp │ ├── tinystr.h │ ├── tinyxmlparser.cpp │ └── tinyxml.cpp ├── XmlEditDlg.h ├── FileBridge.cpp ├── Release ├── 222.txml ├── 333.txml └── XmlEdit.exe ├── XmlEdit.vcproj ├── XmlEditDlg.cpp ├── AttributeEditDlg.h ├── StandardInputDlg.h ├── AttributeCreateDlg.h ├── AttributeEditDlg.cpp ├── StandardInputDlg.cpp ├── AttributeCreateDlg.cpp ├── FileBridge.h ├── XmlEdit.sln └── resource.h /README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/README -------------------------------------------------------------------------------- /Xml/XmlNode.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/Xml/XmlNode.h -------------------------------------------------------------------------------- /Xml/XmlNode.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/Xml/XmlNode.cpp -------------------------------------------------------------------------------- /Xml/XmlStream.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/Xml/XmlStream.h -------------------------------------------------------------------------------- /XmlEdit/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/stdafx.h -------------------------------------------------------------------------------- /Xml/XmlAttribute.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/Xml/XmlAttribute.h -------------------------------------------------------------------------------- /Xml/XmlFileBridge.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/Xml/XmlFileBridge.h -------------------------------------------------------------------------------- /Xml/XmlStream.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/Xml/XmlStream.cpp -------------------------------------------------------------------------------- /XmlEdit/ReadMe.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/ReadMe.txt -------------------------------------------------------------------------------- /XmlEdit/XmlEdit.aps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/XmlEdit.aps -------------------------------------------------------------------------------- /XmlEdit/XmlEdit.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/XmlEdit.cpp -------------------------------------------------------------------------------- /XmlEdit/XmlEdit.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/XmlEdit.h -------------------------------------------------------------------------------- /XmlEdit/XmlEdit.ncb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/XmlEdit.ncb -------------------------------------------------------------------------------- /XmlEdit/XmlEdit.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/XmlEdit.rc -------------------------------------------------------------------------------- /XmlEdit/XmlEdit.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/XmlEdit.suo -------------------------------------------------------------------------------- /XmlEdit/res/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/res/app.ico -------------------------------------------------------------------------------- /XmlEdit/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/stdafx.cpp -------------------------------------------------------------------------------- /Xml/XmlAttribute.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/Xml/XmlAttribute.cpp -------------------------------------------------------------------------------- /XmlEdit/Xml/XmlNode.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/Xml/XmlNode.h -------------------------------------------------------------------------------- /XmlEdit/XmlEditDlg.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/XmlEditDlg.h -------------------------------------------------------------------------------- /Xml/TinyXml/tinystr.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/Xml/TinyXml/tinystr.cpp -------------------------------------------------------------------------------- /XmlEdit/FileBridge.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/FileBridge.cpp -------------------------------------------------------------------------------- /XmlEdit/Release/222.txml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/Release/222.txml -------------------------------------------------------------------------------- /XmlEdit/Release/333.txml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/Release/333.txml -------------------------------------------------------------------------------- /XmlEdit/Xml/XmlNode.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/Xml/XmlNode.cpp -------------------------------------------------------------------------------- /XmlEdit/Xml/XmlStream.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/Xml/XmlStream.h -------------------------------------------------------------------------------- /XmlEdit/XmlEdit.vcproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/XmlEdit.vcproj -------------------------------------------------------------------------------- /XmlEdit/XmlEditDlg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/XmlEditDlg.cpp -------------------------------------------------------------------------------- /XmlEdit/res/CLSDFOLD.ICO: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/res/CLSDFOLD.ICO -------------------------------------------------------------------------------- /XmlEdit/res/OPENFOLD.ICO: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/res/OPENFOLD.ICO -------------------------------------------------------------------------------- /XmlEdit/res/XmlEdit.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/res/XmlEdit.ico -------------------------------------------------------------------------------- /XmlEdit/res/XmlEdit.rc2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/res/XmlEdit.rc2 -------------------------------------------------------------------------------- /XmlEdit/AttributeEditDlg.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/AttributeEditDlg.h -------------------------------------------------------------------------------- /XmlEdit/StandardInputDlg.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/StandardInputDlg.h -------------------------------------------------------------------------------- /XmlEdit/Xml/XmlAttribute.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/Xml/XmlAttribute.h -------------------------------------------------------------------------------- /XmlEdit/Xml/XmlStream.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/Xml/XmlStream.cpp -------------------------------------------------------------------------------- /XmlEdit/AttributeCreateDlg.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/AttributeCreateDlg.h -------------------------------------------------------------------------------- /XmlEdit/AttributeEditDlg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/AttributeEditDlg.cpp -------------------------------------------------------------------------------- /XmlEdit/Release/XmlEdit.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/Release/XmlEdit.exe -------------------------------------------------------------------------------- /XmlEdit/StandardInputDlg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/StandardInputDlg.cpp -------------------------------------------------------------------------------- /XmlEdit/Xml/XmlAttribute.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/Xml/XmlAttribute.cpp -------------------------------------------------------------------------------- /XmlEdit/Xml/XmlFileBridge.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/Xml/XmlFileBridge.h -------------------------------------------------------------------------------- /XmlEdit/AttributeCreateDlg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/AttributeCreateDlg.cpp -------------------------------------------------------------------------------- /XmlEdit/Xml/TinyXml/tinystr.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baickl/PAL4Xml/HEAD/XmlEdit/Xml/TinyXml/tinystr.cpp -------------------------------------------------------------------------------- /XmlEdit/res/XmlEdit.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 在此说明应用程序 10 | 11 | 12 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /XmlEdit/FileBridge.h: -------------------------------------------------------------------------------- 1 | // FileBridge.h: interface for the CFileBridge class. 2 | // 3 | ////////////////////////////////////////////////////////////////////// 4 | 5 | #if !defined(AFX_FILEBRIDGE_H__C8173EDB_BB08_4F1B_9F84_BF3F9F7254C3__INCLUDED_) 6 | #define AFX_FILEBRIDGE_H__C8173EDB_BB08_4F1B_9F84_BF3F9F7254C3__INCLUDED_ 7 | 8 | #include "xml/XmlFileBridge.h" 9 | 10 | #if _MSC_VER > 1000 11 | #pragma once 12 | #endif // _MSC_VER > 1000 13 | 14 | class CFileBridge:public xnd::XmlFileBridge 15 | { 16 | public: 17 | 18 | explicit CFileBridge(CFile* pFile); 19 | virtual ~CFileBridge(); 20 | 21 | virtual int length( void ) const; 22 | virtual int getPosition( void ) const; 23 | virtual void setPosition( int pos ); 24 | virtual bool read( void* out,int len ); 25 | virtual bool write( const void* in,int len ); 26 | 27 | protected: 28 | CFile* m_pFile; 29 | 30 | }; 31 | 32 | #endif // !defined(AFX_FILEBRIDGE_H__C8173EDB_BB08_4F1B_9F84_BF3F9F7254C3__INCLUDED_) 33 | -------------------------------------------------------------------------------- /XmlEdit/XmlEdit.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 8.00 2 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XmlEdit", "XmlEdit.vcproj", "{197E55C8-F659-4289-A015-D93BDDFB19CF}" 3 | ProjectSection(ProjectDependencies) = postProject 4 | EndProjectSection 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfiguration) = preSolution 8 | Debug = Debug 9 | Release = Release 10 | EndGlobalSection 11 | GlobalSection(ProjectConfiguration) = postSolution 12 | {197E55C8-F659-4289-A015-D93BDDFB19CF}.Debug.ActiveCfg = Debug|Win32 13 | {197E55C8-F659-4289-A015-D93BDDFB19CF}.Debug.Build.0 = Debug|Win32 14 | {197E55C8-F659-4289-A015-D93BDDFB19CF}.Release.ActiveCfg = Release|Win32 15 | {197E55C8-F659-4289-A015-D93BDDFB19CF}.Release.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(ExtensibilityGlobals) = postSolution 18 | EndGlobalSection 19 | GlobalSection(ExtensibilityAddIns) = postSolution 20 | EndGlobalSection 21 | EndGlobal 22 | -------------------------------------------------------------------------------- /Xml/TinyXml/tinyxmlerror.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | 25 | #include "stdafx.h" 26 | #include "tinyxml.h" 27 | 28 | // The goal of the seperate error file is to make the first 29 | // step towards localization. tinyxml (currently) only supports 30 | // english error messages, but the could now be translated. 31 | // 32 | // It also cleans up the code a bit. 33 | // 34 | 35 | const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] = 36 | { 37 | "No error", 38 | "Error", 39 | "Failed to open file", 40 | "Memory allocation failed.", 41 | "Error parsing Element.", 42 | "Failed to read Element name", 43 | "Error reading Element value.", 44 | "Error reading Attributes.", 45 | "Error: empty tag.", 46 | "Error reading end tag.", 47 | "Error parsing Unknown.", 48 | "Error parsing Comment.", 49 | "Error parsing Declaration.", 50 | "Error document empty.", 51 | "Error null (0) or unexpected EOF found in input stream.", 52 | "Error parsing CDATA.", 53 | "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", 54 | }; 55 | -------------------------------------------------------------------------------- /XmlEdit/Xml/TinyXml/tinyxmlerror.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | 25 | #include "stdafx.h" 26 | #include "tinyxml.h" 27 | 28 | // The goal of the seperate error file is to make the first 29 | // step towards localization. tinyxml (currently) only supports 30 | // english error messages, but the could now be translated. 31 | // 32 | // It also cleans up the code a bit. 33 | // 34 | 35 | const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] = 36 | { 37 | "No error", 38 | "Error", 39 | "Failed to open file", 40 | "Memory allocation failed.", 41 | "Error parsing Element.", 42 | "Failed to read Element name", 43 | "Error reading Element value.", 44 | "Error reading Attributes.", 45 | "Error: empty tag.", 46 | "Error reading end tag.", 47 | "Error parsing Unknown.", 48 | "Error parsing Comment.", 49 | "Error parsing Declaration.", 50 | "Error document empty.", 51 | "Error null (0) or unexpected EOF found in input stream.", 52 | "Error parsing CDATA.", 53 | "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", 54 | }; 55 | -------------------------------------------------------------------------------- /XmlEdit/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by XmlEdit.rc 4 | // 5 | #define IDM_ABOUTBOX 0x0010 6 | #define IDD_ABOUTBOX 100 7 | #define IDS_ABOUTBOX 101 8 | #define IDD_XMLEDIT_DIALOG 102 9 | #define IDR_MAINMENU 129 10 | #define IDR_MAINFRAME 131 11 | #define IDI_UNSELECT 132 12 | #define IDI_SELECT 133 13 | #define IDR_MENU_TREE 134 14 | #define IDR_MENU_LIST 135 15 | #define IDD_STANDARD_INPUT 136 16 | #define IDD_ATTRIBUTE_DIALOG 137 17 | #define IDD_ATTRIBUTECREAT_DIALOG 138 18 | #define IDC_TREE_NODES 1000 19 | #define IDC_LIST_ATTRIBUTES 1001 20 | #define IDR_STATIC 1002 21 | #define IDC_EDIT 1003 22 | #define IDC_EDIT_NAME 1004 23 | #define IDC_COMBO_TYPE 1006 24 | #define IDC_EDIT_VALUE 1007 25 | #define IDC_BUTTON_IMPORT 1010 26 | #define IDC_BUTTON_EXPORT 1011 27 | #define IDC_BUTTON1 1012 28 | #define IDC_BUTTON_APPLY 1012 29 | #define ID_FILE_O 32771 30 | #define ID_FILE_OPEN32772 32772 31 | #define ID_FILE_SAVE32773 32773 32 | #define ID_FILE_SAVEAS 32774 33 | #define ID_FILE_EXIT 32775 34 | #define ID_HELP_ABOUT 32776 35 | #define ID_TREEPOPUMENU_A 32777 36 | #define ID_TREEPOPUMENU_D 32778 37 | #define ID_TREEPOPUMENU_R 32779 38 | #define ID_F_N 32780 39 | #define ID_F_C 32781 40 | #define ID_LISTPOPUMENU_N 32782 41 | #define ID_LISTPOPUMENU_T 32785 42 | #define ID_T_1 32786 43 | #define ID_T_2 32787 44 | #define ID_T_3 32788 45 | #define ID_T_4 32789 46 | #define ID_T_5 32790 47 | #define ID_LISTPOPUMENU_R 32791 48 | #define ID_LISTPOPUMENU_M 32792 49 | #define ID_LISTPOPUMENU_E 32793 50 | #define ID_LISTPOPUMENU_D 32794 51 | #define ID_N_1 32795 52 | #define ID_N_2 32796 53 | #define ID_N_3 32797 54 | #define ID_N_4 32798 55 | #define ID_N_5 32799 56 | #define ID_A_N 32800 57 | #define ID_N_T 32801 58 | #define ID_N_V 32803 59 | #define ID_N_32804 32804 60 | #define ID_N_C 32805 61 | #define ID_Menu 32806 62 | #define ID_E_32807 32807 63 | #define ID_E_E 32808 64 | #define ID_E_I 32809 65 | #define ID_E_R 32810 66 | 67 | // Next default values for new objects 68 | // 69 | #ifdef APSTUDIO_INVOKED 70 | #ifndef APSTUDIO_READONLY_SYMBOLS 71 | #define _APS_NEXT_RESOURCE_VALUE 139 72 | #define _APS_NEXT_COMMAND_VALUE 32811 73 | #define _APS_NEXT_CONTROL_VALUE 1013 74 | #define _APS_NEXT_SYMED_VALUE 101 75 | #endif 76 | #endif 77 | -------------------------------------------------------------------------------- /Xml/TinyXml/tinystr.h: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original file by Yves Berquin. 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | 25 | /* 26 | * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. 27 | * 28 | * - completely rewritten. compact, clean, and fast implementation. 29 | * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) 30 | * - fixed reserve() to work as per specification. 31 | * - fixed buggy compares operator==(), operator<(), and operator>() 32 | * - fixed operator+=() to take a const ref argument, following spec. 33 | * - added "copy" constructor with length, and most compare operators. 34 | * - added swap(), clear(), size(), capacity(), operator+(). 35 | */ 36 | 37 | 38 | #ifndef TIXML_USE_STL 39 | 40 | #ifndef TIXML_STRING_INCLUDED 41 | #define TIXML_STRING_INCLUDED 42 | 43 | #include 44 | #include 45 | 46 | /* The support for explicit isn't that universal, and it isn't really 47 | required - it is used to check that the TiXmlString class isn't incorrectly 48 | used. Be nice to old compilers and macro it here: 49 | */ 50 | #if defined(_MSC_VER) && (_MSC_VER >= 1200 ) 51 | // Microsoft visual studio, version 6 and higher. 52 | #define TIXML_EXPLICIT explicit 53 | #elif defined(__GNUC__) && (__GNUC__ >= 3 ) 54 | // GCC version 3 and higher.s 55 | #define TIXML_EXPLICIT explicit 56 | #else 57 | #define TIXML_EXPLICIT 58 | #endif 59 | 60 | 61 | /* 62 | TiXmlString is an emulation of a subset of the std::string template. 63 | Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. 64 | Only the member functions relevant to the TinyXML project have been implemented. 65 | The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase 66 | a string and there's no more room, we allocate a buffer twice as big as we need. 67 | */ 68 | class TiXmlString 69 | { 70 | public : 71 | // The size type used 72 | typedef size_t size_type; 73 | 74 | // Error value for find primitive 75 | static const size_type npos; // = -1; 76 | 77 | 78 | // TiXmlString empty constructor 79 | TiXmlString () : rep_(&nullrep_) 80 | { 81 | } 82 | 83 | // TiXmlString copy constructor 84 | TiXmlString ( const TiXmlString & copy) : rep_(0) 85 | { 86 | init(copy.length()); 87 | memcpy(start(), copy.data(), length()); 88 | } 89 | 90 | // TiXmlString constructor, based on a string 91 | TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) 92 | { 93 | init( static_cast( strlen(copy) )); 94 | memcpy(start(), copy, length()); 95 | } 96 | 97 | // TiXmlString constructor, based on a string 98 | TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) 99 | { 100 | init(len); 101 | memcpy(start(), str, len); 102 | } 103 | 104 | // TiXmlString destructor 105 | ~TiXmlString () 106 | { 107 | quit(); 108 | } 109 | 110 | // = operator 111 | TiXmlString& operator = (const char * copy) 112 | { 113 | return assign( copy, (size_type)strlen(copy)); 114 | } 115 | 116 | // = operator 117 | TiXmlString& operator = (const TiXmlString & copy) 118 | { 119 | return assign(copy.start(), copy.length()); 120 | } 121 | 122 | 123 | // += operator. Maps to append 124 | TiXmlString& operator += (const char * suffix) 125 | { 126 | return append(suffix, static_cast( strlen(suffix) )); 127 | } 128 | 129 | // += operator. Maps to append 130 | TiXmlString& operator += (char single) 131 | { 132 | return append(&single, 1); 133 | } 134 | 135 | // += operator. Maps to append 136 | TiXmlString& operator += (const TiXmlString & suffix) 137 | { 138 | return append(suffix.data(), suffix.length()); 139 | } 140 | 141 | 142 | // Convert a TiXmlString into a null-terminated char * 143 | const char * c_str () const { return rep_->str; } 144 | 145 | // Convert a TiXmlString into a char * (need not be null terminated). 146 | const char * data () const { return rep_->str; } 147 | 148 | // Return the length of a TiXmlString 149 | size_type length () const { return rep_->size; } 150 | 151 | // Alias for length() 152 | size_type size () const { return rep_->size; } 153 | 154 | // Checks if a TiXmlString is empty 155 | bool empty () const { return rep_->size == 0; } 156 | 157 | // Return capacity of string 158 | size_type capacity () const { return rep_->capacity; } 159 | 160 | 161 | // single char extraction 162 | const char& at (size_type index) const 163 | { 164 | assert( index < length() ); 165 | return rep_->str[ index ]; 166 | } 167 | 168 | // [] operator 169 | char& operator [] (size_type index) const 170 | { 171 | assert( index < length() ); 172 | return rep_->str[ index ]; 173 | } 174 | 175 | // find a char in a string. Return TiXmlString::npos if not found 176 | size_type find (char lookup) const 177 | { 178 | return find(lookup, 0); 179 | } 180 | 181 | // find a char in a string from an offset. Return TiXmlString::npos if not found 182 | size_type find (char tofind, size_type offset) const 183 | { 184 | if (offset >= length()) return npos; 185 | 186 | for (const char* p = c_str() + offset; *p != '\0'; ++p) 187 | { 188 | if (*p == tofind) return static_cast< size_type >( p - c_str() ); 189 | } 190 | return npos; 191 | } 192 | 193 | void clear () 194 | { 195 | //Lee: 196 | //The original was just too strange, though correct: 197 | // TiXmlString().swap(*this); 198 | //Instead use the quit & re-init: 199 | quit(); 200 | init(0,0); 201 | } 202 | 203 | /* Function to reserve a big amount of data when we know we'll need it. Be aware that this 204 | function DOES NOT clear the content of the TiXmlString if any exists. 205 | */ 206 | void reserve (size_type cap); 207 | 208 | TiXmlString& assign (const char* str, size_type len); 209 | 210 | TiXmlString& append (const char* str, size_type len); 211 | 212 | void swap (TiXmlString& other) 213 | { 214 | Rep* r = rep_; 215 | rep_ = other.rep_; 216 | other.rep_ = r; 217 | } 218 | 219 | private: 220 | 221 | void init(size_type sz) { init(sz, sz); } 222 | void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } 223 | char* start() const { return rep_->str; } 224 | char* finish() const { return rep_->str + rep_->size; } 225 | 226 | struct Rep 227 | { 228 | size_type size, capacity; 229 | char str[1]; 230 | }; 231 | 232 | void init(size_type sz, size_type cap) 233 | { 234 | if (cap) 235 | { 236 | // Lee: the original form: 237 | // rep_ = static_cast(operator new(sizeof(Rep) + cap)); 238 | // doesn't work in some cases of new being overloaded. Switching 239 | // to the normal allocation, although use an 'int' for systems 240 | // that are overly picky about structure alignment. 241 | const size_type bytesNeeded = sizeof(Rep) + cap; 242 | const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); 243 | rep_ = reinterpret_cast( new int[ intsNeeded ] ); 244 | 245 | rep_->str[ rep_->size = sz ] = '\0'; 246 | rep_->capacity = cap; 247 | } 248 | else 249 | { 250 | rep_ = &nullrep_; 251 | } 252 | } 253 | 254 | void quit() 255 | { 256 | if (rep_ != &nullrep_) 257 | { 258 | // The rep_ is really an array of ints. (see the allocator, above). 259 | // Cast it back before delete, so the compiler won't incorrectly call destructors. 260 | delete [] ( reinterpret_cast( rep_ ) ); 261 | } 262 | } 263 | 264 | Rep * rep_; 265 | static Rep nullrep_; 266 | 267 | } ; 268 | 269 | 270 | inline bool operator == (const TiXmlString & a, const TiXmlString & b) 271 | { 272 | return ( a.length() == b.length() ) // optimization on some platforms 273 | && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare 274 | } 275 | inline bool operator < (const TiXmlString & a, const TiXmlString & b) 276 | { 277 | return strcmp(a.c_str(), b.c_str()) < 0; 278 | } 279 | 280 | inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } 281 | inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } 282 | inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } 283 | inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } 284 | 285 | inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } 286 | inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } 287 | inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } 288 | inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } 289 | 290 | TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); 291 | TiXmlString operator + (const TiXmlString & a, const char* b); 292 | TiXmlString operator + (const char* a, const TiXmlString & b); 293 | 294 | 295 | /* 296 | TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. 297 | Only the operators that we need for TinyXML have been developped. 298 | */ 299 | class TiXmlOutStream : public TiXmlString 300 | { 301 | public : 302 | 303 | // TiXmlOutStream << operator. 304 | TiXmlOutStream & operator << (const TiXmlString & in) 305 | { 306 | *this += in; 307 | return *this; 308 | } 309 | 310 | // TiXmlOutStream << operator. 311 | TiXmlOutStream & operator << (const char * in) 312 | { 313 | *this += in; 314 | return *this; 315 | } 316 | 317 | } ; 318 | 319 | #endif // TIXML_STRING_INCLUDED 320 | #endif // TIXML_USE_STL 321 | -------------------------------------------------------------------------------- /XmlEdit/Xml/TinyXml/tinystr.h: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original file by Yves Berquin. 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | 25 | /* 26 | * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. 27 | * 28 | * - completely rewritten. compact, clean, and fast implementation. 29 | * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) 30 | * - fixed reserve() to work as per specification. 31 | * - fixed buggy compares operator==(), operator<(), and operator>() 32 | * - fixed operator+=() to take a const ref argument, following spec. 33 | * - added "copy" constructor with length, and most compare operators. 34 | * - added swap(), clear(), size(), capacity(), operator+(). 35 | */ 36 | 37 | 38 | #ifndef TIXML_USE_STL 39 | 40 | #ifndef TIXML_STRING_INCLUDED 41 | #define TIXML_STRING_INCLUDED 42 | 43 | #include 44 | #include 45 | 46 | /* The support for explicit isn't that universal, and it isn't really 47 | required - it is used to check that the TiXmlString class isn't incorrectly 48 | used. Be nice to old compilers and macro it here: 49 | */ 50 | #if defined(_MSC_VER) && (_MSC_VER >= 1200 ) 51 | // Microsoft visual studio, version 6 and higher. 52 | #define TIXML_EXPLICIT explicit 53 | #elif defined(__GNUC__) && (__GNUC__ >= 3 ) 54 | // GCC version 3 and higher.s 55 | #define TIXML_EXPLICIT explicit 56 | #else 57 | #define TIXML_EXPLICIT 58 | #endif 59 | 60 | 61 | /* 62 | TiXmlString is an emulation of a subset of the std::string template. 63 | Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. 64 | Only the member functions relevant to the TinyXML project have been implemented. 65 | The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase 66 | a string and there's no more room, we allocate a buffer twice as big as we need. 67 | */ 68 | class TiXmlString 69 | { 70 | public : 71 | // The size type used 72 | typedef size_t size_type; 73 | 74 | // Error value for find primitive 75 | static const size_type npos; // = -1; 76 | 77 | 78 | // TiXmlString empty constructor 79 | TiXmlString () : rep_(&nullrep_) 80 | { 81 | } 82 | 83 | // TiXmlString copy constructor 84 | TiXmlString ( const TiXmlString & copy) : rep_(0) 85 | { 86 | init(copy.length()); 87 | memcpy(start(), copy.data(), length()); 88 | } 89 | 90 | // TiXmlString constructor, based on a string 91 | TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) 92 | { 93 | init( static_cast( strlen(copy) )); 94 | memcpy(start(), copy, length()); 95 | } 96 | 97 | // TiXmlString constructor, based on a string 98 | TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) 99 | { 100 | init(len); 101 | memcpy(start(), str, len); 102 | } 103 | 104 | // TiXmlString destructor 105 | ~TiXmlString () 106 | { 107 | quit(); 108 | } 109 | 110 | // = operator 111 | TiXmlString& operator = (const char * copy) 112 | { 113 | return assign( copy, (size_type)strlen(copy)); 114 | } 115 | 116 | // = operator 117 | TiXmlString& operator = (const TiXmlString & copy) 118 | { 119 | return assign(copy.start(), copy.length()); 120 | } 121 | 122 | 123 | // += operator. Maps to append 124 | TiXmlString& operator += (const char * suffix) 125 | { 126 | return append(suffix, static_cast( strlen(suffix) )); 127 | } 128 | 129 | // += operator. Maps to append 130 | TiXmlString& operator += (char single) 131 | { 132 | return append(&single, 1); 133 | } 134 | 135 | // += operator. Maps to append 136 | TiXmlString& operator += (const TiXmlString & suffix) 137 | { 138 | return append(suffix.data(), suffix.length()); 139 | } 140 | 141 | 142 | // Convert a TiXmlString into a null-terminated char * 143 | const char * c_str () const { return rep_->str; } 144 | 145 | // Convert a TiXmlString into a char * (need not be null terminated). 146 | const char * data () const { return rep_->str; } 147 | 148 | // Return the length of a TiXmlString 149 | size_type length () const { return rep_->size; } 150 | 151 | // Alias for length() 152 | size_type size () const { return rep_->size; } 153 | 154 | // Checks if a TiXmlString is empty 155 | bool empty () const { return rep_->size == 0; } 156 | 157 | // Return capacity of string 158 | size_type capacity () const { return rep_->capacity; } 159 | 160 | 161 | // single char extraction 162 | const char& at (size_type index) const 163 | { 164 | assert( index < length() ); 165 | return rep_->str[ index ]; 166 | } 167 | 168 | // [] operator 169 | char& operator [] (size_type index) const 170 | { 171 | assert( index < length() ); 172 | return rep_->str[ index ]; 173 | } 174 | 175 | // find a char in a string. Return TiXmlString::npos if not found 176 | size_type find (char lookup) const 177 | { 178 | return find(lookup, 0); 179 | } 180 | 181 | // find a char in a string from an offset. Return TiXmlString::npos if not found 182 | size_type find (char tofind, size_type offset) const 183 | { 184 | if (offset >= length()) return npos; 185 | 186 | for (const char* p = c_str() + offset; *p != '\0'; ++p) 187 | { 188 | if (*p == tofind) return static_cast< size_type >( p - c_str() ); 189 | } 190 | return npos; 191 | } 192 | 193 | void clear () 194 | { 195 | //Lee: 196 | //The original was just too strange, though correct: 197 | // TiXmlString().swap(*this); 198 | //Instead use the quit & re-init: 199 | quit(); 200 | init(0,0); 201 | } 202 | 203 | /* Function to reserve a big amount of data when we know we'll need it. Be aware that this 204 | function DOES NOT clear the content of the TiXmlString if any exists. 205 | */ 206 | void reserve (size_type cap); 207 | 208 | TiXmlString& assign (const char* str, size_type len); 209 | 210 | TiXmlString& append (const char* str, size_type len); 211 | 212 | void swap (TiXmlString& other) 213 | { 214 | Rep* r = rep_; 215 | rep_ = other.rep_; 216 | other.rep_ = r; 217 | } 218 | 219 | private: 220 | 221 | void init(size_type sz) { init(sz, sz); } 222 | void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } 223 | char* start() const { return rep_->str; } 224 | char* finish() const { return rep_->str + rep_->size; } 225 | 226 | struct Rep 227 | { 228 | size_type size, capacity; 229 | char str[1]; 230 | }; 231 | 232 | void init(size_type sz, size_type cap) 233 | { 234 | if (cap) 235 | { 236 | // Lee: the original form: 237 | // rep_ = static_cast(operator new(sizeof(Rep) + cap)); 238 | // doesn't work in some cases of new being overloaded. Switching 239 | // to the normal allocation, although use an 'int' for systems 240 | // that are overly picky about structure alignment. 241 | const size_type bytesNeeded = sizeof(Rep) + cap; 242 | const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); 243 | rep_ = reinterpret_cast( new int[ intsNeeded ] ); 244 | 245 | rep_->str[ rep_->size = sz ] = '\0'; 246 | rep_->capacity = cap; 247 | } 248 | else 249 | { 250 | rep_ = &nullrep_; 251 | } 252 | } 253 | 254 | void quit() 255 | { 256 | if (rep_ != &nullrep_) 257 | { 258 | // The rep_ is really an array of ints. (see the allocator, above). 259 | // Cast it back before delete, so the compiler won't incorrectly call destructors. 260 | delete [] ( reinterpret_cast( rep_ ) ); 261 | } 262 | } 263 | 264 | Rep * rep_; 265 | static Rep nullrep_; 266 | 267 | } ; 268 | 269 | 270 | inline bool operator == (const TiXmlString & a, const TiXmlString & b) 271 | { 272 | return ( a.length() == b.length() ) // optimization on some platforms 273 | && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare 274 | } 275 | inline bool operator < (const TiXmlString & a, const TiXmlString & b) 276 | { 277 | return strcmp(a.c_str(), b.c_str()) < 0; 278 | } 279 | 280 | inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } 281 | inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } 282 | inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } 283 | inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } 284 | 285 | inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } 286 | inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } 287 | inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } 288 | inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } 289 | 290 | TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); 291 | TiXmlString operator + (const TiXmlString & a, const char* b); 292 | TiXmlString operator + (const char* a, const TiXmlString & b); 293 | 294 | 295 | /* 296 | TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. 297 | Only the operators that we need for TinyXML have been developped. 298 | */ 299 | class TiXmlOutStream : public TiXmlString 300 | { 301 | public : 302 | 303 | // TiXmlOutStream << operator. 304 | TiXmlOutStream & operator << (const TiXmlString & in) 305 | { 306 | *this += in; 307 | return *this; 308 | } 309 | 310 | // TiXmlOutStream << operator. 311 | TiXmlOutStream & operator << (const char * in) 312 | { 313 | *this += in; 314 | return *this; 315 | } 316 | 317 | } ; 318 | 319 | #endif // TIXML_STRING_INCLUDED 320 | #endif // TIXML_USE_STL 321 | -------------------------------------------------------------------------------- /Xml/TinyXml/tinyxmlparser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com) 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | #include "stdafx.h" 25 | #include 26 | #include 27 | 28 | #include "tinyxml.h" 29 | 30 | //#define DEBUG_PARSER 31 | #if defined( DEBUG_PARSER ) 32 | # if defined( DEBUG ) && defined( _MSC_VER ) 33 | # include 34 | # define TIXML_LOG OutputDebugString 35 | # else 36 | # define TIXML_LOG printf 37 | # endif 38 | #endif 39 | 40 | // Note tha "PutString" hardcodes the same list. This 41 | // is less flexible than it appears. Changing the entries 42 | // or order will break putstring. 43 | TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = 44 | { 45 | { "&", 5, '&' }, 46 | { "<", 4, '<' }, 47 | { ">", 4, '>' }, 48 | { """, 6, '\"' }, 49 | { "'", 6, '\'' } 50 | }; 51 | 52 | // Bunch of unicode info at: 53 | // http://www.unicode.org/faq/utf_bom.html 54 | // Including the basic of this table, which determines the #bytes in the 55 | // sequence from the lead byte. 1 placed for invalid sequences -- 56 | // although the result will be junk, pass it through as much as possible. 57 | // Beware of the non-characters in UTF-8: 58 | // ef bb bf (Microsoft "lead bytes") 59 | // ef bf be 60 | // ef bf bf 61 | 62 | const unsigned char TIXML_UTF_LEAD_0 = 0xefU; 63 | const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; 64 | const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; 65 | 66 | const int TiXmlBase::utf8ByteTable[256] = 67 | { 68 | // 0 1 2 3 4 5 6 7 8 9 a b c d e f 69 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 70 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 71 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 72 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 73 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 74 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 75 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 76 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range 77 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid 78 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 79 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 80 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 81 | 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte 82 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 83 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte 84 | 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid 85 | }; 86 | 87 | 88 | void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) 89 | { 90 | const unsigned long BYTE_MASK = 0xBF; 91 | const unsigned long BYTE_MARK = 0x80; 92 | const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 93 | 94 | if (input < 0x80) 95 | *length = 1; 96 | else if ( input < 0x800 ) 97 | *length = 2; 98 | else if ( input < 0x10000 ) 99 | *length = 3; 100 | else if ( input < 0x200000 ) 101 | *length = 4; 102 | else 103 | { *length = 0; return; } // This code won't covert this correctly anyway. 104 | 105 | output += *length; 106 | 107 | // Scary scary fall throughs. 108 | switch (*length) 109 | { 110 | case 4: 111 | --output; 112 | *output = (char)((input | BYTE_MARK) & BYTE_MASK); 113 | input >>= 6; 114 | case 3: 115 | --output; 116 | *output = (char)((input | BYTE_MARK) & BYTE_MASK); 117 | input >>= 6; 118 | case 2: 119 | --output; 120 | *output = (char)((input | BYTE_MARK) & BYTE_MASK); 121 | input >>= 6; 122 | case 1: 123 | --output; 124 | *output = (char)(input | FIRST_BYTE_MARK[*length]); 125 | } 126 | } 127 | 128 | 129 | /*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) 130 | { 131 | // This will only work for low-ascii, everything else is assumed to be a valid 132 | // letter. I'm not sure this is the best approach, but it is quite tricky trying 133 | // to figure out alhabetical vs. not across encoding. So take a very 134 | // conservative approach. 135 | 136 | // if ( encoding == TIXML_ENCODING_UTF8 ) 137 | // { 138 | if ( anyByte < 127 ) 139 | return isalpha( anyByte ); 140 | else 141 | return 1; // What else to do? The unicode set is huge...get the english ones right. 142 | // } 143 | // else 144 | // { 145 | // return isalpha( anyByte ); 146 | // } 147 | } 148 | 149 | 150 | /*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) 151 | { 152 | // This will only work for low-ascii, everything else is assumed to be a valid 153 | // letter. I'm not sure this is the best approach, but it is quite tricky trying 154 | // to figure out alhabetical vs. not across encoding. So take a very 155 | // conservative approach. 156 | 157 | // if ( encoding == TIXML_ENCODING_UTF8 ) 158 | // { 159 | if ( anyByte < 127 ) 160 | return isalnum( anyByte ); 161 | else 162 | return 1; // What else to do? The unicode set is huge...get the english ones right. 163 | // } 164 | // else 165 | // { 166 | // return isalnum( anyByte ); 167 | // } 168 | } 169 | 170 | 171 | class TiXmlParsingData 172 | { 173 | friend class TiXmlDocument; 174 | public: 175 | void Stamp( const char* now, TiXmlEncoding encoding ); 176 | 177 | const TiXmlCursor& Cursor() { return cursor; } 178 | 179 | private: 180 | // Only used by the document! 181 | TiXmlParsingData( const char* start, int _tabsize, int row, int col ) 182 | { 183 | assert( start ); 184 | stamp = start; 185 | tabsize = _tabsize; 186 | cursor.row = row; 187 | cursor.col = col; 188 | } 189 | 190 | TiXmlCursor cursor; 191 | const char* stamp; 192 | int tabsize; 193 | }; 194 | 195 | 196 | void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) 197 | { 198 | assert( now ); 199 | 200 | // Do nothing if the tabsize is 0. 201 | if ( tabsize < 1 ) 202 | { 203 | return; 204 | } 205 | 206 | // Get the current row, column. 207 | int row = cursor.row; 208 | int col = cursor.col; 209 | const char* p = stamp; 210 | assert( p ); 211 | 212 | while ( p < now ) 213 | { 214 | // Treat p as unsigned, so we have a happy compiler. 215 | const unsigned char* pU = (const unsigned char*)p; 216 | 217 | // Code contributed by Fletcher Dunn: (modified by lee) 218 | switch (*pU) { 219 | case 0: 220 | // We *should* never get here, but in case we do, don't 221 | // advance past the terminating null character, ever 222 | return; 223 | 224 | case '\r': 225 | // bump down to the next line 226 | ++row; 227 | col = 0; 228 | // Eat the character 229 | ++p; 230 | 231 | // Check for \r\n sequence, and treat this as a single character 232 | if (*p == '\n') { 233 | ++p; 234 | } 235 | break; 236 | 237 | case '\n': 238 | // bump down to the next line 239 | ++row; 240 | col = 0; 241 | 242 | // Eat the character 243 | ++p; 244 | 245 | // Check for \n\r sequence, and treat this as a single 246 | // character. (Yes, this bizarre thing does occur still 247 | // on some arcane platforms...) 248 | if (*p == '\r') { 249 | ++p; 250 | } 251 | break; 252 | 253 | case '\t': 254 | // Eat the character 255 | ++p; 256 | 257 | // Skip to next tab stop 258 | col = (col / tabsize + 1) * tabsize; 259 | break; 260 | 261 | case TIXML_UTF_LEAD_0: 262 | if ( encoding == TIXML_ENCODING_UTF8 ) 263 | { 264 | if ( *(p+1) && *(p+2) ) 265 | { 266 | // In these cases, don't advance the column. These are 267 | // 0-width spaces. 268 | if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) 269 | p += 3; 270 | else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) 271 | p += 3; 272 | else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) 273 | p += 3; 274 | else 275 | { p +=3; ++col; } // A normal character. 276 | } 277 | } 278 | else 279 | { 280 | ++p; 281 | ++col; 282 | } 283 | break; 284 | 285 | default: 286 | if ( encoding == TIXML_ENCODING_UTF8 ) 287 | { 288 | // Eat the 1 to 4 byte utf8 character. 289 | int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; 290 | if ( step == 0 ) 291 | step = 1; // Error case from bad encoding, but handle gracefully. 292 | p += step; 293 | 294 | // Just advance one column, of course. 295 | ++col; 296 | } 297 | else 298 | { 299 | ++p; 300 | ++col; 301 | } 302 | break; 303 | } 304 | } 305 | cursor.row = row; 306 | cursor.col = col; 307 | assert( cursor.row >= -1 ); 308 | assert( cursor.col >= -1 ); 309 | stamp = p; 310 | assert( stamp ); 311 | } 312 | 313 | 314 | const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) 315 | { 316 | if ( !p || !*p ) 317 | { 318 | return 0; 319 | } 320 | if ( encoding == TIXML_ENCODING_UTF8 ) 321 | { 322 | while ( *p ) 323 | { 324 | const unsigned char* pU = (const unsigned char*)p; 325 | 326 | // Skip the stupid Microsoft UTF-8 Byte order marks 327 | if ( *(pU+0)==TIXML_UTF_LEAD_0 328 | && *(pU+1)==TIXML_UTF_LEAD_1 329 | && *(pU+2)==TIXML_UTF_LEAD_2 ) 330 | { 331 | p += 3; 332 | continue; 333 | } 334 | else if(*(pU+0)==TIXML_UTF_LEAD_0 335 | && *(pU+1)==0xbfU 336 | && *(pU+2)==0xbeU ) 337 | { 338 | p += 3; 339 | continue; 340 | } 341 | else if(*(pU+0)==TIXML_UTF_LEAD_0 342 | && *(pU+1)==0xbfU 343 | && *(pU+2)==0xbfU ) 344 | { 345 | p += 3; 346 | continue; 347 | } 348 | 349 | if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. 350 | ++p; 351 | else 352 | break; 353 | } 354 | } 355 | else 356 | { 357 | while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) 358 | ++p; 359 | } 360 | 361 | return p; 362 | } 363 | 364 | #ifdef TIXML_USE_STL 365 | /*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) 366 | { 367 | for( ;; ) 368 | { 369 | if ( !in->good() ) return false; 370 | 371 | int c = in->peek(); 372 | // At this scope, we can't get to a document. So fail silently. 373 | if ( !IsWhiteSpace( c ) || c <= 0 ) 374 | return true; 375 | 376 | *tag += (char) in->get(); 377 | } 378 | } 379 | 380 | /*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) 381 | { 382 | //assert( character > 0 && character < 128 ); // else it won't work in utf-8 383 | while ( in->good() ) 384 | { 385 | int c = in->peek(); 386 | if ( c == character ) 387 | return true; 388 | if ( c <= 0 ) // Silent failure: can't get document at this scope 389 | return false; 390 | 391 | in->get(); 392 | *tag += (char) c; 393 | } 394 | return false; 395 | } 396 | #endif 397 | 398 | // One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The 399 | // "assign" optimization removes over 10% of the execution time. 400 | // 401 | const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) 402 | { 403 | // Oddly, not supported on some comilers, 404 | //name->clear(); 405 | // So use this: 406 | *name = ""; 407 | assert( p ); 408 | 409 | // Names start with letters or underscores. 410 | // Of course, in unicode, tinyxml has no idea what a letter *is*. The 411 | // algorithm is generous. 412 | // 413 | // After that, they can be letters, underscores, numbers, 414 | // hyphens, or colons. (Colons are valid ony for namespaces, 415 | // but tinyxml can't tell namespaces from names.) 416 | if ( p && *p 417 | && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) 418 | { 419 | const char* start = p; 420 | while( p && *p 421 | && ( IsAlphaNum( (unsigned char ) *p, encoding ) 422 | || *p == '_' 423 | || *p == '-' 424 | || *p == '.' 425 | || *p == ':' ) ) 426 | { 427 | //(*name) += *p; // expensive 428 | ++p; 429 | } 430 | if ( p-start > 0 ) { 431 | name->assign( start, p-start ); 432 | } 433 | return p; 434 | } 435 | return 0; 436 | } 437 | 438 | const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) 439 | { 440 | // Presume an entity, and pull it out. 441 | TIXML_STRING ent; 442 | int i; 443 | *length = 0; 444 | 445 | if ( *(p+1) && *(p+1) == '#' && *(p+2) ) 446 | { 447 | unsigned long ucs = 0; 448 | ptrdiff_t delta = 0; 449 | unsigned mult = 1; 450 | 451 | if ( *(p+2) == 'x' ) 452 | { 453 | // Hexadecimal. 454 | if ( !*(p+3) ) return 0; 455 | 456 | const char* q = p+3; 457 | q = strchr( q, ';' ); 458 | 459 | if ( !q || !*q ) return 0; 460 | 461 | delta = q-p; 462 | --q; 463 | 464 | while ( *q != 'x' ) 465 | { 466 | if ( *q >= '0' && *q <= '9' ) 467 | ucs += mult * (*q - '0'); 468 | else if ( *q >= 'a' && *q <= 'f' ) 469 | ucs += mult * (*q - 'a' + 10); 470 | else if ( *q >= 'A' && *q <= 'F' ) 471 | ucs += mult * (*q - 'A' + 10 ); 472 | else 473 | return 0; 474 | mult *= 16; 475 | --q; 476 | } 477 | } 478 | else 479 | { 480 | // Decimal. 481 | if ( !*(p+2) ) return 0; 482 | 483 | const char* q = p+2; 484 | q = strchr( q, ';' ); 485 | 486 | if ( !q || !*q ) return 0; 487 | 488 | delta = q-p; 489 | --q; 490 | 491 | while ( *q != '#' ) 492 | { 493 | if ( *q >= '0' && *q <= '9' ) 494 | ucs += mult * (*q - '0'); 495 | else 496 | return 0; 497 | mult *= 10; 498 | --q; 499 | } 500 | } 501 | if ( encoding == TIXML_ENCODING_UTF8 ) 502 | { 503 | // convert the UCS to UTF-8 504 | ConvertUTF32ToUTF8( ucs, value, length ); 505 | } 506 | else 507 | { 508 | *value = (char)ucs; 509 | *length = 1; 510 | } 511 | return p + delta + 1; 512 | } 513 | 514 | // Now try to match it. 515 | for( i=0; iappend( cArr, len ); 594 | } 595 | } 596 | else 597 | { 598 | bool whitespace = false; 599 | 600 | // Remove leading white space: 601 | p = SkipWhiteSpace( p, encoding ); 602 | while ( p && *p 603 | && !StringEqual( p, endTag, caseInsensitive, encoding ) ) 604 | { 605 | if ( *p == '\r' || *p == '\n' ) 606 | { 607 | whitespace = true; 608 | ++p; 609 | } 610 | else if ( IsWhiteSpace( *p ) ) 611 | { 612 | whitespace = true; 613 | ++p; 614 | } 615 | else 616 | { 617 | // If we've found whitespace, add it before the 618 | // new character. Any whitespace just becomes a space. 619 | if ( whitespace ) 620 | { 621 | (*text) += ' '; 622 | whitespace = false; 623 | } 624 | int len; 625 | char cArr[4] = { 0, 0, 0, 0 }; 626 | p = GetChar( p, cArr, &len, encoding ); 627 | if ( len == 1 ) 628 | (*text) += cArr[0]; // more efficient 629 | else 630 | text->append( cArr, len ); 631 | } 632 | } 633 | } 634 | if ( p ) 635 | p += strlen( endTag ); 636 | return p; 637 | } 638 | 639 | #ifdef TIXML_USE_STL 640 | 641 | void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) 642 | { 643 | // The basic issue with a document is that we don't know what we're 644 | // streaming. Read something presumed to be a tag (and hope), then 645 | // identify it, and call the appropriate stream method on the tag. 646 | // 647 | // This "pre-streaming" will never read the closing ">" so the 648 | // sub-tag can orient itself. 649 | 650 | if ( !StreamTo( in, '<', tag ) ) 651 | { 652 | SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 653 | return; 654 | } 655 | 656 | while ( in->good() ) 657 | { 658 | int tagIndex = (int) tag->length(); 659 | while ( in->good() && in->peek() != '>' ) 660 | { 661 | int c = in->get(); 662 | if ( c <= 0 ) 663 | { 664 | SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 665 | break; 666 | } 667 | (*tag) += (char) c; 668 | } 669 | 670 | if ( in->good() ) 671 | { 672 | // We now have something we presume to be a node of 673 | // some sort. Identify it, and call the node to 674 | // continue streaming. 675 | TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); 676 | 677 | if ( node ) 678 | { 679 | node->StreamIn( in, tag ); 680 | bool isElement = node->ToElement() != 0; 681 | delete node; 682 | node = 0; 683 | 684 | // If this is the root element, we're done. Parsing will be 685 | // done by the >> operator. 686 | if ( isElement ) 687 | { 688 | return; 689 | } 690 | } 691 | else 692 | { 693 | SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); 694 | return; 695 | } 696 | } 697 | } 698 | // We should have returned sooner. 699 | SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); 700 | } 701 | 702 | #endif 703 | 704 | const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) 705 | { 706 | ClearError(); 707 | 708 | // Parse away, at the document level. Since a document 709 | // contains nothing but other tags, most of what happens 710 | // here is skipping white space. 711 | if ( !p || !*p ) 712 | { 713 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 714 | return 0; 715 | } 716 | 717 | // Note that, for a document, this needs to come 718 | // before the while space skip, so that parsing 719 | // starts from the pointer we are given. 720 | location.Clear(); 721 | if ( prevData ) 722 | { 723 | location.row = prevData->cursor.row; 724 | location.col = prevData->cursor.col; 725 | } 726 | else 727 | { 728 | location.row = 0; 729 | location.col = 0; 730 | } 731 | TiXmlParsingData data( p, TabSize(), location.row, location.col ); 732 | location = data.Cursor(); 733 | 734 | if ( encoding == TIXML_ENCODING_UNKNOWN ) 735 | { 736 | // Check for the Microsoft UTF-8 lead bytes. 737 | const unsigned char* pU = (const unsigned char*)p; 738 | if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 739 | && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 740 | && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) 741 | { 742 | encoding = TIXML_ENCODING_UTF8; 743 | useMicrosoftBOM = true; 744 | } 745 | } 746 | 747 | p = SkipWhiteSpace( p, encoding ); 748 | if ( !p ) 749 | { 750 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 751 | return 0; 752 | } 753 | 754 | while ( p && *p ) 755 | { 756 | TiXmlNode* node = Identify( p, encoding ); 757 | if ( node ) 758 | { 759 | p = node->Parse( p, &data, encoding ); 760 | LinkEndChild( node ); 761 | } 762 | else 763 | { 764 | break; 765 | } 766 | 767 | // Did we get encoding info? 768 | if ( encoding == TIXML_ENCODING_UNKNOWN 769 | && node->ToDeclaration() ) 770 | { 771 | TiXmlDeclaration* dec = node->ToDeclaration(); 772 | const char* enc = dec->Encoding(); 773 | assert( enc ); 774 | 775 | if ( *enc == 0 ) 776 | encoding = TIXML_ENCODING_UTF8; 777 | else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) 778 | encoding = TIXML_ENCODING_UTF8; 779 | else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) 780 | encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice 781 | else 782 | encoding = TIXML_ENCODING_LEGACY; 783 | } 784 | 785 | p = SkipWhiteSpace( p, encoding ); 786 | } 787 | 788 | // Was this empty? 789 | if ( !firstChild ) { 790 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); 791 | return 0; 792 | } 793 | 794 | // All is well. 795 | return p; 796 | } 797 | 798 | void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) 799 | { 800 | // The first error in a chain is more accurate - don't set again! 801 | if ( error ) 802 | return; 803 | 804 | assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); 805 | error = true; 806 | errorId = err; 807 | errorDesc = errorString[ errorId ]; 808 | 809 | errorLocation.Clear(); 810 | if ( pError && data ) 811 | { 812 | data->Stamp( pError, encoding ); 813 | errorLocation = data->Cursor(); 814 | } 815 | } 816 | 817 | 818 | TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) 819 | { 820 | TiXmlNode* returnNode = 0; 821 | 822 | p = SkipWhiteSpace( p, encoding ); 823 | if( !p || !*p || *p != '<' ) 824 | { 825 | return 0; 826 | } 827 | 828 | TiXmlDocument* doc = GetDocument(); 829 | p = SkipWhiteSpace( p, encoding ); 830 | 831 | if ( !p || !*p ) 832 | { 833 | return 0; 834 | } 835 | 836 | // What is this thing? 837 | // - Elements start with a letter or underscore, but xml is reserved. 838 | // - Comments: "; 1345 | 1346 | if ( !StringEqual( p, startTag, false, encoding ) ) 1347 | { 1348 | document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); 1349 | return 0; 1350 | } 1351 | p += strlen( startTag ); 1352 | p = ReadText( p, &value, false, endTag, false, encoding ); 1353 | return p; 1354 | } 1355 | 1356 | 1357 | const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) 1358 | { 1359 | p = SkipWhiteSpace( p, encoding ); 1360 | if ( !p || !*p ) return 0; 1361 | 1362 | // int tabsize = 4; 1363 | // if ( document ) 1364 | // tabsize = document->TabSize(); 1365 | 1366 | if ( data ) 1367 | { 1368 | data->Stamp( p, encoding ); 1369 | location = data->Cursor(); 1370 | } 1371 | // Read the name, the '=' and the value. 1372 | const char* pErr = p; 1373 | p = ReadName( p, &name, encoding ); 1374 | if ( !p || !*p ) 1375 | { 1376 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); 1377 | return 0; 1378 | } 1379 | p = SkipWhiteSpace( p, encoding ); 1380 | if ( !p || !*p || *p != '=' ) 1381 | { 1382 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1383 | return 0; 1384 | } 1385 | 1386 | ++p; // skip '=' 1387 | p = SkipWhiteSpace( p, encoding ); 1388 | if ( !p || !*p ) 1389 | { 1390 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1391 | return 0; 1392 | } 1393 | 1394 | const char* end; 1395 | const char SINGLE_QUOTE = '\''; 1396 | const char DOUBLE_QUOTE = '\"'; 1397 | 1398 | if ( *p == SINGLE_QUOTE ) 1399 | { 1400 | ++p; 1401 | end = "\'"; // single quote in string 1402 | p = ReadText( p, &value, false, end, false, encoding ); 1403 | } 1404 | else if ( *p == DOUBLE_QUOTE ) 1405 | { 1406 | ++p; 1407 | end = "\""; // double quote in string 1408 | p = ReadText( p, &value, false, end, false, encoding ); 1409 | } 1410 | else 1411 | { 1412 | // All attribute values should be in single or double quotes. 1413 | // But this is such a common error that the parser will try 1414 | // its best, even without them. 1415 | value = ""; 1416 | while ( p && *p // existence 1417 | && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace 1418 | && *p != '/' && *p != '>' ) // tag end 1419 | { 1420 | if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { 1421 | // [ 1451649 ] Attribute values with trailing quotes not handled correctly 1422 | // We did not have an opening quote but seem to have a 1423 | // closing one. Give up and throw an error. 1424 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1425 | return 0; 1426 | } 1427 | value += *p; 1428 | ++p; 1429 | } 1430 | } 1431 | return p; 1432 | } 1433 | 1434 | #ifdef TIXML_USE_STL 1435 | void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) 1436 | { 1437 | while ( in->good() ) 1438 | { 1439 | int c = in->peek(); 1440 | if ( !cdata && (c == '<' ) ) 1441 | { 1442 | return; 1443 | } 1444 | if ( c <= 0 ) 1445 | { 1446 | TiXmlDocument* document = GetDocument(); 1447 | if ( document ) 1448 | document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 1449 | return; 1450 | } 1451 | 1452 | (*tag) += (char) c; 1453 | in->get(); // "commits" the peek made above 1454 | 1455 | if ( cdata && c == '>' && tag->size() >= 3 ) { 1456 | size_t len = tag->size(); 1457 | if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { 1458 | // terminator of cdata. 1459 | return; 1460 | } 1461 | } 1462 | } 1463 | } 1464 | #endif 1465 | 1466 | const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) 1467 | { 1468 | value = ""; 1469 | TiXmlDocument* document = GetDocument(); 1470 | 1471 | if ( data ) 1472 | { 1473 | data->Stamp( p, encoding ); 1474 | location = data->Cursor(); 1475 | } 1476 | 1477 | const char* const startTag = ""; 1479 | 1480 | if ( cdata || StringEqual( p, startTag, false, encoding ) ) 1481 | { 1482 | cdata = true; 1483 | 1484 | if ( !StringEqual( p, startTag, false, encoding ) ) 1485 | { 1486 | document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); 1487 | return 0; 1488 | } 1489 | p += strlen( startTag ); 1490 | 1491 | // Keep all the white space, ignore the encoding, etc. 1492 | while ( p && *p 1493 | && !StringEqual( p, endTag, false, encoding ) 1494 | ) 1495 | { 1496 | value += *p; 1497 | ++p; 1498 | } 1499 | 1500 | TIXML_STRING dummy; 1501 | p = ReadText( p, &dummy, false, endTag, false, encoding ); 1502 | return p; 1503 | } 1504 | else 1505 | { 1506 | bool ignoreWhite = true; 1507 | 1508 | const char* end = "<"; 1509 | p = ReadText( p, &value, ignoreWhite, end, false, encoding ); 1510 | if ( p ) 1511 | return p-1; // don't truncate the '<' 1512 | return 0; 1513 | } 1514 | } 1515 | 1516 | #ifdef TIXML_USE_STL 1517 | void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) 1518 | { 1519 | while ( in->good() ) 1520 | { 1521 | int c = in->get(); 1522 | if ( c <= 0 ) 1523 | { 1524 | TiXmlDocument* document = GetDocument(); 1525 | if ( document ) 1526 | document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 1527 | return; 1528 | } 1529 | (*tag) += (char) c; 1530 | 1531 | if ( c == '>' ) 1532 | { 1533 | // All is well. 1534 | return; 1535 | } 1536 | } 1537 | } 1538 | #endif 1539 | 1540 | const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) 1541 | { 1542 | p = SkipWhiteSpace( p, _encoding ); 1543 | // Find the beginning, find the end, and look for 1544 | // the stuff in-between. 1545 | TiXmlDocument* document = GetDocument(); 1546 | if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); 1549 | return 0; 1550 | } 1551 | if ( data ) 1552 | { 1553 | data->Stamp( p, _encoding ); 1554 | location = data->Cursor(); 1555 | } 1556 | p += 5; 1557 | 1558 | version = ""; 1559 | encoding = ""; 1560 | standalone = ""; 1561 | 1562 | while ( p && *p ) 1563 | { 1564 | if ( *p == '>' ) 1565 | { 1566 | ++p; 1567 | return p; 1568 | } 1569 | 1570 | p = SkipWhiteSpace( p, _encoding ); 1571 | if ( StringEqual( p, "version", true, _encoding ) ) 1572 | { 1573 | TiXmlAttribute attrib; 1574 | p = attrib.Parse( p, data, _encoding ); 1575 | version = attrib.Value(); 1576 | } 1577 | else if ( StringEqual( p, "encoding", true, _encoding ) ) 1578 | { 1579 | TiXmlAttribute attrib; 1580 | p = attrib.Parse( p, data, _encoding ); 1581 | encoding = attrib.Value(); 1582 | } 1583 | else if ( StringEqual( p, "standalone", true, _encoding ) ) 1584 | { 1585 | TiXmlAttribute attrib; 1586 | p = attrib.Parse( p, data, _encoding ); 1587 | standalone = attrib.Value(); 1588 | } 1589 | else 1590 | { 1591 | // Read over whatever it is. 1592 | while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) 1593 | ++p; 1594 | } 1595 | } 1596 | return 0; 1597 | } 1598 | 1599 | bool TiXmlText::Blank() const 1600 | { 1601 | for ( unsigned i=0; i 26 | #include 27 | 28 | #include "tinyxml.h" 29 | 30 | //#define DEBUG_PARSER 31 | #if defined( DEBUG_PARSER ) 32 | # if defined( DEBUG ) && defined( _MSC_VER ) 33 | # include 34 | # define TIXML_LOG OutputDebugString 35 | # else 36 | # define TIXML_LOG printf 37 | # endif 38 | #endif 39 | 40 | // Note tha "PutString" hardcodes the same list. This 41 | // is less flexible than it appears. Changing the entries 42 | // or order will break putstring. 43 | TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = 44 | { 45 | { "&", 5, '&' }, 46 | { "<", 4, '<' }, 47 | { ">", 4, '>' }, 48 | { """, 6, '\"' }, 49 | { "'", 6, '\'' } 50 | }; 51 | 52 | // Bunch of unicode info at: 53 | // http://www.unicode.org/faq/utf_bom.html 54 | // Including the basic of this table, which determines the #bytes in the 55 | // sequence from the lead byte. 1 placed for invalid sequences -- 56 | // although the result will be junk, pass it through as much as possible. 57 | // Beware of the non-characters in UTF-8: 58 | // ef bb bf (Microsoft "lead bytes") 59 | // ef bf be 60 | // ef bf bf 61 | 62 | const unsigned char TIXML_UTF_LEAD_0 = 0xefU; 63 | const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; 64 | const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; 65 | 66 | const int TiXmlBase::utf8ByteTable[256] = 67 | { 68 | // 0 1 2 3 4 5 6 7 8 9 a b c d e f 69 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 70 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 71 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 72 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 73 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 74 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 75 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 76 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range 77 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid 78 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 79 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 80 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 81 | 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte 82 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 83 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte 84 | 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid 85 | }; 86 | 87 | 88 | void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) 89 | { 90 | const unsigned long BYTE_MASK = 0xBF; 91 | const unsigned long BYTE_MARK = 0x80; 92 | const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; 93 | 94 | if (input < 0x80) 95 | *length = 1; 96 | else if ( input < 0x800 ) 97 | *length = 2; 98 | else if ( input < 0x10000 ) 99 | *length = 3; 100 | else if ( input < 0x200000 ) 101 | *length = 4; 102 | else 103 | { *length = 0; return; } // This code won't covert this correctly anyway. 104 | 105 | output += *length; 106 | 107 | // Scary scary fall throughs. 108 | switch (*length) 109 | { 110 | case 4: 111 | --output; 112 | *output = (char)((input | BYTE_MARK) & BYTE_MASK); 113 | input >>= 6; 114 | case 3: 115 | --output; 116 | *output = (char)((input | BYTE_MARK) & BYTE_MASK); 117 | input >>= 6; 118 | case 2: 119 | --output; 120 | *output = (char)((input | BYTE_MARK) & BYTE_MASK); 121 | input >>= 6; 122 | case 1: 123 | --output; 124 | *output = (char)(input | FIRST_BYTE_MARK[*length]); 125 | } 126 | } 127 | 128 | 129 | /*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) 130 | { 131 | // This will only work for low-ascii, everything else is assumed to be a valid 132 | // letter. I'm not sure this is the best approach, but it is quite tricky trying 133 | // to figure out alhabetical vs. not across encoding. So take a very 134 | // conservative approach. 135 | 136 | // if ( encoding == TIXML_ENCODING_UTF8 ) 137 | // { 138 | if ( anyByte < 127 ) 139 | return isalpha( anyByte ); 140 | else 141 | return 1; // What else to do? The unicode set is huge...get the english ones right. 142 | // } 143 | // else 144 | // { 145 | // return isalpha( anyByte ); 146 | // } 147 | } 148 | 149 | 150 | /*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) 151 | { 152 | // This will only work for low-ascii, everything else is assumed to be a valid 153 | // letter. I'm not sure this is the best approach, but it is quite tricky trying 154 | // to figure out alhabetical vs. not across encoding. So take a very 155 | // conservative approach. 156 | 157 | // if ( encoding == TIXML_ENCODING_UTF8 ) 158 | // { 159 | if ( anyByte < 127 ) 160 | return isalnum( anyByte ); 161 | else 162 | return 1; // What else to do? The unicode set is huge...get the english ones right. 163 | // } 164 | // else 165 | // { 166 | // return isalnum( anyByte ); 167 | // } 168 | } 169 | 170 | 171 | class TiXmlParsingData 172 | { 173 | friend class TiXmlDocument; 174 | public: 175 | void Stamp( const char* now, TiXmlEncoding encoding ); 176 | 177 | const TiXmlCursor& Cursor() { return cursor; } 178 | 179 | private: 180 | // Only used by the document! 181 | TiXmlParsingData( const char* start, int _tabsize, int row, int col ) 182 | { 183 | assert( start ); 184 | stamp = start; 185 | tabsize = _tabsize; 186 | cursor.row = row; 187 | cursor.col = col; 188 | } 189 | 190 | TiXmlCursor cursor; 191 | const char* stamp; 192 | int tabsize; 193 | }; 194 | 195 | 196 | void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) 197 | { 198 | assert( now ); 199 | 200 | // Do nothing if the tabsize is 0. 201 | if ( tabsize < 1 ) 202 | { 203 | return; 204 | } 205 | 206 | // Get the current row, column. 207 | int row = cursor.row; 208 | int col = cursor.col; 209 | const char* p = stamp; 210 | assert( p ); 211 | 212 | while ( p < now ) 213 | { 214 | // Treat p as unsigned, so we have a happy compiler. 215 | const unsigned char* pU = (const unsigned char*)p; 216 | 217 | // Code contributed by Fletcher Dunn: (modified by lee) 218 | switch (*pU) { 219 | case 0: 220 | // We *should* never get here, but in case we do, don't 221 | // advance past the terminating null character, ever 222 | return; 223 | 224 | case '\r': 225 | // bump down to the next line 226 | ++row; 227 | col = 0; 228 | // Eat the character 229 | ++p; 230 | 231 | // Check for \r\n sequence, and treat this as a single character 232 | if (*p == '\n') { 233 | ++p; 234 | } 235 | break; 236 | 237 | case '\n': 238 | // bump down to the next line 239 | ++row; 240 | col = 0; 241 | 242 | // Eat the character 243 | ++p; 244 | 245 | // Check for \n\r sequence, and treat this as a single 246 | // character. (Yes, this bizarre thing does occur still 247 | // on some arcane platforms...) 248 | if (*p == '\r') { 249 | ++p; 250 | } 251 | break; 252 | 253 | case '\t': 254 | // Eat the character 255 | ++p; 256 | 257 | // Skip to next tab stop 258 | col = (col / tabsize + 1) * tabsize; 259 | break; 260 | 261 | case TIXML_UTF_LEAD_0: 262 | if ( encoding == TIXML_ENCODING_UTF8 ) 263 | { 264 | if ( *(p+1) && *(p+2) ) 265 | { 266 | // In these cases, don't advance the column. These are 267 | // 0-width spaces. 268 | if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) 269 | p += 3; 270 | else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) 271 | p += 3; 272 | else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) 273 | p += 3; 274 | else 275 | { p +=3; ++col; } // A normal character. 276 | } 277 | } 278 | else 279 | { 280 | ++p; 281 | ++col; 282 | } 283 | break; 284 | 285 | default: 286 | if ( encoding == TIXML_ENCODING_UTF8 ) 287 | { 288 | // Eat the 1 to 4 byte utf8 character. 289 | int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; 290 | if ( step == 0 ) 291 | step = 1; // Error case from bad encoding, but handle gracefully. 292 | p += step; 293 | 294 | // Just advance one column, of course. 295 | ++col; 296 | } 297 | else 298 | { 299 | ++p; 300 | ++col; 301 | } 302 | break; 303 | } 304 | } 305 | cursor.row = row; 306 | cursor.col = col; 307 | assert( cursor.row >= -1 ); 308 | assert( cursor.col >= -1 ); 309 | stamp = p; 310 | assert( stamp ); 311 | } 312 | 313 | 314 | const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) 315 | { 316 | if ( !p || !*p ) 317 | { 318 | return 0; 319 | } 320 | if ( encoding == TIXML_ENCODING_UTF8 ) 321 | { 322 | while ( *p ) 323 | { 324 | const unsigned char* pU = (const unsigned char*)p; 325 | 326 | // Skip the stupid Microsoft UTF-8 Byte order marks 327 | if ( *(pU+0)==TIXML_UTF_LEAD_0 328 | && *(pU+1)==TIXML_UTF_LEAD_1 329 | && *(pU+2)==TIXML_UTF_LEAD_2 ) 330 | { 331 | p += 3; 332 | continue; 333 | } 334 | else if(*(pU+0)==TIXML_UTF_LEAD_0 335 | && *(pU+1)==0xbfU 336 | && *(pU+2)==0xbeU ) 337 | { 338 | p += 3; 339 | continue; 340 | } 341 | else if(*(pU+0)==TIXML_UTF_LEAD_0 342 | && *(pU+1)==0xbfU 343 | && *(pU+2)==0xbfU ) 344 | { 345 | p += 3; 346 | continue; 347 | } 348 | 349 | if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. 350 | ++p; 351 | else 352 | break; 353 | } 354 | } 355 | else 356 | { 357 | while ( *p && IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) 358 | ++p; 359 | } 360 | 361 | return p; 362 | } 363 | 364 | #ifdef TIXML_USE_STL 365 | /*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) 366 | { 367 | for( ;; ) 368 | { 369 | if ( !in->good() ) return false; 370 | 371 | int c = in->peek(); 372 | // At this scope, we can't get to a document. So fail silently. 373 | if ( !IsWhiteSpace( c ) || c <= 0 ) 374 | return true; 375 | 376 | *tag += (char) in->get(); 377 | } 378 | } 379 | 380 | /*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) 381 | { 382 | //assert( character > 0 && character < 128 ); // else it won't work in utf-8 383 | while ( in->good() ) 384 | { 385 | int c = in->peek(); 386 | if ( c == character ) 387 | return true; 388 | if ( c <= 0 ) // Silent failure: can't get document at this scope 389 | return false; 390 | 391 | in->get(); 392 | *tag += (char) c; 393 | } 394 | return false; 395 | } 396 | #endif 397 | 398 | // One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The 399 | // "assign" optimization removes over 10% of the execution time. 400 | // 401 | const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) 402 | { 403 | // Oddly, not supported on some comilers, 404 | //name->clear(); 405 | // So use this: 406 | *name = ""; 407 | assert( p ); 408 | 409 | // Names start with letters or underscores. 410 | // Of course, in unicode, tinyxml has no idea what a letter *is*. The 411 | // algorithm is generous. 412 | // 413 | // After that, they can be letters, underscores, numbers, 414 | // hyphens, or colons. (Colons are valid ony for namespaces, 415 | // but tinyxml can't tell namespaces from names.) 416 | if ( p && *p 417 | && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) 418 | { 419 | const char* start = p; 420 | while( p && *p 421 | && ( IsAlphaNum( (unsigned char ) *p, encoding ) 422 | || *p == '_' 423 | || *p == '-' 424 | || *p == '.' 425 | || *p == ':' ) ) 426 | { 427 | //(*name) += *p; // expensive 428 | ++p; 429 | } 430 | if ( p-start > 0 ) { 431 | name->assign( start, p-start ); 432 | } 433 | return p; 434 | } 435 | return 0; 436 | } 437 | 438 | const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) 439 | { 440 | // Presume an entity, and pull it out. 441 | TIXML_STRING ent; 442 | int i; 443 | *length = 0; 444 | 445 | if ( *(p+1) && *(p+1) == '#' && *(p+2) ) 446 | { 447 | unsigned long ucs = 0; 448 | ptrdiff_t delta = 0; 449 | unsigned mult = 1; 450 | 451 | if ( *(p+2) == 'x' ) 452 | { 453 | // Hexadecimal. 454 | if ( !*(p+3) ) return 0; 455 | 456 | const char* q = p+3; 457 | q = strchr( q, ';' ); 458 | 459 | if ( !q || !*q ) return 0; 460 | 461 | delta = q-p; 462 | --q; 463 | 464 | while ( *q != 'x' ) 465 | { 466 | if ( *q >= '0' && *q <= '9' ) 467 | ucs += mult * (*q - '0'); 468 | else if ( *q >= 'a' && *q <= 'f' ) 469 | ucs += mult * (*q - 'a' + 10); 470 | else if ( *q >= 'A' && *q <= 'F' ) 471 | ucs += mult * (*q - 'A' + 10 ); 472 | else 473 | return 0; 474 | mult *= 16; 475 | --q; 476 | } 477 | } 478 | else 479 | { 480 | // Decimal. 481 | if ( !*(p+2) ) return 0; 482 | 483 | const char* q = p+2; 484 | q = strchr( q, ';' ); 485 | 486 | if ( !q || !*q ) return 0; 487 | 488 | delta = q-p; 489 | --q; 490 | 491 | while ( *q != '#' ) 492 | { 493 | if ( *q >= '0' && *q <= '9' ) 494 | ucs += mult * (*q - '0'); 495 | else 496 | return 0; 497 | mult *= 10; 498 | --q; 499 | } 500 | } 501 | if ( encoding == TIXML_ENCODING_UTF8 ) 502 | { 503 | // convert the UCS to UTF-8 504 | ConvertUTF32ToUTF8( ucs, value, length ); 505 | } 506 | else 507 | { 508 | *value = (char)ucs; 509 | *length = 1; 510 | } 511 | return p + delta + 1; 512 | } 513 | 514 | // Now try to match it. 515 | for( i=0; iappend( cArr, len ); 594 | } 595 | } 596 | else 597 | { 598 | bool whitespace = false; 599 | 600 | // Remove leading white space: 601 | p = SkipWhiteSpace( p, encoding ); 602 | while ( p && *p 603 | && !StringEqual( p, endTag, caseInsensitive, encoding ) ) 604 | { 605 | if ( *p == '\r' || *p == '\n' ) 606 | { 607 | whitespace = true; 608 | ++p; 609 | } 610 | else if ( IsWhiteSpace( *p ) ) 611 | { 612 | whitespace = true; 613 | ++p; 614 | } 615 | else 616 | { 617 | // If we've found whitespace, add it before the 618 | // new character. Any whitespace just becomes a space. 619 | if ( whitespace ) 620 | { 621 | (*text) += ' '; 622 | whitespace = false; 623 | } 624 | int len; 625 | char cArr[4] = { 0, 0, 0, 0 }; 626 | p = GetChar( p, cArr, &len, encoding ); 627 | if ( len == 1 ) 628 | (*text) += cArr[0]; // more efficient 629 | else 630 | text->append( cArr, len ); 631 | } 632 | } 633 | } 634 | if ( p ) 635 | p += strlen( endTag ); 636 | return p; 637 | } 638 | 639 | #ifdef TIXML_USE_STL 640 | 641 | void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) 642 | { 643 | // The basic issue with a document is that we don't know what we're 644 | // streaming. Read something presumed to be a tag (and hope), then 645 | // identify it, and call the appropriate stream method on the tag. 646 | // 647 | // This "pre-streaming" will never read the closing ">" so the 648 | // sub-tag can orient itself. 649 | 650 | if ( !StreamTo( in, '<', tag ) ) 651 | { 652 | SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 653 | return; 654 | } 655 | 656 | while ( in->good() ) 657 | { 658 | int tagIndex = (int) tag->length(); 659 | while ( in->good() && in->peek() != '>' ) 660 | { 661 | int c = in->get(); 662 | if ( c <= 0 ) 663 | { 664 | SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 665 | break; 666 | } 667 | (*tag) += (char) c; 668 | } 669 | 670 | if ( in->good() ) 671 | { 672 | // We now have something we presume to be a node of 673 | // some sort. Identify it, and call the node to 674 | // continue streaming. 675 | TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); 676 | 677 | if ( node ) 678 | { 679 | node->StreamIn( in, tag ); 680 | bool isElement = node->ToElement() != 0; 681 | delete node; 682 | node = 0; 683 | 684 | // If this is the root element, we're done. Parsing will be 685 | // done by the >> operator. 686 | if ( isElement ) 687 | { 688 | return; 689 | } 690 | } 691 | else 692 | { 693 | SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); 694 | return; 695 | } 696 | } 697 | } 698 | // We should have returned sooner. 699 | SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); 700 | } 701 | 702 | #endif 703 | 704 | const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) 705 | { 706 | ClearError(); 707 | 708 | // Parse away, at the document level. Since a document 709 | // contains nothing but other tags, most of what happens 710 | // here is skipping white space. 711 | if ( !p || !*p ) 712 | { 713 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 714 | return 0; 715 | } 716 | 717 | // Note that, for a document, this needs to come 718 | // before the while space skip, so that parsing 719 | // starts from the pointer we are given. 720 | location.Clear(); 721 | if ( prevData ) 722 | { 723 | location.row = prevData->cursor.row; 724 | location.col = prevData->cursor.col; 725 | } 726 | else 727 | { 728 | location.row = 0; 729 | location.col = 0; 730 | } 731 | TiXmlParsingData data( p, TabSize(), location.row, location.col ); 732 | location = data.Cursor(); 733 | 734 | if ( encoding == TIXML_ENCODING_UNKNOWN ) 735 | { 736 | // Check for the Microsoft UTF-8 lead bytes. 737 | const unsigned char* pU = (const unsigned char*)p; 738 | if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 739 | && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 740 | && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) 741 | { 742 | encoding = TIXML_ENCODING_UTF8; 743 | useMicrosoftBOM = true; 744 | } 745 | } 746 | 747 | p = SkipWhiteSpace( p, encoding ); 748 | if ( !p ) 749 | { 750 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 751 | return 0; 752 | } 753 | 754 | while ( p && *p ) 755 | { 756 | TiXmlNode* node = Identify( p, encoding ); 757 | if ( node ) 758 | { 759 | p = node->Parse( p, &data, encoding ); 760 | LinkEndChild( node ); 761 | } 762 | else 763 | { 764 | break; 765 | } 766 | 767 | // Did we get encoding info? 768 | if ( encoding == TIXML_ENCODING_UNKNOWN 769 | && node->ToDeclaration() ) 770 | { 771 | TiXmlDeclaration* dec = node->ToDeclaration(); 772 | const char* enc = dec->Encoding(); 773 | assert( enc ); 774 | 775 | if ( *enc == 0 ) 776 | encoding = TIXML_ENCODING_UTF8; 777 | else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) 778 | encoding = TIXML_ENCODING_UTF8; 779 | else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) 780 | encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice 781 | else 782 | encoding = TIXML_ENCODING_LEGACY; 783 | } 784 | 785 | p = SkipWhiteSpace( p, encoding ); 786 | } 787 | 788 | // Was this empty? 789 | if ( !firstChild ) { 790 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); 791 | return 0; 792 | } 793 | 794 | // All is well. 795 | return p; 796 | } 797 | 798 | void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) 799 | { 800 | // The first error in a chain is more accurate - don't set again! 801 | if ( error ) 802 | return; 803 | 804 | assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); 805 | error = true; 806 | errorId = err; 807 | errorDesc = errorString[ errorId ]; 808 | 809 | errorLocation.Clear(); 810 | if ( pError && data ) 811 | { 812 | data->Stamp( pError, encoding ); 813 | errorLocation = data->Cursor(); 814 | } 815 | } 816 | 817 | 818 | TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) 819 | { 820 | TiXmlNode* returnNode = 0; 821 | 822 | p = SkipWhiteSpace( p, encoding ); 823 | if( !p || !*p || *p != '<' ) 824 | { 825 | return 0; 826 | } 827 | 828 | TiXmlDocument* doc = GetDocument(); 829 | p = SkipWhiteSpace( p, encoding ); 830 | 831 | if ( !p || !*p ) 832 | { 833 | return 0; 834 | } 835 | 836 | // What is this thing? 837 | // - Elements start with a letter or underscore, but xml is reserved. 838 | // - Comments: "; 1345 | 1346 | if ( !StringEqual( p, startTag, false, encoding ) ) 1347 | { 1348 | document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); 1349 | return 0; 1350 | } 1351 | p += strlen( startTag ); 1352 | p = ReadText( p, &value, false, endTag, false, encoding ); 1353 | return p; 1354 | } 1355 | 1356 | 1357 | const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) 1358 | { 1359 | p = SkipWhiteSpace( p, encoding ); 1360 | if ( !p || !*p ) return 0; 1361 | 1362 | // int tabsize = 4; 1363 | // if ( document ) 1364 | // tabsize = document->TabSize(); 1365 | 1366 | if ( data ) 1367 | { 1368 | data->Stamp( p, encoding ); 1369 | location = data->Cursor(); 1370 | } 1371 | // Read the name, the '=' and the value. 1372 | const char* pErr = p; 1373 | p = ReadName( p, &name, encoding ); 1374 | if ( !p || !*p ) 1375 | { 1376 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); 1377 | return 0; 1378 | } 1379 | p = SkipWhiteSpace( p, encoding ); 1380 | if ( !p || !*p || *p != '=' ) 1381 | { 1382 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1383 | return 0; 1384 | } 1385 | 1386 | ++p; // skip '=' 1387 | p = SkipWhiteSpace( p, encoding ); 1388 | if ( !p || !*p ) 1389 | { 1390 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1391 | return 0; 1392 | } 1393 | 1394 | const char* end; 1395 | const char SINGLE_QUOTE = '\''; 1396 | const char DOUBLE_QUOTE = '\"'; 1397 | 1398 | if ( *p == SINGLE_QUOTE ) 1399 | { 1400 | ++p; 1401 | end = "\'"; // single quote in string 1402 | p = ReadText( p, &value, false, end, false, encoding ); 1403 | } 1404 | else if ( *p == DOUBLE_QUOTE ) 1405 | { 1406 | ++p; 1407 | end = "\""; // double quote in string 1408 | p = ReadText( p, &value, false, end, false, encoding ); 1409 | } 1410 | else 1411 | { 1412 | // All attribute values should be in single or double quotes. 1413 | // But this is such a common error that the parser will try 1414 | // its best, even without them. 1415 | value = ""; 1416 | while ( p && *p // existence 1417 | && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace 1418 | && *p != '/' && *p != '>' ) // tag end 1419 | { 1420 | if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { 1421 | // [ 1451649 ] Attribute values with trailing quotes not handled correctly 1422 | // We did not have an opening quote but seem to have a 1423 | // closing one. Give up and throw an error. 1424 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1425 | return 0; 1426 | } 1427 | value += *p; 1428 | ++p; 1429 | } 1430 | } 1431 | return p; 1432 | } 1433 | 1434 | #ifdef TIXML_USE_STL 1435 | void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) 1436 | { 1437 | while ( in->good() ) 1438 | { 1439 | int c = in->peek(); 1440 | if ( !cdata && (c == '<' ) ) 1441 | { 1442 | return; 1443 | } 1444 | if ( c <= 0 ) 1445 | { 1446 | TiXmlDocument* document = GetDocument(); 1447 | if ( document ) 1448 | document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 1449 | return; 1450 | } 1451 | 1452 | (*tag) += (char) c; 1453 | in->get(); // "commits" the peek made above 1454 | 1455 | if ( cdata && c == '>' && tag->size() >= 3 ) { 1456 | size_t len = tag->size(); 1457 | if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { 1458 | // terminator of cdata. 1459 | return; 1460 | } 1461 | } 1462 | } 1463 | } 1464 | #endif 1465 | 1466 | const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) 1467 | { 1468 | value = ""; 1469 | TiXmlDocument* document = GetDocument(); 1470 | 1471 | if ( data ) 1472 | { 1473 | data->Stamp( p, encoding ); 1474 | location = data->Cursor(); 1475 | } 1476 | 1477 | const char* const startTag = ""; 1479 | 1480 | if ( cdata || StringEqual( p, startTag, false, encoding ) ) 1481 | { 1482 | cdata = true; 1483 | 1484 | if ( !StringEqual( p, startTag, false, encoding ) ) 1485 | { 1486 | document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); 1487 | return 0; 1488 | } 1489 | p += strlen( startTag ); 1490 | 1491 | // Keep all the white space, ignore the encoding, etc. 1492 | while ( p && *p 1493 | && !StringEqual( p, endTag, false, encoding ) 1494 | ) 1495 | { 1496 | value += *p; 1497 | ++p; 1498 | } 1499 | 1500 | TIXML_STRING dummy; 1501 | p = ReadText( p, &dummy, false, endTag, false, encoding ); 1502 | return p; 1503 | } 1504 | else 1505 | { 1506 | bool ignoreWhite = true; 1507 | 1508 | const char* end = "<"; 1509 | p = ReadText( p, &value, ignoreWhite, end, false, encoding ); 1510 | if ( p ) 1511 | return p-1; // don't truncate the '<' 1512 | return 0; 1513 | } 1514 | } 1515 | 1516 | #ifdef TIXML_USE_STL 1517 | void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) 1518 | { 1519 | while ( in->good() ) 1520 | { 1521 | int c = in->get(); 1522 | if ( c <= 0 ) 1523 | { 1524 | TiXmlDocument* document = GetDocument(); 1525 | if ( document ) 1526 | document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 1527 | return; 1528 | } 1529 | (*tag) += (char) c; 1530 | 1531 | if ( c == '>' ) 1532 | { 1533 | // All is well. 1534 | return; 1535 | } 1536 | } 1537 | } 1538 | #endif 1539 | 1540 | const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) 1541 | { 1542 | p = SkipWhiteSpace( p, _encoding ); 1543 | // Find the beginning, find the end, and look for 1544 | // the stuff in-between. 1545 | TiXmlDocument* document = GetDocument(); 1546 | if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); 1549 | return 0; 1550 | } 1551 | if ( data ) 1552 | { 1553 | data->Stamp( p, _encoding ); 1554 | location = data->Cursor(); 1555 | } 1556 | p += 5; 1557 | 1558 | version = ""; 1559 | encoding = ""; 1560 | standalone = ""; 1561 | 1562 | while ( p && *p ) 1563 | { 1564 | if ( *p == '>' ) 1565 | { 1566 | ++p; 1567 | return p; 1568 | } 1569 | 1570 | p = SkipWhiteSpace( p, _encoding ); 1571 | if ( StringEqual( p, "version", true, _encoding ) ) 1572 | { 1573 | TiXmlAttribute attrib; 1574 | p = attrib.Parse( p, data, _encoding ); 1575 | version = attrib.Value(); 1576 | } 1577 | else if ( StringEqual( p, "encoding", true, _encoding ) ) 1578 | { 1579 | TiXmlAttribute attrib; 1580 | p = attrib.Parse( p, data, _encoding ); 1581 | encoding = attrib.Value(); 1582 | } 1583 | else if ( StringEqual( p, "standalone", true, _encoding ) ) 1584 | { 1585 | TiXmlAttribute attrib; 1586 | p = attrib.Parse( p, data, _encoding ); 1587 | standalone = attrib.Value(); 1588 | } 1589 | else 1590 | { 1591 | // Read over whatever it is. 1592 | while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) 1593 | ++p; 1594 | } 1595 | } 1596 | return 0; 1597 | } 1598 | 1599 | bool TiXmlText::Blank() const 1600 | { 1601 | for ( unsigned i=0; i 28 | 29 | #ifdef TIXML_USE_STL 30 | #include 31 | #include 32 | #endif 33 | 34 | #include "tinyxml.h" 35 | 36 | 37 | bool TiXmlBase::condenseWhiteSpace = true; 38 | 39 | void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString ) 40 | { 41 | int i=0; 42 | 43 | while( i<(int)str.length() ) 44 | { 45 | unsigned char c = (unsigned char) str[i]; 46 | 47 | if ( c == '&' 48 | && i < ( (int)str.length() - 2 ) 49 | && str[i+1] == '#' 50 | && str[i+2] == 'x' ) 51 | { 52 | // Hexadecimal character reference. 53 | // Pass through unchanged. 54 | // © -- copyright symbol, for example. 55 | // 56 | // The -1 is a bug fix from Rob Laveaux. It keeps 57 | // an overflow from happening if there is no ';'. 58 | // There are actually 2 ways to exit this loop - 59 | // while fails (error case) and break (semicolon found). 60 | // However, there is no mechanism (currently) for 61 | // this function to return an error. 62 | while ( i<(int)str.length()-1 ) 63 | { 64 | outString->append( str.c_str() + i, 1 ); 65 | ++i; 66 | if ( str[i] == ';' ) 67 | break; 68 | } 69 | } 70 | else if ( c == '&' ) 71 | { 72 | outString->append( entity[0].str, entity[0].strLength ); 73 | ++i; 74 | } 75 | else if ( c == '<' ) 76 | { 77 | outString->append( entity[1].str, entity[1].strLength ); 78 | ++i; 79 | } 80 | else if ( c == '>' ) 81 | { 82 | outString->append( entity[2].str, entity[2].strLength ); 83 | ++i; 84 | } 85 | else if ( c == '\"' ) 86 | { 87 | outString->append( entity[3].str, entity[3].strLength ); 88 | ++i; 89 | } 90 | else if ( c == '\'' ) 91 | { 92 | outString->append( entity[4].str, entity[4].strLength ); 93 | ++i; 94 | } 95 | else if ( c < 32 ) 96 | { 97 | // Easy pass at non-alpha/numeric/symbol 98 | // Below 32 is symbolic. 99 | char buf[ 32 ]; 100 | 101 | #if defined(TIXML_SNPRINTF) 102 | TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); 103 | #else 104 | sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); 105 | #endif 106 | 107 | //*ME: warning C4267: convert 'size_t' to 'int' 108 | //*ME: Int-Cast to make compiler happy ... 109 | outString->append( buf, (int)strlen( buf ) ); 110 | ++i; 111 | } 112 | else 113 | { 114 | //char realc = (char) c; 115 | //outString->append( &realc, 1 ); 116 | *outString += (char) c; // somewhat more efficient function call. 117 | ++i; 118 | } 119 | } 120 | } 121 | 122 | 123 | TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() 124 | { 125 | parent = 0; 126 | type = _type; 127 | firstChild = 0; 128 | lastChild = 0; 129 | prev = 0; 130 | next = 0; 131 | } 132 | 133 | 134 | TiXmlNode::~TiXmlNode() 135 | { 136 | TiXmlNode* node = firstChild; 137 | TiXmlNode* temp = 0; 138 | 139 | while ( node ) 140 | { 141 | temp = node; 142 | node = node->next; 143 | delete temp; 144 | } 145 | } 146 | 147 | 148 | void TiXmlNode::CopyTo( TiXmlNode* target ) const 149 | { 150 | target->SetValue (value.c_str() ); 151 | target->userData = userData; 152 | } 153 | 154 | 155 | void TiXmlNode::Clear() 156 | { 157 | TiXmlNode* node = firstChild; 158 | TiXmlNode* temp = 0; 159 | 160 | while ( node ) 161 | { 162 | temp = node; 163 | node = node->next; 164 | delete temp; 165 | } 166 | 167 | firstChild = 0; 168 | lastChild = 0; 169 | } 170 | 171 | 172 | TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) 173 | { 174 | assert( node->parent == 0 || node->parent == this ); 175 | assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); 176 | 177 | if ( node->Type() == TiXmlNode::DOCUMENT ) 178 | { 179 | delete node; 180 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 181 | return 0; 182 | } 183 | 184 | node->parent = this; 185 | 186 | node->prev = lastChild; 187 | node->next = 0; 188 | 189 | if ( lastChild ) 190 | lastChild->next = node; 191 | else 192 | firstChild = node; // it was an empty list. 193 | 194 | lastChild = node; 195 | return node; 196 | } 197 | 198 | 199 | TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) 200 | { 201 | if ( addThis.Type() == TiXmlNode::DOCUMENT ) 202 | { 203 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 204 | return 0; 205 | } 206 | TiXmlNode* node = addThis.Clone(); 207 | if ( !node ) 208 | return 0; 209 | 210 | return LinkEndChild( node ); 211 | } 212 | 213 | 214 | TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) 215 | { 216 | if ( !beforeThis || beforeThis->parent != this ) { 217 | return 0; 218 | } 219 | if ( addThis.Type() == TiXmlNode::DOCUMENT ) 220 | { 221 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 222 | return 0; 223 | } 224 | 225 | TiXmlNode* node = addThis.Clone(); 226 | if ( !node ) 227 | return 0; 228 | node->parent = this; 229 | 230 | node->next = beforeThis; 231 | node->prev = beforeThis->prev; 232 | if ( beforeThis->prev ) 233 | { 234 | beforeThis->prev->next = node; 235 | } 236 | else 237 | { 238 | assert( firstChild == beforeThis ); 239 | firstChild = node; 240 | } 241 | beforeThis->prev = node; 242 | return node; 243 | } 244 | 245 | 246 | TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) 247 | { 248 | if ( !afterThis || afterThis->parent != this ) { 249 | return 0; 250 | } 251 | if ( addThis.Type() == TiXmlNode::DOCUMENT ) 252 | { 253 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 254 | return 0; 255 | } 256 | 257 | TiXmlNode* node = addThis.Clone(); 258 | if ( !node ) 259 | return 0; 260 | node->parent = this; 261 | 262 | node->prev = afterThis; 263 | node->next = afterThis->next; 264 | if ( afterThis->next ) 265 | { 266 | afterThis->next->prev = node; 267 | } 268 | else 269 | { 270 | assert( lastChild == afterThis ); 271 | lastChild = node; 272 | } 273 | afterThis->next = node; 274 | return node; 275 | } 276 | 277 | 278 | TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) 279 | { 280 | if ( replaceThis->parent != this ) 281 | return 0; 282 | 283 | TiXmlNode* node = withThis.Clone(); 284 | if ( !node ) 285 | return 0; 286 | 287 | node->next = replaceThis->next; 288 | node->prev = replaceThis->prev; 289 | 290 | if ( replaceThis->next ) 291 | replaceThis->next->prev = node; 292 | else 293 | lastChild = node; 294 | 295 | if ( replaceThis->prev ) 296 | replaceThis->prev->next = node; 297 | else 298 | firstChild = node; 299 | 300 | delete replaceThis; 301 | node->parent = this; 302 | return node; 303 | } 304 | 305 | 306 | bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) 307 | { 308 | if ( removeThis->parent != this ) 309 | { 310 | assert( 0 ); 311 | return false; 312 | } 313 | 314 | if ( removeThis->next ) 315 | removeThis->next->prev = removeThis->prev; 316 | else 317 | lastChild = removeThis->prev; 318 | 319 | if ( removeThis->prev ) 320 | removeThis->prev->next = removeThis->next; 321 | else 322 | firstChild = removeThis->next; 323 | 324 | delete removeThis; 325 | return true; 326 | } 327 | 328 | const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const 329 | { 330 | const TiXmlNode* node; 331 | for ( node = firstChild; node; node = node->next ) 332 | { 333 | if ( strcmp( node->Value(), _value ) == 0 ) 334 | return node; 335 | } 336 | return 0; 337 | } 338 | 339 | 340 | const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const 341 | { 342 | const TiXmlNode* node; 343 | for ( node = lastChild; node; node = node->prev ) 344 | { 345 | if ( strcmp( node->Value(), _value ) == 0 ) 346 | return node; 347 | } 348 | return 0; 349 | } 350 | 351 | 352 | const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const 353 | { 354 | if ( !previous ) 355 | { 356 | return FirstChild(); 357 | } 358 | else 359 | { 360 | assert( previous->parent == this ); 361 | return previous->NextSibling(); 362 | } 363 | } 364 | 365 | 366 | const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const 367 | { 368 | if ( !previous ) 369 | { 370 | return FirstChild( val ); 371 | } 372 | else 373 | { 374 | assert( previous->parent == this ); 375 | return previous->NextSibling( val ); 376 | } 377 | } 378 | 379 | 380 | const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const 381 | { 382 | const TiXmlNode* node; 383 | for ( node = next; node; node = node->next ) 384 | { 385 | if ( strcmp( node->Value(), _value ) == 0 ) 386 | return node; 387 | } 388 | return 0; 389 | } 390 | 391 | 392 | const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const 393 | { 394 | const TiXmlNode* node; 395 | for ( node = prev; node; node = node->prev ) 396 | { 397 | if ( strcmp( node->Value(), _value ) == 0 ) 398 | return node; 399 | } 400 | return 0; 401 | } 402 | 403 | 404 | void TiXmlElement::RemoveAttribute( const char * name ) 405 | { 406 | #ifdef TIXML_USE_STL 407 | TIXML_STRING str( name ); 408 | TiXmlAttribute* node = attributeSet.Find( str ); 409 | #else 410 | TiXmlAttribute* node = attributeSet.Find( name ); 411 | #endif 412 | if ( node ) 413 | { 414 | attributeSet.Remove( node ); 415 | delete node; 416 | } 417 | } 418 | 419 | const TiXmlElement* TiXmlNode::FirstChildElement() const 420 | { 421 | const TiXmlNode* node; 422 | 423 | for ( node = FirstChild(); 424 | node; 425 | node = node->NextSibling() ) 426 | { 427 | if ( node->ToElement() ) 428 | return node->ToElement(); 429 | } 430 | return 0; 431 | } 432 | 433 | 434 | const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const 435 | { 436 | const TiXmlNode* node; 437 | 438 | for ( node = FirstChild( _value ); 439 | node; 440 | node = node->NextSibling( _value ) ) 441 | { 442 | if ( node->ToElement() ) 443 | return node->ToElement(); 444 | } 445 | return 0; 446 | } 447 | 448 | 449 | const TiXmlElement* TiXmlNode::NextSiblingElement() const 450 | { 451 | const TiXmlNode* node; 452 | 453 | for ( node = NextSibling(); 454 | node; 455 | node = node->NextSibling() ) 456 | { 457 | if ( node->ToElement() ) 458 | return node->ToElement(); 459 | } 460 | return 0; 461 | } 462 | 463 | 464 | const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const 465 | { 466 | const TiXmlNode* node; 467 | 468 | for ( node = NextSibling( _value ); 469 | node; 470 | node = node->NextSibling( _value ) ) 471 | { 472 | if ( node->ToElement() ) 473 | return node->ToElement(); 474 | } 475 | return 0; 476 | } 477 | 478 | 479 | const TiXmlDocument* TiXmlNode::GetDocument() const 480 | { 481 | const TiXmlNode* node; 482 | 483 | for( node = this; node; node = node->parent ) 484 | { 485 | if ( node->ToDocument() ) 486 | return node->ToDocument(); 487 | } 488 | return 0; 489 | } 490 | 491 | 492 | TiXmlElement::TiXmlElement (const char * _value) 493 | : TiXmlNode( TiXmlNode::ELEMENT ) 494 | { 495 | firstChild = lastChild = 0; 496 | value = _value; 497 | } 498 | 499 | 500 | #ifdef TIXML_USE_STL 501 | TiXmlElement::TiXmlElement( const std::string& _value ) 502 | : TiXmlNode( TiXmlNode::ELEMENT ) 503 | { 504 | firstChild = lastChild = 0; 505 | value = _value; 506 | } 507 | #endif 508 | 509 | 510 | TiXmlElement::TiXmlElement( const TiXmlElement& copy) 511 | : TiXmlNode( TiXmlNode::ELEMENT ) 512 | { 513 | firstChild = lastChild = 0; 514 | copy.CopyTo( this ); 515 | } 516 | 517 | 518 | void TiXmlElement::operator=( const TiXmlElement& base ) 519 | { 520 | ClearThis(); 521 | base.CopyTo( this ); 522 | } 523 | 524 | 525 | TiXmlElement::~TiXmlElement() 526 | { 527 | ClearThis(); 528 | } 529 | 530 | 531 | void TiXmlElement::ClearThis() 532 | { 533 | Clear(); 534 | while( attributeSet.First() ) 535 | { 536 | TiXmlAttribute* node = attributeSet.First(); 537 | attributeSet.Remove( node ); 538 | delete node; 539 | } 540 | } 541 | 542 | 543 | const char* TiXmlElement::Attribute( const char* name ) const 544 | { 545 | const TiXmlAttribute* node = attributeSet.Find( name ); 546 | if ( node ) 547 | return node->Value(); 548 | return 0; 549 | } 550 | 551 | 552 | #ifdef TIXML_USE_STL 553 | const std::string* TiXmlElement::Attribute( const std::string& name ) const 554 | { 555 | const TiXmlAttribute* node = attributeSet.Find( name ); 556 | if ( node ) 557 | return &node->ValueStr(); 558 | return 0; 559 | } 560 | #endif 561 | 562 | 563 | const char* TiXmlElement::Attribute( const char* name, int* i ) const 564 | { 565 | const char* s = Attribute( name ); 566 | if ( i ) 567 | { 568 | if ( s ) { 569 | *i = atoi( s ); 570 | } 571 | else { 572 | *i = 0; 573 | } 574 | } 575 | return s; 576 | } 577 | 578 | 579 | #ifdef TIXML_USE_STL 580 | const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const 581 | { 582 | const std::string* s = Attribute( name ); 583 | if ( i ) 584 | { 585 | if ( s ) { 586 | *i = atoi( s->c_str() ); 587 | } 588 | else { 589 | *i = 0; 590 | } 591 | } 592 | return s; 593 | } 594 | #endif 595 | 596 | 597 | const char* TiXmlElement::Attribute( const char* name, double* d ) const 598 | { 599 | const char* s = Attribute( name ); 600 | if ( d ) 601 | { 602 | if ( s ) { 603 | *d = atof( s ); 604 | } 605 | else { 606 | *d = 0; 607 | } 608 | } 609 | return s; 610 | } 611 | 612 | 613 | #ifdef TIXML_USE_STL 614 | const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const 615 | { 616 | const std::string* s = Attribute( name ); 617 | if ( d ) 618 | { 619 | if ( s ) { 620 | *d = atof( s->c_str() ); 621 | } 622 | else { 623 | *d = 0; 624 | } 625 | } 626 | return s; 627 | } 628 | #endif 629 | 630 | 631 | int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const 632 | { 633 | const TiXmlAttribute* node = attributeSet.Find( name ); 634 | if ( !node ) 635 | return TIXML_NO_ATTRIBUTE; 636 | return node->QueryIntValue( ival ); 637 | } 638 | 639 | 640 | #ifdef TIXML_USE_STL 641 | int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const 642 | { 643 | const TiXmlAttribute* node = attributeSet.Find( name ); 644 | if ( !node ) 645 | return TIXML_NO_ATTRIBUTE; 646 | return node->QueryIntValue( ival ); 647 | } 648 | #endif 649 | 650 | 651 | int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const 652 | { 653 | const TiXmlAttribute* node = attributeSet.Find( name ); 654 | if ( !node ) 655 | return TIXML_NO_ATTRIBUTE; 656 | return node->QueryDoubleValue( dval ); 657 | } 658 | 659 | 660 | #ifdef TIXML_USE_STL 661 | int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const 662 | { 663 | const TiXmlAttribute* node = attributeSet.Find( name ); 664 | if ( !node ) 665 | return TIXML_NO_ATTRIBUTE; 666 | return node->QueryDoubleValue( dval ); 667 | } 668 | #endif 669 | 670 | 671 | void TiXmlElement::SetAttribute( const char * name, int val ) 672 | { 673 | char buf[64]; 674 | #if defined(TIXML_SNPRINTF) 675 | TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); 676 | #else 677 | sprintf( buf, "%d", val ); 678 | #endif 679 | SetAttribute( name, buf ); 680 | } 681 | 682 | 683 | #ifdef TIXML_USE_STL 684 | void TiXmlElement::SetAttribute( const std::string& name, int val ) 685 | { 686 | std::ostringstream oss; 687 | oss << val; 688 | SetAttribute( name, oss.str() ); 689 | } 690 | #endif 691 | 692 | 693 | void TiXmlElement::SetDoubleAttribute( const char * name, double val ) 694 | { 695 | char buf[256]; 696 | #if defined(TIXML_SNPRINTF) 697 | TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); 698 | #else 699 | sprintf( buf, "%f", val ); 700 | #endif 701 | SetAttribute( name, buf ); 702 | } 703 | 704 | 705 | void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) 706 | { 707 | #ifdef TIXML_USE_STL 708 | TIXML_STRING _name( cname ); 709 | TIXML_STRING _value( cvalue ); 710 | #else 711 | const char* _name = cname; 712 | const char* _value = cvalue; 713 | #endif 714 | 715 | TiXmlAttribute* node = attributeSet.Find( _name ); 716 | if ( node ) 717 | { 718 | node->SetValue( _value ); 719 | return; 720 | } 721 | 722 | TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); 723 | if ( attrib ) 724 | { 725 | attributeSet.Add( attrib ); 726 | } 727 | else 728 | { 729 | TiXmlDocument* document = GetDocument(); 730 | if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); 731 | } 732 | } 733 | 734 | 735 | #ifdef TIXML_USE_STL 736 | void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) 737 | { 738 | TiXmlAttribute* node = attributeSet.Find( name ); 739 | if ( node ) 740 | { 741 | node->SetValue( _value ); 742 | return; 743 | } 744 | 745 | TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); 746 | if ( attrib ) 747 | { 748 | attributeSet.Add( attrib ); 749 | } 750 | else 751 | { 752 | TiXmlDocument* document = GetDocument(); 753 | if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); 754 | } 755 | } 756 | #endif 757 | 758 | 759 | void TiXmlElement::Print( FILE* cfile, int depth ) const 760 | { 761 | int i; 762 | assert( cfile ); 763 | for ( i=0; iNext() ) 771 | { 772 | fprintf( cfile, " " ); 773 | attrib->Print( cfile, depth ); 774 | } 775 | 776 | // There are 3 different formatting approaches: 777 | // 1) An element without children is printed as a node 778 | // 2) An element with only a text child is printed as text 779 | // 3) An element with children is printed on multiple lines. 780 | TiXmlNode* node; 781 | if ( !firstChild ) 782 | { 783 | fprintf( cfile, " />" ); 784 | } 785 | else if ( firstChild == lastChild && firstChild->ToText() ) 786 | { 787 | fprintf( cfile, ">" ); 788 | firstChild->Print( cfile, depth + 1 ); 789 | fprintf( cfile, "", value.c_str() ); 790 | } 791 | else 792 | { 793 | fprintf( cfile, ">" ); 794 | 795 | for ( node = firstChild; node; node=node->NextSibling() ) 796 | { 797 | if ( !node->ToText() ) 798 | { 799 | fprintf( cfile, "\n" ); 800 | } 801 | node->Print( cfile, depth+1 ); 802 | } 803 | fprintf( cfile, "\n" ); 804 | for( i=0; i", value.c_str() ); 808 | } 809 | } 810 | 811 | 812 | void TiXmlElement::CopyTo( TiXmlElement* target ) const 813 | { 814 | // superclass: 815 | TiXmlNode::CopyTo( target ); 816 | 817 | // Element class: 818 | // Clone the attributes, then clone the children. 819 | const TiXmlAttribute* attribute = 0; 820 | for( attribute = attributeSet.First(); 821 | attribute; 822 | attribute = attribute->Next() ) 823 | { 824 | target->SetAttribute( attribute->Name(), attribute->Value() ); 825 | } 826 | 827 | TiXmlNode* node = 0; 828 | for ( node = firstChild; node; node = node->NextSibling() ) 829 | { 830 | target->LinkEndChild( node->Clone() ); 831 | } 832 | } 833 | 834 | bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const 835 | { 836 | if ( visitor->VisitEnter( *this, attributeSet.First() ) ) 837 | { 838 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) 839 | { 840 | if ( !node->Accept( visitor ) ) 841 | break; 842 | } 843 | } 844 | return visitor->VisitExit( *this ); 845 | } 846 | 847 | 848 | TiXmlNode* TiXmlElement::Clone() const 849 | { 850 | TiXmlElement* clone = new TiXmlElement( Value() ); 851 | if ( !clone ) 852 | return 0; 853 | 854 | CopyTo( clone ); 855 | return clone; 856 | } 857 | 858 | 859 | const char* TiXmlElement::GetText() const 860 | { 861 | const TiXmlNode* child = this->FirstChild(); 862 | if ( child ) { 863 | const TiXmlText* childText = child->ToText(); 864 | if ( childText ) { 865 | return childText->Value(); 866 | } 867 | } 868 | return 0; 869 | } 870 | 871 | 872 | TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) 873 | { 874 | tabsize = 4; 875 | useMicrosoftBOM = false; 876 | ClearError(); 877 | } 878 | 879 | TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) 880 | { 881 | tabsize = 4; 882 | useMicrosoftBOM = false; 883 | value = documentName; 884 | ClearError(); 885 | } 886 | 887 | 888 | #ifdef TIXML_USE_STL 889 | TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) 890 | { 891 | tabsize = 4; 892 | useMicrosoftBOM = false; 893 | value = documentName; 894 | ClearError(); 895 | } 896 | #endif 897 | 898 | 899 | TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) 900 | { 901 | copy.CopyTo( this ); 902 | } 903 | 904 | 905 | void TiXmlDocument::operator=( const TiXmlDocument& copy ) 906 | { 907 | Clear(); 908 | copy.CopyTo( this ); 909 | } 910 | 911 | 912 | bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) 913 | { 914 | // See STL_STRING_BUG below. 915 | //StringToBuffer buf( value ); 916 | 917 | return LoadFile( Value(), encoding ); 918 | } 919 | 920 | 921 | bool TiXmlDocument::SaveFile() const 922 | { 923 | // See STL_STRING_BUG below. 924 | // StringToBuffer buf( value ); 925 | // 926 | // if ( buf.buffer && SaveFile( buf.buffer ) ) 927 | // return true; 928 | // 929 | // return false; 930 | return SaveFile( Value() ); 931 | } 932 | 933 | bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) 934 | { 935 | // There was a really terrifying little bug here. The code: 936 | // value = filename 937 | // in the STL case, cause the assignment method of the std::string to 938 | // be called. What is strange, is that the std::string had the same 939 | // address as it's c_str() method, and so bad things happen. Looks 940 | // like a bug in the Microsoft STL implementation. 941 | // Add an extra string to avoid the crash. 942 | TIXML_STRING filename( _filename ); 943 | value = filename; 944 | 945 | // reading in binary mode so that tinyxml can normalize the EOL 946 | FILE* file = fopen( value.c_str (), "rb" ); 947 | 948 | if ( file ) 949 | { 950 | bool result = LoadFile( file, encoding ); 951 | fclose( file ); 952 | return result; 953 | } 954 | else 955 | { 956 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); 957 | return false; 958 | } 959 | } 960 | 961 | bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) 962 | { 963 | if ( !file ) 964 | { 965 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); 966 | return false; 967 | } 968 | 969 | // Delete the existing data: 970 | Clear(); 971 | location.Clear(); 972 | 973 | // Get the file size, so we can pre-allocate the string. HUGE speed impact. 974 | long length = 0; 975 | fseek( file, 0, SEEK_END ); 976 | length = ftell( file ); 977 | fseek( file, 0, SEEK_SET ); 978 | 979 | // Strange case, but good to handle up front. 980 | if ( length == 0 ) 981 | { 982 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 983 | return false; 984 | } 985 | 986 | // If we have a file, assume it is all one big XML file, and read it in. 987 | // The document parser may decide the document ends sooner than the entire file, however. 988 | TIXML_STRING data; 989 | data.reserve( length ); 990 | 991 | // Subtle bug here. TinyXml did use fgets. But from the XML spec: 992 | // 2.11 End-of-Line Handling 993 | // 994 | // 995 | // ...the XML processor MUST behave as if it normalized all line breaks in external 996 | // parsed entities (including the document entity) on input, before parsing, by translating 997 | // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to 998 | // a single #xA character. 999 | // 1000 | // 1001 | // It is not clear fgets does that, and certainly isn't clear it works cross platform. 1002 | // Generally, you expect fgets to translate from the convention of the OS to the c/unix 1003 | // convention, and not work generally. 1004 | 1005 | /* 1006 | while( fgets( buf, sizeof(buf), file ) ) 1007 | { 1008 | data += buf; 1009 | } 1010 | */ 1011 | 1012 | char* buf = new char[ length+1 ]; 1013 | buf[0] = 0; 1014 | 1015 | if ( fread( buf, length, 1, file ) != 1 ) { 1016 | delete [] buf; 1017 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); 1018 | return false; 1019 | } 1020 | 1021 | const char* lastPos = buf; 1022 | const char* p = buf; 1023 | 1024 | buf[length] = 0; 1025 | while( *p ) { 1026 | assert( p < (buf+length) ); 1027 | if ( *p == 0xa ) { 1028 | // Newline character. No special rules for this. Append all the characters 1029 | // since the last string, and include the newline. 1030 | data.append( lastPos, (p-lastPos+1) ); // append, include the newline 1031 | ++p; // move past the newline 1032 | lastPos = p; // and point to the new buffer (may be 0) 1033 | assert( p <= (buf+length) ); 1034 | } 1035 | else if ( *p == 0xd ) { 1036 | // Carriage return. Append what we have so far, then 1037 | // handle moving forward in the buffer. 1038 | if ( (p-lastPos) > 0 ) { 1039 | data.append( lastPos, p-lastPos ); // do not add the CR 1040 | } 1041 | data += (char)0xa; // a proper newline 1042 | 1043 | if ( *(p+1) == 0xa ) { 1044 | // Carriage return - new line sequence 1045 | p += 2; 1046 | lastPos = p; 1047 | assert( p <= (buf+length) ); 1048 | } 1049 | else { 1050 | // it was followed by something else...that is presumably characters again. 1051 | ++p; 1052 | lastPos = p; 1053 | assert( p <= (buf+length) ); 1054 | } 1055 | } 1056 | else { 1057 | ++p; 1058 | } 1059 | } 1060 | // Handle any left over characters. 1061 | if ( p-lastPos ) { 1062 | data.append( lastPos, p-lastPos ); 1063 | } 1064 | delete [] buf; 1065 | buf = 0; 1066 | 1067 | Parse( data.c_str(), 0, encoding ); 1068 | 1069 | if ( Error() ) 1070 | return false; 1071 | else 1072 | return true; 1073 | } 1074 | 1075 | 1076 | bool TiXmlDocument::SaveFile( const char * filename ) const 1077 | { 1078 | // The old c stuff lives on... 1079 | FILE* fp = fopen( filename, "w" ); 1080 | if ( fp ) 1081 | { 1082 | bool result = SaveFile( fp ); 1083 | fclose( fp ); 1084 | return result; 1085 | } 1086 | return false; 1087 | } 1088 | 1089 | 1090 | bool TiXmlDocument::SaveFile( FILE* fp ) const 1091 | { 1092 | if ( useMicrosoftBOM ) 1093 | { 1094 | const unsigned char TIXML_UTF_LEAD_0 = 0xefU; 1095 | const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; 1096 | const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; 1097 | 1098 | fputc( TIXML_UTF_LEAD_0, fp ); 1099 | fputc( TIXML_UTF_LEAD_1, fp ); 1100 | fputc( TIXML_UTF_LEAD_2, fp ); 1101 | } 1102 | Print( fp, 0 ); 1103 | return (ferror(fp) == 0); 1104 | } 1105 | 1106 | 1107 | void TiXmlDocument::CopyTo( TiXmlDocument* target ) const 1108 | { 1109 | TiXmlNode::CopyTo( target ); 1110 | 1111 | target->error = error; 1112 | target->errorDesc = errorDesc.c_str (); 1113 | 1114 | TiXmlNode* node = 0; 1115 | for ( node = firstChild; node; node = node->NextSibling() ) 1116 | { 1117 | target->LinkEndChild( node->Clone() ); 1118 | } 1119 | } 1120 | 1121 | 1122 | TiXmlNode* TiXmlDocument::Clone() const 1123 | { 1124 | TiXmlDocument* clone = new TiXmlDocument(); 1125 | if ( !clone ) 1126 | return 0; 1127 | 1128 | CopyTo( clone ); 1129 | return clone; 1130 | } 1131 | 1132 | 1133 | void TiXmlDocument::Print( FILE* cfile, int depth ) const 1134 | { 1135 | assert( cfile ); 1136 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) 1137 | { 1138 | node->Print( cfile, depth ); 1139 | fprintf( cfile, "\n" ); 1140 | } 1141 | } 1142 | 1143 | 1144 | bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const 1145 | { 1146 | if ( visitor->VisitEnter( *this ) ) 1147 | { 1148 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) 1149 | { 1150 | if ( !node->Accept( visitor ) ) 1151 | break; 1152 | } 1153 | } 1154 | return visitor->VisitExit( *this ); 1155 | } 1156 | 1157 | 1158 | const TiXmlAttribute* TiXmlAttribute::Next() const 1159 | { 1160 | // We are using knowledge of the sentinel. The sentinel 1161 | // have a value or name. 1162 | if ( next->value.empty() && next->name.empty() ) 1163 | return 0; 1164 | return next; 1165 | } 1166 | 1167 | /* 1168 | TiXmlAttribute* TiXmlAttribute::Next() 1169 | { 1170 | // We are using knowledge of the sentinel. The sentinel 1171 | // have a value or name. 1172 | if ( next->value.empty() && next->name.empty() ) 1173 | return 0; 1174 | return next; 1175 | } 1176 | */ 1177 | 1178 | const TiXmlAttribute* TiXmlAttribute::Previous() const 1179 | { 1180 | // We are using knowledge of the sentinel. The sentinel 1181 | // have a value or name. 1182 | if ( prev->value.empty() && prev->name.empty() ) 1183 | return 0; 1184 | return prev; 1185 | } 1186 | 1187 | /* 1188 | TiXmlAttribute* TiXmlAttribute::Previous() 1189 | { 1190 | // We are using knowledge of the sentinel. The sentinel 1191 | // have a value or name. 1192 | if ( prev->value.empty() && prev->name.empty() ) 1193 | return 0; 1194 | return prev; 1195 | } 1196 | */ 1197 | 1198 | void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const 1199 | { 1200 | TIXML_STRING n, v; 1201 | 1202 | PutString( name, &n ); 1203 | PutString( value, &v ); 1204 | 1205 | if (value.find ('\"') == TIXML_STRING::npos) { 1206 | if ( cfile ) { 1207 | fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); 1208 | } 1209 | if ( str ) { 1210 | (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; 1211 | } 1212 | } 1213 | else { 1214 | if ( cfile ) { 1215 | fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); 1216 | } 1217 | if ( str ) { 1218 | (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; 1219 | } 1220 | } 1221 | } 1222 | 1223 | 1224 | int TiXmlAttribute::QueryIntValue( int* ival ) const 1225 | { 1226 | if ( sscanf( value.c_str(), "%d", ival ) == 1 ) 1227 | return TIXML_SUCCESS; 1228 | return TIXML_WRONG_TYPE; 1229 | } 1230 | 1231 | int TiXmlAttribute::QueryDoubleValue( double* dval ) const 1232 | { 1233 | if ( sscanf( value.c_str(), "%lf", dval ) == 1 ) 1234 | return TIXML_SUCCESS; 1235 | return TIXML_WRONG_TYPE; 1236 | } 1237 | 1238 | void TiXmlAttribute::SetIntValue( int _value ) 1239 | { 1240 | char buf [64]; 1241 | #if defined(TIXML_SNPRINTF) 1242 | TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); 1243 | #else 1244 | sprintf (buf, "%d", _value); 1245 | #endif 1246 | SetValue (buf); 1247 | } 1248 | 1249 | void TiXmlAttribute::SetDoubleValue( double _value ) 1250 | { 1251 | char buf [256]; 1252 | #if defined(TIXML_SNPRINTF) 1253 | TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); 1254 | #else 1255 | sprintf (buf, "%lf", _value); 1256 | #endif 1257 | SetValue (buf); 1258 | } 1259 | 1260 | int TiXmlAttribute::IntValue() const 1261 | { 1262 | return atoi (value.c_str ()); 1263 | } 1264 | 1265 | double TiXmlAttribute::DoubleValue() const 1266 | { 1267 | return atof (value.c_str ()); 1268 | } 1269 | 1270 | 1271 | TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) 1272 | { 1273 | copy.CopyTo( this ); 1274 | } 1275 | 1276 | 1277 | void TiXmlComment::operator=( const TiXmlComment& base ) 1278 | { 1279 | Clear(); 1280 | base.CopyTo( this ); 1281 | } 1282 | 1283 | 1284 | void TiXmlComment::Print( FILE* cfile, int depth ) const 1285 | { 1286 | assert( cfile ); 1287 | for ( int i=0; i", value.c_str() ); 1292 | } 1293 | 1294 | 1295 | void TiXmlComment::CopyTo( TiXmlComment* target ) const 1296 | { 1297 | TiXmlNode::CopyTo( target ); 1298 | } 1299 | 1300 | 1301 | bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const 1302 | { 1303 | return visitor->Visit( *this ); 1304 | } 1305 | 1306 | 1307 | TiXmlNode* TiXmlComment::Clone() const 1308 | { 1309 | TiXmlComment* clone = new TiXmlComment(); 1310 | 1311 | if ( !clone ) 1312 | return 0; 1313 | 1314 | CopyTo( clone ); 1315 | return clone; 1316 | } 1317 | 1318 | 1319 | void TiXmlText::Print( FILE* cfile, int depth ) const 1320 | { 1321 | assert( cfile ); 1322 | if ( cdata ) 1323 | { 1324 | int i; 1325 | fprintf( cfile, "\n" ); 1326 | for ( i=0; i\n", value.c_str() ); // unformatted output 1330 | } 1331 | else 1332 | { 1333 | TIXML_STRING buffer; 1334 | PutString( value, &buffer ); 1335 | fprintf( cfile, "%s", buffer.c_str() ); 1336 | } 1337 | } 1338 | 1339 | 1340 | void TiXmlText::CopyTo( TiXmlText* target ) const 1341 | { 1342 | TiXmlNode::CopyTo( target ); 1343 | target->cdata = cdata; 1344 | } 1345 | 1346 | 1347 | bool TiXmlText::Accept( TiXmlVisitor* visitor ) const 1348 | { 1349 | return visitor->Visit( *this ); 1350 | } 1351 | 1352 | 1353 | TiXmlNode* TiXmlText::Clone() const 1354 | { 1355 | TiXmlText* clone = 0; 1356 | clone = new TiXmlText( "" ); 1357 | 1358 | if ( !clone ) 1359 | return 0; 1360 | 1361 | CopyTo( clone ); 1362 | return clone; 1363 | } 1364 | 1365 | 1366 | TiXmlDeclaration::TiXmlDeclaration( const char * _version, 1367 | const char * _encoding, 1368 | const char * _standalone ) 1369 | : TiXmlNode( TiXmlNode::DECLARATION ) 1370 | { 1371 | version = _version; 1372 | encoding = _encoding; 1373 | standalone = _standalone; 1374 | } 1375 | 1376 | 1377 | #ifdef TIXML_USE_STL 1378 | TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, 1379 | const std::string& _encoding, 1380 | const std::string& _standalone ) 1381 | : TiXmlNode( TiXmlNode::DECLARATION ) 1382 | { 1383 | version = _version; 1384 | encoding = _encoding; 1385 | standalone = _standalone; 1386 | } 1387 | #endif 1388 | 1389 | 1390 | TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) 1391 | : TiXmlNode( TiXmlNode::DECLARATION ) 1392 | { 1393 | copy.CopyTo( this ); 1394 | } 1395 | 1396 | 1397 | void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) 1398 | { 1399 | Clear(); 1400 | copy.CopyTo( this ); 1401 | } 1402 | 1403 | 1404 | void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const 1405 | { 1406 | if ( cfile ) fprintf( cfile, "" ); 1422 | if ( str ) (*str) += "?>"; 1423 | } 1424 | 1425 | 1426 | void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const 1427 | { 1428 | TiXmlNode::CopyTo( target ); 1429 | 1430 | target->version = version; 1431 | target->encoding = encoding; 1432 | target->standalone = standalone; 1433 | } 1434 | 1435 | 1436 | bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const 1437 | { 1438 | return visitor->Visit( *this ); 1439 | } 1440 | 1441 | 1442 | TiXmlNode* TiXmlDeclaration::Clone() const 1443 | { 1444 | TiXmlDeclaration* clone = new TiXmlDeclaration(); 1445 | 1446 | if ( !clone ) 1447 | return 0; 1448 | 1449 | CopyTo( clone ); 1450 | return clone; 1451 | } 1452 | 1453 | 1454 | void TiXmlUnknown::Print( FILE* cfile, int depth ) const 1455 | { 1456 | for ( int i=0; i", value.c_str() ); 1459 | } 1460 | 1461 | 1462 | void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const 1463 | { 1464 | TiXmlNode::CopyTo( target ); 1465 | } 1466 | 1467 | 1468 | bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const 1469 | { 1470 | return visitor->Visit( *this ); 1471 | } 1472 | 1473 | 1474 | TiXmlNode* TiXmlUnknown::Clone() const 1475 | { 1476 | TiXmlUnknown* clone = new TiXmlUnknown(); 1477 | 1478 | if ( !clone ) 1479 | return 0; 1480 | 1481 | CopyTo( clone ); 1482 | return clone; 1483 | } 1484 | 1485 | 1486 | TiXmlAttributeSet::TiXmlAttributeSet() 1487 | { 1488 | sentinel.next = &sentinel; 1489 | sentinel.prev = &sentinel; 1490 | } 1491 | 1492 | 1493 | TiXmlAttributeSet::~TiXmlAttributeSet() 1494 | { 1495 | assert( sentinel.next == &sentinel ); 1496 | assert( sentinel.prev == &sentinel ); 1497 | } 1498 | 1499 | 1500 | void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) 1501 | { 1502 | #ifdef TIXML_USE_STL 1503 | assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. 1504 | #else 1505 | assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. 1506 | #endif 1507 | 1508 | addMe->next = &sentinel; 1509 | addMe->prev = sentinel.prev; 1510 | 1511 | sentinel.prev->next = addMe; 1512 | sentinel.prev = addMe; 1513 | } 1514 | 1515 | void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) 1516 | { 1517 | TiXmlAttribute* node; 1518 | 1519 | for( node = sentinel.next; node != &sentinel; node = node->next ) 1520 | { 1521 | if ( node == removeMe ) 1522 | { 1523 | node->prev->next = node->next; 1524 | node->next->prev = node->prev; 1525 | node->next = 0; 1526 | node->prev = 0; 1527 | return; 1528 | } 1529 | } 1530 | assert( 0 ); // we tried to remove a non-linked attribute. 1531 | } 1532 | 1533 | 1534 | #ifdef TIXML_USE_STL 1535 | const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const 1536 | { 1537 | for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) 1538 | { 1539 | if ( node->name == name ) 1540 | return node; 1541 | } 1542 | return 0; 1543 | } 1544 | 1545 | /* 1546 | TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) 1547 | { 1548 | for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) 1549 | { 1550 | if ( node->name == name ) 1551 | return node; 1552 | } 1553 | return 0; 1554 | } 1555 | */ 1556 | #endif 1557 | 1558 | 1559 | const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const 1560 | { 1561 | for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) 1562 | { 1563 | if ( strcmp( node->name.c_str(), name ) == 0 ) 1564 | return node; 1565 | } 1566 | return 0; 1567 | } 1568 | 1569 | /* 1570 | TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) 1571 | { 1572 | for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) 1573 | { 1574 | if ( strcmp( node->name.c_str(), name ) == 0 ) 1575 | return node; 1576 | } 1577 | return 0; 1578 | } 1579 | */ 1580 | 1581 | #ifdef TIXML_USE_STL 1582 | std::istream& operator>> (std::istream & in, TiXmlNode & base) 1583 | { 1584 | TIXML_STRING tag; 1585 | tag.reserve( 8 * 1000 ); 1586 | base.StreamIn( &in, &tag ); 1587 | 1588 | base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); 1589 | return in; 1590 | } 1591 | #endif 1592 | 1593 | 1594 | #ifdef TIXML_USE_STL 1595 | std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) 1596 | { 1597 | TiXmlPrinter printer; 1598 | printer.SetStreamPrinting(); 1599 | base.Accept( &printer ); 1600 | out << printer.Str(); 1601 | 1602 | return out; 1603 | } 1604 | 1605 | 1606 | std::string& operator<< (std::string& out, const TiXmlNode& base ) 1607 | { 1608 | TiXmlPrinter printer; 1609 | printer.SetStreamPrinting(); 1610 | base.Accept( &printer ); 1611 | out.append( printer.Str() ); 1612 | 1613 | return out; 1614 | } 1615 | #endif 1616 | 1617 | 1618 | TiXmlHandle TiXmlHandle::FirstChild() const 1619 | { 1620 | if ( node ) 1621 | { 1622 | TiXmlNode* child = node->FirstChild(); 1623 | if ( child ) 1624 | return TiXmlHandle( child ); 1625 | } 1626 | return TiXmlHandle( 0 ); 1627 | } 1628 | 1629 | 1630 | TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const 1631 | { 1632 | if ( node ) 1633 | { 1634 | TiXmlNode* child = node->FirstChild( value ); 1635 | if ( child ) 1636 | return TiXmlHandle( child ); 1637 | } 1638 | return TiXmlHandle( 0 ); 1639 | } 1640 | 1641 | 1642 | TiXmlHandle TiXmlHandle::FirstChildElement() const 1643 | { 1644 | if ( node ) 1645 | { 1646 | TiXmlElement* child = node->FirstChildElement(); 1647 | if ( child ) 1648 | return TiXmlHandle( child ); 1649 | } 1650 | return TiXmlHandle( 0 ); 1651 | } 1652 | 1653 | 1654 | TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const 1655 | { 1656 | if ( node ) 1657 | { 1658 | TiXmlElement* child = node->FirstChildElement( value ); 1659 | if ( child ) 1660 | return TiXmlHandle( child ); 1661 | } 1662 | return TiXmlHandle( 0 ); 1663 | } 1664 | 1665 | 1666 | TiXmlHandle TiXmlHandle::Child( int count ) const 1667 | { 1668 | if ( node ) 1669 | { 1670 | int i; 1671 | TiXmlNode* child = node->FirstChild(); 1672 | for ( i=0; 1673 | child && iNextSibling(), ++i ) 1675 | { 1676 | // nothing 1677 | } 1678 | if ( child ) 1679 | return TiXmlHandle( child ); 1680 | } 1681 | return TiXmlHandle( 0 ); 1682 | } 1683 | 1684 | 1685 | TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const 1686 | { 1687 | if ( node ) 1688 | { 1689 | int i; 1690 | TiXmlNode* child = node->FirstChild( value ); 1691 | for ( i=0; 1692 | child && iNextSibling( value ), ++i ) 1694 | { 1695 | // nothing 1696 | } 1697 | if ( child ) 1698 | return TiXmlHandle( child ); 1699 | } 1700 | return TiXmlHandle( 0 ); 1701 | } 1702 | 1703 | 1704 | TiXmlHandle TiXmlHandle::ChildElement( int count ) const 1705 | { 1706 | if ( node ) 1707 | { 1708 | int i; 1709 | TiXmlElement* child = node->FirstChildElement(); 1710 | for ( i=0; 1711 | child && iNextSiblingElement(), ++i ) 1713 | { 1714 | // nothing 1715 | } 1716 | if ( child ) 1717 | return TiXmlHandle( child ); 1718 | } 1719 | return TiXmlHandle( 0 ); 1720 | } 1721 | 1722 | 1723 | TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const 1724 | { 1725 | if ( node ) 1726 | { 1727 | int i; 1728 | TiXmlElement* child = node->FirstChildElement( value ); 1729 | for ( i=0; 1730 | child && iNextSiblingElement( value ), ++i ) 1732 | { 1733 | // nothing 1734 | } 1735 | if ( child ) 1736 | return TiXmlHandle( child ); 1737 | } 1738 | return TiXmlHandle( 0 ); 1739 | } 1740 | 1741 | 1742 | bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) 1743 | { 1744 | return true; 1745 | } 1746 | 1747 | bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) 1748 | { 1749 | return true; 1750 | } 1751 | 1752 | bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) 1753 | { 1754 | DoIndent(); 1755 | buffer += "<"; 1756 | buffer += element.Value(); 1757 | 1758 | for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) 1759 | { 1760 | buffer += " "; 1761 | attrib->Print( 0, 0, &buffer ); 1762 | } 1763 | 1764 | if ( !element.FirstChild() ) 1765 | { 1766 | buffer += " />"; 1767 | DoLineBreak(); 1768 | } 1769 | else 1770 | { 1771 | buffer += ">"; 1772 | if ( element.FirstChild()->ToText() 1773 | && element.LastChild() == element.FirstChild() 1774 | && element.FirstChild()->ToText()->CDATA() == false ) 1775 | { 1776 | simpleTextPrint = true; 1777 | // no DoLineBreak()! 1778 | } 1779 | else 1780 | { 1781 | DoLineBreak(); 1782 | } 1783 | } 1784 | ++depth; 1785 | return true; 1786 | } 1787 | 1788 | 1789 | bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) 1790 | { 1791 | --depth; 1792 | if ( !element.FirstChild() ) 1793 | { 1794 | // nothing. 1795 | } 1796 | else 1797 | { 1798 | if ( simpleTextPrint ) 1799 | { 1800 | simpleTextPrint = false; 1801 | } 1802 | else 1803 | { 1804 | DoIndent(); 1805 | } 1806 | buffer += ""; 1809 | DoLineBreak(); 1810 | } 1811 | return true; 1812 | } 1813 | 1814 | 1815 | bool TiXmlPrinter::Visit( const TiXmlText& text ) 1816 | { 1817 | if ( text.CDATA() ) 1818 | { 1819 | DoIndent(); 1820 | buffer += ""; 1823 | DoLineBreak(); 1824 | } 1825 | else if ( simpleTextPrint ) 1826 | { 1827 | buffer += text.Value(); 1828 | } 1829 | else 1830 | { 1831 | DoIndent(); 1832 | buffer += text.Value(); 1833 | DoLineBreak(); 1834 | } 1835 | return true; 1836 | } 1837 | 1838 | 1839 | bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) 1840 | { 1841 | DoIndent(); 1842 | declaration.Print( 0, 0, &buffer ); 1843 | DoLineBreak(); 1844 | return true; 1845 | } 1846 | 1847 | 1848 | bool TiXmlPrinter::Visit( const TiXmlComment& comment ) 1849 | { 1850 | DoIndent(); 1851 | buffer += ""; 1854 | DoLineBreak(); 1855 | return true; 1856 | } 1857 | 1858 | 1859 | bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) 1860 | { 1861 | DoIndent(); 1862 | buffer += "<"; 1863 | buffer += unknown.Value(); 1864 | buffer += ">"; 1865 | DoLineBreak(); 1866 | return true; 1867 | } 1868 | 1869 | -------------------------------------------------------------------------------- /XmlEdit/Xml/TinyXml/tinyxml.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) 4 | 5 | This software is provided 'as-is', without any express or implied 6 | warranty. In no event will the authors be held liable for any 7 | damages arising from the use of this software. 8 | 9 | Permission is granted to anyone to use this software for any 10 | purpose, including commercial applications, and to alter it and 11 | redistribute it freely, subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must 14 | not claim that you wrote the original software. If you use this 15 | software in a product, an acknowledgment in the product documentation 16 | would be appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source 22 | distribution. 23 | */ 24 | 25 | #include "stdafx.h" 26 | 27 | #include 28 | 29 | #ifdef TIXML_USE_STL 30 | #include 31 | #include 32 | #endif 33 | 34 | #include "tinyxml.h" 35 | 36 | 37 | bool TiXmlBase::condenseWhiteSpace = true; 38 | 39 | void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString ) 40 | { 41 | int i=0; 42 | 43 | while( i<(int)str.length() ) 44 | { 45 | unsigned char c = (unsigned char) str[i]; 46 | 47 | if ( c == '&' 48 | && i < ( (int)str.length() - 2 ) 49 | && str[i+1] == '#' 50 | && str[i+2] == 'x' ) 51 | { 52 | // Hexadecimal character reference. 53 | // Pass through unchanged. 54 | // © -- copyright symbol, for example. 55 | // 56 | // The -1 is a bug fix from Rob Laveaux. It keeps 57 | // an overflow from happening if there is no ';'. 58 | // There are actually 2 ways to exit this loop - 59 | // while fails (error case) and break (semicolon found). 60 | // However, there is no mechanism (currently) for 61 | // this function to return an error. 62 | while ( i<(int)str.length()-1 ) 63 | { 64 | outString->append( str.c_str() + i, 1 ); 65 | ++i; 66 | if ( str[i] == ';' ) 67 | break; 68 | } 69 | } 70 | else if ( c == '&' ) 71 | { 72 | outString->append( entity[0].str, entity[0].strLength ); 73 | ++i; 74 | } 75 | else if ( c == '<' ) 76 | { 77 | outString->append( entity[1].str, entity[1].strLength ); 78 | ++i; 79 | } 80 | else if ( c == '>' ) 81 | { 82 | outString->append( entity[2].str, entity[2].strLength ); 83 | ++i; 84 | } 85 | else if ( c == '\"' ) 86 | { 87 | outString->append( entity[3].str, entity[3].strLength ); 88 | ++i; 89 | } 90 | else if ( c == '\'' ) 91 | { 92 | outString->append( entity[4].str, entity[4].strLength ); 93 | ++i; 94 | } 95 | else if ( c < 32 ) 96 | { 97 | // Easy pass at non-alpha/numeric/symbol 98 | // Below 32 is symbolic. 99 | char buf[ 32 ]; 100 | 101 | #if defined(TIXML_SNPRINTF) 102 | TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); 103 | #else 104 | sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); 105 | #endif 106 | 107 | //*ME: warning C4267: convert 'size_t' to 'int' 108 | //*ME: Int-Cast to make compiler happy ... 109 | outString->append( buf, (int)strlen( buf ) ); 110 | ++i; 111 | } 112 | else 113 | { 114 | //char realc = (char) c; 115 | //outString->append( &realc, 1 ); 116 | *outString += (char) c; // somewhat more efficient function call. 117 | ++i; 118 | } 119 | } 120 | } 121 | 122 | 123 | TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() 124 | { 125 | parent = 0; 126 | type = _type; 127 | firstChild = 0; 128 | lastChild = 0; 129 | prev = 0; 130 | next = 0; 131 | } 132 | 133 | 134 | TiXmlNode::~TiXmlNode() 135 | { 136 | TiXmlNode* node = firstChild; 137 | TiXmlNode* temp = 0; 138 | 139 | while ( node ) 140 | { 141 | temp = node; 142 | node = node->next; 143 | delete temp; 144 | } 145 | } 146 | 147 | 148 | void TiXmlNode::CopyTo( TiXmlNode* target ) const 149 | { 150 | target->SetValue (value.c_str() ); 151 | target->userData = userData; 152 | } 153 | 154 | 155 | void TiXmlNode::Clear() 156 | { 157 | TiXmlNode* node = firstChild; 158 | TiXmlNode* temp = 0; 159 | 160 | while ( node ) 161 | { 162 | temp = node; 163 | node = node->next; 164 | delete temp; 165 | } 166 | 167 | firstChild = 0; 168 | lastChild = 0; 169 | } 170 | 171 | 172 | TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) 173 | { 174 | assert( node->parent == 0 || node->parent == this ); 175 | assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); 176 | 177 | if ( node->Type() == TiXmlNode::DOCUMENT ) 178 | { 179 | delete node; 180 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 181 | return 0; 182 | } 183 | 184 | node->parent = this; 185 | 186 | node->prev = lastChild; 187 | node->next = 0; 188 | 189 | if ( lastChild ) 190 | lastChild->next = node; 191 | else 192 | firstChild = node; // it was an empty list. 193 | 194 | lastChild = node; 195 | return node; 196 | } 197 | 198 | 199 | TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) 200 | { 201 | if ( addThis.Type() == TiXmlNode::DOCUMENT ) 202 | { 203 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 204 | return 0; 205 | } 206 | TiXmlNode* node = addThis.Clone(); 207 | if ( !node ) 208 | return 0; 209 | 210 | return LinkEndChild( node ); 211 | } 212 | 213 | 214 | TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) 215 | { 216 | if ( !beforeThis || beforeThis->parent != this ) { 217 | return 0; 218 | } 219 | if ( addThis.Type() == TiXmlNode::DOCUMENT ) 220 | { 221 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 222 | return 0; 223 | } 224 | 225 | TiXmlNode* node = addThis.Clone(); 226 | if ( !node ) 227 | return 0; 228 | node->parent = this; 229 | 230 | node->next = beforeThis; 231 | node->prev = beforeThis->prev; 232 | if ( beforeThis->prev ) 233 | { 234 | beforeThis->prev->next = node; 235 | } 236 | else 237 | { 238 | assert( firstChild == beforeThis ); 239 | firstChild = node; 240 | } 241 | beforeThis->prev = node; 242 | return node; 243 | } 244 | 245 | 246 | TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) 247 | { 248 | if ( !afterThis || afterThis->parent != this ) { 249 | return 0; 250 | } 251 | if ( addThis.Type() == TiXmlNode::DOCUMENT ) 252 | { 253 | if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 254 | return 0; 255 | } 256 | 257 | TiXmlNode* node = addThis.Clone(); 258 | if ( !node ) 259 | return 0; 260 | node->parent = this; 261 | 262 | node->prev = afterThis; 263 | node->next = afterThis->next; 264 | if ( afterThis->next ) 265 | { 266 | afterThis->next->prev = node; 267 | } 268 | else 269 | { 270 | assert( lastChild == afterThis ); 271 | lastChild = node; 272 | } 273 | afterThis->next = node; 274 | return node; 275 | } 276 | 277 | 278 | TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) 279 | { 280 | if ( replaceThis->parent != this ) 281 | return 0; 282 | 283 | TiXmlNode* node = withThis.Clone(); 284 | if ( !node ) 285 | return 0; 286 | 287 | node->next = replaceThis->next; 288 | node->prev = replaceThis->prev; 289 | 290 | if ( replaceThis->next ) 291 | replaceThis->next->prev = node; 292 | else 293 | lastChild = node; 294 | 295 | if ( replaceThis->prev ) 296 | replaceThis->prev->next = node; 297 | else 298 | firstChild = node; 299 | 300 | delete replaceThis; 301 | node->parent = this; 302 | return node; 303 | } 304 | 305 | 306 | bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) 307 | { 308 | if ( removeThis->parent != this ) 309 | { 310 | assert( 0 ); 311 | return false; 312 | } 313 | 314 | if ( removeThis->next ) 315 | removeThis->next->prev = removeThis->prev; 316 | else 317 | lastChild = removeThis->prev; 318 | 319 | if ( removeThis->prev ) 320 | removeThis->prev->next = removeThis->next; 321 | else 322 | firstChild = removeThis->next; 323 | 324 | delete removeThis; 325 | return true; 326 | } 327 | 328 | const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const 329 | { 330 | const TiXmlNode* node; 331 | for ( node = firstChild; node; node = node->next ) 332 | { 333 | if ( strcmp( node->Value(), _value ) == 0 ) 334 | return node; 335 | } 336 | return 0; 337 | } 338 | 339 | 340 | const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const 341 | { 342 | const TiXmlNode* node; 343 | for ( node = lastChild; node; node = node->prev ) 344 | { 345 | if ( strcmp( node->Value(), _value ) == 0 ) 346 | return node; 347 | } 348 | return 0; 349 | } 350 | 351 | 352 | const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const 353 | { 354 | if ( !previous ) 355 | { 356 | return FirstChild(); 357 | } 358 | else 359 | { 360 | assert( previous->parent == this ); 361 | return previous->NextSibling(); 362 | } 363 | } 364 | 365 | 366 | const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const 367 | { 368 | if ( !previous ) 369 | { 370 | return FirstChild( val ); 371 | } 372 | else 373 | { 374 | assert( previous->parent == this ); 375 | return previous->NextSibling( val ); 376 | } 377 | } 378 | 379 | 380 | const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const 381 | { 382 | const TiXmlNode* node; 383 | for ( node = next; node; node = node->next ) 384 | { 385 | if ( strcmp( node->Value(), _value ) == 0 ) 386 | return node; 387 | } 388 | return 0; 389 | } 390 | 391 | 392 | const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const 393 | { 394 | const TiXmlNode* node; 395 | for ( node = prev; node; node = node->prev ) 396 | { 397 | if ( strcmp( node->Value(), _value ) == 0 ) 398 | return node; 399 | } 400 | return 0; 401 | } 402 | 403 | 404 | void TiXmlElement::RemoveAttribute( const char * name ) 405 | { 406 | #ifdef TIXML_USE_STL 407 | TIXML_STRING str( name ); 408 | TiXmlAttribute* node = attributeSet.Find( str ); 409 | #else 410 | TiXmlAttribute* node = attributeSet.Find( name ); 411 | #endif 412 | if ( node ) 413 | { 414 | attributeSet.Remove( node ); 415 | delete node; 416 | } 417 | } 418 | 419 | const TiXmlElement* TiXmlNode::FirstChildElement() const 420 | { 421 | const TiXmlNode* node; 422 | 423 | for ( node = FirstChild(); 424 | node; 425 | node = node->NextSibling() ) 426 | { 427 | if ( node->ToElement() ) 428 | return node->ToElement(); 429 | } 430 | return 0; 431 | } 432 | 433 | 434 | const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const 435 | { 436 | const TiXmlNode* node; 437 | 438 | for ( node = FirstChild( _value ); 439 | node; 440 | node = node->NextSibling( _value ) ) 441 | { 442 | if ( node->ToElement() ) 443 | return node->ToElement(); 444 | } 445 | return 0; 446 | } 447 | 448 | 449 | const TiXmlElement* TiXmlNode::NextSiblingElement() const 450 | { 451 | const TiXmlNode* node; 452 | 453 | for ( node = NextSibling(); 454 | node; 455 | node = node->NextSibling() ) 456 | { 457 | if ( node->ToElement() ) 458 | return node->ToElement(); 459 | } 460 | return 0; 461 | } 462 | 463 | 464 | const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const 465 | { 466 | const TiXmlNode* node; 467 | 468 | for ( node = NextSibling( _value ); 469 | node; 470 | node = node->NextSibling( _value ) ) 471 | { 472 | if ( node->ToElement() ) 473 | return node->ToElement(); 474 | } 475 | return 0; 476 | } 477 | 478 | 479 | const TiXmlDocument* TiXmlNode::GetDocument() const 480 | { 481 | const TiXmlNode* node; 482 | 483 | for( node = this; node; node = node->parent ) 484 | { 485 | if ( node->ToDocument() ) 486 | return node->ToDocument(); 487 | } 488 | return 0; 489 | } 490 | 491 | 492 | TiXmlElement::TiXmlElement (const char * _value) 493 | : TiXmlNode( TiXmlNode::ELEMENT ) 494 | { 495 | firstChild = lastChild = 0; 496 | value = _value; 497 | } 498 | 499 | 500 | #ifdef TIXML_USE_STL 501 | TiXmlElement::TiXmlElement( const std::string& _value ) 502 | : TiXmlNode( TiXmlNode::ELEMENT ) 503 | { 504 | firstChild = lastChild = 0; 505 | value = _value; 506 | } 507 | #endif 508 | 509 | 510 | TiXmlElement::TiXmlElement( const TiXmlElement& copy) 511 | : TiXmlNode( TiXmlNode::ELEMENT ) 512 | { 513 | firstChild = lastChild = 0; 514 | copy.CopyTo( this ); 515 | } 516 | 517 | 518 | void TiXmlElement::operator=( const TiXmlElement& base ) 519 | { 520 | ClearThis(); 521 | base.CopyTo( this ); 522 | } 523 | 524 | 525 | TiXmlElement::~TiXmlElement() 526 | { 527 | ClearThis(); 528 | } 529 | 530 | 531 | void TiXmlElement::ClearThis() 532 | { 533 | Clear(); 534 | while( attributeSet.First() ) 535 | { 536 | TiXmlAttribute* node = attributeSet.First(); 537 | attributeSet.Remove( node ); 538 | delete node; 539 | } 540 | } 541 | 542 | 543 | const char* TiXmlElement::Attribute( const char* name ) const 544 | { 545 | const TiXmlAttribute* node = attributeSet.Find( name ); 546 | if ( node ) 547 | return node->Value(); 548 | return 0; 549 | } 550 | 551 | 552 | #ifdef TIXML_USE_STL 553 | const std::string* TiXmlElement::Attribute( const std::string& name ) const 554 | { 555 | const TiXmlAttribute* node = attributeSet.Find( name ); 556 | if ( node ) 557 | return &node->ValueStr(); 558 | return 0; 559 | } 560 | #endif 561 | 562 | 563 | const char* TiXmlElement::Attribute( const char* name, int* i ) const 564 | { 565 | const char* s = Attribute( name ); 566 | if ( i ) 567 | { 568 | if ( s ) { 569 | *i = atoi( s ); 570 | } 571 | else { 572 | *i = 0; 573 | } 574 | } 575 | return s; 576 | } 577 | 578 | 579 | #ifdef TIXML_USE_STL 580 | const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const 581 | { 582 | const std::string* s = Attribute( name ); 583 | if ( i ) 584 | { 585 | if ( s ) { 586 | *i = atoi( s->c_str() ); 587 | } 588 | else { 589 | *i = 0; 590 | } 591 | } 592 | return s; 593 | } 594 | #endif 595 | 596 | 597 | const char* TiXmlElement::Attribute( const char* name, double* d ) const 598 | { 599 | const char* s = Attribute( name ); 600 | if ( d ) 601 | { 602 | if ( s ) { 603 | *d = atof( s ); 604 | } 605 | else { 606 | *d = 0; 607 | } 608 | } 609 | return s; 610 | } 611 | 612 | 613 | #ifdef TIXML_USE_STL 614 | const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const 615 | { 616 | const std::string* s = Attribute( name ); 617 | if ( d ) 618 | { 619 | if ( s ) { 620 | *d = atof( s->c_str() ); 621 | } 622 | else { 623 | *d = 0; 624 | } 625 | } 626 | return s; 627 | } 628 | #endif 629 | 630 | 631 | int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const 632 | { 633 | const TiXmlAttribute* node = attributeSet.Find( name ); 634 | if ( !node ) 635 | return TIXML_NO_ATTRIBUTE; 636 | return node->QueryIntValue( ival ); 637 | } 638 | 639 | 640 | #ifdef TIXML_USE_STL 641 | int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const 642 | { 643 | const TiXmlAttribute* node = attributeSet.Find( name ); 644 | if ( !node ) 645 | return TIXML_NO_ATTRIBUTE; 646 | return node->QueryIntValue( ival ); 647 | } 648 | #endif 649 | 650 | 651 | int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const 652 | { 653 | const TiXmlAttribute* node = attributeSet.Find( name ); 654 | if ( !node ) 655 | return TIXML_NO_ATTRIBUTE; 656 | return node->QueryDoubleValue( dval ); 657 | } 658 | 659 | 660 | #ifdef TIXML_USE_STL 661 | int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const 662 | { 663 | const TiXmlAttribute* node = attributeSet.Find( name ); 664 | if ( !node ) 665 | return TIXML_NO_ATTRIBUTE; 666 | return node->QueryDoubleValue( dval ); 667 | } 668 | #endif 669 | 670 | 671 | void TiXmlElement::SetAttribute( const char * name, int val ) 672 | { 673 | char buf[64]; 674 | #if defined(TIXML_SNPRINTF) 675 | TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); 676 | #else 677 | sprintf( buf, "%d", val ); 678 | #endif 679 | SetAttribute( name, buf ); 680 | } 681 | 682 | 683 | #ifdef TIXML_USE_STL 684 | void TiXmlElement::SetAttribute( const std::string& name, int val ) 685 | { 686 | std::ostringstream oss; 687 | oss << val; 688 | SetAttribute( name, oss.str() ); 689 | } 690 | #endif 691 | 692 | 693 | void TiXmlElement::SetDoubleAttribute( const char * name, double val ) 694 | { 695 | char buf[256]; 696 | #if defined(TIXML_SNPRINTF) 697 | TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); 698 | #else 699 | sprintf( buf, "%f", val ); 700 | #endif 701 | SetAttribute( name, buf ); 702 | } 703 | 704 | 705 | void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) 706 | { 707 | #ifdef TIXML_USE_STL 708 | TIXML_STRING _name( cname ); 709 | TIXML_STRING _value( cvalue ); 710 | #else 711 | const char* _name = cname; 712 | const char* _value = cvalue; 713 | #endif 714 | 715 | TiXmlAttribute* node = attributeSet.Find( _name ); 716 | if ( node ) 717 | { 718 | node->SetValue( _value ); 719 | return; 720 | } 721 | 722 | TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue ); 723 | if ( attrib ) 724 | { 725 | attributeSet.Add( attrib ); 726 | } 727 | else 728 | { 729 | TiXmlDocument* document = GetDocument(); 730 | if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); 731 | } 732 | } 733 | 734 | 735 | #ifdef TIXML_USE_STL 736 | void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) 737 | { 738 | TiXmlAttribute* node = attributeSet.Find( name ); 739 | if ( node ) 740 | { 741 | node->SetValue( _value ); 742 | return; 743 | } 744 | 745 | TiXmlAttribute* attrib = new TiXmlAttribute( name, _value ); 746 | if ( attrib ) 747 | { 748 | attributeSet.Add( attrib ); 749 | } 750 | else 751 | { 752 | TiXmlDocument* document = GetDocument(); 753 | if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); 754 | } 755 | } 756 | #endif 757 | 758 | 759 | void TiXmlElement::Print( FILE* cfile, int depth ) const 760 | { 761 | int i; 762 | assert( cfile ); 763 | for ( i=0; iNext() ) 771 | { 772 | fprintf( cfile, " " ); 773 | attrib->Print( cfile, depth ); 774 | } 775 | 776 | // There are 3 different formatting approaches: 777 | // 1) An element without children is printed as a node 778 | // 2) An element with only a text child is printed as text 779 | // 3) An element with children is printed on multiple lines. 780 | TiXmlNode* node; 781 | if ( !firstChild ) 782 | { 783 | fprintf( cfile, " />" ); 784 | } 785 | else if ( firstChild == lastChild && firstChild->ToText() ) 786 | { 787 | fprintf( cfile, ">" ); 788 | firstChild->Print( cfile, depth + 1 ); 789 | fprintf( cfile, "", value.c_str() ); 790 | } 791 | else 792 | { 793 | fprintf( cfile, ">" ); 794 | 795 | for ( node = firstChild; node; node=node->NextSibling() ) 796 | { 797 | if ( !node->ToText() ) 798 | { 799 | fprintf( cfile, "\n" ); 800 | } 801 | node->Print( cfile, depth+1 ); 802 | } 803 | fprintf( cfile, "\n" ); 804 | for( i=0; i", value.c_str() ); 808 | } 809 | } 810 | 811 | 812 | void TiXmlElement::CopyTo( TiXmlElement* target ) const 813 | { 814 | // superclass: 815 | TiXmlNode::CopyTo( target ); 816 | 817 | // Element class: 818 | // Clone the attributes, then clone the children. 819 | const TiXmlAttribute* attribute = 0; 820 | for( attribute = attributeSet.First(); 821 | attribute; 822 | attribute = attribute->Next() ) 823 | { 824 | target->SetAttribute( attribute->Name(), attribute->Value() ); 825 | } 826 | 827 | TiXmlNode* node = 0; 828 | for ( node = firstChild; node; node = node->NextSibling() ) 829 | { 830 | target->LinkEndChild( node->Clone() ); 831 | } 832 | } 833 | 834 | bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const 835 | { 836 | if ( visitor->VisitEnter( *this, attributeSet.First() ) ) 837 | { 838 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) 839 | { 840 | if ( !node->Accept( visitor ) ) 841 | break; 842 | } 843 | } 844 | return visitor->VisitExit( *this ); 845 | } 846 | 847 | 848 | TiXmlNode* TiXmlElement::Clone() const 849 | { 850 | TiXmlElement* clone = new TiXmlElement( Value() ); 851 | if ( !clone ) 852 | return 0; 853 | 854 | CopyTo( clone ); 855 | return clone; 856 | } 857 | 858 | 859 | const char* TiXmlElement::GetText() const 860 | { 861 | const TiXmlNode* child = this->FirstChild(); 862 | if ( child ) { 863 | const TiXmlText* childText = child->ToText(); 864 | if ( childText ) { 865 | return childText->Value(); 866 | } 867 | } 868 | return 0; 869 | } 870 | 871 | 872 | TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) 873 | { 874 | tabsize = 4; 875 | useMicrosoftBOM = false; 876 | ClearError(); 877 | } 878 | 879 | TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) 880 | { 881 | tabsize = 4; 882 | useMicrosoftBOM = false; 883 | value = documentName; 884 | ClearError(); 885 | } 886 | 887 | 888 | #ifdef TIXML_USE_STL 889 | TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) 890 | { 891 | tabsize = 4; 892 | useMicrosoftBOM = false; 893 | value = documentName; 894 | ClearError(); 895 | } 896 | #endif 897 | 898 | 899 | TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) 900 | { 901 | copy.CopyTo( this ); 902 | } 903 | 904 | 905 | void TiXmlDocument::operator=( const TiXmlDocument& copy ) 906 | { 907 | Clear(); 908 | copy.CopyTo( this ); 909 | } 910 | 911 | 912 | bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) 913 | { 914 | // See STL_STRING_BUG below. 915 | //StringToBuffer buf( value ); 916 | 917 | return LoadFile( Value(), encoding ); 918 | } 919 | 920 | 921 | bool TiXmlDocument::SaveFile() const 922 | { 923 | // See STL_STRING_BUG below. 924 | // StringToBuffer buf( value ); 925 | // 926 | // if ( buf.buffer && SaveFile( buf.buffer ) ) 927 | // return true; 928 | // 929 | // return false; 930 | return SaveFile( Value() ); 931 | } 932 | 933 | bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) 934 | { 935 | // There was a really terrifying little bug here. The code: 936 | // value = filename 937 | // in the STL case, cause the assignment method of the std::string to 938 | // be called. What is strange, is that the std::string had the same 939 | // address as it's c_str() method, and so bad things happen. Looks 940 | // like a bug in the Microsoft STL implementation. 941 | // Add an extra string to avoid the crash. 942 | TIXML_STRING filename( _filename ); 943 | value = filename; 944 | 945 | // reading in binary mode so that tinyxml can normalize the EOL 946 | FILE* file = fopen( value.c_str (), "rb" ); 947 | 948 | if ( file ) 949 | { 950 | bool result = LoadFile( file, encoding ); 951 | fclose( file ); 952 | return result; 953 | } 954 | else 955 | { 956 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); 957 | return false; 958 | } 959 | } 960 | 961 | bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) 962 | { 963 | if ( !file ) 964 | { 965 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); 966 | return false; 967 | } 968 | 969 | // Delete the existing data: 970 | Clear(); 971 | location.Clear(); 972 | 973 | // Get the file size, so we can pre-allocate the string. HUGE speed impact. 974 | long length = 0; 975 | fseek( file, 0, SEEK_END ); 976 | length = ftell( file ); 977 | fseek( file, 0, SEEK_SET ); 978 | 979 | // Strange case, but good to handle up front. 980 | if ( length == 0 ) 981 | { 982 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 983 | return false; 984 | } 985 | 986 | // If we have a file, assume it is all one big XML file, and read it in. 987 | // The document parser may decide the document ends sooner than the entire file, however. 988 | TIXML_STRING data; 989 | data.reserve( length ); 990 | 991 | // Subtle bug here. TinyXml did use fgets. But from the XML spec: 992 | // 2.11 End-of-Line Handling 993 | // 994 | // 995 | // ...the XML processor MUST behave as if it normalized all line breaks in external 996 | // parsed entities (including the document entity) on input, before parsing, by translating 997 | // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to 998 | // a single #xA character. 999 | // 1000 | // 1001 | // It is not clear fgets does that, and certainly isn't clear it works cross platform. 1002 | // Generally, you expect fgets to translate from the convention of the OS to the c/unix 1003 | // convention, and not work generally. 1004 | 1005 | /* 1006 | while( fgets( buf, sizeof(buf), file ) ) 1007 | { 1008 | data += buf; 1009 | } 1010 | */ 1011 | 1012 | char* buf = new char[ length+1 ]; 1013 | buf[0] = 0; 1014 | 1015 | if ( fread( buf, length, 1, file ) != 1 ) { 1016 | delete [] buf; 1017 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); 1018 | return false; 1019 | } 1020 | 1021 | const char* lastPos = buf; 1022 | const char* p = buf; 1023 | 1024 | buf[length] = 0; 1025 | while( *p ) { 1026 | assert( p < (buf+length) ); 1027 | if ( *p == 0xa ) { 1028 | // Newline character. No special rules for this. Append all the characters 1029 | // since the last string, and include the newline. 1030 | data.append( lastPos, (p-lastPos+1) ); // append, include the newline 1031 | ++p; // move past the newline 1032 | lastPos = p; // and point to the new buffer (may be 0) 1033 | assert( p <= (buf+length) ); 1034 | } 1035 | else if ( *p == 0xd ) { 1036 | // Carriage return. Append what we have so far, then 1037 | // handle moving forward in the buffer. 1038 | if ( (p-lastPos) > 0 ) { 1039 | data.append( lastPos, p-lastPos ); // do not add the CR 1040 | } 1041 | data += (char)0xa; // a proper newline 1042 | 1043 | if ( *(p+1) == 0xa ) { 1044 | // Carriage return - new line sequence 1045 | p += 2; 1046 | lastPos = p; 1047 | assert( p <= (buf+length) ); 1048 | } 1049 | else { 1050 | // it was followed by something else...that is presumably characters again. 1051 | ++p; 1052 | lastPos = p; 1053 | assert( p <= (buf+length) ); 1054 | } 1055 | } 1056 | else { 1057 | ++p; 1058 | } 1059 | } 1060 | // Handle any left over characters. 1061 | if ( p-lastPos ) { 1062 | data.append( lastPos, p-lastPos ); 1063 | } 1064 | delete [] buf; 1065 | buf = 0; 1066 | 1067 | Parse( data.c_str(), 0, encoding ); 1068 | 1069 | if ( Error() ) 1070 | return false; 1071 | else 1072 | return true; 1073 | } 1074 | 1075 | 1076 | bool TiXmlDocument::SaveFile( const char * filename ) const 1077 | { 1078 | // The old c stuff lives on... 1079 | FILE* fp = fopen( filename, "w" ); 1080 | if ( fp ) 1081 | { 1082 | bool result = SaveFile( fp ); 1083 | fclose( fp ); 1084 | return result; 1085 | } 1086 | return false; 1087 | } 1088 | 1089 | 1090 | bool TiXmlDocument::SaveFile( FILE* fp ) const 1091 | { 1092 | if ( useMicrosoftBOM ) 1093 | { 1094 | const unsigned char TIXML_UTF_LEAD_0 = 0xefU; 1095 | const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; 1096 | const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; 1097 | 1098 | fputc( TIXML_UTF_LEAD_0, fp ); 1099 | fputc( TIXML_UTF_LEAD_1, fp ); 1100 | fputc( TIXML_UTF_LEAD_2, fp ); 1101 | } 1102 | Print( fp, 0 ); 1103 | return (ferror(fp) == 0); 1104 | } 1105 | 1106 | 1107 | void TiXmlDocument::CopyTo( TiXmlDocument* target ) const 1108 | { 1109 | TiXmlNode::CopyTo( target ); 1110 | 1111 | target->error = error; 1112 | target->errorDesc = errorDesc.c_str (); 1113 | 1114 | TiXmlNode* node = 0; 1115 | for ( node = firstChild; node; node = node->NextSibling() ) 1116 | { 1117 | target->LinkEndChild( node->Clone() ); 1118 | } 1119 | } 1120 | 1121 | 1122 | TiXmlNode* TiXmlDocument::Clone() const 1123 | { 1124 | TiXmlDocument* clone = new TiXmlDocument(); 1125 | if ( !clone ) 1126 | return 0; 1127 | 1128 | CopyTo( clone ); 1129 | return clone; 1130 | } 1131 | 1132 | 1133 | void TiXmlDocument::Print( FILE* cfile, int depth ) const 1134 | { 1135 | assert( cfile ); 1136 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) 1137 | { 1138 | node->Print( cfile, depth ); 1139 | fprintf( cfile, "\n" ); 1140 | } 1141 | } 1142 | 1143 | 1144 | bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const 1145 | { 1146 | if ( visitor->VisitEnter( *this ) ) 1147 | { 1148 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) 1149 | { 1150 | if ( !node->Accept( visitor ) ) 1151 | break; 1152 | } 1153 | } 1154 | return visitor->VisitExit( *this ); 1155 | } 1156 | 1157 | 1158 | const TiXmlAttribute* TiXmlAttribute::Next() const 1159 | { 1160 | // We are using knowledge of the sentinel. The sentinel 1161 | // have a value or name. 1162 | if ( next->value.empty() && next->name.empty() ) 1163 | return 0; 1164 | return next; 1165 | } 1166 | 1167 | /* 1168 | TiXmlAttribute* TiXmlAttribute::Next() 1169 | { 1170 | // We are using knowledge of the sentinel. The sentinel 1171 | // have a value or name. 1172 | if ( next->value.empty() && next->name.empty() ) 1173 | return 0; 1174 | return next; 1175 | } 1176 | */ 1177 | 1178 | const TiXmlAttribute* TiXmlAttribute::Previous() const 1179 | { 1180 | // We are using knowledge of the sentinel. The sentinel 1181 | // have a value or name. 1182 | if ( prev->value.empty() && prev->name.empty() ) 1183 | return 0; 1184 | return prev; 1185 | } 1186 | 1187 | /* 1188 | TiXmlAttribute* TiXmlAttribute::Previous() 1189 | { 1190 | // We are using knowledge of the sentinel. The sentinel 1191 | // have a value or name. 1192 | if ( prev->value.empty() && prev->name.empty() ) 1193 | return 0; 1194 | return prev; 1195 | } 1196 | */ 1197 | 1198 | void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const 1199 | { 1200 | TIXML_STRING n, v; 1201 | 1202 | PutString( name, &n ); 1203 | PutString( value, &v ); 1204 | 1205 | if (value.find ('\"') == TIXML_STRING::npos) { 1206 | if ( cfile ) { 1207 | fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); 1208 | } 1209 | if ( str ) { 1210 | (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; 1211 | } 1212 | } 1213 | else { 1214 | if ( cfile ) { 1215 | fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); 1216 | } 1217 | if ( str ) { 1218 | (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; 1219 | } 1220 | } 1221 | } 1222 | 1223 | 1224 | int TiXmlAttribute::QueryIntValue( int* ival ) const 1225 | { 1226 | if ( sscanf( value.c_str(), "%d", ival ) == 1 ) 1227 | return TIXML_SUCCESS; 1228 | return TIXML_WRONG_TYPE; 1229 | } 1230 | 1231 | int TiXmlAttribute::QueryDoubleValue( double* dval ) const 1232 | { 1233 | if ( sscanf( value.c_str(), "%lf", dval ) == 1 ) 1234 | return TIXML_SUCCESS; 1235 | return TIXML_WRONG_TYPE; 1236 | } 1237 | 1238 | void TiXmlAttribute::SetIntValue( int _value ) 1239 | { 1240 | char buf [64]; 1241 | #if defined(TIXML_SNPRINTF) 1242 | TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); 1243 | #else 1244 | sprintf (buf, "%d", _value); 1245 | #endif 1246 | SetValue (buf); 1247 | } 1248 | 1249 | void TiXmlAttribute::SetDoubleValue( double _value ) 1250 | { 1251 | char buf [256]; 1252 | #if defined(TIXML_SNPRINTF) 1253 | TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); 1254 | #else 1255 | sprintf (buf, "%lf", _value); 1256 | #endif 1257 | SetValue (buf); 1258 | } 1259 | 1260 | int TiXmlAttribute::IntValue() const 1261 | { 1262 | return atoi (value.c_str ()); 1263 | } 1264 | 1265 | double TiXmlAttribute::DoubleValue() const 1266 | { 1267 | return atof (value.c_str ()); 1268 | } 1269 | 1270 | 1271 | TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) 1272 | { 1273 | copy.CopyTo( this ); 1274 | } 1275 | 1276 | 1277 | void TiXmlComment::operator=( const TiXmlComment& base ) 1278 | { 1279 | Clear(); 1280 | base.CopyTo( this ); 1281 | } 1282 | 1283 | 1284 | void TiXmlComment::Print( FILE* cfile, int depth ) const 1285 | { 1286 | assert( cfile ); 1287 | for ( int i=0; i", value.c_str() ); 1292 | } 1293 | 1294 | 1295 | void TiXmlComment::CopyTo( TiXmlComment* target ) const 1296 | { 1297 | TiXmlNode::CopyTo( target ); 1298 | } 1299 | 1300 | 1301 | bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const 1302 | { 1303 | return visitor->Visit( *this ); 1304 | } 1305 | 1306 | 1307 | TiXmlNode* TiXmlComment::Clone() const 1308 | { 1309 | TiXmlComment* clone = new TiXmlComment(); 1310 | 1311 | if ( !clone ) 1312 | return 0; 1313 | 1314 | CopyTo( clone ); 1315 | return clone; 1316 | } 1317 | 1318 | 1319 | void TiXmlText::Print( FILE* cfile, int depth ) const 1320 | { 1321 | assert( cfile ); 1322 | if ( cdata ) 1323 | { 1324 | int i; 1325 | fprintf( cfile, "\n" ); 1326 | for ( i=0; i\n", value.c_str() ); // unformatted output 1330 | } 1331 | else 1332 | { 1333 | TIXML_STRING buffer; 1334 | PutString( value, &buffer ); 1335 | fprintf( cfile, "%s", buffer.c_str() ); 1336 | } 1337 | } 1338 | 1339 | 1340 | void TiXmlText::CopyTo( TiXmlText* target ) const 1341 | { 1342 | TiXmlNode::CopyTo( target ); 1343 | target->cdata = cdata; 1344 | } 1345 | 1346 | 1347 | bool TiXmlText::Accept( TiXmlVisitor* visitor ) const 1348 | { 1349 | return visitor->Visit( *this ); 1350 | } 1351 | 1352 | 1353 | TiXmlNode* TiXmlText::Clone() const 1354 | { 1355 | TiXmlText* clone = 0; 1356 | clone = new TiXmlText( "" ); 1357 | 1358 | if ( !clone ) 1359 | return 0; 1360 | 1361 | CopyTo( clone ); 1362 | return clone; 1363 | } 1364 | 1365 | 1366 | TiXmlDeclaration::TiXmlDeclaration( const char * _version, 1367 | const char * _encoding, 1368 | const char * _standalone ) 1369 | : TiXmlNode( TiXmlNode::DECLARATION ) 1370 | { 1371 | version = _version; 1372 | encoding = _encoding; 1373 | standalone = _standalone; 1374 | } 1375 | 1376 | 1377 | #ifdef TIXML_USE_STL 1378 | TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, 1379 | const std::string& _encoding, 1380 | const std::string& _standalone ) 1381 | : TiXmlNode( TiXmlNode::DECLARATION ) 1382 | { 1383 | version = _version; 1384 | encoding = _encoding; 1385 | standalone = _standalone; 1386 | } 1387 | #endif 1388 | 1389 | 1390 | TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) 1391 | : TiXmlNode( TiXmlNode::DECLARATION ) 1392 | { 1393 | copy.CopyTo( this ); 1394 | } 1395 | 1396 | 1397 | void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) 1398 | { 1399 | Clear(); 1400 | copy.CopyTo( this ); 1401 | } 1402 | 1403 | 1404 | void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const 1405 | { 1406 | if ( cfile ) fprintf( cfile, "" ); 1422 | if ( str ) (*str) += "?>"; 1423 | } 1424 | 1425 | 1426 | void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const 1427 | { 1428 | TiXmlNode::CopyTo( target ); 1429 | 1430 | target->version = version; 1431 | target->encoding = encoding; 1432 | target->standalone = standalone; 1433 | } 1434 | 1435 | 1436 | bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const 1437 | { 1438 | return visitor->Visit( *this ); 1439 | } 1440 | 1441 | 1442 | TiXmlNode* TiXmlDeclaration::Clone() const 1443 | { 1444 | TiXmlDeclaration* clone = new TiXmlDeclaration(); 1445 | 1446 | if ( !clone ) 1447 | return 0; 1448 | 1449 | CopyTo( clone ); 1450 | return clone; 1451 | } 1452 | 1453 | 1454 | void TiXmlUnknown::Print( FILE* cfile, int depth ) const 1455 | { 1456 | for ( int i=0; i", value.c_str() ); 1459 | } 1460 | 1461 | 1462 | void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const 1463 | { 1464 | TiXmlNode::CopyTo( target ); 1465 | } 1466 | 1467 | 1468 | bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const 1469 | { 1470 | return visitor->Visit( *this ); 1471 | } 1472 | 1473 | 1474 | TiXmlNode* TiXmlUnknown::Clone() const 1475 | { 1476 | TiXmlUnknown* clone = new TiXmlUnknown(); 1477 | 1478 | if ( !clone ) 1479 | return 0; 1480 | 1481 | CopyTo( clone ); 1482 | return clone; 1483 | } 1484 | 1485 | 1486 | TiXmlAttributeSet::TiXmlAttributeSet() 1487 | { 1488 | sentinel.next = &sentinel; 1489 | sentinel.prev = &sentinel; 1490 | } 1491 | 1492 | 1493 | TiXmlAttributeSet::~TiXmlAttributeSet() 1494 | { 1495 | assert( sentinel.next == &sentinel ); 1496 | assert( sentinel.prev == &sentinel ); 1497 | } 1498 | 1499 | 1500 | void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) 1501 | { 1502 | #ifdef TIXML_USE_STL 1503 | assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. 1504 | #else 1505 | assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. 1506 | #endif 1507 | 1508 | addMe->next = &sentinel; 1509 | addMe->prev = sentinel.prev; 1510 | 1511 | sentinel.prev->next = addMe; 1512 | sentinel.prev = addMe; 1513 | } 1514 | 1515 | void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) 1516 | { 1517 | TiXmlAttribute* node; 1518 | 1519 | for( node = sentinel.next; node != &sentinel; node = node->next ) 1520 | { 1521 | if ( node == removeMe ) 1522 | { 1523 | node->prev->next = node->next; 1524 | node->next->prev = node->prev; 1525 | node->next = 0; 1526 | node->prev = 0; 1527 | return; 1528 | } 1529 | } 1530 | assert( 0 ); // we tried to remove a non-linked attribute. 1531 | } 1532 | 1533 | 1534 | #ifdef TIXML_USE_STL 1535 | const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const 1536 | { 1537 | for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) 1538 | { 1539 | if ( node->name == name ) 1540 | return node; 1541 | } 1542 | return 0; 1543 | } 1544 | 1545 | /* 1546 | TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) 1547 | { 1548 | for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) 1549 | { 1550 | if ( node->name == name ) 1551 | return node; 1552 | } 1553 | return 0; 1554 | } 1555 | */ 1556 | #endif 1557 | 1558 | 1559 | const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const 1560 | { 1561 | for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) 1562 | { 1563 | if ( strcmp( node->name.c_str(), name ) == 0 ) 1564 | return node; 1565 | } 1566 | return 0; 1567 | } 1568 | 1569 | /* 1570 | TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) 1571 | { 1572 | for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) 1573 | { 1574 | if ( strcmp( node->name.c_str(), name ) == 0 ) 1575 | return node; 1576 | } 1577 | return 0; 1578 | } 1579 | */ 1580 | 1581 | #ifdef TIXML_USE_STL 1582 | std::istream& operator>> (std::istream & in, TiXmlNode & base) 1583 | { 1584 | TIXML_STRING tag; 1585 | tag.reserve( 8 * 1000 ); 1586 | base.StreamIn( &in, &tag ); 1587 | 1588 | base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); 1589 | return in; 1590 | } 1591 | #endif 1592 | 1593 | 1594 | #ifdef TIXML_USE_STL 1595 | std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) 1596 | { 1597 | TiXmlPrinter printer; 1598 | printer.SetStreamPrinting(); 1599 | base.Accept( &printer ); 1600 | out << printer.Str(); 1601 | 1602 | return out; 1603 | } 1604 | 1605 | 1606 | std::string& operator<< (std::string& out, const TiXmlNode& base ) 1607 | { 1608 | TiXmlPrinter printer; 1609 | printer.SetStreamPrinting(); 1610 | base.Accept( &printer ); 1611 | out.append( printer.Str() ); 1612 | 1613 | return out; 1614 | } 1615 | #endif 1616 | 1617 | 1618 | TiXmlHandle TiXmlHandle::FirstChild() const 1619 | { 1620 | if ( node ) 1621 | { 1622 | TiXmlNode* child = node->FirstChild(); 1623 | if ( child ) 1624 | return TiXmlHandle( child ); 1625 | } 1626 | return TiXmlHandle( 0 ); 1627 | } 1628 | 1629 | 1630 | TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const 1631 | { 1632 | if ( node ) 1633 | { 1634 | TiXmlNode* child = node->FirstChild( value ); 1635 | if ( child ) 1636 | return TiXmlHandle( child ); 1637 | } 1638 | return TiXmlHandle( 0 ); 1639 | } 1640 | 1641 | 1642 | TiXmlHandle TiXmlHandle::FirstChildElement() const 1643 | { 1644 | if ( node ) 1645 | { 1646 | TiXmlElement* child = node->FirstChildElement(); 1647 | if ( child ) 1648 | return TiXmlHandle( child ); 1649 | } 1650 | return TiXmlHandle( 0 ); 1651 | } 1652 | 1653 | 1654 | TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const 1655 | { 1656 | if ( node ) 1657 | { 1658 | TiXmlElement* child = node->FirstChildElement( value ); 1659 | if ( child ) 1660 | return TiXmlHandle( child ); 1661 | } 1662 | return TiXmlHandle( 0 ); 1663 | } 1664 | 1665 | 1666 | TiXmlHandle TiXmlHandle::Child( int count ) const 1667 | { 1668 | if ( node ) 1669 | { 1670 | int i; 1671 | TiXmlNode* child = node->FirstChild(); 1672 | for ( i=0; 1673 | child && iNextSibling(), ++i ) 1675 | { 1676 | // nothing 1677 | } 1678 | if ( child ) 1679 | return TiXmlHandle( child ); 1680 | } 1681 | return TiXmlHandle( 0 ); 1682 | } 1683 | 1684 | 1685 | TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const 1686 | { 1687 | if ( node ) 1688 | { 1689 | int i; 1690 | TiXmlNode* child = node->FirstChild( value ); 1691 | for ( i=0; 1692 | child && iNextSibling( value ), ++i ) 1694 | { 1695 | // nothing 1696 | } 1697 | if ( child ) 1698 | return TiXmlHandle( child ); 1699 | } 1700 | return TiXmlHandle( 0 ); 1701 | } 1702 | 1703 | 1704 | TiXmlHandle TiXmlHandle::ChildElement( int count ) const 1705 | { 1706 | if ( node ) 1707 | { 1708 | int i; 1709 | TiXmlElement* child = node->FirstChildElement(); 1710 | for ( i=0; 1711 | child && iNextSiblingElement(), ++i ) 1713 | { 1714 | // nothing 1715 | } 1716 | if ( child ) 1717 | return TiXmlHandle( child ); 1718 | } 1719 | return TiXmlHandle( 0 ); 1720 | } 1721 | 1722 | 1723 | TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const 1724 | { 1725 | if ( node ) 1726 | { 1727 | int i; 1728 | TiXmlElement* child = node->FirstChildElement( value ); 1729 | for ( i=0; 1730 | child && iNextSiblingElement( value ), ++i ) 1732 | { 1733 | // nothing 1734 | } 1735 | if ( child ) 1736 | return TiXmlHandle( child ); 1737 | } 1738 | return TiXmlHandle( 0 ); 1739 | } 1740 | 1741 | 1742 | bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) 1743 | { 1744 | return true; 1745 | } 1746 | 1747 | bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) 1748 | { 1749 | return true; 1750 | } 1751 | 1752 | bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) 1753 | { 1754 | DoIndent(); 1755 | buffer += "<"; 1756 | buffer += element.Value(); 1757 | 1758 | for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) 1759 | { 1760 | buffer += " "; 1761 | attrib->Print( 0, 0, &buffer ); 1762 | } 1763 | 1764 | if ( !element.FirstChild() ) 1765 | { 1766 | buffer += " />"; 1767 | DoLineBreak(); 1768 | } 1769 | else 1770 | { 1771 | buffer += ">"; 1772 | if ( element.FirstChild()->ToText() 1773 | && element.LastChild() == element.FirstChild() 1774 | && element.FirstChild()->ToText()->CDATA() == false ) 1775 | { 1776 | simpleTextPrint = true; 1777 | // no DoLineBreak()! 1778 | } 1779 | else 1780 | { 1781 | DoLineBreak(); 1782 | } 1783 | } 1784 | ++depth; 1785 | return true; 1786 | } 1787 | 1788 | 1789 | bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) 1790 | { 1791 | --depth; 1792 | if ( !element.FirstChild() ) 1793 | { 1794 | // nothing. 1795 | } 1796 | else 1797 | { 1798 | if ( simpleTextPrint ) 1799 | { 1800 | simpleTextPrint = false; 1801 | } 1802 | else 1803 | { 1804 | DoIndent(); 1805 | } 1806 | buffer += ""; 1809 | DoLineBreak(); 1810 | } 1811 | return true; 1812 | } 1813 | 1814 | 1815 | bool TiXmlPrinter::Visit( const TiXmlText& text ) 1816 | { 1817 | if ( text.CDATA() ) 1818 | { 1819 | DoIndent(); 1820 | buffer += ""; 1823 | DoLineBreak(); 1824 | } 1825 | else if ( simpleTextPrint ) 1826 | { 1827 | buffer += text.Value(); 1828 | } 1829 | else 1830 | { 1831 | DoIndent(); 1832 | buffer += text.Value(); 1833 | DoLineBreak(); 1834 | } 1835 | return true; 1836 | } 1837 | 1838 | 1839 | bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) 1840 | { 1841 | DoIndent(); 1842 | declaration.Print( 0, 0, &buffer ); 1843 | DoLineBreak(); 1844 | return true; 1845 | } 1846 | 1847 | 1848 | bool TiXmlPrinter::Visit( const TiXmlComment& comment ) 1849 | { 1850 | DoIndent(); 1851 | buffer += ""; 1854 | DoLineBreak(); 1855 | return true; 1856 | } 1857 | 1858 | 1859 | bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) 1860 | { 1861 | DoIndent(); 1862 | buffer += "<"; 1863 | buffer += unknown.Value(); 1864 | buffer += ">"; 1865 | DoLineBreak(); 1866 | return true; 1867 | } 1868 | 1869 | --------------------------------------------------------------------------------