Changeset 0b4b81c in mainline
- Timestamp:
- 2018-07-05T21:41:18Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6648ab33
- Parents:
- 6702d7e
- git-author:
- Jaroslav Jindrak <dzejrou@…> (2017-11-08 21:23:49)
- git-committer:
- Dzejrou <dzejrou@…> (2018-07-05 21:41:18)
- Location:
- uspace/lib/cpp
- Files:
-
- 1 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/cpp/include/impl/locale.hpp
r6702d7e r0b4b81c 30 30 #define LIBCPP_LOCALE 31 31 32 #include <cctype> 33 #include <cstdlib> 34 #include <iosfwd> 35 #include <string> 36 32 37 namespace std 33 38 { 39 40 /** 41 * Note: This is a very simplistic implementation of <locale>. 42 * We have a single locale that has all of its facets. 43 * This should behave correctly on the outside but will prevent 44 * us from using multiple locales so if that becomes necessary 45 * in the future, TODO: implement :) 46 */ 47 48 namespace aux 49 { 50 class facet 51 { 52 protected: 53 explicit facet(size_t refs = 0); 54 55 virtual ~facet(); 56 57 facet(const facet&) = delete; 58 void operator=(const facet&) = delete; 59 }; 60 61 class id 62 { 63 public: 64 id() = default; 65 66 id(const id&) = delete; 67 void operator=(const id&) = delete; 68 }; 69 } 70 71 /** 72 * 22.4.1, the type category: 73 */ 74 75 class ctype_base 76 { 77 public: 78 using mask = uint16_t; 79 80 static constexpr mask space = 0b00'0000'0001; 81 static constexpr mask print = 0b00'0000'0010; 82 static constexpr mask cntrl = 0b00'0000'0100; 83 static constexpr mask upper = 0b00'0000'1000; 84 static constexpr mask lower = 0b00'0001'0000; 85 static constexpr mask alpha = 0b00'0010'0000; 86 static constexpr mask digit = 0b00'0100'0000; 87 static constexpr mask punct = 0b00'1000'0000; 88 static constexpr mask xdigit = 0b01'0000'0000; 89 static constexpr mask blank = 0b10'0000'0000; 90 static constexpr mask alnum = alpha | digit; 91 static constexpr mask graph = alnum | punct; 92 }; 93 94 /** 95 * 22.4.1.1, class template ctype: 96 */ 97 98 template<class Char> 99 class ctype: public aux::facet, public ctype_base 100 { 101 public: 102 using char_type = Char; 103 104 explicit ctype(size_t) 105 { /* DUMMY BODY */ } 106 107 bool is(mask m, char_type c) const 108 { 109 return do_is(m, c); 110 } 111 112 const char_type* is(const char_type* low, const char_type* high, 113 mask* vec) const 114 { 115 return do_is(low, high, vec); 116 } 117 118 const char_type* scan_is(mask m, const char_type* low, 119 const char_type* high) const 120 { 121 return do_scan_is(m, low, high); 122 } 123 124 const char_type* scan_not(mask m, const char_type* low, 125 const char_type* high) const 126 { 127 return do_scan_not(m, low, high); 128 } 129 130 char_type toupper(char_type c) const 131 { 132 return do_toupper(c); 133 } 134 135 const char_type* toupper(char_type* low, const char_type* high) const 136 { 137 return do_toupper(low, high); 138 } 139 140 char_type tolower(char_type c) const 141 { 142 return do_tolower(c); 143 } 144 145 const char_type* tolower(char_type* low, const char_type* high) const 146 { 147 return do_tolower(low, high); 148 } 149 150 char_type widen(char c) const 151 { 152 return do_widen(c); 153 } 154 155 const char_type* widen(const char* low, const char* high, char_type* to) const 156 { 157 return do_widen(low, high, to); 158 } 159 160 char narrow(char_type c, char def) const 161 { 162 return do_narrow(c, def); 163 } 164 165 const char_type* narrow(const char_type* low, const char_type* high, 166 char def, char* to) const 167 { 168 return do_narrow(low, high, def, to); 169 } 170 171 static aux::id id; 172 173 /** 174 * Note: This is a deviation from the standard, because in the 175 * ISO C++ Standard this function is protected (because 176 * the instances are reference counted, but in our design 177 * they are not and as such we did this change). 178 * (This applies to all constructors of all facets.) 179 */ 180 ~ctype() = default; 181 182 protected: 183 virtual bool do_is(mask m, char_type c) const 184 { 185 // TODO: implement 186 return false; 187 } 188 189 virtual const char_type* do_is(const char_type* low, const char_type high, 190 mask m) const 191 { 192 // TODO: implement 193 return high; 194 } 195 196 virtual const char_type* do_scan_is(mask m, const char_type* low, 197 const char_type* high) const 198 { 199 // TODO: implement 200 return high; 201 } 202 203 virtual const char_type* do_scan_not(mask m, const char_type* low, 204 const char_type* high) const 205 { 206 // TODO: implement 207 return low; 208 } 209 210 virtual char_type do_toupper(char_type c) const 211 { 212 // TODO: implement 213 return c; 214 } 215 216 virtual const char_type* do_toupper(char_type* low, const char_type* high) const 217 { 218 // TODO: implement 219 return high; 220 } 221 222 virtual char_type do_tolower(char_type c) const 223 { 224 // TODO: implement 225 return c; 226 } 227 228 virtual const char_type* do_tolower(char_type* low, const char_type* high) const 229 { 230 // TODO: implement 231 return high; 232 } 233 234 virtual char_type do_widen(char c) const 235 { 236 // TODO: implement 237 return c; 238 } 239 240 virtual const char_type* do_widen(const char* low, const char* high, 241 char_type* dest) const 242 { 243 // TODO: implement 244 return high; 245 } 246 247 virtual char do_narrow(char_type c, char def) const 248 { 249 // TODO: implement 250 return c; 251 } 252 253 virtual const char_type* do_narrow(const char_type* low, const char_type* high, 254 char def, char* dest) const 255 { 256 // TODO: implement 257 return high; 258 } 259 }; 260 261 template<class Char> 262 aux::id ctype<Char>::id{}; 263 264 /** 265 * 22.4.1.2, class template ctype_byname: 266 * Note: Dummy, TODO: implement. 267 */ 268 269 template<class Char> 270 class ctype_byname: public ctype<Char> 271 { 272 public: 273 using mask = typename ctype<Char>::mask; 274 275 explicit ctype_byname(const char* name, size_t = 0) 276 { /* DUMMY BODY */ } 277 278 explicit ctype_byname(const string& name, size_t = 0) 279 { /* DUMMY BODY */ } 280 281 protected: 282 ~ctype_byname() = default; 283 }; 284 285 /** 286 * 22.4.1.3, ctype specialziations: 287 */ 288 289 template<> 290 class ctype<char>: public aux::facet, public ctype_base 291 { 292 public: 293 using char_type = char; 294 295 explicit ctype(const mask* tab = nullptr, bool del = false, size_t = 0) 296 { /* DUMMY BODY */ } 297 298 bool is(mask m, char_type c) const 299 { 300 return do_is(m, c); 301 } 302 303 const char_type* is(const char_type* low, const char_type* high, 304 mask* vec) const 305 { 306 return do_is(low, high, vec); 307 } 308 309 const char_type* scan_is(mask m, const char_type* low, 310 const char_type* high) const 311 { 312 return do_scan_is(m, low, high); 313 } 314 315 const char_type* scan_not(mask m, const char_type* low, 316 const char_type* high) const 317 { 318 return do_scan_not(m, low, high); 319 } 320 321 char_type toupper(char_type c) const 322 { 323 return do_toupper(c); 324 } 325 326 const char_type* toupper(char_type* low, const char_type* high) const 327 { 328 return do_toupper(low, high); 329 } 330 331 char_type tolower(char_type c) const 332 { 333 return do_tolower(c); 334 } 335 336 const char_type* tolower(char_type* low, const char_type* high) const 337 { 338 return do_tolower(low, high); 339 } 340 341 char_type widen(char c) const 342 { 343 return do_widen(c); 344 } 345 346 const char_type* widen(const char* low, const char* high, char_type* to) const 347 { 348 return do_widen(low, high, to); 349 } 350 351 char narrow(char_type c, char def) const 352 { 353 return do_narrow(c, def); 354 } 355 356 const char_type* narrow(const char_type* low, const char_type* high, 357 char def, char* to) const 358 { 359 return do_narrow(low, high, def, to); 360 } 361 362 static aux::id id; 363 static const size_t table_size{0}; 364 365 const mask* table() const noexcept 366 { 367 return classic_table(); 368 } 369 370 static const mask* classic_table() noexcept 371 { 372 return classic_table_; 373 } 374 375 ~ctype() = default; 376 377 protected: 378 virtual bool do_is(mask m, char_type c) const 379 { 380 // TODO: implement, this is a dummy 381 if ((m & space) != 0 && std::isspace(c)) 382 return true; 383 else if ((m & alpha) != 0 && std::isalpha(c)) 384 return true; 385 else if ((m & upper) != 0 && std::isupper(c)) 386 return true; 387 else if ((m & lower) != 0 && std::islower(c)) 388 return true; 389 else if ((m & digit) != 0 && std::isdigit(c)) 390 return true; 391 return false; 392 } 393 394 virtual const char_type* do_is(const char_type* low, const char_type* high, 395 mask* m) const 396 { 397 // TODO: implement 398 return high; 399 } 400 401 virtual const char_type* do_scan_is(mask m, const char_type* low, 402 const char_type* high) const 403 { 404 // TODO: implement 405 return high; 406 } 407 408 virtual const char_type* do_scan_not(mask m, const char_type* low, 409 const char_type* high) const 410 { 411 // TODO: implement 412 return high; 413 } 414 415 virtual char_type do_toupper(char_type c) const 416 { 417 return std::toupper(c); 418 } 419 420 virtual const char_type* do_toupper(char_type* low, const char_type* high) const 421 { 422 while (low != high) 423 *low = std::toupper(*low); 424 425 return high; 426 } 427 428 virtual char_type do_tolower(char_type c) const 429 { 430 return std::tolower(c); 431 } 432 433 virtual const char_type* do_tolower(char_type* low, const char_type* high) const 434 { 435 while (low != high) 436 *low = std::tolower(*low); 437 438 return high; 439 } 440 441 virtual char_type do_widen(char c) const 442 { 443 return c; 444 } 445 446 virtual const char_type* do_widen(const char* low, const char* high, 447 char_type* dest) const 448 { 449 while (low != high) 450 *dest++ = *low++; 451 452 return high; 453 } 454 455 virtual char do_narrow(char_type c, char def) const 456 { 457 return c; 458 } 459 460 virtual const char_type* do_narrow(const char_type* low, const char_type* high, 461 char def, char* dest) const 462 { 463 while (low != high) 464 *dest++ = *low++; 465 466 return high; 467 } 468 469 private: 470 static constexpr mask* classic_table_{nullptr}; 471 }; 472 473 template<> 474 class ctype<wchar_t>: public aux::facet, public ctype_base 475 { 476 public: 477 using char_type = wchar_t; 478 479 explicit ctype(const mask* tab = nullptr, bool del = false, size_t = 0) 480 { /* DUMMY BODY */ } 481 482 bool is(mask m, char_type c) const 483 { 484 return do_is(m, c); 485 } 486 487 const char_type* is(const char_type* low, const char_type* high, 488 mask* vec) const 489 { 490 return do_is(low, high, vec); 491 } 492 493 const char_type* scan_is(mask m, const char_type* low, 494 const char_type* high) const 495 { 496 return do_scan_is(m, low, high); 497 } 498 499 const char_type* scan_not(mask m, const char_type* low, 500 const char_type* high) const 501 { 502 return do_scan_not(m, low, high); 503 } 504 505 char_type toupper(char_type c) const 506 { 507 return do_toupper(c); 508 } 509 510 const char_type* toupper(char_type* low, const char_type* high) const 511 { 512 return do_toupper(low, high); 513 } 514 515 char_type tolower(char_type c) const 516 { 517 return do_tolower(c); 518 } 519 520 const char_type* tolower(char_type* low, const char_type* high) const 521 { 522 return do_tolower(low, high); 523 } 524 525 char_type widen(char c) const 526 { 527 return do_widen(c); 528 } 529 530 const char_type* widen(const char* low, const char* high, char_type* to) const 531 { 532 return do_widen(low, high, to); 533 } 534 535 char narrow(char_type c, char def) const 536 { 537 return do_narrow(c, def); 538 } 539 540 const char_type* narrow(const char_type* low, const char_type* high, 541 char def, char* to) const 542 { 543 return do_narrow(low, high, def, to); 544 } 545 546 static aux::id id; 547 static const size_t table_size{0}; 548 549 const mask* table() const noexcept 550 { 551 return classic_table(); 552 } 553 554 static const mask* classic_table() noexcept 555 { 556 return classic_table_; 557 } 558 559 ~ctype() = default; 560 561 protected: 562 virtual bool do_is(mask m, char_type c) const 563 { 564 // TODO: implement 565 return false; 566 } 567 568 virtual const char_type* do_is(const char_type* low, const char_type* high, 569 mask* m) const 570 { 571 // TODO: implement 572 return high; 573 } 574 575 virtual const char_type* do_scan_is(mask m, const char_type* low, 576 const char_type* high) const 577 { 578 // TODO: implement 579 return high; 580 } 581 582 virtual const char_type* do_scan_not(mask m, const char_type* low, 583 const char_type* high) const 584 { 585 // TODO: implement 586 return high; 587 } 588 589 virtual char_type do_toupper(char_type c) const 590 { 591 // TODO: implement 592 return c; 593 } 594 595 virtual const char_type* do_toupper(char_type* low, const char_type* high) const 596 { 597 // TODO: implement 598 return high; 599 } 600 601 virtual char_type do_tolower(char_type c) const 602 { 603 // TODO: implement 604 return c; 605 } 606 607 virtual const char_type* do_tolower(char_type* low, const char_type* high) const 608 { 609 // TODO: implement 610 return high; 611 } 612 613 virtual char_type do_widen(char c) const 614 { 615 // TODO: implement 616 return c; 617 } 618 619 virtual const char_type* do_widen(const char* low, const char* high, 620 char_type* dest) const 621 { 622 // TODO: implement 623 return dest; 624 } 625 626 virtual char do_narrow(char_type c, char def) const 627 { 628 // TODO: implement 629 return c; 630 } 631 632 virtual const char_type* do_narrow(const char_type* low, const char_type* high, 633 char def, char* dest) const 634 { 635 // TODO: implement 636 return high; 637 } 638 639 private: 640 static constexpr mask* classic_table_{nullptr}; 641 }; 642 643 /** 644 * 22.4.1.4, class template codecvt: 645 */ 646 647 class codecvt_base 648 { 649 public: 650 enum result 651 { 652 ok, partial, error, noconv 653 }; 654 }; 655 656 template<class Intern, class Extern, class State> 657 class codecvt: public codecvt_base 658 { 659 public: 660 using intern_type = Intern; 661 using extern_type = Extern; 662 using state_type = State; 663 664 explicit codecvt(size_t = 0) 665 { /* DUMMY BODY */ } 666 667 result out(state_type& state, const intern_type* from, const intern_type* from_end, 668 const intern_type*& from_next, extern_type* to, extern_type* to_end, 669 extern_type*& to_next) const 670 { 671 return do_out(state, from, from_end, from_next, to, to_end, to_next); 672 } 673 674 result unshift(state_type& state, extern_type* to, extern_type* to_end, 675 extern_type*& to_next) const 676 { 677 return do_unshift(state, to, to_end, to_next); 678 } 679 680 result in(state_type& state, const extern_type* from, const extern_type* from_end, 681 const extern_type*& from_next, intern_type* to, intern_type* to_end, 682 intern_type*& to_next) const 683 { 684 return do_in(state, from, from_end, from_next, to, to_end, to_next); 685 } 686 687 int encoding() const noexcept 688 { 689 return do_encoding(); 690 } 691 692 bool always_noconv() const noexcept 693 { 694 return do_always_noconv(); 695 } 696 697 int length(state_type& state, const extern_type* from, const extern_type* end, 698 size_t max) const 699 { 700 return do_length(state, from, end, max); 701 } 702 703 int max_length() const noexcept 704 { 705 return do_max_length(); 706 } 707 708 static aux::id id; 709 710 ~codecvt() = default; 711 712 protected: 713 virtual result do_out(state_type& state, const intern_type* from, const intern_type* from_end, 714 const intern_type*& from_next, extern_type* to, extern_type* to_end, 715 extern_type*& to_next) const 716 { 717 // TODO: implement 718 return error; 719 } 720 721 virtual result do_unshift(state_type& state, extern_type* to, extern_type* to_end, 722 extern_type*& to_next) const 723 { 724 // TODO: implement 725 return error; 726 } 727 728 virtual result do_in(state_type& state, const extern_type* from, const extern_type* from_end, 729 const extern_type*& from_next, intern_type* to, intern_type* to_end, 730 intern_type*& to_next) const 731 { 732 // TODO: implement 733 return error; 734 } 735 736 virtual int do_encoding() const noexcept 737 { 738 // TODO: implement 739 return 0; 740 } 741 742 virtual bool do_always_noconv() const noexcept 743 { 744 // TODO: implement 745 return false; 746 } 747 748 virtual int do_length(state_type& state, const extern_type* from, const extern_type* end, 749 size_t max) const 750 { 751 // TODO: implement 752 return 0; 753 } 754 755 virtual int do_max_length() const noexcept 756 { 757 // TODO: implement 758 return 0; 759 } 760 }; 761 762 template<class Intern, class Extern, class State> 763 aux::id codecvt<Intern, Extern, State>::id{}; 764 765 /** 766 * 22.4.1.5, class template codecvt_byname: 767 * Note: Dummy, TODO: implement. 768 */ 769 770 template<class Intern, class Extern, class State> 771 class codecvt_byname: public codecvt<Intern, Extern, State> 772 { 773 public: 774 explicit codecvt_byname(const char*, size_t = 0) 775 { /* DUMMY BODY */ } 776 777 explicit codecvt_byname(const string&, size_t = 0) 778 { /* DUMMY BODY */ } 779 780 ~codecvt_byname() = default; 781 }; 782 783 /** 784 * 22.3.1, class locale: 785 */ 786 34 787 class locale 35 788 { 36 // TODO: implement 789 public: 790 using facet = aux::facet; 791 using id = aux::id; 792 793 using category = int; 794 795 static const category none = 0b000'0001; 796 static const category collate = 0b000'0010; 797 static const category ctype = 0b000'0100; 798 static const category monetary = 0b000'1000; 799 static const category numeric = 0b001'0000; 800 static const category time = 0b010'0000; 801 static const category messages = 0b100'0000; 802 static const category all = collate | ctype | monetary | 803 numeric | time | messages; 804 805 locale() noexcept; 806 807 locale(const locale& other) noexcept; 808 809 explicit locale(const char* name); 810 811 explicit locale(const string& name); 812 813 locale(const locale& other, const char* name, category); 814 815 locale(const locale& other, const string& name, category); 816 817 template<class Facet> 818 locale(const locale& other, Facet* f) 819 : name_{other.name_} 820 { /* DUMMY BODY */ } 821 822 locale(const locale& other, const locale& one, category); 823 824 ~locale() = default; 825 826 const locale& operator=(const locale& other) noexcept; 827 828 template<class Facet> 829 locale combine(const locale& other) const 830 { 831 return other; 832 } 833 834 string name() const; 835 836 bool operator==(const locale& other) const; 837 bool operator!=(const locale& other) const; 838 839 template<class Char, class Traits, class Allocator> 840 bool operator()(const basic_string<Char, Traits, Allocator>& s1, 841 const basic_string<Char, Traits, Allocator>& s2) const 842 { 843 // TODO: define outside locale 844 /* return use_facet<collate<Char>>(*this).compare( */ 845 /* s1.begin(), s1.end(), s2.begin(), s2.end() */ 846 /* ) < 0; */ 847 return false; 848 } 849 850 static locale global(const locale&) 851 { 852 return *the_locale_; 853 } 854 855 static const locale& classic() 856 { 857 return *the_locale_; 858 } 859 860 private: 861 string name_; 862 863 // TODO: implement the_locale_ 864 static constexpr locale* the_locale_{nullptr}; 865 866 template<class Facet> 867 friend bool has_facet(const locale&); 868 869 template<class Facet> 870 bool has_() 871 { // Our single locale atm has all facets. 872 return true; 873 } 874 875 template<class Facet> 876 friend const Facet& use_facet(const locale&); 877 878 /** 879 * Note: We store all of the facets in the main 880 * locale. 881 */ 882 883 template<class Facet> 884 const Facet& get_(); 885 886 std::ctype<char> ctype_char_{}; 887 std::ctype<wchar_t> ctype_wchar_{}; 37 888 }; 889 890 template<> 891 const ctype<char>& locale::get_<ctype<char>>() 892 { 893 return ctype_char_; 894 } 895 896 template<> 897 const ctype<wchar_t>& locale::get_<ctype<wchar_t>>() 898 { 899 return ctype_wchar_; 900 } 901 902 template<class Facet> 903 const Facet& use_facet(const locale& loc) 904 { 905 return loc.get_<Facet>(); 906 } 907 908 template<class Facet> 909 bool has_facet(const locale& loc) 910 { 911 return loc.has_<Facet>(); 912 } 913 914 /** 915 * 22.3.3, convenience interfaces: 916 */ 917 918 /** 919 * 22.3.3.1, character classification: 920 */ 921 922 template<class Char> 923 bool isspace(Char c, const locale& loc) 924 { 925 return use_facet<ctype<Char>>(loc).is(ctype_base::space, c); 926 } 927 928 template<class Char> 929 bool isprint(Char c, const locale& loc) 930 { 931 return use_facet<ctype<Char>>(loc).is(ctype_base::print, c); 932 } 933 934 template<class Char> 935 bool iscntrl(Char c, const locale& loc) 936 { 937 return use_facet<ctype<Char>>(loc).is(ctype_base::cntrl, c); 938 } 939 940 template<class Char> 941 bool isupper(Char c, const locale& loc) 942 { 943 return use_facet<ctype<Char>>(loc).is(ctype_base::upper, c); 944 } 945 946 template<class Char> 947 bool islower(Char c, const locale& loc) 948 { 949 return use_facet<ctype<Char>>(loc).is(ctype_base::lower, c); 950 } 951 952 template<class Char> 953 bool isalpha(Char c, const locale& loc) 954 { 955 return use_facet<ctype<Char>>(loc).is(ctype_base::alpha, c); 956 } 957 958 template<class Char> 959 bool isdigit(Char c, const locale& loc) 960 { 961 return use_facet<ctype<Char>>(loc).is(ctype_base::digit, c); 962 } 963 964 template<class Char> 965 bool ispunct(Char c, const locale& loc) 966 { 967 return use_facet<ctype<Char>>(loc).is(ctype_base::punct, c); 968 } 969 970 template<class Char> 971 bool isxdigit(Char c, const locale& loc) 972 { 973 return use_facet<ctype<Char>>(loc).is(ctype_base::xdigit, c); 974 } 975 976 template<class Char> 977 bool isalnum(Char c, const locale& loc) 978 { 979 return use_facet<ctype<Char>>(loc).is(ctype_base::alnum, c); 980 } 981 982 template<class Char> 983 bool isgraph(Char c, const locale& loc) 984 { 985 return use_facet<ctype<Char>>(loc).is(ctype_base::graph, c); 986 } 987 988 template<class Char> 989 bool isblank(Char c, const locale& loc) 990 { 991 return use_facet<ctype<Char>>(loc).is(ctype_base::blank, c); 992 } 993 994 /** 995 * 22.3.3.2, conversions: 996 */ 997 998 /** 999 * 22.3.3.2.1, character conversions: 1000 */ 1001 1002 template<class Char> 1003 Char toupper(Char c, const locale& loc) 1004 { 1005 return use_facet<ctype<Char>>(loc).toupper(c); 1006 } 1007 1008 template<class Char> 1009 Char tolower(Char c, const locale& loc) 1010 { 1011 return use_facet<ctype<Char>>(loc).tolower(c); 1012 } 1013 1014 /** 1015 * 22.3.3.2.2, string conversions: 1016 */ 1017 1018 // TODO: implement 38 1019 } 39 1020
Note:
See TracChangeset
for help on using the changeset viewer.