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