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