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