├── include ├── sar_comm.h ├── Dem.h ├── SBAS.h ├── Utils.h ├── Deflat.h ├── Filter.h ├── Package.h ├── Unwrap.h ├── ComplexMat.h ├── Evaluation.h ├── Registration.h ├── globalparam.h ├── SLC_simulator.h ├── FormatConversion.h └── tinystr.h ├── Dem ├── Dem.cpp ├── stdafx.h ├── stdafx.cpp └── targetver.h ├── Deflat ├── stdafx.h ├── Deflat.cpp ├── stdafx.cpp └── targetver.h ├── Filter ├── stdafx.h ├── Filter.cpp ├── stdafx.cpp └── targetver.h ├── SBAS ├── SBAS.cpp ├── pch.cpp ├── framework.h └── pch.h ├── Unwrap ├── stdafx.h ├── Unwrap.cpp ├── stdafx.cpp └── targetver.h ├── Utils ├── Utils.cpp ├── stdafx.h ├── stdafx.cpp └── targetver.h ├── ComplexMat ├── stdafx.h ├── stdafx.cpp ├── targetver.h └── ComplexMat.cpp ├── Registration ├── stdafx.h ├── stdafx.cpp ├── targetver.h └── Registration.cpp ├── Evaluation ├── Evaluation.cpp ├── Evaluation.zip ├── framework.h ├── pch.h ├── tinyxmlerror.cpp ├── tinystr.cpp ├── tinyxmlparser.cpp └── tinyxml.cpp ├── simulation ├── SLC_simulator.cpp ├── pch.cpp ├── framework.h └── pch.h ├── FormatConversion ├── pch.cpp ├── FormatConversion.cpp ├── framework.h ├── pch.h ├── tinyxmlerror.cpp ├── tinystr.cpp └── tinyxmlparser.cpp ├── README.md ├── unziptool ├── unziptool.cpp ├── zip.h └── unzip.h └── .gitignore /include/sar_comm.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Dem/Dem.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Dem/Dem.cpp -------------------------------------------------------------------------------- /Dem/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Dem/stdafx.h -------------------------------------------------------------------------------- /Deflat/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Deflat/stdafx.h -------------------------------------------------------------------------------- /Dem/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Dem/stdafx.cpp -------------------------------------------------------------------------------- /Dem/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Dem/targetver.h -------------------------------------------------------------------------------- /Filter/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Filter/stdafx.h -------------------------------------------------------------------------------- /SBAS/SBAS.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/SBAS/SBAS.cpp -------------------------------------------------------------------------------- /Unwrap/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Unwrap/stdafx.h -------------------------------------------------------------------------------- /Utils/Utils.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Utils/Utils.cpp -------------------------------------------------------------------------------- /Utils/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Utils/stdafx.h -------------------------------------------------------------------------------- /include/Dem.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/Dem.h -------------------------------------------------------------------------------- /include/SBAS.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/SBAS.h -------------------------------------------------------------------------------- /include/Utils.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/Utils.h -------------------------------------------------------------------------------- /Deflat/Deflat.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Deflat/Deflat.cpp -------------------------------------------------------------------------------- /Deflat/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Deflat/stdafx.cpp -------------------------------------------------------------------------------- /Filter/Filter.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Filter/Filter.cpp -------------------------------------------------------------------------------- /Filter/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Filter/stdafx.cpp -------------------------------------------------------------------------------- /Unwrap/Unwrap.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Unwrap/Unwrap.cpp -------------------------------------------------------------------------------- /Unwrap/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Unwrap/stdafx.cpp -------------------------------------------------------------------------------- /Utils/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Utils/stdafx.cpp -------------------------------------------------------------------------------- /Utils/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Utils/targetver.h -------------------------------------------------------------------------------- /include/Deflat.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/Deflat.h -------------------------------------------------------------------------------- /include/Filter.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/Filter.h -------------------------------------------------------------------------------- /include/Package.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/Package.h -------------------------------------------------------------------------------- /include/Unwrap.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/Unwrap.h -------------------------------------------------------------------------------- /ComplexMat/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/ComplexMat/stdafx.h -------------------------------------------------------------------------------- /Deflat/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Deflat/targetver.h -------------------------------------------------------------------------------- /Filter/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Filter/targetver.h -------------------------------------------------------------------------------- /Unwrap/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Unwrap/targetver.h -------------------------------------------------------------------------------- /include/ComplexMat.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/ComplexMat.h -------------------------------------------------------------------------------- /include/Evaluation.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/Evaluation.h -------------------------------------------------------------------------------- /ComplexMat/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/ComplexMat/stdafx.cpp -------------------------------------------------------------------------------- /ComplexMat/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/ComplexMat/targetver.h -------------------------------------------------------------------------------- /Registration/stdafx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Registration/stdafx.h -------------------------------------------------------------------------------- /include/Registration.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/Registration.h -------------------------------------------------------------------------------- /include/globalparam.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/globalparam.h -------------------------------------------------------------------------------- /Evaluation/Evaluation.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Evaluation/Evaluation.cpp -------------------------------------------------------------------------------- /Evaluation/Evaluation.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Evaluation/Evaluation.zip -------------------------------------------------------------------------------- /Registration/stdafx.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Registration/stdafx.cpp -------------------------------------------------------------------------------- /Registration/targetver.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Registration/targetver.h -------------------------------------------------------------------------------- /include/SLC_simulator.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/SLC_simulator.h -------------------------------------------------------------------------------- /SBAS/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: 与预编译标头对应的源文件 2 | 3 | #include "pch.h" 4 | 5 | // 当使用预编译的头时,需要使用此源文件,编译才能成功。 6 | -------------------------------------------------------------------------------- /include/FormatConversion.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/include/FormatConversion.h -------------------------------------------------------------------------------- /Registration/Registration.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/Registration/Registration.cpp -------------------------------------------------------------------------------- /simulation/SLC_simulator.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/simulation/SLC_simulator.cpp -------------------------------------------------------------------------------- /simulation/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: 与预编译标头对应的源文件 2 | 3 | #include "pch.h" 4 | 5 | // 当使用预编译的头时,需要使用此源文件,编译才能成功。 6 | -------------------------------------------------------------------------------- /FormatConversion/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: 与预编译标头对应的源文件 2 | 3 | #include "pch.h" 4 | 5 | // 当使用预编译的头时,需要使用此源文件,编译才能成功。 6 | -------------------------------------------------------------------------------- /FormatConversion/FormatConversion.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zengguobing/InSAR/HEAD/FormatConversion/FormatConversion.cpp -------------------------------------------------------------------------------- /SBAS/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 4 | // Windows 头文件 5 | #include 6 | -------------------------------------------------------------------------------- /Evaluation/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 4 | // Windows 头文件 5 | #include 6 | -------------------------------------------------------------------------------- /simulation/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 4 | // Windows 头文件 5 | #include 6 | -------------------------------------------------------------------------------- /FormatConversion/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 4 | // Windows 头文件 5 | #include 6 | -------------------------------------------------------------------------------- /SBAS/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: 这是预编译标头文件。 2 | // 下方列出的文件仅编译一次,提高了将来生成的生成性能。 3 | // 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 4 | // 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 5 | // 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // 添加要在此处预编译的标头 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /Evaluation/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: 这是预编译标头文件。 2 | // 下方列出的文件仅编译一次,提高了将来生成的生成性能。 3 | // 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 4 | // 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 5 | // 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // 添加要在此处预编译的标头 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /simulation/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: 这是预编译标头文件。 2 | // 下方列出的文件仅编译一次,提高了将来生成的生成性能。 3 | // 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 4 | // 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 5 | // 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // 添加要在此处预编译的标头 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /FormatConversion/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: 这是预编译标头文件。 2 | // 下方列出的文件仅编译一次,提高了将来生成的生成性能。 3 | // 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 4 | // 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 5 | // 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // 添加要在此处预编译的标头 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This is an C++ InSAR processing tools project, which includes SAR images co-registration, interferometric phase deramping, denoising, phase unwrapping, geocoding, DEM generation, SBAS-InSAR processing, etc. 4 | 5 | If you have any problems, feel free to contact me at guobing.zeng@ntu.edu.sg or zengguobing@buaa.edu.cn 6 | 7 | # Applicable SAR dataset 8 | 9 | Sentinel-1A/B/C, TerraSAR-X/TanDEM-X, ALOS2, COSMO-SkyMed, LuTan-1, Hongtu-1 constellation, Fucheng-1(Spacety). 10 | -------------------------------------------------------------------------------- /unziptool/unziptool.cpp: -------------------------------------------------------------------------------- 1 | // unziptool.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 2 | // 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include"zip.h" 12 | #include"unzip.h" 13 | using namespace std; 14 | int main(int argc, char* argv[]) 15 | { 16 | if (argc != 3) return -1; 17 | string srcFile(argv[1]); 18 | string dstPath(argv[2]); 19 | USES_CONVERSION; 20 | std::replace(srcFile.begin(), srcFile.end(), '/', '\\'); 21 | HZIP hz = OpenZip(A2W(srcFile.c_str()), 0); 22 | ZIPENTRY ze; GetZipItem(hz, -1, &ze); int numitems = ze.index; 23 | for (int i = 0; i < numitems; i++) 24 | { 25 | GetZipItem(hz, i, &ze); 26 | std::string str = dstPath + string("\\") + std::string(W2A(ze.name)); 27 | std::replace(str.begin(), str.end(), '/', '\\'); 28 | UnzipItem(hz, i, A2W(str.c_str())); 29 | } 30 | CloseZip(hz); 31 | return 0; 32 | } 33 | 34 | // 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 35 | // 调试程序: F5 或调试 >“开始调试”菜单 36 | 37 | // 入门使用技巧: 38 | // 1. 使用解决方案资源管理器窗口添加/管理文件 39 | // 2. 使用团队资源管理器窗口连接到源代码管理 40 | // 3. 使用输出窗口查看生成输出和其他消息 41 | // 4. 使用错误列表窗口查看错误 42 | // 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 43 | // 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 44 | -------------------------------------------------------------------------------- /Evaluation/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 | #include"pch.h" 25 | #include "tinyxml.h" 26 | 27 | // The goal of the seperate error file is to make the first 28 | // step towards localization. tinyxml (currently) only supports 29 | // english error messages, but the could now be translated. 30 | // 31 | // It also cleans up the code a bit. 32 | // 33 | 34 | const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] = 35 | { 36 | "No error", 37 | "Error", 38 | "Failed to open file", 39 | "Error parsing Element.", 40 | "Failed to read Element name", 41 | "Error reading Element value.", 42 | "Error reading Attributes.", 43 | "Error: empty tag.", 44 | "Error reading end tag.", 45 | "Error parsing Unknown.", 46 | "Error parsing Comment.", 47 | "Error parsing Declaration.", 48 | "Error document empty.", 49 | "Error null (0) or unexpected EOF found in input stream.", 50 | "Error parsing CDATA.", 51 | "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", 52 | }; 53 | -------------------------------------------------------------------------------- /FormatConversion/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 | #include"pch.h" 25 | #include "tinyxml.h" 26 | 27 | // The goal of the seperate error file is to make the first 28 | // step towards localization. tinyxml (currently) only supports 29 | // english error messages, but the could now be translated. 30 | // 31 | // It also cleans up the code a bit. 32 | // 33 | 34 | const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] = 35 | { 36 | "No error", 37 | "Error", 38 | "Failed to open file", 39 | "Error parsing Element.", 40 | "Failed to read Element name", 41 | "Error reading Element value.", 42 | "Error reading Attributes.", 43 | "Error: empty tag.", 44 | "Error reading end tag.", 45 | "Error parsing Unknown.", 46 | "Error parsing Comment.", 47 | "Error parsing Declaration.", 48 | "Error document empty.", 49 | "Error null (0) or unexpected EOF found in input stream.", 50 | "Error parsing CDATA.", 51 | "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", 52 | }; 53 | -------------------------------------------------------------------------------- /Evaluation/tinystr.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any 6 | damages arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any 9 | purpose, including commercial applications, and to alter it and 10 | redistribute it freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must 13 | not claim that you wrote the original software. If you use this 14 | software in a product, an acknowledgment in the product documentation 15 | would be appreciated but is not required. 16 | 17 | 2. Altered source versions must be plainly marked as such, and 18 | must not be misrepresented as being the original software. 19 | 20 | 3. This notice may not be removed or altered from any source 21 | distribution. 22 | */ 23 | 24 | #include"pch.h" 25 | #ifndef TIXML_USE_STL 26 | 27 | #include "tinystr.h" 28 | 29 | // Error value for find primitive 30 | const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); 31 | 32 | 33 | // Null rep. 34 | TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; 35 | 36 | 37 | void TiXmlString::reserve (size_type cap) 38 | { 39 | if (cap > capacity()) 40 | { 41 | TiXmlString tmp; 42 | tmp.init(length(), cap); 43 | memcpy(tmp.start(), data(), length()); 44 | swap(tmp); 45 | } 46 | } 47 | 48 | 49 | TiXmlString& TiXmlString::assign(const char* str, size_type len) 50 | { 51 | size_type cap = capacity(); 52 | if (len > cap || cap > 3*(len + 8)) 53 | { 54 | TiXmlString tmp; 55 | tmp.init(len); 56 | memcpy(tmp.start(), str, len); 57 | swap(tmp); 58 | } 59 | else 60 | { 61 | memmove(start(), str, len); 62 | set_size(len); 63 | } 64 | return *this; 65 | } 66 | 67 | 68 | TiXmlString& TiXmlString::append(const char* str, size_type len) 69 | { 70 | size_type newsize = length() + len; 71 | if (newsize > capacity()) 72 | { 73 | reserve (newsize + capacity()); 74 | } 75 | memmove(finish(), str, len); 76 | set_size(newsize); 77 | return *this; 78 | } 79 | 80 | 81 | TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) 82 | { 83 | TiXmlString tmp; 84 | tmp.reserve(a.length() + b.length()); 85 | tmp += a; 86 | tmp += b; 87 | return tmp; 88 | } 89 | 90 | TiXmlString operator + (const TiXmlString & a, const char* b) 91 | { 92 | TiXmlString tmp; 93 | TiXmlString::size_type b_len = static_cast( strlen(b) ); 94 | tmp.reserve(a.length() + b_len); 95 | tmp += a; 96 | tmp.append(b, b_len); 97 | return tmp; 98 | } 99 | 100 | TiXmlString operator + (const char* a, const TiXmlString & b) 101 | { 102 | TiXmlString tmp; 103 | TiXmlString::size_type a_len = static_cast( strlen(a) ); 104 | tmp.reserve(a_len + b.length()); 105 | tmp.append(a, a_len); 106 | tmp += b; 107 | return tmp; 108 | } 109 | 110 | 111 | #endif // TIXML_USE_STL 112 | -------------------------------------------------------------------------------- /FormatConversion/tinystr.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any 6 | damages arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any 9 | purpose, including commercial applications, and to alter it and 10 | redistribute it freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must 13 | not claim that you wrote the original software. If you use this 14 | software in a product, an acknowledgment in the product documentation 15 | would be appreciated but is not required. 16 | 17 | 2. Altered source versions must be plainly marked as such, and 18 | must not be misrepresented as being the original software. 19 | 20 | 3. This notice may not be removed or altered from any source 21 | distribution. 22 | */ 23 | 24 | #include"pch.h" 25 | #ifndef TIXML_USE_STL 26 | 27 | #include "tinystr.h" 28 | 29 | // Error value for find primitive 30 | const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); 31 | 32 | 33 | // Null rep. 34 | TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; 35 | 36 | 37 | void TiXmlString::reserve (size_type cap) 38 | { 39 | if (cap > capacity()) 40 | { 41 | TiXmlString tmp; 42 | tmp.init(length(), cap); 43 | memcpy(tmp.start(), data(), length()); 44 | swap(tmp); 45 | } 46 | } 47 | 48 | 49 | TiXmlString& TiXmlString::assign(const char* str, size_type len) 50 | { 51 | size_type cap = capacity(); 52 | if (len > cap || cap > 3*(len + 8)) 53 | { 54 | TiXmlString tmp; 55 | tmp.init(len); 56 | memcpy(tmp.start(), str, len); 57 | swap(tmp); 58 | } 59 | else 60 | { 61 | memmove(start(), str, len); 62 | set_size(len); 63 | } 64 | return *this; 65 | } 66 | 67 | 68 | TiXmlString& TiXmlString::append(const char* str, size_type len) 69 | { 70 | size_type newsize = length() + len; 71 | if (newsize > capacity()) 72 | { 73 | reserve (newsize + capacity()); 74 | } 75 | memmove(finish(), str, len); 76 | set_size(newsize); 77 | return *this; 78 | } 79 | 80 | 81 | TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) 82 | { 83 | TiXmlString tmp; 84 | tmp.reserve(a.length() + b.length()); 85 | tmp += a; 86 | tmp += b; 87 | return tmp; 88 | } 89 | 90 | TiXmlString operator + (const TiXmlString & a, const char* b) 91 | { 92 | TiXmlString tmp; 93 | TiXmlString::size_type b_len = static_cast( strlen(b) ); 94 | tmp.reserve(a.length() + b_len); 95 | tmp += a; 96 | tmp.append(b, b_len); 97 | return tmp; 98 | } 99 | 100 | TiXmlString operator + (const char* a, const TiXmlString & b) 101 | { 102 | TiXmlString tmp; 103 | TiXmlString::size_type a_len = static_cast( strlen(a) ); 104 | tmp.reserve(a_len + b.length()); 105 | tmp.append(a, a_len); 106 | tmp += b; 107 | return tmp; 108 | } 109 | 110 | 111 | #endif // TIXML_USE_STL 112 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ---> VisualStudio 2 | ## Ignore Visual Studio temporary files, build results, and 3 | ## files generated by popular Visual Studio add-ons. 4 | 5 | # User-specific files 6 | *.suo 7 | *.user 8 | *.userosscache 9 | *.sln.docstates 10 | 11 | # User-specific files (MonoDevelop/Xamarin Studio) 12 | *.userprefs 13 | 14 | # Build results 15 | [Dd]ebug/ 16 | [Dd]ebugPublic/ 17 | [Rr]elease/ 18 | [Rr]eleases/ 19 | x64/ 20 | x86/ 21 | build/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | 26 | # Visual Studio 2015 cache/options directory 27 | .vs/ 28 | # Uncomment if you have tasks that create the project's static files in wwwroot 29 | #wwwroot/ 30 | 31 | # MSTest test Results 32 | [Tt]est[Rr]esult*/ 33 | [Bb]uild[Ll]og.* 34 | 35 | # NUNIT 36 | *.VisualState.xml 37 | TestResult.xml 38 | 39 | # Build Results of an ATL Project 40 | [Dd]ebugPS/ 41 | [Rr]eleasePS/ 42 | dlldata.c 43 | 44 | # DNX 45 | project.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | 84 | # Visual Studio profiler 85 | *.psess 86 | *.vsp 87 | *.vspx 88 | *.sap 89 | 90 | # TFS 2012 Local Workspace 91 | $tf/ 92 | 93 | # Guidance Automation Toolkit 94 | *.gpState 95 | 96 | # ReSharper is a .NET coding add-in 97 | _ReSharper*/ 98 | *.[Rr]e[Ss]harper 99 | *.DotSettings.user 100 | 101 | # JustCode is a .NET coding add-in 102 | .JustCode 103 | 104 | # TeamCity is a build add-in 105 | _TeamCity* 106 | 107 | # DotCover is a Code Coverage Tool 108 | *.dotCover 109 | 110 | # NCrunch 111 | _NCrunch_* 112 | .*crunch*.local.xml 113 | nCrunchTemp_* 114 | 115 | # MightyMoose 116 | *.mm.* 117 | AutoTest.Net/ 118 | 119 | # Web workbench (sass) 120 | .sass-cache/ 121 | 122 | # Installshield output folder 123 | [Ee]xpress/ 124 | 125 | # DocProject is a documentation generator add-in 126 | DocProject/buildhelp/ 127 | DocProject/Help/*.HxT 128 | DocProject/Help/*.HxC 129 | DocProject/Help/*.hhc 130 | DocProject/Help/*.hhk 131 | DocProject/Help/*.hhp 132 | DocProject/Help/Html2 133 | DocProject/Help/html 134 | 135 | # Click-Once directory 136 | publish/ 137 | 138 | # Publish Web Output 139 | *.[Pp]ublish.xml 140 | *.azurePubxml 141 | # TODO: Comment the next line if you want to checkin your web deploy settings 142 | # but database connection strings (with potential passwords) will be unencrypted 143 | *.pubxml 144 | *.publishproj 145 | 146 | # NuGet Packages 147 | *.nupkg 148 | # The packages folder can be ignored because of Package Restore 149 | **/packages/* 150 | # except build/, which is used as an MSBuild target. 151 | !**/packages/build/ 152 | # Uncomment if necessary however generally it will be regenerated when needed 153 | #!**/packages/repositories.config 154 | 155 | # Windows Azure Build Output 156 | csx/ 157 | *.build.csdef 158 | 159 | # Windows Store app package directory 160 | AppPackages/ 161 | 162 | # Visual Studio cache files 163 | # files ending in .cache can be ignored 164 | *.[Cc]ache 165 | # but keep track of directories ending in .cache 166 | !*.[Cc]ache/ 167 | 168 | # Others 169 | ClientBin/ 170 | [Ss]tyle[Cc]op.* 171 | ~$* 172 | *~ 173 | *.dbmdl 174 | *.dbproj.schemaview 175 | *.pfx 176 | *.publishsettings 177 | node_modules/ 178 | orleans.codegen.cs 179 | 180 | # RIA/Silverlight projects 181 | Generated_Code/ 182 | 183 | # Backup & report files from converting an old project file 184 | # to a newer Visual Studio version. Backup files are not needed, 185 | # because we have git ;-) 186 | _UpgradeReport_Files/ 187 | Backup*/ 188 | UpgradeLog*.XML 189 | UpgradeLog*.htm 190 | 191 | # SQL Server files 192 | *.mdf 193 | *.ldf 194 | 195 | # Business Intelligence projects 196 | *.rdl.data 197 | *.bim.layout 198 | *.bim_*.settings 199 | 200 | # Microsoft Fakes 201 | FakesAssemblies/ 202 | 203 | # Node.js Tools for Visual Studio 204 | .ntvs_analysis.dat 205 | 206 | # Visual Studio 6 build log 207 | *.plg 208 | 209 | # Visual Studio 6 workspace options file 210 | *.opt 211 | 212 | # Visual Studio LightSwitch build output 213 | **/*.HTMLClient/GeneratedArtifacts 214 | **/*.DesktopClient/GeneratedArtifacts 215 | **/*.DesktopClient/ModelManifest.xml 216 | **/*.Server/GeneratedArtifacts 217 | **/*.Server/ModelManifest.xml 218 | _Pvt_Extensions 219 | 220 | # self defined ignore files 221 | 222 | test/ 223 | test2/ 224 | test3/ 225 | lib/ 226 | 227 | *.vcxproj 228 | *.filters 229 | *.docx 230 | *.sln 231 | dllmain.cpp 232 | ReadMe.txt 233 | 234 | 235 | -------------------------------------------------------------------------------- /include/tinystr.h: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any 6 | damages arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any 9 | purpose, including commercial applications, and to alter it and 10 | redistribute it freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must 13 | not claim that you wrote the original software. If you use this 14 | software in a product, an acknowledgment in the product documentation 15 | would be appreciated but is not required. 16 | 17 | 2. Altered source versions must be plainly marked as such, and 18 | must not be misrepresented as being the original software. 19 | 20 | 3. This notice may not be removed or altered from any source 21 | distribution. 22 | */ 23 | 24 | 25 | #ifndef TIXML_USE_STL 26 | 27 | #ifndef TIXML_STRING_INCLUDED 28 | #define TIXML_STRING_INCLUDED 29 | 30 | #include 31 | #include 32 | 33 | /* The support for explicit isn't that universal, and it isn't really 34 | required - it is used to check that the TiXmlString class isn't incorrectly 35 | used. Be nice to old compilers and macro it here: 36 | */ 37 | #if defined(_MSC_VER) && (_MSC_VER >= 1200 ) 38 | // Microsoft visual studio, version 6 and higher. 39 | #define TIXML_EXPLICIT explicit 40 | #elif defined(__GNUC__) && (__GNUC__ >= 3 ) 41 | // GCC version 3 and higher.s 42 | #define TIXML_EXPLICIT explicit 43 | #else 44 | #define TIXML_EXPLICIT 45 | #endif 46 | 47 | 48 | /* 49 | TiXmlString is an emulation of a subset of the std::string template. 50 | Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. 51 | Only the member functions relevant to the TinyXML project have been implemented. 52 | The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase 53 | a string and there's no more room, we allocate a buffer twice as big as we need. 54 | */ 55 | class TiXmlString 56 | { 57 | public : 58 | // The size type used 59 | typedef size_t size_type; 60 | 61 | // Error value for find primitive 62 | static const size_type npos; // = -1; 63 | 64 | 65 | // TiXmlString empty constructor 66 | TiXmlString () : rep_(&nullrep_) 67 | { 68 | } 69 | 70 | // TiXmlString copy constructor 71 | TiXmlString ( const TiXmlString & copy) : rep_(0) 72 | { 73 | init(copy.length()); 74 | memcpy(start(), copy.data(), length()); 75 | } 76 | 77 | // TiXmlString constructor, based on a string 78 | TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) 79 | { 80 | init( static_cast( strlen(copy) )); 81 | memcpy(start(), copy, length()); 82 | } 83 | 84 | // TiXmlString constructor, based on a string 85 | TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) 86 | { 87 | init(len); 88 | memcpy(start(), str, len); 89 | } 90 | 91 | // TiXmlString destructor 92 | ~TiXmlString () 93 | { 94 | quit(); 95 | } 96 | 97 | TiXmlString& operator = (const char * copy) 98 | { 99 | return assign( copy, (size_type)strlen(copy)); 100 | } 101 | 102 | TiXmlString& operator = (const TiXmlString & copy) 103 | { 104 | return assign(copy.start(), copy.length()); 105 | } 106 | 107 | 108 | // += operator. Maps to append 109 | TiXmlString& operator += (const char * suffix) 110 | { 111 | return append(suffix, static_cast( strlen(suffix) )); 112 | } 113 | 114 | // += operator. Maps to append 115 | TiXmlString& operator += (char single) 116 | { 117 | return append(&single, 1); 118 | } 119 | 120 | // += operator. Maps to append 121 | TiXmlString& operator += (const TiXmlString & suffix) 122 | { 123 | return append(suffix.data(), suffix.length()); 124 | } 125 | 126 | 127 | // Convert a TiXmlString into a null-terminated char * 128 | const char * c_str () const { return rep_->str; } 129 | 130 | // Convert a TiXmlString into a char * (need not be null terminated). 131 | const char * data () const { return rep_->str; } 132 | 133 | // Return the length of a TiXmlString 134 | size_type length () const { return rep_->size; } 135 | 136 | // Alias for length() 137 | size_type size () const { return rep_->size; } 138 | 139 | // Checks if a TiXmlString is empty 140 | bool empty () const { return rep_->size == 0; } 141 | 142 | // Return capacity of string 143 | size_type capacity () const { return rep_->capacity; } 144 | 145 | 146 | // single char extraction 147 | const char& at (size_type index) const 148 | { 149 | assert( index < length() ); 150 | return rep_->str[ index ]; 151 | } 152 | 153 | // [] operator 154 | char& operator [] (size_type index) const 155 | { 156 | assert( index < length() ); 157 | return rep_->str[ index ]; 158 | } 159 | 160 | // find a char in a string. Return TiXmlString::npos if not found 161 | size_type find (char lookup) const 162 | { 163 | return find(lookup, 0); 164 | } 165 | 166 | // find a char in a string from an offset. Return TiXmlString::npos if not found 167 | size_type find (char tofind, size_type offset) const 168 | { 169 | if (offset >= length()) return npos; 170 | 171 | for (const char* p = c_str() + offset; *p != '\0'; ++p) 172 | { 173 | if (*p == tofind) return static_cast< size_type >( p - c_str() ); 174 | } 175 | return npos; 176 | } 177 | 178 | void clear () 179 | { 180 | //Lee: 181 | //The original was just too strange, though correct: 182 | // TiXmlString().swap(*this); 183 | //Instead use the quit & re-init: 184 | quit(); 185 | init(0,0); 186 | } 187 | 188 | /* Function to reserve a big amount of data when we know we'll need it. Be aware that this 189 | function DOES NOT clear the content of the TiXmlString if any exists. 190 | */ 191 | void reserve (size_type cap); 192 | 193 | TiXmlString& assign (const char* str, size_type len); 194 | 195 | TiXmlString& append (const char* str, size_type len); 196 | 197 | void swap (TiXmlString& other) 198 | { 199 | Rep* r = rep_; 200 | rep_ = other.rep_; 201 | other.rep_ = r; 202 | } 203 | 204 | private: 205 | 206 | void init(size_type sz) { init(sz, sz); } 207 | void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } 208 | char* start() const { return rep_->str; } 209 | char* finish() const { return rep_->str + rep_->size; } 210 | 211 | struct Rep 212 | { 213 | size_type size, capacity; 214 | char str[1]; 215 | }; 216 | 217 | void init(size_type sz, size_type cap) 218 | { 219 | if (cap) 220 | { 221 | // Lee: the original form: 222 | // rep_ = static_cast(operator new(sizeof(Rep) + cap)); 223 | // doesn't work in some cases of new being overloaded. Switching 224 | // to the normal allocation, although use an 'int' for systems 225 | // that are overly picky about structure alignment. 226 | const size_type bytesNeeded = sizeof(Rep) + cap; 227 | const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); 228 | rep_ = reinterpret_cast( new int[ intsNeeded ] ); 229 | 230 | rep_->str[ rep_->size = sz ] = '\0'; 231 | rep_->capacity = cap; 232 | } 233 | else 234 | { 235 | rep_ = &nullrep_; 236 | } 237 | } 238 | 239 | void quit() 240 | { 241 | if (rep_ != &nullrep_) 242 | { 243 | // The rep_ is really an array of ints. (see the allocator, above). 244 | // Cast it back before delete, so the compiler won't incorrectly call destructors. 245 | delete [] ( reinterpret_cast( rep_ ) ); 246 | } 247 | } 248 | 249 | Rep * rep_; 250 | static Rep nullrep_; 251 | 252 | } ; 253 | 254 | 255 | inline bool operator == (const TiXmlString & a, const TiXmlString & b) 256 | { 257 | return ( a.length() == b.length() ) // optimization on some platforms 258 | && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare 259 | } 260 | inline bool operator < (const TiXmlString & a, const TiXmlString & b) 261 | { 262 | return strcmp(a.c_str(), b.c_str()) < 0; 263 | } 264 | 265 | inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } 266 | inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } 267 | inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } 268 | inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } 269 | 270 | inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } 271 | inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } 272 | inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } 273 | inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } 274 | 275 | TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); 276 | TiXmlString operator + (const TiXmlString & a, const char* b); 277 | TiXmlString operator + (const char* a, const TiXmlString & b); 278 | 279 | 280 | /* 281 | TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. 282 | Only the operators that we need for TinyXML have been developped. 283 | */ 284 | class TiXmlOutStream : public TiXmlString 285 | { 286 | public : 287 | 288 | // TiXmlOutStream << operator. 289 | TiXmlOutStream & operator << (const TiXmlString & in) 290 | { 291 | *this += in; 292 | return *this; 293 | } 294 | 295 | // TiXmlOutStream << operator. 296 | TiXmlOutStream & operator << (const char * in) 297 | { 298 | *this += in; 299 | return *this; 300 | } 301 | 302 | } ; 303 | 304 | #endif // TIXML_STRING_INCLUDED 305 | #endif // TIXML_USE_STL 306 | -------------------------------------------------------------------------------- /unziptool/zip.h: -------------------------------------------------------------------------------- 1 | #ifndef _zip_H 2 | #define _zip_H 3 | 4 | 5 | // ZIP functions -- for creating zip files 6 | // This file is a repackaged form of the Info-Zip source code available 7 | // at www.info-zip.org. The original copyright notice may be found in 8 | // zip.cpp. The repackaging was done by Lucian Wischik to simplify and 9 | // extend its use in Windows/C++. Also to add encryption and unicode. 10 | 11 | 12 | #ifndef _unzip_H 13 | DECLARE_HANDLE(HZIP); 14 | #endif 15 | // An HZIP identifies a zip file that is being created 16 | 17 | typedef DWORD ZRESULT; 18 | // return codes from any of the zip functions. Listed later. 19 | 20 | 21 | 22 | HZIP CreateZip(const TCHAR *fn, const char *password); 23 | HZIP CreateZip(void *buf,unsigned int len, const char *password); 24 | HZIP CreateZipHandle(HANDLE h, const char *password); 25 | // CreateZip - call this to start the creation of a zip file. 26 | // As the zip is being created, it will be stored somewhere: 27 | // to a pipe: CreateZipHandle(hpipe_write); 28 | // in a file (by handle): CreateZipHandle(hfile); 29 | // in a file (by name): CreateZip("c:\\test.zip"); 30 | // in memory: CreateZip(buf, len); 31 | // or in pagefile memory: CreateZip(0, len); 32 | // The final case stores it in memory backed by the system paging file, 33 | // where the zip may not exceed len bytes. This is a bit friendlier than 34 | // allocating memory with new[]: it won't lead to fragmentation, and the 35 | // memory won't be touched unless needed. That means you can give very 36 | // large estimates of the maximum-size without too much worry. 37 | // As for the password, it lets you encrypt every file in the archive. 38 | // (This api doesn't support per-file encryption.) 39 | // Note: because pipes don't allow random access, the structure of a zipfile 40 | // created into a pipe is slightly different from that created into a file 41 | // or memory. In particular, the compressed-size of the item cannot be 42 | // stored in the zipfile until after the item itself. (Also, for an item added 43 | // itself via a pipe, the uncompressed-size might not either be known until 44 | // after.) This is not normally a problem. But if you try to unzip via a pipe 45 | // as well, then the unzipper will not know these things about the item until 46 | // after it has been unzipped. Therefore: for unzippers which don't just write 47 | // each item to disk or to a pipe, but instead pre-allocate memory space into 48 | // which to unzip them, then either you have to create the zip not to a pipe, 49 | // or you have to add items not from a pipe, or at least when adding items 50 | // from a pipe you have to specify the length. 51 | // Note: for windows-ce, you cannot close the handle until after CloseZip. 52 | // but for real windows, the zip makes its own copy of your handle, so you 53 | // can close yours anytime. 54 | 55 | 56 | ZRESULT ZipAdd(HZIP hz,const TCHAR *dstzn, const TCHAR *fn); 57 | ZRESULT ZipAdd(HZIP hz,const TCHAR *dstzn, void *src,unsigned int len); 58 | ZRESULT ZipAddHandle(HZIP hz,const TCHAR *dstzn, HANDLE h); 59 | ZRESULT ZipAddHandle(HZIP hz,const TCHAR *dstzn, HANDLE h, unsigned int len); 60 | ZRESULT ZipAddFolder(HZIP hz,const TCHAR *dstzn); 61 | // ZipAdd - call this for each file to be added to the zip. 62 | // dstzn is the name that the file will be stored as in the zip file. 63 | // The file to be added to the zip can come 64 | // from a pipe: ZipAddHandle(hz,"file.dat", hpipe_read); 65 | // from a file: ZipAddHandle(hz,"file.dat", hfile); 66 | // from a filen: ZipAdd(hz,"file.dat", "c:\\docs\\origfile.dat"); 67 | // from memory: ZipAdd(hz,"subdir\\file.dat", buf,len); 68 | // (folder): ZipAddFolder(hz,"subdir"); 69 | // Note: if adding an item from a pipe, and if also creating the zip file itself 70 | // to a pipe, then you might wish to pass a non-zero length to the ZipAddHandle 71 | // function. This will let the zipfile store the item's size ahead of the 72 | // compressed item itself, which in turn makes it easier when unzipping the 73 | // zipfile from a pipe. 74 | 75 | ZRESULT ZipGetMemory(HZIP hz, void **buf, unsigned long *len); 76 | // ZipGetMemory - If the zip was created in memory, via ZipCreate(0,len), 77 | // then this function will return information about that memory block. 78 | // buf will receive a pointer to its start, and len its length. 79 | // Note: you can't add any more after calling this. 80 | 81 | ZRESULT CloseZip(HZIP hz); 82 | // CloseZip - the zip handle must be closed with this function. 83 | 84 | unsigned int FormatZipMessage(ZRESULT code, TCHAR *buf,unsigned int len); 85 | // FormatZipMessage - given an error code, formats it as a string. 86 | // It returns the length of the error message. If buf/len points 87 | // to a real buffer, then it also writes as much as possible into there. 88 | 89 | 90 | 91 | // These are the result codes: 92 | #define ZR_OK 0x00000000 // nb. the pseudo-code zr-recent is never returned, 93 | #define ZR_RECENT 0x00000001 // but can be passed to FormatZipMessage. 94 | // The following come from general system stuff (e.g. files not openable) 95 | #define ZR_GENMASK 0x0000FF00 96 | #define ZR_NODUPH 0x00000100 // couldn't duplicate the handle 97 | #define ZR_NOFILE 0x00000200 // couldn't create/open the file 98 | #define ZR_NOALLOC 0x00000300 // failed to allocate some resource 99 | #define ZR_WRITE 0x00000400 // a general error writing to the file 100 | #define ZR_NOTFOUND 0x00000500 // couldn't find that file in the zip 101 | #define ZR_MORE 0x00000600 // there's still more data to be unzipped 102 | #define ZR_CORRUPT 0x00000700 // the zipfile is corrupt or not a zipfile 103 | #define ZR_READ 0x00000800 // a general error reading the file 104 | // The following come from mistakes on the part of the caller 105 | #define ZR_CALLERMASK 0x00FF0000 106 | #define ZR_ARGS 0x00010000 // general mistake with the arguments 107 | #define ZR_NOTMMAP 0x00020000 // tried to ZipGetMemory, but that only works on mmap zipfiles, which yours wasn't 108 | #define ZR_MEMSIZE 0x00030000 // the memory size is too small 109 | #define ZR_FAILED 0x00040000 // the thing was already failed when you called this function 110 | #define ZR_ENDED 0x00050000 // the zip creation has already been closed 111 | #define ZR_MISSIZE 0x00060000 // the indicated input file size turned out mistaken 112 | #define ZR_PARTIALUNZ 0x00070000 // the file had already been partially unzipped 113 | #define ZR_ZMODE 0x00080000 // tried to mix creating/opening a zip 114 | // The following come from bugs within the zip library itself 115 | #define ZR_BUGMASK 0xFF000000 116 | #define ZR_NOTINITED 0x01000000 // initialisation didn't work 117 | #define ZR_SEEK 0x02000000 // trying to seek in an unseekable file 118 | #define ZR_NOCHANGE 0x04000000 // changed its mind on storage, but not allowed 119 | #define ZR_FLATE 0x05000000 // an internal error in the de/inflation code 120 | 121 | 122 | 123 | 124 | 125 | 126 | // e.g. 127 | // 128 | // (1) Traditional use, creating a zipfile from existing files 129 | // HZIP hz = CreateZip("c:\\simple1.zip",0); 130 | // ZipAdd(hz,"znsimple.bmp", "c:\\simple.bmp"); 131 | // ZipAdd(hz,"znsimple.txt", "c:\\simple.txt"); 132 | // CloseZip(hz); 133 | // 134 | // (2) Memory use, creating an auto-allocated mem-based zip file from various sources 135 | // HZIP hz = CreateZip(0,100000, 0); 136 | // // adding a conventional file... 137 | // ZipAdd(hz,"src1.txt", "c:\\src1.txt"); 138 | // // adding something from memory... 139 | // char buf[1000]; for (int i=0; i<1000; i++) buf[i]=(char)(i&0x7F); 140 | // ZipAdd(hz,"file.dat", buf,1000); 141 | // // adding something from a pipe... 142 | // HANDLE hread,hwrite; CreatePipe(&hread,&hwrite,NULL,0); 143 | // HANDLE hthread = CreateThread(0,0,ThreadFunc,(void*)hwrite,0,0); 144 | // ZipAdd(hz,"unz3.dat", hread,1000); // the '1000' is optional. 145 | // WaitForSingleObject(hthread,INFINITE); 146 | // CloseHandle(hthread); CloseHandle(hread); 147 | // ... meanwhile DWORD WINAPI ThreadFunc(void *dat) 148 | // { HANDLE hwrite = (HANDLE)dat; 149 | // char buf[1000]={17}; 150 | // DWORD writ; WriteFile(hwrite,buf,1000,&writ,NULL); 151 | // CloseHandle(hwrite); 152 | // return 0; 153 | // } 154 | // // and now that the zip is created, let's do something with it: 155 | // void *zbuf; unsigned long zlen; ZipGetMemory(hz,&zbuf,&zlen); 156 | // HANDLE hfz = CreateFile("test2.zip",GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); 157 | // DWORD writ; WriteFile(hfz,zbuf,zlen,&writ,NULL); 158 | // CloseHandle(hfz); 159 | // CloseZip(hz); 160 | // 161 | // (3) Handle use, for file handles and pipes 162 | // HANDLE hzread,hzwrite; CreatePipe(&hzread,&hzwrite,0,0); 163 | // HANDLE hthread = CreateThread(0,0,ZipReceiverThread,(void*)hzread,0,0); 164 | // HZIP hz = CreateZipHandle(hzwrite,0); 165 | // // ... add to it 166 | // CloseZip(hz); 167 | // CloseHandle(hzwrite); 168 | // WaitForSingleObject(hthread,INFINITE); 169 | // CloseHandle(hthread); 170 | // ... meanwhile DWORD WINAPI ZipReceiverThread(void *dat) 171 | // { HANDLE hread = (HANDLE)dat; 172 | // char buf[1000]; 173 | // while (true) 174 | // { DWORD red; ReadFile(hread,buf,1000,&red,NULL); 175 | // // ... and do something with this zip data we're receiving 176 | // if (red==0) break; 177 | // } 178 | // CloseHandle(hread); 179 | // return 0; 180 | // } 181 | 182 | 183 | 184 | // Now we indulge in a little skullduggery so that the code works whether 185 | // the user has included just zip or both zip and unzip. 186 | // Idea: if header files for both zip and unzip are present, then presumably 187 | // the cpp files for zip and unzip are both present, so we will call 188 | // one or the other of them based on a dynamic choice. If the header file 189 | // for only one is present, then we will bind to that particular one. 190 | ZRESULT CloseZipZ(HZIP hz); 191 | unsigned int FormatZipMessageZ(ZRESULT code, char *buf,unsigned int len); 192 | bool IsZipHandleZ(HZIP hz); 193 | #ifdef _unzip_H 194 | #undef CloseZip 195 | #define CloseZip(hz) (IsZipHandleZ(hz)?CloseZipZ(hz):CloseZipU(hz)) 196 | #else 197 | #define CloseZip CloseZipZ 198 | #define FormatZipMessage FormatZipMessageZ 199 | #endif 200 | 201 | 202 | 203 | #endif 204 | -------------------------------------------------------------------------------- /unziptool/unzip.h: -------------------------------------------------------------------------------- 1 | #ifndef _unzip_H 2 | #define _unzip_H 3 | 4 | // UNZIPPING functions -- for unzipping. 5 | // This file is a repackaged form of extracts from the zlib code available 6 | // at www.gzip.org/zlib, by Jean-Loup Gailly and Mark Adler. The original 7 | // copyright notice may be found in unzip.cpp. The repackaging was done 8 | // by Lucian Wischik to simplify and extend its use in Windows/C++. Also 9 | // encryption and unicode filenames have been added. 10 | 11 | 12 | #ifndef _zip_H 13 | DECLARE_HANDLE(HZIP); 14 | #endif 15 | // An HZIP identifies a zip file that has been opened 16 | 17 | typedef DWORD ZRESULT; 18 | // return codes from any of the zip functions. Listed later. 19 | 20 | typedef struct 21 | { int index; // index of this file within the zip 22 | TCHAR name[MAX_PATH]; // filename within the zip 23 | DWORD attr; // attributes, as in GetFileAttributes. 24 | FILETIME atime,ctime,mtime;// access, create, modify filetimes 25 | long comp_size; // sizes of item, compressed and uncompressed. These 26 | long unc_size; // may be -1 if not yet known (e.g. being streamed in) 27 | } ZIPENTRY; 28 | 29 | 30 | HZIP OpenZip(const TCHAR *fn, const char *password); 31 | HZIP OpenZip(void *z,unsigned int len, const char *password); 32 | HZIP OpenZipHandle(HANDLE h, const char *password); 33 | // OpenZip - opens a zip file and returns a handle with which you can 34 | // subsequently examine its contents. You can open a zip file from: 35 | // from a pipe: OpenZipHandle(hpipe_read,0); 36 | // from a file (by handle): OpenZipHandle(hfile,0); 37 | // from a file (by name): OpenZip("c:\\test.zip","password"); 38 | // from a memory block: OpenZip(bufstart, buflen,0); 39 | // If the file is opened through a pipe, then items may only be 40 | // accessed in increasing order, and an item may only be unzipped once, 41 | // although GetZipItem can be called immediately before and after unzipping 42 | // it. If it's opened in any other way, then full random access is possible. 43 | // Note: pipe input is not yet implemented. 44 | // Note: zip passwords are ascii, not unicode. 45 | // Note: for windows-ce, you cannot close the handle until after CloseZip. 46 | // but for real windows, the zip makes its own copy of your handle, so you 47 | // can close yours anytime. 48 | 49 | ZRESULT GetZipItem(HZIP hz, int index, ZIPENTRY *ze); 50 | // GetZipItem - call this to get information about an item in the zip. 51 | // If index is -1 and the file wasn't opened through a pipe, 52 | // then it returns information about the whole zipfile 53 | // (and in particular ze.index returns the number of index items). 54 | // Note: the item might be a directory (ze.attr & FILE_ATTRIBUTE_DIRECTORY) 55 | // See below for notes on what happens when you unzip such an item. 56 | // Note: if you are opening the zip through a pipe, then random access 57 | // is not possible and GetZipItem(-1) fails and you can't discover the number 58 | // of items except by calling GetZipItem on each one of them in turn, 59 | // starting at 0, until eventually the call fails. Also, in the event that 60 | // you are opening through a pipe and the zip was itself created into a pipe, 61 | // then then comp_size and sometimes unc_size as well may not be known until 62 | // after the item has been unzipped. 63 | 64 | ZRESULT FindZipItem(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze); 65 | // FindZipItem - finds an item by name. ic means 'insensitive to case'. 66 | // It returns the index of the item, and returns information about it. 67 | // If nothing was found, then index is set to -1 and the function returns 68 | // an error code. 69 | 70 | ZRESULT UnzipItem(HZIP hz, int index, const TCHAR *fn); 71 | ZRESULT UnzipItem(HZIP hz, int index, void *z,unsigned int len); 72 | ZRESULT UnzipItemHandle(HZIP hz, int index, HANDLE h); 73 | // UnzipItem - given an index to an item, unzips it. You can unzip to: 74 | // to a pipe: UnzipItemHandle(hz,i, hpipe_write); 75 | // to a file (by handle): UnzipItemHandle(hz,i, hfile); 76 | // to a file (by name): UnzipItem(hz,i, ze.name); 77 | // to a memory block: UnzipItem(hz,i, buf,buflen); 78 | // In the final case, if the buffer isn't large enough to hold it all, 79 | // then the return code indicates that more is yet to come. If it was 80 | // large enough, and you want to know precisely how big, GetZipItem. 81 | // Note: zip files are normally stored with relative pathnames. If you 82 | // unzip with ZIP_FILENAME a relative pathname then the item gets created 83 | // relative to the current directory - it first ensures that all necessary 84 | // subdirectories have been created. Also, the item may itself be a directory. 85 | // If you unzip a directory with ZIP_FILENAME, then the directory gets created. 86 | // If you unzip it to a handle or a memory block, then nothing gets created 87 | // and it emits 0 bytes. 88 | ZRESULT SetUnzipBaseDir(HZIP hz, const TCHAR *dir); 89 | // if unzipping to a filename, and it's a relative filename, then it will be relative to here. 90 | // (defaults to current-directory). 91 | 92 | 93 | ZRESULT CloseZip(HZIP hz); 94 | // CloseZip - the zip handle must be closed with this function. 95 | 96 | unsigned int FormatZipMessage(ZRESULT code, TCHAR *buf,unsigned int len); 97 | // FormatZipMessage - given an error code, formats it as a string. 98 | // It returns the length of the error message. If buf/len points 99 | // to a real buffer, then it also writes as much as possible into there. 100 | 101 | 102 | // These are the result codes: 103 | #define ZR_OK 0x00000000 // nb. the pseudo-code zr-recent is never returned, 104 | #define ZR_RECENT 0x00000001 // but can be passed to FormatZipMessage. 105 | // The following come from general system stuff (e.g. files not openable) 106 | #define ZR_GENMASK 0x0000FF00 107 | #define ZR_NODUPH 0x00000100 // couldn't duplicate the handle 108 | #define ZR_NOFILE 0x00000200 // couldn't create/open the file 109 | #define ZR_NOALLOC 0x00000300 // failed to allocate some resource 110 | #define ZR_WRITE 0x00000400 // a general error writing to the file 111 | #define ZR_NOTFOUND 0x00000500 // couldn't find that file in the zip 112 | #define ZR_MORE 0x00000600 // there's still more data to be unzipped 113 | #define ZR_CORRUPT 0x00000700 // the zipfile is corrupt or not a zipfile 114 | #define ZR_READ 0x00000800 // a general error reading the file 115 | #define ZR_PASSWORD 0x00001000 // we didn't get the right password to unzip the file 116 | // The following come from mistakes on the part of the caller 117 | #define ZR_CALLERMASK 0x00FF0000 118 | #define ZR_ARGS 0x00010000 // general mistake with the arguments 119 | #define ZR_NOTMMAP 0x00020000 // tried to ZipGetMemory, but that only works on mmap zipfiles, which yours wasn't 120 | #define ZR_MEMSIZE 0x00030000 // the memory size is too small 121 | #define ZR_FAILED 0x00040000 // the thing was already failed when you called this function 122 | #define ZR_ENDED 0x00050000 // the zip creation has already been closed 123 | #define ZR_MISSIZE 0x00060000 // the indicated input file size turned out mistaken 124 | #define ZR_PARTIALUNZ 0x00070000 // the file had already been partially unzipped 125 | #define ZR_ZMODE 0x00080000 // tried to mix creating/opening a zip 126 | // The following come from bugs within the zip library itself 127 | #define ZR_BUGMASK 0xFF000000 128 | #define ZR_NOTINITED 0x01000000 // initialisation didn't work 129 | #define ZR_SEEK 0x02000000 // trying to seek in an unseekable file 130 | #define ZR_NOCHANGE 0x04000000 // changed its mind on storage, but not allowed 131 | #define ZR_FLATE 0x05000000 // an internal error in the de/inflation code 132 | 133 | 134 | 135 | 136 | 137 | // e.g. 138 | // 139 | // SetCurrentDirectory("c:\\docs\\stuff"); 140 | // HZIP hz = OpenZip("c:\\stuff.zip",0); 141 | // ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index; 142 | // for (int i=0; ire); 9 | tmp.copyTo(this->im); 10 | } 11 | 12 | ComplexMat::ComplexMat(Mat& re, Mat& im) 13 | { 14 | //this->re = re; 15 | //this->im = im; 16 | re.copyTo(this->re); 17 | im.copyTo(this->im); 18 | } 19 | 20 | ComplexMat::ComplexMat(int rows, int cols) 21 | { 22 | if (rows > 0 && cols > 0) 23 | { 24 | Mat tmp = Mat::zeros(rows, cols, CV_64F); 25 | tmp.copyTo(this->im); 26 | tmp.copyTo(this->re); 27 | } 28 | } 29 | 30 | ComplexMat::ComplexMat(const ComplexMat& b) 31 | { 32 | b.re.copyTo(this->re); 33 | b.im.copyTo(this->im); 34 | } 35 | 36 | ComplexMat::~ComplexMat() 37 | { 38 | 39 | } 40 | 41 | void ComplexMat::release() 42 | { 43 | this->re.release(); 44 | this->im.release(); 45 | } 46 | 47 | int ComplexMat::type() const 48 | { 49 | if (re.type() != im.type()) return -1; 50 | return this->re.type(); 51 | } 52 | 53 | int ComplexMat::Mul(const ComplexMat& Src, ComplexMat& Dst, bool bConj) const 54 | { 55 | ComplexMat result; 56 | if (this->GetRows() < 1 || 57 | this->GetCols() < 1 || 58 | Src.GetRows() < 1 || 59 | Src.GetCols() < 1|| 60 | this->GetCols() != Src.GetCols()|| 61 | this->GetRows() != Src.GetRows()|| 62 | this->type() != Src.type()) 63 | { 64 | fprintf(stderr, "ComplexMat::Mul(): input check failed!\n\n"); 65 | return -1; 66 | } 67 | 68 | if (bConj) 69 | { 70 | result.re = this->re.mul(Src.re) + this->im.mul(Src.im); 71 | result.im = Src.re.mul(this->im) - this->re.mul(Src.im); 72 | } 73 | else 74 | { 75 | result.re = this->re.mul(Src.re) - this->im.mul(Src.im); 76 | result.im = Src.re.mul(this->im) + this->re.mul(Src.im); 77 | } 78 | Dst.SetRe(result.re); 79 | Dst.SetIm(result.im); 80 | return 0; 81 | } 82 | 83 | ComplexMat ComplexMat::operator*(const ComplexMat& b) const 84 | { 85 | ComplexMat result; 86 | if (this->GetRows() < 1 || 87 | this->GetCols() < 1 || 88 | b.GetRows() < 1 || 89 | b.GetCols() < 1 || 90 | (this->GetCols() != b.GetCols()) && b.GetCols() != 1 || 91 | (this->GetRows() != b.GetRows()) && b.GetRows() != 1 || 92 | this->type() != b.type()) 93 | { 94 | fprintf(stderr, "ComplexMat::Mul(): input check failed!\n\n"); 95 | return ComplexMat(); 96 | } 97 | if (b.GetCols() == 1 && b.GetRows() == 1) 98 | { 99 | result.re = this->re * b.re.at(0, 0) - this->im * b.im.at(0, 0); 100 | result.im = this->im * b.re.at(0, 0) + this->re * b.im.at(0, 0); 101 | } 102 | else 103 | { 104 | result.re = this->re.mul(b.re) - this->im.mul(b.im); 105 | result.im = b.re.mul(this->im) + this->re.mul(b.im); 106 | } 107 | return result; 108 | } 109 | 110 | ComplexMat ComplexMat::operator*(const Mat& a) const 111 | { 112 | if (a.cols != this->GetCols() || 113 | a.rows != this->GetRows()|| 114 | a.type() != this->type()|| 115 | a.channels() != 1) 116 | { 117 | fprintf(stderr, "ComplexMat::operator*(const Mat& a): input check failed!\n\n"); 118 | return ComplexMat(); 119 | } 120 | Mat out_re, out_im; 121 | ComplexMat out; 122 | out_re = this->re.mul(a); 123 | out_im = this->im.mul(a); 124 | out.SetRe(out_re); 125 | out.SetIm(out_im); 126 | return out; 127 | } 128 | 129 | ComplexMat ComplexMat::operator*(const double& a) const 130 | { 131 | Mat out_re, out_im; 132 | ComplexMat out; 133 | out_re = this->re * a; 134 | out_im = this->im * a; 135 | out.SetRe(out_re); 136 | out.SetIm(out_im); 137 | return out; 138 | } 139 | 140 | ComplexMat ComplexMat::operator()(cv::Range _rowRange, cv::Range _colRange) const 141 | { 142 | if (_rowRange.start < 0 || 143 | _rowRange.end > this->GetRows() || 144 | _colRange.start < 0 || 145 | _colRange.end > this->GetCols()) 146 | { 147 | fprintf(stderr, "ComplexMat::operator()(cv::Range _rowRange, cv::Range _colRange): \n Range exceeds legal value!\n\n"); 148 | return ComplexMat(); 149 | } 150 | ComplexMat out; 151 | this->re(cv::Range(_rowRange.start, _rowRange.end), cv::Range(_colRange.start, _colRange.end)).copyTo(out.re); 152 | this->im(cv::Range(_rowRange.start, _rowRange.end), cv::Range(_colRange.start, _colRange.end)).copyTo(out.im); 153 | return out; 154 | } 155 | 156 | int ComplexMat::SetValue(cv::Range _rowRange, cv::Range _colRange, ComplexMat& src) 157 | { 158 | if ((_rowRange.end - _rowRange.start) != src.GetRows() || 159 | (_colRange.end - _colRange.start) != src.GetCols() || 160 | _rowRange.start < 0 || 161 | _rowRange.end > this->GetRows() || 162 | _colRange.start < 0 || 163 | _colRange.end > this->GetCols()|| 164 | src.type() != this->type()|| 165 | (src.type() != CV_64F && src.type() != CV_16S) 166 | ) 167 | { 168 | fprintf(stderr, "ComplexMat::SetValue(): input check failed!\n\n"); 169 | return -1; 170 | } 171 | if (src.type() == CV_64F) 172 | { 173 | for (int i = _rowRange.start; i < _rowRange.end; i++) 174 | { 175 | for (int j = _colRange.start; j < _colRange.end; j++) 176 | { 177 | 178 | this->re.at(i, j) = src.re.at(i - _rowRange.start, j - _colRange.start); 179 | this->im.at(i, j) = src.im.at(i - _rowRange.start, j - _colRange.start); 180 | } 181 | } 182 | } 183 | if (src.type() == CV_16S) 184 | { 185 | for (int i = _rowRange.start; i < _rowRange.end; i++) 186 | { 187 | for (int j = _colRange.start; j < _colRange.end; j++) 188 | { 189 | 190 | this->re.at(i, j) = src.re.at(i - _rowRange.start, j - _colRange.start); 191 | this->im.at(i, j) = src.im.at(i - _rowRange.start, j - _colRange.start); 192 | } 193 | } 194 | } 195 | 196 | return 0; 197 | } 198 | 199 | Mat ComplexMat::GetIm() const 200 | { 201 | return this->im; 202 | } 203 | 204 | Mat ComplexMat::GetMod() const 205 | { 206 | Mat tmp; 207 | magnitude(this->re, this->im, tmp); 208 | return tmp; 209 | } 210 | 211 | Mat ComplexMat::GetPhase() 212 | { 213 | int nr = this->GetRows(); 214 | int nc = this->GetCols(); 215 | if (nr < 1 || nc < 1) 216 | { 217 | return Mat::zeros(1, 1, CV_64F); 218 | } 219 | Mat phase(nr, nc, CV_64F); 220 | if (this->type() == CV_64F) 221 | { 222 | #pragma omp parallel for schedule(guided) 223 | for (int i = 0; i < nr; i++) 224 | { 225 | for (int j = 0; j < nc; j++) 226 | { 227 | phase.at (i, j) = atan2(this->im.at(i, j), this->re.at(i, j)); 228 | } 229 | } 230 | } 231 | else if (this->type() == CV_32F) 232 | { 233 | #pragma omp parallel for schedule(guided) 234 | for (int i = 0; i < nr; i++) 235 | { 236 | for (int j = 0; j < nc; j++) 237 | { 238 | phase.at (i, j) = atan2(this->im.at(i, j), this->re.at(i, j)); 239 | } 240 | } 241 | } 242 | else if (this->type() == CV_32S) 243 | { 244 | #pragma omp parallel for schedule(guided) 245 | for (int i = 0; i < nr; i++) 246 | { 247 | for (int j = 0; j < nc; j++) 248 | { 249 | phase.at (i, j) = atan2((double)this->im.at(i, j), (double)this->re.at(i, j)); 250 | } 251 | } 252 | } 253 | else if (this->type() == CV_16S) 254 | { 255 | #pragma omp parallel for schedule(guided) 256 | for (int i = 0; i < nr; i++) 257 | { 258 | for (int j = 0; j < nc; j++) 259 | { 260 | phase.at (i, j) = atan2((double)this->im.at(i, j), (double)this->re.at(i, j)); 261 | } 262 | } 263 | } 264 | 265 | return phase; 266 | } 267 | 268 | Mat ComplexMat::GetRe() const 269 | { 270 | return this->re; 271 | } 272 | 273 | void ComplexMat::SetIm(Mat& im) 274 | { 275 | im.copyTo(this->im); 276 | 277 | } 278 | 279 | void ComplexMat::SetRe(Mat& re) 280 | { 281 | re.copyTo(this->re); 282 | } 283 | 284 | int ComplexMat::GetCols() const 285 | { 286 | if (re.cols != im.cols) return -1; 287 | return this->re.cols; 288 | } 289 | 290 | int ComplexMat::mul(const ComplexMat& Src, ComplexMat& Dst, bool bConj) 291 | { 292 | if (Src.isempty() || 293 | this->isempty() || 294 | Src.type() != this->type() || 295 | this->GetCols() != Src.GetRows() 296 | ) 297 | { 298 | fprintf(stderr, "ComplexMat::mul(): input check failed!\n"); 299 | return -1; 300 | } 301 | if (!bConj) 302 | { 303 | Dst.re = this->re * Src.re - this->im * Src.im; 304 | Dst.im = this->re * Src.im + this->im * Src.re; 305 | } 306 | else 307 | { 308 | Dst.re = this->re * Src.re + this->im * Src.im; 309 | Dst.im = this->im * Src.re - this->re * Src.im; 310 | } 311 | 312 | return 0; 313 | } 314 | 315 | int ComplexMat::GetRows() const 316 | { 317 | if (re.rows != im.rows) return -1; 318 | return this->re.rows; 319 | } 320 | 321 | ComplexMat ComplexMat::operator+(const ComplexMat& b) const 322 | { 323 | if (this->GetCols() != b.GetCols() || 324 | b.GetRows() != b.GetRows() || 325 | this->type() != b.type()|| 326 | this->GetCols() < 1|| 327 | this->GetRows() < 1 328 | ) 329 | { 330 | fprintf(stderr, "ComplexMat operator+: input check failed!\n\n"); 331 | return *this; 332 | } 333 | ComplexMat out; 334 | Mat out_re, out_im; 335 | out_re = this->re + b.re; 336 | out_im = this->im + b.im; 337 | out.SetIm(out_im); 338 | out.SetRe(out_re); 339 | return out; 340 | } 341 | 342 | ComplexMat ComplexMat::operator=(const ComplexMat& b) 343 | { 344 | b.re.copyTo(this->re); 345 | b.im.copyTo(this->im); 346 | return *this; 347 | } 348 | 349 | ComplexMat ComplexMat::sum(int dim) const 350 | { 351 | ComplexMat out; 352 | Mat re, im; 353 | int nr = this->GetRows(); 354 | int nc = this->GetCols(); 355 | if (nr < 0 || nc < 0) 356 | { 357 | fprintf(stderr, "ComplexMat::sum(): rows or cols < 0!\n\n"); 358 | return ComplexMat(); 359 | } 360 | if (dim == 1) 361 | { 362 | re = Mat::zeros(nr, 1, CV_64F); 363 | im = Mat::zeros(nr, 1, CV_64F); 364 | #pragma omp parallel for schedule(guided) 365 | for (int i = 0; i < nr; i++) 366 | { 367 | double tmp_re, tmp_im; 368 | tmp_re = 0.0; tmp_im = 0.0; 369 | for (int j = 0; j < nc; j++) 370 | { 371 | tmp_re += this->re.at(i, j); 372 | tmp_im += this->im.at(i, j); 373 | } 374 | re.at(i, 0) = tmp_re; 375 | im.at(i, 0) = tmp_im; 376 | } 377 | } 378 | else 379 | { 380 | re = Mat::zeros(1, nc, CV_64F); 381 | im = Mat::zeros(1, nc, CV_64F); 382 | 383 | #pragma omp parallel for schedule(guided) 384 | for (int j = 0; j < nc; j++) 385 | { 386 | double tmp_re, tmp_im; 387 | tmp_re = 0.0; tmp_im = 0.0; 388 | for (int i = 0; i < nr; i++) 389 | { 390 | tmp_re += this->re.at(i, j); 391 | tmp_im += this->im.at(i, j); 392 | } 393 | re.at(0, j) = tmp_re; 394 | im.at(0, j) = tmp_im; 395 | } 396 | } 397 | out.SetRe(re); 398 | out.SetIm(im); 399 | return out; 400 | } 401 | 402 | complex ComplexMat::determinant() const 403 | { 404 | int nr, nc; 405 | nr = this->GetRows(); 406 | nc = this->GetCols(); 407 | Eigen::MatrixXcd x(nr, nc); 408 | complex d; 409 | if (this->type() == CV_32F) 410 | { 411 | for (int i = 0; i < nr; i++) 412 | { 413 | for (int j = 0; j < nc; j++) 414 | { 415 | d.real(this->re.at(i, j)); 416 | d.imag(this->im.at(i, j)); 417 | x(i, j) = d; 418 | } 419 | } 420 | } 421 | else 422 | { 423 | for (int i = 0; i < nr; i++) 424 | { 425 | for (int j = 0; j < nc; j++) 426 | { 427 | d.real(this->re.at(i, j)); 428 | d.imag(this->im.at(i, j)); 429 | x(i, j) = d; 430 | } 431 | } 432 | } 433 | 434 | return x.determinant(); 435 | } 436 | 437 | ComplexMat ComplexMat::conj() const 438 | { 439 | ComplexMat out; 440 | Mat im, re; 441 | this->re.copyTo(re); 442 | this->im.copyTo(im); 443 | im = -im; 444 | out.SetRe(re); 445 | out.SetIm(im); 446 | return out; 447 | } 448 | 449 | ComplexMat ComplexMat::transpose(bool conj) const 450 | { 451 | ComplexMat out; 452 | Mat im, re; 453 | this->re.copyTo(re); 454 | this->im.copyTo(im); 455 | if (conj) im = -im; 456 | cv::transpose(re, re); 457 | cv::transpose(im, im); 458 | out.SetRe(re); 459 | out.SetIm(im); 460 | return out; 461 | } 462 | 463 | int ComplexMat::reshape(int rows, int cols, ComplexMat& dst) 464 | { 465 | if (rows * cols != this->GetCols() * this->GetRows()) 466 | { 467 | fprintf(stderr, "ComplexMat::reshape(): input check failed!\n"); 468 | return -1; 469 | } 470 | Mat real, imagine; 471 | cv::transpose(this->re, real); 472 | cv::transpose(this->im, imagine); 473 | real = real.reshape(1, rows); 474 | imagine = imagine.reshape(1, rows); 475 | real.copyTo(dst.re); 476 | imagine.copyTo(dst.im); 477 | return 0; 478 | } 479 | 480 | int ComplexMat::countNonzero() const 481 | { 482 | if (this->re.rows == 0 || 483 | this->im.rows == 0 || 484 | this->re.cols == 0 || 485 | this->im.cols == 0 486 | ) 487 | { 488 | return 0; 489 | } 490 | int count = 0; 491 | int nr = GetRows(); 492 | int nc = GetCols(); 493 | for (int i = 0; i < nr; i++) 494 | { 495 | for (int j = 0; j < nc; j++) 496 | { 497 | if (fabs(this->re.at(i, j)) > DBL_EPSILON || fabs(this->im.at(i, j)) > DBL_EPSILON) 498 | { 499 | count++; 500 | } 501 | } 502 | } 503 | return count; 504 | } 505 | 506 | bool ComplexMat::isempty() const 507 | { 508 | if (this->GetRows() < 1 || this->GetCols() < 1) return true; 509 | return false; 510 | } 511 | 512 | void ComplexMat::convertTo(ComplexMat& out, int type) const 513 | { 514 | if (this->type() == type) 515 | { 516 | out = *this; 517 | } 518 | else 519 | { 520 | this->re.convertTo(out.re, type); 521 | this->im.convertTo(out.im, type); 522 | } 523 | } 524 | -------------------------------------------------------------------------------- /Evaluation/tinyxmlparser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | www.sourceforge.net/projects/tinyxml 3 | Original code by 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"pch.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[ TiXmlBase::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() const { 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 ) ) // Still using old rules for white space. 350 | ++p; 351 | else 352 | break; 353 | } 354 | } 355 | else 356 | { 357 | while ( *p && IsWhiteSpace( *p ) ) 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 && *p ) 635 | p += strlen( endTag ); 636 | return ( p && *p ) ? p : 0; 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 | p = SkipWhiteSpace( p, encoding ); 829 | 830 | if ( !p || !*p ) 831 | { 832 | return 0; 833 | } 834 | 835 | // What is this thing? 836 | // - Elements start with a letter or underscore, but xml is reserved. 837 | // - Comments: "; 1351 | 1352 | if ( !StringEqual( p, startTag, false, encoding ) ) 1353 | { 1354 | if ( document ) 1355 | document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); 1356 | return 0; 1357 | } 1358 | p += strlen( startTag ); 1359 | 1360 | // [ 1475201 ] TinyXML parses entities in comments 1361 | // Oops - ReadText doesn't work, because we don't want to parse the entities. 1362 | // p = ReadText( p, &value, false, endTag, false, encoding ); 1363 | // 1364 | // from the XML spec: 1365 | /* 1366 | [Definition: Comments may appear anywhere in a document outside other markup; in addition, 1367 | they may appear within the document type declaration at places allowed by the grammar. 1368 | They are not part of the document's character data; an XML processor MAY, but need not, 1369 | make it possible for an application to retrieve the text of comments. For compatibility, 1370 | the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity 1371 | references MUST NOT be recognized within comments. 1372 | 1373 | An example of a comment: 1374 | 1375 | 1376 | */ 1377 | 1378 | value = ""; 1379 | // Keep all the white space. 1380 | while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) 1381 | { 1382 | value.append( p, 1 ); 1383 | ++p; 1384 | } 1385 | if ( p && *p ) 1386 | p += strlen( endTag ); 1387 | 1388 | return p; 1389 | } 1390 | 1391 | 1392 | const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) 1393 | { 1394 | p = SkipWhiteSpace( p, encoding ); 1395 | if ( !p || !*p ) return 0; 1396 | 1397 | if ( data ) 1398 | { 1399 | data->Stamp( p, encoding ); 1400 | location = data->Cursor(); 1401 | } 1402 | // Read the name, the '=' and the value. 1403 | const char* pErr = p; 1404 | p = ReadName( p, &name, encoding ); 1405 | if ( !p || !*p ) 1406 | { 1407 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); 1408 | return 0; 1409 | } 1410 | p = SkipWhiteSpace( p, encoding ); 1411 | if ( !p || !*p || *p != '=' ) 1412 | { 1413 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1414 | return 0; 1415 | } 1416 | 1417 | ++p; // skip '=' 1418 | p = SkipWhiteSpace( p, encoding ); 1419 | if ( !p || !*p ) 1420 | { 1421 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1422 | return 0; 1423 | } 1424 | 1425 | const char* end; 1426 | const char SINGLE_QUOTE = '\''; 1427 | const char DOUBLE_QUOTE = '\"'; 1428 | 1429 | if ( *p == SINGLE_QUOTE ) 1430 | { 1431 | ++p; 1432 | end = "\'"; // single quote in string 1433 | p = ReadText( p, &value, false, end, false, encoding ); 1434 | } 1435 | else if ( *p == DOUBLE_QUOTE ) 1436 | { 1437 | ++p; 1438 | end = "\""; // double quote in string 1439 | p = ReadText( p, &value, false, end, false, encoding ); 1440 | } 1441 | else 1442 | { 1443 | // All attribute values should be in single or double quotes. 1444 | // But this is such a common error that the parser will try 1445 | // its best, even without them. 1446 | value = ""; 1447 | while ( p && *p // existence 1448 | && !IsWhiteSpace( *p ) // whitespace 1449 | && *p != '/' && *p != '>' ) // tag end 1450 | { 1451 | if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { 1452 | // [ 1451649 ] Attribute values with trailing quotes not handled correctly 1453 | // We did not have an opening quote but seem to have a 1454 | // closing one. Give up and throw an error. 1455 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1456 | return 0; 1457 | } 1458 | value += *p; 1459 | ++p; 1460 | } 1461 | } 1462 | return p; 1463 | } 1464 | 1465 | #ifdef TIXML_USE_STL 1466 | void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) 1467 | { 1468 | while ( in->good() ) 1469 | { 1470 | int c = in->peek(); 1471 | if ( !cdata && (c == '<' ) ) 1472 | { 1473 | return; 1474 | } 1475 | if ( c <= 0 ) 1476 | { 1477 | TiXmlDocument* document = GetDocument(); 1478 | if ( document ) 1479 | document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 1480 | return; 1481 | } 1482 | 1483 | (*tag) += (char) c; 1484 | in->get(); // "commits" the peek made above 1485 | 1486 | if ( cdata && c == '>' && tag->size() >= 3 ) { 1487 | size_t len = tag->size(); 1488 | if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { 1489 | // terminator of cdata. 1490 | return; 1491 | } 1492 | } 1493 | } 1494 | } 1495 | #endif 1496 | 1497 | const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) 1498 | { 1499 | value = ""; 1500 | TiXmlDocument* document = GetDocument(); 1501 | 1502 | if ( data ) 1503 | { 1504 | data->Stamp( p, encoding ); 1505 | location = data->Cursor(); 1506 | } 1507 | 1508 | const char* const startTag = ""; 1510 | 1511 | if ( cdata || StringEqual( p, startTag, false, encoding ) ) 1512 | { 1513 | cdata = true; 1514 | 1515 | if ( !StringEqual( p, startTag, false, encoding ) ) 1516 | { 1517 | if ( document ) 1518 | document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); 1519 | return 0; 1520 | } 1521 | p += strlen( startTag ); 1522 | 1523 | // Keep all the white space, ignore the encoding, etc. 1524 | while ( p && *p 1525 | && !StringEqual( p, endTag, false, encoding ) 1526 | ) 1527 | { 1528 | value += *p; 1529 | ++p; 1530 | } 1531 | 1532 | TIXML_STRING dummy; 1533 | p = ReadText( p, &dummy, false, endTag, false, encoding ); 1534 | return p; 1535 | } 1536 | else 1537 | { 1538 | bool ignoreWhite = true; 1539 | 1540 | const char* end = "<"; 1541 | p = ReadText( p, &value, ignoreWhite, end, false, encoding ); 1542 | if ( p && *p ) 1543 | return p-1; // don't truncate the '<' 1544 | return 0; 1545 | } 1546 | } 1547 | 1548 | #ifdef TIXML_USE_STL 1549 | void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) 1550 | { 1551 | while ( in->good() ) 1552 | { 1553 | int c = in->get(); 1554 | if ( c <= 0 ) 1555 | { 1556 | TiXmlDocument* document = GetDocument(); 1557 | if ( document ) 1558 | document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 1559 | return; 1560 | } 1561 | (*tag) += (char) c; 1562 | 1563 | if ( c == '>' ) 1564 | { 1565 | // All is well. 1566 | return; 1567 | } 1568 | } 1569 | } 1570 | #endif 1571 | 1572 | const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) 1573 | { 1574 | p = SkipWhiteSpace( p, _encoding ); 1575 | // Find the beginning, find the end, and look for 1576 | // the stuff in-between. 1577 | TiXmlDocument* document = GetDocument(); 1578 | if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); 1581 | return 0; 1582 | } 1583 | if ( data ) 1584 | { 1585 | data->Stamp( p, _encoding ); 1586 | location = data->Cursor(); 1587 | } 1588 | p += 5; 1589 | 1590 | version = ""; 1591 | encoding = ""; 1592 | standalone = ""; 1593 | 1594 | while ( p && *p ) 1595 | { 1596 | if ( *p == '>' ) 1597 | { 1598 | ++p; 1599 | return p; 1600 | } 1601 | 1602 | p = SkipWhiteSpace( p, _encoding ); 1603 | if ( StringEqual( p, "version", true, _encoding ) ) 1604 | { 1605 | TiXmlAttribute attrib; 1606 | p = attrib.Parse( p, data, _encoding ); 1607 | version = attrib.Value(); 1608 | } 1609 | else if ( StringEqual( p, "encoding", true, _encoding ) ) 1610 | { 1611 | TiXmlAttribute attrib; 1612 | p = attrib.Parse( p, data, _encoding ); 1613 | encoding = attrib.Value(); 1614 | } 1615 | else if ( StringEqual( p, "standalone", true, _encoding ) ) 1616 | { 1617 | TiXmlAttribute attrib; 1618 | p = attrib.Parse( p, data, _encoding ); 1619 | standalone = attrib.Value(); 1620 | } 1621 | else 1622 | { 1623 | // Read over whatever it is. 1624 | while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) 1625 | ++p; 1626 | } 1627 | } 1628 | return 0; 1629 | } 1630 | 1631 | bool TiXmlText::Blank() const 1632 | { 1633 | 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[ TiXmlBase::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() const { 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 ) ) // Still using old rules for white space. 350 | ++p; 351 | else 352 | break; 353 | } 354 | } 355 | else 356 | { 357 | while ( *p && IsWhiteSpace( *p ) ) 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 && *p ) 635 | p += strlen( endTag ); 636 | return ( p && *p ) ? p : 0; 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 | p = SkipWhiteSpace( p, encoding ); 829 | 830 | if ( !p || !*p ) 831 | { 832 | return 0; 833 | } 834 | 835 | // What is this thing? 836 | // - Elements start with a letter or underscore, but xml is reserved. 837 | // - Comments: "; 1351 | 1352 | if ( !StringEqual( p, startTag, false, encoding ) ) 1353 | { 1354 | if ( document ) 1355 | document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); 1356 | return 0; 1357 | } 1358 | p += strlen( startTag ); 1359 | 1360 | // [ 1475201 ] TinyXML parses entities in comments 1361 | // Oops - ReadText doesn't work, because we don't want to parse the entities. 1362 | // p = ReadText( p, &value, false, endTag, false, encoding ); 1363 | // 1364 | // from the XML spec: 1365 | /* 1366 | [Definition: Comments may appear anywhere in a document outside other markup; in addition, 1367 | they may appear within the document type declaration at places allowed by the grammar. 1368 | They are not part of the document's character data; an XML processor MAY, but need not, 1369 | make it possible for an application to retrieve the text of comments. For compatibility, 1370 | the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity 1371 | references MUST NOT be recognized within comments. 1372 | 1373 | An example of a comment: 1374 | 1375 | 1376 | */ 1377 | 1378 | value = ""; 1379 | // Keep all the white space. 1380 | while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) 1381 | { 1382 | value.append( p, 1 ); 1383 | ++p; 1384 | } 1385 | if ( p && *p ) 1386 | p += strlen( endTag ); 1387 | 1388 | return p; 1389 | } 1390 | 1391 | 1392 | const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) 1393 | { 1394 | p = SkipWhiteSpace( p, encoding ); 1395 | if ( !p || !*p ) return 0; 1396 | 1397 | if ( data ) 1398 | { 1399 | data->Stamp( p, encoding ); 1400 | location = data->Cursor(); 1401 | } 1402 | // Read the name, the '=' and the value. 1403 | const char* pErr = p; 1404 | p = ReadName( p, &name, encoding ); 1405 | if ( !p || !*p ) 1406 | { 1407 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); 1408 | return 0; 1409 | } 1410 | p = SkipWhiteSpace( p, encoding ); 1411 | if ( !p || !*p || *p != '=' ) 1412 | { 1413 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1414 | return 0; 1415 | } 1416 | 1417 | ++p; // skip '=' 1418 | p = SkipWhiteSpace( p, encoding ); 1419 | if ( !p || !*p ) 1420 | { 1421 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1422 | return 0; 1423 | } 1424 | 1425 | const char* end; 1426 | const char SINGLE_QUOTE = '\''; 1427 | const char DOUBLE_QUOTE = '\"'; 1428 | 1429 | if ( *p == SINGLE_QUOTE ) 1430 | { 1431 | ++p; 1432 | end = "\'"; // single quote in string 1433 | p = ReadText( p, &value, false, end, false, encoding ); 1434 | } 1435 | else if ( *p == DOUBLE_QUOTE ) 1436 | { 1437 | ++p; 1438 | end = "\""; // double quote in string 1439 | p = ReadText( p, &value, false, end, false, encoding ); 1440 | } 1441 | else 1442 | { 1443 | // All attribute values should be in single or double quotes. 1444 | // But this is such a common error that the parser will try 1445 | // its best, even without them. 1446 | value = ""; 1447 | while ( p && *p // existence 1448 | && !IsWhiteSpace( *p ) // whitespace 1449 | && *p != '/' && *p != '>' ) // tag end 1450 | { 1451 | if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { 1452 | // [ 1451649 ] Attribute values with trailing quotes not handled correctly 1453 | // We did not have an opening quote but seem to have a 1454 | // closing one. Give up and throw an error. 1455 | if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); 1456 | return 0; 1457 | } 1458 | value += *p; 1459 | ++p; 1460 | } 1461 | } 1462 | return p; 1463 | } 1464 | 1465 | #ifdef TIXML_USE_STL 1466 | void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) 1467 | { 1468 | while ( in->good() ) 1469 | { 1470 | int c = in->peek(); 1471 | if ( !cdata && (c == '<' ) ) 1472 | { 1473 | return; 1474 | } 1475 | if ( c <= 0 ) 1476 | { 1477 | TiXmlDocument* document = GetDocument(); 1478 | if ( document ) 1479 | document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 1480 | return; 1481 | } 1482 | 1483 | (*tag) += (char) c; 1484 | in->get(); // "commits" the peek made above 1485 | 1486 | if ( cdata && c == '>' && tag->size() >= 3 ) { 1487 | size_t len = tag->size(); 1488 | if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { 1489 | // terminator of cdata. 1490 | return; 1491 | } 1492 | } 1493 | } 1494 | } 1495 | #endif 1496 | 1497 | const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) 1498 | { 1499 | value = ""; 1500 | TiXmlDocument* document = GetDocument(); 1501 | 1502 | if ( data ) 1503 | { 1504 | data->Stamp( p, encoding ); 1505 | location = data->Cursor(); 1506 | } 1507 | 1508 | const char* const startTag = ""; 1510 | 1511 | if ( cdata || StringEqual( p, startTag, false, encoding ) ) 1512 | { 1513 | cdata = true; 1514 | 1515 | if ( !StringEqual( p, startTag, false, encoding ) ) 1516 | { 1517 | if ( document ) 1518 | document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); 1519 | return 0; 1520 | } 1521 | p += strlen( startTag ); 1522 | 1523 | // Keep all the white space, ignore the encoding, etc. 1524 | while ( p && *p 1525 | && !StringEqual( p, endTag, false, encoding ) 1526 | ) 1527 | { 1528 | value += *p; 1529 | ++p; 1530 | } 1531 | 1532 | TIXML_STRING dummy; 1533 | p = ReadText( p, &dummy, false, endTag, false, encoding ); 1534 | return p; 1535 | } 1536 | else 1537 | { 1538 | bool ignoreWhite = true; 1539 | 1540 | const char* end = "<"; 1541 | p = ReadText( p, &value, ignoreWhite, end, false, encoding ); 1542 | if ( p && *p ) 1543 | return p-1; // don't truncate the '<' 1544 | return 0; 1545 | } 1546 | } 1547 | 1548 | #ifdef TIXML_USE_STL 1549 | void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) 1550 | { 1551 | while ( in->good() ) 1552 | { 1553 | int c = in->get(); 1554 | if ( c <= 0 ) 1555 | { 1556 | TiXmlDocument* document = GetDocument(); 1557 | if ( document ) 1558 | document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); 1559 | return; 1560 | } 1561 | (*tag) += (char) c; 1562 | 1563 | if ( c == '>' ) 1564 | { 1565 | // All is well. 1566 | return; 1567 | } 1568 | } 1569 | } 1570 | #endif 1571 | 1572 | const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) 1573 | { 1574 | p = SkipWhiteSpace( p, _encoding ); 1575 | // Find the beginning, find the end, and look for 1576 | // the stuff in-between. 1577 | TiXmlDocument* document = GetDocument(); 1578 | if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); 1581 | return 0; 1582 | } 1583 | if ( data ) 1584 | { 1585 | data->Stamp( p, _encoding ); 1586 | location = data->Cursor(); 1587 | } 1588 | p += 5; 1589 | 1590 | version = ""; 1591 | encoding = ""; 1592 | standalone = ""; 1593 | 1594 | while ( p && *p ) 1595 | { 1596 | if ( *p == '>' ) 1597 | { 1598 | ++p; 1599 | return p; 1600 | } 1601 | 1602 | p = SkipWhiteSpace( p, _encoding ); 1603 | if ( StringEqual( p, "version", true, _encoding ) ) 1604 | { 1605 | TiXmlAttribute attrib; 1606 | p = attrib.Parse( p, data, _encoding ); 1607 | version = attrib.Value(); 1608 | } 1609 | else if ( StringEqual( p, "encoding", true, _encoding ) ) 1610 | { 1611 | TiXmlAttribute attrib; 1612 | p = attrib.Parse( p, data, _encoding ); 1613 | encoding = attrib.Value(); 1614 | } 1615 | else if ( StringEqual( p, "standalone", true, _encoding ) ) 1616 | { 1617 | TiXmlAttribute attrib; 1618 | p = attrib.Parse( p, data, _encoding ); 1619 | standalone = attrib.Value(); 1620 | } 1621 | else 1622 | { 1623 | // Read over whatever it is. 1624 | while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) 1625 | ++p; 1626 | } 1627 | } 1628 | return 0; 1629 | } 1630 | 1631 | bool TiXmlText::Blank() const 1632 | { 1633 | for ( unsigned i=0; i 26 | #include"pch.h" 27 | #ifdef TIXML_USE_STL 28 | #include 29 | #include 30 | #endif 31 | 32 | #include "tinyxml.h" 33 | 34 | FILE* TiXmlFOpen( const char* filename, const char* mode ); 35 | 36 | bool TiXmlBase::condenseWhiteSpace = true; 37 | 38 | // Microsoft compiler security 39 | FILE* TiXmlFOpen( const char* filename, const char* mode ) 40 | { 41 | #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) 42 | FILE* fp = 0; 43 | errno_t err = fopen_s( &fp, filename, mode ); 44 | if ( !err && fp ) 45 | return fp; 46 | return 0; 47 | #else 48 | return fopen( filename, mode ); 49 | #endif 50 | } 51 | 52 | void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) 53 | { 54 | int i=0; 55 | 56 | while( i<(int)str.length() ) 57 | { 58 | unsigned char c = (unsigned char) str[i]; 59 | 60 | if ( c == '&' 61 | && i < ( (int)str.length() - 2 ) 62 | && str[i+1] == '#' 63 | && str[i+2] == 'x' ) 64 | { 65 | // Hexadecimal character reference. 66 | // Pass through unchanged. 67 | // © -- copyright symbol, for example. 68 | // 69 | // The -1 is a bug fix from Rob Laveaux. It keeps 70 | // an overflow from happening if there is no ';'. 71 | // There are actually 2 ways to exit this loop - 72 | // while fails (error case) and break (semicolon found). 73 | // However, there is no mechanism (currently) for 74 | // this function to return an error. 75 | while ( i<(int)str.length()-1 ) 76 | { 77 | outString->append( str.c_str() + i, 1 ); 78 | ++i; 79 | if ( str[i] == ';' ) 80 | break; 81 | } 82 | } 83 | else if ( c == '&' ) 84 | { 85 | outString->append( entity[0].str, entity[0].strLength ); 86 | ++i; 87 | } 88 | else if ( c == '<' ) 89 | { 90 | outString->append( entity[1].str, entity[1].strLength ); 91 | ++i; 92 | } 93 | else if ( c == '>' ) 94 | { 95 | outString->append( entity[2].str, entity[2].strLength ); 96 | ++i; 97 | } 98 | else if ( c == '\"' ) 99 | { 100 | outString->append( entity[3].str, entity[3].strLength ); 101 | ++i; 102 | } 103 | else if ( c == '\'' ) 104 | { 105 | outString->append( entity[4].str, entity[4].strLength ); 106 | ++i; 107 | } 108 | else if ( c < 32 ) 109 | { 110 | // Easy pass at non-alpha/numeric/symbol 111 | // Below 32 is symbolic. 112 | char buf[ 32 ]; 113 | 114 | #if defined(TIXML_SNPRINTF) 115 | TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); 116 | #else 117 | sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); 118 | #endif 119 | 120 | //*ME: warning C4267: convert 'size_t' to 'int' 121 | //*ME: Int-Cast to make compiler happy ... 122 | outString->append( buf, (int)strlen( buf ) ); 123 | ++i; 124 | } 125 | else 126 | { 127 | //char realc = (char) c; 128 | //outString->append( &realc, 1 ); 129 | *outString += (char) c; // somewhat more efficient function call. 130 | ++i; 131 | } 132 | } 133 | } 134 | 135 | 136 | TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() 137 | { 138 | parent = 0; 139 | type = _type; 140 | firstChild = 0; 141 | lastChild = 0; 142 | prev = 0; 143 | next = 0; 144 | } 145 | 146 | 147 | TiXmlNode::~TiXmlNode() 148 | { 149 | TiXmlNode* node = firstChild; 150 | TiXmlNode* temp = 0; 151 | 152 | while ( node ) 153 | { 154 | temp = node; 155 | node = node->next; 156 | delete temp; 157 | } 158 | } 159 | 160 | 161 | void TiXmlNode::CopyTo( TiXmlNode* target ) const 162 | { 163 | target->SetValue (value.c_str() ); 164 | target->userData = userData; 165 | target->location = location; 166 | } 167 | 168 | 169 | void TiXmlNode::Clear() 170 | { 171 | TiXmlNode* node = firstChild; 172 | TiXmlNode* temp = 0; 173 | 174 | while ( node ) 175 | { 176 | temp = node; 177 | node = node->next; 178 | delete temp; 179 | } 180 | 181 | firstChild = 0; 182 | lastChild = 0; 183 | } 184 | 185 | 186 | TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) 187 | { 188 | assert( node->parent == 0 || node->parent == this ); 189 | assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); 190 | 191 | if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) 192 | { 193 | delete node; 194 | if ( GetDocument() ) 195 | GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 196 | return 0; 197 | } 198 | 199 | node->parent = this; 200 | 201 | node->prev = lastChild; 202 | node->next = 0; 203 | 204 | if ( lastChild ) 205 | lastChild->next = node; 206 | else 207 | firstChild = node; // it was an empty list. 208 | 209 | lastChild = node; 210 | return node; 211 | } 212 | 213 | 214 | TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) 215 | { 216 | if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) 217 | { 218 | if ( GetDocument() ) 219 | GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 220 | return 0; 221 | } 222 | TiXmlNode* node = addThis.Clone(); 223 | if ( !node ) 224 | return 0; 225 | 226 | return LinkEndChild( node ); 227 | } 228 | 229 | 230 | TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) 231 | { 232 | if ( !beforeThis || beforeThis->parent != this ) { 233 | return 0; 234 | } 235 | if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) 236 | { 237 | if ( GetDocument() ) 238 | GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 239 | return 0; 240 | } 241 | 242 | TiXmlNode* node = addThis.Clone(); 243 | if ( !node ) 244 | return 0; 245 | node->parent = this; 246 | 247 | node->next = beforeThis; 248 | node->prev = beforeThis->prev; 249 | if ( beforeThis->prev ) 250 | { 251 | beforeThis->prev->next = node; 252 | } 253 | else 254 | { 255 | assert( firstChild == beforeThis ); 256 | firstChild = node; 257 | } 258 | beforeThis->prev = node; 259 | return node; 260 | } 261 | 262 | 263 | TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) 264 | { 265 | if ( !afterThis || afterThis->parent != this ) { 266 | return 0; 267 | } 268 | if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) 269 | { 270 | if ( GetDocument() ) 271 | GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 272 | return 0; 273 | } 274 | 275 | TiXmlNode* node = addThis.Clone(); 276 | if ( !node ) 277 | return 0; 278 | node->parent = this; 279 | 280 | node->prev = afterThis; 281 | node->next = afterThis->next; 282 | if ( afterThis->next ) 283 | { 284 | afterThis->next->prev = node; 285 | } 286 | else 287 | { 288 | assert( lastChild == afterThis ); 289 | lastChild = node; 290 | } 291 | afterThis->next = node; 292 | return node; 293 | } 294 | 295 | 296 | TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) 297 | { 298 | if ( !replaceThis ) 299 | return 0; 300 | 301 | if ( replaceThis->parent != this ) 302 | return 0; 303 | 304 | if ( withThis.ToDocument() ) { 305 | // A document can never be a child. Thanks to Noam. 306 | TiXmlDocument* document = GetDocument(); 307 | if ( document ) 308 | document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); 309 | return 0; 310 | } 311 | 312 | TiXmlNode* node = withThis.Clone(); 313 | if ( !node ) 314 | return 0; 315 | 316 | node->next = replaceThis->next; 317 | node->prev = replaceThis->prev; 318 | 319 | if ( replaceThis->next ) 320 | replaceThis->next->prev = node; 321 | else 322 | lastChild = node; 323 | 324 | if ( replaceThis->prev ) 325 | replaceThis->prev->next = node; 326 | else 327 | firstChild = node; 328 | 329 | delete replaceThis; 330 | node->parent = this; 331 | return node; 332 | } 333 | 334 | 335 | bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) 336 | { 337 | if ( !removeThis ) { 338 | return false; 339 | } 340 | 341 | if ( removeThis->parent != this ) 342 | { 343 | assert( 0 ); 344 | return false; 345 | } 346 | 347 | if ( removeThis->next ) 348 | removeThis->next->prev = removeThis->prev; 349 | else 350 | lastChild = removeThis->prev; 351 | 352 | if ( removeThis->prev ) 353 | removeThis->prev->next = removeThis->next; 354 | else 355 | firstChild = removeThis->next; 356 | 357 | delete removeThis; 358 | return true; 359 | } 360 | 361 | const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const 362 | { 363 | const TiXmlNode* node; 364 | for ( node = firstChild; node; node = node->next ) 365 | { 366 | if ( strcmp( node->Value(), _value ) == 0 ) 367 | return node; 368 | } 369 | return 0; 370 | } 371 | 372 | 373 | const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const 374 | { 375 | const TiXmlNode* node; 376 | for ( node = lastChild; node; node = node->prev ) 377 | { 378 | if ( strcmp( node->Value(), _value ) == 0 ) 379 | return node; 380 | } 381 | return 0; 382 | } 383 | 384 | 385 | const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const 386 | { 387 | if ( !previous ) 388 | { 389 | return FirstChild(); 390 | } 391 | else 392 | { 393 | assert( previous->parent == this ); 394 | return previous->NextSibling(); 395 | } 396 | } 397 | 398 | 399 | const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const 400 | { 401 | if ( !previous ) 402 | { 403 | return FirstChild( val ); 404 | } 405 | else 406 | { 407 | assert( previous->parent == this ); 408 | return previous->NextSibling( val ); 409 | } 410 | } 411 | 412 | 413 | const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const 414 | { 415 | const TiXmlNode* node; 416 | for ( node = next; node; node = node->next ) 417 | { 418 | if ( strcmp( node->Value(), _value ) == 0 ) 419 | return node; 420 | } 421 | return 0; 422 | } 423 | 424 | 425 | const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const 426 | { 427 | const TiXmlNode* node; 428 | for ( node = prev; node; node = node->prev ) 429 | { 430 | if ( strcmp( node->Value(), _value ) == 0 ) 431 | return node; 432 | } 433 | return 0; 434 | } 435 | 436 | 437 | void TiXmlElement::RemoveAttribute( const char * name ) 438 | { 439 | #ifdef TIXML_USE_STL 440 | TIXML_STRING str( name ); 441 | TiXmlAttribute* node = attributeSet.Find( str ); 442 | #else 443 | TiXmlAttribute* node = attributeSet.Find( name ); 444 | #endif 445 | if ( node ) 446 | { 447 | attributeSet.Remove( node ); 448 | delete node; 449 | } 450 | } 451 | 452 | const TiXmlElement* TiXmlNode::FirstChildElement() const 453 | { 454 | const TiXmlNode* node; 455 | 456 | for ( node = FirstChild(); 457 | node; 458 | node = node->NextSibling() ) 459 | { 460 | if ( node->ToElement() ) 461 | return node->ToElement(); 462 | } 463 | return 0; 464 | } 465 | 466 | 467 | const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const 468 | { 469 | const TiXmlNode* node; 470 | 471 | for ( node = FirstChild( _value ); 472 | node; 473 | node = node->NextSibling( _value ) ) 474 | { 475 | if ( node->ToElement() ) 476 | return node->ToElement(); 477 | } 478 | return 0; 479 | } 480 | 481 | 482 | const TiXmlElement* TiXmlNode::NextSiblingElement() const 483 | { 484 | const TiXmlNode* node; 485 | 486 | for ( node = NextSibling(); 487 | node; 488 | node = node->NextSibling() ) 489 | { 490 | if ( node->ToElement() ) 491 | return node->ToElement(); 492 | } 493 | return 0; 494 | } 495 | 496 | 497 | const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const 498 | { 499 | const TiXmlNode* node; 500 | 501 | for ( node = NextSibling( _value ); 502 | node; 503 | node = node->NextSibling( _value ) ) 504 | { 505 | if ( node->ToElement() ) 506 | return node->ToElement(); 507 | } 508 | return 0; 509 | } 510 | 511 | 512 | const TiXmlDocument* TiXmlNode::GetDocument() const 513 | { 514 | const TiXmlNode* node; 515 | 516 | for( node = this; node; node = node->parent ) 517 | { 518 | if ( node->ToDocument() ) 519 | return node->ToDocument(); 520 | } 521 | return 0; 522 | } 523 | 524 | 525 | TiXmlElement::TiXmlElement (const char * _value) 526 | : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) 527 | { 528 | firstChild = lastChild = 0; 529 | value = _value; 530 | } 531 | 532 | 533 | #ifdef TIXML_USE_STL 534 | TiXmlElement::TiXmlElement( const std::string& _value ) 535 | : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) 536 | { 537 | firstChild = lastChild = 0; 538 | value = _value; 539 | } 540 | #endif 541 | 542 | 543 | TiXmlElement::TiXmlElement( const TiXmlElement& copy) 544 | : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) 545 | { 546 | firstChild = lastChild = 0; 547 | copy.CopyTo( this ); 548 | } 549 | 550 | 551 | TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base ) 552 | { 553 | ClearThis(); 554 | base.CopyTo( this ); 555 | return *this; 556 | } 557 | 558 | 559 | TiXmlElement::~TiXmlElement() 560 | { 561 | ClearThis(); 562 | } 563 | 564 | 565 | void TiXmlElement::ClearThis() 566 | { 567 | Clear(); 568 | while( attributeSet.First() ) 569 | { 570 | TiXmlAttribute* node = attributeSet.First(); 571 | attributeSet.Remove( node ); 572 | delete node; 573 | } 574 | } 575 | 576 | 577 | const char* TiXmlElement::Attribute( const char* name ) const 578 | { 579 | const TiXmlAttribute* node = attributeSet.Find( name ); 580 | if ( node ) 581 | return node->Value(); 582 | return 0; 583 | } 584 | 585 | 586 | #ifdef TIXML_USE_STL 587 | const std::string* TiXmlElement::Attribute( const std::string& name ) const 588 | { 589 | const TiXmlAttribute* attrib = attributeSet.Find( name ); 590 | if ( attrib ) 591 | return &attrib->ValueStr(); 592 | return 0; 593 | } 594 | #endif 595 | 596 | 597 | const char* TiXmlElement::Attribute( const char* name, int* i ) const 598 | { 599 | const TiXmlAttribute* attrib = attributeSet.Find( name ); 600 | const char* result = 0; 601 | 602 | if ( attrib ) { 603 | result = attrib->Value(); 604 | if ( i ) { 605 | attrib->QueryIntValue( i ); 606 | } 607 | } 608 | return result; 609 | } 610 | 611 | 612 | #ifdef TIXML_USE_STL 613 | const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const 614 | { 615 | const TiXmlAttribute* attrib = attributeSet.Find( name ); 616 | const std::string* result = 0; 617 | 618 | if ( attrib ) { 619 | result = &attrib->ValueStr(); 620 | if ( i ) { 621 | attrib->QueryIntValue( i ); 622 | } 623 | } 624 | return result; 625 | } 626 | #endif 627 | 628 | 629 | const char* TiXmlElement::Attribute( const char* name, double* d ) const 630 | { 631 | const TiXmlAttribute* attrib = attributeSet.Find( name ); 632 | const char* result = 0; 633 | 634 | if ( attrib ) { 635 | result = attrib->Value(); 636 | if ( d ) { 637 | attrib->QueryDoubleValue( d ); 638 | } 639 | } 640 | return result; 641 | } 642 | 643 | 644 | #ifdef TIXML_USE_STL 645 | const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const 646 | { 647 | const TiXmlAttribute* attrib = attributeSet.Find( name ); 648 | const std::string* result = 0; 649 | 650 | if ( attrib ) { 651 | result = &attrib->ValueStr(); 652 | if ( d ) { 653 | attrib->QueryDoubleValue( d ); 654 | } 655 | } 656 | return result; 657 | } 658 | #endif 659 | 660 | 661 | int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const 662 | { 663 | const TiXmlAttribute* attrib = attributeSet.Find( name ); 664 | if ( !attrib ) 665 | return TIXML_NO_ATTRIBUTE; 666 | return attrib->QueryIntValue( ival ); 667 | } 668 | 669 | 670 | int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const 671 | { 672 | const TiXmlAttribute* node = attributeSet.Find( name ); 673 | if ( !node ) 674 | return TIXML_NO_ATTRIBUTE; 675 | 676 | int ival = 0; 677 | int result = node->QueryIntValue( &ival ); 678 | *value = (unsigned)ival; 679 | return result; 680 | } 681 | 682 | 683 | int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const 684 | { 685 | const TiXmlAttribute* node = attributeSet.Find( name ); 686 | if ( !node ) 687 | return TIXML_NO_ATTRIBUTE; 688 | 689 | int result = TIXML_WRONG_TYPE; 690 | if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) 691 | || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) 692 | || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) 693 | { 694 | *bval = true; 695 | result = TIXML_SUCCESS; 696 | } 697 | else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) 698 | || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) 699 | || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) 700 | { 701 | *bval = false; 702 | result = TIXML_SUCCESS; 703 | } 704 | return result; 705 | } 706 | 707 | 708 | 709 | #ifdef TIXML_USE_STL 710 | int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const 711 | { 712 | const TiXmlAttribute* attrib = attributeSet.Find( name ); 713 | if ( !attrib ) 714 | return TIXML_NO_ATTRIBUTE; 715 | return attrib->QueryIntValue( ival ); 716 | } 717 | #endif 718 | 719 | 720 | int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const 721 | { 722 | const TiXmlAttribute* attrib = attributeSet.Find( name ); 723 | if ( !attrib ) 724 | return TIXML_NO_ATTRIBUTE; 725 | return attrib->QueryDoubleValue( dval ); 726 | } 727 | 728 | 729 | #ifdef TIXML_USE_STL 730 | int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const 731 | { 732 | const TiXmlAttribute* attrib = attributeSet.Find( name ); 733 | if ( !attrib ) 734 | return TIXML_NO_ATTRIBUTE; 735 | return attrib->QueryDoubleValue( dval ); 736 | } 737 | #endif 738 | 739 | 740 | void TiXmlElement::SetAttribute( const char * name, int val ) 741 | { 742 | TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); 743 | if ( attrib ) { 744 | attrib->SetIntValue( val ); 745 | } 746 | } 747 | 748 | 749 | #ifdef TIXML_USE_STL 750 | void TiXmlElement::SetAttribute( const std::string& name, int val ) 751 | { 752 | TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); 753 | if ( attrib ) { 754 | attrib->SetIntValue( val ); 755 | } 756 | } 757 | #endif 758 | 759 | 760 | void TiXmlElement::SetDoubleAttribute( const char * name, double val ) 761 | { 762 | TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); 763 | if ( attrib ) { 764 | attrib->SetDoubleValue( val ); 765 | } 766 | } 767 | 768 | 769 | #ifdef TIXML_USE_STL 770 | void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) 771 | { 772 | TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); 773 | if ( attrib ) { 774 | attrib->SetDoubleValue( val ); 775 | } 776 | } 777 | #endif 778 | 779 | 780 | void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) 781 | { 782 | TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); 783 | if ( attrib ) { 784 | attrib->SetValue( cvalue ); 785 | } 786 | } 787 | 788 | 789 | #ifdef TIXML_USE_STL 790 | void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) 791 | { 792 | TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); 793 | if ( attrib ) { 794 | attrib->SetValue( _value ); 795 | } 796 | } 797 | #endif 798 | 799 | 800 | void TiXmlElement::Print( FILE* cfile, int depth ) const 801 | { 802 | int i; 803 | assert( cfile ); 804 | for ( i=0; iNext() ) 812 | { 813 | fprintf( cfile, " " ); 814 | attrib->Print( cfile, depth ); 815 | } 816 | 817 | // There are 3 different formatting approaches: 818 | // 1) An element without children is printed as a node 819 | // 2) An element with only a text child is printed as text 820 | // 3) An element with children is printed on multiple lines. 821 | TiXmlNode* node; 822 | if ( !firstChild ) 823 | { 824 | fprintf( cfile, " />" ); 825 | } 826 | else if ( firstChild == lastChild && firstChild->ToText() ) 827 | { 828 | fprintf( cfile, ">" ); 829 | firstChild->Print( cfile, depth + 1 ); 830 | fprintf( cfile, "", value.c_str() ); 831 | } 832 | else 833 | { 834 | fprintf( cfile, ">" ); 835 | 836 | for ( node = firstChild; node; node=node->NextSibling() ) 837 | { 838 | if ( !node->ToText() ) 839 | { 840 | fprintf( cfile, "\n" ); 841 | } 842 | node->Print( cfile, depth+1 ); 843 | } 844 | fprintf( cfile, "\n" ); 845 | for( i=0; i", value.c_str() ); 849 | } 850 | } 851 | 852 | 853 | void TiXmlElement::CopyTo( TiXmlElement* target ) const 854 | { 855 | // superclass: 856 | TiXmlNode::CopyTo( target ); 857 | 858 | // Element class: 859 | // Clone the attributes, then clone the children. 860 | const TiXmlAttribute* attribute = 0; 861 | for( attribute = attributeSet.First(); 862 | attribute; 863 | attribute = attribute->Next() ) 864 | { 865 | target->SetAttribute( attribute->Name(), attribute->Value() ); 866 | } 867 | 868 | TiXmlNode* node = 0; 869 | for ( node = firstChild; node; node = node->NextSibling() ) 870 | { 871 | target->LinkEndChild( node->Clone() ); 872 | } 873 | } 874 | 875 | bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const 876 | { 877 | if ( visitor->VisitEnter( *this, attributeSet.First() ) ) 878 | { 879 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) 880 | { 881 | if ( !node->Accept( visitor ) ) 882 | break; 883 | } 884 | } 885 | return visitor->VisitExit( *this ); 886 | } 887 | 888 | 889 | TiXmlNode* TiXmlElement::Clone() const 890 | { 891 | TiXmlElement* clone = new TiXmlElement( Value() ); 892 | if ( !clone ) 893 | return 0; 894 | 895 | CopyTo( clone ); 896 | return clone; 897 | } 898 | 899 | 900 | const char* TiXmlElement::GetText() const 901 | { 902 | const TiXmlNode* child = this->FirstChild(); 903 | if ( child ) { 904 | const TiXmlText* childText = child->ToText(); 905 | if ( childText ) { 906 | return childText->Value(); 907 | } 908 | } 909 | return 0; 910 | } 911 | 912 | 913 | TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) 914 | { 915 | tabsize = 4; 916 | useMicrosoftBOM = false; 917 | ClearError(); 918 | } 919 | 920 | TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) 921 | { 922 | tabsize = 4; 923 | useMicrosoftBOM = false; 924 | value = documentName; 925 | ClearError(); 926 | } 927 | 928 | 929 | #ifdef TIXML_USE_STL 930 | TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) 931 | { 932 | tabsize = 4; 933 | useMicrosoftBOM = false; 934 | value = documentName; 935 | ClearError(); 936 | } 937 | #endif 938 | 939 | 940 | TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) 941 | { 942 | copy.CopyTo( this ); 943 | } 944 | 945 | 946 | TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy ) 947 | { 948 | Clear(); 949 | copy.CopyTo( this ); 950 | return *this; 951 | } 952 | 953 | 954 | bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) 955 | { 956 | return LoadFile( Value(), encoding ); 957 | } 958 | 959 | 960 | bool TiXmlDocument::SaveFile() const 961 | { 962 | return SaveFile( Value() ); 963 | } 964 | 965 | bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) 966 | { 967 | TIXML_STRING filename( _filename ); 968 | //value = filename; 969 | 970 | // reading in binary mode so that tinyxml can normalize the EOL 971 | FILE* file = TiXmlFOpen( /*value.c_str ()*/_filename, "rb" ); 972 | 973 | if ( file ) 974 | { 975 | bool result = LoadFile( file, encoding ); 976 | fclose( file ); 977 | return result; 978 | } 979 | else 980 | { 981 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); 982 | return false; 983 | } 984 | } 985 | 986 | bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) 987 | { 988 | if ( !file ) 989 | { 990 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); 991 | return false; 992 | } 993 | 994 | // Delete the existing data: 995 | Clear(); 996 | location.Clear(); 997 | 998 | // Get the file size, so we can pre-allocate the string. HUGE speed impact. 999 | long length = 0; 1000 | fseek( file, 0, SEEK_END ); 1001 | length = ftell( file ); 1002 | fseek( file, 0, SEEK_SET ); 1003 | 1004 | // Strange case, but good to handle up front. 1005 | if ( length <= 0 ) 1006 | { 1007 | SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); 1008 | return false; 1009 | } 1010 | 1011 | // Subtle bug here. TinyXml did use fgets. But from the XML spec: 1012 | // 2.11 End-of-Line Handling 1013 | // 1014 | // 1015 | // ...the XML processor MUST behave as if it normalized all line breaks in external 1016 | // parsed entities (including the document entity) on input, before parsing, by translating 1017 | // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to 1018 | // a single #xA character. 1019 | // 1020 | // 1021 | // It is not clear fgets does that, and certainly isn't clear it works cross platform. 1022 | // Generally, you expect fgets to translate from the convention of the OS to the c/unix 1023 | // convention, and not work generally. 1024 | 1025 | /* 1026 | while( fgets( buf, sizeof(buf), file ) ) 1027 | { 1028 | data += buf; 1029 | } 1030 | */ 1031 | 1032 | char* buf = new char[ length+1 ]; 1033 | buf[0] = 0; 1034 | 1035 | if ( fread( buf, length, 1, file ) != 1 ) { 1036 | delete [] buf; 1037 | SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); 1038 | return false; 1039 | } 1040 | 1041 | // Process the buffer in place to normalize new lines. (See comment above.) 1042 | // Copies from the 'p' to 'q' pointer, where p can advance faster if 1043 | // a newline-carriage return is hit. 1044 | // 1045 | // Wikipedia: 1046 | // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or 1047 | // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... 1048 | // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others 1049 | // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS 1050 | // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 1051 | 1052 | const char* p = buf; // the read head 1053 | char* q = buf; // the write head 1054 | const char CR = 0x0d; 1055 | const char LF = 0x0a; 1056 | 1057 | buf[length] = 0; 1058 | while( *p ) { 1059 | assert( p < (buf+length) ); 1060 | assert( q <= (buf+length) ); 1061 | assert( q <= p ); 1062 | 1063 | if ( *p == CR ) { 1064 | *q++ = LF; 1065 | p++; 1066 | if ( *p == LF ) { // check for CR+LF (and skip LF) 1067 | p++; 1068 | } 1069 | } 1070 | else { 1071 | *q++ = *p++; 1072 | } 1073 | } 1074 | assert( q <= (buf+length) ); 1075 | *q = 0; 1076 | 1077 | Parse( buf, 0, encoding ); 1078 | 1079 | delete [] buf; 1080 | return !Error(); 1081 | } 1082 | 1083 | 1084 | bool TiXmlDocument::SaveFile( const char * filename ) const 1085 | { 1086 | // The old c stuff lives on... 1087 | FILE* fp = TiXmlFOpen( filename, "w" ); 1088 | if ( fp ) 1089 | { 1090 | bool result = SaveFile( fp ); 1091 | fclose( fp ); 1092 | return result; 1093 | } 1094 | return false; 1095 | } 1096 | 1097 | 1098 | bool TiXmlDocument::SaveFile( FILE* fp ) const 1099 | { 1100 | if ( useMicrosoftBOM ) 1101 | { 1102 | const unsigned char TIXML_UTF_LEAD_0 = 0xefU; 1103 | const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; 1104 | const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; 1105 | 1106 | fputc( TIXML_UTF_LEAD_0, fp ); 1107 | fputc( TIXML_UTF_LEAD_1, fp ); 1108 | fputc( TIXML_UTF_LEAD_2, fp ); 1109 | } 1110 | Print( fp, 0 ); 1111 | return (ferror(fp) == 0); 1112 | } 1113 | 1114 | 1115 | void TiXmlDocument::CopyTo( TiXmlDocument* target ) const 1116 | { 1117 | TiXmlNode::CopyTo( target ); 1118 | 1119 | target->error = error; 1120 | target->errorId = errorId; 1121 | target->errorDesc = errorDesc; 1122 | target->tabsize = tabsize; 1123 | target->errorLocation = errorLocation; 1124 | target->useMicrosoftBOM = useMicrosoftBOM; 1125 | 1126 | TiXmlNode* node = 0; 1127 | for ( node = firstChild; node; node = node->NextSibling() ) 1128 | { 1129 | target->LinkEndChild( node->Clone() ); 1130 | } 1131 | } 1132 | 1133 | 1134 | TiXmlNode* TiXmlDocument::Clone() const 1135 | { 1136 | TiXmlDocument* clone = new TiXmlDocument(); 1137 | if ( !clone ) 1138 | return 0; 1139 | 1140 | CopyTo( clone ); 1141 | return clone; 1142 | } 1143 | 1144 | 1145 | void TiXmlDocument::Print( FILE* cfile, int depth ) const 1146 | { 1147 | assert( cfile ); 1148 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) 1149 | { 1150 | node->Print( cfile, depth ); 1151 | fprintf( cfile, "\n" ); 1152 | } 1153 | } 1154 | 1155 | 1156 | bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const 1157 | { 1158 | if ( visitor->VisitEnter( *this ) ) 1159 | { 1160 | for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) 1161 | { 1162 | if ( !node->Accept( visitor ) ) 1163 | break; 1164 | } 1165 | } 1166 | return visitor->VisitExit( *this ); 1167 | } 1168 | 1169 | 1170 | const TiXmlAttribute* TiXmlAttribute::Next() const 1171 | { 1172 | // We are using knowledge of the sentinel. The sentinel 1173 | // have a value or name. 1174 | if ( next->value.empty() && next->name.empty() ) 1175 | return 0; 1176 | return next; 1177 | } 1178 | 1179 | /* 1180 | TiXmlAttribute* TiXmlAttribute::Next() 1181 | { 1182 | // We are using knowledge of the sentinel. The sentinel 1183 | // have a value or name. 1184 | if ( next->value.empty() && next->name.empty() ) 1185 | return 0; 1186 | return next; 1187 | } 1188 | */ 1189 | 1190 | const TiXmlAttribute* TiXmlAttribute::Previous() const 1191 | { 1192 | // We are using knowledge of the sentinel. The sentinel 1193 | // have a value or name. 1194 | if ( prev->value.empty() && prev->name.empty() ) 1195 | return 0; 1196 | return prev; 1197 | } 1198 | 1199 | /* 1200 | TiXmlAttribute* TiXmlAttribute::Previous() 1201 | { 1202 | // We are using knowledge of the sentinel. The sentinel 1203 | // have a value or name. 1204 | if ( prev->value.empty() && prev->name.empty() ) 1205 | return 0; 1206 | return prev; 1207 | } 1208 | */ 1209 | 1210 | void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const 1211 | { 1212 | TIXML_STRING n, v; 1213 | 1214 | EncodeString( name, &n ); 1215 | EncodeString( value, &v ); 1216 | 1217 | if (value.find ('\"') == TIXML_STRING::npos) { 1218 | if ( cfile ) { 1219 | fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); 1220 | } 1221 | if ( str ) { 1222 | (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; 1223 | } 1224 | } 1225 | else { 1226 | if ( cfile ) { 1227 | fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); 1228 | } 1229 | if ( str ) { 1230 | (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; 1231 | } 1232 | } 1233 | } 1234 | 1235 | 1236 | int TiXmlAttribute::QueryIntValue( int* ival ) const 1237 | { 1238 | if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) 1239 | return TIXML_SUCCESS; 1240 | return TIXML_WRONG_TYPE; 1241 | } 1242 | 1243 | int TiXmlAttribute::QueryDoubleValue( double* dval ) const 1244 | { 1245 | if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) 1246 | return TIXML_SUCCESS; 1247 | return TIXML_WRONG_TYPE; 1248 | } 1249 | 1250 | void TiXmlAttribute::SetIntValue( int _value ) 1251 | { 1252 | char buf [64]; 1253 | #if defined(TIXML_SNPRINTF) 1254 | TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); 1255 | #else 1256 | sprintf (buf, "%d", _value); 1257 | #endif 1258 | SetValue (buf); 1259 | } 1260 | 1261 | void TiXmlAttribute::SetDoubleValue( double _value ) 1262 | { 1263 | char buf [256]; 1264 | #if defined(TIXML_SNPRINTF) 1265 | TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); 1266 | #else 1267 | sprintf (buf, "%g", _value); 1268 | #endif 1269 | SetValue (buf); 1270 | } 1271 | 1272 | int TiXmlAttribute::IntValue() const 1273 | { 1274 | return atoi (value.c_str ()); 1275 | } 1276 | 1277 | double TiXmlAttribute::DoubleValue() const 1278 | { 1279 | return atof (value.c_str ()); 1280 | } 1281 | 1282 | 1283 | TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) 1284 | { 1285 | copy.CopyTo( this ); 1286 | } 1287 | 1288 | 1289 | TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base ) 1290 | { 1291 | Clear(); 1292 | base.CopyTo( this ); 1293 | return *this; 1294 | } 1295 | 1296 | 1297 | void TiXmlComment::Print( FILE* cfile, int depth ) const 1298 | { 1299 | assert( cfile ); 1300 | for ( int i=0; i", value.c_str() ); 1305 | } 1306 | 1307 | 1308 | void TiXmlComment::CopyTo( TiXmlComment* target ) const 1309 | { 1310 | TiXmlNode::CopyTo( target ); 1311 | } 1312 | 1313 | 1314 | bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const 1315 | { 1316 | return visitor->Visit( *this ); 1317 | } 1318 | 1319 | 1320 | TiXmlNode* TiXmlComment::Clone() const 1321 | { 1322 | TiXmlComment* clone = new TiXmlComment(); 1323 | 1324 | if ( !clone ) 1325 | return 0; 1326 | 1327 | CopyTo( clone ); 1328 | return clone; 1329 | } 1330 | 1331 | 1332 | void TiXmlText::Print( FILE* cfile, int depth ) const 1333 | { 1334 | assert( cfile ); 1335 | if ( cdata ) 1336 | { 1337 | int i; 1338 | fprintf( cfile, "\n" ); 1339 | for ( i=0; i\n", value.c_str() ); // unformatted output 1343 | } 1344 | else 1345 | { 1346 | TIXML_STRING buffer; 1347 | EncodeString( value, &buffer ); 1348 | fprintf( cfile, "%s", buffer.c_str() ); 1349 | } 1350 | } 1351 | 1352 | 1353 | void TiXmlText::CopyTo( TiXmlText* target ) const 1354 | { 1355 | TiXmlNode::CopyTo( target ); 1356 | target->cdata = cdata; 1357 | } 1358 | 1359 | 1360 | bool TiXmlText::Accept( TiXmlVisitor* visitor ) const 1361 | { 1362 | return visitor->Visit( *this ); 1363 | } 1364 | 1365 | 1366 | TiXmlNode* TiXmlText::Clone() const 1367 | { 1368 | TiXmlText* clone = 0; 1369 | clone = new TiXmlText( "" ); 1370 | 1371 | if ( !clone ) 1372 | return 0; 1373 | 1374 | CopyTo( clone ); 1375 | return clone; 1376 | } 1377 | 1378 | 1379 | TiXmlDeclaration::TiXmlDeclaration( const char * _version, 1380 | const char * _encoding, 1381 | const char * _standalone ) 1382 | : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) 1383 | { 1384 | version = _version; 1385 | encoding = _encoding; 1386 | standalone = _standalone; 1387 | } 1388 | 1389 | 1390 | #ifdef TIXML_USE_STL 1391 | TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, 1392 | const std::string& _encoding, 1393 | const std::string& _standalone ) 1394 | : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) 1395 | { 1396 | version = _version; 1397 | encoding = _encoding; 1398 | standalone = _standalone; 1399 | } 1400 | #endif 1401 | 1402 | 1403 | TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) 1404 | : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) 1405 | { 1406 | copy.CopyTo( this ); 1407 | } 1408 | 1409 | 1410 | TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) 1411 | { 1412 | Clear(); 1413 | copy.CopyTo( this ); 1414 | return *this; 1415 | } 1416 | 1417 | 1418 | void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const 1419 | { 1420 | if ( cfile ) fprintf( cfile, "" ); 1436 | if ( str ) (*str) += "?>"; 1437 | } 1438 | 1439 | 1440 | void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const 1441 | { 1442 | TiXmlNode::CopyTo( target ); 1443 | 1444 | target->version = version; 1445 | target->encoding = encoding; 1446 | target->standalone = standalone; 1447 | } 1448 | 1449 | 1450 | bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const 1451 | { 1452 | return visitor->Visit( *this ); 1453 | } 1454 | 1455 | 1456 | TiXmlNode* TiXmlDeclaration::Clone() const 1457 | { 1458 | TiXmlDeclaration* clone = new TiXmlDeclaration(); 1459 | 1460 | if ( !clone ) 1461 | return 0; 1462 | 1463 | CopyTo( clone ); 1464 | return clone; 1465 | } 1466 | 1467 | 1468 | void TiXmlUnknown::Print( FILE* cfile, int depth ) const 1469 | { 1470 | for ( int i=0; i", value.c_str() ); 1473 | } 1474 | 1475 | 1476 | void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const 1477 | { 1478 | TiXmlNode::CopyTo( target ); 1479 | } 1480 | 1481 | 1482 | bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const 1483 | { 1484 | return visitor->Visit( *this ); 1485 | } 1486 | 1487 | 1488 | TiXmlNode* TiXmlUnknown::Clone() const 1489 | { 1490 | TiXmlUnknown* clone = new TiXmlUnknown(); 1491 | 1492 | if ( !clone ) 1493 | return 0; 1494 | 1495 | CopyTo( clone ); 1496 | return clone; 1497 | } 1498 | 1499 | 1500 | TiXmlAttributeSet::TiXmlAttributeSet() 1501 | { 1502 | sentinel.next = &sentinel; 1503 | sentinel.prev = &sentinel; 1504 | } 1505 | 1506 | 1507 | TiXmlAttributeSet::~TiXmlAttributeSet() 1508 | { 1509 | assert( sentinel.next == &sentinel ); 1510 | assert( sentinel.prev == &sentinel ); 1511 | } 1512 | 1513 | 1514 | void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) 1515 | { 1516 | #ifdef TIXML_USE_STL 1517 | assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. 1518 | #else 1519 | assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. 1520 | #endif 1521 | 1522 | addMe->next = &sentinel; 1523 | addMe->prev = sentinel.prev; 1524 | 1525 | sentinel.prev->next = addMe; 1526 | sentinel.prev = addMe; 1527 | } 1528 | 1529 | void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) 1530 | { 1531 | TiXmlAttribute* node; 1532 | 1533 | for( node = sentinel.next; node != &sentinel; node = node->next ) 1534 | { 1535 | if ( node == removeMe ) 1536 | { 1537 | node->prev->next = node->next; 1538 | node->next->prev = node->prev; 1539 | node->next = 0; 1540 | node->prev = 0; 1541 | return; 1542 | } 1543 | } 1544 | assert( 0 ); // we tried to remove a non-linked attribute. 1545 | } 1546 | 1547 | 1548 | #ifdef TIXML_USE_STL 1549 | TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const 1550 | { 1551 | for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) 1552 | { 1553 | if ( node->name == name ) 1554 | return node; 1555 | } 1556 | return 0; 1557 | } 1558 | 1559 | TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) 1560 | { 1561 | TiXmlAttribute* attrib = Find( _name ); 1562 | if ( !attrib ) { 1563 | attrib = new TiXmlAttribute(); 1564 | Add( attrib ); 1565 | attrib->SetName( _name ); 1566 | } 1567 | return attrib; 1568 | } 1569 | #endif 1570 | 1571 | 1572 | TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const 1573 | { 1574 | for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) 1575 | { 1576 | if ( strcmp( node->name.c_str(), name ) == 0 ) 1577 | return node; 1578 | } 1579 | return 0; 1580 | } 1581 | 1582 | 1583 | TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) 1584 | { 1585 | TiXmlAttribute* attrib = Find( _name ); 1586 | if ( !attrib ) { 1587 | attrib = new TiXmlAttribute(); 1588 | Add( attrib ); 1589 | attrib->SetName( _name ); 1590 | } 1591 | return attrib; 1592 | } 1593 | 1594 | 1595 | #ifdef TIXML_USE_STL 1596 | std::istream& operator>> (std::istream & in, TiXmlNode & base) 1597 | { 1598 | TIXML_STRING tag; 1599 | tag.reserve( 8 * 1000 ); 1600 | base.StreamIn( &in, &tag ); 1601 | 1602 | base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); 1603 | return in; 1604 | } 1605 | #endif 1606 | 1607 | 1608 | #ifdef TIXML_USE_STL 1609 | std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) 1610 | { 1611 | TiXmlPrinter printer; 1612 | printer.SetStreamPrinting(); 1613 | base.Accept( &printer ); 1614 | out << printer.Str(); 1615 | 1616 | return out; 1617 | } 1618 | 1619 | 1620 | std::string& operator<< (std::string& out, const TiXmlNode& base ) 1621 | { 1622 | TiXmlPrinter printer; 1623 | printer.SetStreamPrinting(); 1624 | base.Accept( &printer ); 1625 | out.append( printer.Str() ); 1626 | 1627 | return out; 1628 | } 1629 | #endif 1630 | 1631 | 1632 | TiXmlHandle TiXmlHandle::FirstChild() const 1633 | { 1634 | if ( node ) 1635 | { 1636 | TiXmlNode* child = node->FirstChild(); 1637 | if ( child ) 1638 | return TiXmlHandle( child ); 1639 | } 1640 | return TiXmlHandle( 0 ); 1641 | } 1642 | 1643 | 1644 | TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const 1645 | { 1646 | if ( node ) 1647 | { 1648 | TiXmlNode* child = node->FirstChild( value ); 1649 | if ( child ) 1650 | return TiXmlHandle( child ); 1651 | } 1652 | return TiXmlHandle( 0 ); 1653 | } 1654 | 1655 | 1656 | TiXmlHandle TiXmlHandle::FirstChildElement() const 1657 | { 1658 | if ( node ) 1659 | { 1660 | TiXmlElement* child = node->FirstChildElement(); 1661 | if ( child ) 1662 | return TiXmlHandle( child ); 1663 | } 1664 | return TiXmlHandle( 0 ); 1665 | } 1666 | 1667 | 1668 | TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const 1669 | { 1670 | if ( node ) 1671 | { 1672 | TiXmlElement* child = node->FirstChildElement( value ); 1673 | if ( child ) 1674 | return TiXmlHandle( child ); 1675 | } 1676 | return TiXmlHandle( 0 ); 1677 | } 1678 | 1679 | 1680 | TiXmlHandle TiXmlHandle::Child( int count ) const 1681 | { 1682 | if ( node ) 1683 | { 1684 | int i; 1685 | TiXmlNode* child = node->FirstChild(); 1686 | for ( i=0; 1687 | child && iNextSibling(), ++i ) 1689 | { 1690 | // nothing 1691 | } 1692 | if ( child ) 1693 | return TiXmlHandle( child ); 1694 | } 1695 | return TiXmlHandle( 0 ); 1696 | } 1697 | 1698 | 1699 | TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const 1700 | { 1701 | if ( node ) 1702 | { 1703 | int i; 1704 | TiXmlNode* child = node->FirstChild( value ); 1705 | for ( i=0; 1706 | child && iNextSibling( value ), ++i ) 1708 | { 1709 | // nothing 1710 | } 1711 | if ( child ) 1712 | return TiXmlHandle( child ); 1713 | } 1714 | return TiXmlHandle( 0 ); 1715 | } 1716 | 1717 | 1718 | TiXmlHandle TiXmlHandle::ChildElement( int count ) const 1719 | { 1720 | if ( node ) 1721 | { 1722 | int i; 1723 | TiXmlElement* child = node->FirstChildElement(); 1724 | for ( i=0; 1725 | child && iNextSiblingElement(), ++i ) 1727 | { 1728 | // nothing 1729 | } 1730 | if ( child ) 1731 | return TiXmlHandle( child ); 1732 | } 1733 | return TiXmlHandle( 0 ); 1734 | } 1735 | 1736 | 1737 | TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const 1738 | { 1739 | if ( node ) 1740 | { 1741 | int i; 1742 | TiXmlElement* child = node->FirstChildElement( value ); 1743 | for ( i=0; 1744 | child && iNextSiblingElement( value ), ++i ) 1746 | { 1747 | // nothing 1748 | } 1749 | if ( child ) 1750 | return TiXmlHandle( child ); 1751 | } 1752 | return TiXmlHandle( 0 ); 1753 | } 1754 | 1755 | 1756 | bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) 1757 | { 1758 | return true; 1759 | } 1760 | 1761 | bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) 1762 | { 1763 | return true; 1764 | } 1765 | 1766 | bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) 1767 | { 1768 | DoIndent(); 1769 | buffer += "<"; 1770 | buffer += element.Value(); 1771 | 1772 | for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) 1773 | { 1774 | buffer += " "; 1775 | attrib->Print( 0, 0, &buffer ); 1776 | } 1777 | 1778 | if ( !element.FirstChild() ) 1779 | { 1780 | buffer += " />"; 1781 | DoLineBreak(); 1782 | } 1783 | else 1784 | { 1785 | buffer += ">"; 1786 | if ( element.FirstChild()->ToText() 1787 | && element.LastChild() == element.FirstChild() 1788 | && element.FirstChild()->ToText()->CDATA() == false ) 1789 | { 1790 | simpleTextPrint = true; 1791 | // no DoLineBreak()! 1792 | } 1793 | else 1794 | { 1795 | DoLineBreak(); 1796 | } 1797 | } 1798 | ++depth; 1799 | return true; 1800 | } 1801 | 1802 | 1803 | bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) 1804 | { 1805 | --depth; 1806 | if ( !element.FirstChild() ) 1807 | { 1808 | // nothing. 1809 | } 1810 | else 1811 | { 1812 | if ( simpleTextPrint ) 1813 | { 1814 | simpleTextPrint = false; 1815 | } 1816 | else 1817 | { 1818 | DoIndent(); 1819 | } 1820 | buffer += ""; 1823 | DoLineBreak(); 1824 | } 1825 | return true; 1826 | } 1827 | 1828 | 1829 | bool TiXmlPrinter::Visit( const TiXmlText& text ) 1830 | { 1831 | if ( text.CDATA() ) 1832 | { 1833 | DoIndent(); 1834 | buffer += ""; 1837 | DoLineBreak(); 1838 | } 1839 | else if ( simpleTextPrint ) 1840 | { 1841 | TIXML_STRING str; 1842 | TiXmlBase::EncodeString( text.ValueTStr(), &str ); 1843 | buffer += str; 1844 | } 1845 | else 1846 | { 1847 | DoIndent(); 1848 | TIXML_STRING str; 1849 | TiXmlBase::EncodeString( text.ValueTStr(), &str ); 1850 | buffer += str; 1851 | DoLineBreak(); 1852 | } 1853 | return true; 1854 | } 1855 | 1856 | 1857 | bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) 1858 | { 1859 | DoIndent(); 1860 | declaration.Print( 0, 0, &buffer ); 1861 | DoLineBreak(); 1862 | return true; 1863 | } 1864 | 1865 | 1866 | bool TiXmlPrinter::Visit( const TiXmlComment& comment ) 1867 | { 1868 | DoIndent(); 1869 | buffer += ""; 1872 | DoLineBreak(); 1873 | return true; 1874 | } 1875 | 1876 | 1877 | bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) 1878 | { 1879 | DoIndent(); 1880 | buffer += "<"; 1881 | buffer += unknown.Value(); 1882 | buffer += ">"; 1883 | DoLineBreak(); 1884 | return true; 1885 | } 1886 | 1887 | --------------------------------------------------------------------------------