root/win32/xsd-3.1.0-i686/libxsd/xsd/cxx/parser/expat/elements.txx @ 111

Revision 111, 20.5 kB (checked in by mido, 16 years ago)

pridana knihovna XSD (a jeji chlebodarkyne XERCES), v ramci Win32 zprovoznen priklad tests/test_xsd_hello.cxx

Line 
1// file      : xsd/cxx/parser/expat/elements.txx
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#include <new>     // std::bad_alloc
7#include <istream>
8#include <fstream>
9#include <cstring> // std::strchr
10#include <cassert>
11
12#include <xsd/cxx/xml/bits/literals.hxx> // xml::bits::{xml_prefix, etc}
13
14#include <xsd/cxx/parser/error-handler.hxx>
15#include <xsd/cxx/parser/schema-exceptions.hxx>
16
17namespace xsd
18{
19  namespace cxx
20  {
21    namespace parser
22    {
23      namespace expat
24      {
25
26        // document
27        //
28
29        template <typename C>
30        document<C>::
31        document (parser_base<C>& p,
32                  const std::basic_string<C>& name,
33                  bool polymorphic)
34            : cxx::parser::document<C> (p, std::basic_string<C> (), name),
35              polymorphic_ (polymorphic),
36              router_ (*this, polymorphic),
37              xml_parser_ (0)
38        {
39        }
40
41        template <typename C>
42        document<C>::
43        document (parser_base<C>& p,
44                  const C* name,
45                  bool polymorphic)
46            : cxx::parser::document<C> (p, std::basic_string<C> (), name),
47              polymorphic_ (polymorphic),
48              router_ (*this, polymorphic),
49              xml_parser_ (0)
50        {
51        }
52
53        template <typename C>
54        document<C>::
55        document (parser_base<C>& p,
56                  const C* ns,
57                  const C* name,
58                  bool polymorphic)
59            : cxx::parser::document<C> (p, ns, name),
60              polymorphic_ (polymorphic),
61              router_ (*this, polymorphic),
62              xml_parser_ (0)
63        {
64        }
65
66        template <typename C>
67        document<C>::
68        document (parser_base<C>& p,
69                  const std::basic_string<C>& ns,
70                  const std::basic_string<C>& name,
71                  bool polymorphic)
72            : cxx::parser::document<C> (p, ns, name),
73              polymorphic_ (polymorphic),
74              router_ (*this, polymorphic),
75              xml_parser_ (0)
76        {
77        }
78
79        template <typename C>
80        document<C>::
81        document (bool polymorphic)
82            : polymorphic_ (polymorphic),
83              router_ (*this, polymorphic),
84              xml_parser_ (0)
85        {
86        }
87
88        // file
89        //
90
91        template <typename C>
92        void document<C>::
93        parse (const std::basic_string<C>& file)
94        {
95          std::ifstream ifs;
96          ifs.exceptions (std::ios_base::badbit | std::ios_base::failbit);
97          ifs.open (file.c_str (), std::ios_base::in | std::ios_base::binary);
98
99          parse (ifs, file);
100        }
101
102        template <typename C>
103        void document<C>::
104        parse (const std::basic_string<C>& file, xml::error_handler<C>& eh)
105        {
106          std::ifstream ifs;
107          ifs.exceptions (std::ios_base::badbit | std::ios_base::failbit);
108          ifs.open (file.c_str (), std::ios_base::in | std::ios_base::binary);
109
110          parse (ifs, file, eh);
111        }
112
113
114        // istream
115        //
116
117        template <typename C>
118        void document<C>::
119        parse (std::istream& is)
120        {
121          error_handler<C> eh;
122          parse (is, 0, 0, eh);
123          eh.throw_if_failed ();
124        }
125
126        template <typename C>
127        void document<C>::
128        parse (std::istream& is, xml::error_handler<C>& eh)
129        {
130          if (!parse (is, 0, 0, eh))
131            throw parsing<C> ();
132        }
133
134        template <typename C>
135        void document<C>::
136        parse (std::istream& is, const std::basic_string<C>& system_id)
137        {
138          error_handler<C> eh;
139          parse (is, &system_id, 0, eh);
140          eh.throw_if_failed ();
141        }
142
143        template <typename C>
144        void document<C>::
145        parse (std::istream& is,
146               const std::basic_string<C>& system_id,
147               xml::error_handler<C>& eh)
148        {
149          if (!parse (is, &system_id, 0, eh))
150            throw parsing<C> ();
151        }
152
153        template <typename C>
154        void document<C>::
155        parse (std::istream& is,
156               const std::basic_string<C>& system_id,
157               const std::basic_string<C>& public_id)
158        {
159          error_handler<C> eh;
160          parse (is, &system_id, &public_id, eh);
161          eh.throw_if_failed ();
162        }
163
164        template <typename C>
165        void document<C>::
166        parse (std::istream& is,
167               const std::basic_string<C>& system_id,
168               const std::basic_string<C>& public_id,
169               xml::error_handler<C>& eh)
170        {
171          if (!parse (is, &system_id, &public_id, eh))
172            throw parsing<C> ();
173        }
174
175        // data
176        //
177
178        template <typename C>
179        void document<C>::
180        parse (const void* data, std::size_t size, bool last)
181        {
182          error_handler<C> eh;
183          parse (data, size, last, 0, 0, eh);
184          eh.throw_if_failed ();
185        }
186
187        template <typename C>
188        void document<C>::
189        parse (const void* data, std::size_t size, bool last,
190               xml::error_handler<C>& eh)
191        {
192          if (!parse (data, size, last, 0, 0, eh))
193            throw parsing<C> ();
194        }
195
196        template <typename C>
197        void document<C>::
198        parse (const void* data, std::size_t size, bool last,
199               const std::basic_string<C>& system_id)
200        {
201          error_handler<C> eh;
202          parse (data, size, last, &system_id, 0, eh);
203          eh.throw_if_failed ();
204        }
205
206        template <typename C>
207        void document<C>::
208        parse (const void* data, std::size_t size, bool last,
209               const std::basic_string<C>& system_id,
210               xml::error_handler<C>& eh)
211        {
212          if (!parse (data, size, last, &system_id, 0, eh))
213            throw parsing<C> ();
214        }
215
216        template <typename C>
217        void document<C>::
218        parse (const void* data, std::size_t size, bool last,
219               const std::basic_string<C>& system_id,
220               const std::basic_string<C>& public_id)
221        {
222          error_handler<C> eh;
223          parse (data, size, last, &system_id, &public_id, eh);
224          eh.throw_if_failed ();
225        }
226
227        template <typename C>
228        void document<C>::
229        parse (const void* data, std::size_t size, bool last,
230               const std::basic_string<C>& system_id,
231               const std::basic_string<C>& public_id,
232               xml::error_handler<C>& eh)
233        {
234          if (!parse (data, size, last, &system_id, &public_id, eh))
235            throw parsing<C> ();
236        }
237
238        // Implementation details.
239        //
240
241        namespace bits
242        {
243          struct stream_exception_controller
244          {
245            ~stream_exception_controller ()
246            {
247              if (is_.fail () && is_.eof ())
248                is_.clear (is_.rdstate () & ~std::ios_base::failbit);
249
250              is_.exceptions (old_state_);
251            }
252
253            stream_exception_controller (std::istream& is)
254                : is_ (is), old_state_ (is_.exceptions ())
255            {
256              is_.exceptions (old_state_ & ~std::ios_base::failbit);
257            }
258
259          private:
260            stream_exception_controller (const stream_exception_controller&);
261
262            stream_exception_controller&
263            operator= (const stream_exception_controller&);
264
265          private:
266            std::istream& is_;
267            std::ios_base::iostate old_state_;
268          };
269        };
270
271        template <typename C>
272        bool document<C>::
273        parse (std::istream& is,
274               const std::basic_string<C>* system_id,
275               const std::basic_string<C>* public_id,
276               xml::error_handler<C>& eh)
277        {
278          parser_auto_ptr parser (XML_ParserCreateNS (0, XML_Char (' ')));
279
280          if (parser == 0)
281            throw std::bad_alloc ();
282
283          parse_begin (parser);
284
285          // Temporarily unset the exception failbit. Also clear the
286          // fail bit when we reset the old state if it was caused
287          // by eof.
288          //
289          bits::stream_exception_controller sec (is);
290
291          char buf[16384]; // 4 x page size.
292
293          do
294          {
295            is.read (buf, sizeof (buf));
296
297            if (is.bad () || (is.fail () && !is.eof ()))
298            {
299              // If the stream is not using exceptions then the user
300              // will have to test for stream failures before calling
301              // post.
302              //
303              return true;
304            }
305
306            try
307            {
308              if (XML_Parse (
309                    parser, buf, is.gcount (), is.eof ()) == XML_STATUS_ERROR)
310              {
311                unsigned long l (XML_GetCurrentLineNumber (xml_parser_));
312                unsigned long c (XML_GetCurrentColumnNumber (xml_parser_));
313                std::basic_string<C> message (
314                  XML_ErrorString (XML_GetErrorCode (xml_parser_)));
315
316                parse_end ();
317
318                eh.handle (
319                  public_id
320                  ? *public_id
321                  : (system_id ? *system_id : std::basic_string<C> ()),
322                  l, c, xml::error_handler<C>::severity::fatal, message);
323
324                return false;
325              }
326            }
327            catch (const schema_exception<C>& e)
328            {
329              unsigned long l (XML_GetCurrentLineNumber (xml_parser_));
330              unsigned long c (XML_GetCurrentColumnNumber (xml_parser_));
331
332              parse_end ();
333
334              eh.handle (
335                public_id
336                ? *public_id
337                : (system_id ? *system_id : std::basic_string<C> ()),
338                l, c, xml::error_handler<C>::severity::fatal, e.message ());
339
340              return false;
341            }
342
343          } while (!is.eof ());
344
345          parse_end ();
346
347          return true;
348        }
349
350        template <typename C>
351        bool document<C>::
352        parse (const void* data,
353               std::size_t size,
354               bool last,
355               const std::basic_string<C>* system_id,
356               const std::basic_string<C>* public_id,
357               xml::error_handler<C>& eh)
358        {
359          // First call.
360          //
361          if (auto_xml_parser_ == 0)
362          {
363            auto_xml_parser_ = XML_ParserCreateNS (0, XML_Char (' '));
364
365            if (auto_xml_parser_ == 0)
366              throw std::bad_alloc ();
367
368            parse_begin (auto_xml_parser_);
369          }
370
371          try
372          {
373            if (XML_Parse (xml_parser_,
374                           static_cast<const char*> (data),
375                           static_cast<int> (size),
376                           last) == XML_STATUS_ERROR)
377            {
378              unsigned long l (XML_GetCurrentLineNumber (xml_parser_));
379              unsigned long c (XML_GetCurrentColumnNumber (xml_parser_));
380              std::basic_string<C> message (
381                XML_ErrorString (XML_GetErrorCode (xml_parser_)));
382
383              parse_end ();
384
385              eh.handle (
386                public_id
387                ? *public_id
388                : (system_id ? *system_id : std::basic_string<C> ()),
389                l, c, xml::error_handler<C>::severity::fatal, message);
390
391              return false;
392            }
393          }
394          catch (const schema_exception<C>& e)
395          {
396            unsigned long l (XML_GetCurrentLineNumber (xml_parser_));
397            unsigned long c (XML_GetCurrentColumnNumber (xml_parser_));
398
399            parse_end ();
400
401            eh.handle (
402              public_id
403              ? *public_id
404              : (system_id ? *system_id : std::basic_string<C> ()),
405              l, c, xml::error_handler<C>::severity::fatal, e.message ());
406
407            return false;
408          }
409
410          if (last)
411            parse_end ();
412
413          return true;
414        }
415
416        // XML_Parser
417        //
418
419        template <typename C>
420        void document<C>::
421        parse_begin (XML_Parser parser)
422        {
423          xml_parser_ = parser;
424          set ();
425        }
426
427        template <typename C>
428        void document<C>::
429        parse_end ()
430        {
431          clear ();
432          xml_parser_ = 0;
433          auto_xml_parser_ = 0;
434        }
435
436        //
437        //
438        template <typename C>
439        void document<C>::
440        set ()
441        {
442          assert (xml_parser_ != 0);
443
444          XML_SetUserData(xml_parser_, &router_);
445
446          XML_SetStartElementHandler (
447            xml_parser_, event_router<C>::start_element);
448          XML_SetEndElementHandler (
449            xml_parser_, event_router<C>::end_element);
450          XML_SetCharacterDataHandler (
451            xml_parser_, event_router<C>::characters);
452
453          if (polymorphic_)
454          {
455            XML_SetNamespaceDeclHandler (
456              xml_parser_,
457              event_router<C>::start_namespace_decl,
458              event_router<C>::end_namespace_decl);
459          }
460        }
461
462        template <typename C>
463        void document<C>::
464        clear ()
465        {
466          assert (xml_parser_ != 0);
467
468          XML_SetUserData (xml_parser_, 0);
469          XML_SetStartElementHandler (xml_parser_, 0);
470          XML_SetEndElementHandler (xml_parser_, 0);
471          XML_SetCharacterDataHandler (xml_parser_, 0);
472
473          if (polymorphic_)
474            XML_SetNamespaceDeclHandler (xml_parser_, 0, 0);
475        }
476
477        // event_router
478        //
479
480        template <typename C>
481        event_router<C>::
482        event_router (cxx::parser::document<C>& consumer, bool polymorphic)
483            : consumer_ (consumer), polymorphic_ (polymorphic)
484        {
485        }
486
487        // Expat thunks.
488        //
489        template <typename C>
490        void XMLCALL event_router<C>::
491        start_element (
492          void* data, const XML_Char* ns_name, const XML_Char** atts)
493        {
494          event_router& r (*reinterpret_cast<event_router*> (data));
495          r.start_element_ (ns_name, atts);
496        }
497
498        template <typename C>
499        void XMLCALL event_router<C>::
500        end_element (void* data, const XML_Char* ns_name)
501        {
502          event_router& r (*reinterpret_cast<event_router*> (data));
503          r.end_element_ (ns_name);
504        }
505
506        template <typename C>
507        void XMLCALL event_router<C>::
508        characters (void* data, const XML_Char* s, int n)
509        {
510          event_router& r (*reinterpret_cast<event_router*> (data));
511          r.characters_ (s, static_cast<std::size_t> (n));
512        }
513
514        template <typename C>
515        void XMLCALL event_router<C>::
516        start_namespace_decl (void* data,
517                              const XML_Char* prefix,
518                              const XML_Char* ns)
519        {
520          event_router& r (*reinterpret_cast<event_router*> (data));
521          r.start_namespace_decl_ (prefix, ns);
522        }
523
524        template <typename C>
525        void XMLCALL event_router<C>::
526        end_namespace_decl (void* data, const XML_Char* prefix)
527        {
528          event_router& r (*reinterpret_cast<event_router*> (data));
529          r.end_namespace_decl_ (prefix);
530        }
531
532        namespace bits
533        {
534          inline void
535          split_name (const XML_Char* s,
536                      const char*& ns, std::size_t& ns_s,
537                      const char*& name, std::size_t& name_s)
538          {
539            const char* p (std::strchr (s, ' '));
540
541            if (p)
542            {
543              ns = s;
544              ns_s = p - s;
545              name = p + 1;
546            }
547            else
548            {
549              ns = s;
550              ns_s = 0;
551              name = s;
552            }
553
554            name_s = std::char_traits<char>::length (name);
555          }
556        }
557
558        template <typename C>
559        void event_router<C>::
560        start_element_ (const XML_Char* ns_name, const XML_Char** atts)
561        {
562          typedef std::basic_string<C> string;
563
564          const char* ns_p;
565          const char* name_p;
566          size_t ns_s, name_s;
567
568          bits::split_name (ns_name, ns_p, ns_s, name_p, name_s);
569
570          {
571            const ro_string<C> ns (ns_p, ns_s), name (name_p, name_s);
572
573            if (!polymorphic_)
574              consumer_.start_element (ns, name, 0);
575            else
576            {
577              // Search for the xsi:type attribute.
578              //
579              const XML_Char** p (atts);
580              for (; *p != 0; p += 2)
581              {
582                bits::split_name (*p, ns_p, ns_s, name_p, name_s);
583                const ro_string<C> ns (ns_p, ns_s), name (name_p, name_s);
584
585                if (name == xml::bits::type<C> () &&
586                    ns == xml::bits::xsi_namespace<C> ())
587                  break;
588              }
589
590              if (*p == 0)
591                consumer_.start_element (ns, name, 0);
592              else
593              {
594                // @@ Need proper QName validation.
595                //
596                // Get the qualified type name and try to resolve it.
597                //
598                ro_string<C> qn (*(p + 1));
599
600                string tp, tn, tns;
601                typename ro_string<C>::size_type pos (qn.find (C (':')));
602
603                if (pos != ro_string<C>::npos)
604                {
605                  tp.assign (qn.data (), pos);
606                  tn.assign (qn.data () + pos + 1);
607
608                  if (tp.empty ())
609                    throw dynamic_type<C> (qn);
610                }
611                else
612                  tn = qn;
613
614                if (tn.empty ())
615                  throw dynamic_type<C> (qn);
616
617                // Search our namespace declaration stack. Sun CC 5.7
618                  // blows if we use const_reverse_iterator.
619                //
620                for (typename ns_decls::reverse_iterator
621                       it (ns_decls_.rbegin ()), e (ns_decls_.rend ());
622                     it != e; ++it)
623                {
624                  if (it->prefix == tp)
625                  {
626                    tns = it->ns;
627                    break;
628                  }
629                }
630
631                if (!tp.empty () && tns.empty ())
632                {
633                  // The 'xml' prefix requires special handling.
634                  //
635                  if (tp == xml::bits::xml_prefix<C> ())
636                    tns = xml::bits::xml_namespace<C> ();
637                  else
638                    throw dynamic_type<C> (qn);
639                }
640
641                // Construct the compound name.
642                //
643                if (!tns.empty ())
644                {
645                  tn += C (' ');
646                  tn += tns;
647                }
648
649                ro_string<C> ro_tn (tn);
650
651                consumer_.start_element (ns, name, &ro_tn);
652              }
653            }
654          }
655
656          for (; *atts != 0; atts += 2)
657          {
658            bits::split_name (*atts, ns_p, ns_s, name_p, name_s);
659
660            const ro_string<C> ns (ns_p, ns_s), name (name_p, name_s);
661            const ro_string<C> value (*(atts + 1));
662
663            consumer_.attribute (ns, name, value);
664          }
665        }
666
667        template <typename C>
668        void event_router<C>::
669        end_element_ (const XML_Char* ns_name)
670        {
671          const char* ns_p;
672          const char* name_p;
673          size_t ns_s, name_s;
674
675          bits::split_name (ns_name, ns_p, ns_s, name_p, name_s);
676
677          const ro_string<C> ns (ns_p, ns_s), name (name_p, name_s);
678
679          consumer_.end_element (ns, name);
680        }
681
682        template <typename C>
683        void event_router<C>::
684        characters_ (const XML_Char* s, std::size_t n)
685        {
686          if (n != 0)
687          {
688            const ro_string<C> str (s, n);
689            consumer_.characters (str);
690          }
691        }
692
693        template <typename C>
694        void event_router<C>::
695        start_namespace_decl_ (const XML_Char* p, const XML_Char* ns)
696        {
697          // prefix is 0 for default namespace
698          // namespace is 0 when unsetting default namespace
699          //
700          if (polymorphic_)
701          {
702            ns_decls_.push_back (ns_decl ((p ? p : ""), (ns ? ns : "")));
703          }
704        }
705
706        template <typename C>
707        void event_router<C>::
708        end_namespace_decl_ (const XML_Char* p)
709        {
710          // prefix is 0 for default namespace
711          //
712          if (polymorphic_)
713          {
714            // Here we assume the prefixes are removed in the reverse
715            // order of them being added. This appears to how every
716            // sensible implementation works.
717            //
718            assert (p
719                    ? ns_decls_.back ().prefix == p
720                    : ns_decls_.back ().prefix.empty ());
721
722            ns_decls_.pop_back ();
723          }
724        }
725      }
726    }
727  }
728}
Note: See TracBrowser for help on using the browser.