Fix INT_MAX definition on some newer systems.
[Tsunagari.git] / src / xml.cpp
blob0cdd3cd426c3e37363d06dd37306e0c450d0e27b
1 /***************************************
2 ** Tsunagari Tile Engine **
3 ** xml.cpp **
4 ** Copyright 2011-2013 PariahSoft LLC **
5 ***************************************/
7 // **********
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // **********
27 #include <stdlib.h>
28 #include <string.h>
30 #include "log.h"
31 #include "string.h"
32 #include "xml.h"
34 #ifdef _WIN32
35 #include "os-windows.h"
36 #endif
38 XMLNode::XMLNode()
42 XMLNode::XMLNode(XMLDoc* doc, xmlNode* node)
43 : doc(doc), node(node)
47 XMLNode XMLNode::childrenNode() const
49 return XMLNode(doc, node->xmlChildrenNode);
52 XMLNode XMLNode::next() const
54 return XMLNode(doc, node->next);
57 bool XMLNode::is(const char* name) const
59 return !xmlStrncmp(node->name, BAD_CAST(name), (int)strlen(name)+1);
62 std::string XMLNode::content() const
64 xmlChar* content = xmlNodeGetContent(node);
65 std::string s = content ? (const char*)content : "";
66 xmlFree(content);
67 return s;
70 bool XMLNode::intContent(int* i) const
72 std::string s = content();
73 if (!isInteger(s)) {
74 Log::err(doc->path(), "expected integer");
75 return false;
77 *i = atoi(s.c_str());
78 return true;
81 bool XMLNode::doubleContent(double *d) const
83 std::string s = content();
84 if (!isDecimal(s)) {
85 Log::err(doc->path(), "expected decimal");
86 return false;
88 *d = atof(s.c_str());
89 return true;
92 bool XMLNode::hasAttr(const std::string& name) const
94 return xmlHasProp(node, BAD_CAST(name.c_str()));
97 std::string XMLNode::attr(const std::string& name) const
99 xmlChar* content = xmlGetProp(node, BAD_CAST(name.c_str()));
100 std::string s = content ? (const char*)content : "";
101 xmlFree(content);
102 return s;
105 bool XMLNode::intAttr(const std::string& name, int* i) const
107 std::string s = attr(name);
108 if (!isInteger(s)) {
109 Log::err(doc->path(), "expected integer");
110 return false;
112 *i = atoi(s.c_str());
113 return true;
116 bool XMLNode::doubleAttr(const std::string& name, double* d) const
118 std::string s = attr(name);
119 if (!isDecimal(s)) {
120 Log::err(doc->path(), "expected decimal");
121 return false;
123 *d = atof(s.c_str());
124 return true;
127 XMLNode::operator bool() const
129 return node != NULL;
133 static void xmlErrorCb(void* pstrFilename, const char* msg, ...)
136 const std::string* filename = (const std::string*)pstrFilename;
137 char buf[512];
138 va_list ap;
140 va_start(ap, msg);
141 snprintf(buf, sizeof(buf)-1, msg, va_arg(ap, char*));
142 Log::err(*filename, buf);
143 va_end(ap);
146 XMLDoc::XMLDoc()
150 bool XMLDoc::init(const std::string& path,
151 const std::string& data,
152 xmlDtd* dtd)
154 this->path_ = path;
156 xmlParserCtxt* pc = xmlNewParserCtxt();
157 pc->vctxt.userData = (void*)&path;
158 pc->vctxt.error = xmlErrorCb;
160 // Parse the XML. Hand over our error callback fn.
161 doc.reset(xmlCtxtReadMemory(pc, data.c_str(),
162 (int)data.size(), NULL, NULL,
163 XML_PARSE_NOBLANKS | XML_PARSE_NONET), xmlFreeDoc);
164 xmlFreeParserCtxt(pc);
165 if (!doc) {
166 Log::err(path, "could not parse file");
167 return false;
170 // Assert the document is sane.
171 xmlValidCtxt* vc = xmlNewValidCtxt();
172 int valid = xmlValidateDtd(vc, doc.get(), dtd);
173 xmlFreeValidCtxt(vc);
175 if (!valid) {
176 doc.reset();
177 Log::err(path, "XML document does not follow DTD");
178 return false;
181 return true;
184 XMLNode XMLDoc::root()
186 return XMLNode(this, xmlDocGetRootElement(doc.get()));
189 xmlNode* XMLDoc::temporaryGetRoot() const
191 return xmlDocGetRootElement(doc.get());
194 const std::string& XMLDoc::path() const
196 return path_;
199 XMLDoc::operator bool() const
201 return doc.get();
204 bool XMLDoc::unique() const
206 return doc.unique();
209 long XMLDoc::use_count() const
211 return doc.use_count();