aboutsummaryrefslogtreecommitdiff
path: root/libxsd/xsd/cxx/parser/expat/elements.hxx
blob: 0ab3f952b86435b3e336ffcc10f075e2ff094e14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
// file      : xsd/cxx/parser/expat/elements.hxx
// copyright : Copyright (c) 2005-2011 Code Synthesis Tools CC
// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file

#ifndef XSD_CXX_PARSER_EXPAT_ELEMENTS_HXX
#define XSD_CXX_PARSER_EXPAT_ELEMENTS_HXX

#include <xsd/cxx/config.hxx> // XSD_CXX11

#include <string>
#include <iosfwd>
#include <cstddef> // std::size_t
#include <vector>

#ifdef XSD_CXX11
#  include <memory> // std::unique_ptr
#endif

#include <expat.h>

// We only support UTF-8 expat for now.
//
#ifdef XML_UNICODE
#error UTF-16 expat (XML_UNICODE defined) is not supported
#endif

#include <xsd/cxx/xml/error-handler.hxx>

#include <xsd/cxx/parser/exceptions.hxx>
#include <xsd/cxx/parser/elements.hxx>
#include <xsd/cxx/parser/document.hxx>
#include <xsd/cxx/parser/error-handler.hxx>
#include <xsd/cxx/parser/schema-exceptions.hxx>

namespace xsd
{
  namespace cxx
  {
    namespace parser
    {
      namespace expat
      {
#ifdef XSD_CXX11
        struct parser_deleter
        {
          void
          operator() (XML_Parser p) const
          {
            if (p != 0)
              XML_ParserFree (p);
          }
        };

        typedef std::unique_ptr<XML_ParserStruct> parser_auto_ptr;
#else
        // Simple auto pointer for Expat's XML_Parser object.
        //
        struct parser_auto_ptr
        {
          ~parser_auto_ptr ()
          {
            if (parser_ != 0)
              XML_ParserFree (parser_);
          }

          explicit
          parser_auto_ptr (XML_Parser parser = 0)
              : parser_ (parser)
          {
          }

          parser_auto_ptr&
          operator= (XML_Parser parser)
          {
            if (parser_ != 0)
              XML_ParserFree (parser_);

            parser_ = parser;
            return *this;
          }

          XML_Parser
          get () const
          {
            return parser_;
          }

        private:
          parser_auto_ptr (const parser_auto_ptr&);

          parser_auto_ptr&
          operator= (const parser_auto_ptr&);

        private:
          XML_Parser parser_;
        };
#endif // XSD_CXX11

        //
        //
        template <typename C>
        struct document: cxx::parser::document<C> // VC likes it qualified
        {
        public:
          document (parser_base<C>&,
                    const C* root_element_name,
                    bool polymorphic = false);

          document (parser_base<C>&,
                    const std::basic_string<C>& root_element_name,
                    bool polymorphic = false);

          document (parser_base<C>&,
                    const C* root_element_namespace,
                    const C* root_element_name,
                    bool polymorphic = false);

          document (parser_base<C>&,
                    const std::basic_string<C>& root_element_namespace,
                    const std::basic_string<C>& root_element_name,
                    bool polymorphic = false);

        protected:
          document (bool polymorphic = false);

        public:
          // Parse a local file. The file is accessed with std::ifstream
          // in binary mode. The std::ios_base::failure exception is used
          // to report io errors (badbit and failbit).
          void
          parse (const std::basic_string<C>& file);

          // Parse a local file with a user-provided error_handler
          // object. The file is accessed with std::ifstream in binary
          // mode. The std::ios_base::failure exception is used to report
          // io errors (badbit and failbit).
          //
          void
          parse (const std::basic_string<C>& file, xml::error_handler<C>&);

        public:
          // System id is a "system" identifier of the resources (e.g.,
          // URI or a full file path). Public id is a "public" identifier
          // of the resource (e.g., application-specific name or relative
          // file path). System id is used to resolve relative paths.
          // In diagnostics messages system id is used if public id is
          // not available. Otherwise public id is used.
          //

          // Parse std::istream.
          //
          void
          parse (std::istream&);

          // Parse std::istream with a user-provided error_handler object.
          //
          void
          parse (std::istream&, xml::error_handler<C>&);

          // Parse std::istream with a system id.
          //
          void
          parse (std::istream&, const std::basic_string<C>& system_id);

          // Parse std::istream with a system id and a user-provided
          // error_handler object.
          //
          void
          parse (std::istream&,
                 const std::basic_string<C>& system_id,
                 xml::error_handler<C>&);

          // Parse std::istream with system and public ids.
          //
          void
          parse (std::istream&,
                 const std::basic_string<C>& system_id,
                 const std::basic_string<C>& public_id);

          // Parse std::istream with system and public ids and a user-provided
          // error_handler object.
          //
          void
          parse (std::istream&,
                 const std::basic_string<C>& system_id,
                 const std::basic_string<C>& public_id,
                 xml::error_handler<C>&);

        public:
          // Parse a chunk of input. You can call these functions multiple
          // times with the last call having the last argument true.
          //
          void
          parse (const void* data, std::size_t size, bool last);

          void
          parse (const void* data, std::size_t size, bool last,
                 xml::error_handler<C>&);

          void
          parse (const void* data, std::size_t size, bool last,
                 const std::basic_string<C>& system_id);

          void
          parse (const void* data, std::size_t size, bool last,
                 const std::basic_string<C>& system_id,
                 xml::error_handler<C>&);

          void
          parse (const void* data, std::size_t size, bool last,
                 const std::basic_string<C>& system_id,
                 const std::basic_string<C>& public_id);

          void
          parse (const void* data, std::size_t size, bool last,
                 const std::basic_string<C>& system_id,
                 const std::basic_string<C>& public_id,
                 xml::error_handler<C>&);

        public:
          // Low-level Expat-specific parsing API. A typical use case
          // would look like this (pseudo-code):
          //
          // xxx_pimpl root;
          // document doc (root, "root");
          //
          // root.pre ();
          // doc.parse_begin (xml_parser, "file.xml");
          //
          // while (more_stuff_to_parse &&)
          // {
          //    // Call XML_Parse or XML_ParseBuffer.
          //
          //    if (status == XML_STATUS_ERROR)
          //      break;
          // }
          //
          // // Call parse_end even in case of an error to translate
          // // XML and Schema errors to exceptions or error_handler
          // // calls.
          // //
          // doc.parse_end ();
          // result_type result (root.post_xxx ());
          //
          // Notes:
          //
          // 1. If your XML instances use XML namespaces, the
          //    XML_ParserCreateNS functions should be used to create the
          //    XML parser. Space (XML_Char (' ')) should be used as a
          //    separator (the second argument to XML_ParserCreateNS).
          //
          void
          parse_begin (XML_Parser);

          void
          parse_begin (XML_Parser, const std::basic_string<C>& public_id);

          void
          parse_begin (XML_Parser, xml::error_handler<C>&);

          void
          parse_begin (XML_Parser,
                       const std::basic_string<C>& public_id,
                       xml::error_handler<C>&);
          void
          parse_end ();

          // Event routing.
          //
        public:
          static void XMLCALL
          start_element_thunk_ (void*, const XML_Char*, const XML_Char**);

          static void XMLCALL
          end_element_thunk_ (void*, const XML_Char*);

          static void XMLCALL
          characters_thunk_ (void*, const XML_Char*, int);

          static void XMLCALL
          start_namespace_decl_thunk_ (
            void*, const XML_Char*, const XML_Char*);

          static void XMLCALL
          end_namespace_decl_thunk_ (void*, const XML_Char*);

        protected:
          void
          start_element_ (const XML_Char* ns_name, const XML_Char** atts);

          void
          end_element_ (const XML_Char* ns_name);

          void
          characters_ (const XML_Char* s, std::size_t n);

          void
          start_namespace_decl_ (const XML_Char* prefix, const XML_Char* ns);

          void
          end_namespace_decl_ (const XML_Char* prefix);

        protected:
          void
          set ();

          void
          clear ();

          bool
          parse (std::istream&,
                 const std::basic_string<C>* system_id,
                 const std::basic_string<C>* public_id,
                 xml::error_handler<C>&);

          bool
          parse (const void* data, std::size_t size, bool last,
                 const std::basic_string<C>* system_id,
                 const std::basic_string<C>* public_id,
                 xml::error_handler<C>&);


          void
          translate_schema_exception (const schema_exception<C>& e);

        protected:
          XML_Parser xml_parser_;
          parser_auto_ptr auto_xml_parser_;

          xml::error_handler<C>* eh_;
          error_handler<C> default_eh_;
          std::basic_string<C> public_id_;

          bool polymorphic_;

          // Namespace-prefix mapping. Only maintained in the polymorphic
          // case.
          //
          struct ns_decl
          {
            ns_decl (const std::basic_string<C>& p,
                     const std::basic_string<C>& n)
                : prefix (p), ns (n)
            {
            }

            std::basic_string<C> prefix;
            std::basic_string<C> ns;
          };

          typedef std::vector<ns_decl> ns_decls;

          ns_decls ns_decls_;
        };
      }
    }
  }
}

#include <xsd/cxx/parser/expat/elements.txx>

#endif  // XSD_CXX_PARSER_EXPAT_ELEMENTS_HXX