]> git.mxchange.org Git - simgear.git/blob - simgear/xml/easyxml.cxx
Merge branch 'fredb/effect-stuff'
[simgear.git] / simgear / xml / easyxml.cxx
1 /**
2  * \file easyxml.cxx - implementation of EasyXML interfaces.
3  * Written by David Megginson, 2000-2001
4  * This file is in the Public Domain, and comes with NO WARRANTY of any kind.
5  */
6
7 #include <simgear/compiler.h>
8
9 #include <string.h>             // strcmp()
10
11 #include "easyxml.hxx"
12 #include "xmlparse.h"
13
14 #include <fstream>
15 #include <iostream>
16
17 using std::ifstream;
18
19
20 \f
21 ////////////////////////////////////////////////////////////////////////
22 // Implementation of XMLAttributes.
23 ////////////////////////////////////////////////////////////////////////
24
25 XMLAttributes::XMLAttributes ()
26 {
27 }
28
29 XMLAttributes::~XMLAttributes ()
30 {
31 }
32
33 int
34 XMLAttributes::findAttribute (const char * name) const
35 {
36   int s = size();
37   for (int i = 0; i < s; i++) {
38     if (strcmp(name, getName(i)) == 0)
39       return i;
40   }
41   return -1;
42 }
43
44 bool
45 XMLAttributes::hasAttribute (const char * name) const
46 {
47   return (findAttribute(name) != -1);
48 }
49
50 const char *
51 XMLAttributes::getValue (const char * name) const
52 {
53   int pos = findAttribute(name);
54   if (pos >= 0)
55     return getValue(pos);
56   else
57     return 0;
58 }
59
60 \f
61 ////////////////////////////////////////////////////////////////////////
62 // Implementation of XMLAttributesDefault.
63 ////////////////////////////////////////////////////////////////////////
64
65 XMLAttributesDefault::XMLAttributesDefault ()
66 {
67 }
68
69 XMLAttributesDefault::XMLAttributesDefault (const XMLAttributes &atts)
70 {
71   int s = atts.size();
72   for (int i = 0; i < s; i++)
73     addAttribute(atts.getName(i), atts.getValue(i));
74 }
75
76 XMLAttributesDefault::~XMLAttributesDefault ()
77 {
78 }
79
80 int
81 XMLAttributesDefault::size () const
82 {
83   return _atts.size() / 2;
84 }
85
86 const char *
87 XMLAttributesDefault::getName (int i) const
88 {
89   return _atts[i*2].c_str();
90 }
91
92 const char *
93 XMLAttributesDefault::getValue (int i) const
94 {
95   return _atts[i*2+1].c_str();
96 }
97
98 void
99 XMLAttributesDefault::addAttribute (const char * name, const char * value)
100 {
101   _atts.push_back(name);
102   _atts.push_back(value);
103 }
104
105 void
106 XMLAttributesDefault::setName (int i, const char * name)
107 {
108   _atts[i*2] = name;
109 }
110
111 void
112 XMLAttributesDefault::setValue (int i, const char * name)
113 {
114   _atts[i*2+1] = name;
115 }
116
117 void
118 XMLAttributesDefault::setValue (const char * name, const char * value)
119 {
120   int pos = findAttribute(name);
121   if (pos >= 0) {
122     setName(pos, name);
123     setValue(pos, value);
124   } else {
125     addAttribute(name, value);
126   }
127 }
128
129
130 \f
131 ////////////////////////////////////////////////////////////////////////
132 // Attribute list wrapper for Expat.
133 ////////////////////////////////////////////////////////////////////////
134
135 class ExpatAtts : public XMLAttributes
136 {
137 public:
138   ExpatAtts (const char ** atts) : _atts(atts) {}
139   
140   virtual int size () const;
141   virtual const char * getName (int i) const;
142   virtual const char * getValue (int i) const;
143   
144 private:
145   const char ** _atts;
146 };
147
148 int
149 ExpatAtts::size () const
150 {
151   int s = 0;
152   for (int i = 0; _atts[i] != 0; i += 2)
153     s++;
154   return s;
155 }
156
157 const char *
158 ExpatAtts::getName (int i) const
159 {
160   return _atts[i*2];
161 }
162
163 const char *
164 ExpatAtts::getValue (int i) const
165 {
166   return _atts[i*2+1];
167 }
168
169
170 \f
171 ////////////////////////////////////////////////////////////////////////
172 // Static callback functions for Expat.
173 ////////////////////////////////////////////////////////////////////////
174
175 #define VISITOR (*((XMLVisitor *)userData))
176
177 static void
178 start_element (void * userData, const char * name, const char ** atts)
179 {
180   VISITOR.startElement(name, ExpatAtts(atts));
181 }
182
183 static void
184 end_element (void * userData, const char * name)
185 {
186   VISITOR.endElement(name);
187 }
188
189 static void
190 character_data (void * userData, const char * s, int len)
191 {
192   VISITOR.data(s, len);
193 }
194
195 static void
196 processing_instruction (void * userData,
197                         const char * target,
198                         const char * data)
199 {
200   VISITOR.pi(target, data);
201 }
202
203 #undef VISITOR
204
205
206 \f
207 ////////////////////////////////////////////////////////////////////////
208 // Implementation of XMLReader.
209 ////////////////////////////////////////////////////////////////////////
210
211 void
212 readXML (istream &input, XMLVisitor &visitor, const string &path)
213 {
214   XML_Parser parser = XML_ParserCreate(0);
215   XML_SetUserData(parser, &visitor);
216   XML_SetElementHandler(parser, start_element, end_element);
217   XML_SetCharacterDataHandler(parser, character_data);
218   XML_SetProcessingInstructionHandler(parser, processing_instruction);
219
220   visitor.startXML();
221
222   char buf[16384];
223   while (!input.eof()) {
224
225                                 // FIXME: get proper error string from system
226     if (!input.good()) {
227       sg_io_exception ex ("Problem reading file",
228                             sg_location(path,
229                                         XML_GetCurrentLineNumber(parser),
230                                         XML_GetCurrentColumnNumber(parser)),
231                             "SimGear XML Parser");
232       XML_ParserFree(parser);
233       throw ex;
234     }
235
236     input.read(buf,16384);
237     if (!XML_Parse(parser, buf, input.gcount(), false)) {
238       sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)),
239                             sg_location(path,
240                                         XML_GetCurrentLineNumber(parser),
241                                         XML_GetCurrentColumnNumber(parser)),
242                             "SimGear XML Parser");
243       XML_ParserFree(parser);
244       throw ex;
245     }
246
247   }
248
249                                 // Verify end of document.
250   if (!XML_Parse(parser, buf, 0, true)) {
251     sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)),
252                           sg_location(path,
253                                       XML_GetCurrentLineNumber(parser),
254                                       XML_GetCurrentColumnNumber(parser)),
255                           "SimGear XML Parser");
256     XML_ParserFree(parser);
257     throw ex;
258   }
259
260   XML_ParserFree(parser);
261   visitor.endXML();
262 }
263
264 void
265 readXML (const string &path, XMLVisitor &visitor)
266 {
267   ifstream input(path.c_str());
268   if (input.good()) {
269     try {
270       readXML(input, visitor, path);
271     } catch (sg_io_exception &) {
272       input.close();
273       throw;
274     } catch (sg_throwable &) {
275       input.close();
276       throw;
277     }
278   } else {
279     throw sg_io_exception("Failed to open file", sg_location(path),
280                           "SimGear XML Parser");
281   }
282   input.close();
283 }
284
285 void
286 readXML (const char *buf, const int size, XMLVisitor &visitor)
287 {
288   XML_Parser parser = XML_ParserCreate(0);
289   XML_SetUserData(parser, &visitor);
290   XML_SetElementHandler(parser, start_element, end_element);
291   XML_SetCharacterDataHandler(parser, character_data);
292   XML_SetProcessingInstructionHandler(parser, processing_instruction);
293
294   visitor.startXML();
295
296   if (!XML_Parse(parser, buf, size, false)) {
297       sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)),
298                             sg_location("In-memory XML buffer",
299                                         XML_GetCurrentLineNumber(parser),
300                                         XML_GetCurrentColumnNumber(parser)),
301                             "SimGear XML Parser");
302       XML_ParserFree(parser);
303       throw ex;
304   }
305
306   XML_ParserFree(parser);
307   visitor.endXML();
308 }
309
310 // end of easyxml.cxx