Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifndef XS_NO_COMMENT
00041 #define XS_NO_COMMENT // no #pragma comment(lib, ...) statements in .lib files to enable static linking
00042 #endif
00043
00044 #include "xmlstorage.h"
00045
00046
00047 #if !defined(XS_USE_EXPAT) && !defined(XS_USE_XERCES)
00048
00049 namespace XMLStorage {
00050
00051
00052 XMLReaderBase::~XMLReaderBase()
00053 {
00054 }
00055
00056
00057 void XMLReaderBase::read(bool force_utf8)
00058 {
00059 if (!parse(force_utf8)) {
00060 XMLError error("XML parsing error");
00061
00062
00063
00064 _errors.push_back(error);
00065 }
00066
00067 finish_read();
00068 }
00069
00070
00071
00072
00073 ReadBuffer::ReadBuffer(XMLErrorList& errors, XMLLocation& location)
00074 : _errors(errors),
00075 _location(location)
00076 {
00077 _buffer = (char*) malloc(BUFFER_LEN);
00078 _len = BUFFER_LEN;
00079
00080 reset();
00081 }
00082
00083 ReadBuffer::~ReadBuffer()
00084 {
00085 free(_buffer);
00086 }
00087
00088 void ReadBuffer::reset()
00089 {
00090 _wptr = _buffer;
00091 _buffer_str.erase();
00092 }
00093
00094 bool ReadBuffer::append(int c)
00095 {
00096 size_t wpos = _wptr-_buffer;
00097
00098 if (wpos >= _len) {
00099 size_t new_len = _len << 1;
00100
00101 void* new_ptr = realloc(_buffer, new_len);
00102
00103 if (new_ptr) {
00104 _buffer = (char*)new_ptr;
00105 _wptr = _buffer + wpos;
00106 _len = new_len;
00107 } else
00108 return false;
00109 }
00110
00111 *_wptr++ = static_cast<char>(c);
00112
00113 return true;
00114 }
00115
00116 const std::string& ReadBuffer::str(bool utf8)
00117 {
00118 #if defined(_WIN32) && !defined(XS_STRING_UTF8)
00119 if (utf8)
00120 #endif
00121 _buffer_str.assign(_buffer, _wptr-_buffer);
00122 #if defined(_WIN32) && !defined(XS_STRING_UTF8)
00123 else
00124 _buffer_str = get_utf8(_buffer, _wptr-_buffer);
00125 #endif
00126
00127 return _buffer_str;
00128 }
00129
00130 size_t ReadBuffer::len() const
00131 {
00132 return _wptr - _buffer;
00133 }
00134
00135 bool ReadBuffer::has_CDEnd() const
00136 {
00137
00138
00139
00140 return !strncmp(_wptr-3, CDATA_END, 3);
00141 }
00142
00143 XS_String ReadBuffer::get_tag() const
00144 {
00145 const char* p = _buffer_str.c_str();
00146
00147 if (*p == '<')
00148 ++p;
00149
00150 if (*p == '/')
00151 ++p;
00152
00153 const char* q = p;
00154
00155 if (*q == '?')
00156 ++q;
00157
00158 q = get_xmlsym_end_utf8(q);
00159
00160 #ifdef XS_STRING_UTF8
00161 return XS_String(p, q-p);
00162 #else
00163 return from_utf8(p, q-p);
00164 #endif
00165 }
00166
00167
00168 void ReadBuffer::get_attributes(XMLNode::AttributeMap& attributes) const
00169 {
00170 const char* p = _buffer_str.c_str();
00171
00172
00173 if (*p == '<')
00174 ++p;
00175
00176 if (*p == '/')
00177 ++p;
00178 else if (*p == '?')
00179 ++p;
00180
00181 p = get_xmlsym_end_utf8(p);
00182
00183
00184 while(*p && *p!='>' && *p!='/') {
00185 while(isspace((unsigned char)*p))
00186 ++p;
00187
00188 if (*p=='?' || *p=='>' || *p=='/')
00189 break;
00190
00191 const char* attr_name = p;
00192
00193 p = get_xmlsym_end_utf8(p);
00194
00195 if (*p != '=') {
00196 _errors.push_back(XMLError(_location, "missing attribute assignment"));
00197 break;
00198 }
00199
00200 size_t attr_len = p - attr_name;
00201
00202 if (*++p!='"' && *p!='\'') {
00203 _errors.push_back(XMLError(_location, "missing attribute value quote"));
00204 break;
00205 }
00206
00207 char delim = *p;
00208 const char* value = ++p;
00209
00210 while(*p && *p!=delim)
00211 ++p;
00212
00213 size_t value_len = p - value;
00214
00215 if (*p)
00216 ++p;
00217 else
00218 _errors.push_back(XMLError(_location, "unterminated attribute quote"));
00219
00220 #ifdef XS_STRING_UTF8
00221 XS_String name_str(attr_name, attr_len);
00222 #else
00223 XS_String name_str;
00224 assign_utf8(name_str, attr_name, attr_len);
00225 #endif
00226
00227 attributes[name_str] = DecodeXMLString(std::string(value, value_len));
00228 }
00229 }
00230
00231
00232 ParseContext::ParseContext(XMLReaderBase& reader, bool force_utf8)
00233 : _reader(reader),
00234 _buffer(reader._errors, reader._location),
00235 _utf8(force_utf8)
00236 {
00237 _next = reader.get();
00238 _in_comment = false;
00239
00240
00241 read_bom();
00242 }
00243
00244 void ParseContext::read_bom()
00245 {
00246 if (_next == 0xEF) {
00247 _next = _reader.get();
00248
00249 if (_next == 0xBB) {
00250 _next = _reader.get();
00251
00252 if (_next == 0xBF) {
00253 _utf8 = true;
00254 _reader._format._utf8_bom = true;
00255
00256 _next = _reader.get();
00257 }
00258 }
00259 }
00260 }
00261
00262 bool ParseContext::proceed()
00263 {
00264 if (_next != EOF)
00265 _next = process_next(_next);
00266
00267 return _next != EOF;
00268 }
00269
00270 int ParseContext::process_next(int c)
00271 {
00272 if (_in_comment || c=='<') {
00273 if (!_buffer.empty())
00274 _buffer.reset();
00275
00276 _buffer.append(c);
00277
00278
00279 for(;;) {
00280 c = _reader.get();
00281
00282 if (c == EOF)
00283 break;
00284
00285 _buffer.append(c);
00286
00287 if (c == '>')
00288 break;
00289 }
00290
00291 const std::string& b = _buffer.str(_utf8);
00292 const char* str = b.c_str();
00293
00294 if (_in_comment || !strncmp(str+1, "!--", 3)) {
00295
00296 _reader.DefaultHandler(b);
00297
00298 if (strcmp(str+b.length()-3, "-->"))
00299 _in_comment = true;
00300 else
00301 _in_comment = false;
00302
00303 c = _reader.get();
00304 } else if (str[1] == '/') {
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 _reader.EndElementHandler();
00316
00317 c = _reader.get();
00318 } else if (str[1] == '?') {
00319
00320 const XS_String& tag = _buffer.get_tag();
00321
00322 if (tag == "?xml") {
00323 XMLNode::AttributeMap attributes;
00324 _buffer.get_attributes(attributes);
00325
00326 const std::string& version = attributes.get("version");
00327 const std::string& encoding = attributes.get("encoding");
00328
00329 int standalone;
00330 XMLNode::AttributeMap::const_iterator found =
00331 const_cast<const XMLNode::AttributeMap&>(attributes).find("standalone");
00332 if (found != attributes.end())
00333 standalone = !XS_icmp(found->second.c_str(), XS_TEXT("yes"));
00334 else
00335 standalone = -1;
00336
00337 _reader.XmlDeclHandler(version.empty()?NULL:version.c_str(), encoding.empty()?NULL:encoding.c_str(), standalone);
00338
00339 if (!encoding.empty()) {
00340 if (!_stricmp(encoding.c_str(), "utf-8"))
00341 _utf8 = true;
00342 else
00343 assert(!_reader._format._utf8_bom);
00344 }
00345
00346 c = _reader.eat_endl();
00347 } else if (tag == "?xml-stylesheet") {
00348 XMLNode::AttributeMap attributes;
00349 _buffer.get_attributes(attributes);
00350
00351 StyleSheet stylesheet(attributes.get("href"), attributes.get("type"), !XS_icmp(attributes.get("alternate"), XS_TEXT("yes")));
00352 stylesheet._title = attributes.get("title");
00353 stylesheet._media = attributes.get("media");
00354 stylesheet._charset = attributes.get("charset");
00355
00356 _reader._format._stylesheets.push_back(stylesheet);
00357
00358 c = _reader.eat_endl();
00359 } else {
00360 _reader.DefaultHandler(b);
00361 c = _reader.get();
00362 }
00363 } else if (str[1] == '!') {
00364 if (!strncmp(str+2, "DOCTYPE ", 8)) {
00365 _reader._format._doctype.parse(str+10);
00366
00367 c = _reader.eat_endl();
00368 } else if (!strncmp(str+2, "[CDATA[", 7)) {
00369
00370 while(!_buffer.has_CDEnd()) {
00371 c = _reader.get();
00372
00373 if (c == EOF)
00374 break;
00375
00376 _buffer.append(c);
00377 }
00378
00379 _reader.DefaultHandler(_buffer.str(_utf8));
00380
00381 c = _reader.get();
00382 }
00383 } else {
00384
00385 const XS_String& tag = _buffer.get_tag();
00386
00387 if (!tag.empty()) {
00388 XMLNode::AttributeMap attributes;
00389 _buffer.get_attributes(attributes);
00390
00391 _reader.StartElementHandler(tag, attributes);
00392
00393 if (str[b.length()-2] == '/')
00394 _reader.EndElementHandler();
00395 }
00396
00397 c = _reader.get();
00398 }
00399 } else {
00400 _buffer.append(c);
00401
00402
00403 for(;;) {
00404
00405 if (!_reader._endl_defined) {
00406 if (c == '\n') {
00407 _reader._format._endl = "\n";
00408 _reader._endl_defined = true;
00409 } else if (c == '\r') {
00410 _reader._format._endl = "\r\n";
00411 _reader._endl_defined = true;
00412 }
00413 }
00414
00415 c = _reader.get();
00416
00417 if (c == EOF)
00418 break;
00419
00420 if (c == '<')
00421 break;
00422
00423 _buffer.append(c);
00424 }
00425
00426 _reader.DefaultHandler(_buffer.str(_utf8));
00427 }
00428
00429 _buffer.reset();
00430
00431 return c;
00432 }
00433
00434
00435 bool XMLReaderBase::parse(bool force_utf8)
00436 {
00437 ParseContext ctx(*this, force_utf8);
00438
00439 while(ctx.proceed()) {
00440 }
00441
00442 return true;
00443 }
00444
00445 int XMLReaderBase::eat_endl()
00446 {
00447 int c = get();
00448
00449 if (c == '\r')
00450 c = get();
00451
00452 if (c == '\n')
00453 c = get();
00454
00455 return c;
00456 }
00457
00458
00459
00460 void XMLReaderBase::DefaultHandler(const std::string& s)
00461 {
00462 _content.append(s);
00463 }
00464
00465
00466 }
00467
00468 #endif // !defined(XS_USE_EXPAT) && !defined(XS_USE_XERCES)