xref: /netbsd-src/external/apache2/llvm/dist/libcxx/include/__string (revision 4d6fc14bc9b0c5bf3e30be318c143ee82cadd108)
1*4d6fc14bSjoerg// -*- C++ -*-
2*4d6fc14bSjoerg//===-------------------------- __string ----------------------------------===//
3*4d6fc14bSjoerg//
4*4d6fc14bSjoerg// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*4d6fc14bSjoerg// See https://llvm.org/LICENSE.txt for license information.
6*4d6fc14bSjoerg// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*4d6fc14bSjoerg//
8*4d6fc14bSjoerg//===----------------------------------------------------------------------===//
9*4d6fc14bSjoerg
10*4d6fc14bSjoerg#ifndef _LIBCPP___STRING
11*4d6fc14bSjoerg#define _LIBCPP___STRING
12*4d6fc14bSjoerg
13*4d6fc14bSjoerg#include <__config>
14*4d6fc14bSjoerg#include <algorithm>  // for search and min
15*4d6fc14bSjoerg#include <cstdio>     // for EOF
16*4d6fc14bSjoerg#include <cstring>    // for memcpy
17*4d6fc14bSjoerg#include <cwchar>     // for wmemcpy
18*4d6fc14bSjoerg#include <memory>     // for __murmur2_or_cityhash
19*4d6fc14bSjoerg
20*4d6fc14bSjoerg#include <__debug>
21*4d6fc14bSjoerg
22*4d6fc14bSjoerg#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23*4d6fc14bSjoerg#pragma GCC system_header
24*4d6fc14bSjoerg#endif
25*4d6fc14bSjoerg
26*4d6fc14bSjoerg_LIBCPP_PUSH_MACROS
27*4d6fc14bSjoerg#include <__undef_macros>
28*4d6fc14bSjoerg
29*4d6fc14bSjoerg
30*4d6fc14bSjoerg_LIBCPP_BEGIN_NAMESPACE_STD
31*4d6fc14bSjoerg
32*4d6fc14bSjoerg// The the extern template ABI lists are kept outside of <string> to improve the
33*4d6fc14bSjoerg// readability of that header.
34*4d6fc14bSjoerg
35*4d6fc14bSjoerg// The extern template ABI lists are kept outside of <string> to improve the
36*4d6fc14bSjoerg// readability of that header. We maintain 2 ABI lists:
37*4d6fc14bSjoerg// - _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST
38*4d6fc14bSjoerg// - _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST
39*4d6fc14bSjoerg// As the name implies, the ABI lists define the V1 (Stable) and unstable ABI.
40*4d6fc14bSjoerg//
41*4d6fc14bSjoerg// For unstable, we may explicitly remove function that are external in V1,
42*4d6fc14bSjoerg// and add (new) external functions to better control inlining and compiler
43*4d6fc14bSjoerg// optimization opportunities.
44*4d6fc14bSjoerg//
45*4d6fc14bSjoerg// For stable, the ABI list should rarely change, except for adding new
46*4d6fc14bSjoerg// functions supporting new c++ version / API changes. Typically entries
47*4d6fc14bSjoerg// must never be removed from the stable list.
48*4d6fc14bSjoerg#define _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_Func, _CharType) \
49*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \
50*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \
51*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \
52*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&)) \
53*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*)) \
54*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, allocator<_CharType> const&)) \
55*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \
56*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \
57*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \
58*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \
59*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \
60*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type)) \
61*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS const _CharType& basic_string<_CharType>::at(size_type) const) \
62*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \
63*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \
64*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \
65*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*, size_type)) \
66*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \
67*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \
68*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \
69*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::copy(value_type*, size_type, size_type) const) \
70*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, size_type, size_type, allocator<_CharType> const&)) \
71*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \
72*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(size_type, value_type)) \
73*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \
74*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \
75*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \
76*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \
77*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \
78*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \
79*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \
80*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \
81*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \
82*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::erase(size_type, size_type)) \
83*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \
84*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \
85*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \
86*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS _CharType& basic_string<_CharType>::at(size_type)) \
87*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*)) \
88*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \
89*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \
90*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \
91*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) \
92*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \
93*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \
94*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \
95*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \
96*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type))
97*4d6fc14bSjoerg
98*4d6fc14bSjoerg#define _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_Func, _CharType) \
99*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \
100*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \
101*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \
102*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*)) \
103*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \
104*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \
105*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \
106*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \
107*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \
108*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type)) \
109*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init_copy_ctor_external(value_type const*, size_type)) \
110*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS const _CharType& basic_string<_CharType>::at(size_type) const) \
111*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \
112*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \
113*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \
114*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*, size_type)) \
115*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*)) \
116*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \
117*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \
118*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \
119*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::copy(value_type*, size_type, size_type) const) \
120*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, size_type, size_type, allocator<_CharType> const&)) \
121*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \
122*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(size_type, value_type)) \
123*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \
124*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \
125*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \
126*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by_and_replace(size_type, size_type, size_type, size_type, size_type, size_type, value_type const*)) \
127*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_no_alias<false>(value_type const*, size_type)) \
128*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_no_alias<true>(value_type const*, size_type)) \
129*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \
130*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \
131*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \
132*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \
133*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \
134*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__erase_external_with_move(size_type, size_type)) \
135*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \
136*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \
137*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \
138*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS _CharType& basic_string<_CharType>::at(size_type)) \
139*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \
140*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \
141*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \
142*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \
143*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \
144*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \
145*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \
146*4d6fc14bSjoerg  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type))
147*4d6fc14bSjoerg
148*4d6fc14bSjoerg
149*4d6fc14bSjoerg// char_traits
150*4d6fc14bSjoerg
151*4d6fc14bSjoergtemplate <class _CharT>
152*4d6fc14bSjoergstruct _LIBCPP_TEMPLATE_VIS char_traits
153*4d6fc14bSjoerg{
154*4d6fc14bSjoerg    typedef _CharT    char_type;
155*4d6fc14bSjoerg    typedef int       int_type;
156*4d6fc14bSjoerg    typedef streamoff off_type;
157*4d6fc14bSjoerg    typedef streampos pos_type;
158*4d6fc14bSjoerg    typedef mbstate_t state_type;
159*4d6fc14bSjoerg
160*4d6fc14bSjoerg    static inline void _LIBCPP_CONSTEXPR_AFTER_CXX14
161*4d6fc14bSjoerg        assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
162*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
163*4d6fc14bSjoerg        {return __c1 == __c2;}
164*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
165*4d6fc14bSjoerg        {return __c1 < __c2;}
166*4d6fc14bSjoerg
167*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX14
168*4d6fc14bSjoerg    int compare(const char_type* __s1, const char_type* __s2, size_t __n);
169*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
170*4d6fc14bSjoerg    size_t length(const char_type* __s);
171*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
172*4d6fc14bSjoerg    const char_type* find(const char_type* __s, size_t __n, const char_type& __a);
173*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX17
174*4d6fc14bSjoerg    char_type*       move(char_type* __s1, const char_type* __s2, size_t __n);
175*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
176*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX17
177*4d6fc14bSjoerg    char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n);
178*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY
179*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX17
180*4d6fc14bSjoerg    char_type*       assign(char_type* __s, size_t __n, char_type __a);
181*4d6fc14bSjoerg
182*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
183*4d6fc14bSjoerg        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
184*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
185*4d6fc14bSjoerg        {return char_type(__c);}
186*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type  to_int_type(char_type __c) _NOEXCEPT
187*4d6fc14bSjoerg        {return int_type(__c);}
188*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool      eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
189*4d6fc14bSjoerg        {return __c1 == __c2;}
190*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type  eof() _NOEXCEPT
191*4d6fc14bSjoerg        {return int_type(EOF);}
192*4d6fc14bSjoerg};
193*4d6fc14bSjoerg
194*4d6fc14bSjoergtemplate <class _CharT>
195*4d6fc14bSjoerg_LIBCPP_CONSTEXPR_AFTER_CXX14 int
196*4d6fc14bSjoergchar_traits<_CharT>::compare(const char_type* __s1, const char_type* __s2, size_t __n)
197*4d6fc14bSjoerg{
198*4d6fc14bSjoerg    for (; __n; --__n, ++__s1, ++__s2)
199*4d6fc14bSjoerg    {
200*4d6fc14bSjoerg        if (lt(*__s1, *__s2))
201*4d6fc14bSjoerg            return -1;
202*4d6fc14bSjoerg        if (lt(*__s2, *__s1))
203*4d6fc14bSjoerg            return 1;
204*4d6fc14bSjoerg    }
205*4d6fc14bSjoerg    return 0;
206*4d6fc14bSjoerg}
207*4d6fc14bSjoerg
208*4d6fc14bSjoergtemplate <class _CharT>
209*4d6fc14bSjoerginline
210*4d6fc14bSjoerg_LIBCPP_CONSTEXPR_AFTER_CXX14 size_t
211*4d6fc14bSjoergchar_traits<_CharT>::length(const char_type* __s)
212*4d6fc14bSjoerg{
213*4d6fc14bSjoerg    size_t __len = 0;
214*4d6fc14bSjoerg    for (; !eq(*__s, char_type(0)); ++__s)
215*4d6fc14bSjoerg        ++__len;
216*4d6fc14bSjoerg    return __len;
217*4d6fc14bSjoerg}
218*4d6fc14bSjoerg
219*4d6fc14bSjoergtemplate <class _CharT>
220*4d6fc14bSjoerginline
221*4d6fc14bSjoerg_LIBCPP_CONSTEXPR_AFTER_CXX14 const _CharT*
222*4d6fc14bSjoergchar_traits<_CharT>::find(const char_type* __s, size_t __n, const char_type& __a)
223*4d6fc14bSjoerg{
224*4d6fc14bSjoerg    for (; __n; --__n)
225*4d6fc14bSjoerg    {
226*4d6fc14bSjoerg        if (eq(*__s, __a))
227*4d6fc14bSjoerg            return __s;
228*4d6fc14bSjoerg        ++__s;
229*4d6fc14bSjoerg    }
230*4d6fc14bSjoerg    return nullptr;
231*4d6fc14bSjoerg}
232*4d6fc14bSjoerg
233*4d6fc14bSjoergtemplate <class _CharT>
234*4d6fc14bSjoerg_LIBCPP_CONSTEXPR_AFTER_CXX17 _CharT*
235*4d6fc14bSjoergchar_traits<_CharT>::move(char_type* __s1, const char_type* __s2, size_t __n)
236*4d6fc14bSjoerg{
237*4d6fc14bSjoerg    if (__n == 0) return __s1;
238*4d6fc14bSjoerg    char_type* __r = __s1;
239*4d6fc14bSjoerg    if (__s1 < __s2)
240*4d6fc14bSjoerg    {
241*4d6fc14bSjoerg        for (; __n; --__n, ++__s1, ++__s2)
242*4d6fc14bSjoerg            assign(*__s1, *__s2);
243*4d6fc14bSjoerg    }
244*4d6fc14bSjoerg    else if (__s2 < __s1)
245*4d6fc14bSjoerg    {
246*4d6fc14bSjoerg        __s1 += __n;
247*4d6fc14bSjoerg        __s2 += __n;
248*4d6fc14bSjoerg        for (; __n; --__n)
249*4d6fc14bSjoerg            assign(*--__s1, *--__s2);
250*4d6fc14bSjoerg    }
251*4d6fc14bSjoerg    return __r;
252*4d6fc14bSjoerg}
253*4d6fc14bSjoerg
254*4d6fc14bSjoergtemplate <class _CharT>
255*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX17
256*4d6fc14bSjoerg_CharT*
257*4d6fc14bSjoergchar_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n)
258*4d6fc14bSjoerg{
259*4d6fc14bSjoerg    _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
260*4d6fc14bSjoerg    char_type* __r = __s1;
261*4d6fc14bSjoerg    for (; __n; --__n, ++__s1, ++__s2)
262*4d6fc14bSjoerg        assign(*__s1, *__s2);
263*4d6fc14bSjoerg    return __r;
264*4d6fc14bSjoerg}
265*4d6fc14bSjoerg
266*4d6fc14bSjoergtemplate <class _CharT>
267*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX17
268*4d6fc14bSjoerg_CharT*
269*4d6fc14bSjoergchar_traits<_CharT>::assign(char_type* __s, size_t __n, char_type __a)
270*4d6fc14bSjoerg{
271*4d6fc14bSjoerg    char_type* __r = __s;
272*4d6fc14bSjoerg    for (; __n; --__n, ++__s)
273*4d6fc14bSjoerg        assign(*__s, __a);
274*4d6fc14bSjoerg    return __r;
275*4d6fc14bSjoerg}
276*4d6fc14bSjoerg
277*4d6fc14bSjoerg// constexpr versions of move/copy/assign.
278*4d6fc14bSjoerg
279*4d6fc14bSjoergtemplate <class _CharT>
280*4d6fc14bSjoergstatic inline _LIBCPP_CONSTEXPR_AFTER_CXX17
281*4d6fc14bSjoerg_CharT* __move_constexpr(_CharT* __s1, const _CharT* __s2, size_t __n) _NOEXCEPT
282*4d6fc14bSjoerg{
283*4d6fc14bSjoerg    if (__n == 0) return __s1;
284*4d6fc14bSjoerg    if (__s1 < __s2) {
285*4d6fc14bSjoerg      _VSTD::copy(__s2, __s2 + __n, __s1);
286*4d6fc14bSjoerg    } else if (__s2 < __s1) {
287*4d6fc14bSjoerg      _VSTD::copy_backward(__s2, __s2 + __n, __s1 + __n);
288*4d6fc14bSjoerg    }
289*4d6fc14bSjoerg    return __s1;
290*4d6fc14bSjoerg}
291*4d6fc14bSjoerg
292*4d6fc14bSjoergtemplate <class _CharT>
293*4d6fc14bSjoergstatic inline _LIBCPP_CONSTEXPR_AFTER_CXX17
294*4d6fc14bSjoerg_CharT* __copy_constexpr(_CharT* __s1, const _CharT* __s2, size_t __n) _NOEXCEPT
295*4d6fc14bSjoerg{
296*4d6fc14bSjoerg    _VSTD::copy_n(__s2, __n, __s1);
297*4d6fc14bSjoerg    return __s1;
298*4d6fc14bSjoerg}
299*4d6fc14bSjoerg
300*4d6fc14bSjoergtemplate <class _CharT>
301*4d6fc14bSjoergstatic inline _LIBCPP_CONSTEXPR_AFTER_CXX17
302*4d6fc14bSjoerg_CharT* __assign_constexpr(_CharT* __s, size_t __n, _CharT __a) _NOEXCEPT
303*4d6fc14bSjoerg{
304*4d6fc14bSjoerg     _VSTD::fill_n(__s, __n, __a);
305*4d6fc14bSjoerg     return __s;
306*4d6fc14bSjoerg}
307*4d6fc14bSjoerg
308*4d6fc14bSjoerg// char_traits<char>
309*4d6fc14bSjoerg
310*4d6fc14bSjoergtemplate <>
311*4d6fc14bSjoergstruct _LIBCPP_TEMPLATE_VIS char_traits<char>
312*4d6fc14bSjoerg{
313*4d6fc14bSjoerg    typedef char      char_type;
314*4d6fc14bSjoerg    typedef int       int_type;
315*4d6fc14bSjoerg    typedef streamoff off_type;
316*4d6fc14bSjoerg    typedef streampos pos_type;
317*4d6fc14bSjoerg    typedef mbstate_t state_type;
318*4d6fc14bSjoerg
319*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
320*4d6fc14bSjoerg    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
321*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
322*4d6fc14bSjoerg            {return __c1 == __c2;}
323*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
324*4d6fc14bSjoerg        {return (unsigned char)__c1 < (unsigned char)__c2;}
325*4d6fc14bSjoerg
326*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX14
327*4d6fc14bSjoerg    int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
328*4d6fc14bSjoerg    static inline size_t _LIBCPP_CONSTEXPR_AFTER_CXX14
329*4d6fc14bSjoerg    length(const char_type* __s)  _NOEXCEPT {return __builtin_strlen(__s);}
330*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX14
331*4d6fc14bSjoerg    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
332*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
333*4d6fc14bSjoerg    char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
334*4d6fc14bSjoerg        {
335*4d6fc14bSjoerg            return __libcpp_is_constant_evaluated()
336*4d6fc14bSjoerg                       ? _VSTD::__move_constexpr(__s1, __s2, __n)
337*4d6fc14bSjoerg                       : __n == 0 ? __s1 : (char_type*)_VSTD::memmove(__s1, __s2, __n);
338*4d6fc14bSjoerg        }
339*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
340*4d6fc14bSjoerg    char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
341*4d6fc14bSjoerg        {
342*4d6fc14bSjoerg            _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
343*4d6fc14bSjoerg            return __libcpp_is_constant_evaluated()
344*4d6fc14bSjoerg                       ? _VSTD::__copy_constexpr(__s1, __s2, __n)
345*4d6fc14bSjoerg                       : __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
346*4d6fc14bSjoerg        }
347*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
348*4d6fc14bSjoerg    char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
349*4d6fc14bSjoerg        {
350*4d6fc14bSjoerg            return __libcpp_is_constant_evaluated()
351*4d6fc14bSjoerg                       ? _VSTD::__assign_constexpr(__s, __n, __a)
352*4d6fc14bSjoerg                       : __n == 0 ? __s : (char_type*)_VSTD::memset(__s, to_int_type(__a), __n);
353*4d6fc14bSjoerg        }
354*4d6fc14bSjoerg
355*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
356*4d6fc14bSjoerg        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
357*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
358*4d6fc14bSjoerg        {return char_type(__c);}
359*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
360*4d6fc14bSjoerg        {return int_type((unsigned char)__c);}
361*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
362*4d6fc14bSjoerg        {return __c1 == __c2;}
363*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type  eof() _NOEXCEPT
364*4d6fc14bSjoerg        {return int_type(EOF);}
365*4d6fc14bSjoerg};
366*4d6fc14bSjoerg
367*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX14
368*4d6fc14bSjoergint
369*4d6fc14bSjoergchar_traits<char>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
370*4d6fc14bSjoerg{
371*4d6fc14bSjoerg    if (__n == 0)
372*4d6fc14bSjoerg        return 0;
373*4d6fc14bSjoerg#if __has_feature(cxx_constexpr_string_builtins)
374*4d6fc14bSjoerg    return __builtin_memcmp(__s1, __s2, __n);
375*4d6fc14bSjoerg#elif _LIBCPP_STD_VER <= 14
376*4d6fc14bSjoerg    return _VSTD::memcmp(__s1, __s2, __n);
377*4d6fc14bSjoerg#else
378*4d6fc14bSjoerg    for (; __n; --__n, ++__s1, ++__s2)
379*4d6fc14bSjoerg    {
380*4d6fc14bSjoerg        if (lt(*__s1, *__s2))
381*4d6fc14bSjoerg            return -1;
382*4d6fc14bSjoerg        if (lt(*__s2, *__s1))
383*4d6fc14bSjoerg            return 1;
384*4d6fc14bSjoerg    }
385*4d6fc14bSjoerg    return 0;
386*4d6fc14bSjoerg#endif
387*4d6fc14bSjoerg}
388*4d6fc14bSjoerg
389*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX14
390*4d6fc14bSjoergconst char*
391*4d6fc14bSjoergchar_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
392*4d6fc14bSjoerg{
393*4d6fc14bSjoerg    if (__n == 0)
394*4d6fc14bSjoerg        return nullptr;
395*4d6fc14bSjoerg#if __has_feature(cxx_constexpr_string_builtins)
396*4d6fc14bSjoerg    return __builtin_char_memchr(__s, to_int_type(__a), __n);
397*4d6fc14bSjoerg#elif _LIBCPP_STD_VER <= 14
398*4d6fc14bSjoerg    return (const char_type*) _VSTD::memchr(__s, to_int_type(__a), __n);
399*4d6fc14bSjoerg#else
400*4d6fc14bSjoerg    for (; __n; --__n)
401*4d6fc14bSjoerg    {
402*4d6fc14bSjoerg        if (eq(*__s, __a))
403*4d6fc14bSjoerg            return __s;
404*4d6fc14bSjoerg        ++__s;
405*4d6fc14bSjoerg    }
406*4d6fc14bSjoerg    return nullptr;
407*4d6fc14bSjoerg#endif
408*4d6fc14bSjoerg}
409*4d6fc14bSjoerg
410*4d6fc14bSjoerg
411*4d6fc14bSjoerg// char_traits<wchar_t>
412*4d6fc14bSjoerg
413*4d6fc14bSjoergtemplate <>
414*4d6fc14bSjoergstruct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
415*4d6fc14bSjoerg{
416*4d6fc14bSjoerg    typedef wchar_t   char_type;
417*4d6fc14bSjoerg    typedef wint_t    int_type;
418*4d6fc14bSjoerg    typedef streamoff off_type;
419*4d6fc14bSjoerg    typedef streampos pos_type;
420*4d6fc14bSjoerg    typedef mbstate_t state_type;
421*4d6fc14bSjoerg
422*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
423*4d6fc14bSjoerg    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
424*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
425*4d6fc14bSjoerg        {return __c1 == __c2;}
426*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
427*4d6fc14bSjoerg        {return __c1 < __c2;}
428*4d6fc14bSjoerg
429*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX14
430*4d6fc14bSjoerg    int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
431*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX14
432*4d6fc14bSjoerg    size_t length(const char_type* __s) _NOEXCEPT;
433*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX14
434*4d6fc14bSjoerg    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
435*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
436*4d6fc14bSjoerg    char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
437*4d6fc14bSjoerg        {
438*4d6fc14bSjoerg            return __libcpp_is_constant_evaluated()
439*4d6fc14bSjoerg                       ? _VSTD::__move_constexpr(__s1, __s2, __n)
440*4d6fc14bSjoerg                       : __n == 0 ? __s1 : _VSTD::wmemmove(__s1, __s2, __n);
441*4d6fc14bSjoerg        }
442*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
443*4d6fc14bSjoerg    char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
444*4d6fc14bSjoerg        {
445*4d6fc14bSjoerg            _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
446*4d6fc14bSjoerg            return __libcpp_is_constant_evaluated()
447*4d6fc14bSjoerg                       ? _VSTD::__copy_constexpr(__s1, __s2, __n)
448*4d6fc14bSjoerg                       : __n == 0 ? __s1 : _VSTD::wmemcpy(__s1, __s2, __n);
449*4d6fc14bSjoerg        }
450*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
451*4d6fc14bSjoerg    char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
452*4d6fc14bSjoerg        {
453*4d6fc14bSjoerg            return __libcpp_is_constant_evaluated()
454*4d6fc14bSjoerg                       ? _VSTD::__assign_constexpr(__s, __n, __a)
455*4d6fc14bSjoerg                       : __n == 0 ? __s : _VSTD::wmemset(__s, __a, __n);
456*4d6fc14bSjoerg        }
457*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
458*4d6fc14bSjoerg        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
459*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
460*4d6fc14bSjoerg        {return char_type(__c);}
461*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
462*4d6fc14bSjoerg        {return int_type(__c);}
463*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
464*4d6fc14bSjoerg        {return __c1 == __c2;}
465*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
466*4d6fc14bSjoerg        {return int_type(WEOF);}
467*4d6fc14bSjoerg};
468*4d6fc14bSjoerg
469*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX14
470*4d6fc14bSjoergint
471*4d6fc14bSjoergchar_traits<wchar_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
472*4d6fc14bSjoerg{
473*4d6fc14bSjoerg    if (__n == 0)
474*4d6fc14bSjoerg        return 0;
475*4d6fc14bSjoerg#if __has_feature(cxx_constexpr_string_builtins)
476*4d6fc14bSjoerg    return __builtin_wmemcmp(__s1, __s2, __n);
477*4d6fc14bSjoerg#elif _LIBCPP_STD_VER <= 14
478*4d6fc14bSjoerg    return _VSTD::wmemcmp(__s1, __s2, __n);
479*4d6fc14bSjoerg#else
480*4d6fc14bSjoerg    for (; __n; --__n, ++__s1, ++__s2)
481*4d6fc14bSjoerg    {
482*4d6fc14bSjoerg        if (lt(*__s1, *__s2))
483*4d6fc14bSjoerg            return -1;
484*4d6fc14bSjoerg        if (lt(*__s2, *__s1))
485*4d6fc14bSjoerg            return 1;
486*4d6fc14bSjoerg    }
487*4d6fc14bSjoerg    return 0;
488*4d6fc14bSjoerg#endif
489*4d6fc14bSjoerg}
490*4d6fc14bSjoerg
491*4d6fc14bSjoerg
492*4d6fc14bSjoergtemplate <class _Traits>
493*4d6fc14bSjoerg_LIBCPP_INLINE_VISIBILITY
494*4d6fc14bSjoerg_LIBCPP_CONSTEXPR
495*4d6fc14bSjoerginline size_t __char_traits_length_checked(const typename _Traits::char_type* __s) _NOEXCEPT {
496*4d6fc14bSjoerg#if _LIBCPP_DEBUG_LEVEL >= 1
497*4d6fc14bSjoerg  return __s ? _Traits::length(__s) : (_VSTD::__libcpp_debug_function(_VSTD::__libcpp_debug_info(__FILE__, __LINE__, "p == nullptr", "null pointer pass to non-null argument of char_traits<...>::length")), 0);
498*4d6fc14bSjoerg#else
499*4d6fc14bSjoerg  return _Traits::length(__s);
500*4d6fc14bSjoerg#endif
501*4d6fc14bSjoerg}
502*4d6fc14bSjoerg
503*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX14
504*4d6fc14bSjoergsize_t
505*4d6fc14bSjoergchar_traits<wchar_t>::length(const char_type* __s) _NOEXCEPT
506*4d6fc14bSjoerg{
507*4d6fc14bSjoerg#if __has_feature(cxx_constexpr_string_builtins)
508*4d6fc14bSjoerg    return __builtin_wcslen(__s);
509*4d6fc14bSjoerg#elif _LIBCPP_STD_VER <= 14
510*4d6fc14bSjoerg    return _VSTD::wcslen(__s);
511*4d6fc14bSjoerg#else
512*4d6fc14bSjoerg    size_t __len = 0;
513*4d6fc14bSjoerg    for (; !eq(*__s, char_type(0)); ++__s)
514*4d6fc14bSjoerg        ++__len;
515*4d6fc14bSjoerg    return __len;
516*4d6fc14bSjoerg#endif
517*4d6fc14bSjoerg}
518*4d6fc14bSjoerg
519*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX14
520*4d6fc14bSjoergconst wchar_t*
521*4d6fc14bSjoergchar_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
522*4d6fc14bSjoerg{
523*4d6fc14bSjoerg    if (__n == 0)
524*4d6fc14bSjoerg        return nullptr;
525*4d6fc14bSjoerg#if __has_feature(cxx_constexpr_string_builtins)
526*4d6fc14bSjoerg    return __builtin_wmemchr(__s, __a, __n);
527*4d6fc14bSjoerg#elif _LIBCPP_STD_VER <= 14
528*4d6fc14bSjoerg    return _VSTD::wmemchr(__s, __a, __n);
529*4d6fc14bSjoerg#else
530*4d6fc14bSjoerg    for (; __n; --__n)
531*4d6fc14bSjoerg    {
532*4d6fc14bSjoerg        if (eq(*__s, __a))
533*4d6fc14bSjoerg            return __s;
534*4d6fc14bSjoerg        ++__s;
535*4d6fc14bSjoerg    }
536*4d6fc14bSjoerg    return nullptr;
537*4d6fc14bSjoerg#endif
538*4d6fc14bSjoerg}
539*4d6fc14bSjoerg
540*4d6fc14bSjoerg
541*4d6fc14bSjoerg#ifndef _LIBCPP_HAS_NO_CHAR8_T
542*4d6fc14bSjoerg
543*4d6fc14bSjoergtemplate <>
544*4d6fc14bSjoergstruct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
545*4d6fc14bSjoerg{
546*4d6fc14bSjoerg    typedef char8_t        char_type;
547*4d6fc14bSjoerg    typedef unsigned int   int_type;
548*4d6fc14bSjoerg    typedef streamoff      off_type;
549*4d6fc14bSjoerg    typedef u8streampos    pos_type;
550*4d6fc14bSjoerg    typedef mbstate_t      state_type;
551*4d6fc14bSjoerg
552*4d6fc14bSjoerg    static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
553*4d6fc14bSjoerg        {__c1 = __c2;}
554*4d6fc14bSjoerg    static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept
555*4d6fc14bSjoerg        {return __c1 == __c2;}
556*4d6fc14bSjoerg    static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept
557*4d6fc14bSjoerg        {return __c1 < __c2;}
558*4d6fc14bSjoerg
559*4d6fc14bSjoerg    static constexpr
560*4d6fc14bSjoerg    int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
561*4d6fc14bSjoerg
562*4d6fc14bSjoerg    static constexpr
563*4d6fc14bSjoerg    size_t           length(const char_type* __s) _NOEXCEPT;
564*4d6fc14bSjoerg
565*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY static constexpr
566*4d6fc14bSjoerg    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
567*4d6fc14bSjoerg
568*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX17
569*4d6fc14bSjoerg    char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
570*4d6fc14bSjoerg        {
571*4d6fc14bSjoerg            return __libcpp_is_constant_evaluated()
572*4d6fc14bSjoerg                       ? _VSTD::__move_constexpr(__s1, __s2, __n)
573*4d6fc14bSjoerg                       : __n == 0 ? __s1 : (char_type*)_VSTD::memmove(__s1, __s2, __n);
574*4d6fc14bSjoerg        }
575*4d6fc14bSjoerg
576*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX17
577*4d6fc14bSjoerg    char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
578*4d6fc14bSjoerg       {
579*4d6fc14bSjoerg            _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
580*4d6fc14bSjoerg            return __libcpp_is_constant_evaluated()
581*4d6fc14bSjoerg                       ? _VSTD::__copy_constexpr(__s1, __s2, __n)
582*4d6fc14bSjoerg                       : __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
583*4d6fc14bSjoerg        }
584*4d6fc14bSjoerg
585*4d6fc14bSjoerg    static _LIBCPP_CONSTEXPR_AFTER_CXX17
586*4d6fc14bSjoerg    char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
587*4d6fc14bSjoerg        {
588*4d6fc14bSjoerg            return __libcpp_is_constant_evaluated()
589*4d6fc14bSjoerg                       ? _VSTD::__assign_constexpr(__s, __n, __a)
590*4d6fc14bSjoerg                       : __n == 0 ? __s : (char_type*)_VSTD::memset(__s, to_int_type(__a), __n);
591*4d6fc14bSjoerg        }
592*4d6fc14bSjoerg
593*4d6fc14bSjoerg    static inline constexpr int_type  not_eof(int_type __c) noexcept
594*4d6fc14bSjoerg        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
595*4d6fc14bSjoerg    static inline constexpr char_type to_char_type(int_type __c) noexcept
596*4d6fc14bSjoerg        {return char_type(__c);}
597*4d6fc14bSjoerg    static inline constexpr int_type to_int_type(char_type __c) noexcept
598*4d6fc14bSjoerg        {return int_type(__c);}
599*4d6fc14bSjoerg    static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept
600*4d6fc14bSjoerg        {return __c1 == __c2;}
601*4d6fc14bSjoerg    static inline constexpr int_type eof() noexcept
602*4d6fc14bSjoerg        {return int_type(EOF);}
603*4d6fc14bSjoerg};
604*4d6fc14bSjoerg
605*4d6fc14bSjoerg// TODO use '__builtin_strlen' if it ever supports char8_t ??
606*4d6fc14bSjoerginline constexpr
607*4d6fc14bSjoergsize_t
608*4d6fc14bSjoergchar_traits<char8_t>::length(const char_type* __s) _NOEXCEPT
609*4d6fc14bSjoerg{
610*4d6fc14bSjoerg    size_t __len = 0;
611*4d6fc14bSjoerg    for (; !eq(*__s, char_type(0)); ++__s)
612*4d6fc14bSjoerg        ++__len;
613*4d6fc14bSjoerg    return __len;
614*4d6fc14bSjoerg}
615*4d6fc14bSjoerg
616*4d6fc14bSjoerginline constexpr
617*4d6fc14bSjoergint
618*4d6fc14bSjoergchar_traits<char8_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
619*4d6fc14bSjoerg{
620*4d6fc14bSjoerg#if __has_feature(cxx_constexpr_string_builtins)
621*4d6fc14bSjoerg    return __builtin_memcmp(__s1, __s2, __n);
622*4d6fc14bSjoerg#else
623*4d6fc14bSjoerg    for (; __n; --__n, ++__s1, ++__s2)
624*4d6fc14bSjoerg    {
625*4d6fc14bSjoerg        if (lt(*__s1, *__s2))
626*4d6fc14bSjoerg            return -1;
627*4d6fc14bSjoerg        if (lt(*__s2, *__s1))
628*4d6fc14bSjoerg            return 1;
629*4d6fc14bSjoerg    }
630*4d6fc14bSjoerg    return 0;
631*4d6fc14bSjoerg#endif
632*4d6fc14bSjoerg}
633*4d6fc14bSjoerg
634*4d6fc14bSjoerg// TODO use '__builtin_char_memchr' if it ever supports char8_t ??
635*4d6fc14bSjoerginline constexpr
636*4d6fc14bSjoergconst char8_t*
637*4d6fc14bSjoergchar_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
638*4d6fc14bSjoerg{
639*4d6fc14bSjoerg    for (; __n; --__n)
640*4d6fc14bSjoerg    {
641*4d6fc14bSjoerg        if (eq(*__s, __a))
642*4d6fc14bSjoerg            return __s;
643*4d6fc14bSjoerg        ++__s;
644*4d6fc14bSjoerg    }
645*4d6fc14bSjoerg    return nullptr;
646*4d6fc14bSjoerg}
647*4d6fc14bSjoerg
648*4d6fc14bSjoerg#endif // #_LIBCPP_HAS_NO_CHAR8_T
649*4d6fc14bSjoerg
650*4d6fc14bSjoerg#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
651*4d6fc14bSjoerg
652*4d6fc14bSjoergtemplate <>
653*4d6fc14bSjoergstruct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
654*4d6fc14bSjoerg{
655*4d6fc14bSjoerg    typedef char16_t       char_type;
656*4d6fc14bSjoerg    typedef uint_least16_t int_type;
657*4d6fc14bSjoerg    typedef streamoff      off_type;
658*4d6fc14bSjoerg    typedef u16streampos   pos_type;
659*4d6fc14bSjoerg    typedef mbstate_t      state_type;
660*4d6fc14bSjoerg
661*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
662*4d6fc14bSjoerg    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
663*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
664*4d6fc14bSjoerg        {return __c1 == __c2;}
665*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
666*4d6fc14bSjoerg        {return __c1 < __c2;}
667*4d6fc14bSjoerg
668*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
669*4d6fc14bSjoerg    int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
670*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
671*4d6fc14bSjoerg    size_t           length(const char_type* __s) _NOEXCEPT;
672*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
673*4d6fc14bSjoerg    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
674*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
675*4d6fc14bSjoerg    static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
676*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
677*4d6fc14bSjoerg    static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
678*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
679*4d6fc14bSjoerg    static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
680*4d6fc14bSjoerg
681*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
682*4d6fc14bSjoerg        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
683*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
684*4d6fc14bSjoerg        {return char_type(__c);}
685*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
686*4d6fc14bSjoerg        {return int_type(__c);}
687*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
688*4d6fc14bSjoerg        {return __c1 == __c2;}
689*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
690*4d6fc14bSjoerg        {return int_type(0xFFFF);}
691*4d6fc14bSjoerg};
692*4d6fc14bSjoerg
693*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX14
694*4d6fc14bSjoergint
695*4d6fc14bSjoergchar_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
696*4d6fc14bSjoerg{
697*4d6fc14bSjoerg    for (; __n; --__n, ++__s1, ++__s2)
698*4d6fc14bSjoerg    {
699*4d6fc14bSjoerg        if (lt(*__s1, *__s2))
700*4d6fc14bSjoerg            return -1;
701*4d6fc14bSjoerg        if (lt(*__s2, *__s1))
702*4d6fc14bSjoerg            return 1;
703*4d6fc14bSjoerg    }
704*4d6fc14bSjoerg    return 0;
705*4d6fc14bSjoerg}
706*4d6fc14bSjoerg
707*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX14
708*4d6fc14bSjoergsize_t
709*4d6fc14bSjoergchar_traits<char16_t>::length(const char_type* __s) _NOEXCEPT
710*4d6fc14bSjoerg{
711*4d6fc14bSjoerg    size_t __len = 0;
712*4d6fc14bSjoerg    for (; !eq(*__s, char_type(0)); ++__s)
713*4d6fc14bSjoerg        ++__len;
714*4d6fc14bSjoerg    return __len;
715*4d6fc14bSjoerg}
716*4d6fc14bSjoerg
717*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX14
718*4d6fc14bSjoergconst char16_t*
719*4d6fc14bSjoergchar_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
720*4d6fc14bSjoerg{
721*4d6fc14bSjoerg    for (; __n; --__n)
722*4d6fc14bSjoerg    {
723*4d6fc14bSjoerg        if (eq(*__s, __a))
724*4d6fc14bSjoerg            return __s;
725*4d6fc14bSjoerg        ++__s;
726*4d6fc14bSjoerg    }
727*4d6fc14bSjoerg    return nullptr;
728*4d6fc14bSjoerg}
729*4d6fc14bSjoerg
730*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX17
731*4d6fc14bSjoergchar16_t*
732*4d6fc14bSjoergchar_traits<char16_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
733*4d6fc14bSjoerg{
734*4d6fc14bSjoerg    if (__n == 0) return __s1;
735*4d6fc14bSjoerg    char_type* __r = __s1;
736*4d6fc14bSjoerg    if (__s1 < __s2)
737*4d6fc14bSjoerg    {
738*4d6fc14bSjoerg        for (; __n; --__n, ++__s1, ++__s2)
739*4d6fc14bSjoerg            assign(*__s1, *__s2);
740*4d6fc14bSjoerg    }
741*4d6fc14bSjoerg    else if (__s2 < __s1)
742*4d6fc14bSjoerg    {
743*4d6fc14bSjoerg        __s1 += __n;
744*4d6fc14bSjoerg        __s2 += __n;
745*4d6fc14bSjoerg        for (; __n; --__n)
746*4d6fc14bSjoerg            assign(*--__s1, *--__s2);
747*4d6fc14bSjoerg    }
748*4d6fc14bSjoerg    return __r;
749*4d6fc14bSjoerg}
750*4d6fc14bSjoerg
751*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX17
752*4d6fc14bSjoergchar16_t*
753*4d6fc14bSjoergchar_traits<char16_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
754*4d6fc14bSjoerg{
755*4d6fc14bSjoerg    _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
756*4d6fc14bSjoerg    char_type* __r = __s1;
757*4d6fc14bSjoerg    for (; __n; --__n, ++__s1, ++__s2)
758*4d6fc14bSjoerg        assign(*__s1, *__s2);
759*4d6fc14bSjoerg    return __r;
760*4d6fc14bSjoerg}
761*4d6fc14bSjoerg
762*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX17
763*4d6fc14bSjoergchar16_t*
764*4d6fc14bSjoergchar_traits<char16_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
765*4d6fc14bSjoerg{
766*4d6fc14bSjoerg    char_type* __r = __s;
767*4d6fc14bSjoerg    for (; __n; --__n, ++__s)
768*4d6fc14bSjoerg        assign(*__s, __a);
769*4d6fc14bSjoerg    return __r;
770*4d6fc14bSjoerg}
771*4d6fc14bSjoerg
772*4d6fc14bSjoergtemplate <>
773*4d6fc14bSjoergstruct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
774*4d6fc14bSjoerg{
775*4d6fc14bSjoerg    typedef char32_t       char_type;
776*4d6fc14bSjoerg    typedef uint_least32_t int_type;
777*4d6fc14bSjoerg    typedef streamoff      off_type;
778*4d6fc14bSjoerg    typedef u32streampos   pos_type;
779*4d6fc14bSjoerg    typedef mbstate_t      state_type;
780*4d6fc14bSjoerg
781*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
782*4d6fc14bSjoerg    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
783*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
784*4d6fc14bSjoerg        {return __c1 == __c2;}
785*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
786*4d6fc14bSjoerg        {return __c1 < __c2;}
787*4d6fc14bSjoerg
788*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
789*4d6fc14bSjoerg    int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
790*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
791*4d6fc14bSjoerg    size_t           length(const char_type* __s) _NOEXCEPT;
792*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
793*4d6fc14bSjoerg    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
794*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
795*4d6fc14bSjoerg    static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
796*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
797*4d6fc14bSjoerg    static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
798*4d6fc14bSjoerg    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
799*4d6fc14bSjoerg    static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
800*4d6fc14bSjoerg
801*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
802*4d6fc14bSjoerg        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
803*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
804*4d6fc14bSjoerg        {return char_type(__c);}
805*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
806*4d6fc14bSjoerg        {return int_type(__c);}
807*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
808*4d6fc14bSjoerg        {return __c1 == __c2;}
809*4d6fc14bSjoerg    static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
810*4d6fc14bSjoerg        {return int_type(0xFFFFFFFF);}
811*4d6fc14bSjoerg};
812*4d6fc14bSjoerg
813*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX14
814*4d6fc14bSjoergint
815*4d6fc14bSjoergchar_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
816*4d6fc14bSjoerg{
817*4d6fc14bSjoerg    for (; __n; --__n, ++__s1, ++__s2)
818*4d6fc14bSjoerg    {
819*4d6fc14bSjoerg        if (lt(*__s1, *__s2))
820*4d6fc14bSjoerg            return -1;
821*4d6fc14bSjoerg        if (lt(*__s2, *__s1))
822*4d6fc14bSjoerg            return 1;
823*4d6fc14bSjoerg    }
824*4d6fc14bSjoerg    return 0;
825*4d6fc14bSjoerg}
826*4d6fc14bSjoerg
827*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX14
828*4d6fc14bSjoergsize_t
829*4d6fc14bSjoergchar_traits<char32_t>::length(const char_type* __s) _NOEXCEPT
830*4d6fc14bSjoerg{
831*4d6fc14bSjoerg    size_t __len = 0;
832*4d6fc14bSjoerg    for (; !eq(*__s, char_type(0)); ++__s)
833*4d6fc14bSjoerg        ++__len;
834*4d6fc14bSjoerg    return __len;
835*4d6fc14bSjoerg}
836*4d6fc14bSjoerg
837*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX14
838*4d6fc14bSjoergconst char32_t*
839*4d6fc14bSjoergchar_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
840*4d6fc14bSjoerg{
841*4d6fc14bSjoerg    for (; __n; --__n)
842*4d6fc14bSjoerg    {
843*4d6fc14bSjoerg        if (eq(*__s, __a))
844*4d6fc14bSjoerg            return __s;
845*4d6fc14bSjoerg        ++__s;
846*4d6fc14bSjoerg    }
847*4d6fc14bSjoerg    return nullptr;
848*4d6fc14bSjoerg}
849*4d6fc14bSjoerg
850*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX17
851*4d6fc14bSjoergchar32_t*
852*4d6fc14bSjoergchar_traits<char32_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
853*4d6fc14bSjoerg{
854*4d6fc14bSjoerg    if (__n == 0) return __s1;
855*4d6fc14bSjoerg    char_type* __r = __s1;
856*4d6fc14bSjoerg    if (__s1 < __s2)
857*4d6fc14bSjoerg    {
858*4d6fc14bSjoerg        for (; __n; --__n, ++__s1, ++__s2)
859*4d6fc14bSjoerg            assign(*__s1, *__s2);
860*4d6fc14bSjoerg    }
861*4d6fc14bSjoerg    else if (__s2 < __s1)
862*4d6fc14bSjoerg    {
863*4d6fc14bSjoerg        __s1 += __n;
864*4d6fc14bSjoerg        __s2 += __n;
865*4d6fc14bSjoerg        for (; __n; --__n)
866*4d6fc14bSjoerg            assign(*--__s1, *--__s2);
867*4d6fc14bSjoerg    }
868*4d6fc14bSjoerg    return __r;
869*4d6fc14bSjoerg}
870*4d6fc14bSjoerg
871*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX17
872*4d6fc14bSjoergchar32_t*
873*4d6fc14bSjoergchar_traits<char32_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
874*4d6fc14bSjoerg{
875*4d6fc14bSjoerg    _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
876*4d6fc14bSjoerg    char_type* __r = __s1;
877*4d6fc14bSjoerg    for (; __n; --__n, ++__s1, ++__s2)
878*4d6fc14bSjoerg        assign(*__s1, *__s2);
879*4d6fc14bSjoerg    return __r;
880*4d6fc14bSjoerg}
881*4d6fc14bSjoerg
882*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX17
883*4d6fc14bSjoergchar32_t*
884*4d6fc14bSjoergchar_traits<char32_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
885*4d6fc14bSjoerg{
886*4d6fc14bSjoerg    char_type* __r = __s;
887*4d6fc14bSjoerg    for (; __n; --__n, ++__s)
888*4d6fc14bSjoerg        assign(*__s, __a);
889*4d6fc14bSjoerg    return __r;
890*4d6fc14bSjoerg}
891*4d6fc14bSjoerg
892*4d6fc14bSjoerg#endif // _LIBCPP_HAS_NO_UNICODE_CHARS
893*4d6fc14bSjoerg
894*4d6fc14bSjoerg// helper fns for basic_string and string_view
895*4d6fc14bSjoerg
896*4d6fc14bSjoerg// __str_find
897*4d6fc14bSjoergtemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
898*4d6fc14bSjoerginline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
899*4d6fc14bSjoerg__str_find(const _CharT *__p, _SizeT __sz,
900*4d6fc14bSjoerg             _CharT __c, _SizeT __pos) _NOEXCEPT
901*4d6fc14bSjoerg{
902*4d6fc14bSjoerg    if (__pos >= __sz)
903*4d6fc14bSjoerg        return __npos;
904*4d6fc14bSjoerg    const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
905*4d6fc14bSjoerg    if (__r == nullptr)
906*4d6fc14bSjoerg        return __npos;
907*4d6fc14bSjoerg    return static_cast<_SizeT>(__r - __p);
908*4d6fc14bSjoerg}
909*4d6fc14bSjoerg
910*4d6fc14bSjoergtemplate <class _CharT, class _Traits>
911*4d6fc14bSjoerginline _LIBCPP_CONSTEXPR_AFTER_CXX11 const _CharT *
912*4d6fc14bSjoerg__search_substring(const _CharT *__first1, const _CharT *__last1,
913*4d6fc14bSjoerg                   const _CharT *__first2, const _CharT *__last2) _NOEXCEPT {
914*4d6fc14bSjoerg  // Take advantage of knowing source and pattern lengths.
915*4d6fc14bSjoerg  // Stop short when source is smaller than pattern.
916*4d6fc14bSjoerg  const ptrdiff_t __len2 = __last2 - __first2;
917*4d6fc14bSjoerg  if (__len2 == 0)
918*4d6fc14bSjoerg    return __first1;
919*4d6fc14bSjoerg
920*4d6fc14bSjoerg  ptrdiff_t __len1 = __last1 - __first1;
921*4d6fc14bSjoerg  if (__len1 < __len2)
922*4d6fc14bSjoerg    return __last1;
923*4d6fc14bSjoerg
924*4d6fc14bSjoerg  // First element of __first2 is loop invariant.
925*4d6fc14bSjoerg  _CharT __f2 = *__first2;
926*4d6fc14bSjoerg  while (true) {
927*4d6fc14bSjoerg    __len1 = __last1 - __first1;
928*4d6fc14bSjoerg    // Check whether __first1 still has at least __len2 bytes.
929*4d6fc14bSjoerg    if (__len1 < __len2)
930*4d6fc14bSjoerg      return __last1;
931*4d6fc14bSjoerg
932*4d6fc14bSjoerg    // Find __f2 the first byte matching in __first1.
933*4d6fc14bSjoerg    __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2);
934*4d6fc14bSjoerg    if (__first1 == nullptr)
935*4d6fc14bSjoerg      return __last1;
936*4d6fc14bSjoerg
937*4d6fc14bSjoerg    // It is faster to compare from the first byte of __first1 even if we
938*4d6fc14bSjoerg    // already know that it matches the first byte of __first2: this is because
939*4d6fc14bSjoerg    // __first2 is most likely aligned, as it is user's "pattern" string, and
940*4d6fc14bSjoerg    // __first1 + 1 is most likely not aligned, as the match is in the middle of
941*4d6fc14bSjoerg    // the string.
942*4d6fc14bSjoerg    if (_Traits::compare(__first1, __first2, __len2) == 0)
943*4d6fc14bSjoerg      return __first1;
944*4d6fc14bSjoerg
945*4d6fc14bSjoerg    ++__first1;
946*4d6fc14bSjoerg  }
947*4d6fc14bSjoerg}
948*4d6fc14bSjoerg
949*4d6fc14bSjoergtemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
950*4d6fc14bSjoerginline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
951*4d6fc14bSjoerg__str_find(const _CharT *__p, _SizeT __sz,
952*4d6fc14bSjoerg       const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
953*4d6fc14bSjoerg{
954*4d6fc14bSjoerg    if (__pos > __sz)
955*4d6fc14bSjoerg        return __npos;
956*4d6fc14bSjoerg
957*4d6fc14bSjoerg    if (__n == 0) // There is nothing to search, just return __pos.
958*4d6fc14bSjoerg        return __pos;
959*4d6fc14bSjoerg
960*4d6fc14bSjoerg    const _CharT *__r = __search_substring<_CharT, _Traits>(
961*4d6fc14bSjoerg        __p + __pos, __p + __sz, __s, __s + __n);
962*4d6fc14bSjoerg
963*4d6fc14bSjoerg    if (__r == __p + __sz)
964*4d6fc14bSjoerg        return __npos;
965*4d6fc14bSjoerg    return static_cast<_SizeT>(__r - __p);
966*4d6fc14bSjoerg}
967*4d6fc14bSjoerg
968*4d6fc14bSjoerg
969*4d6fc14bSjoerg// __str_rfind
970*4d6fc14bSjoerg
971*4d6fc14bSjoergtemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
972*4d6fc14bSjoerginline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
973*4d6fc14bSjoerg__str_rfind(const _CharT *__p, _SizeT __sz,
974*4d6fc14bSjoerg              _CharT __c, _SizeT __pos) _NOEXCEPT
975*4d6fc14bSjoerg{
976*4d6fc14bSjoerg    if (__sz < 1)
977*4d6fc14bSjoerg        return __npos;
978*4d6fc14bSjoerg    if (__pos < __sz)
979*4d6fc14bSjoerg        ++__pos;
980*4d6fc14bSjoerg    else
981*4d6fc14bSjoerg        __pos = __sz;
982*4d6fc14bSjoerg    for (const _CharT* __ps = __p + __pos; __ps != __p;)
983*4d6fc14bSjoerg    {
984*4d6fc14bSjoerg        if (_Traits::eq(*--__ps, __c))
985*4d6fc14bSjoerg            return static_cast<_SizeT>(__ps - __p);
986*4d6fc14bSjoerg    }
987*4d6fc14bSjoerg    return __npos;
988*4d6fc14bSjoerg}
989*4d6fc14bSjoerg
990*4d6fc14bSjoergtemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
991*4d6fc14bSjoerginline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
992*4d6fc14bSjoerg__str_rfind(const _CharT *__p, _SizeT __sz,
993*4d6fc14bSjoerg        const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
994*4d6fc14bSjoerg{
995*4d6fc14bSjoerg    __pos = _VSTD::min(__pos, __sz);
996*4d6fc14bSjoerg    if (__n < __sz - __pos)
997*4d6fc14bSjoerg        __pos += __n;
998*4d6fc14bSjoerg    else
999*4d6fc14bSjoerg        __pos = __sz;
1000*4d6fc14bSjoerg    const _CharT* __r = _VSTD::__find_end(
1001*4d6fc14bSjoerg                  __p, __p + __pos, __s, __s + __n, _Traits::eq,
1002*4d6fc14bSjoerg                        random_access_iterator_tag(), random_access_iterator_tag());
1003*4d6fc14bSjoerg    if (__n > 0 && __r == __p + __pos)
1004*4d6fc14bSjoerg        return __npos;
1005*4d6fc14bSjoerg    return static_cast<_SizeT>(__r - __p);
1006*4d6fc14bSjoerg}
1007*4d6fc14bSjoerg
1008*4d6fc14bSjoerg// __str_find_first_of
1009*4d6fc14bSjoergtemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1010*4d6fc14bSjoerginline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1011*4d6fc14bSjoerg__str_find_first_of(const _CharT *__p, _SizeT __sz,
1012*4d6fc14bSjoerg                const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1013*4d6fc14bSjoerg{
1014*4d6fc14bSjoerg    if (__pos >= __sz || __n == 0)
1015*4d6fc14bSjoerg        return __npos;
1016*4d6fc14bSjoerg    const _CharT* __r = _VSTD::__find_first_of_ce
1017*4d6fc14bSjoerg        (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq );
1018*4d6fc14bSjoerg    if (__r == __p + __sz)
1019*4d6fc14bSjoerg        return __npos;
1020*4d6fc14bSjoerg    return static_cast<_SizeT>(__r - __p);
1021*4d6fc14bSjoerg}
1022*4d6fc14bSjoerg
1023*4d6fc14bSjoerg
1024*4d6fc14bSjoerg// __str_find_last_of
1025*4d6fc14bSjoergtemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1026*4d6fc14bSjoerginline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1027*4d6fc14bSjoerg__str_find_last_of(const _CharT *__p, _SizeT __sz,
1028*4d6fc14bSjoerg               const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1029*4d6fc14bSjoerg    {
1030*4d6fc14bSjoerg    if (__n != 0)
1031*4d6fc14bSjoerg    {
1032*4d6fc14bSjoerg        if (__pos < __sz)
1033*4d6fc14bSjoerg            ++__pos;
1034*4d6fc14bSjoerg        else
1035*4d6fc14bSjoerg            __pos = __sz;
1036*4d6fc14bSjoerg        for (const _CharT* __ps = __p + __pos; __ps != __p;)
1037*4d6fc14bSjoerg        {
1038*4d6fc14bSjoerg            const _CharT* __r = _Traits::find(__s, __n, *--__ps);
1039*4d6fc14bSjoerg            if (__r)
1040*4d6fc14bSjoerg                return static_cast<_SizeT>(__ps - __p);
1041*4d6fc14bSjoerg        }
1042*4d6fc14bSjoerg    }
1043*4d6fc14bSjoerg    return __npos;
1044*4d6fc14bSjoerg}
1045*4d6fc14bSjoerg
1046*4d6fc14bSjoerg
1047*4d6fc14bSjoerg// __str_find_first_not_of
1048*4d6fc14bSjoergtemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1049*4d6fc14bSjoerginline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1050*4d6fc14bSjoerg__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
1051*4d6fc14bSjoerg                    const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1052*4d6fc14bSjoerg{
1053*4d6fc14bSjoerg    if (__pos < __sz)
1054*4d6fc14bSjoerg    {
1055*4d6fc14bSjoerg        const _CharT* __pe = __p + __sz;
1056*4d6fc14bSjoerg        for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
1057*4d6fc14bSjoerg            if (_Traits::find(__s, __n, *__ps) == nullptr)
1058*4d6fc14bSjoerg                return static_cast<_SizeT>(__ps - __p);
1059*4d6fc14bSjoerg    }
1060*4d6fc14bSjoerg    return __npos;
1061*4d6fc14bSjoerg}
1062*4d6fc14bSjoerg
1063*4d6fc14bSjoerg
1064*4d6fc14bSjoergtemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1065*4d6fc14bSjoerginline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1066*4d6fc14bSjoerg__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
1067*4d6fc14bSjoerg                          _CharT __c, _SizeT __pos) _NOEXCEPT
1068*4d6fc14bSjoerg{
1069*4d6fc14bSjoerg    if (__pos < __sz)
1070*4d6fc14bSjoerg    {
1071*4d6fc14bSjoerg        const _CharT* __pe = __p + __sz;
1072*4d6fc14bSjoerg        for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
1073*4d6fc14bSjoerg            if (!_Traits::eq(*__ps, __c))
1074*4d6fc14bSjoerg                return static_cast<_SizeT>(__ps - __p);
1075*4d6fc14bSjoerg    }
1076*4d6fc14bSjoerg    return __npos;
1077*4d6fc14bSjoerg}
1078*4d6fc14bSjoerg
1079*4d6fc14bSjoerg
1080*4d6fc14bSjoerg// __str_find_last_not_of
1081*4d6fc14bSjoergtemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1082*4d6fc14bSjoerginline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1083*4d6fc14bSjoerg__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
1084*4d6fc14bSjoerg                   const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
1085*4d6fc14bSjoerg{
1086*4d6fc14bSjoerg    if (__pos < __sz)
1087*4d6fc14bSjoerg        ++__pos;
1088*4d6fc14bSjoerg    else
1089*4d6fc14bSjoerg        __pos = __sz;
1090*4d6fc14bSjoerg    for (const _CharT* __ps = __p + __pos; __ps != __p;)
1091*4d6fc14bSjoerg        if (_Traits::find(__s, __n, *--__ps) == nullptr)
1092*4d6fc14bSjoerg            return static_cast<_SizeT>(__ps - __p);
1093*4d6fc14bSjoerg    return __npos;
1094*4d6fc14bSjoerg}
1095*4d6fc14bSjoerg
1096*4d6fc14bSjoerg
1097*4d6fc14bSjoergtemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
1098*4d6fc14bSjoerginline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
1099*4d6fc14bSjoerg__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
1100*4d6fc14bSjoerg                         _CharT __c, _SizeT __pos) _NOEXCEPT
1101*4d6fc14bSjoerg{
1102*4d6fc14bSjoerg    if (__pos < __sz)
1103*4d6fc14bSjoerg        ++__pos;
1104*4d6fc14bSjoerg    else
1105*4d6fc14bSjoerg        __pos = __sz;
1106*4d6fc14bSjoerg    for (const _CharT* __ps = __p + __pos; __ps != __p;)
1107*4d6fc14bSjoerg        if (!_Traits::eq(*--__ps, __c))
1108*4d6fc14bSjoerg            return static_cast<_SizeT>(__ps - __p);
1109*4d6fc14bSjoerg    return __npos;
1110*4d6fc14bSjoerg}
1111*4d6fc14bSjoerg
1112*4d6fc14bSjoergtemplate<class _Ptr>
1113*4d6fc14bSjoerginline _LIBCPP_INLINE_VISIBILITY
1114*4d6fc14bSjoergsize_t __do_string_hash(_Ptr __p, _Ptr __e)
1115*4d6fc14bSjoerg{
1116*4d6fc14bSjoerg    typedef typename iterator_traits<_Ptr>::value_type value_type;
1117*4d6fc14bSjoerg    return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type));
1118*4d6fc14bSjoerg}
1119*4d6fc14bSjoerg
1120*4d6fc14bSjoergtemplate <class _CharT, class _Iter, class _Traits=char_traits<_CharT> >
1121*4d6fc14bSjoergstruct __quoted_output_proxy
1122*4d6fc14bSjoerg{
1123*4d6fc14bSjoerg    _Iter  __first;
1124*4d6fc14bSjoerg    _Iter  __last;
1125*4d6fc14bSjoerg    _CharT  __delim;
1126*4d6fc14bSjoerg    _CharT  __escape;
1127*4d6fc14bSjoerg
1128*4d6fc14bSjoerg    __quoted_output_proxy(_Iter __f, _Iter __l, _CharT __d, _CharT __e)
1129*4d6fc14bSjoerg    : __first(__f), __last(__l), __delim(__d), __escape(__e) {}
1130*4d6fc14bSjoerg    //  This would be a nice place for a string_ref
1131*4d6fc14bSjoerg};
1132*4d6fc14bSjoerg
1133*4d6fc14bSjoerg_LIBCPP_END_NAMESPACE_STD
1134*4d6fc14bSjoerg
1135*4d6fc14bSjoerg_LIBCPP_POP_MACROS
1136*4d6fc14bSjoerg
1137*4d6fc14bSjoerg#endif // _LIBCPP___STRING
1138