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