-revert janderwalds change until because it breaks the gcc 4.x build
[reactos.git] / reactos / base / applications / ibrowser / utility / xs-native.cpp
1
2 //
3 // XML storage classes
4 //
5 // xs-native.cpp
6 //
7 // Copyright (c) 2006 Martin Fuchs <martin-fuchs@gmx.net>
8 //
9
10
11 /*
12
13 All rights reserved.
14
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions are met:
17
18 * Redistributions of source code must retain the above copyright
19 notice, this list of conditions and the following disclaimer.
20 * Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in
22 the documentation and/or other materials provided with the
23 distribution.
24
25 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 POSSIBILITY OF SUCH DAMAGE.
36
37 */
38
39 #ifndef XS_NO_COMMENT
40 #define XS_NO_COMMENT // no #pragma comment(lib, ...) statements in .lib files to enable static linking
41 #endif
42
43 //#include "xmlstorage.h"
44 #include <precomp.h>
45
46
47 #if !defined(XS_USE_EXPAT) && !defined(XS_USE_XERCES)
48
49 namespace XMLStorage {
50
51
52 XMLReaderBase::~XMLReaderBase()
53 {
54 }
55
56 /// read XML stream into XML tree below _pos
57 void XMLReaderBase::read()
58 {
59 if (!parse()) {
60 XMLError error;
61
62 error._message = "XML parsing error";
63 //error._line = ;
64 //error._column = ;
65
66 _errors.push_back(error);
67 }
68
69 finish_read();
70 }
71
72
73 struct Buffer
74 {
75 Buffer()
76 {
77 _buffer = (char*) malloc(BUFFER_LEN);
78 _len = BUFFER_LEN;
79
80 reset();
81 }
82
83 ~Buffer()
84 {
85 free(_buffer);
86 }
87
88 void reset()
89 {
90 _wptr = _buffer;
91 _buffer_str.erase();
92 }
93
94 void append(char c)
95 {
96 size_t wpos = _wptr-_buffer;
97
98 if (wpos >= _len) {
99 _len <<= 1;
100 _buffer = (char*) realloc(_buffer, _len);
101 _wptr = _buffer + wpos;
102 }
103
104 *_wptr++ = c;
105 }
106
107 const std::string& str(bool utf8) // returns UTF-8 encoded buffer content
108 {
109 if (utf8)
110 _buffer_str.assign(_buffer, _wptr-_buffer);
111 else
112 _buffer_str = get_utf8(_buffer, _wptr-_buffer);
113
114 return _buffer_str;
115 }
116
117 size_t len() const
118 {
119 return _wptr - _buffer;
120 }
121
122 bool has_CDEnd() const
123 {
124 //if (_wptr-_buffer < 3)
125 // return false;
126
127 return !strncmp(_wptr-3, "]]>", 3);
128 }
129
130 XS_String get_tag() const
131 {
132 const char* p = _buffer_str.c_str();
133
134 if (*p == '<')
135 ++p;
136
137 if (*p == '/')
138 ++p;
139
140 const char* q = p;
141
142 if (*q == '?')
143 ++q;
144
145 while(isxmlsym(*q))
146 ++q;
147
148 #ifdef XS_STRING_UTF8
149 return XS_String(p, q-p);
150 #else
151 XS_String tag;
152 assign_utf8(tag, p, q-p);
153 return tag;
154 #endif
155 }
156
157 /// read attributes and values
158 void get_attributes(XMLNode::AttributeMap& attributes) const
159 {
160 const char* p = _buffer_str.c_str();
161
162 // find end of tag name
163 if (*p == '<')
164 ++p;
165
166 if (*p == '/')
167 ++p;
168 else if (*p == '?')
169 ++p;
170
171 while(isxmlsym(*p))
172 ++p;
173
174 // read attributes from buffer
175 while(*p && *p!='>' && *p!='/') {
176 while(isspace((unsigned char)*p))
177 ++p;
178
179 const char* attr_name = p;
180
181 while(isxmlsym(*p))
182 ++p;
183
184 if (*p != '=')
185 break; //@TODO error handling
186
187 size_t attr_len = p - attr_name;
188
189 if (*++p!='"' && *p!='\'')
190 break; //@TODO error handling
191
192 char delim = *p;
193 const char* value = ++p;
194
195 while(*p && *p!=delim)
196 ++p;
197
198 size_t value_len = p - value;
199
200 if (*p)
201 ++p; // '"'
202
203 #ifdef XS_STRING_UTF8
204 XS_String name_str(attr_name, attr_len);
205 XS_String value_str(value, value_len);
206 #else
207 XS_String name_str, value_str;
208 assign_utf8(name_str, attr_name, attr_len);
209 assign_utf8(value_str, value, value_len);
210 #endif
211
212 attributes[name_str] = DecodeXMLString(value_str);
213 }
214 }
215
216 protected:
217 char* _buffer;
218 char* _wptr;
219 size_t _len;
220 std::string _buffer_str; // UF-8 encoded
221 };
222
223 bool XMLReaderBase::parse()
224 {
225 Buffer buffer;
226 int c = get();
227 bool in_comment = false;
228
229 while(c != EOF) {
230 if (in_comment || c=='<') {
231 buffer.append(c);
232
233 // read start or end tag
234 for(;;) {
235 c = get();
236
237 if (c == EOF)
238 break;
239
240 buffer.append(c);
241
242 if (c == '>')
243 break;
244 }
245
246 const std::string& b = buffer.str(_utf8);
247 const char* str = b.c_str();
248
249 if (in_comment || !strncmp(str+1, "!--", 3)) {
250 // XML comment
251 DefaultHandler(b);
252
253 if (strcmp(str+b.length()-3, "-->"))
254 in_comment = true;
255 else
256 in_comment = false;
257
258 c = get();
259 } else if (str[1] == '/') {
260 // end tag
261
262 /*@TODO error handling
263 const XS_String& tag = buffer.get_tag();
264
265 if (tag != last_opened_tag) {
266 ERROR
267 }
268 */
269
270 EndElementHandler();
271
272 c = get();
273 } else if (str[1] == '?') {
274 // XML declaration
275 const XS_String& tag = buffer.get_tag();
276
277 if (tag == "?xml") {
278 XMLNode::AttributeMap attributes;
279 buffer.get_attributes(attributes);
280
281 const std::string& version = attributes.get("version");
282 const std::string& encoding = attributes.get("encoding");
283
284 int standalone;
285 XMLNode::AttributeMap::const_iterator found = // const_cast for ISO C++ compatibility error of GCC
286 const_cast<const XMLNode::AttributeMap&>(attributes).find("standalone");
287 if (found != attributes.end())
288 standalone = !XS_icmp(found->second.c_str(), XS_TEXT("yes"));
289 else
290 standalone = -1;
291
292 XmlDeclHandler(version.empty()?NULL:version.c_str(), encoding.empty()?NULL:encoding.c_str(), standalone);
293
294 if (!encoding.empty() && !_stricmp(encoding.c_str(), "utf-8"))
295 _utf8 = true;
296
297 c = eat_endl();
298 } else if (tag == "?xml-stylesheet") {
299 XMLNode::AttributeMap attributes;
300 buffer.get_attributes(attributes);
301
302 StyleSheet stylesheet(attributes.get("href"), attributes.get("type"), !XS_icmp(attributes.get("alternate"), XS_TEXT("yes")));
303 stylesheet._title = attributes.get("title");
304 stylesheet._media = attributes.get("media");
305 stylesheet._charset = attributes.get("charset");
306
307 _format._stylesheets.push_back(stylesheet);
308
309 c = eat_endl();
310 } else {
311 DefaultHandler(b);
312 c = get();
313 }
314 } else if (str[1] == '!') {
315 if (!strncmp(str+2, "DOCTYPE ", 8)) {
316 _format._doctype.parse(str+10);
317
318 c = eat_endl();
319 } else if (!strncmp(str+2, "[CDATA[", 7)) {
320 // parse <![CDATA[ ... ]]> strings
321 while(!buffer.has_CDEnd()) {
322 c = get();
323
324 if (c == EOF)
325 break;
326
327 buffer.append(c);
328 }
329
330 DefaultHandler(buffer.str(_utf8));
331
332 c = get();
333 }
334 } else {
335 // start tag
336 const XS_String& tag = buffer.get_tag();
337
338 if (!tag.empty()) {
339 XMLNode::AttributeMap attributes;
340 buffer.get_attributes(attributes);
341
342 StartElementHandler(tag, attributes);
343
344 if (str[b.length()-2] == '/')
345 EndElementHandler();
346 }
347
348 c = get();
349 }
350 } else {
351 buffer.append(c);
352
353 // read white space
354 for(;;) {
355 // check for the encoding of the first line end
356 if (!_endl_defined)
357 if (c == '\n') {
358 _format._endl = "\n";
359 _endl_defined = true;
360 } else if (c == '\r') {
361 _format._endl = "\r\n";
362 _endl_defined = true;
363 }
364
365 c = get();
366
367 if (c == EOF)
368 break;
369
370 if (c == '<')
371 break;
372
373 buffer.append(c);
374 }
375
376 DefaultHandler(buffer.str(_utf8));
377 }
378
379 buffer.reset();
380 }
381
382 return true;
383 }
384
385 int XMLReaderBase::eat_endl()
386 {
387 int c = get();
388
389 if (c == '\r')
390 c = get();
391
392 if (c == '\n')
393 c = get();
394
395 return c;
396 }
397
398 /// return current parser position as string
399 std::string XMLReaderBase::get_position() const
400 {
401 /*@TODO display parser position in case of errors
402 int line = XML_GetCurrentLineNumber(_parser);
403 int column = XML_GetCurrentColumnNumber(_parser);
404
405 std::ostringstream out;
406 out << "(" << line << ") : [column " << column << "]";
407
408 return out.str();
409 */
410 return "";
411 }
412
413
414 #ifdef XMLNODE_LOCATION
415
416 XMLLocation XMLReaderBase::get_location() const
417 {
418 return XMLLocation(); //@TODO XMLLocation for XS-native
419 }
420
421 std::string XMLLocation::str() const
422 {
423 return ""; //TODO
424 }
425
426 #endif
427
428
429 /// store content, white space and comments
430 void XMLReaderBase::DefaultHandler(const std::string& s)
431 {
432 _content.append(s);
433 }
434
435
436 } // namespace XMLStorage
437
438 #endif // !defined(XS_USE_EXPAT) && !defined(XS_USE_XERCES)