├── 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), "%02X;", (unsigned) ( c & 0xff ) );
103 | #else
104 | sprintf( buf, "%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, "%s>", 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 += "";
1807 | buffer += element.Value();
1808 | 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), "%02X;", (unsigned) ( c & 0xff ) );
103 | #else
104 | sprintf( buf, "%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, "%s>", 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 += "";
1807 | buffer += element.Value();
1808 | 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 |
--------------------------------------------------------------------------------