]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/xml/xmlparser.h
initial
[xonotic/netradiant.git] / libs / xml / xmlparser.h
1 /*
2 Copyright (C) 2001-2006, William Joseph.
3 All Rights Reserved.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #if !defined(INCLUDED_XML_XMLPARSER_H)
23 #define INCLUDED_XML_XMLPARSER_H
24
25 #include <cstdio>
26 #include <string.h>
27 #include "ixml.h"
28 #include "libxml/parser.h"
29 #include "convert.h"
30
31 class TextInputStream;
32
33 class SAXElement : public XMLElement
34 {
35 public:
36   SAXElement(const char* name, const char** atts)
37     : m_name(name), m_atts(atts)
38   {
39   }
40   const char* name() const
41   {
42     return m_name;
43   }
44   const char* attribute(const char* name) const
45   {
46     if(m_atts != 0)
47     {
48       for(const char** att = m_atts; *att != 0; att+=2)
49       {
50         if(strcmp(*att, name) == 0)
51         {
52           return *(++att);
53         }
54       }
55     }
56     return "";
57   }
58   void forEachAttribute(XMLAttrVisitor& visitor) const
59   {
60     if(m_atts != 0)
61     {
62       for(const char** att = m_atts; *att != 0; att+=2)
63       {
64         visitor.visit(*att, *(att+1));
65       }
66     }
67   }
68 private:
69   const char* m_name;
70   const char** m_atts;
71 };
72
73 #include <stdarg.h>
74
75 class FormattedVA
76 {
77 public:
78   const char* m_format;
79   va_list& m_arguments;
80   FormattedVA(const char* format, va_list& m_arguments)
81     : m_format(format), m_arguments(m_arguments)
82   {
83   }
84 };
85
86 class Formatted
87 {
88 public:
89   const char* m_format;
90   va_list m_arguments;
91   Formatted(const char* format, ...)
92     : m_format(format)
93   {
94     va_start(m_arguments, format);
95   }
96   ~Formatted()
97   {
98     va_end(m_arguments);
99   }
100 };
101
102 #ifdef WIN32
103 #if _MSC_VER < 1400 
104 #define vsnprintf std::vsnprintf
105 #endif
106 #endif
107
108 template<typename TextOutputStreamType>
109 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const FormattedVA& formatted)
110 {
111   char buffer[1024];
112   ostream.write(buffer, vsnprintf(buffer, 1023, formatted.m_format, formatted.m_arguments));
113   return ostream;
114 }
115
116 template<typename TextOutputStreamType>
117 inline TextOutputStreamType& ostream_write(TextOutputStreamType& ostream, const Formatted& formatted)
118 {
119   char buffer[1024];
120   ostream.write(buffer, vsnprintf(buffer, 1023, formatted.m_format, formatted.m_arguments));
121   return ostream;
122 }
123
124 class XMLSAXImporter
125 {
126   XMLImporter& m_importer;
127   xmlSAXHandler m_sax;
128
129   static void startElement(void *user_data, const xmlChar *name, const xmlChar **atts)
130   {
131     SAXElement element(reinterpret_cast<const char*>(name), reinterpret_cast<const char**>(atts));
132     reinterpret_cast<XMLSAXImporter*>(user_data)->m_importer.pushElement(element);
133   }
134   static void endElement(void *user_data, const xmlChar *name)
135   {
136     reinterpret_cast<XMLSAXImporter*>(user_data)->m_importer.popElement(reinterpret_cast<const char*>(name));
137   }
138   static void characters(void *user_data, const xmlChar *ch, int len)
139   {
140     reinterpret_cast<XMLSAXImporter*>(user_data)->m_importer
141       << ConvertUTF8ToLocale(StringRange(reinterpret_cast<const char*>(ch), reinterpret_cast<const char*>(ch + len)));
142   }
143
144   static void warning(void *user_data, const char *msg, ...)
145   {
146     va_list args;
147     va_start(args, msg); 
148     globalErrorStream() << "XML WARNING: " << FormattedVA(msg, args);
149     va_end(args);
150   }
151   static void error(void *user_data, const char *msg, ...)
152   {
153     va_list args;
154     va_start(args, msg); 
155     globalErrorStream() << "XML ERROR: " << FormattedVA(msg, args);
156     va_end(args);
157   }
158
159 public:
160   XMLSAXImporter(XMLImporter& importer) : m_importer(importer)
161   {
162       m_sax.internalSubset = 0;
163       m_sax.isStandalone = 0;
164       m_sax.hasInternalSubset = 0;
165       m_sax.hasExternalSubset = 0;
166       m_sax.resolveEntity = 0;
167       m_sax.getEntity = 0;
168       m_sax.entityDecl = 0;
169       m_sax.notationDecl = 0;
170       m_sax.attributeDecl = 0;
171       m_sax.elementDecl = 0;
172       m_sax.unparsedEntityDecl = 0;
173       m_sax.setDocumentLocator = 0;
174       m_sax.startDocument = 0;
175       m_sax.endDocument = 0;
176       m_sax.startElement = startElement;
177       m_sax.endElement = endElement;
178       m_sax.reference = 0;
179       m_sax.characters = characters;
180       m_sax.ignorableWhitespace = 0;
181       m_sax.processingInstruction = 0;
182       m_sax.comment = 0;
183       m_sax.warning = warning;
184       m_sax.error = error;
185       m_sax.fatalError = 0;
186       m_sax.getParameterEntity = 0;
187       m_sax.cdataBlock = 0;
188       m_sax.externalSubset = 0;
189       m_sax.initialized = 1;
190   }
191
192   xmlSAXHandler* callbacks()
193   {
194     return &m_sax;
195   }
196   void* context()
197   {
198     return this;
199   }
200 };
201
202 class XMLStreamParser : public XMLExporter
203 {
204   enum unnamed0 { BUFSIZE = 1024 };
205 public:
206   XMLStreamParser(TextInputStream& istream)
207     : m_istream(istream)
208   {
209   }
210   virtual void exportXML(XMLImporter& importer)
211   {
212     bool wellFormed = false;
213
214     char chars[BUFSIZE];
215     std::size_t res = m_istream.read(chars, 4);
216     if (res > 0)
217     {
218       XMLSAXImporter sax(importer);
219
220       xmlParserCtxtPtr ctxt = xmlCreatePushParserCtxt(sax.callbacks(), sax.context(), chars, static_cast<int>(res), 0);
221       ctxt->replaceEntities = 1;
222
223       while ((res = m_istream.read(chars, BUFSIZE)) > 0)
224       {
225         xmlParseChunk(ctxt, chars, static_cast<int>(res), 0);
226       }
227       xmlParseChunk(ctxt, chars, 0, 1);
228
229       wellFormed = (ctxt->wellFormed == 1);
230
231       xmlFreeParserCtxt(ctxt);
232     }
233
234     //return wellFormed;
235   }
236 private:
237   TextInputStream& m_istream;
238 };
239
240
241
242 #endif