]> git.mxchange.org Git - simgear.git/blob - simgear/xml/easyxml.cxx
2331fc375aea9d49ade461e689a2d8942b5614d5
[simgear.git] / simgear / xml / easyxml.cxx
1 // easyxml.cxx - implementation of EasyXML interfaces.
2
3 #include "easyxml.hxx"
4 #include "xmlparse.h"
5
6 \f
7 ////////////////////////////////////////////////////////////////////////
8 // Implementation of XMLAttributes.
9 ////////////////////////////////////////////////////////////////////////
10
11 XMLAttributes::XMLAttributes ()
12 {
13 }
14
15 XMLAttributes::~XMLAttributes ()
16 {
17 }
18
19 int
20 XMLAttributes::findAttribute (const char * name) const
21 {
22   int s = size();
23   for (int i = 0; i < s; i++)
24     if (strcmp(name, getName(i)) == 0)
25       return i;
26   return -1;
27 }
28
29 bool
30 XMLAttributes::hasAttribute (const char * name) const
31 {
32   return (findAttribute(name) != -1);
33 }
34
35 const char *
36 XMLAttributes::getValue (const char * name) const
37 {
38   int pos = findAttribute(name);
39   if (pos >= 0)
40     return getValue(pos);
41   else
42     return getValue(0);
43 }
44
45 \f
46 ////////////////////////////////////////////////////////////////////////
47 // Implementation of XMLAttributesDefault.
48 ////////////////////////////////////////////////////////////////////////
49
50 XMLAttributesDefault::XMLAttributesDefault ()
51 {
52 }
53
54 XMLAttributesDefault::XMLAttributesDefault (const XMLAttributes &atts)
55 {
56   int s = atts.size();
57   for (int i = 0; i < s; i++)
58     addAttribute(atts.getName(i), atts.getValue(i));
59 }
60
61 XMLAttributesDefault::~XMLAttributesDefault ()
62 {
63 }
64
65 int
66 XMLAttributesDefault::size () const
67 {
68   return _atts.size() / 2;
69 }
70
71 const char *
72 XMLAttributesDefault::getName (int i) const
73 {
74   return _atts[i*2].c_str();
75 }
76
77 const char *
78 XMLAttributesDefault::getValue (int i) const
79 {
80   return _atts[i*2+1].c_str();
81 }
82
83 void
84 XMLAttributesDefault::addAttribute (const char * name, const char * value)
85 {
86   _atts.push_back(name);
87   _atts.push_back(value);
88 }
89
90 void
91 XMLAttributesDefault::setName (int i, const char * name)
92 {
93   _atts[i*2] = name;
94 }
95
96 void
97 XMLAttributesDefault::setValue (int i, const char * name)
98 {
99   _atts[i*2+1] = name;
100 }
101
102 void
103 XMLAttributesDefault::setValue (const char * name, const char * value)
104 {
105   int pos = findAttribute(name);
106   if (pos >= 0) {
107     setName(pos, name);
108     setValue(pos, value);
109   } else {
110     addAttribute(name, value);
111   }
112 }
113
114
115 \f
116 ////////////////////////////////////////////////////////////////////////
117 // Attribute list wrapper for Expat.
118 ////////////////////////////////////////////////////////////////////////
119
120 class ExpatAtts : public XMLAttributes
121 {
122 public:
123   ExpatAtts (const char ** atts) : _atts(atts) {}
124   
125   int size () const;
126   const char * getName (int i) const;
127   const char * getValue (int i) const;
128   
129 private:
130   const char ** _atts;
131 };
132
133 int
134 ExpatAtts::size () const
135 {
136   int s = 0;
137   for (int i = 0; _atts[i] != 0; i += 2)
138     s++;
139   return s;
140 }
141
142 const char *
143 ExpatAtts::getName (int i) const
144 {
145   return _atts[i*2];
146 }
147
148 const char *
149 ExpatAtts::getValue (int i) const
150 {
151   return _atts[i*2+1];
152 }
153
154
155 \f
156 ////////////////////////////////////////////////////////////////////////
157 // Static callback functions for Expat.
158 ////////////////////////////////////////////////////////////////////////
159
160 #define VISITOR (*((XMLVisitor*)userData))
161
162 static void
163 start_element (void * userData, const char * name, const char ** atts)
164 {
165   ExpatAtts attributes(atts);
166   VISITOR.startElement(name, attributes);
167 }
168
169 static void
170 end_element (void * userData, const char * name)
171 {
172   VISITOR.endElement(name);
173 }
174
175 static void
176 character_data (void * userData, const char * s, int len)
177 {
178   VISITOR.data(s, len);
179 }
180
181 static void
182 processing_instruction (void * userData,
183                         const char * target,
184                         const char * data)
185 {
186   VISITOR.pi(target, data);
187 }
188
189 #undef VISITOR
190
191
192 \f
193 ////////////////////////////////////////////////////////////////////////
194 // Implementation of XMLReader.
195 ////////////////////////////////////////////////////////////////////////
196
197 bool
198 readXML (istream &input, XMLVisitor &visitor)
199 {
200   bool retval = true;
201
202   XML_Parser parser = XML_ParserCreate(0);
203   XML_SetUserData(parser, &visitor);
204   XML_SetElementHandler(parser, start_element, end_element);
205   XML_SetCharacterDataHandler(parser, character_data);
206   XML_SetProcessingInstructionHandler(parser, processing_instruction);
207
208   visitor.startXML();
209
210   char buf[16384];
211   while (!input.eof()) {
212
213     input.read(buf,16384);
214                                 // TODO: deal with bad stream.
215     if (!XML_Parse(parser, buf, input.gcount(), false)) {
216       visitor.error(XML_ErrorString(XML_GetErrorCode(parser)),
217                     XML_GetCurrentColumnNumber(parser),
218                     XML_GetCurrentLineNumber(parser));
219       retval = false;
220     }
221   }
222
223   if (retval)
224     visitor.endXML();
225
226   XML_ParserFree(parser);
227
228   return retval;
229 }
230
231 // end of easyxml.cxx