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