1aed8d94eSDimitry Andric// -*- C++ -*-
2aed8d94eSDimitry Andric//===-------------------------- __string ----------------------------------===//
3aed8d94eSDimitry Andric//
4aed8d94eSDimitry Andric//                     The LLVM Compiler Infrastructure
5aed8d94eSDimitry Andric//
6aed8d94eSDimitry Andric// This file is distributed under the University of Illinois Open Source
7aed8d94eSDimitry Andric// License. See LICENSE.TXT for details.
8aed8d94eSDimitry Andric//
9aed8d94eSDimitry Andric//===----------------------------------------------------------------------===//
10aed8d94eSDimitry Andric
11aed8d94eSDimitry Andric#ifndef _LIBCPP___STRING
12aed8d94eSDimitry Andric#define _LIBCPP___STRING
13aed8d94eSDimitry Andric
14aed8d94eSDimitry Andric/*
15aed8d94eSDimitry Andric    string synopsis
16aed8d94eSDimitry Andric
17aed8d94eSDimitry Andricnamespace std
18aed8d94eSDimitry Andric{
19aed8d94eSDimitry Andric
20aed8d94eSDimitry Andrictemplate <class charT>
21aed8d94eSDimitry Andricstruct char_traits
22aed8d94eSDimitry Andric{
23aed8d94eSDimitry Andric    typedef charT     char_type;
24aed8d94eSDimitry Andric    typedef ...       int_type;
25aed8d94eSDimitry Andric    typedef streamoff off_type;
26aed8d94eSDimitry Andric    typedef streampos pos_type;
27aed8d94eSDimitry Andric    typedef mbstate_t state_type;
28aed8d94eSDimitry Andric
297a848d17SDimitry Andric    static constexpr void assign(char_type& c1, const char_type& c2) noexcept;
30aed8d94eSDimitry Andric    static constexpr bool eq(char_type c1, char_type c2) noexcept;
31aed8d94eSDimitry Andric    static constexpr bool lt(char_type c1, char_type c2) noexcept;
32aed8d94eSDimitry Andric
337a848d17SDimitry Andric    static constexpr int    compare(const char_type* s1, const char_type* s2, size_t n);
347a848d17SDimitry Andric    static constexpr size_t length(const char_type* s);
357a848d17SDimitry Andric    static constexpr const char_type*
367a848d17SDimitry Andric                            find(const char_type* s, size_t n, const char_type& a);
37aed8d94eSDimitry Andric    static char_type*       move(char_type* s1, const char_type* s2, size_t n);
38aed8d94eSDimitry Andric    static char_type*       copy(char_type* s1, const char_type* s2, size_t n);
39aed8d94eSDimitry Andric    static char_type*       assign(char_type* s, size_t n, char_type a);
40aed8d94eSDimitry Andric
41aed8d94eSDimitry Andric    static constexpr int_type  not_eof(int_type c) noexcept;
42aed8d94eSDimitry Andric    static constexpr char_type to_char_type(int_type c) noexcept;
43aed8d94eSDimitry Andric    static constexpr int_type  to_int_type(char_type c) noexcept;
44aed8d94eSDimitry Andric    static constexpr bool      eq_int_type(int_type c1, int_type c2) noexcept;
45aed8d94eSDimitry Andric    static constexpr int_type  eof() noexcept;
46aed8d94eSDimitry Andric};
47aed8d94eSDimitry Andric
48aed8d94eSDimitry Andrictemplate <> struct char_traits<char>;
49aed8d94eSDimitry Andrictemplate <> struct char_traits<wchar_t>;
50*b5893f02SDimitry Andrictemplate <> struct char_traits<char8_t>;  // c++20
51aed8d94eSDimitry Andric
52aed8d94eSDimitry Andric}  // std
53aed8d94eSDimitry Andric
54aed8d94eSDimitry Andric*/
55aed8d94eSDimitry Andric
56aed8d94eSDimitry Andric#include <__config>
57aed8d94eSDimitry Andric#include <algorithm>  // for search and min
58aed8d94eSDimitry Andric#include <cstdio>     // For EOF.
59aed8d94eSDimitry Andric#include <memory>     // for __murmur2_or_cityhash
60aed8d94eSDimitry Andric
61aed8d94eSDimitry Andric#include <__debug>
62aed8d94eSDimitry Andric
63aed8d94eSDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
64aed8d94eSDimitry Andric#pragma GCC system_header
65aed8d94eSDimitry Andric#endif
66aed8d94eSDimitry Andric
67f9448bf3SDimitry Andric_LIBCPP_PUSH_MACROS
68f9448bf3SDimitry Andric#include <__undef_macros>
69f9448bf3SDimitry Andric
70f9448bf3SDimitry Andric
71aed8d94eSDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
72aed8d94eSDimitry Andric
73aed8d94eSDimitry Andric// char_traits
74aed8d94eSDimitry Andric
75aed8d94eSDimitry Andrictemplate <class _CharT>
76aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits
77aed8d94eSDimitry Andric{
78aed8d94eSDimitry Andric    typedef _CharT    char_type;
79aed8d94eSDimitry Andric    typedef int       int_type;
80aed8d94eSDimitry Andric    typedef streamoff off_type;
81aed8d94eSDimitry Andric    typedef streampos pos_type;
82aed8d94eSDimitry Andric    typedef mbstate_t state_type;
83aed8d94eSDimitry Andric
847a848d17SDimitry Andric    static inline void _LIBCPP_CONSTEXPR_AFTER_CXX14
857a848d17SDimitry Andric        assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
86aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
87aed8d94eSDimitry Andric        {return __c1 == __c2;}
88aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
89aed8d94eSDimitry Andric        {return __c1 < __c2;}
90aed8d94eSDimitry Andric
917a848d17SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
927a848d17SDimitry Andric    int compare(const char_type* __s1, const char_type* __s2, size_t __n);
937a848d17SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
947a848d17SDimitry Andric    size_t length(const char_type* __s);
957a848d17SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
967a848d17SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a);
97aed8d94eSDimitry Andric    static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n);
98aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
99aed8d94eSDimitry Andric    static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n);
100aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
101aed8d94eSDimitry Andric    static char_type*       assign(char_type* __s, size_t __n, char_type __a);
102aed8d94eSDimitry Andric
103aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
104aed8d94eSDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
105aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
106aed8d94eSDimitry Andric        {return char_type(__c);}
107aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  to_int_type(char_type __c) _NOEXCEPT
108aed8d94eSDimitry Andric        {return int_type(__c);}
109aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool      eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
110aed8d94eSDimitry Andric        {return __c1 == __c2;}
111aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  eof() _NOEXCEPT
112aed8d94eSDimitry Andric        {return int_type(EOF);}
113aed8d94eSDimitry Andric};
114aed8d94eSDimitry Andric
115aed8d94eSDimitry Andrictemplate <class _CharT>
1167a848d17SDimitry Andric_LIBCPP_CONSTEXPR_AFTER_CXX14 int
117aed8d94eSDimitry Andricchar_traits<_CharT>::compare(const char_type* __s1, const char_type* __s2, size_t __n)
118aed8d94eSDimitry Andric{
119aed8d94eSDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
120aed8d94eSDimitry Andric    {
121aed8d94eSDimitry Andric        if (lt(*__s1, *__s2))
122aed8d94eSDimitry Andric            return -1;
123aed8d94eSDimitry Andric        if (lt(*__s2, *__s1))
124aed8d94eSDimitry Andric            return 1;
125aed8d94eSDimitry Andric    }
126aed8d94eSDimitry Andric    return 0;
127aed8d94eSDimitry Andric}
128aed8d94eSDimitry Andric
129aed8d94eSDimitry Andrictemplate <class _CharT>
130aed8d94eSDimitry Andricinline
1317a848d17SDimitry Andric_LIBCPP_CONSTEXPR_AFTER_CXX14 size_t
132aed8d94eSDimitry Andricchar_traits<_CharT>::length(const char_type* __s)
133aed8d94eSDimitry Andric{
134aed8d94eSDimitry Andric    size_t __len = 0;
135aed8d94eSDimitry Andric    for (; !eq(*__s, char_type(0)); ++__s)
136aed8d94eSDimitry Andric        ++__len;
137aed8d94eSDimitry Andric    return __len;
138aed8d94eSDimitry Andric}
139aed8d94eSDimitry Andric
140aed8d94eSDimitry Andrictemplate <class _CharT>
141aed8d94eSDimitry Andricinline
1427a848d17SDimitry Andric_LIBCPP_CONSTEXPR_AFTER_CXX14 const _CharT*
143aed8d94eSDimitry Andricchar_traits<_CharT>::find(const char_type* __s, size_t __n, const char_type& __a)
144aed8d94eSDimitry Andric{
145aed8d94eSDimitry Andric    for (; __n; --__n)
146aed8d94eSDimitry Andric    {
147aed8d94eSDimitry Andric        if (eq(*__s, __a))
148aed8d94eSDimitry Andric            return __s;
149aed8d94eSDimitry Andric        ++__s;
150aed8d94eSDimitry Andric    }
151aed8d94eSDimitry Andric    return 0;
152aed8d94eSDimitry Andric}
153aed8d94eSDimitry Andric
154aed8d94eSDimitry Andrictemplate <class _CharT>
155aed8d94eSDimitry Andric_CharT*
156aed8d94eSDimitry Andricchar_traits<_CharT>::move(char_type* __s1, const char_type* __s2, size_t __n)
157aed8d94eSDimitry Andric{
158aed8d94eSDimitry Andric    char_type* __r = __s1;
159aed8d94eSDimitry Andric    if (__s1 < __s2)
160aed8d94eSDimitry Andric    {
161aed8d94eSDimitry Andric        for (; __n; --__n, ++__s1, ++__s2)
162aed8d94eSDimitry Andric            assign(*__s1, *__s2);
163aed8d94eSDimitry Andric    }
164aed8d94eSDimitry Andric    else if (__s2 < __s1)
165aed8d94eSDimitry Andric    {
166aed8d94eSDimitry Andric        __s1 += __n;
167aed8d94eSDimitry Andric        __s2 += __n;
168aed8d94eSDimitry Andric        for (; __n; --__n)
169aed8d94eSDimitry Andric            assign(*--__s1, *--__s2);
170aed8d94eSDimitry Andric    }
171aed8d94eSDimitry Andric    return __r;
172aed8d94eSDimitry Andric}
173aed8d94eSDimitry Andric
174aed8d94eSDimitry Andrictemplate <class _CharT>
175aed8d94eSDimitry Andricinline
176aed8d94eSDimitry Andric_CharT*
177aed8d94eSDimitry Andricchar_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n)
178aed8d94eSDimitry Andric{
179aed8d94eSDimitry Andric    _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
180aed8d94eSDimitry Andric    char_type* __r = __s1;
181aed8d94eSDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
182aed8d94eSDimitry Andric        assign(*__s1, *__s2);
183aed8d94eSDimitry Andric    return __r;
184aed8d94eSDimitry Andric}
185aed8d94eSDimitry Andric
186aed8d94eSDimitry Andrictemplate <class _CharT>
187aed8d94eSDimitry Andricinline
188aed8d94eSDimitry Andric_CharT*
189aed8d94eSDimitry Andricchar_traits<_CharT>::assign(char_type* __s, size_t __n, char_type __a)
190aed8d94eSDimitry Andric{
191aed8d94eSDimitry Andric    char_type* __r = __s;
192aed8d94eSDimitry Andric    for (; __n; --__n, ++__s)
193aed8d94eSDimitry Andric        assign(*__s, __a);
194aed8d94eSDimitry Andric    return __r;
195aed8d94eSDimitry Andric}
196aed8d94eSDimitry Andric
197aed8d94eSDimitry Andric// char_traits<char>
198aed8d94eSDimitry Andric
199aed8d94eSDimitry Andrictemplate <>
200aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits<char>
201aed8d94eSDimitry Andric{
202aed8d94eSDimitry Andric    typedef char      char_type;
203aed8d94eSDimitry Andric    typedef int       int_type;
204aed8d94eSDimitry Andric    typedef streamoff off_type;
205aed8d94eSDimitry Andric    typedef streampos pos_type;
206aed8d94eSDimitry Andric    typedef mbstate_t state_type;
207aed8d94eSDimitry Andric
2087a848d17SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
2097a848d17SDimitry Andric    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
210aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
211aed8d94eSDimitry Andric            {return __c1 == __c2;}
212aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
213aed8d94eSDimitry Andric        {return (unsigned char)__c1 < (unsigned char)__c2;}
214aed8d94eSDimitry Andric
2157a848d17SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
2167a848d17SDimitry Andric    int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
2177a848d17SDimitry Andric    static inline size_t _LIBCPP_CONSTEXPR_AFTER_CXX14
2187a848d17SDimitry Andric    length(const char_type* __s)  _NOEXCEPT {return __builtin_strlen(__s);}
2197a848d17SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
2207a848d17SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
221aed8d94eSDimitry Andric    static inline char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
222aed8d94eSDimitry Andric        {return __n == 0 ? __s1 : (char_type*) memmove(__s1, __s2, __n);}
223aed8d94eSDimitry Andric    static inline char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
224aed8d94eSDimitry Andric        {
225aed8d94eSDimitry Andric            _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
226aed8d94eSDimitry Andric            return __n == 0 ? __s1 : (char_type*)memcpy(__s1, __s2, __n);
227aed8d94eSDimitry Andric        }
228aed8d94eSDimitry Andric    static inline char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
229aed8d94eSDimitry Andric        {return __n == 0 ? __s : (char_type*)memset(__s, to_int_type(__a), __n);}
230aed8d94eSDimitry Andric
231aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
232aed8d94eSDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
233aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
234aed8d94eSDimitry Andric        {return char_type(__c);}
235aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
236aed8d94eSDimitry Andric        {return int_type((unsigned char)__c);}
237aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
238aed8d94eSDimitry Andric        {return __c1 == __c2;}
239aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  eof() _NOEXCEPT
240aed8d94eSDimitry Andric        {return int_type(EOF);}
241aed8d94eSDimitry Andric};
242aed8d94eSDimitry Andric
2437a848d17SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
2447a848d17SDimitry Andricint
2457a848d17SDimitry Andricchar_traits<char>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
2467a848d17SDimitry Andric{
2477a848d17SDimitry Andric    if (__n == 0)
2487a848d17SDimitry Andric        return 0;
24998221d2eSDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
2507a848d17SDimitry Andric    return __builtin_memcmp(__s1, __s2, __n);
2517a848d17SDimitry Andric#elif _LIBCPP_STD_VER <= 14
2527a848d17SDimitry Andric    return memcmp(__s1, __s2, __n);
2537a848d17SDimitry Andric#else
2547a848d17SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
2557a848d17SDimitry Andric    {
2567a848d17SDimitry Andric        if (lt(*__s1, *__s2))
2577a848d17SDimitry Andric            return -1;
2587a848d17SDimitry Andric        if (lt(*__s2, *__s1))
2597a848d17SDimitry Andric            return 1;
2607a848d17SDimitry Andric    }
2617a848d17SDimitry Andric    return 0;
2627a848d17SDimitry Andric#endif
2637a848d17SDimitry Andric}
2647a848d17SDimitry Andric
2657a848d17SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
2667a848d17SDimitry Andricconst char*
2677a848d17SDimitry Andricchar_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
2687a848d17SDimitry Andric{
2697a848d17SDimitry Andric    if (__n == 0)
2704ba319b5SDimitry Andric        return nullptr;
27198221d2eSDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
27298221d2eSDimitry Andric    return __builtin_char_memchr(__s, to_int_type(__a), __n);
27398221d2eSDimitry Andric#elif _LIBCPP_STD_VER <= 14
2747a848d17SDimitry Andric    return (const char_type*) memchr(__s, to_int_type(__a), __n);
2757a848d17SDimitry Andric#else
2767a848d17SDimitry Andric    for (; __n; --__n)
2777a848d17SDimitry Andric    {
2787a848d17SDimitry Andric        if (eq(*__s, __a))
2797a848d17SDimitry Andric            return __s;
2807a848d17SDimitry Andric        ++__s;
2817a848d17SDimitry Andric    }
2824ba319b5SDimitry Andric    return nullptr;
2837a848d17SDimitry Andric#endif
2847a848d17SDimitry Andric}
2857a848d17SDimitry Andric
2867a848d17SDimitry Andric
287aed8d94eSDimitry Andric// char_traits<wchar_t>
288aed8d94eSDimitry Andric
289aed8d94eSDimitry Andrictemplate <>
290aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
291aed8d94eSDimitry Andric{
292aed8d94eSDimitry Andric    typedef wchar_t   char_type;
293aed8d94eSDimitry Andric    typedef wint_t    int_type;
294aed8d94eSDimitry Andric    typedef streamoff off_type;
295aed8d94eSDimitry Andric    typedef streampos pos_type;
296aed8d94eSDimitry Andric    typedef mbstate_t state_type;
297aed8d94eSDimitry Andric
2987a848d17SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
2997a848d17SDimitry Andric    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
300aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
301aed8d94eSDimitry Andric        {return __c1 == __c2;}
302aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
303aed8d94eSDimitry Andric        {return __c1 < __c2;}
304aed8d94eSDimitry Andric
3057a848d17SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
3067a848d17SDimitry Andric    int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
3077a848d17SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
3087a848d17SDimitry Andric    size_t length(const char_type* __s) _NOEXCEPT;
3097a848d17SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
3107a848d17SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
311aed8d94eSDimitry Andric    static inline char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
312aed8d94eSDimitry Andric        {return __n == 0 ? __s1 : (char_type*)wmemmove(__s1, __s2, __n);}
313aed8d94eSDimitry Andric    static inline char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
314aed8d94eSDimitry Andric        {
315aed8d94eSDimitry Andric            _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
316aed8d94eSDimitry Andric            return __n == 0 ? __s1 : (char_type*)wmemcpy(__s1, __s2, __n);
317aed8d94eSDimitry Andric        }
318aed8d94eSDimitry Andric    static inline char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
319aed8d94eSDimitry Andric        {return __n == 0 ? __s : (char_type*)wmemset(__s, __a, __n);}
320aed8d94eSDimitry Andric
321aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
322aed8d94eSDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
323aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
324aed8d94eSDimitry Andric        {return char_type(__c);}
325aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
326aed8d94eSDimitry Andric        {return int_type(__c);}
327aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
328aed8d94eSDimitry Andric        {return __c1 == __c2;}
329aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
330aed8d94eSDimitry Andric        {return int_type(WEOF);}
331aed8d94eSDimitry Andric};
332aed8d94eSDimitry Andric
3337a848d17SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
3347a848d17SDimitry Andricint
3357a848d17SDimitry Andricchar_traits<wchar_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
3367a848d17SDimitry Andric{
3377a848d17SDimitry Andric    if (__n == 0)
3387a848d17SDimitry Andric        return 0;
33998221d2eSDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
3407a848d17SDimitry Andric    return __builtin_wmemcmp(__s1, __s2, __n);
3417a848d17SDimitry Andric#elif _LIBCPP_STD_VER <= 14
3427a848d17SDimitry Andric    return wmemcmp(__s1, __s2, __n);
3437a848d17SDimitry Andric#else
3447a848d17SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
3457a848d17SDimitry Andric    {
3467a848d17SDimitry Andric        if (lt(*__s1, *__s2))
3477a848d17SDimitry Andric            return -1;
3487a848d17SDimitry Andric        if (lt(*__s2, *__s1))
3497a848d17SDimitry Andric            return 1;
3507a848d17SDimitry Andric    }
3517a848d17SDimitry Andric    return 0;
3527a848d17SDimitry Andric#endif
3537a848d17SDimitry Andric}
3547a848d17SDimitry Andric
3557a848d17SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
3567a848d17SDimitry Andricsize_t
3577a848d17SDimitry Andricchar_traits<wchar_t>::length(const char_type* __s) _NOEXCEPT
3587a848d17SDimitry Andric{
35998221d2eSDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
3607a848d17SDimitry Andric    return __builtin_wcslen(__s);
3617a848d17SDimitry Andric#elif _LIBCPP_STD_VER <= 14
3627a848d17SDimitry Andric    return wcslen(__s);
3637a848d17SDimitry Andric#else
3647a848d17SDimitry Andric    size_t __len = 0;
3657a848d17SDimitry Andric    for (; !eq(*__s, char_type(0)); ++__s)
3667a848d17SDimitry Andric        ++__len;
3677a848d17SDimitry Andric    return __len;
3687a848d17SDimitry Andric#endif
3697a848d17SDimitry Andric}
3707a848d17SDimitry Andric
3717a848d17SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
3727a848d17SDimitry Andricconst wchar_t*
3737a848d17SDimitry Andricchar_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
3747a848d17SDimitry Andric{
3757a848d17SDimitry Andric    if (__n == 0)
3764ba319b5SDimitry Andric        return nullptr;
37798221d2eSDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
3787a848d17SDimitry Andric    return __builtin_wmemchr(__s, __a, __n);
3797a848d17SDimitry Andric#elif _LIBCPP_STD_VER <= 14
3807a848d17SDimitry Andric    return wmemchr(__s, __a, __n);
3817a848d17SDimitry Andric#else
3827a848d17SDimitry Andric    for (; __n; --__n)
3837a848d17SDimitry Andric    {
3847a848d17SDimitry Andric        if (eq(*__s, __a))
3857a848d17SDimitry Andric            return __s;
3867a848d17SDimitry Andric        ++__s;
3877a848d17SDimitry Andric    }
3884ba319b5SDimitry Andric    return nullptr;
3897a848d17SDimitry Andric#endif
3907a848d17SDimitry Andric}
3917a848d17SDimitry Andric
3927a848d17SDimitry Andric
393*b5893f02SDimitry Andric#ifndef _LIBCPP_NO_HAS_CHAR8_T
394*b5893f02SDimitry Andric
395*b5893f02SDimitry Andrictemplate <>
396*b5893f02SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
397*b5893f02SDimitry Andric{
398*b5893f02SDimitry Andric    typedef char8_t        char_type;
399*b5893f02SDimitry Andric    typedef unsigned int   int_type;
400*b5893f02SDimitry Andric    typedef streamoff      off_type;
401*b5893f02SDimitry Andric    typedef u8streampos    pos_type;
402*b5893f02SDimitry Andric    typedef mbstate_t      state_type;
403*b5893f02SDimitry Andric
404*b5893f02SDimitry Andric    static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
405*b5893f02SDimitry Andric        {__c1 = __c2;}
406*b5893f02SDimitry Andric    static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept
407*b5893f02SDimitry Andric        {return __c1 == __c2;}
408*b5893f02SDimitry Andric    static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept
409*b5893f02SDimitry Andric        {return __c1 < __c2;}
410*b5893f02SDimitry Andric
411*b5893f02SDimitry Andric    static constexpr
412*b5893f02SDimitry Andric    int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
413*b5893f02SDimitry Andric
414*b5893f02SDimitry Andric    static constexpr
415*b5893f02SDimitry Andric    size_t           length(const char_type* __s) _NOEXCEPT;
416*b5893f02SDimitry Andric
417*b5893f02SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static constexpr
418*b5893f02SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
419*b5893f02SDimitry Andric
420*b5893f02SDimitry Andric    static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
421*b5893f02SDimitry Andric        {return __n == 0 ? __s1 : (char_type*) memmove(__s1, __s2, __n);}
422*b5893f02SDimitry Andric
423*b5893f02SDimitry Andric    static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
424*b5893f02SDimitry Andric       {
425*b5893f02SDimitry Andric            _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
426*b5893f02SDimitry Andric            return __n == 0 ? __s1 : (char_type*)memcpy(__s1, __s2, __n);
427*b5893f02SDimitry Andric       }
428*b5893f02SDimitry Andric
429*b5893f02SDimitry Andric    static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
430*b5893f02SDimitry Andric        {return __n == 0 ? __s : (char_type*)memset(__s, to_int_type(__a), __n);}
431*b5893f02SDimitry Andric
432*b5893f02SDimitry Andric    static inline constexpr int_type  not_eof(int_type __c) noexcept
433*b5893f02SDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
434*b5893f02SDimitry Andric    static inline constexpr char_type to_char_type(int_type __c) noexcept
435*b5893f02SDimitry Andric        {return char_type(__c);}
436*b5893f02SDimitry Andric    static inline constexpr int_type to_int_type(char_type __c) noexcept
437*b5893f02SDimitry Andric        {return int_type(__c);}
438*b5893f02SDimitry Andric    static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept
439*b5893f02SDimitry Andric        {return __c1 == __c2;}
440*b5893f02SDimitry Andric    static inline constexpr int_type eof() noexcept
441*b5893f02SDimitry Andric        {return int_type(EOF);}
442*b5893f02SDimitry Andric};
443*b5893f02SDimitry Andric
444*b5893f02SDimitry Andric// TODO use '__builtin_strlen' if it ever supports char8_t ??
445*b5893f02SDimitry Andricinline constexpr
446*b5893f02SDimitry Andricsize_t
447*b5893f02SDimitry Andricchar_traits<char8_t>::length(const char_type* __s) _NOEXCEPT
448*b5893f02SDimitry Andric{
449*b5893f02SDimitry Andric    size_t __len = 0;
450*b5893f02SDimitry Andric    for (; !eq(*__s, char_type(0)); ++__s)
451*b5893f02SDimitry Andric        ++__len;
452*b5893f02SDimitry Andric    return __len;
453*b5893f02SDimitry Andric}
454*b5893f02SDimitry Andric
455*b5893f02SDimitry Andricinline constexpr
456*b5893f02SDimitry Andricint
457*b5893f02SDimitry Andricchar_traits<char8_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
458*b5893f02SDimitry Andric{
459*b5893f02SDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
460*b5893f02SDimitry Andric    return __builtin_memcmp(__s1, __s2, __n);
461*b5893f02SDimitry Andric#else
462*b5893f02SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
463*b5893f02SDimitry Andric    {
464*b5893f02SDimitry Andric        if (lt(*__s1, *__s2))
465*b5893f02SDimitry Andric            return -1;
466*b5893f02SDimitry Andric        if (lt(*__s2, *__s1))
467*b5893f02SDimitry Andric            return 1;
468*b5893f02SDimitry Andric    }
469*b5893f02SDimitry Andric    return 0;
470*b5893f02SDimitry Andric#endif
471*b5893f02SDimitry Andric}
472*b5893f02SDimitry Andric
473*b5893f02SDimitry Andric// TODO use '__builtin_char_memchr' if it ever supports char8_t ??
474*b5893f02SDimitry Andricinline constexpr
475*b5893f02SDimitry Andricconst char8_t*
476*b5893f02SDimitry Andricchar_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
477*b5893f02SDimitry Andric{
478*b5893f02SDimitry Andric    for (; __n; --__n)
479*b5893f02SDimitry Andric    {
480*b5893f02SDimitry Andric        if (eq(*__s, __a))
481*b5893f02SDimitry Andric            return __s;
482*b5893f02SDimitry Andric        ++__s;
483*b5893f02SDimitry Andric    }
484*b5893f02SDimitry Andric    return 0;
485*b5893f02SDimitry Andric}
486*b5893f02SDimitry Andric
487*b5893f02SDimitry Andric#endif // #_LIBCPP_NO_HAS_CHAR8_T
488*b5893f02SDimitry Andric
489aed8d94eSDimitry Andric#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
490aed8d94eSDimitry Andric
491aed8d94eSDimitry Andrictemplate <>
492aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
493aed8d94eSDimitry Andric{
494aed8d94eSDimitry Andric    typedef char16_t       char_type;
495aed8d94eSDimitry Andric    typedef uint_least16_t int_type;
496aed8d94eSDimitry Andric    typedef streamoff      off_type;
497aed8d94eSDimitry Andric    typedef u16streampos   pos_type;
498aed8d94eSDimitry Andric    typedef mbstate_t      state_type;
499aed8d94eSDimitry Andric
5007a848d17SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
5017a848d17SDimitry Andric    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
502aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
503aed8d94eSDimitry Andric        {return __c1 == __c2;}
504aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
505aed8d94eSDimitry Andric        {return __c1 < __c2;}
506aed8d94eSDimitry Andric
5077a848d17SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
5087a848d17SDimitry Andric    int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
5097a848d17SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
5107a848d17SDimitry Andric    size_t           length(const char_type* __s) _NOEXCEPT;
5117a848d17SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
5127a848d17SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
513aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
514aed8d94eSDimitry Andric    static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
515aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
516aed8d94eSDimitry Andric    static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
517aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
518aed8d94eSDimitry Andric    static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
519aed8d94eSDimitry Andric
520aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
521aed8d94eSDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
522aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
523aed8d94eSDimitry Andric        {return char_type(__c);}
524aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
525aed8d94eSDimitry Andric        {return int_type(__c);}
526aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
527aed8d94eSDimitry Andric        {return __c1 == __c2;}
528aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
529aed8d94eSDimitry Andric        {return int_type(0xFFFF);}
530aed8d94eSDimitry Andric};
531aed8d94eSDimitry Andric
5327a848d17SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
533aed8d94eSDimitry Andricint
534aed8d94eSDimitry Andricchar_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
535aed8d94eSDimitry Andric{
536aed8d94eSDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
537aed8d94eSDimitry Andric    {
538aed8d94eSDimitry Andric        if (lt(*__s1, *__s2))
539aed8d94eSDimitry Andric            return -1;
540aed8d94eSDimitry Andric        if (lt(*__s2, *__s1))
541aed8d94eSDimitry Andric            return 1;
542aed8d94eSDimitry Andric    }
543aed8d94eSDimitry Andric    return 0;
544aed8d94eSDimitry Andric}
545aed8d94eSDimitry Andric
5467a848d17SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
547aed8d94eSDimitry Andricsize_t
548aed8d94eSDimitry Andricchar_traits<char16_t>::length(const char_type* __s) _NOEXCEPT
549aed8d94eSDimitry Andric{
550aed8d94eSDimitry Andric    size_t __len = 0;
551aed8d94eSDimitry Andric    for (; !eq(*__s, char_type(0)); ++__s)
552aed8d94eSDimitry Andric        ++__len;
553aed8d94eSDimitry Andric    return __len;
554aed8d94eSDimitry Andric}
555aed8d94eSDimitry Andric
5567a848d17SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
557aed8d94eSDimitry Andricconst char16_t*
558aed8d94eSDimitry Andricchar_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
559aed8d94eSDimitry Andric{
560aed8d94eSDimitry Andric    for (; __n; --__n)
561aed8d94eSDimitry Andric    {
562aed8d94eSDimitry Andric        if (eq(*__s, __a))
563aed8d94eSDimitry Andric            return __s;
564aed8d94eSDimitry Andric        ++__s;
565aed8d94eSDimitry Andric    }
566aed8d94eSDimitry Andric    return 0;
567aed8d94eSDimitry Andric}
568aed8d94eSDimitry Andric
569aed8d94eSDimitry Andricinline
570aed8d94eSDimitry Andricchar16_t*
571aed8d94eSDimitry Andricchar_traits<char16_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
572aed8d94eSDimitry Andric{
573aed8d94eSDimitry Andric    char_type* __r = __s1;
574aed8d94eSDimitry Andric    if (__s1 < __s2)
575aed8d94eSDimitry Andric    {
576aed8d94eSDimitry Andric        for (; __n; --__n, ++__s1, ++__s2)
577aed8d94eSDimitry Andric            assign(*__s1, *__s2);
578aed8d94eSDimitry Andric    }
579aed8d94eSDimitry Andric    else if (__s2 < __s1)
580aed8d94eSDimitry Andric    {
581aed8d94eSDimitry Andric        __s1 += __n;
582aed8d94eSDimitry Andric        __s2 += __n;
583aed8d94eSDimitry Andric        for (; __n; --__n)
584aed8d94eSDimitry Andric            assign(*--__s1, *--__s2);
585aed8d94eSDimitry Andric    }
586aed8d94eSDimitry Andric    return __r;
587aed8d94eSDimitry Andric}
588aed8d94eSDimitry Andric
589aed8d94eSDimitry Andricinline
590aed8d94eSDimitry Andricchar16_t*
591aed8d94eSDimitry Andricchar_traits<char16_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
592aed8d94eSDimitry Andric{
593aed8d94eSDimitry Andric    _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
594aed8d94eSDimitry Andric    char_type* __r = __s1;
595aed8d94eSDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
596aed8d94eSDimitry Andric        assign(*__s1, *__s2);
597aed8d94eSDimitry Andric    return __r;
598aed8d94eSDimitry Andric}
599aed8d94eSDimitry Andric
600aed8d94eSDimitry Andricinline
601aed8d94eSDimitry Andricchar16_t*
602aed8d94eSDimitry Andricchar_traits<char16_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
603aed8d94eSDimitry Andric{
604aed8d94eSDimitry Andric    char_type* __r = __s;
605aed8d94eSDimitry Andric    for (; __n; --__n, ++__s)
606aed8d94eSDimitry Andric        assign(*__s, __a);
607aed8d94eSDimitry Andric    return __r;
608aed8d94eSDimitry Andric}
609aed8d94eSDimitry Andric
610aed8d94eSDimitry Andrictemplate <>
611aed8d94eSDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
612aed8d94eSDimitry Andric{
613aed8d94eSDimitry Andric    typedef char32_t       char_type;
614aed8d94eSDimitry Andric    typedef uint_least32_t int_type;
615aed8d94eSDimitry Andric    typedef streamoff      off_type;
616aed8d94eSDimitry Andric    typedef u32streampos   pos_type;
617aed8d94eSDimitry Andric    typedef mbstate_t      state_type;
618aed8d94eSDimitry Andric
6197a848d17SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
6207a848d17SDimitry Andric    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
621aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
622aed8d94eSDimitry Andric        {return __c1 == __c2;}
623aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
624aed8d94eSDimitry Andric        {return __c1 < __c2;}
625aed8d94eSDimitry Andric
6267a848d17SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
6277a848d17SDimitry Andric    int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
6287a848d17SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
6297a848d17SDimitry Andric    size_t           length(const char_type* __s) _NOEXCEPT;
6307a848d17SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
6317a848d17SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
632aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
633aed8d94eSDimitry Andric    static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
634aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
635aed8d94eSDimitry Andric    static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
636aed8d94eSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
637aed8d94eSDimitry Andric    static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
638aed8d94eSDimitry Andric
639aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
640aed8d94eSDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
641aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
642aed8d94eSDimitry Andric        {return char_type(__c);}
643aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
644aed8d94eSDimitry Andric        {return int_type(__c);}
645aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
646aed8d94eSDimitry Andric        {return __c1 == __c2;}
647aed8d94eSDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
648aed8d94eSDimitry Andric        {return int_type(0xFFFFFFFF);}
649aed8d94eSDimitry Andric};
650aed8d94eSDimitry Andric
6517a848d17SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
652aed8d94eSDimitry Andricint
653aed8d94eSDimitry Andricchar_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
654aed8d94eSDimitry Andric{
655aed8d94eSDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
656aed8d94eSDimitry Andric    {
657aed8d94eSDimitry Andric        if (lt(*__s1, *__s2))
658aed8d94eSDimitry Andric            return -1;
659aed8d94eSDimitry Andric        if (lt(*__s2, *__s1))
660aed8d94eSDimitry Andric            return 1;
661aed8d94eSDimitry Andric    }
662aed8d94eSDimitry Andric    return 0;
663aed8d94eSDimitry Andric}
664aed8d94eSDimitry Andric
6657a848d17SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
666aed8d94eSDimitry Andricsize_t
667aed8d94eSDimitry Andricchar_traits<char32_t>::length(const char_type* __s) _NOEXCEPT
668aed8d94eSDimitry Andric{
669aed8d94eSDimitry Andric    size_t __len = 0;
670aed8d94eSDimitry Andric    for (; !eq(*__s, char_type(0)); ++__s)
671aed8d94eSDimitry Andric        ++__len;
672aed8d94eSDimitry Andric    return __len;
673aed8d94eSDimitry Andric}
674aed8d94eSDimitry Andric
6757a848d17SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
676aed8d94eSDimitry Andricconst char32_t*
677aed8d94eSDimitry Andricchar_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
678aed8d94eSDimitry Andric{
679aed8d94eSDimitry Andric    for (; __n; --__n)
680aed8d94eSDimitry Andric    {
681aed8d94eSDimitry Andric        if (eq(*__s, __a))
682aed8d94eSDimitry Andric            return __s;
683aed8d94eSDimitry Andric        ++__s;
684aed8d94eSDimitry Andric    }
685aed8d94eSDimitry Andric    return 0;
686aed8d94eSDimitry Andric}
687aed8d94eSDimitry Andric
688aed8d94eSDimitry Andricinline
689aed8d94eSDimitry Andricchar32_t*
690aed8d94eSDimitry Andricchar_traits<char32_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
691aed8d94eSDimitry Andric{
692aed8d94eSDimitry Andric    char_type* __r = __s1;
693aed8d94eSDimitry Andric    if (__s1 < __s2)
694aed8d94eSDimitry Andric    {
695aed8d94eSDimitry Andric        for (; __n; --__n, ++__s1, ++__s2)
696aed8d94eSDimitry Andric            assign(*__s1, *__s2);
697aed8d94eSDimitry Andric    }
698aed8d94eSDimitry Andric    else if (__s2 < __s1)
699aed8d94eSDimitry Andric    {
700aed8d94eSDimitry Andric        __s1 += __n;
701aed8d94eSDimitry Andric        __s2 += __n;
702aed8d94eSDimitry Andric        for (; __n; --__n)
703aed8d94eSDimitry Andric            assign(*--__s1, *--__s2);
704aed8d94eSDimitry Andric    }
705aed8d94eSDimitry Andric    return __r;
706aed8d94eSDimitry Andric}
707aed8d94eSDimitry Andric
708aed8d94eSDimitry Andricinline
709aed8d94eSDimitry Andricchar32_t*
710aed8d94eSDimitry Andricchar_traits<char32_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
711aed8d94eSDimitry Andric{
712aed8d94eSDimitry Andric    _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
713aed8d94eSDimitry Andric    char_type* __r = __s1;
714aed8d94eSDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
715aed8d94eSDimitry Andric        assign(*__s1, *__s2);
716aed8d94eSDimitry Andric    return __r;
717aed8d94eSDimitry Andric}
718aed8d94eSDimitry Andric
719aed8d94eSDimitry Andricinline
720aed8d94eSDimitry Andricchar32_t*
721aed8d94eSDimitry Andricchar_traits<char32_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
722aed8d94eSDimitry Andric{
723aed8d94eSDimitry Andric    char_type* __r = __s;
724aed8d94eSDimitry Andric    for (; __n; --__n, ++__s)
725aed8d94eSDimitry Andric        assign(*__s, __a);
726aed8d94eSDimitry Andric    return __r;
727aed8d94eSDimitry Andric}
728aed8d94eSDimitry Andric
729aed8d94eSDimitry Andric#endif  // _LIBCPP_HAS_NO_UNICODE_CHARS
730aed8d94eSDimitry Andric
731aed8d94eSDimitry Andric// helper fns for basic_string and string_view
732aed8d94eSDimitry Andric
733aed8d94eSDimitry Andric// __str_find
734aed8d94eSDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
735aed8d94eSDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
736aed8d94eSDimitry Andric__str_find(const _CharT *__p, _SizeT __sz,
737aed8d94eSDimitry Andric             _CharT __c, _SizeT __pos) _NOEXCEPT
738aed8d94eSDimitry Andric{
739aed8d94eSDimitry Andric    if (__pos >= __sz)
740aed8d94eSDimitry Andric        return __npos;
741aed8d94eSDimitry Andric    const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
742aed8d94eSDimitry Andric    if (__r == 0)
743aed8d94eSDimitry Andric        return __npos;
744aed8d94eSDimitry Andric    return static_cast<_SizeT>(__r - __p);
745aed8d94eSDimitry Andric}
746aed8d94eSDimitry Andric
747aed8d94eSDimitry Andrictemplate <class _CharT, class _Traits>
748aed8d94eSDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX11 const _CharT *
749aed8d94eSDimitry Andric__search_substring(const _CharT *__first1, const _CharT *__last1,
750aed8d94eSDimitry Andric                   const _CharT *__first2, const _CharT *__last2) {
751aed8d94eSDimitry Andric  // Take advantage of knowing source and pattern lengths.
752aed8d94eSDimitry Andric  // Stop short when source is smaller than pattern.
753aed8d94eSDimitry Andric  const ptrdiff_t __len2 = __last2 - __first2;
754aed8d94eSDimitry Andric  if (__len2 == 0)
755aed8d94eSDimitry Andric    return __first1;
756aed8d94eSDimitry Andric
757aed8d94eSDimitry Andric  ptrdiff_t __len1 = __last1 - __first1;
758aed8d94eSDimitry Andric  if (__len1 < __len2)
759aed8d94eSDimitry Andric    return __last1;
760aed8d94eSDimitry Andric
761aed8d94eSDimitry Andric  // First element of __first2 is loop invariant.
762aed8d94eSDimitry Andric  _CharT __f2 = *__first2;
763aed8d94eSDimitry Andric  while (true) {
764aed8d94eSDimitry Andric    __len1 = __last1 - __first1;
765aed8d94eSDimitry Andric    // Check whether __first1 still has at least __len2 bytes.
766aed8d94eSDimitry Andric    if (__len1 < __len2)
767aed8d94eSDimitry Andric      return __last1;
768aed8d94eSDimitry Andric
769aed8d94eSDimitry Andric    // Find __f2 the first byte matching in __first1.
770aed8d94eSDimitry Andric    __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2);
771aed8d94eSDimitry Andric    if (__first1 == 0)
772aed8d94eSDimitry Andric      return __last1;
773aed8d94eSDimitry Andric
774aed8d94eSDimitry Andric    // It is faster to compare from the first byte of __first1 even if we
775aed8d94eSDimitry Andric    // already know that it matches the first byte of __first2: this is because
776aed8d94eSDimitry Andric    // __first2 is most likely aligned, as it is user's "pattern" string, and
777aed8d94eSDimitry Andric    // __first1 + 1 is most likely not aligned, as the match is in the middle of
778aed8d94eSDimitry Andric    // the string.
779aed8d94eSDimitry Andric    if (_Traits::compare(__first1, __first2, __len2) == 0)
780aed8d94eSDimitry Andric      return __first1;
781aed8d94eSDimitry Andric
782aed8d94eSDimitry Andric    ++__first1;
783aed8d94eSDimitry Andric  }
784aed8d94eSDimitry Andric}
785aed8d94eSDimitry Andric
786aed8d94eSDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
787aed8d94eSDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
788aed8d94eSDimitry Andric__str_find(const _CharT *__p, _SizeT __sz,
789aed8d94eSDimitry Andric       const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
790aed8d94eSDimitry Andric{
791aed8d94eSDimitry Andric    if (__pos > __sz)
792aed8d94eSDimitry Andric        return __npos;
793aed8d94eSDimitry Andric
794aed8d94eSDimitry Andric    if (__n == 0) // There is nothing to search, just return __pos.
795aed8d94eSDimitry Andric        return __pos;
796aed8d94eSDimitry Andric
797aed8d94eSDimitry Andric    const _CharT *__r = __search_substring<_CharT, _Traits>(
798aed8d94eSDimitry Andric        __p + __pos, __p + __sz, __s, __s + __n);
799aed8d94eSDimitry Andric
800aed8d94eSDimitry Andric    if (__r == __p + __sz)
801aed8d94eSDimitry Andric        return __npos;
802aed8d94eSDimitry Andric    return static_cast<_SizeT>(__r - __p);
803aed8d94eSDimitry Andric}
804aed8d94eSDimitry Andric
805aed8d94eSDimitry Andric
806aed8d94eSDimitry Andric// __str_rfind
807aed8d94eSDimitry Andric
808aed8d94eSDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
809aed8d94eSDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
810aed8d94eSDimitry Andric__str_rfind(const _CharT *__p, _SizeT __sz,
811aed8d94eSDimitry Andric              _CharT __c, _SizeT __pos) _NOEXCEPT
812aed8d94eSDimitry Andric{
813aed8d94eSDimitry Andric    if (__sz < 1)
814aed8d94eSDimitry Andric        return __npos;
815aed8d94eSDimitry Andric    if (__pos < __sz)
816aed8d94eSDimitry Andric        ++__pos;
817aed8d94eSDimitry Andric    else
818aed8d94eSDimitry Andric        __pos = __sz;
819aed8d94eSDimitry Andric    for (const _CharT* __ps = __p + __pos; __ps != __p;)
820aed8d94eSDimitry Andric    {
821aed8d94eSDimitry Andric        if (_Traits::eq(*--__ps, __c))
822aed8d94eSDimitry Andric            return static_cast<_SizeT>(__ps - __p);
823aed8d94eSDimitry Andric    }
824aed8d94eSDimitry Andric    return __npos;
825aed8d94eSDimitry Andric}
826aed8d94eSDimitry Andric
827aed8d94eSDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
828aed8d94eSDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
829aed8d94eSDimitry Andric__str_rfind(const _CharT *__p, _SizeT __sz,
830aed8d94eSDimitry Andric        const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
831aed8d94eSDimitry Andric{
832aed8d94eSDimitry Andric    __pos = _VSTD::min(__pos, __sz);
833aed8d94eSDimitry Andric    if (__n < __sz - __pos)
834aed8d94eSDimitry Andric        __pos += __n;
835aed8d94eSDimitry Andric    else
836aed8d94eSDimitry Andric        __pos = __sz;
837aed8d94eSDimitry Andric    const _CharT* __r = _VSTD::__find_end(
838aed8d94eSDimitry Andric                  __p, __p + __pos, __s, __s + __n, _Traits::eq,
839aed8d94eSDimitry Andric                        random_access_iterator_tag(), random_access_iterator_tag());
840aed8d94eSDimitry Andric    if (__n > 0 && __r == __p + __pos)
841aed8d94eSDimitry Andric        return __npos;
842aed8d94eSDimitry Andric    return static_cast<_SizeT>(__r - __p);
843aed8d94eSDimitry Andric}
844aed8d94eSDimitry Andric
845aed8d94eSDimitry Andric// __str_find_first_of
846aed8d94eSDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
847aed8d94eSDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
848aed8d94eSDimitry Andric__str_find_first_of(const _CharT *__p, _SizeT __sz,
849aed8d94eSDimitry Andric                const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
850aed8d94eSDimitry Andric{
851aed8d94eSDimitry Andric    if (__pos >= __sz || __n == 0)
852aed8d94eSDimitry Andric        return __npos;
853aed8d94eSDimitry Andric    const _CharT* __r = _VSTD::__find_first_of_ce
854aed8d94eSDimitry Andric        (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq );
855aed8d94eSDimitry Andric    if (__r == __p + __sz)
856aed8d94eSDimitry Andric        return __npos;
857aed8d94eSDimitry Andric    return static_cast<_SizeT>(__r - __p);
858aed8d94eSDimitry Andric}
859aed8d94eSDimitry Andric
860aed8d94eSDimitry Andric
861aed8d94eSDimitry Andric// __str_find_last_of
862aed8d94eSDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
863aed8d94eSDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
864aed8d94eSDimitry Andric__str_find_last_of(const _CharT *__p, _SizeT __sz,
865aed8d94eSDimitry Andric               const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
866aed8d94eSDimitry Andric    {
867aed8d94eSDimitry Andric    if (__n != 0)
868aed8d94eSDimitry Andric    {
869aed8d94eSDimitry Andric        if (__pos < __sz)
870aed8d94eSDimitry Andric            ++__pos;
871aed8d94eSDimitry Andric        else
872aed8d94eSDimitry Andric            __pos = __sz;
873aed8d94eSDimitry Andric        for (const _CharT* __ps = __p + __pos; __ps != __p;)
874aed8d94eSDimitry Andric        {
875aed8d94eSDimitry Andric            const _CharT* __r = _Traits::find(__s, __n, *--__ps);
876aed8d94eSDimitry Andric            if (__r)
877aed8d94eSDimitry Andric                return static_cast<_SizeT>(__ps - __p);
878aed8d94eSDimitry Andric        }
879aed8d94eSDimitry Andric    }
880aed8d94eSDimitry Andric    return __npos;
881aed8d94eSDimitry Andric}
882aed8d94eSDimitry Andric
883aed8d94eSDimitry Andric
884aed8d94eSDimitry Andric// __str_find_first_not_of
885aed8d94eSDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
886aed8d94eSDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
887aed8d94eSDimitry Andric__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
888aed8d94eSDimitry Andric                    const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
889aed8d94eSDimitry Andric{
890aed8d94eSDimitry Andric    if (__pos < __sz)
891aed8d94eSDimitry Andric    {
892aed8d94eSDimitry Andric        const _CharT* __pe = __p + __sz;
893aed8d94eSDimitry Andric        for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
894aed8d94eSDimitry Andric            if (_Traits::find(__s, __n, *__ps) == 0)
895aed8d94eSDimitry Andric                return static_cast<_SizeT>(__ps - __p);
896aed8d94eSDimitry Andric    }
897aed8d94eSDimitry Andric    return __npos;
898aed8d94eSDimitry Andric}
899aed8d94eSDimitry Andric
900aed8d94eSDimitry Andric
901aed8d94eSDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
902aed8d94eSDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
903aed8d94eSDimitry Andric__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
904aed8d94eSDimitry Andric                          _CharT __c, _SizeT __pos) _NOEXCEPT
905aed8d94eSDimitry Andric{
906aed8d94eSDimitry Andric    if (__pos < __sz)
907aed8d94eSDimitry Andric    {
908aed8d94eSDimitry Andric        const _CharT* __pe = __p + __sz;
909aed8d94eSDimitry Andric        for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
910aed8d94eSDimitry Andric            if (!_Traits::eq(*__ps, __c))
911aed8d94eSDimitry Andric                return static_cast<_SizeT>(__ps - __p);
912aed8d94eSDimitry Andric    }
913aed8d94eSDimitry Andric    return __npos;
914aed8d94eSDimitry Andric}
915aed8d94eSDimitry Andric
916aed8d94eSDimitry Andric
917aed8d94eSDimitry Andric// __str_find_last_not_of
918aed8d94eSDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
919aed8d94eSDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
920aed8d94eSDimitry Andric__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
921aed8d94eSDimitry Andric                   const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
922aed8d94eSDimitry Andric{
923aed8d94eSDimitry Andric    if (__pos < __sz)
924aed8d94eSDimitry Andric        ++__pos;
925aed8d94eSDimitry Andric    else
926aed8d94eSDimitry Andric        __pos = __sz;
927aed8d94eSDimitry Andric    for (const _CharT* __ps = __p + __pos; __ps != __p;)
928aed8d94eSDimitry Andric        if (_Traits::find(__s, __n, *--__ps) == 0)
929aed8d94eSDimitry Andric            return static_cast<_SizeT>(__ps - __p);
930aed8d94eSDimitry Andric    return __npos;
931aed8d94eSDimitry Andric}
932aed8d94eSDimitry Andric
933aed8d94eSDimitry Andric
934aed8d94eSDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
935aed8d94eSDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
936aed8d94eSDimitry Andric__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
937aed8d94eSDimitry Andric                         _CharT __c, _SizeT __pos) _NOEXCEPT
938aed8d94eSDimitry Andric{
939aed8d94eSDimitry Andric    if (__pos < __sz)
940aed8d94eSDimitry Andric        ++__pos;
941aed8d94eSDimitry Andric    else
942aed8d94eSDimitry Andric        __pos = __sz;
943aed8d94eSDimitry Andric    for (const _CharT* __ps = __p + __pos; __ps != __p;)
944aed8d94eSDimitry Andric        if (!_Traits::eq(*--__ps, __c))
945aed8d94eSDimitry Andric            return static_cast<_SizeT>(__ps - __p);
946aed8d94eSDimitry Andric    return __npos;
947aed8d94eSDimitry Andric}
948aed8d94eSDimitry Andric
949aed8d94eSDimitry Andrictemplate<class _Ptr>
950aed8d94eSDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
951aed8d94eSDimitry Andricsize_t __do_string_hash(_Ptr __p, _Ptr __e)
952aed8d94eSDimitry Andric{
953aed8d94eSDimitry Andric    typedef typename iterator_traits<_Ptr>::value_type value_type;
954aed8d94eSDimitry Andric    return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type));
955aed8d94eSDimitry Andric}
956aed8d94eSDimitry Andric
957aed8d94eSDimitry Andrictemplate <class _CharT, class _Iter, class _Traits=char_traits<_CharT> >
958aed8d94eSDimitry Andricstruct __quoted_output_proxy
959aed8d94eSDimitry Andric{
960aed8d94eSDimitry Andric    _Iter  __first;
961aed8d94eSDimitry Andric    _Iter  __last;
962aed8d94eSDimitry Andric    _CharT  __delim;
963aed8d94eSDimitry Andric    _CharT  __escape;
964aed8d94eSDimitry Andric
965aed8d94eSDimitry Andric    __quoted_output_proxy(_Iter __f, _Iter __l, _CharT __d, _CharT __e)
966aed8d94eSDimitry Andric    : __first(__f), __last(__l), __delim(__d), __escape(__e) {}
967aed8d94eSDimitry Andric    //  This would be a nice place for a string_ref
968aed8d94eSDimitry Andric};
969aed8d94eSDimitry Andric
970aed8d94eSDimitry Andric_LIBCPP_END_NAMESPACE_STD
971aed8d94eSDimitry Andric
972f9448bf3SDimitry Andric_LIBCPP_POP_MACROS
973f9448bf3SDimitry Andric
974aed8d94eSDimitry Andric#endif  // _LIBCPP___STRING
975