source: mainline/uspace/lib/cpp/include/impl/locale.hpp@ 7258487

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7258487 was 0b4b81c, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added some more dummy locale implementations

  • Property mode set to 100644
File size: 29.1 KB
Line 
1/*
2 * Copyright (c) 2017 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_LOCALE
30#define LIBCPP_LOCALE
31
32#include <cctype>
33#include <cstdlib>
34#include <iosfwd>
35#include <string>
36
37namespace std
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
787 class locale
788 {
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_{};
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
1019}
1020
1021#endif
Note: See TracBrowser for help on using the repository browser.