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