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