root/win32/xsd-3.1.0-i686/libxsd/xsd/cxx/parser/validating/xml-schema-pimpl.txx @ 111

Revision 111, 64.3 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/validating/xml-schema-pimpl.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 <limits>
7#include <locale>
8
9#include <xsd/cxx/zc-istream.hxx>
10#include <xsd/cxx/parser/validating/exceptions.hxx>
11
12namespace xsd
13{
14  namespace cxx
15  {
16    namespace parser
17    {
18      namespace validating
19      {
20        // Note that most of the types implemented here cannot have
21        // whitespaces in the value. As result we don't need to waste
22        // time collapsing whitespaces. All we need to do is trim the
23        // string representation which can be done without copying.
24        //
25
26        // Character table.
27        //
28        namespace bits
29        {
30          const unsigned char ncname_mask     = 0x1;
31          const unsigned char name_first_mask = 0x2;
32          const unsigned char name_mask       = 0x4;
33
34          template <typename C>
35          struct char_table
36          {
37            static C table[0x80];
38          };
39
40          template <typename C>
41          C char_table<C>::table[0x80] =
42          {
43            0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0xD0, 0x00, 0x00, 0xD0, 0x00, 0x00,
44            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45            0xD8, 0x48, 0x58, 0x48, 0x48, 0x48, 0x40, 0x58, 0x48, 0x48, 0x48, 0x48, 0x48, 0x4D, 0x4D, 0x58,
46            0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4D, 0x4E, 0x48, 0x50, 0x48, 0x58, 0x48,
47            0x48, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F,
48            0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x48, 0x48, 0x40, 0x48, 0x4F,
49            0x48, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F,
50            0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x48, 0x48, 0x48, 0x48, 0x48
51          };
52        }
53
54        // any_type
55        //
56
57        template <typename C>
58        void any_type_pimpl<C>::
59        post_any_type ()
60        {
61        }
62
63        // any_simple_type
64        //
65
66        template <typename C>
67        void any_simple_type_pimpl<C>::
68        post_any_simple_type ()
69        {
70        }
71
72        // boolean
73        //
74
75        template <typename C>
76        void boolean_pimpl<C>::
77        _pre ()
78        {
79          str_.clear ();
80        }
81
82        template <typename C>
83        void boolean_pimpl<C>::
84        _characters (const ro_string<C>& s)
85        {
86          str_ += s;
87        }
88
89        template <typename C>
90        void boolean_pimpl<C>::
91        _post ()
92        {
93          ro_string<C> str (str_);
94          trim (str);
95
96          if (str == bits::true_<C> () || str == bits::one<C> ())
97            value_ = true;
98          else if (str == bits::false_<C> () || str == bits::zero<C> ())
99            value_ = false;
100          else
101            throw invalid_value<C> (bits::boolean<C> (), str);
102        }
103
104        template <typename C>
105        bool boolean_pimpl<C>::
106        post_boolean ()
107        {
108          return value_;
109        }
110
111        // byte
112        //
113
114        template <typename C>
115        void byte_pimpl<C>::
116        _pre ()
117        {
118          str_.clear ();
119        }
120
121        template <typename C>
122        void byte_pimpl<C>::
123        _characters (const ro_string<C>& s)
124        {
125          str_ += s;
126        }
127
128        template <typename C>
129        void byte_pimpl<C>::
130        _post ()
131        {
132          ro_string<C> str (str_);
133          trim (str);
134
135          short t;
136          zc_istream<C> is (str);
137
138          if (is >> t && is.exhausted () && t >= -128 && t <= 127)
139            value_ = static_cast<signed char> (t);
140          else
141            throw invalid_value<C> (bits::byte<C> (), str);
142        }
143
144        template <typename C>
145        signed char byte_pimpl<C>::
146        post_byte ()
147        {
148          return value_;
149        }
150
151        // unsigned_byte
152        //
153
154        template <typename C>
155        void unsigned_byte_pimpl<C>::
156        _pre ()
157        {
158          str_.clear ();
159        }
160
161        template <typename C>
162        void unsigned_byte_pimpl<C>::
163        _characters (const ro_string<C>& s)
164        {
165          str_ += s;
166        }
167
168        template <typename C>
169        void unsigned_byte_pimpl<C>::
170        _post ()
171        {
172          ro_string<C> str (str_);
173          trim (str);
174
175          unsigned short t;
176          zc_istream<C> is (str);
177
178          if (is >> t && is.exhausted () && t <= 255)
179            value_ = static_cast<unsigned char> (t);
180          else
181            throw invalid_value<C> (bits::unsigned_byte<C> (), str);
182        }
183
184        template <typename C>
185        unsigned char unsigned_byte_pimpl<C>::
186        post_unsigned_byte ()
187        {
188          return value_;
189        }
190
191        // short
192        //
193
194        template <typename C>
195        void short_pimpl<C>::
196        _pre ()
197        {
198          str_.clear ();
199        }
200
201        template <typename C>
202        void short_pimpl<C>::
203        _characters (const ro_string<C>& s)
204        {
205          str_ += s;
206        }
207
208        template <typename C>
209        void short_pimpl<C>::
210        _post ()
211        {
212          ro_string<C> str (str_);
213          trim (str);
214
215          zc_istream<C> is (str);
216
217          if (!(is >> value_ && is.exhausted ()))
218            throw invalid_value<C> (bits::short_<C> (), str);
219        }
220
221        template <typename C>
222        short short_pimpl<C>::
223        post_short ()
224        {
225          return value_;
226        }
227
228
229        // unsigned_short
230        //
231
232        template <typename C>
233        void unsigned_short_pimpl<C>::
234        _pre ()
235        {
236          str_.clear ();
237        }
238
239        template <typename C>
240        void unsigned_short_pimpl<C>::
241        _characters (const ro_string<C>& s)
242        {
243          str_ += s;
244        }
245
246        template <typename C>
247        void unsigned_short_pimpl<C>::
248        _post ()
249        {
250          ro_string<C> str (str_);
251          trim (str);
252
253          zc_istream<C> is (str);
254
255          if (!(is >> value_ && is.exhausted ()))
256            throw invalid_value<C> (bits::unsigned_short<C> (), str);
257        }
258
259        template <typename C>
260        unsigned short unsigned_short_pimpl<C>::
261        post_unsigned_short ()
262        {
263          return value_;
264        }
265
266        // int
267        //
268
269        template <typename C>
270        void int_pimpl<C>::
271        _pre ()
272        {
273          str_.clear ();
274        }
275
276        template <typename C>
277        void int_pimpl<C>::
278        _characters (const ro_string<C>& s)
279        {
280          str_ += s;
281        }
282
283        template <typename C>
284        void int_pimpl<C>::
285        _post ()
286        {
287          ro_string<C> str (str_);
288          trim (str);
289
290          zc_istream<C> is (str);
291
292          if (!(is >> value_ && is.exhausted ()))
293            throw invalid_value<C> (bits::int_<C> (), str);
294        }
295
296        template <typename C>
297        int int_pimpl<C>::
298        post_int ()
299        {
300          return value_;
301        }
302
303
304        // unsigned_int
305        //
306
307        template <typename C>
308        void unsigned_int_pimpl<C>::
309        _pre ()
310        {
311          str_.clear ();
312        }
313
314        template <typename C>
315        void unsigned_int_pimpl<C>::
316        _characters (const ro_string<C>& s)
317        {
318          str_ += s;
319        }
320
321        template <typename C>
322        void unsigned_int_pimpl<C>::
323        _post ()
324        {
325          ro_string<C> str (str_);
326          trim (str);
327
328          zc_istream<C> is (str);
329
330          if (!(is >> value_ && is.exhausted ()))
331            throw invalid_value<C> (bits::unsigned_int<C> (), str);
332        }
333
334        template <typename C>
335        unsigned int unsigned_int_pimpl<C>::
336        post_unsigned_int ()
337        {
338          return value_;
339        }
340
341
342        // long
343        //
344        template <typename C>
345        void long_pimpl<C>::
346        _pre ()
347        {
348          str_.clear ();
349        }
350
351        template <typename C>
352        void long_pimpl<C>::
353        _characters (const ro_string<C>& s)
354        {
355          str_ += s;
356        }
357
358        template <typename C>
359        void long_pimpl<C>::
360        _post ()
361        {
362          ro_string<C> str (str_);
363          trim (str);
364
365          zc_istream<C> is (str);
366
367          if (!(is >> value_ && is.exhausted ()))
368            throw invalid_value<C> (bits::long_<C> (), str);
369        }
370
371        template <typename C>
372        long long long_pimpl<C>::
373        post_long ()
374        {
375          return value_;
376        }
377
378        // unsigned_long
379        //
380        template <typename C>
381        void unsigned_long_pimpl<C>::
382        _pre ()
383        {
384          str_.clear ();
385        }
386
387        template <typename C>
388        void unsigned_long_pimpl<C>::
389        _characters (const ro_string<C>& s)
390        {
391          str_ += s;
392        }
393
394        template <typename C>
395        void unsigned_long_pimpl<C>::
396        _post ()
397        {
398          ro_string<C> str (str_);
399          trim (str);
400
401          zc_istream<C> is (str);
402
403          if (!(is >> value_ && is.exhausted ()))
404            throw invalid_value<C> (bits::unsigned_long<C> (), str);
405        }
406
407        template <typename C>
408        unsigned long long unsigned_long_pimpl<C>::
409        post_unsigned_long ()
410        {
411          return value_;
412        }
413
414
415        // integer
416        //
417        template <typename C>
418        void integer_pimpl<C>::
419        _pre ()
420        {
421          str_.clear ();
422        }
423
424        template <typename C>
425        void integer_pimpl<C>::
426        _characters (const ro_string<C>& s)
427        {
428          str_ += s;
429        }
430
431        template <typename C>
432        void integer_pimpl<C>::
433        _post ()
434        {
435          ro_string<C> str (str_);
436          trim (str);
437
438          zc_istream<C> is (str);
439
440          if (!(is >> value_ && is.exhausted ()))
441            throw invalid_value<C> (bits::integer<C> (), str);
442        }
443
444        template <typename C>
445        long long integer_pimpl<C>::
446        post_integer ()
447        {
448          return value_;
449        }
450
451        // negative_integer
452        //
453        template <typename C>
454        void negative_integer_pimpl<C>::
455        _pre ()
456        {
457          str_.clear ();
458        }
459
460        template <typename C>
461        void negative_integer_pimpl<C>::
462        _characters (const ro_string<C>& s)
463        {
464          str_ += s;
465        }
466
467        template <typename C>
468        void negative_integer_pimpl<C>::
469        _post ()
470        {
471          ro_string<C> str (str_);
472          trim (str);
473
474          zc_istream<C> is (str);
475
476          if (!(is >> value_ && is.exhausted () && value_ < 0))
477            throw invalid_value<C> (bits::negative_integer<C> (), str);
478        }
479
480        template <typename C>
481        long long negative_integer_pimpl<C>::
482        post_negative_integer ()
483        {
484          return value_;
485        }
486
487
488        // non_positive_integer
489        //
490        template <typename C>
491        void non_positive_integer_pimpl<C>::
492        _pre ()
493        {
494          str_.clear ();
495        }
496
497        template <typename C>
498        void non_positive_integer_pimpl<C>::
499        _characters (const ro_string<C>& s)
500        {
501          str_ += s;
502        }
503
504        template <typename C>
505        void non_positive_integer_pimpl<C>::
506        _post ()
507        {
508          ro_string<C> str (str_);
509          trim (str);
510
511          zc_istream<C> is (str);
512
513          if (!(is >> value_ && is.exhausted () && value_ <= 0))
514            throw invalid_value<C> (bits::non_positive_integer<C> (), str);
515        }
516
517        template <typename C>
518        long long non_positive_integer_pimpl<C>::
519        post_non_positive_integer ()
520        {
521          return value_;
522        }
523
524        // positive_integer
525        //
526        template <typename C>
527        void positive_integer_pimpl<C>::
528        _pre ()
529        {
530          str_.clear ();
531        }
532
533        template <typename C>
534        void positive_integer_pimpl<C>::
535        _characters (const ro_string<C>& s)
536        {
537          str_ += s;
538        }
539
540        template <typename C>
541        void positive_integer_pimpl<C>::
542        _post ()
543        {
544          ro_string<C> str (str_);
545          trim (str);
546
547          zc_istream<C> is (str);
548
549          if (!(is >> value_ && is.exhausted () && value_ > 0))
550            throw invalid_value<C> (bits::positive_integer<C> (), str);
551        }
552
553        template <typename C>
554        unsigned long long positive_integer_pimpl<C>::
555        post_positive_integer ()
556        {
557          return value_;
558        }
559
560
561        // non_negative_integer
562        //
563        template <typename C>
564        void non_negative_integer_pimpl<C>::
565        _pre ()
566        {
567          str_.clear ();
568        }
569
570        template <typename C>
571        void non_negative_integer_pimpl<C>::
572        _characters (const ro_string<C>& s)
573        {
574          str_ += s;
575        }
576
577        template <typename C>
578        void non_negative_integer_pimpl<C>::
579        _post ()
580        {
581          ro_string<C> str (str_);
582          trim (str);
583
584          zc_istream<C> is (str);
585
586          if (!(is >> value_ && is.exhausted ()))
587            throw invalid_value<C> (bits::non_negative_integer<C> (), str);
588        }
589
590        template <typename C>
591        unsigned long long non_negative_integer_pimpl<C>::
592        post_non_negative_integer ()
593        {
594          return value_;
595        }
596
597
598        // float
599        //
600        template <typename C>
601        void float_pimpl<C>::
602        _pre ()
603        {
604          str_.clear ();
605        }
606
607        template <typename C>
608        void float_pimpl<C>::
609        _characters (const ro_string<C>& s)
610        {
611          str_ += s;
612        }
613
614        template <typename C>
615        void float_pimpl<C>::
616        _post ()
617        {
618          ro_string<C> str (str_);
619          trim (str);
620
621          if (str == bits::positive_inf<C> ())
622            value_ = std::numeric_limits<float>::infinity ();
623          else if (str == bits::negative_inf<C> ())
624            value_ = -std::numeric_limits<float>::infinity ();
625          else if (str == bits::nan<C> ())
626            value_ = std::numeric_limits<float>::quiet_NaN ();
627          else
628          {
629            zc_istream<C> is (str);
630            is.imbue (std::locale::classic ());
631
632            if (!(is >> value_ && is.exhausted ()))
633              throw invalid_value<C> (bits::float_<C> (), str);
634          }
635        }
636
637        template <typename C>
638        float float_pimpl<C>::
639        post_float ()
640        {
641          return value_;
642        }
643
644
645        // double
646        //
647        template <typename C>
648        void double_pimpl<C>::
649        _pre ()
650        {
651          str_.clear ();
652        }
653
654        template <typename C>
655        void double_pimpl<C>::
656        _characters (const ro_string<C>& s)
657        {
658          str_ += s;
659        }
660
661        template <typename C>
662        void double_pimpl<C>::
663        _post ()
664        {
665          ro_string<C> str (str_);
666          trim (str);
667
668          if (str == bits::positive_inf<C> ())
669            value_ = std::numeric_limits<double>::infinity ();
670          else if (str == bits::negative_inf<C> ())
671            value_ = -std::numeric_limits<double>::infinity ();
672          else if (str == bits::nan<C> ())
673            value_ = std::numeric_limits<double>::quiet_NaN ();
674          else
675          {
676            zc_istream<C> is (str);
677            is.imbue (std::locale::classic ());
678
679            if (!(is >> value_ && is.exhausted ()))
680              throw invalid_value<C> (bits::double_<C> (), str);
681          }
682        }
683
684        template <typename C>
685        double double_pimpl<C>::
686        post_double ()
687        {
688          return value_;
689        }
690
691        // decimal
692        //
693        template <typename C>
694        void decimal_pimpl<C>::
695        _pre ()
696        {
697          str_.clear ();
698        }
699
700        template <typename C>
701        void decimal_pimpl<C>::
702        _characters (const ro_string<C>& s)
703        {
704          str_ += s;
705        }
706
707        template <typename C>
708        void decimal_pimpl<C>::
709        _post ()
710        {
711          ro_string<C> str (str_);
712          trim (str);
713
714          zc_istream<C> is (str);
715          is.imbue (std::locale::classic ());
716
717          //@@ TODO: now we accept scientific notations and INF/NaN.
718          //
719          if (!(is >> value_ && is.exhausted ()))
720            throw invalid_value<C> (bits::decimal<C> (), str);
721        }
722
723        template <typename C>
724        double decimal_pimpl<C>::
725        post_decimal ()
726        {
727          return value_;
728        }
729
730        // string
731        //
732        template <typename C>
733        void string_pimpl<C>::
734        _pre ()
735        {
736          str_.clear ();
737        }
738
739        template <typename C>
740        void string_pimpl<C>::
741        _characters (const ro_string<C>& s)
742        {
743          str_ += s;
744        }
745
746        template <typename C>
747        std::basic_string<C> string_pimpl<C>::
748        post_string ()
749        {
750          std::basic_string<C> r;
751          r.swap (str_);
752          return r;
753        }
754
755        // normalized_string
756        //
757        template <typename C>
758        void normalized_string_pimpl<C>::
759        _pre ()
760        {
761          str_.clear ();
762        }
763
764        template <typename C>
765        void normalized_string_pimpl<C>::
766        _characters (const ro_string<C>& s)
767        {
768          str_ += s;
769        }
770
771        template <typename C>
772        std::basic_string<C> normalized_string_pimpl<C>::
773        post_normalized_string ()
774        {
775          typedef typename std::basic_string<C>::size_type size_type;
776
777          size_type size (str_.size ());
778
779          for (size_type i (0); i < size; ++i)
780          {
781            C& c = str_[i];
782
783            if (c == C (0x0A) || c == C (0x0D) || c == C (0x09))
784              c = C (0x20);
785          }
786
787          std::basic_string<C> r;
788          r.swap (str_);
789          return r;
790        }
791
792        // token
793        //
794        template <typename C>
795        void token_pimpl<C>::
796        _pre ()
797        {
798          str_.clear ();
799        }
800
801        template <typename C>
802        void token_pimpl<C>::
803        _characters (const ro_string<C>& s)
804        {
805          if (str_.size () == 0)
806          {
807            ro_string<C> tmp (s.data (), s.size ());
808
809            if (trim_left (tmp) != 0)
810              str_ += tmp;
811          }
812          else
813            str_ += s;
814        }
815
816        template <typename C>
817        std::basic_string<C> token_pimpl<C>::
818        post_token ()
819        {
820          typedef typename std::basic_string<C>::size_type size_type;
821
822          size_type size (str_.size ());
823          size_type j (0);
824
825          bool subs (false);
826
827          for (size_type i (0); i < size; ++i)
828          {
829            C c = str_[i];
830
831            if (c == C (0x20) || c == C (0x0A) ||
832                c == C (0x0D) || c == C (0x09))
833            {
834              subs = true;
835            }
836            else
837            {
838              if (subs)
839              {
840                subs = false;
841                str_[j++] = C (0x20);
842              }
843
844              str_[j++] = c;
845            }
846          }
847
848          str_.resize (j);
849
850          std::basic_string<C> r;
851          r.swap (str_);
852          return r;
853        }
854
855        // name
856        //
857        template <typename C>
858        void name_pimpl<C>::
859        _pre ()
860        {
861          str_.clear ();
862        }
863
864        template <typename C>
865        void name_pimpl<C>::
866        _characters (const ro_string<C>& s)
867        {
868          if (str_.size () == 0)
869          {
870            ro_string<C> tmp (s.data (), s.size ());
871
872            if (trim_left (tmp) != 0)
873              str_ += tmp;
874          }
875          else
876            str_ += s;
877        }
878
879        template <typename C>
880        void name_pimpl<C>::
881        _post ()
882        {
883          typedef typename ro_string<C>::size_type size_type;
884
885          ro_string<C> tmp (str_);
886          size_type size (trim_right (tmp));
887
888          // For now we are only checking the US-ASCII characters.
889          //
890
891          bool ok (size != 0);
892
893          if (ok)
894          {
895            unsigned int c (static_cast<unsigned int> (str_[0]));
896
897            ok = c >= 0x80 ||
898              (bits::char_table<unsigned char>::table[c] &
899               bits::name_first_mask);
900
901            if (ok)
902            {
903              for (size_type i (1); i < size; ++i)
904              {
905                c = static_cast<unsigned int> (str_[i]);
906
907                if (c < 0x80 &&
908                    !(bits::char_table<unsigned char>::table[c] &
909                      bits::name_mask))
910                {
911                  ok = false;
912                  break;
913                }
914              }
915            }
916          }
917
918          if (!ok)
919            throw invalid_value<C> (bits::name<C> (), tmp);
920
921          str_.resize (size);
922        }
923
924        template <typename C>
925        std::basic_string<C> name_pimpl<C>::
926        post_name ()
927        {
928          std::basic_string<C> r;
929          r.swap (str_);
930          return r;
931        }
932
933        // nmtoken
934        //
935        template <typename C>
936        void nmtoken_pimpl<C>::
937        _pre ()
938        {
939          str_.clear ();
940        }
941
942        template <typename C>
943        void nmtoken_pimpl<C>::
944        _characters (const ro_string<C>& s)
945        {
946          if (str_.size () == 0)
947          {
948            ro_string<C> tmp (s.data (), s.size ());
949
950            if (trim_left (tmp) != 0)
951              str_ += tmp;
952          }
953          else
954            str_ += s;
955        }
956
957        template <typename C>
958        void nmtoken_pimpl<C>::
959        _post ()
960        {
961          typedef typename ro_string<C>::size_type size_type;
962
963          ro_string<C> tmp (str_);
964          size_type size (trim_right (tmp));
965
966          // For now we are only checking the US-ASCII characters.
967          //
968
969          bool ok (size != 0);
970
971          if (ok)
972          {
973            for (size_type i (0); i < size; ++i)
974            {
975              unsigned int c (static_cast<unsigned int> (str_[i]));
976
977              if (c < 0x80 &&
978                  !(bits::char_table<unsigned char>::table[c] &
979                    bits::name_mask))
980              {
981                ok = false;
982                break;
983              }
984            }
985          }
986
987          if (!ok)
988            throw invalid_value<C> (bits::nmtoken<C> (), tmp);
989
990          str_.resize (size);
991        }
992
993        template <typename C>
994        std::basic_string<C> nmtoken_pimpl<C>::
995        post_nmtoken ()
996        {
997          std::basic_string<C> r;
998          r.swap (str_);
999          return r;
1000        }
1001
1002        // nmtokens
1003        //
1004        template <typename C>
1005        void nmtokens_pimpl<C>::
1006        _pre ()
1007        {
1008          nmtokens_pskel<C>::_pre ();
1009          seq_.clear ();
1010        }
1011
1012        template <typename C>
1013        void nmtokens_pimpl<C>::
1014        _post ()
1015        {
1016          nmtokens_pskel<C>::_post ();
1017
1018          // Should have at least one element.
1019          //
1020          if (seq_.size () < 1)
1021          {
1022            ro_string<C> tmp;
1023            throw invalid_value<C> (bits::nmtokens<C> (), tmp);
1024          }
1025        }
1026
1027        template <typename C>
1028        string_sequence<C> nmtokens_pimpl<C>::
1029        post_nmtokens ()
1030        {
1031          string_sequence<C> r;
1032          r.swap (seq_);
1033          return r;
1034        }
1035
1036        template <typename C>
1037        void nmtokens_pimpl<C>::
1038        _xsd_parse_item (const ro_string<C>& s)
1039        {
1040          parser_.pre ();
1041          parser_._pre ();
1042          parser_._characters (s);
1043          parser_._post ();
1044          seq_.push_back (parser_.post_nmtoken ());
1045        }
1046
1047        // ncname
1048        //
1049        namespace bits
1050        {
1051          template <typename C>
1052          bool
1053          valid_ncname (const C* s, typename ro_string<C>::size_type size)
1054          {
1055            typedef typename ro_string<C>::size_type size_type;
1056
1057            // For now we are only checking the US-ASCII characters.
1058            //
1059            bool ok (size != 0);
1060
1061            if (ok)
1062            {
1063              unsigned int c (static_cast<unsigned int> (s[0]));
1064
1065              ok = c >= 0x80 ||
1066                ((bits::char_table<unsigned char>::table[c] &
1067                  bits::name_first_mask) && c != C (':'));
1068
1069              if (ok)
1070              {
1071                for (size_type i (1); i < size; ++i)
1072                {
1073                  c = static_cast<unsigned int> (s[i]);
1074
1075                  if (c < 0x80 &&
1076                      !(bits::char_table<unsigned char>::table[c] &
1077                        bits::ncname_mask))
1078                  {
1079                    ok = false;
1080                    break;
1081                  }
1082                }
1083              }
1084            }
1085
1086            return ok;
1087          }
1088        }
1089
1090        template <typename C>
1091        void ncname_pimpl<C>::
1092        _pre ()
1093        {
1094          str_.clear ();
1095        }
1096
1097        template <typename C>
1098        void ncname_pimpl<C>::
1099        _characters (const ro_string<C>& s)
1100        {
1101          if (str_.size () == 0)
1102          {
1103            ro_string<C> tmp (s.data (), s.size ());
1104
1105            if (trim_left (tmp) != 0)
1106              str_ += tmp;
1107          }
1108          else
1109            str_ += s;
1110        }
1111
1112        template <typename C>
1113        void ncname_pimpl<C>::
1114        _post ()
1115        {
1116          typedef typename ro_string<C>::size_type size_type;
1117
1118          ro_string<C> tmp (str_);
1119          size_type size (trim_right (tmp));
1120
1121          if (!bits::valid_ncname (tmp.data (), size))
1122            throw invalid_value<C> (bits::ncname<C> (), tmp);
1123
1124          str_.resize (size);
1125        }
1126
1127        template <typename C>
1128        std::basic_string<C> ncname_pimpl<C>::
1129        post_ncname ()
1130        {
1131          std::basic_string<C> r;
1132          r.swap (str_);
1133          return r;
1134        }
1135
1136        // id
1137        //
1138        template <typename C>
1139        std::basic_string<C> id_pimpl<C>::
1140        post_id ()
1141        {
1142          return this->post_ncname ();
1143        }
1144
1145        // idref
1146        //
1147        template <typename C>
1148        std::basic_string<C> idref_pimpl<C>::
1149        post_idref ()
1150        {
1151          return this->post_ncname ();
1152        }
1153
1154        // idrefs
1155        //
1156        template <typename C>
1157        void idrefs_pimpl<C>::
1158        _pre ()
1159        {
1160          idrefs_pskel<C>::_pre ();
1161          seq_.clear ();
1162        }
1163
1164        template <typename C>
1165        void idrefs_pimpl<C>::
1166        _post ()
1167        {
1168          idrefs_pskel<C>::_post ();
1169
1170          // Should have at least one element.
1171          //
1172          if (seq_.size () < 1)
1173          {
1174            ro_string<C> tmp;
1175            throw invalid_value<C> (bits::idrefs<C> (), tmp);
1176          }
1177        }
1178
1179        template <typename C>
1180        string_sequence<C> idrefs_pimpl<C>::
1181        post_idrefs ()
1182        {
1183          string_sequence<C> r;
1184          r.swap (seq_);
1185          return r;
1186        }
1187
1188        template <typename C>
1189        void idrefs_pimpl<C>::
1190        _xsd_parse_item (const ro_string<C>& s)
1191        {
1192          parser_.pre ();
1193          parser_._pre ();
1194          parser_._characters (s);
1195          parser_._post ();
1196          seq_.push_back (parser_.post_idref ());
1197        }
1198
1199        // language
1200        //
1201        template <typename C>
1202        void language_pimpl<C>::
1203        _pre ()
1204        {
1205          str_.clear ();
1206        }
1207
1208        template <typename C>
1209        void language_pimpl<C>::
1210        _characters (const ro_string<C>& s)
1211        {
1212          if (str_.size () == 0)
1213          {
1214            ro_string<C> tmp (s.data (), s.size ());
1215
1216            if (trim_left (tmp) != 0)
1217              str_ += tmp;
1218          }
1219          else
1220            str_ += s;
1221        }
1222
1223        template <typename C>
1224        void language_pimpl<C>::
1225        _post ()
1226        {
1227          typedef typename ro_string<C>::size_type size_type;
1228
1229          ro_string<C> tmp (str_);
1230          size_type size (trim_right (tmp));
1231
1232          // language := ALPHA{1,8} *(-(ALPHA | DIGIT){1,8})
1233          //
1234          bool ok (true);
1235
1236          for (size_type tag (0), i (0); ; ++tag)
1237          {
1238            size_type n (0);
1239
1240            for (; i < size && n < 8; ++n, ++i)
1241            {
1242              C c (tmp[i]);
1243
1244              if (!((c >= C ('a') && c <= C ('z')) ||
1245                    (c >= C ('A') && c <= C ('Z')) ||
1246                    (tag != 0 && c >= C ('0') && c <= C ('9'))))
1247                break;
1248            }
1249
1250            if (n == 0)
1251            {
1252              ok = false;
1253              break;
1254            }
1255
1256            if (i == size)
1257              break;
1258
1259            if (tmp[i++] != C ('-'))
1260            {
1261              ok = false;
1262              break;
1263            }
1264          }
1265
1266          if (!ok)
1267            throw invalid_value<C> (bits::language<C> (), tmp);
1268
1269          str_.resize (size);
1270        }
1271
1272        template <typename C>
1273        std::basic_string<C> language_pimpl<C>::
1274        post_language ()
1275        {
1276          std::basic_string<C> r;
1277          r.swap (str_);
1278          return r;
1279        }
1280
1281        // uri
1282        //
1283        template <typename C>
1284        void uri_pimpl<C>::
1285        _pre ()
1286        {
1287          str_.clear ();
1288        }
1289
1290        template <typename C>
1291        void uri_pimpl<C>::
1292        _characters (const ro_string<C>& s)
1293        {
1294          if (str_.size () == 0)
1295          {
1296            ro_string<C> tmp (s.data (), s.size ());
1297
1298            if (trim_left (tmp) != 0)
1299              str_ += tmp;
1300          }
1301          else
1302            str_ += s;
1303        }
1304
1305        template <typename C>
1306        std::basic_string<C> uri_pimpl<C>::
1307        post_uri ()
1308        {
1309          // According to Datatypes 3.2.17 and RFC2396 pretty much anything
1310          // can be a URI and conforming processors do not need to figure
1311          // out and verify particular URI schemes.
1312          //
1313          ro_string<C> tmp (str_);
1314          str_.resize (trim_right (tmp));
1315
1316          std::basic_string<C> r;
1317          r.swap (str_);
1318          return r;
1319        }
1320
1321        // qname
1322        //
1323        template <typename C>
1324        void qname_pimpl<C>::
1325        _pre ()
1326        {
1327          str_.clear ();
1328        }
1329
1330        template <typename C>
1331        void qname_pimpl<C>::
1332        _characters (const ro_string<C>& s)
1333        {
1334          if (str_.size () == 0)
1335          {
1336            ro_string<C> tmp (s.data (), s.size ());
1337
1338            if (trim_left (tmp) != 0)
1339              str_ += tmp;
1340          }
1341          else
1342            str_ += s;
1343        }
1344
1345        template <typename C>
1346        void qname_pimpl<C>::
1347        _post ()
1348        {
1349          typedef typename ro_string<C>::size_type size_type;
1350
1351          ro_string<C> tmp (str_);
1352          size_type size (trim_right (tmp));
1353          size_type pos (tmp.find (C (':')));
1354
1355          const C* s (tmp.data ());
1356
1357          if (pos != ro_string<C>::npos)
1358          {
1359            if (!bits::valid_ncname (s, pos) ||
1360                !bits::valid_ncname (s + pos + 1, size - pos - 1))
1361              throw invalid_value<C> (bits::qname<C> (), tmp);
1362
1363            prefix_.assign (s, pos);
1364            name_.assign (s + pos + 1, size - pos - 1);
1365          }
1366          else
1367          {
1368            if (!bits::valid_ncname (s, size))
1369              throw invalid_value<C> (bits::qname<C> (), tmp);
1370
1371            prefix_.clear ();
1372            str_.resize (size);
1373            name_.swap (str_);
1374          }
1375        }
1376
1377        template <typename C>
1378        qname<C> qname_pimpl<C>::
1379        post_qname ()
1380        {
1381          return prefix_.empty ()
1382            ? qname<C> (name_)
1383            : qname<C> (prefix_, name_);
1384        }
1385
1386        // base64_binary
1387        //
1388        template <typename C>
1389        void base64_binary_pimpl<C>::
1390        _pre ()
1391        {
1392          str_.clear ();
1393        }
1394
1395        template <typename C>
1396        void base64_binary_pimpl<C>::
1397        _characters (const ro_string<C>& s)
1398        {
1399          if (str_.size () == 0)
1400          {
1401            ro_string<C> tmp (s.data (), s.size ());
1402
1403            if (trim_left (tmp) != 0)
1404              str_ += tmp;
1405          }
1406          else
1407            str_ += s;
1408        }
1409
1410        namespace bits
1411        {
1412          template <typename C>
1413          inline unsigned char
1414          base64_decode (C c)
1415          {
1416            unsigned char r (0xFF);
1417
1418            if (c >= C('A') && c <= C ('Z'))
1419              r = static_cast<unsigned char> (c - C ('A'));
1420            else if (c >= C('a') && c <= C ('z'))
1421              r = static_cast<unsigned char> (c - C ('a') + 26);
1422            else if (c >= C('0') && c <= C ('9'))
1423              r = static_cast<unsigned char> (c - C ('0') + 52);
1424            else if (c == C ('+'))
1425              r = 62;
1426            else if (c == C ('/'))
1427              r = 63;
1428
1429            return r;
1430          }
1431        }
1432
1433        template <typename C>
1434        void base64_binary_pimpl<C>::
1435        _post ()
1436        {
1437          typedef typename std::basic_string<C>::size_type size_type;
1438
1439          size_type size (str_.size ());
1440          const C* src (str_.c_str ());
1441
1442          // Remove all whitespaces.
1443          //
1444          {
1445            size_type j (0);
1446
1447            bool subs (false);
1448
1449            for (size_type i (0); i < size; ++i)
1450            {
1451              C c = str_[i];
1452
1453              if (c == C (0x20) || c == C (0x0A) ||
1454                  c == C (0x0D) || c == C (0x09))
1455              {
1456                subs = true;
1457              }
1458              else
1459              {
1460                if (subs)
1461                  subs = false;
1462
1463                str_[j++] = c;
1464              }
1465            }
1466
1467            size = j;
1468            str_.resize (size);
1469          }
1470
1471          // Our length should be a multiple of four.
1472          //
1473          if (size == 0 || size % 4 != 0)
1474            throw invalid_value<C> (bits::base64_binary<C> (), str_);
1475
1476          size_type quad_count (size / 4);
1477          size_type capacity (quad_count * 3 + 1);
1478
1479          buf_.reset (new buffer (capacity, capacity));
1480          char* dst (buf_->data ());
1481
1482          size_type si (0), di (0); // Source and destination indexes.
1483
1484          // Process all quads except the last one.
1485          //
1486          unsigned char b1, b2, b3, b4;
1487
1488          for (size_type q (0); q < quad_count - 1; ++q)
1489          {
1490            b1 = bits::base64_decode (src[si++]);
1491            b2 = bits::base64_decode (src[si++]);
1492            b3 = bits::base64_decode (src[si++]);
1493            b4 = bits::base64_decode (src[si++]);
1494
1495            if (b1 == 0xFF || b2 == 0xFF || b3 == 0xFF || b4 == 0xFF)
1496              throw invalid_value<C> (bits::base64_binary<C> (), str_);
1497
1498            dst[di++] = (b1 << 2) | (b2 >> 4);
1499            dst[di++] = (b2 << 4) | (b3 >> 2);
1500            dst[di++] = (b3 << 6) | b4;
1501          }
1502
1503          // Process the last quad. The first two octets are always there.
1504          //
1505          b1 = bits::base64_decode (src[si++]);
1506          b2 = bits::base64_decode (src[si++]);
1507
1508          if (b1 == 0xFF || b2 == 0xFF)
1509            throw invalid_value<C> (bits::base64_binary<C> (), str_);
1510
1511          C e3 (src[si++]);
1512          C e4 (src[si++]);
1513
1514          if (e4 == C ('='))
1515          {
1516            if (e3 == C ('='))
1517            {
1518              // Two pads. Last 4 bits in b2 should be zero.
1519              //
1520              if ((b2 & 0x0F) != 0)
1521                throw invalid_value<C> (bits::base64_binary<C> (), str_);
1522
1523              dst[di++] = (b1 << 2) | (b2 >> 4);
1524            }
1525            else
1526            {
1527              // One pad. Last 2 bits in b3 should be zero.
1528              //
1529              b3 = bits::base64_decode (e3);
1530
1531              if (b3 == 0xFF || (b3 & 0x03) != 0)
1532                throw invalid_value<C> (bits::base64_binary<C> (), str_);
1533
1534              dst[di++] = (b1 << 2) | (b2 >> 4);
1535              dst[di++] = (b2 << 4) | (b3 >> 2);
1536            }
1537          }
1538          else
1539          {
1540            // No pads.
1541            //
1542            b3 = bits::base64_decode (e3);
1543            b4 = bits::base64_decode (e4);
1544
1545            if (b3 == 0xFF || b4 == 0xFF)
1546              throw invalid_value<C> (bits::base64_binary<C> (), str_);
1547
1548            dst[di++] = (b1 << 2) | (b2 >> 4);
1549            dst[di++] = (b2 << 4) | (b3 >> 2);
1550            dst[di++] = (b3 << 6) | b4;
1551          }
1552
1553          // Set the real size.
1554          //
1555          buf_->size (di);
1556        }
1557
1558        template <typename C>
1559        std::auto_ptr<buffer> base64_binary_pimpl<C>::
1560        post_base64_binary ()
1561        {
1562          return buf_;
1563        }
1564
1565        // hex_binary
1566        //
1567        template <typename C>
1568        void hex_binary_pimpl<C>::
1569        _pre ()
1570        {
1571          str_.clear ();
1572        }
1573
1574        template <typename C>
1575        void hex_binary_pimpl<C>::
1576        _characters (const ro_string<C>& s)
1577        {
1578          if (str_.size () == 0)
1579          {
1580            ro_string<C> tmp (s.data (), s.size ());
1581
1582            if (trim_left (tmp) != 0)
1583              str_ += tmp;
1584          }
1585          else
1586            str_ += s;
1587        }
1588
1589        namespace bits
1590        {
1591          template <typename C>
1592          inline unsigned char
1593          hex_decode (C c)
1594          {
1595            unsigned char r (0xFF);
1596
1597            if (c >= C('0') && c <= C ('9'))
1598              r = static_cast<unsigned char> (c - C ('0'));
1599            else if (c >= C ('A') && c <= C ('F'))
1600              r = static_cast<unsigned char> (10 + (c - C ('A')));
1601            else if (c >= C ('a') && c <= C ('f'))
1602              r = static_cast<unsigned char> (10 + (c - C ('a')));
1603
1604            return r;
1605          }
1606        }
1607
1608        template <typename C>
1609        void hex_binary_pimpl<C>::
1610        _post ()
1611        {
1612          typedef typename ro_string<C>::size_type size_type;
1613
1614          ro_string<C> tmp (str_);
1615          size_type size (trim_right (tmp));
1616
1617          if (size % 2 != 0)
1618            throw invalid_value<C> (bits::hex_binary<C> (), tmp);
1619
1620          buffer::size_t n (size / 2);
1621          buf_.reset (new buffer (n));
1622
1623          if (n != 0)
1624          {
1625            const C* src (tmp.data ());
1626            char* dst (buf_->data ());
1627            buffer::size_t i (0);
1628
1629            for (; i < n; ++i)
1630            {
1631              unsigned char h (bits::hex_decode (src[2 * i]));
1632              unsigned char l (bits::hex_decode (src[2 * i + 1]));
1633
1634              if (h == 0xFF || l == 0xFF)
1635                break;
1636
1637              dst[i] = (h << 4) | l;
1638            }
1639
1640            if (i != n)
1641              throw invalid_value<C> (bits::hex_binary<C> (), tmp);
1642          }
1643        }
1644
1645        template <typename C>
1646        std::auto_ptr<buffer> hex_binary_pimpl<C>::
1647        post_hex_binary ()
1648        {
1649          return buf_;
1650        }
1651
1652        // time_zone
1653        //
1654        namespace bits
1655        {
1656          // Datatypes 3.2.7.3. Return false if time zone is invalid.
1657          //
1658          template <typename C>
1659          bool
1660          parse_tz (const C* s,
1661                    typename std::basic_string<C>::size_type n,
1662                    short& h, short& m)
1663          {
1664            // time_zone := Z|(+|-)HH:MM
1665            //
1666            if (n == 0)
1667            {
1668              return false;
1669            }
1670            else if (s[0] == 'Z')
1671            {
1672              if (n != 1)
1673                return false;
1674
1675              h = 0;
1676              m = 0;
1677            }
1678            else
1679            {
1680              if (n != 6 || (s[0] != '-' && s[0] != '+') || s[3] != ':')
1681                return false;
1682
1683              // Parse hours.
1684              //
1685              char d1 = s[1];
1686              char d2 = s[2];
1687
1688              if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
1689                return false;
1690
1691              h = 10 * (d1 - '0') + (d2 - '0');
1692
1693              if (h > 14)
1694                return false;
1695
1696              // Parse minutes.
1697              //
1698              d1 = s[4];
1699              d2 = s[5];
1700
1701              if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
1702                return false;
1703
1704              m = 10 * (d1 - '0') + (d2 - '0');
1705
1706              if (m > 59 || (h == 14 && m != 0))
1707                return false;
1708
1709              if (s[0] == '-')
1710              {
1711                h = -h;
1712                m = -m;
1713              }
1714            }
1715
1716            return true;
1717          }
1718        }
1719
1720        // gday
1721        //
1722        template <typename C>
1723        void gday_pimpl<C>::
1724        _pre ()
1725        {
1726          str_.clear ();
1727        }
1728
1729        template <typename C>
1730        void gday_pimpl<C>::
1731        _characters (const ro_string<C>& s)
1732        {
1733          if (str_.size () == 0)
1734          {
1735            ro_string<C> tmp (s.data (), s.size ());
1736
1737            if (trim_left (tmp) != 0)
1738              str_ += tmp;
1739          }
1740          else
1741            str_ += s;
1742        }
1743
1744        template <typename C>
1745        void gday_pimpl<C>::
1746        _post ()
1747        {
1748          typedef typename ro_string<C>::size_type size_type;
1749
1750          ro_string<C> tmp (str_);
1751          size_type size (trim_right (tmp));
1752          const C* s (tmp.data ());
1753
1754          // gday := ---DD[Z|(+|-)HH:MM]
1755          //
1756          if (size < 5 ||
1757              s[0] != C ('-') || s[1] != C ('-') || s[2] != C ('-'))
1758            throw invalid_value<C> (bits::gday<C> (), tmp);
1759
1760          C d1 (s[3]), d2 (s[4]);
1761
1762          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
1763            throw invalid_value<C> (bits::gday<C> (), tmp);
1764
1765          day_ = 10 * (d1 - '0') + (d2 - '0');
1766
1767          if (day_ < 1 || day_ > 31)
1768            throw invalid_value<C> (bits::gday<C> (), tmp);
1769
1770          if (size > 5)
1771          {
1772            if (!bits::parse_tz (s + 5, size - 5, zh_, zm_))
1773              throw invalid_value<C> (bits::gday<C> (), tmp);
1774
1775            z_ = true;
1776          }
1777          else
1778            z_ = false;
1779        }
1780
1781        template <typename C>
1782        gday gday_pimpl<C>::
1783        post_gday ()
1784        {
1785          return z_ ? gday (day_, zh_, zm_) : gday (day_);
1786        }
1787
1788        // gmonth
1789        //
1790        template <typename C>
1791        void gmonth_pimpl<C>::
1792        _pre ()
1793        {
1794          str_.clear ();
1795        }
1796
1797        template <typename C>
1798        void gmonth_pimpl<C>::
1799        _characters (const ro_string<C>& s)
1800        {
1801          if (str_.size () == 0)
1802          {
1803            ro_string<C> tmp (s.data (), s.size ());
1804
1805            if (trim_left (tmp) != 0)
1806              str_ += tmp;
1807          }
1808          else
1809            str_ += s;
1810        }
1811
1812        template <typename C>
1813        void gmonth_pimpl<C>::
1814        _post ()
1815        {
1816          typedef typename ro_string<C>::size_type size_type;
1817
1818          ro_string<C> tmp (str_);
1819          size_type size (trim_right (tmp));
1820          const C* s (tmp.data ());
1821
1822          // gmonth := --MM[Z|(+|-)HH:MM]
1823          //
1824          if (size < 4 || s[0] != C ('-') || s[1] != C ('-'))
1825            throw invalid_value<C> (bits::gmonth<C> (), tmp);
1826
1827          C d1 (s[2]), d2 (s[3]);
1828
1829          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
1830            throw invalid_value<C> (bits::gmonth<C> (), tmp);
1831
1832          month_ = 10 * (d1 - '0') + (d2 - '0');
1833
1834          if (month_ < 1 || month_ > 12)
1835            throw invalid_value<C> (bits::gmonth<C> (), tmp);
1836
1837          if (size > 4)
1838          {
1839            if (!bits::parse_tz (s + 4, size - 4, zh_, zm_))
1840              throw invalid_value<C> (bits::gmonth<C> (), tmp);
1841
1842            z_ = true;
1843          }
1844          else
1845            z_ = false;
1846        }
1847
1848        template <typename C>
1849        gmonth gmonth_pimpl<C>::
1850        post_gmonth ()
1851        {
1852          return z_ ? gmonth (month_, zh_, zm_) : gmonth (month_);
1853        }
1854
1855        // gyear
1856        //
1857        template <typename C>
1858        void gyear_pimpl<C>::
1859        _pre ()
1860        {
1861          str_.clear ();
1862        }
1863
1864        template <typename C>
1865        void gyear_pimpl<C>::
1866        _characters (const ro_string<C>& s)
1867        {
1868          if (str_.size () == 0)
1869          {
1870            ro_string<C> tmp (s.data (), s.size ());
1871
1872            if (trim_left (tmp) != 0)
1873              str_ += tmp;
1874          }
1875          else
1876            str_ += s;
1877        }
1878
1879        template <typename C>
1880        void gyear_pimpl<C>::
1881        _post ()
1882        {
1883          typedef typename ro_string<C>::size_type size_type;
1884
1885          ro_string<C> tmp (str_);
1886          size_type size (trim_right (tmp));
1887          const C* s (tmp.data ());
1888
1889          // gyear := [-]CCYY[N]*[Z|(+|-)HH:MM]
1890          //
1891
1892          if (size < 4 || (s[0] == C ('-') && size < 5))
1893            throw invalid_value<C> (bits::gyear<C> (), tmp);
1894
1895          // Find the end of the year token.
1896          //
1897          size_type pos (s[0] == C ('-') ? 5 : 4);
1898          for (; pos < size; ++pos)
1899          {
1900            C c (s[pos]);
1901
1902            if (c == C ('Z') || c == C ('+') || c == C ('-'))
1903              break;
1904          }
1905
1906          ro_string<C> year_fragment (s, pos);
1907          zc_istream<C> is (year_fragment);
1908
1909          if (!(is >> year_ && is.exhausted () && year_ != 0))
1910            throw invalid_value<C> (bits::gyear<C> (), tmp);
1911
1912          if (pos < size)
1913          {
1914            if (!bits::parse_tz (s + pos, size - pos, zh_, zm_))
1915              throw invalid_value<C> (bits::gyear<C> (), tmp);
1916
1917            z_ = true;
1918          }
1919          else
1920            z_ = false;
1921        }
1922
1923        template <typename C>
1924        gyear gyear_pimpl<C>::
1925        post_gyear ()
1926        {
1927          return z_ ? gyear (year_, zh_, zm_) : gyear (year_);
1928        }
1929
1930        // gmonth_day
1931        //
1932        template <typename C>
1933        void gmonth_day_pimpl<C>::
1934        _pre ()
1935        {
1936          str_.clear ();
1937        }
1938
1939        template <typename C>
1940        void gmonth_day_pimpl<C>::
1941        _characters (const ro_string<C>& s)
1942        {
1943          if (str_.size () == 0)
1944          {
1945            ro_string<C> tmp (s.data (), s.size ());
1946
1947            if (trim_left (tmp) != 0)
1948              str_ += tmp;
1949          }
1950          else
1951            str_ += s;
1952        }
1953
1954        template <typename C>
1955        void gmonth_day_pimpl<C>::
1956        _post ()
1957        {
1958          typedef typename ro_string<C>::size_type size_type;
1959
1960          ro_string<C> tmp (str_);
1961          size_type size (trim_right (tmp));
1962          const C* s (tmp.data ());
1963
1964          // gmonth_day := --MM-DD[Z|(+|-)HH:MM]
1965          //
1966          if (size < 7 ||
1967              s[0] != C ('-') || s[1] != C ('-') || s[4] != C ('-'))
1968            throw invalid_value<C> (bits::gmonth_day<C> (), tmp);
1969
1970          // month
1971          //
1972          C d1 (s[2]), d2 (s[3]);
1973
1974          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
1975            throw invalid_value<C> (bits::gmonth_day<C> (), tmp);
1976
1977          month_ = 10 * (d1 - '0') + (d2 - '0');
1978
1979          if (month_ < 1 || month_ > 12)
1980            throw invalid_value<C> (bits::gmonth_day<C> (), tmp);
1981
1982          // day
1983          //
1984          d1 = s[5];
1985          d2 = s[6];
1986
1987          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
1988            throw invalid_value<C> (bits::gmonth_day<C> (), tmp);
1989
1990          day_ = 10 * (d1 - '0') + (d2 - '0');
1991
1992          if (day_ < 1 || day_ > 31)
1993            throw invalid_value<C> (bits::gmonth_day<C> (), tmp);
1994
1995          // zone
1996          //
1997          if (size > 7)
1998          {
1999            if (!bits::parse_tz (s + 7, size - 7, zh_, zm_))
2000              throw invalid_value<C> (bits::gmonth_day<C> (), tmp);
2001
2002            z_ = true;
2003          }
2004          else
2005            z_ = false;
2006        }
2007
2008        template <typename C>
2009        gmonth_day gmonth_day_pimpl<C>::
2010        post_gmonth_day ()
2011        {
2012          return z_
2013            ? gmonth_day (month_, day_, zh_, zm_)
2014            : gmonth_day (month_, day_);
2015        }
2016
2017        // gyear_month
2018        //
2019        template <typename C>
2020        void gyear_month_pimpl<C>::
2021        _pre ()
2022        {
2023          str_.clear ();
2024        }
2025
2026        template <typename C>
2027        void gyear_month_pimpl<C>::
2028        _characters (const ro_string<C>& s)
2029        {
2030          if (str_.size () == 0)
2031          {
2032            ro_string<C> tmp (s.data (), s.size ());
2033
2034            if (trim_left (tmp) != 0)
2035              str_ += tmp;
2036          }
2037          else
2038            str_ += s;
2039        }
2040
2041        template <typename C>
2042        void gyear_month_pimpl<C>::
2043        _post ()
2044        {
2045          typedef typename ro_string<C>::size_type size_type;
2046
2047          ro_string<C> tmp (str_);
2048          size_type size (trim_right (tmp));
2049          const C* s (tmp.data ());
2050
2051          // gyear_month := [-]CCYY[N]*-MM[Z|(+|-)HH:MM]
2052          //
2053
2054          if (size < 7 || (s[0] == C ('-') && size < 8))
2055            throw invalid_value<C> (bits::gyear_month<C> (), tmp);
2056
2057          // Find the end of the year token.
2058          //
2059          size_type pos (tmp.find (C ('-'), s[0] == C ('-') ? 5 : 4));
2060
2061          if (pos == ro_string<C>::npos || (size - pos - 1) < 2)
2062            throw invalid_value<C> (bits::gyear_month<C> (), tmp);
2063
2064          ro_string<C> year_fragment (s, pos);
2065          zc_istream<C> yis (year_fragment);
2066
2067          if (!(yis >> year_ && yis.exhausted () && year_ != 0))
2068            throw invalid_value<C> (bits::gyear_month<C> (), tmp);
2069
2070          // month
2071          //
2072          C d1 (s[pos + 1]), d2 (s[pos + 2]);
2073
2074          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
2075            throw invalid_value<C> (bits::gyear_month<C> (), tmp);
2076
2077          month_ = 10 * (d1 - '0') + (d2 - '0');
2078
2079          if (month_ < 1 || month_ > 12)
2080            throw invalid_value<C> (bits::gyear_month<C> (), tmp);
2081
2082          // zone
2083          //
2084          pos += 3;
2085
2086          if (pos < size)
2087          {
2088            if (!bits::parse_tz (s + pos, size - pos, zh_, zm_))
2089              throw invalid_value<C> (bits::gyear_month<C> (), tmp);
2090
2091            z_ = true;
2092          }
2093          else
2094            z_ = false;
2095        }
2096
2097        template <typename C>
2098        gyear_month gyear_month_pimpl<C>::
2099        post_gyear_month ()
2100        {
2101          return z_
2102            ? gyear_month (year_, month_, zh_, zm_)
2103            : gyear_month (year_, month_);
2104        }
2105
2106        // date
2107        //
2108        template <typename C>
2109        void date_pimpl<C>::
2110        _pre ()
2111        {
2112          str_.clear ();
2113        }
2114
2115        template <typename C>
2116        void date_pimpl<C>::
2117        _characters (const ro_string<C>& s)
2118        {
2119          if (str_.size () == 0)
2120          {
2121            ro_string<C> tmp (s.data (), s.size ());
2122
2123            if (trim_left (tmp) != 0)
2124              str_ += tmp;
2125          }
2126          else
2127            str_ += s;
2128        }
2129
2130        template <typename C>
2131        void date_pimpl<C>::
2132        _post ()
2133        {
2134          typedef typename ro_string<C>::size_type size_type;
2135
2136          ro_string<C> tmp (str_);
2137          size_type size (trim_right (tmp));
2138          const C* s (tmp.data ());
2139
2140          // date := [-]CCYY[N]*-MM-DD[Z|(+|-)HH:MM]
2141          //
2142
2143          if (size < 10 || (s[0] == C ('-') && size < 11))
2144            throw invalid_value<C> (bits::date<C> (), tmp);
2145
2146          // Find the end of the year token.
2147          //
2148          size_type pos (tmp.find (C ('-'), s[0] == C ('-') ? 5 : 4));
2149
2150          if (pos == ro_string<C>::npos
2151              || (size - pos - 1) < 5
2152              || s[pos + 3] != C ('-'))
2153            throw invalid_value<C> (bits::date<C> (), tmp);
2154
2155          ro_string<C> year_fragment (s, pos);
2156          zc_istream<C> yis (year_fragment);
2157
2158          if (!(yis >> year_ && yis.exhausted () && year_ != 0))
2159            throw invalid_value<C> (bits::date<C> (), tmp);
2160
2161          // month
2162          //
2163          C d1 (s[pos + 1]), d2 (s[pos + 2]);
2164
2165          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
2166            throw invalid_value<C> (bits::date<C> (), tmp);
2167
2168          month_ = 10 * (d1 - '0') + (d2 - '0');
2169
2170          if (month_ < 1 || month_ > 12)
2171            throw invalid_value<C> (bits::date<C> (), tmp);
2172
2173          // day
2174          //
2175          d1 = s[pos + 4];
2176          d2 = s[pos + 5];
2177
2178          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
2179            throw invalid_value<C> (bits::date<C> (), tmp);
2180
2181          day_ = 10 * (d1 - '0') + (d2 - '0');
2182
2183          if (day_ < 1 || day_ > 31)
2184            throw invalid_value<C> (bits::date<C> (), tmp);
2185
2186          // zone
2187          //
2188          pos += 6;
2189
2190          if (pos < size)
2191          {
2192            if (!bits::parse_tz (s + pos, size - pos, zh_, zm_))
2193              throw invalid_value<C> (bits::date<C> (), tmp);
2194
2195            z_ = true;
2196          }
2197          else
2198            z_ = false;
2199        }
2200
2201        template <typename C>
2202        date date_pimpl<C>::
2203        post_date ()
2204        {
2205          return z_
2206            ? date (year_, month_, day_, zh_, zm_)
2207            : date (year_, month_, day_);
2208        }
2209
2210        // time
2211        //
2212        template <typename C>
2213        void time_pimpl<C>::
2214        _pre ()
2215        {
2216          str_.clear ();
2217        }
2218
2219        template <typename C>
2220        void time_pimpl<C>::
2221        _characters (const ro_string<C>& s)
2222        {
2223          if (str_.size () == 0)
2224          {
2225            ro_string<C> tmp (s.data (), s.size ());
2226
2227            if (trim_left (tmp) != 0)
2228              str_ += tmp;
2229          }
2230          else
2231            str_ += s;
2232        }
2233
2234        template <typename C>
2235        void time_pimpl<C>::
2236        _post ()
2237        {
2238          typedef typename ro_string<C>::size_type size_type;
2239
2240          ro_string<C> tmp (str_);
2241          size_type size (trim_right (tmp));
2242          const C* s (tmp.data ());
2243
2244          // time := HH:MM:SS[.S+][Z|(+|-)HH:MM]
2245          //
2246
2247          if (size < 8 || s[2] != C (':') || s[5] != C (':'))
2248            throw invalid_value<C> (bits::time<C> (), tmp);
2249
2250          // hours
2251          //
2252          C d1 (s[0]), d2 (s[1]);
2253
2254          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
2255            throw invalid_value<C> (bits::time<C> (), tmp);
2256
2257          hours_ = 10 * (d1 - '0') + (d2 - '0');
2258
2259          if (hours_ > 24)
2260            throw invalid_value<C> (bits::time<C> (), tmp);
2261
2262          // minutes
2263          //
2264          d1 = s[3];
2265          d2 = s[4];
2266
2267          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
2268            throw invalid_value<C> (bits::time<C> (), tmp);
2269
2270          minutes_ = 10 * (d1 - '0') + (d2 - '0');
2271
2272          if (minutes_ > 59)
2273            throw invalid_value<C> (bits::time<C> (), tmp);
2274
2275          // Find the end of the seconds fragment.
2276          //
2277          size_type pos (8);
2278          for (; pos < size; ++pos)
2279          {
2280            C c (s[pos]);
2281
2282            if (c == C ('Z') || c == C ('+') || c == C ('-'))
2283              break;
2284          }
2285
2286          // At least one digit should follow the fraction point.
2287          //
2288          if ((pos - 6) == 3)
2289            throw invalid_value<C> (bits::time<C> (), tmp);
2290
2291          ro_string<C> seconds_fragment (s + 6, pos - 6);
2292          zc_istream<C> sis (seconds_fragment);
2293
2294          if (!(sis >> seconds_ && sis.exhausted () && seconds_ < 60.0))
2295            throw invalid_value<C> (bits::time<C> (), tmp);
2296
2297          if (hours_ == 24 && (minutes_ != 0 || seconds_ != 0.0))
2298            throw invalid_value<C> (bits::time<C> (), tmp);
2299
2300          // zone
2301          //
2302          if (pos < size)
2303          {
2304            if (!bits::parse_tz (s + pos, size - pos, zh_, zm_))
2305              throw invalid_value<C> (bits::time<C> (), tmp);
2306
2307            z_ = true;
2308          }
2309          else
2310            z_ = false;
2311        }
2312
2313        template <typename C>
2314        time time_pimpl<C>::
2315        post_time ()
2316        {
2317          return z_
2318            ? time (hours_, minutes_, seconds_, zh_, zm_)
2319            : time (hours_, minutes_, seconds_);
2320        }
2321
2322
2323        // date_time
2324        //
2325        template <typename C>
2326        void date_time_pimpl<C>::
2327        _pre ()
2328        {
2329          str_.clear ();
2330        }
2331
2332        template <typename C>
2333        void date_time_pimpl<C>::
2334        _characters (const ro_string<C>& s)
2335        {
2336          if (str_.size () == 0)
2337          {
2338            ro_string<C> tmp (s.data (), s.size ());
2339
2340            if (trim_left (tmp) != 0)
2341              str_ += tmp;
2342          }
2343          else
2344            str_ += s;
2345        }
2346
2347        template <typename C>
2348        void date_time_pimpl<C>::
2349        _post ()
2350        {
2351          typedef typename ro_string<C>::size_type size_type;
2352
2353          ro_string<C> tmp (str_);
2354          size_type size (trim_right (tmp));
2355          const C* s (tmp.data ());
2356
2357          // date_time := [-]CCYY[N]*-MM-DDTHH:MM:SS[.S+][Z|(+|-)HH:MM]
2358          //
2359
2360          if (size < 19 || (s[0] == C ('-') && size < 20))
2361            throw invalid_value<C> (bits::date_time<C> (), tmp);
2362
2363          // Find the end of the year token.
2364          //
2365          size_type pos (tmp.find (C ('-'), s[0] == C ('-') ? 5 : 4));
2366
2367          if (pos == ro_string<C>::npos || (size - pos - 1) < 14
2368              || s[pos + 3] != C ('-') || s[pos + 6] != C ('T')
2369              || s[pos + 9] != C (':') || s[pos + 12] != C (':'))
2370            throw invalid_value<C> (bits::date_time<C> (), tmp);
2371
2372          // year
2373          //
2374          ro_string<C> year_fragment (s, pos);
2375          zc_istream<C> yis (year_fragment);
2376
2377          if (!(yis >> year_ && yis.exhausted () && year_ != 0))
2378            throw invalid_value<C> (bits::date_time<C> (), tmp);
2379
2380          // month
2381          //
2382          C d1 (s[pos + 1]), d2 (s[pos + 2]);
2383
2384          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
2385            throw invalid_value<C> (bits::date_time<C> (), tmp);
2386
2387          month_ = 10 * (d1 - '0') + (d2 - '0');
2388
2389          if (month_ < 1 || month_ > 12)
2390            throw invalid_value<C> (bits::date_time<C> (), tmp);
2391
2392          // day
2393          //
2394          d1 = s[pos + 4];
2395          d2 = s[pos + 5];
2396
2397          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
2398            throw invalid_value<C> (bits::date_time<C> (), tmp);
2399
2400          day_ = 10 * (d1 - '0') + (d2 - '0');
2401
2402          if (day_ < 1 || day_ > 31)
2403            throw invalid_value<C> (bits::date_time<C> (), tmp);
2404
2405          pos += 7; // Point to the first H.
2406
2407          // hours
2408          //
2409          d1 = s[pos];
2410          d2 = s[pos + 1];
2411
2412          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
2413            throw invalid_value<C> (bits::date_time<C> (), tmp);
2414
2415          hours_ = 10 * (d1 - '0') + (d2 - '0');
2416
2417          if (hours_ > 24)
2418            throw invalid_value<C> (bits::date_time<C> (), tmp);
2419
2420          // minutes
2421          //
2422          d1 = s[pos + 3];
2423          d2 = s[pos + 4];
2424
2425          if (d1 < '0' || d1 > '9' || d2 < '0' || d2 > '9')
2426            throw invalid_value<C> (bits::date_time<C> (), tmp);
2427
2428          minutes_ = 10 * (d1 - '0') + (d2 - '0');
2429
2430          if (minutes_ > 59)
2431            throw invalid_value<C> (bits::date_time<C> (), tmp);
2432
2433          // Find the end of the seconds fragment.
2434          //
2435          pos += 6; // Point to the first S.
2436
2437          size_type sec_end (pos + 2);
2438          for (; sec_end < size; ++sec_end)
2439          {
2440            C c (s[sec_end]);
2441
2442            if (c == C ('Z') || c == C ('+') || c == C ('-'))
2443              break;
2444          }
2445
2446          // At least one digit should should follow the fraction point.
2447          //
2448          if ((sec_end - pos) == 3)
2449            throw invalid_value<C> (bits::date_time<C> (), tmp);
2450
2451          ro_string<C> seconds_fragment (s + pos, sec_end - pos);
2452          zc_istream<C> sis (seconds_fragment);
2453
2454          if (!(sis >> seconds_ && sis.exhausted () && seconds_ < 60.0))
2455            throw invalid_value<C> (bits::date_time<C> (), tmp);
2456
2457          if (hours_ == 24 && (minutes_ != 0 || seconds_ != 0.0))
2458            throw invalid_value<C> (bits::date_time<C> (), tmp);
2459
2460          // zone
2461          //
2462          if (sec_end < size)
2463          {
2464            if (!bits::parse_tz (s + sec_end, size - sec_end, zh_, zm_))
2465              throw invalid_value<C> (bits::date_time<C> (), tmp);
2466
2467            z_ = true;
2468          }
2469          else
2470            z_ = false;
2471        }
2472
2473        template <typename C>
2474        date_time date_time_pimpl<C>::
2475        post_date_time ()
2476        {
2477          return z_
2478            ? date_time (year_, month_, day_, hours_, minutes_, seconds_,
2479                         zh_, zm_)
2480            : date_time (year_, month_, day_, hours_, minutes_, seconds_);
2481        }
2482
2483        // duration
2484        //
2485        template <typename C>
2486        void duration_pimpl<C>::
2487        _pre ()
2488        {
2489          str_.clear ();
2490        }
2491
2492        template <typename C>
2493        void duration_pimpl<C>::
2494        _characters (const ro_string<C>& s)
2495        {
2496          if (str_.size () == 0)
2497          {
2498            ro_string<C> tmp (s.data (), s.size ());
2499
2500            if (trim_left (tmp) != 0)
2501              str_ += tmp;
2502          }
2503          else
2504            str_ += s;
2505        }
2506
2507        namespace bits
2508        {
2509          template <typename C>
2510          inline typename ro_string<C>::size_type
2511          duration_delim (const C* s,
2512                          typename ro_string<C>::size_type pos,
2513                          typename ro_string<C>::size_type size)
2514          {
2515            const C* p (s + pos);
2516            for (; p < (s + size); ++p)
2517            {
2518              if (*p == C ('Y') || *p == C ('D') || *p == C ('M') ||
2519                  *p == C ('H') || *p == C ('M') || *p == C ('S') ||
2520                  *p == C ('T'))
2521                break;
2522            }
2523
2524            return p - s;
2525          }
2526        }
2527
2528        template <typename C>
2529        void duration_pimpl<C>::
2530        _post ()
2531        {
2532          typedef typename ro_string<C>::size_type size_type;
2533
2534          ro_string<C> tmp (str_);
2535          size_type size (trim_right (tmp));
2536
2537          negative_ = false;
2538          years_ = 0;
2539          months_ = 0;
2540          days_ = 0;
2541          hours_ = 0;
2542          minutes_ = 0;
2543          seconds_ = 0.0;
2544
2545          // duration := [-]P[nY][nM][nD][TnHnMn[.n+]S]
2546          //
2547          const C* s (tmp.data ());
2548
2549          if (size < 3 || (s[0] == C ('-') && size < 4))
2550            throw invalid_value<C> (bits::duration<C> (), tmp);
2551
2552          size_type pos (0);
2553
2554          if (s[0] == C ('-'))
2555          {
2556            negative_ = true;
2557            pos++;
2558          }
2559
2560          if (s[pos++] != C ('P'))
2561            throw invalid_value<C> (bits::duration<C> (), tmp);
2562
2563          size_type del (bits::duration_delim (s, pos, size));
2564
2565          // Duration should contain at least one component.
2566          //
2567          if (del == size)
2568            throw invalid_value<C> (bits::duration<C> (), tmp);
2569
2570          if (s[del] == C ('Y'))
2571          {
2572            ro_string<C> fragment (s + pos, del - pos);
2573            zc_istream<C> is (fragment);
2574
2575            if (!(is >> years_ && is.exhausted ()))
2576              throw invalid_value<C> (bits::duration<C> (), tmp);
2577
2578            pos = del + 1;
2579            del = bits::duration_delim (s, pos, size);
2580          }
2581
2582          if (del != size && s[del] == C ('M'))
2583          {
2584            ro_string<C> fragment (s + pos, del - pos);
2585            zc_istream<C> is (fragment);
2586
2587            if (!(is >> months_ && is.exhausted ()))
2588              throw invalid_value<C> (bits::duration<C> (), tmp);
2589
2590            pos = del + 1;
2591            del = bits::duration_delim (s, pos, size);
2592          }
2593
2594          if (del != size && s[del] == C ('D'))
2595          {
2596            ro_string<C> fragment (s + pos, del - pos);
2597            zc_istream<C> is (fragment);
2598
2599            if (!(is >> days_ && is.exhausted ()))
2600              throw invalid_value<C> (bits::duration<C> (), tmp);
2601
2602            pos = del + 1;
2603            del = bits::duration_delim (s, pos, size);
2604          }
2605
2606          if (del != size && s[del] == C ('T'))
2607          {
2608            pos = del + 1;
2609            del = bits::duration_delim (s, pos, size);
2610
2611            // At least one time component should be present.
2612            //
2613            if (del == size)
2614              throw invalid_value<C> (bits::duration<C> (), tmp);
2615
2616            if (s[del] == C ('H'))
2617            {
2618              ro_string<C> fragment (s + pos, del - pos);
2619              zc_istream<C> is (fragment);
2620
2621              if (!(is >> hours_ && is.exhausted ()))
2622                throw invalid_value<C> (bits::duration<C> (), tmp);
2623
2624              pos = del + 1;
2625              del = bits::duration_delim (s, pos, size);
2626            }
2627
2628            if (del != size && s[del] == C ('M'))
2629            {
2630              ro_string<C> fragment (s + pos, del - pos);
2631              zc_istream<C> is (fragment);
2632
2633              if (!(is >> minutes_ && is.exhausted ()))
2634                throw invalid_value<C> (bits::duration<C> (), tmp);
2635
2636              pos = del + 1;
2637              del = bits::duration_delim (s, pos, size);
2638            }
2639
2640            if (del != size && s[del] == C ('S'))
2641            {
2642              ro_string<C> fragment (s + pos, del - pos);
2643              zc_istream<C> is (fragment);
2644
2645              if (!(is >> seconds_ && is.exhausted () && seconds_ >= 0.0))
2646                throw invalid_value<C> (bits::duration<C> (), tmp);
2647
2648              pos = del + 1;
2649            }
2650          }
2651
2652          // Something did not match or appeared in the wrong order.
2653          //
2654          if (pos != size)
2655            throw invalid_value<C> (bits::duration<C> (), tmp);
2656        }
2657
2658        template <typename C>
2659        duration duration_pimpl<C>::
2660        post_duration ()
2661        {
2662          return duration (
2663            negative_, years_, months_, days_, hours_, minutes_, seconds_);
2664        }
2665      }
2666    }
2667  }
2668}
Note: See TracBrowser for help on using the browser.