| 1 | // file : xsd/cxx/parser/expat/elements.hxx |
|---|
| 2 | // author : Boris Kolpackov <boris@codesynthesis.com> |
|---|
| 3 | // copyright : Copyright (c) 2005-2008 Code Synthesis Tools CC |
|---|
| 4 | // license : GNU GPL v2 + exceptions; see accompanying LICENSE file |
|---|
| 5 | |
|---|
| 6 | #ifndef XSD_CXX_PARSER_EXPAT_ELEMENTS_HXX |
|---|
| 7 | #define XSD_CXX_PARSER_EXPAT_ELEMENTS_HXX |
|---|
| 8 | |
|---|
| 9 | #include <string> |
|---|
| 10 | #include <iosfwd> |
|---|
| 11 | #include <cstddef> // std::size_t |
|---|
| 12 | #include <vector> |
|---|
| 13 | |
|---|
| 14 | #include <expat.h> |
|---|
| 15 | |
|---|
| 16 | // We only support UTF-8 expat for now. |
|---|
| 17 | // |
|---|
| 18 | #ifdef XML_UNICODE |
|---|
| 19 | #error UTF-16 expat (XML_UNICODE defined) is not supported |
|---|
| 20 | #endif |
|---|
| 21 | |
|---|
| 22 | #include <xsd/cxx/xml/error-handler.hxx> |
|---|
| 23 | |
|---|
| 24 | #include <xsd/cxx/parser/exceptions.hxx> |
|---|
| 25 | #include <xsd/cxx/parser/elements.hxx> |
|---|
| 26 | #include <xsd/cxx/parser/document.hxx> |
|---|
| 27 | |
|---|
| 28 | namespace xsd |
|---|
| 29 | { |
|---|
| 30 | namespace cxx |
|---|
| 31 | { |
|---|
| 32 | namespace parser |
|---|
| 33 | { |
|---|
| 34 | namespace expat |
|---|
| 35 | { |
|---|
| 36 | // Simple auto pointer for Expat's XML_Parser object. |
|---|
| 37 | // |
|---|
| 38 | struct parser_auto_ptr |
|---|
| 39 | { |
|---|
| 40 | ~parser_auto_ptr () |
|---|
| 41 | { |
|---|
| 42 | if (parser_ != 0) |
|---|
| 43 | XML_ParserFree (parser_); |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | explicit |
|---|
| 47 | parser_auto_ptr (XML_Parser parser = 0) |
|---|
| 48 | : parser_ (parser) |
|---|
| 49 | { |
|---|
| 50 | } |
|---|
| 51 | |
|---|
| 52 | parser_auto_ptr& |
|---|
| 53 | operator= (XML_Parser parser) |
|---|
| 54 | { |
|---|
| 55 | if (parser_ != 0) |
|---|
| 56 | XML_ParserFree (parser_); |
|---|
| 57 | |
|---|
| 58 | parser_ = parser; |
|---|
| 59 | return *this; |
|---|
| 60 | } |
|---|
| 61 | |
|---|
| 62 | public: |
|---|
| 63 | operator XML_Parser () |
|---|
| 64 | { |
|---|
| 65 | return parser_; |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | private: |
|---|
| 69 | parser_auto_ptr (const parser_auto_ptr&); |
|---|
| 70 | |
|---|
| 71 | parser_auto_ptr& |
|---|
| 72 | operator= (const parser_auto_ptr&); |
|---|
| 73 | |
|---|
| 74 | private: |
|---|
| 75 | XML_Parser parser_; |
|---|
| 76 | }; |
|---|
| 77 | |
|---|
| 78 | |
|---|
| 79 | // |
|---|
| 80 | // |
|---|
| 81 | template <typename C> |
|---|
| 82 | struct event_router |
|---|
| 83 | { |
|---|
| 84 | public: |
|---|
| 85 | event_router (cxx::parser::document<C>& consumer, |
|---|
| 86 | bool polymorphic); |
|---|
| 87 | |
|---|
| 88 | public: |
|---|
| 89 | static void XMLCALL |
|---|
| 90 | start_element (void*, const XML_Char*, const XML_Char**); |
|---|
| 91 | |
|---|
| 92 | static void XMLCALL |
|---|
| 93 | end_element (void*, const XML_Char*); |
|---|
| 94 | |
|---|
| 95 | static void XMLCALL |
|---|
| 96 | characters (void*, const XML_Char*, int); |
|---|
| 97 | |
|---|
| 98 | static void XMLCALL |
|---|
| 99 | start_namespace_decl (void*, const XML_Char*, const XML_Char*); |
|---|
| 100 | |
|---|
| 101 | static void XMLCALL |
|---|
| 102 | end_namespace_decl (void*, const XML_Char*); |
|---|
| 103 | |
|---|
| 104 | private: |
|---|
| 105 | void |
|---|
| 106 | start_element_ (const XML_Char* ns_name, const XML_Char** atts); |
|---|
| 107 | |
|---|
| 108 | void |
|---|
| 109 | end_element_ (const XML_Char* ns_name); |
|---|
| 110 | |
|---|
| 111 | void |
|---|
| 112 | characters_ (const XML_Char* s, std::size_t n); |
|---|
| 113 | |
|---|
| 114 | void |
|---|
| 115 | start_namespace_decl_ (const XML_Char* prefix, const XML_Char* ns); |
|---|
| 116 | |
|---|
| 117 | void |
|---|
| 118 | end_namespace_decl_ (const XML_Char* prefix); |
|---|
| 119 | |
|---|
| 120 | private: |
|---|
| 121 | cxx::parser::document<C>& consumer_; |
|---|
| 122 | bool polymorphic_; |
|---|
| 123 | |
|---|
| 124 | // Namespace-prefix mapping. Only maintained in the polymorphic |
|---|
| 125 | // case. |
|---|
| 126 | // |
|---|
| 127 | struct ns_decl |
|---|
| 128 | { |
|---|
| 129 | ns_decl (const std::basic_string<C>& p, |
|---|
| 130 | const std::basic_string<C>& n) |
|---|
| 131 | : prefix (p), ns (n) |
|---|
| 132 | { |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | std::basic_string<C> prefix; |
|---|
| 136 | std::basic_string<C> ns; |
|---|
| 137 | }; |
|---|
| 138 | |
|---|
| 139 | typedef std::vector<ns_decl> ns_decls; |
|---|
| 140 | |
|---|
| 141 | ns_decls ns_decls_; |
|---|
| 142 | }; |
|---|
| 143 | |
|---|
| 144 | |
|---|
| 145 | // |
|---|
| 146 | // |
|---|
| 147 | template <typename C> |
|---|
| 148 | struct document: cxx::parser::document<C> // VC 7.1 likes it qualified |
|---|
| 149 | { |
|---|
| 150 | public: |
|---|
| 151 | document (parser_base<C>&, |
|---|
| 152 | const C* root_element_name, |
|---|
| 153 | bool polymorphic = false); |
|---|
| 154 | |
|---|
| 155 | document (parser_base<C>&, |
|---|
| 156 | const std::basic_string<C>& root_element_name, |
|---|
| 157 | bool polymorphic = false); |
|---|
| 158 | |
|---|
| 159 | document (parser_base<C>&, |
|---|
| 160 | const C* root_element_namespace, |
|---|
| 161 | const C* root_element_name, |
|---|
| 162 | bool polymorphic = false); |
|---|
| 163 | |
|---|
| 164 | document (parser_base<C>&, |
|---|
| 165 | const std::basic_string<C>& root_element_namespace, |
|---|
| 166 | const std::basic_string<C>& root_element_name, |
|---|
| 167 | bool polymorphic = false); |
|---|
| 168 | |
|---|
| 169 | protected: |
|---|
| 170 | document (bool polymorphic = false); |
|---|
| 171 | |
|---|
| 172 | public: |
|---|
| 173 | // Parse a local file. The file is accessed with std::ifstream |
|---|
| 174 | // in binary mode. The std::ios_base::failure exception is used |
|---|
| 175 | // to report io errors (badbit and failbit). |
|---|
| 176 | void |
|---|
| 177 | parse (const std::basic_string<C>& file); |
|---|
| 178 | |
|---|
| 179 | // Parse a local file with a user-provided error_handler |
|---|
| 180 | // object. The file is accessed with std::ifstream in binary |
|---|
| 181 | // mode. The std::ios_base::failure exception is used to report |
|---|
| 182 | // io errors (badbit and failbit). |
|---|
| 183 | // |
|---|
| 184 | void |
|---|
| 185 | parse (const std::basic_string<C>& file, xml::error_handler<C>&); |
|---|
| 186 | |
|---|
| 187 | public: |
|---|
| 188 | // System id is a "system" identifier of the resources (e.g., |
|---|
| 189 | // URI or a full file path). Public id is a "public" identifier |
|---|
| 190 | // of the resource (e.g., application-specific name or relative |
|---|
| 191 | // file path). System id is used to resolve relative paths. |
|---|
| 192 | // In diagnostics messages system id is used if public id is |
|---|
| 193 | // not available. Otherwise public id is used. |
|---|
| 194 | // |
|---|
| 195 | |
|---|
| 196 | // Parse std::istream. |
|---|
| 197 | // |
|---|
| 198 | void |
|---|
| 199 | parse (std::istream&); |
|---|
| 200 | |
|---|
| 201 | // Parse std::istream with a user-provided error_handler object. |
|---|
| 202 | // |
|---|
| 203 | void |
|---|
| 204 | parse (std::istream&, xml::error_handler<C>&); |
|---|
| 205 | |
|---|
| 206 | // Parse std::istream with a system id. |
|---|
| 207 | // |
|---|
| 208 | void |
|---|
| 209 | parse (std::istream&, const std::basic_string<C>& system_id); |
|---|
| 210 | |
|---|
| 211 | // Parse std::istream with a system id and a user-provided |
|---|
| 212 | // error_handler object. |
|---|
| 213 | // |
|---|
| 214 | void |
|---|
| 215 | parse (std::istream&, |
|---|
| 216 | const std::basic_string<C>& system_id, |
|---|
| 217 | xml::error_handler<C>&); |
|---|
| 218 | |
|---|
| 219 | // Parse std::istream with system and public ids. |
|---|
| 220 | // |
|---|
| 221 | void |
|---|
| 222 | parse (std::istream&, |
|---|
| 223 | const std::basic_string<C>& system_id, |
|---|
| 224 | const std::basic_string<C>& public_id); |
|---|
| 225 | |
|---|
| 226 | // Parse std::istream with system and public ids and a user-provided |
|---|
| 227 | // error_handler object. |
|---|
| 228 | // |
|---|
| 229 | void |
|---|
| 230 | parse (std::istream&, |
|---|
| 231 | const std::basic_string<C>& system_id, |
|---|
| 232 | const std::basic_string<C>& public_id, |
|---|
| 233 | xml::error_handler<C>&); |
|---|
| 234 | |
|---|
| 235 | public: |
|---|
| 236 | // Parse a chunk of input. You can call these functions multiple |
|---|
| 237 | // times with the last call having the last argument true. |
|---|
| 238 | // |
|---|
| 239 | void |
|---|
| 240 | parse (const void* data, std::size_t size, bool last); |
|---|
| 241 | |
|---|
| 242 | void |
|---|
| 243 | parse (const void* data, std::size_t size, bool last, |
|---|
| 244 | xml::error_handler<C>&); |
|---|
| 245 | |
|---|
| 246 | void |
|---|
| 247 | parse (const void* data, std::size_t size, bool last, |
|---|
| 248 | const std::basic_string<C>& system_id); |
|---|
| 249 | |
|---|
| 250 | void |
|---|
| 251 | parse (const void* data, std::size_t size, bool last, |
|---|
| 252 | const std::basic_string<C>& system_id, |
|---|
| 253 | xml::error_handler<C>&); |
|---|
| 254 | |
|---|
| 255 | void |
|---|
| 256 | parse (const void* data, std::size_t size, bool last, |
|---|
| 257 | const std::basic_string<C>& system_id, |
|---|
| 258 | const std::basic_string<C>& public_id); |
|---|
| 259 | |
|---|
| 260 | void |
|---|
| 261 | parse (const void* data, std::size_t size, bool last, |
|---|
| 262 | const std::basic_string<C>& system_id, |
|---|
| 263 | const std::basic_string<C>& public_id, |
|---|
| 264 | xml::error_handler<C>&); |
|---|
| 265 | |
|---|
| 266 | public: |
|---|
| 267 | // Low-level Expat-specific parsing API. A typical use case |
|---|
| 268 | // would look like this (pseudo-code): |
|---|
| 269 | // |
|---|
| 270 | // xxx_pimpl root; |
|---|
| 271 | // document doc (root, "root"); |
|---|
| 272 | // |
|---|
| 273 | // root.pre (); |
|---|
| 274 | // doc.parse_begin (xml_parser); |
|---|
| 275 | // |
|---|
| 276 | // while (more_stuff_to_parse) |
|---|
| 277 | // { |
|---|
| 278 | // // Call XML_Parse or XML_ParseBuffer. |
|---|
| 279 | // // Handle XML wellformedness errors if any. |
|---|
| 280 | // } |
|---|
| 281 | // |
|---|
| 282 | // doc.parse_end (); |
|---|
| 283 | // result_type result (root.post_xxx ()); |
|---|
| 284 | // |
|---|
| 285 | // Notes: |
|---|
| 286 | // |
|---|
| 287 | // 1. If your XML instances use XML namespaces, the |
|---|
| 288 | // XML_ParserCreateNS functions should be used to create the |
|---|
| 289 | // XML parser. Space (XML_Char (' ')) should be used as a |
|---|
| 290 | // separator (the second argument to XML_ParserCreateNS). |
|---|
| 291 | // |
|---|
| 292 | void |
|---|
| 293 | parse_begin (XML_Parser); |
|---|
| 294 | |
|---|
| 295 | void |
|---|
| 296 | parse_end (); |
|---|
| 297 | |
|---|
| 298 | protected: |
|---|
| 299 | void |
|---|
| 300 | set (); |
|---|
| 301 | |
|---|
| 302 | void |
|---|
| 303 | clear (); |
|---|
| 304 | |
|---|
| 305 | bool |
|---|
| 306 | parse (std::istream&, |
|---|
| 307 | const std::basic_string<C>* system_id, |
|---|
| 308 | const std::basic_string<C>* public_id, |
|---|
| 309 | xml::error_handler<C>&); |
|---|
| 310 | |
|---|
| 311 | bool |
|---|
| 312 | parse (const void* data, std::size_t size, bool last, |
|---|
| 313 | const std::basic_string<C>* system_id, |
|---|
| 314 | const std::basic_string<C>* public_id, |
|---|
| 315 | xml::error_handler<C>&); |
|---|
| 316 | |
|---|
| 317 | protected: |
|---|
| 318 | bool polymorphic_; |
|---|
| 319 | event_router<C> router_; |
|---|
| 320 | |
|---|
| 321 | XML_Parser xml_parser_; |
|---|
| 322 | parser_auto_ptr auto_xml_parser_; |
|---|
| 323 | }; |
|---|
| 324 | } |
|---|
| 325 | } |
|---|
| 326 | } |
|---|
| 327 | } |
|---|
| 328 | |
|---|
| 329 | #include <xsd/cxx/parser/expat/elements.txx> |
|---|
| 330 | |
|---|
| 331 | #endif // XSD_CXX_PARSER_EXPAT_ELEMENTS_HXX |
|---|