@@ -39,132 +39,37 @@ _LIBCPP_PUSH_MACROS
3939_LIBCPP_BEGIN_NAMESPACE_STD
4040
4141template <class _CharT >
42- struct _LIBCPP_TEMPLATE_VIS char_traits
42+ struct char_traits ;
43+ /*
44+ The Standard does not define the base template for char_traits because it is impossible to provide
45+ a correct definition for arbitrary character types. Instead, it requires implementations to provide
46+ specializations for predefined character types like `char`, `wchar_t` and others. We provide this as
47+ exposition-only to document what members a char_traits specialization should provide:
4348{
4449 using char_type = _CharT;
45- using int_type = int ;
46- using off_type = streamoff;
47- using pos_type = streampos;
48- using state_type = mbstate_t ;
49-
50- static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17
51- assign (char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
52- static inline _LIBCPP_CONSTEXPR bool eq (char_type __c1, char_type __c2) _NOEXCEPT
53- {return __c1 == __c2;}
54- static inline _LIBCPP_CONSTEXPR bool lt (char_type __c1, char_type __c2) _NOEXCEPT
55- {return __c1 < __c2;}
56-
57- static _LIBCPP_CONSTEXPR_SINCE_CXX17
58- int compare (const char_type* __s1, const char_type* __s2, size_t __n);
59- _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
60- size_t length (const char_type* __s);
61- _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
62- const char_type* find (const char_type* __s, size_t __n, const char_type& __a);
63- static _LIBCPP_CONSTEXPR_SINCE_CXX20
64- char_type* move (char_type* __s1, const char_type* __s2, size_t __n);
65- _LIBCPP_INLINE_VISIBILITY
66- static _LIBCPP_CONSTEXPR_SINCE_CXX20
67- char_type* copy (char_type* __s1, const char_type* __s2, size_t __n);
68- _LIBCPP_INLINE_VISIBILITY
69- static _LIBCPP_CONSTEXPR_SINCE_CXX20
70- char_type* assign (char_type* __s, size_t __n, char_type __a);
71-
72- static inline _LIBCPP_CONSTEXPR int_type not_eof (int_type __c) _NOEXCEPT
73- {return eq_int_type (__c, eof ()) ? ~eof () : __c;}
74- static inline _LIBCPP_CONSTEXPR char_type to_char_type (int_type __c) _NOEXCEPT
75- {return char_type (__c);}
76- static inline _LIBCPP_CONSTEXPR int_type to_int_type (char_type __c) _NOEXCEPT
77- {return int_type (__c);}
78- static inline _LIBCPP_CONSTEXPR bool eq_int_type (int_type __c1, int_type __c2) _NOEXCEPT
79- {return __c1 == __c2;}
80- static inline _LIBCPP_CONSTEXPR int_type eof () _NOEXCEPT
81- {return int_type (EOF);}
50+ using int_type = ...;
51+ using off_type = ...;
52+ using pos_type = ...;
53+ using state_type = ...;
54+
55+ static void assign(char_type&, const char_type&);
56+ static bool eq(char_type, char_type);
57+ static bool lt(char_type, char_type);
58+
59+ static int compare(const char_type*, const char_type*, size_t);
60+ static size_t length(const char_type*);
61+ static const char_type* find(const char_type*, size_t, const char_type&);
62+ static char_type* move(char_type*, const char_type*, size_t);
63+ static char_type* copy(char_type*, const char_type* __s2, size_t);
64+ static char_type* assign(char_type*, size_t, char_type);
65+
66+ static int_type not_eof(int_type);
67+ static char_type to_char_type(int_type);
68+ static int_type to_int_type(char_type);
69+ static bool eq_int_type(int_type, int_type);
70+ static int_type eof();
8271};
83-
84- template <class _CharT >
85- _LIBCPP_CONSTEXPR_SINCE_CXX17 int
86- char_traits<_CharT>::compare(const char_type* __s1, const char_type* __s2, size_t __n)
87- {
88- for (; __n; --__n, ++__s1, ++__s2)
89- {
90- if (lt (*__s1, *__s2))
91- return -1 ;
92- if (lt (*__s2, *__s1))
93- return 1 ;
94- }
95- return 0 ;
96- }
97-
98- template <class _CharT >
99- inline
100- _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t
101- char_traits<_CharT>::length(const char_type* __s)
102- {
103- size_t __len = 0 ;
104- for (; !eq (*__s, char_type (0 )); ++__s)
105- ++__len;
106- return __len;
107- }
108-
109- template <class _CharT >
110- inline
111- _LIBCPP_CONSTEXPR_SINCE_CXX17 const _CharT*
112- char_traits<_CharT>::find(const char_type* __s, size_t __n, const char_type& __a)
113- {
114- for (; __n; --__n)
115- {
116- if (eq (*__s, __a))
117- return __s;
118- ++__s;
119- }
120- return nullptr ;
121- }
122-
123- template <class _CharT >
124- _LIBCPP_CONSTEXPR_SINCE_CXX20 _CharT*
125- char_traits<_CharT>::move(char_type* __s1, const char_type* __s2, size_t __n)
126- {
127- if (__n == 0 ) return __s1;
128- char_type* __r = __s1;
129- if (__s1 < __s2)
130- {
131- for (; __n; --__n, ++__s1, ++__s2)
132- assign (*__s1, *__s2);
133- }
134- else if (__s2 < __s1)
135- {
136- __s1 += __n;
137- __s2 += __n;
138- for (; __n; --__n)
139- assign (*--__s1, *--__s2);
140- }
141- return __r;
142- }
143-
144- template <class _CharT >
145- inline _LIBCPP_CONSTEXPR_SINCE_CXX20
146- _CharT*
147- char_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n)
148- {
149- if (!__libcpp_is_constant_evaluated ()) {
150- _LIBCPP_ASSERT (__s2 < __s1 || __s2 >= __s1+__n, " char_traits::copy overlapped range" );
151- }
152- char_type* __r = __s1;
153- for (; __n; --__n, ++__s1, ++__s2)
154- assign (*__s1, *__s2);
155- return __r;
156- }
157-
158- template <class _CharT >
159- inline _LIBCPP_CONSTEXPR_SINCE_CXX20
160- _CharT*
161- char_traits<_CharT>::assign(char_type* __s, size_t __n, char_type __a)
162- {
163- char_type* __r = __s;
164- for (; __n; --__n, ++__s)
165- assign (*__s, __a);
166- return __r;
167- }
72+ */
16873
16974template <class _CharT >
17075_LIBCPP_HIDE_FROM_ABI static inline _LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -300,7 +205,6 @@ char_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a)
300205#endif
301206}
302207
303-
304208// char_traits<wchar_t>
305209
306210#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
@@ -713,6 +617,202 @@ char_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& _
713617 return nullptr ;
714618}
715619
620+ //
621+ // Temporary extensions for std::char_traits<unsigned char> and std::char_traits<signed char>.
622+ // TODO: Remove those in LLVM 18.
623+ //
624+ template <>
625+ struct _LIBCPP_TEMPLATE_VIS
626+ _LIBCPP_DEPRECATED_ (" char_traits<unsigned char> is non-standard and is provided for a temporary period. It will be removed in LLVM 18, so please migrate off of it." )
627+ char_traits<unsigned char>
628+ {
629+ using char_type = unsigned char ;
630+ using int_type = int ;
631+ using off_type = streamoff;
632+ using pos_type = streampos;
633+ using state_type = mbstate_t ;
634+
635+ static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17
636+ assign (char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
637+ static inline _LIBCPP_CONSTEXPR bool eq (char_type __c1, char_type __c2) _NOEXCEPT
638+ {return __c1 == __c2;}
639+ static inline _LIBCPP_CONSTEXPR bool lt (char_type __c1, char_type __c2) _NOEXCEPT
640+ {return __c1 < __c2;}
641+
642+ static _LIBCPP_CONSTEXPR_SINCE_CXX17
643+ int compare (const char_type* __s1, const char_type* __s2, size_t __n) {
644+ for (; __n; --__n, ++__s1, ++__s2)
645+ {
646+ if (lt (*__s1, *__s2))
647+ return -1 ;
648+ if (lt (*__s2, *__s1))
649+ return 1 ;
650+ }
651+ return 0 ;
652+ }
653+ _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
654+ size_t length (const char_type* __s) {
655+ size_t __len = 0 ;
656+ for (; !eq (*__s, char_type (0 )); ++__s)
657+ ++__len;
658+ return __len;
659+ }
660+ _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
661+ const char_type* find (const char_type* __s, size_t __n, const char_type& __a) {
662+ for (; __n; --__n)
663+ {
664+ if (eq (*__s, __a))
665+ return __s;
666+ ++__s;
667+ }
668+ return nullptr ;
669+ }
670+ static _LIBCPP_CONSTEXPR_SINCE_CXX20
671+ char_type* move (char_type* __s1, const char_type* __s2, size_t __n) {
672+ if (__n == 0 ) return __s1;
673+ char_type* __r = __s1;
674+ if (__s1 < __s2)
675+ {
676+ for (; __n; --__n, ++__s1, ++__s2)
677+ assign (*__s1, *__s2);
678+ }
679+ else if (__s2 < __s1)
680+ {
681+ __s1 += __n;
682+ __s2 += __n;
683+ for (; __n; --__n)
684+ assign (*--__s1, *--__s2);
685+ }
686+ return __r;
687+ }
688+ _LIBCPP_INLINE_VISIBILITY
689+ static _LIBCPP_CONSTEXPR_SINCE_CXX20
690+ char_type* copy (char_type* __s1, const char_type* __s2, size_t __n) {
691+ if (!__libcpp_is_constant_evaluated ()) {
692+ _LIBCPP_ASSERT (__s2 < __s1 || __s2 >= __s1+__n, " char_traits::copy overlapped range" );
693+ }
694+ char_type* __r = __s1;
695+ for (; __n; --__n, ++__s1, ++__s2)
696+ assign (*__s1, *__s2);
697+ return __r;
698+ }
699+ _LIBCPP_INLINE_VISIBILITY
700+ static _LIBCPP_CONSTEXPR_SINCE_CXX20
701+ char_type* assign (char_type* __s, size_t __n, char_type __a) {
702+ char_type* __r = __s;
703+ for (; __n; --__n, ++__s)
704+ assign (*__s, __a);
705+ return __r;
706+ }
707+
708+ static inline _LIBCPP_CONSTEXPR int_type not_eof (int_type __c) _NOEXCEPT
709+ {return eq_int_type (__c, eof ()) ? ~eof () : __c;}
710+ static inline _LIBCPP_CONSTEXPR char_type to_char_type (int_type __c) _NOEXCEPT
711+ {return char_type (__c);}
712+ static inline _LIBCPP_CONSTEXPR int_type to_int_type (char_type __c) _NOEXCEPT
713+ {return int_type (__c);}
714+ static inline _LIBCPP_CONSTEXPR bool eq_int_type (int_type __c1, int_type __c2) _NOEXCEPT
715+ {return __c1 == __c2;}
716+ static inline _LIBCPP_CONSTEXPR int_type eof () _NOEXCEPT
717+ {return int_type (EOF);}
718+ };
719+
720+ template <>
721+ struct _LIBCPP_TEMPLATE_VIS
722+ _LIBCPP_DEPRECATED_ (" char_traits<signed char> is non-standard and is provided for a temporary period. It will be removed in LLVM 18, so please migrate off of it." )
723+ char_traits<signed char>
724+ {
725+ using char_type = signed char ;
726+ using int_type = int ;
727+ using off_type = streamoff;
728+ using pos_type = streampos;
729+ using state_type = mbstate_t ;
730+
731+ static inline void _LIBCPP_CONSTEXPR_SINCE_CXX17
732+ assign (char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
733+ static inline _LIBCPP_CONSTEXPR bool eq (char_type __c1, char_type __c2) _NOEXCEPT
734+ {return __c1 == __c2;}
735+ static inline _LIBCPP_CONSTEXPR bool lt (char_type __c1, char_type __c2) _NOEXCEPT
736+ {return __c1 < __c2;}
737+
738+ static _LIBCPP_CONSTEXPR_SINCE_CXX17
739+ int compare (const char_type* __s1, const char_type* __s2, size_t __n) {
740+ for (; __n; --__n, ++__s1, ++__s2)
741+ {
742+ if (lt (*__s1, *__s2))
743+ return -1 ;
744+ if (lt (*__s2, *__s1))
745+ return 1 ;
746+ }
747+ return 0 ;
748+ }
749+ _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
750+ size_t length (const char_type* __s) {
751+ size_t __len = 0 ;
752+ for (; !eq (*__s, char_type (0 )); ++__s)
753+ ++__len;
754+ return __len;
755+ }
756+ _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_SINCE_CXX17
757+ const char_type* find (const char_type* __s, size_t __n, const char_type& __a) {
758+ for (; __n; --__n)
759+ {
760+ if (eq (*__s, __a))
761+ return __s;
762+ ++__s;
763+ }
764+ return nullptr ;
765+ }
766+ static _LIBCPP_CONSTEXPR_SINCE_CXX20
767+ char_type* move (char_type* __s1, const char_type* __s2, size_t __n) {
768+ if (__n == 0 ) return __s1;
769+ char_type* __r = __s1;
770+ if (__s1 < __s2)
771+ {
772+ for (; __n; --__n, ++__s1, ++__s2)
773+ assign (*__s1, *__s2);
774+ }
775+ else if (__s2 < __s1)
776+ {
777+ __s1 += __n;
778+ __s2 += __n;
779+ for (; __n; --__n)
780+ assign (*--__s1, *--__s2);
781+ }
782+ return __r;
783+ }
784+ _LIBCPP_INLINE_VISIBILITY
785+ static _LIBCPP_CONSTEXPR_SINCE_CXX20
786+ char_type* copy (char_type* __s1, const char_type* __s2, size_t __n) {
787+ if (!__libcpp_is_constant_evaluated ()) {
788+ _LIBCPP_ASSERT (__s2 < __s1 || __s2 >= __s1+__n, " char_traits::copy overlapped range" );
789+ }
790+ char_type* __r = __s1;
791+ for (; __n; --__n, ++__s1, ++__s2)
792+ assign (*__s1, *__s2);
793+ return __r;
794+ }
795+ _LIBCPP_INLINE_VISIBILITY
796+ static _LIBCPP_CONSTEXPR_SINCE_CXX20
797+ char_type* assign (char_type* __s, size_t __n, char_type __a) {
798+ char_type* __r = __s;
799+ for (; __n; --__n, ++__s)
800+ assign (*__s, __a);
801+ return __r;
802+ }
803+
804+ static inline _LIBCPP_CONSTEXPR int_type not_eof (int_type __c) _NOEXCEPT
805+ {return eq_int_type (__c, eof ()) ? ~eof () : __c;}
806+ static inline _LIBCPP_CONSTEXPR char_type to_char_type (int_type __c) _NOEXCEPT
807+ {return char_type (__c);}
808+ static inline _LIBCPP_CONSTEXPR int_type to_int_type (char_type __c) _NOEXCEPT
809+ {return int_type (__c);}
810+ static inline _LIBCPP_CONSTEXPR bool eq_int_type (int_type __c1, int_type __c2) _NOEXCEPT
811+ {return __c1 == __c2;}
812+ static inline _LIBCPP_CONSTEXPR int_type eof () _NOEXCEPT
813+ {return int_type (EOF);}
814+ };
815+
716816// helper fns for basic_string and string_view
717817
718818// __str_find
0 commit comments