summaryrefslogtreecommitdiff
path: root/src/utils
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2017-02-07 20:38:10 +0300
committerAndrei Karas <akaras@inbox.ru>2017-03-24 00:08:35 +0300
commitd1590377de1141144d59ca1160de2822177f6f2a (patch)
treea368b251dedc7164cadbfe459de4cf5c983acf98 /src/utils
parent65422e722cfe0616c65498c71aa0651857dcc49a (diff)
downloadmv-d1590377de1141144d59ca1160de2822177f6f2a.tar.gz
mv-d1590377de1141144d59ca1160de2822177f6f2a.tar.bz2
mv-d1590377de1141144d59ca1160de2822177f6f2a.tar.xz
mv-d1590377de1141144d59ca1160de2822177f6f2a.zip
Add support for tinyxml2 for reading / writing xml files.
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/xml.h2
-rw-r--r--src/utils/xml/libxml.cpp14
-rw-r--r--src/utils/xml/libxml.h14
-rw-r--r--src/utils/xml/libxml.inc7
-rw-r--r--src/utils/xml/pugixml.cpp14
-rw-r--r--src/utils/xml/pugixml.h14
-rw-r--r--src/utils/xml/pugixml.inc6
-rw-r--r--src/utils/xml/tinyxml2.cpp306
-rw-r--r--src/utils/xml/tinyxml2.h161
-rw-r--r--src/utils/xml/tinyxml2.inc70
-rw-r--r--src/utils/xml_unittest.cc22
-rw-r--r--src/utils/xmlutils.cpp6
12 files changed, 594 insertions, 42 deletions
diff --git a/src/utils/xml.h b/src/utils/xml.h
index d15afd1b9..ac93231fc 100644
--- a/src/utils/xml.h
+++ b/src/utils/xml.h
@@ -23,6 +23,8 @@
#ifdef ENABLE_PUGIXML
#include "utils/xml/pugixml.h"
+#elif defined(ENABLE_TINYXML2)
+#include "utils/xml/tinyxml2.h"
#else // ENABLE_PUGIXML
#include "utils/xml/libxml.h"
#endif // ENABLE_PUGIXML
diff --git a/src/utils/xml/libxml.cpp b/src/utils/xml/libxml.cpp
index f6e38f08f..cb350a639 100644
--- a/src/utils/xml/libxml.cpp
+++ b/src/utils/xml/libxml.cpp
@@ -165,7 +165,7 @@ namespace XML
return mDoc ? xmlDocGetRootElement(mDoc) : nullptr;
}
- int getProperty(const XmlNodePtr node,
+ int getProperty(XmlNodeConstPtr node,
const char *const name,
int def)
{
@@ -181,7 +181,7 @@ namespace XML
return ret;
}
- int getIntProperty(const XmlNodePtr node,
+ int getIntProperty(XmlNodeConstPtr node,
const char *const name,
int def,
const int min,
@@ -202,7 +202,7 @@ namespace XML
return ret;
}
- double getFloatProperty(const XmlNodePtr node,
+ double getFloatProperty(XmlNodeConstPtr node,
const char *const name,
double def)
{
@@ -218,7 +218,7 @@ namespace XML
return ret;
}
- std::string getProperty(const XmlNodePtr node,
+ std::string getProperty(XmlNodeConstPtr node,
const char *const name,
const std::string &def)
{
@@ -233,7 +233,7 @@ namespace XML
return def;
}
- std::string langProperty(const XmlNodePtr node,
+ std::string langProperty(XmlNodeConstPtr node,
const char *const name,
const std::string &def)
{
@@ -244,7 +244,7 @@ namespace XML
return translator->getStr(str);
}
- bool getBoolProperty(const XmlNodePtr node,
+ bool getBoolProperty(XmlNodeConstPtr node,
const char *const name,
const bool def)
{
@@ -264,7 +264,7 @@ namespace XML
return def;
}
- XmlNodePtr findFirstChildByName(const XmlNodePtrConst parent,
+ XmlNodePtr findFirstChildByName(XmlNodeConstPtrConst parent,
const char *const name)
{
if (!parent)
diff --git a/src/utils/xml/libxml.h b/src/utils/xml/libxml.h
index 9ef419121..d9f707a5e 100644
--- a/src/utils/xml/libxml.h
+++ b/src/utils/xml/libxml.h
@@ -98,21 +98,21 @@ namespace XML
/**
* Gets an floating point property from an XmlNodePtr.
*/
- double getFloatProperty(const XmlNodePtr node,
+ double getFloatProperty(XmlNodeConstPtr node,
const char *const name,
double def) A_WARN_UNUSED;
/**
* Gets an integer property from an XmlNodePtr.
*/
- int getProperty(const XmlNodePtr node,
+ int getProperty(XmlNodeConstPtr node,
const char *const name,
int def) A_WARN_UNUSED;
/**
* Gets an integer property from an XmlNodePtr.
*/
- int getIntProperty(const XmlNodePtr node,
+ int getIntProperty(XmlNodeConstPtr node,
const char *const name,
int def,
const int min,
@@ -121,28 +121,28 @@ namespace XML
/**
* Gets a string property from an XmlNodePtr.
*/
- std::string getProperty(const XmlNodePtr node,
+ std::string getProperty(XmlNodeConstPtr node,
const char *const name,
const std::string &def) A_WARN_UNUSED;
/**
* Gets a translated string property from an XmlNodePtr.
*/
- std::string langProperty(const XmlNodePtr node,
+ std::string langProperty(XmlNodeConstPtr node,
const char *const name,
const std::string &def) A_WARN_UNUSED;
/**
* Gets a boolean property from an XmlNodePtr.
*/
- bool getBoolProperty(const XmlNodePtr node,
+ bool getBoolProperty(XmlNodeConstPtr node,
const char *const name,
const bool def) A_WARN_UNUSED;
/**
* Finds the first child node with the given name
*/
- XmlNodePtr findFirstChildByName(const XmlNodePtrConst parent,
+ XmlNodePtr findFirstChildByName(XmlNodeConstPtrConst parent,
const char *const name) A_WARN_UNUSED;
void initXML();
diff --git a/src/utils/xml/libxml.inc b/src/utils/xml/libxml.inc
index 1bf4fddd5..ec837f224 100644
--- a/src/utils/xml/libxml.inc
+++ b/src/utils/xml/libxml.inc
@@ -29,16 +29,20 @@ __XML_XMLWRITER_H__
#define XmlNodePtr xmlNodePtr
#define XmlNodePtrConst xmlNode *const
+#define XmlNodeConstPtr const xmlNodePtr
+#define XmlNodeConstPtrConst const xmlNode *const
#define XmlStrEqual(str1, str2) xmlStrEqual(str1, \
reinterpret_cast<const xmlChar*>(str2))
#define xmlNameEqual(node, str) xmlStrEqual((node)->name, \
reinterpret_cast<const xmlChar*>(str))
-#define XmlTextWriterPtr xmlTextWriterPtr
+#define XmlTextWriterPtr const xmlTextWriterPtr
#define xmlTypeEqual(node, typ) ((node)->type == (typ))
#define XmlHasProp(node, name) (xmlHasProp(node, \
reinterpret_cast<const xmlChar*>(name)) != nullptr)
#define XmlGetProp(node, name) xmlGetProp(node, \
reinterpret_cast<const xmlChar*>(name))
+#define XmlTextWriterStartRootElement(writer, name) \
+ xmlTextWriterStartElement(writer, reinterpret_cast<const xmlChar*>(name))
#define XmlTextWriterStartElement(writer, name) \
xmlTextWriterStartElement(writer, reinterpret_cast<const xmlChar*>(name))
#define XmlTextWriterEndElement(writer) xmlTextWriterEndElement(writer)
@@ -49,6 +53,7 @@ __XML_XMLWRITER_H__
#define XmlNodeGetContent(node) xmlNodeGetContent(node)
#define XmlNewTextWriterFilename(name, flags) \
xmlNewTextWriterFilename(name, flags)
+#define XmlSaveTextWriterFilename(writer, name)
#define XmlTextWriterSetIndent(writer, flags) \
xmlTextWriterSetIndent(writer, flags)
#define XmlTextWriterStartDocument(writer, p1, p2, p3) \
diff --git a/src/utils/xml/pugixml.cpp b/src/utils/xml/pugixml.cpp
index 8d5e8db59..1897bc943 100644
--- a/src/utils/xml/pugixml.cpp
+++ b/src/utils/xml/pugixml.cpp
@@ -176,7 +176,7 @@ namespace XML
return mDoc.first_child();
}
- int getProperty(const XmlNodePtr node,
+ int getProperty(XmlNodeConstPtr node,
const char *const name,
int def)
{
@@ -191,7 +191,7 @@ namespace XML
return ret;
}
- int getIntProperty(const XmlNodePtr node,
+ int getIntProperty(XmlNodeConstPtr node,
const char *const name,
int def,
const int min,
@@ -212,7 +212,7 @@ namespace XML
return ret;
}
- double getFloatProperty(const XmlNodePtr node,
+ double getFloatProperty(XmlNodeConstPtr node,
const char *const name,
double def)
{
@@ -227,7 +227,7 @@ namespace XML
return ret;
}
- std::string getProperty(const XmlNodePtr node,
+ std::string getProperty(XmlNodeConstPtr node,
const char *const name,
const std::string &def)
{
@@ -240,7 +240,7 @@ namespace XML
return def;
}
- std::string langProperty(const XmlNodePtr node,
+ std::string langProperty(XmlNodeConstPtr node,
const char *const name,
const std::string &def)
{
@@ -251,7 +251,7 @@ namespace XML
return translator->getStr(str);
}
- bool getBoolProperty(const XmlNodePtr node,
+ bool getBoolProperty(XmlNodeConstPtr node,
const char *const name,
const bool def)
{
@@ -270,7 +270,7 @@ namespace XML
return def;
}
- XmlNodePtr findFirstChildByName(const XmlNodePtrConst parent,
+ XmlNodePtr findFirstChildByName(XmlNodeConstPtrConst parent,
const char *const name)
{
if (!parent || !name)
diff --git a/src/utils/xml/pugixml.h b/src/utils/xml/pugixml.h
index b6d9e5bfd..14a3bdbdf 100644
--- a/src/utils/xml/pugixml.h
+++ b/src/utils/xml/pugixml.h
@@ -99,21 +99,21 @@ namespace XML
/**
* Gets an floating point property from an XmlNodePtr.
*/
- double getFloatProperty(const XmlNodePtr node,
+ double getFloatProperty(XmlNodeConstPtr node,
const char *const name,
double def) A_WARN_UNUSED;
/**
* Gets an integer property from an XmlNodePtr.
*/
- int getProperty(const XmlNodePtr node,
+ int getProperty(XmlNodeConstPtr node,
const char *const name,
int def) A_WARN_UNUSED;
/**
* Gets an integer property from an XmlNodePtr.
*/
- int getIntProperty(const XmlNodePtr node,
+ int getIntProperty(XmlNodeConstPtr node,
const char *const name,
int def,
const int min,
@@ -122,28 +122,28 @@ namespace XML
/**
* Gets a string property from an XmlNodePtr.
*/
- std::string getProperty(const XmlNodePtr node,
+ std::string getProperty(XmlNodeConstPtr node,
const char *const name,
const std::string &def) A_WARN_UNUSED;
/**
* Gets a translated string property from an XmlNodePtr.
*/
- std::string langProperty(const XmlNodePtr node,
+ std::string langProperty(XmlNodeConstPtr node,
const char *const name,
const std::string &def) A_WARN_UNUSED;
/**
* Gets a boolean property from an XmlNodePtr.
*/
- bool getBoolProperty(const XmlNodePtr node,
+ bool getBoolProperty(XmlNodeConstPtr node,
const char *const name,
const bool def) A_WARN_UNUSED;
/**
* Finds the first child node with the given name
*/
- XmlNodePtr findFirstChildByName(const XmlNodePtrConst parent,
+ XmlNodePtr findFirstChildByName(XmlNodeConstPtrConst parent,
const char *const name) A_WARN_UNUSED;
void initXML();
diff --git a/src/utils/xml/pugixml.inc b/src/utils/xml/pugixml.inc
index d8ef38242..c8685f877 100644
--- a/src/utils/xml/pugixml.inc
+++ b/src/utils/xml/pugixml.inc
@@ -27,6 +27,8 @@
#define XmlNodePtr pugi::xml_node
#define XmlNodePtrConst pugi::xml_node
+#define XmlNodeConstPtr const pugi::xml_node
+#define XmlNodeConstPtrConst const pugi::xml_node
#define xmlNameEqual(node, str) !strcmp((node).name(), str)
#define xmlTypeEqual(node, typ) ((node).type() == (typ))
#define XmlHasProp(node, name) (!((node).attribute(name).empty()))
@@ -37,12 +39,14 @@
#define XmlFree(ptr)
#define XmlNodeDefault pugi::xml_node()
#define XmlNodeGetContent(node) (node).child_value()
-#define XmlTextWriterPtr XML::Writer *
+#define XmlTextWriterPtr const XML::Writer *
+#define XmlTextWriterStartRootElement(writer, name) (writer)->startNode(name)
#define XmlTextWriterStartElement(writer, name) (writer)->startNode(name)
#define XmlTextWriterEndElement(writer) (writer)->endNode()
#define XmlTextWriterWriteAttribute(writer, name, content) \
(writer)->addAttribute(name, content)
#define XmlNewTextWriterFilename(name, flags) new XML::Writer(name);
+#define XmlSaveTextWriterFilename(writer, name)
#define XmlTextWriterSetIndent(writer, flags)
#define XmlTextWriterStartDocument(writer, p1, p2, p3)
#define XmlTextWriterEndDocument(writer) (writer)->endDocument()
diff --git a/src/utils/xml/tinyxml2.cpp b/src/utils/xml/tinyxml2.cpp
new file mode 100644
index 000000000..6805ef48d
--- /dev/null
+++ b/src/utils/xml/tinyxml2.cpp
@@ -0,0 +1,306 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef ENABLE_TINYXML2
+
+#include "utils/xml/tinyxml2.h"
+
+#include "fs/virtfstools.h"
+
+#include "utils/checkutils.h"
+#include "utils/fuzzer.h"
+#include "utils/stringutils.h"
+
+#include "utils/translation/podict.h"
+
+#include "debug.h"
+
+namespace
+{
+ bool valid = false;
+} // namespace
+
+namespace XML
+{
+ static void showErrorStatus(tinyxml2::XMLDocument &doc)
+ {
+ logger->log("xml error: %s, in lines: %s\n%s",
+ doc.ErrorName(),
+ doc.GetErrorStr1(),
+ doc.GetErrorStr2());
+ }
+
+ Document::Document(const std::string &filename,
+ const UseVirtFs useResman,
+ const SkipError skipError) :
+ Resource(),
+ mDoc(),
+ mData(nullptr),
+ mIsValid(false)
+ {
+#ifdef USE_FUZZER
+ if (Fuzzer::conditionTerminate(filename.c_str()))
+ return;
+#endif // USE_FUZZER
+
+ BLOCK_START("XML::Document::Document")
+ int size = 0;
+ char *data = nullptr;
+ valid = true;
+ if (useResman == UseVirtFs_true)
+ {
+ data = static_cast<char*>(VirtFs::loadFile(
+ filename.c_str(), size));
+ }
+ else
+ {
+ std::ifstream file;
+ file.open(filename.c_str(), std::ios::in);
+
+ if (file.is_open())
+ {
+ // Get length of file
+ file.seekg(0, std::ios::end);
+ size = CAST_S32(file.tellg());
+ if (size < 0)
+ {
+ reportAlways("Error loading XML file %s",
+ filename.c_str());
+ }
+ else
+ {
+ file.seekg(0, std::ios::beg);
+ data = static_cast<char*>(malloc(size));
+ file.read(data, size);
+ }
+ file.close();
+ }
+ else
+ {
+ reportAlways("Error loading XML file %s",
+ filename.c_str());
+ }
+ }
+
+ if (data)
+ {
+ tinyxml2::XMLError result = mDoc.Parse(data,
+ size);
+ if (result != tinyxml2::XML_SUCCESS)
+ {
+ showErrorStatus(mDoc);
+ free(data);
+ }
+ else
+ {
+ mData = data;
+ }
+ }
+ else if (skipError == SkipError_false)
+ {
+ reportAlways("Error loading %s", filename.c_str());
+ }
+ mIsValid = valid;
+ BLOCK_END("XML::Document::Document")
+ }
+
+ Document::Document(const char *const data, const int size) :
+ Resource(),
+ mDoc(),
+ mData(nullptr),
+ mIsValid(true)
+ {
+ if (!data)
+ return;
+
+ char *buf = static_cast<char*>(calloc(size + 1, 1));
+ strncpy(buf, data, size);
+ buf[size] = 0;
+
+ tinyxml2::XMLError result = mDoc.Parse(buf,
+ size);
+ if (result != tinyxml2::XML_SUCCESS)
+ {
+ showErrorStatus(mDoc);
+ free(buf);
+ }
+ else
+ {
+ mData = buf;
+ }
+ }
+
+ Document::~Document()
+ {
+ free(mData);
+ mData = nullptr;
+ }
+
+ XmlNodeConstPtr Document::rootNode()
+ {
+ return mDoc.FirstChildElement();
+ }
+
+ int getProperty(XmlNodeConstPtr node,
+ const char *const name,
+ int def)
+ {
+ int &ret = def;
+
+ if (!node)
+ return ret;
+ const char *attr = node->Attribute(name);
+ if (attr != nullptr)
+ ret = atoi(attr);
+
+ return ret;
+ }
+
+ int getIntProperty(XmlNodeConstPtr node,
+ const char *const name,
+ int def,
+ const int min,
+ const int max)
+ {
+ int &ret = def;
+
+ if (!node)
+ return ret;
+ const char *attr = node->Attribute(name);
+ if (attr != nullptr)
+ ret = atoi(attr);
+
+ if (ret < min)
+ ret = min;
+ else if (ret > max)
+ ret = max;
+ return ret;
+ }
+
+ double getFloatProperty(XmlNodeConstPtr node,
+ const char *const name,
+ double def)
+ {
+ double &ret = def;
+
+ if (!node)
+ return ret;
+ const char *attr = node->Attribute(name);
+ if (attr != nullptr)
+ ret = atof(attr);
+
+ return ret;
+ }
+
+ std::string getProperty(XmlNodeConstPtr node,
+ const char *const name,
+ const std::string &def)
+ {
+ if (!node)
+ return def;
+ const char *attr = node->Attribute(name);
+ if (attr != nullptr)
+ return attr;
+
+ return def;
+ }
+
+ std::string langProperty(XmlNodeConstPtr node,
+ const char *const name,
+ const std::string &def)
+ {
+ std::string str = getProperty(node, name, def);
+ if (!translator)
+ return str;
+
+ return translator->getStr(str);
+ }
+
+ bool getBoolProperty(XmlNodeConstPtr node,
+ const char *const name,
+ const bool def)
+ {
+ if (!node)
+ return def;
+ const char *attr = node->Attribute(name);
+ if (attr != nullptr)
+ {
+ std::string val = attr;
+ if (val == "true")
+ return true;
+ if (val == "false")
+ return false;
+ }
+
+ return def;
+ }
+
+ XmlNodeConstPtr findFirstChildByName(XmlNodeConstPtrConst parent,
+ const char *const name)
+ {
+ if (!parent || !name)
+ return nullptr;
+ return parent->FirstChildElement(name);
+ }
+
+ // Initialize xml
+ void initXML()
+ {
+ }
+
+ // Shutdown xml
+ void cleanupXML()
+ {
+ }
+
+ bool Document::validateXml(const std::string &fileName)
+ {
+ tinyxml2::XMLDocument doc;
+ tinyxml2::XMLError result = doc.LoadFile(fileName.c_str());
+
+ if (result != tinyxml2::XML_SUCCESS)
+ {
+ showErrorStatus(doc);
+ return false;
+ }
+
+ std::ifstream file;
+ file.open(fileName.c_str(), std::ios::in);
+ if (!file.is_open())
+ {
+ file.close();
+ return false;
+ }
+ char line[101];
+ if (!file.getline(line, 100))
+ return false;
+ file.close();
+
+ const std::string str = line;
+ if (!strStartWith(str, "<?xml "))
+ return false;
+
+ return true;
+ }
+} // namespace XML
+
+#endif // ENABLE_TINYXML2
diff --git a/src/utils/xml/tinyxml2.h b/src/utils/xml/tinyxml2.h
new file mode 100644
index 000000000..e817f7276
--- /dev/null
+++ b/src/utils/xml/tinyxml2.h
@@ -0,0 +1,161 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_XML_TINYXML2_H
+#define UTILS_XML_TINYXML2_H
+
+#ifdef ENABLE_TINYXML2
+
+#define XML_INCLUDE_DEFINE
+
+#include "enums/simpletypes/skiperror.h"
+#include "enums/simpletypes/usevirtfs.h"
+
+#include "utils/xml/tinyxml2.inc"
+
+#include "resources/resource.h"
+
+#ifndef _GLIBCXX_STRING
+#include <string>
+#endif // _GLIBCXX_STRING
+
+#include "localconsts.h"
+
+/**
+ * XML helper functions.
+ */
+namespace XML
+{
+ /**
+ * A helper class for parsing an XML document, which also cleans it up
+ * again (RAII).
+ */
+ class Document final : public Resource
+ {
+ public:
+ /**
+ * Constructor that attempts to load the given file through the
+ * resource manager. Logs errors.
+ */
+ Document(const std::string &filename,
+ const UseVirtFs useResman,
+ const SkipError skipError);
+
+ /**
+ * Constructor that attempts to load an XML document from memory.
+ * Does not log errors.
+ *
+ * @param data the string to parse as XML
+ * @param size the length of the string in bytes
+ */
+ Document(const char *const data, const int size);
+
+ A_DELETE_COPY(Document)
+
+ /**
+ * Destructor. Frees the loaded XML file.
+ */
+ ~Document();
+
+ /**
+ * Returns the root node of the document (or NULL if there was a
+ * load error).
+ */
+ XmlNodePtr rootNode() A_WARN_UNUSED;
+
+ bool isLoaded() const
+ { return mDoc.Error() == false; }
+
+ bool isValid() const
+ { return mIsValid; }
+
+ static bool validateXml(const std::string &fileName);
+
+ private:
+ tinyxml2::XMLDocument mDoc;
+ char *mData;
+ bool mIsValid;
+ };
+
+ /**
+ * Gets an floating point property from an XmlNodePtr.
+ */
+ double getFloatProperty(XmlNodeConstPtr node,
+ const char *const name,
+ double def) A_WARN_UNUSED;
+
+ /**
+ * Gets an integer property from an XmlNodePtr.
+ */
+ int getProperty(XmlNodeConstPtr node,
+ const char *const name,
+ int def) A_WARN_UNUSED;
+
+ /**
+ * Gets an integer property from an XmlNodePtr.
+ */
+ int getIntProperty(XmlNodeConstPtr node,
+ const char *const name,
+ int def,
+ const int min,
+ const int max) A_WARN_UNUSED;
+
+ /**
+ * Gets a string property from an XmlNodePtr.
+ */
+ std::string getProperty(XmlNodeConstPtr node,
+ const char *const name,
+ const std::string &def) A_WARN_UNUSED;
+
+ /**
+ * Gets a translated string property from an XmlNodePtr.
+ */
+ std::string langProperty(XmlNodeConstPtr node,
+ const char *const name,
+ const std::string &def) A_WARN_UNUSED;
+
+ /**
+ * Gets a boolean property from an XmlNodePtr.
+ */
+ bool getBoolProperty(XmlNodeConstPtr node,
+ const char *const name,
+ const bool def) A_WARN_UNUSED;
+
+ /**
+ * Finds the first child node with the given name
+ */
+ XmlNodeConstPtr findFirstChildByName(XmlNodeConstPtrConst parent,
+ const char *const name)
+ A_WARN_UNUSED;
+
+ void initXML();
+
+ void cleanupXML();
+} // namespace XML
+
+#define for_each_xml_child_node(var, parent) \
+ for (const tinyxml2::XMLElement *var = parent->FirstChildElement(); \
+ var != nullptr; \
+ var = var->NextSiblingElement())
+
+#endif // ENABLE_TINYXML2
+#endif // UTILS_XML_TINYXML2_H
diff --git a/src/utils/xml/tinyxml2.inc b/src/utils/xml/tinyxml2.inc
new file mode 100644
index 000000000..a0554e5b9
--- /dev/null
+++ b/src/utils/xml/tinyxml2.inc
@@ -0,0 +1,70 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2011-2017 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_XML_TINYXML2_INC
+#define UTILS_XML_TINYXML2_INC
+
+#ifdef ENABLE_TINYXML2
+
+#include <tinyxml2.h>
+
+TINYXML2_INCLUDED
+
+#define XML_ELEMENT_NODE tinyxml2::XMLElement
+
+#define XmlNodePtr const tinyxml2::XMLElement*
+#define XmlNodePtrConst const tinyxml2::XMLElement *const
+#define XmlNodeConstPtr const tinyxml2::XMLElement*
+#define XmlNodeConstPtrConst const tinyxml2::XMLElement *const
+#define xmlNameEqual(node, str) !strcmp((node)->Value(), str)
+#define XmlTextWriterPtr tinyxml2::XMLPrinter*
+// +++ need replace xmlTypeEqual to isXmlElementNode
+#define xmlTypeEqual(node, typ) true
+#define XmlHasProp(node, name) ((node)->Attribute(name) != nullptr)
+
+#define XmlNodeGetContent(node) (node)->GetText()
+#define XmlHaveChildContent(node) ((node)->GetText() != nullptr)
+#define XmlChildContent(node) ((node)->GetText())
+
+#define XmlFree(ptr)
+#define XmlNodeDefault nullptr
+#define XmlChar const char
+#define XmlConstChar const char
+
+#define XmlTextWriterStartElement(writer, name) (writer)->OpenElement(name)
+#define XmlTextWriterStartRootElement(writer, name) (writer)->OpenElement(name)
+#define XmlTextWriterEndElement(writer) (writer)->CloseElement()
+#define XmlTextWriterWriteAttribute(writer, name, content) \
+ (writer)->PushAttribute(name, content)
+#define XmlNewTextWriterFilename(name, flags) new tinyxml2::XMLPrinter
+#define XmlSaveTextWriterFilename(writer, name) \
+ { \
+ FILE *const writer##File = fopen(name, "wb"); \
+ fwrite((writer)->CStr(), 1, (writer)->CStrSize() - 1, writer##File); \
+ fclose(writer##File); \
+ }
+#define XmlTextWriterSetIndent(writer, flags)
+#define XmlTextWriterStartDocument(writer, p1, p2, p3) \
+ (writer)->PushDeclaration("xml version=\"1.0\" encoding=\"utf-8\"")
+#define XmlTextWriterEndDocument(writer) (writer)->CloseElement()
+#define XmlFreeTextWriter(writer) delete writer
+
+#endif // ENABLE_TINYXML2
+#endif // UTILS_XML_TINYXML2_INC
diff --git a/src/utils/xml_unittest.cc b/src/utils/xml_unittest.cc
index fc7818085..69940b0af 100644
--- a/src/utils/xml_unittest.cc
+++ b/src/utils/xml_unittest.cc
@@ -152,7 +152,7 @@ TEST_CASE("xml doc")
UseVirtFs_true,
SkipError_false);
- const XmlNodePtr rootNode = doc.rootNode();
+ XmlNodeConstPtr rootNode = doc.rootNode();
REQUIRE(XML::getProperty(rootNode, "image", "") == "window.png");
}
@@ -162,7 +162,7 @@ TEST_CASE("xml doc")
UseVirtFs_true,
SkipError_false);
- const XmlNodePtr rootNode = doc.rootNode();
+ XmlNodeConstPtr rootNode = doc.rootNode();
// REQUIRE(XmlHaveChildContent(rootNode) == true);
XmlNodePtr node = XmlNodeDefault;
for_each_xml_child_node(widgetNode, rootNode)
@@ -202,7 +202,7 @@ TEST_CASE("xml doc")
UseVirtFs_true,
SkipError_false);
- const XmlNodePtr rootNode = doc.rootNode();
+ XmlNodeConstPtr rootNode = doc.rootNode();
XmlNodePtr node = XML::findFirstChildByName(rootNode, "widget");
REQUIRE(node != nullptr);
REQUIRE(xmlTypeEqual(node, XML_ELEMENT_NODE) == true);
@@ -234,7 +234,7 @@ TEST_CASE("xml doc")
"<root><data option1=\"false\" option2=\"true\" "
"option3=\"10.5\"/></root>";
XML::Document doc(xml, strlen(xml));
- const XmlNodePtr rootNode = doc.rootNode();
+ XmlNodeConstPtr rootNode = doc.rootNode();
REQUIRE(XmlHaveChildContent(rootNode) == false);
XmlNodePtr node = XML::findFirstChildByName(rootNode, "data");
REQUIRE(node != nullptr);
@@ -257,7 +257,7 @@ TEST_CASE("xml doc")
"<data option1=\"false\" option2=\"true\" "
"option3=\"10.5\"/><!-- comment --></root>";
XML::Document doc(xml.c_str(), xml.size());
- const XmlNodePtr rootNode = doc.rootNode();
+ XmlNodeConstPtr rootNode = doc.rootNode();
// REQUIRE(XmlHaveChildContent(rootNode) == true);
XmlNodePtr node = XML::findFirstChildByName(rootNode, "data");
REQUIRE(node != nullptr);
@@ -292,13 +292,15 @@ TEST_CASE("xml doc")
FILE *const testFile = fopen(tempXmlName, "w");
REQUIRE(testFile);
fclose(testFile);
- const XmlTextWriterPtr writer = XmlNewTextWriterFilename(
+ XmlTextWriterPtr writer = XmlNewTextWriterFilename(
tempXmlName,
0);
XmlTextWriterSetIndent(writer, 1);
XmlTextWriterStartDocument(writer, nullptr, nullptr, nullptr);
- XmlTextWriterStartElement(writer, "root");
+ XmlTextWriterStartRootElement(writer, "root");
XmlTextWriterEndDocument(writer);
+ XmlSaveTextWriterFilename(writer, tempXmlName);
+ logger->log("xml test: %s", writer->CStr());
XmlFreeTextWriter(writer);
// load
@@ -326,12 +328,12 @@ TEST_CASE("xml doc")
FILE *const testFile = fopen(tempXmlName, "w");
REQUIRE(testFile);
fclose(testFile);
- const XmlTextWriterPtr writer = XmlNewTextWriterFilename(
+ XmlTextWriterPtr writer = XmlNewTextWriterFilename(
tempXmlName,
0);
XmlTextWriterSetIndent(writer, 1);
XmlTextWriterStartDocument(writer, nullptr, nullptr, nullptr);
- XmlTextWriterStartElement(writer, "root");
+ XmlTextWriterStartRootElement(writer, "root");
XmlTextWriterStartElement(writer, "option");
XmlTextWriterWriteAttribute(writer, "name", "the name");
@@ -339,6 +341,7 @@ TEST_CASE("xml doc")
XmlTextWriterEndElement(writer);
XmlTextWriterEndDocument(writer);
+ XmlSaveTextWriterFilename(writer, tempXmlName);
XmlFreeTextWriter(writer);
// load
@@ -366,6 +369,7 @@ TEST_CASE("xml doc")
// clean again
::remove(tempXmlName);
}
+
delete2(theme);
delete2(client);
VirtFs::unmountDirSilent("data");
diff --git a/src/utils/xmlutils.cpp b/src/utils/xmlutils.cpp
index 450a392d4..a6648c212 100644
--- a/src/utils/xmlutils.cpp
+++ b/src/utils/xmlutils.cpp
@@ -35,7 +35,7 @@ void readXmlIntVector(const std::string &fileName,
const SkipError skipError)
{
XML::Document doc(fileName, UseVirtFs_true, skipError);
- const XmlNodePtrConst rootNode = doc.rootNode();
+ XmlNodeConstPtrConst rootNode = doc.rootNode();
if (!rootNode || !xmlNameEqual(rootNode, rootName.c_str()))
{
@@ -86,7 +86,7 @@ void readXmlStringMap(const std::string &fileName,
const SkipError skipError)
{
XML::Document doc(fileName, UseVirtFs_true, skipError);
- const XmlNodePtrConst rootNode = doc.rootNode();
+ XmlNodeConstPtrConst rootNode = doc.rootNode();
if (!rootNode || !xmlNameEqual(rootNode, rootName.c_str()))
{
@@ -140,7 +140,7 @@ void readXmlIntMap(const std::string &fileName,
const SkipError skipError)
{
XML::Document doc(fileName, UseVirtFs_true, skipError);
- const XmlNodePtrConst rootNode = doc.rootNode();
+ XmlNodeConstPtrConst rootNode = doc.rootNode();
if (!rootNode || !xmlNameEqual(rootNode, rootName.c_str()))
{