xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/bits/char_traits.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 // Character Traits for use by standard string and iostream -*- C++ -*-
2 
3 // Copyright (C) 1997-2022 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file bits/char_traits.h
26  *  This is an internal header file, included by other library headers.
27  *  Do not attempt to use it directly. @headername{string}
28  */
29 
30 //
31 // ISO C++ 14882: 21  Strings library
32 //
33 
34 #ifndef _CHAR_TRAITS_H
35 #define _CHAR_TRAITS_H 1
36 
37 #pragma GCC system_header
38 
39 #include <bits/postypes.h>      // For streampos
40 #include <cwchar>               // For WEOF, wmemmove, wmemset, etc.
41 #if __cplusplus >= 201103L
42 # include <type_traits>
43 #endif
44 #if __cplusplus >= 202002L
45 # include <compare>
46 # include <bits/stl_construct.h>
47 #endif
48 
49 #ifndef _GLIBCXX_ALWAYS_INLINE
50 # define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
51 #endif
52 
_GLIBCXX_VISIBILITY(default)53 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
54 {
55 _GLIBCXX_BEGIN_NAMESPACE_VERSION
56 
57 #pragma GCC diagnostic push
58 #pragma GCC diagnostic ignored "-Wstringop-overflow"
59 #pragma GCC diagnostic ignored "-Wstringop-overread"
60 #pragma GCC diagnostic ignored "-Warray-bounds"
61 
62   /**
63    *  @brief  Mapping from character type to associated types.
64    *
65    *  @note This is an implementation class for the generic version
66    *  of char_traits.  It defines int_type, off_type, pos_type, and
67    *  state_type.  By default these are unsigned long, streamoff,
68    *  streampos, and mbstate_t.  Users who need a different set of
69    *  types, but who don't need to change the definitions of any function
70    *  defined in char_traits, can specialize __gnu_cxx::_Char_types
71    *  while leaving __gnu_cxx::char_traits alone. */
72   template<typename _CharT>
73     struct _Char_types
74     {
75       typedef unsigned long   int_type;
76       typedef std::streampos  pos_type;
77       typedef std::streamoff  off_type;
78       typedef std::mbstate_t  state_type;
79     };
80 
81 
82   /**
83    *  @brief  Base class used to implement std::char_traits.
84    *
85    *  @note For any given actual character type, this definition is
86    *  probably wrong.  (Most of the member functions are likely to be
87    *  right, but the int_type and state_type typedefs, and the eof()
88    *  member function, are likely to be wrong.)  The reason this class
89    *  exists is so users can specialize it.  Classes in namespace std
90    *  may not be specialized for fundamental types, but classes in
91    *  namespace __gnu_cxx may be.
92    *
93    *  See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
94    *  for advice on how to make use of this class for @a unusual character
95    *  types. Also, check out include/ext/pod_char_traits.h.
96    */
97   template<typename _CharT>
98     struct char_traits
99     {
100       typedef _CharT                                    char_type;
101       typedef typename _Char_types<_CharT>::int_type    int_type;
102       typedef typename _Char_types<_CharT>::pos_type    pos_type;
103       typedef typename _Char_types<_CharT>::off_type    off_type;
104       typedef typename _Char_types<_CharT>::state_type  state_type;
105 #if __cpp_lib_three_way_comparison
106       using comparison_category = std::strong_ordering;
107 #endif
108 
109       static _GLIBCXX14_CONSTEXPR void
110       assign(char_type& __c1, const char_type& __c2)
111       {
112 #if __cpp_constexpr_dynamic_alloc
113 	if (std::__is_constant_evaluated())
114 	  std::construct_at(__builtin_addressof(__c1), __c2);
115 	else
116 #endif
117 	__c1 = __c2;
118       }
119 
120       static _GLIBCXX_CONSTEXPR bool
121       eq(const char_type& __c1, const char_type& __c2)
122       { return __c1 == __c2; }
123 
124       static _GLIBCXX_CONSTEXPR bool
125       lt(const char_type& __c1, const char_type& __c2)
126       { return __c1 < __c2; }
127 
128       static _GLIBCXX14_CONSTEXPR int
129       compare(const char_type* __s1, const char_type* __s2, std::size_t __n);
130 
131       static _GLIBCXX14_CONSTEXPR std::size_t
132       length(const char_type* __s);
133 
134       static _GLIBCXX14_CONSTEXPR const char_type*
135       find(const char_type* __s, std::size_t __n, const char_type& __a);
136 
137       static _GLIBCXX20_CONSTEXPR char_type*
138       move(char_type* __s1, const char_type* __s2, std::size_t __n);
139 
140       static _GLIBCXX20_CONSTEXPR char_type*
141       copy(char_type* __s1, const char_type* __s2, std::size_t __n);
142 
143       static _GLIBCXX20_CONSTEXPR char_type*
144       assign(char_type* __s, std::size_t __n, char_type __a);
145 
146       static _GLIBCXX_CONSTEXPR char_type
147       to_char_type(const int_type& __c)
148       { return static_cast<char_type>(__c); }
149 
150       static _GLIBCXX_CONSTEXPR int_type
151       to_int_type(const char_type& __c)
152       { return static_cast<int_type>(__c); }
153 
154       static _GLIBCXX_CONSTEXPR bool
155       eq_int_type(const int_type& __c1, const int_type& __c2)
156       { return __c1 == __c2; }
157 
158       static _GLIBCXX_CONSTEXPR int_type
159       eof()
160       { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
161 
162       static _GLIBCXX_CONSTEXPR int_type
163       not_eof(const int_type& __c)
164       { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); }
165     };
166 
167   template<typename _CharT>
168     _GLIBCXX14_CONSTEXPR int
169     char_traits<_CharT>::
170     compare(const char_type* __s1, const char_type* __s2, std::size_t __n)
171     {
172       for (std::size_t __i = 0; __i < __n; ++__i)
173 	if (lt(__s1[__i], __s2[__i]))
174 	  return -1;
175 	else if (lt(__s2[__i], __s1[__i]))
176 	  return 1;
177       return 0;
178     }
179 
180   template<typename _CharT>
181     _GLIBCXX14_CONSTEXPR std::size_t
182     char_traits<_CharT>::
183     length(const char_type* __p)
184     {
185       std::size_t __i = 0;
186       while (!eq(__p[__i], char_type()))
187         ++__i;
188       return __i;
189     }
190 
191   template<typename _CharT>
192     _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type*
193     char_traits<_CharT>::
194     find(const char_type* __s, std::size_t __n, const char_type& __a)
195     {
196       for (std::size_t __i = 0; __i < __n; ++__i)
197         if (eq(__s[__i], __a))
198           return __s + __i;
199       return 0;
200     }
201 
202   template<typename _CharT>
203     _GLIBCXX20_CONSTEXPR
204     typename char_traits<_CharT>::char_type*
205     char_traits<_CharT>::
206     move(char_type* __s1, const char_type* __s2, std::size_t __n)
207     {
208       if (__n == 0)
209 	return __s1;
210 #if __cplusplus >= 202002L
211       if (std::__is_constant_evaluated())
212 	{
213 #if __cpp_constexpr_dynamic_alloc
214 	  // The overlap detection below fails due to PR c++/89074,
215 	  // so use a temporary buffer instead.
216 	  char_type* __tmp = new char_type[__n];
217 	  copy(__tmp, __s2, __n);
218 	  copy(__s1, __tmp, __n);
219 	  delete[] __tmp;
220 #else
221 	  // Use __builtin_constant_p to avoid comparing unrelated pointers.
222 	  if (__builtin_constant_p(__s2 < __s1)
223 		&& __s1 > __s2 && __s1 < (__s2 + __n))
224 	    {
225 	      do
226 		{
227 		  --__n;
228 		  assign(__s1[__n], __s2[__n]);
229 		}
230 	      while (__n > 0);
231 	    }
232 	  else
233 	    copy(__s1, __s2, __n);
234 #endif
235 	  return __s1;
236 	}
237 #endif
238       __builtin_memmove(__s1, __s2, __n * sizeof(char_type));
239       return __s1;
240     }
241 
242   template<typename _CharT>
243     _GLIBCXX20_CONSTEXPR
244     typename char_traits<_CharT>::char_type*
245     char_traits<_CharT>::
246     copy(char_type* __s1, const char_type* __s2, std::size_t __n)
247     {
248       if (__n == 0)
249 	return __s1;
250 #if __cplusplus >= 202002L
251       if (std::__is_constant_evaluated())
252 	{
253 	  for (std::size_t __i = 0; __i < __n; ++__i)
254 	    std::construct_at(__s1 + __i, __s2[__i]);
255 	  return __s1;
256 	}
257 #endif
258       __builtin_memcpy(__s1, __s2, __n * sizeof(char_type));
259       return __s1;
260     }
261 
262   template<typename _CharT>
263     _GLIBCXX20_CONSTEXPR
264     typename char_traits<_CharT>::char_type*
265     char_traits<_CharT>::
266     assign(char_type* __s, std::size_t __n, char_type __a)
267     {
268 #if __cplusplus >= 202002L
269       if (std::__is_constant_evaluated())
270 	{
271 	  for (std::size_t __i = 0; __i < __n; ++__i)
272 	    std::construct_at(__s + __i, __a);
273 	  return __s;
274 	}
275 #endif
276 
277       if _GLIBCXX17_CONSTEXPR (sizeof(_CharT) == 1 && __is_trivial(_CharT))
278 	{
279 	  if (__n)
280 	    {
281 	      unsigned char __c;
282 	      __builtin_memcpy(&__c, __builtin_addressof(__a), 1);
283 	      __builtin_memset(__s, __c, __n);
284 	    }
285 	}
286       else
287 	{
288 	  for (std::size_t __i = 0; __i < __n; ++__i)
289 	    __s[__i] = __a;
290 	}
291       return __s;
292     }
293 
294 _GLIBCXX_END_NAMESPACE_VERSION
295 } // namespace
296 
_GLIBCXX_VISIBILITY(default)297 namespace std _GLIBCXX_VISIBILITY(default)
298 {
299 _GLIBCXX_BEGIN_NAMESPACE_VERSION
300 
301 #ifdef __cpp_lib_is_constant_evaluated
302 // Unofficial macro indicating P1032R1 support in C++20
303 # define __cpp_lib_constexpr_char_traits 201811L
304 #elif __cplusplus >= 201703L && _GLIBCXX_HAVE_IS_CONSTANT_EVALUATED
305 // Unofficial macro indicating P0426R1 support in C++17
306 # define __cpp_lib_constexpr_char_traits 201611L
307 #endif
308 
309   // 21.1
310   /**
311    *  @brief  Basis for explicit traits specializations.
312    *
313    *  @note  For any given actual character type, this definition is
314    *  probably wrong.  Since this is just a thin wrapper around
315    *  __gnu_cxx::char_traits, it is possible to achieve a more
316    *  appropriate definition by specializing __gnu_cxx::char_traits.
317    *
318    *  See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types
319    *  for advice on how to make use of this class for @a unusual character
320    *  types. Also, check out include/ext/pod_char_traits.h.
321   */
322   template<typename _CharT>
323     struct char_traits : public __gnu_cxx::char_traits<_CharT>
324     { };
325 
326 
327   /// 21.1.3.1  char_traits specializations
328   template<>
329     struct char_traits<char>
330     {
331       typedef char              char_type;
332       typedef int               int_type;
333       typedef streampos         pos_type;
334       typedef streamoff         off_type;
335       typedef mbstate_t         state_type;
336 #if __cpp_lib_three_way_comparison
337       using comparison_category = strong_ordering;
338 #endif
339 
340       static _GLIBCXX17_CONSTEXPR void
341       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
342       {
343 #if __cpp_constexpr_dynamic_alloc
344 	if (std::__is_constant_evaluated())
345 	  std::construct_at(__builtin_addressof(__c1), __c2);
346 	else
347 #endif
348 	__c1 = __c2;
349       }
350 
351       static _GLIBCXX_CONSTEXPR bool
352       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
353       { return __c1 == __c2; }
354 
355       static _GLIBCXX_CONSTEXPR bool
356       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
357       {
358 	// LWG 467.
359 	return (static_cast<unsigned char>(__c1)
360 		< static_cast<unsigned char>(__c2));
361       }
362 
363       static _GLIBCXX17_CONSTEXPR int
364       compare(const char_type* __s1, const char_type* __s2, size_t __n)
365       {
366 	if (__n == 0)
367 	  return 0;
368 #if __cplusplus >= 201703L
369 	if (std::__is_constant_evaluated())
370 	  {
371 	    for (size_t __i = 0; __i < __n; ++__i)
372 	      if (lt(__s1[__i], __s2[__i]))
373 		return -1;
374 	      else if (lt(__s2[__i], __s1[__i]))
375 		return 1;
376 	    return 0;
377 	  }
378 #endif
379 	return __builtin_memcmp(__s1, __s2, __n);
380       }
381 
382       static _GLIBCXX17_CONSTEXPR size_t
383       length(const char_type* __s)
384       {
385 #if __cplusplus >= 201703L
386 	if (std::__is_constant_evaluated())
387 	  return __gnu_cxx::char_traits<char_type>::length(__s);
388 #endif
389 	return __builtin_strlen(__s);
390       }
391 
392       static _GLIBCXX17_CONSTEXPR const char_type*
393       find(const char_type* __s, size_t __n, const char_type& __a)
394       {
395 	if (__n == 0)
396 	  return 0;
397 #if __cplusplus >= 201703L
398 	if (std::__is_constant_evaluated())
399 	  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
400 #endif
401 	return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
402       }
403 
404       static _GLIBCXX20_CONSTEXPR char_type*
405       move(char_type* __s1, const char_type* __s2, size_t __n)
406       {
407 	if (__n == 0)
408 	  return __s1;
409 #if __cplusplus >= 202002L
410 	if (std::__is_constant_evaluated())
411 	  return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
412 #endif
413 	return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
414       }
415 
416       static _GLIBCXX20_CONSTEXPR char_type*
417       copy(char_type* __s1, const char_type* __s2, size_t __n)
418       {
419 	if (__n == 0)
420 	  return __s1;
421 #if __cplusplus >= 202002L
422 	if (std::__is_constant_evaluated())
423 	  return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
424 #endif
425 	return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
426       }
427 
428       static _GLIBCXX20_CONSTEXPR char_type*
429       assign(char_type* __s, size_t __n, char_type __a)
430       {
431 	if (__n == 0)
432 	  return __s;
433 #if __cplusplus >= 202002L
434 	if (std::__is_constant_evaluated())
435 	  return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
436 #endif
437 	return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
438       }
439 
440       static _GLIBCXX_CONSTEXPR char_type
441       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
442       { return static_cast<char_type>(__c); }
443 
444       // To keep both the byte 0xff and the eof symbol 0xffffffff
445       // from ending up as 0xffffffff.
446       static _GLIBCXX_CONSTEXPR int_type
447       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
448       { return static_cast<int_type>(static_cast<unsigned char>(__c)); }
449 
450       static _GLIBCXX_CONSTEXPR bool
451       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
452       { return __c1 == __c2; }
453 
454       static _GLIBCXX_CONSTEXPR int_type
455       eof() _GLIBCXX_NOEXCEPT
456       { return static_cast<int_type>(_GLIBCXX_STDIO_EOF); }
457 
458       static _GLIBCXX_CONSTEXPR int_type
459       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
460       { return (__c == eof()) ? 0 : __c; }
461   };
462 
463 
464 #ifdef _GLIBCXX_USE_WCHAR_T
465   /// 21.1.3.2  char_traits specializations
466   template<>
467     struct char_traits<wchar_t>
468     {
469       typedef wchar_t           char_type;
470       typedef wint_t            int_type;
471       typedef streamoff         off_type;
472       typedef wstreampos        pos_type;
473       typedef mbstate_t         state_type;
474 #if __cpp_lib_three_way_comparison
475       using comparison_category = strong_ordering;
476 #endif
477 
478       static _GLIBCXX17_CONSTEXPR void
479       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
480       {
481 #if __cpp_constexpr_dynamic_alloc
482 	if (std::__is_constant_evaluated())
483 	  std::construct_at(__builtin_addressof(__c1), __c2);
484 	else
485 #endif
486 	__c1 = __c2;
487       }
488 
489       static _GLIBCXX_CONSTEXPR bool
490       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
491       { return __c1 == __c2; }
492 
493       static _GLIBCXX_CONSTEXPR bool
494       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
495       { return __c1 < __c2; }
496 
497       static _GLIBCXX17_CONSTEXPR int
498       compare(const char_type* __s1, const char_type* __s2, size_t __n)
499       {
500 	if (__n == 0)
501 	  return 0;
502 #if __cplusplus >= 201703L
503 	if (std::__is_constant_evaluated())
504 	  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
505 #endif
506 	return wmemcmp(__s1, __s2, __n);
507       }
508 
509       static _GLIBCXX17_CONSTEXPR size_t
510       length(const char_type* __s)
511       {
512 #if __cplusplus >= 201703L
513 	if (std::__is_constant_evaluated())
514 	  return __gnu_cxx::char_traits<char_type>::length(__s);
515 #endif
516 	return wcslen(__s);
517       }
518 
519       static _GLIBCXX17_CONSTEXPR const char_type*
520       find(const char_type* __s, size_t __n, const char_type& __a)
521       {
522 	if (__n == 0)
523 	  return 0;
524 #if __cplusplus >= 201703L
525 	if (std::__is_constant_evaluated())
526 	  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
527 #endif
528 	return wmemchr(__s, __a, __n);
529       }
530 
531       static _GLIBCXX20_CONSTEXPR char_type*
532       move(char_type* __s1, const char_type* __s2, size_t __n)
533       {
534 	if (__n == 0)
535 	  return __s1;
536 #if __cplusplus >= 202002L
537 	if (std::__is_constant_evaluated())
538 	  return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
539 #endif
540 	return wmemmove(__s1, __s2, __n);
541       }
542 
543       static _GLIBCXX20_CONSTEXPR char_type*
544       copy(char_type* __s1, const char_type* __s2, size_t __n)
545       {
546 	if (__n == 0)
547 	  return __s1;
548 #if __cplusplus >= 202002L
549 	if (std::__is_constant_evaluated())
550 	  return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
551 #endif
552 	return wmemcpy(__s1, __s2, __n);
553       }
554 
555       static _GLIBCXX20_CONSTEXPR char_type*
556       assign(char_type* __s, size_t __n, char_type __a)
557       {
558 	if (__n == 0)
559 	  return __s;
560 #if __cplusplus >= 202002L
561 	if (std::__is_constant_evaluated())
562 	  return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
563 #endif
564 	return wmemset(__s, __a, __n);
565       }
566 
567       static _GLIBCXX_CONSTEXPR char_type
568       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
569       { return char_type(__c); }
570 
571       static _GLIBCXX_CONSTEXPR int_type
572       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
573       { return int_type(__c); }
574 
575       static _GLIBCXX_CONSTEXPR bool
576       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
577       { return __c1 == __c2; }
578 
579       static _GLIBCXX_CONSTEXPR int_type
580       eof() _GLIBCXX_NOEXCEPT
581       { return static_cast<int_type>(WEOF); }
582 
583       static _GLIBCXX_CONSTEXPR int_type
584       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
585       { return eq_int_type(__c, eof()) ? 0 : __c; }
586   };
587 #else // _GLIBCXX_USE_WCHAR_T
588   template<>
589     struct char_traits<wchar_t> : public __gnu_cxx::char_traits<wchar_t>
590     { };
591 #endif //_GLIBCXX_USE_WCHAR_T
592 
593 #ifdef _GLIBCXX_USE_CHAR8_T
594   template<>
595     struct char_traits<char8_t>
596     {
597       typedef char8_t           char_type;
598       typedef unsigned int      int_type;
599       typedef u8streampos       pos_type;
600       typedef streamoff         off_type;
601       typedef mbstate_t         state_type;
602 #if __cpp_lib_three_way_comparison
603       using comparison_category = strong_ordering;
604 #endif
605 
606       static _GLIBCXX17_CONSTEXPR void
607       assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
608       {
609 #if __cpp_constexpr_dynamic_alloc
610 	if (std::__is_constant_evaluated())
611 	  std::construct_at(__builtin_addressof(__c1), __c2);
612 	else
613 #endif
614 	__c1 = __c2;
615       }
616 
617       static _GLIBCXX_CONSTEXPR bool
618       eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
619       { return __c1 == __c2; }
620 
621       static _GLIBCXX_CONSTEXPR bool
622       lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
623       { return __c1 < __c2; }
624 
625       static _GLIBCXX17_CONSTEXPR int
626       compare(const char_type* __s1, const char_type* __s2, size_t __n)
627       {
628 	if (__n == 0)
629 	  return 0;
630 #if __cplusplus >= 201703L
631 	if (std::__is_constant_evaluated())
632 	  return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
633 #endif
634 	return __builtin_memcmp(__s1, __s2, __n);
635       }
636 
637       static _GLIBCXX17_CONSTEXPR size_t
638       length(const char_type* __s)
639       {
640 #if __cplusplus >= 201703L
641 	if (std::__is_constant_evaluated())
642 	  return __gnu_cxx::char_traits<char_type>::length(__s);
643 #endif
644 	size_t __i = 0;
645 	while (!eq(__s[__i], char_type()))
646 	  ++__i;
647 	return __i;
648       }
649 
650       static _GLIBCXX17_CONSTEXPR const char_type*
651       find(const char_type* __s, size_t __n, const char_type& __a)
652       {
653 	if (__n == 0)
654 	  return 0;
655 #if __cplusplus >= 201703L
656 	if (std::__is_constant_evaluated())
657 	  return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
658 #endif
659 	return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
660       }
661 
662       static _GLIBCXX20_CONSTEXPR char_type*
663       move(char_type* __s1, const char_type* __s2, size_t __n)
664       {
665 	if (__n == 0)
666 	  return __s1;
667 #if __cplusplus >= 202002L
668 	if (std::__is_constant_evaluated())
669 	  return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
670 #endif
671 	return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
672       }
673 
674       static _GLIBCXX20_CONSTEXPR char_type*
675       copy(char_type* __s1, const char_type* __s2, size_t __n)
676       {
677 	if (__n == 0)
678 	  return __s1;
679 #if __cplusplus >= 202002L
680 	if (std::__is_constant_evaluated())
681 	  return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
682 #endif
683 	return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
684       }
685 
686       static _GLIBCXX20_CONSTEXPR char_type*
687       assign(char_type* __s, size_t __n, char_type __a)
688       {
689 	if (__n == 0)
690 	  return __s;
691 #if __cplusplus >= 202002L
692 	if (std::__is_constant_evaluated())
693 	  return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
694 #endif
695 	return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
696       }
697 
698       static _GLIBCXX_CONSTEXPR char_type
699       to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT
700       { return char_type(__c); }
701 
702       static _GLIBCXX_CONSTEXPR int_type
703       to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT
704       { return int_type(__c); }
705 
706       static _GLIBCXX_CONSTEXPR bool
707       eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT
708       { return __c1 == __c2; }
709 
710       static _GLIBCXX_CONSTEXPR int_type
711       eof() _GLIBCXX_NOEXCEPT
712       { return static_cast<int_type>(-1); }
713 
714       static _GLIBCXX_CONSTEXPR int_type
715       not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
716       { return eq_int_type(__c, eof()) ? 0 : __c; }
717     };
718 #endif //_GLIBCXX_USE_CHAR8_T
719 
720 _GLIBCXX_END_NAMESPACE_VERSION
721 } // namespace
722 
723 #if __cplusplus >= 201103L
724 
725 #include <cstdint>
726 
727 namespace std _GLIBCXX_VISIBILITY(default)
728 {
729 _GLIBCXX_BEGIN_NAMESPACE_VERSION
730 
731   template<>
732     struct char_traits<char16_t>
733     {
734       typedef char16_t          char_type;
735 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
736       typedef uint_least16_t    int_type;
737 #elif defined __UINT_LEAST16_TYPE__
738       typedef __UINT_LEAST16_TYPE__	    int_type;
739 #else
740       typedef make_unsigned<char16_t>::type int_type;
741 #endif
742       typedef streamoff         off_type;
743       typedef u16streampos      pos_type;
744       typedef mbstate_t         state_type;
745 #if __cpp_lib_three_way_comparison
746       using comparison_category = strong_ordering;
747 #endif
748 
749       static _GLIBCXX17_CONSTEXPR void
750       assign(char_type& __c1, const char_type& __c2) noexcept
751       {
752 #if __cpp_constexpr_dynamic_alloc
753 	if (std::__is_constant_evaluated())
754 	  std::construct_at(__builtin_addressof(__c1), __c2);
755 	else
756 #endif
757 	__c1 = __c2;
758       }
759 
760       static constexpr bool
761       eq(const char_type& __c1, const char_type& __c2) noexcept
762       { return __c1 == __c2; }
763 
764       static constexpr bool
765       lt(const char_type& __c1, const char_type& __c2) noexcept
766       { return __c1 < __c2; }
767 
768       static _GLIBCXX17_CONSTEXPR int
769       compare(const char_type* __s1, const char_type* __s2, size_t __n)
770       {
771 	for (size_t __i = 0; __i < __n; ++__i)
772 	  if (lt(__s1[__i], __s2[__i]))
773 	    return -1;
774 	  else if (lt(__s2[__i], __s1[__i]))
775 	    return 1;
776 	return 0;
777       }
778 
779       static _GLIBCXX17_CONSTEXPR size_t
780       length(const char_type* __s)
781       {
782 	size_t __i = 0;
783 	while (!eq(__s[__i], char_type()))
784 	  ++__i;
785 	return __i;
786       }
787 
788       static _GLIBCXX17_CONSTEXPR const char_type*
789       find(const char_type* __s, size_t __n, const char_type& __a)
790       {
791 	for (size_t __i = 0; __i < __n; ++__i)
792 	  if (eq(__s[__i], __a))
793 	    return __s + __i;
794 	return 0;
795       }
796 
797       static _GLIBCXX20_CONSTEXPR char_type*
798       move(char_type* __s1, const char_type* __s2, size_t __n)
799       {
800 	if (__n == 0)
801 	  return __s1;
802 #if __cplusplus >= 202002L
803 	if (std::__is_constant_evaluated())
804 	  return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
805 #endif
806 	return (static_cast<char_type*>
807 		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
808       }
809 
810       static _GLIBCXX20_CONSTEXPR char_type*
811       copy(char_type* __s1, const char_type* __s2, size_t __n)
812       {
813 	if (__n == 0)
814 	  return __s1;
815 #if __cplusplus >= 202002L
816 	if (std::__is_constant_evaluated())
817 	  return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
818 #endif
819 	return (static_cast<char_type*>
820 		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
821       }
822 
823       static _GLIBCXX20_CONSTEXPR char_type*
824       assign(char_type* __s, size_t __n, char_type __a)
825       {
826 	for (size_t __i = 0; __i < __n; ++__i)
827 	  assign(__s[__i], __a);
828 	return __s;
829       }
830 
831       static constexpr char_type
832       to_char_type(const int_type& __c) noexcept
833       { return char_type(__c); }
834 
835       static constexpr int_type
836       to_int_type(const char_type& __c) noexcept
837       { return __c == eof() ? int_type(0xfffd) : int_type(__c); }
838 
839       static constexpr bool
840       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
841       { return __c1 == __c2; }
842 
843       static constexpr int_type
844       eof() noexcept
845       { return static_cast<int_type>(-1); }
846 
847       static constexpr int_type
848       not_eof(const int_type& __c) noexcept
849       { return eq_int_type(__c, eof()) ? 0 : __c; }
850     };
851 
852   template<>
853     struct char_traits<char32_t>
854     {
855       typedef char32_t          char_type;
856 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
857       typedef uint_least32_t    int_type;
858 #elif defined __UINT_LEAST32_TYPE__
859       typedef __UINT_LEAST32_TYPE__	    int_type;
860 #else
861       typedef make_unsigned<char32_t>::type int_type;
862 #endif
863       typedef streamoff         off_type;
864       typedef u32streampos      pos_type;
865       typedef mbstate_t         state_type;
866 #if __cpp_lib_three_way_comparison
867       using comparison_category = strong_ordering;
868 #endif
869 
870       static _GLIBCXX17_CONSTEXPR void
871       assign(char_type& __c1, const char_type& __c2) noexcept
872       {
873 #if __cpp_constexpr_dynamic_alloc
874 	if (std::__is_constant_evaluated())
875 	  std::construct_at(__builtin_addressof(__c1), __c2);
876 	else
877 #endif
878 	__c1 = __c2;
879       }
880 
881       static constexpr bool
882       eq(const char_type& __c1, const char_type& __c2) noexcept
883       { return __c1 == __c2; }
884 
885       static constexpr bool
886       lt(const char_type& __c1, const char_type& __c2) noexcept
887       { return __c1 < __c2; }
888 
889       static _GLIBCXX17_CONSTEXPR int
890       compare(const char_type* __s1, const char_type* __s2, size_t __n)
891       {
892 	for (size_t __i = 0; __i < __n; ++__i)
893 	  if (lt(__s1[__i], __s2[__i]))
894 	    return -1;
895 	  else if (lt(__s2[__i], __s1[__i]))
896 	    return 1;
897 	return 0;
898       }
899 
900       static _GLIBCXX17_CONSTEXPR size_t
901       length(const char_type* __s)
902       {
903 	size_t __i = 0;
904 	while (!eq(__s[__i], char_type()))
905 	  ++__i;
906 	return __i;
907       }
908 
909       static _GLIBCXX17_CONSTEXPR const char_type*
910       find(const char_type* __s, size_t __n, const char_type& __a)
911       {
912 	for (size_t __i = 0; __i < __n; ++__i)
913 	  if (eq(__s[__i], __a))
914 	    return __s + __i;
915 	return 0;
916       }
917 
918       static _GLIBCXX20_CONSTEXPR char_type*
919       move(char_type* __s1, const char_type* __s2, size_t __n)
920       {
921 	if (__n == 0)
922 	  return __s1;
923 #if __cplusplus >= 202002L
924 	if (std::__is_constant_evaluated())
925 	  return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
926 #endif
927 	return (static_cast<char_type*>
928 		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
929       }
930 
931       static _GLIBCXX20_CONSTEXPR char_type*
932       copy(char_type* __s1, const char_type* __s2, size_t __n)
933       {
934 	if (__n == 0)
935 	  return __s1;
936 #if __cplusplus >= 202002L
937 	if (std::__is_constant_evaluated())
938 	  return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
939 #endif
940 	return (static_cast<char_type*>
941 		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
942       }
943 
944       static _GLIBCXX20_CONSTEXPR char_type*
945       assign(char_type* __s, size_t __n, char_type __a)
946       {
947 	for (size_t __i = 0; __i < __n; ++__i)
948 	  assign(__s[__i], __a);
949 	return __s;
950       }
951 
952       static constexpr char_type
953       to_char_type(const int_type& __c) noexcept
954       { return char_type(__c); }
955 
956       static constexpr int_type
957       to_int_type(const char_type& __c) noexcept
958       { return int_type(__c); }
959 
960       static constexpr bool
961       eq_int_type(const int_type& __c1, const int_type& __c2) noexcept
962       { return __c1 == __c2; }
963 
964       static constexpr int_type
965       eof() noexcept
966       { return static_cast<int_type>(-1); }
967 
968       static constexpr int_type
969       not_eof(const int_type& __c) noexcept
970       { return eq_int_type(__c, eof()) ? 0 : __c; }
971     };
972 
973 #if __cpp_lib_three_way_comparison
974   namespace __detail
975   {
976     template<typename _ChTraits>
977       constexpr auto
978       __char_traits_cmp_cat(int __cmp) noexcept
979       {
980 	if constexpr (requires { typename _ChTraits::comparison_category; })
981 	  {
982 	    using _Cat = typename _ChTraits::comparison_category;
983 	    static_assert( !is_void_v<common_comparison_category_t<_Cat>> );
984 	    return static_cast<_Cat>(__cmp <=> 0);
985 	  }
986 	else
987 	  return static_cast<weak_ordering>(__cmp <=> 0);
988       }
989   } // namespace __detail
990 #endif // C++20
991 
992 #pragma GCC diagnostic pop
993 
994 _GLIBCXX_END_NAMESPACE_VERSION
995 } // namespace
996 
997 #endif  // C++11
998 
999 #endif // _CHAR_TRAITS_H
1000