10b57cec5SDimitry Andric// -*- C++ -*-
20b57cec5SDimitry Andric//===-------------------------- __string ----------------------------------===//
30b57cec5SDimitry Andric//
40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
70b57cec5SDimitry Andric//
80b57cec5SDimitry Andric//===----------------------------------------------------------------------===//
90b57cec5SDimitry Andric
100b57cec5SDimitry Andric#ifndef _LIBCPP___STRING
110b57cec5SDimitry Andric#define _LIBCPP___STRING
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric#include <__config>
14*5f7ddb14SDimitry Andric#include <__algorithm/copy.h>
15*5f7ddb14SDimitry Andric#include <__algorithm/copy_backward.h>
16*5f7ddb14SDimitry Andric#include <__algorithm/copy_n.h>
17*5f7ddb14SDimitry Andric#include <__algorithm/fill_n.h>
18*5f7ddb14SDimitry Andric#include <__algorithm/find_first_of.h>
19*5f7ddb14SDimitry Andric#include <__algorithm/find_end.h>
20*5f7ddb14SDimitry Andric#include <__algorithm/min.h>
21*5f7ddb14SDimitry Andric#include <__functional/hash.h>     // for __murmur2_or_cityhash
22*5f7ddb14SDimitry Andric#include <__iterator/iterator_traits.h>
23af732203SDimitry Andric#include <cstdio>      // for EOF
24*5f7ddb14SDimitry Andric#include <cstdint>     // for uint_least16_t
25af732203SDimitry Andric#include <cstring>     // for memcpy
26af732203SDimitry Andric#include <cwchar>      // for wmemcpy
27*5f7ddb14SDimitry Andric#include <type_traits> // for __libcpp_is_constant_evaluated
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric#include <__debug>
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
320b57cec5SDimitry Andric#pragma GCC system_header
330b57cec5SDimitry Andric#endif
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric_LIBCPP_PUSH_MACROS
360b57cec5SDimitry Andric#include <__undef_macros>
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
400b57cec5SDimitry Andric
415ffd83dbSDimitry Andric// The the extern template ABI lists are kept outside of <string> to improve the
425ffd83dbSDimitry Andric// readability of that header.
435ffd83dbSDimitry Andric
445ffd83dbSDimitry Andric// The extern template ABI lists are kept outside of <string> to improve the
455ffd83dbSDimitry Andric// readability of that header. We maintain 2 ABI lists:
465ffd83dbSDimitry Andric// - _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST
475ffd83dbSDimitry Andric// - _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST
485ffd83dbSDimitry Andric// As the name implies, the ABI lists define the V1 (Stable) and unstable ABI.
495ffd83dbSDimitry Andric//
505ffd83dbSDimitry Andric// For unstable, we may explicitly remove function that are external in V1,
515ffd83dbSDimitry Andric// and add (new) external functions to better control inlining and compiler
525ffd83dbSDimitry Andric// optimization opportunities.
535ffd83dbSDimitry Andric//
545ffd83dbSDimitry Andric// For stable, the ABI list should rarely change, except for adding new
555ffd83dbSDimitry Andric// functions supporting new c++ version / API changes. Typically entries
565ffd83dbSDimitry Andric// must never be removed from the stable list.
575ffd83dbSDimitry Andric#define _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_Func, _CharType) \
585ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \
595ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \
605ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \
615ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&)) \
625ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*)) \
63af732203SDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, allocator<_CharType> const&)) \
645ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \
655ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \
665ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \
675ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \
685ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \
695ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type)) \
705ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS const _CharType& basic_string<_CharType>::at(size_type) const) \
715ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \
725ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \
735ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \
745ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*, size_type)) \
755ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \
765ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \
775ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \
785ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::copy(value_type*, size_type, size_type) const) \
79af732203SDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, size_type, size_type, allocator<_CharType> const&)) \
805ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \
815ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(size_type, value_type)) \
825ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \
835ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \
845ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \
855ffd83dbSDimitry Andric  _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*)) \
865ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \
875ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \
885ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \
895ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \
905ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \
915ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::erase(size_type, size_type)) \
925ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \
935ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \
945ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \
955ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS _CharType& basic_string<_CharType>::at(size_type)) \
965ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*)) \
975ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \
985ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \
995ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \
1005ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) \
1015ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \
1025ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \
1035ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \
1045ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \
1055ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type))
1065ffd83dbSDimitry Andric
1075ffd83dbSDimitry Andric#define _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_Func, _CharType) \
1085ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \
1095ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \
1105ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \
1115ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*)) \
1125ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \
1135ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \
1145ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \
1155ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \
1165ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \
1175ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type)) \
1185ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init_copy_ctor_external(value_type const*, size_type)) \
1195ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS const _CharType& basic_string<_CharType>::at(size_type) const) \
1205ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*, size_type)) \
1215ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \
1225ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \
1235ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*, size_type)) \
1245ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_external(value_type const*)) \
1255ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::reserve(size_type)) \
1265ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \
1275ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \
1285ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::copy(value_type*, size_type, size_type) const) \
129af732203SDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, size_type, size_type, allocator<_CharType> const&)) \
1305ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type, size_type) const) \
1315ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(size_type, value_type)) \
1325ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, value_type const*)) \
1335ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_of(value_type const*, size_type, size_type) const) \
1345ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__grow_by(size_type, size_type, size_type, size_type, size_type, size_type)) \
1355ffd83dbSDimitry Andric  _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*)) \
1365ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_no_alias<false>(value_type const*, size_type)) \
1375ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::__assign_no_alias<true>(value_type const*, size_type)) \
1385ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::push_back(value_type)) \
1395ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(size_type, value_type)) \
1405ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type, size_type) const) \
1415ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS const basic_string<_CharType>::size_type basic_string<_CharType>::npos) \
1425ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::assign(size_type, value_type)) \
1435ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__erase_external_with_move(size_type, size_type)) \
1445ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(basic_string const&, size_type, size_type)) \
1455ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(value_type const*) const) \
1465ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*) const) \
1475ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS _CharType& basic_string<_CharType>::at(size_type)) \
1485ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \
1495ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \
1505ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \
1515ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \
1525ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \
1535ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \
1545ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \
1555ffd83dbSDimitry Andric  _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type))
1565ffd83dbSDimitry Andric
1575ffd83dbSDimitry Andric
1580b57cec5SDimitry Andric// char_traits
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andrictemplate <class _CharT>
1610b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits
1620b57cec5SDimitry Andric{
1630b57cec5SDimitry Andric    typedef _CharT    char_type;
1640b57cec5SDimitry Andric    typedef int       int_type;
1650b57cec5SDimitry Andric    typedef streamoff off_type;
1660b57cec5SDimitry Andric    typedef streampos pos_type;
1670b57cec5SDimitry Andric    typedef mbstate_t state_type;
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric    static inline void _LIBCPP_CONSTEXPR_AFTER_CXX14
1700b57cec5SDimitry Andric        assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
1710b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
1720b57cec5SDimitry Andric        {return __c1 == __c2;}
1730b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
1740b57cec5SDimitry Andric        {return __c1 < __c2;}
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
1770b57cec5SDimitry Andric    int compare(const char_type* __s1, const char_type* __s2, size_t __n);
1780b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
1790b57cec5SDimitry Andric    size_t length(const char_type* __s);
1800b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
1810b57cec5SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a);
182480093f4SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX17
183480093f4SDimitry Andric    char_type*       move(char_type* __s1, const char_type* __s2, size_t __n);
1840b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
185480093f4SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX17
186480093f4SDimitry Andric    char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n);
1870b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
188480093f4SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX17
189480093f4SDimitry Andric    char_type*       assign(char_type* __s, size_t __n, char_type __a);
1900b57cec5SDimitry Andric
1910b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
1920b57cec5SDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
1930b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
1940b57cec5SDimitry Andric        {return char_type(__c);}
1950b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  to_int_type(char_type __c) _NOEXCEPT
1960b57cec5SDimitry Andric        {return int_type(__c);}
1970b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool      eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
1980b57cec5SDimitry Andric        {return __c1 == __c2;}
1990b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  eof() _NOEXCEPT
2000b57cec5SDimitry Andric        {return int_type(EOF);}
2010b57cec5SDimitry Andric};
2020b57cec5SDimitry Andric
2030b57cec5SDimitry Andrictemplate <class _CharT>
2040b57cec5SDimitry Andric_LIBCPP_CONSTEXPR_AFTER_CXX14 int
2050b57cec5SDimitry Andricchar_traits<_CharT>::compare(const char_type* __s1, const char_type* __s2, size_t __n)
2060b57cec5SDimitry Andric{
2070b57cec5SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
2080b57cec5SDimitry Andric    {
2090b57cec5SDimitry Andric        if (lt(*__s1, *__s2))
2100b57cec5SDimitry Andric            return -1;
2110b57cec5SDimitry Andric        if (lt(*__s2, *__s1))
2120b57cec5SDimitry Andric            return 1;
2130b57cec5SDimitry Andric    }
2140b57cec5SDimitry Andric    return 0;
2150b57cec5SDimitry Andric}
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andrictemplate <class _CharT>
2180b57cec5SDimitry Andricinline
2190b57cec5SDimitry Andric_LIBCPP_CONSTEXPR_AFTER_CXX14 size_t
2200b57cec5SDimitry Andricchar_traits<_CharT>::length(const char_type* __s)
2210b57cec5SDimitry Andric{
2220b57cec5SDimitry Andric    size_t __len = 0;
2230b57cec5SDimitry Andric    for (; !eq(*__s, char_type(0)); ++__s)
2240b57cec5SDimitry Andric        ++__len;
2250b57cec5SDimitry Andric    return __len;
2260b57cec5SDimitry Andric}
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andrictemplate <class _CharT>
2290b57cec5SDimitry Andricinline
2300b57cec5SDimitry Andric_LIBCPP_CONSTEXPR_AFTER_CXX14 const _CharT*
2310b57cec5SDimitry Andricchar_traits<_CharT>::find(const char_type* __s, size_t __n, const char_type& __a)
2320b57cec5SDimitry Andric{
2330b57cec5SDimitry Andric    for (; __n; --__n)
2340b57cec5SDimitry Andric    {
2350b57cec5SDimitry Andric        if (eq(*__s, __a))
2360b57cec5SDimitry Andric            return __s;
2370b57cec5SDimitry Andric        ++__s;
2380b57cec5SDimitry Andric    }
239af732203SDimitry Andric    return nullptr;
2400b57cec5SDimitry Andric}
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andrictemplate <class _CharT>
243480093f4SDimitry Andric_LIBCPP_CONSTEXPR_AFTER_CXX17 _CharT*
2440b57cec5SDimitry Andricchar_traits<_CharT>::move(char_type* __s1, const char_type* __s2, size_t __n)
2450b57cec5SDimitry Andric{
246480093f4SDimitry Andric    if (__n == 0) return __s1;
2470b57cec5SDimitry Andric    char_type* __r = __s1;
2480b57cec5SDimitry Andric    if (__s1 < __s2)
2490b57cec5SDimitry Andric    {
2500b57cec5SDimitry Andric        for (; __n; --__n, ++__s1, ++__s2)
2510b57cec5SDimitry Andric            assign(*__s1, *__s2);
2520b57cec5SDimitry Andric    }
2530b57cec5SDimitry Andric    else if (__s2 < __s1)
2540b57cec5SDimitry Andric    {
2550b57cec5SDimitry Andric        __s1 += __n;
2560b57cec5SDimitry Andric        __s2 += __n;
2570b57cec5SDimitry Andric        for (; __n; --__n)
2580b57cec5SDimitry Andric            assign(*--__s1, *--__s2);
2590b57cec5SDimitry Andric    }
2600b57cec5SDimitry Andric    return __r;
2610b57cec5SDimitry Andric}
2620b57cec5SDimitry Andric
2630b57cec5SDimitry Andrictemplate <class _CharT>
264480093f4SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX17
2650b57cec5SDimitry Andric_CharT*
2660b57cec5SDimitry Andricchar_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n)
2670b57cec5SDimitry Andric{
2680b57cec5SDimitry Andric    _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
2690b57cec5SDimitry Andric    char_type* __r = __s1;
2700b57cec5SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
2710b57cec5SDimitry Andric        assign(*__s1, *__s2);
2720b57cec5SDimitry Andric    return __r;
2730b57cec5SDimitry Andric}
2740b57cec5SDimitry Andric
2750b57cec5SDimitry Andrictemplate <class _CharT>
276480093f4SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX17
2770b57cec5SDimitry Andric_CharT*
2780b57cec5SDimitry Andricchar_traits<_CharT>::assign(char_type* __s, size_t __n, char_type __a)
2790b57cec5SDimitry Andric{
2800b57cec5SDimitry Andric    char_type* __r = __s;
2810b57cec5SDimitry Andric    for (; __n; --__n, ++__s)
2820b57cec5SDimitry Andric        assign(*__s, __a);
2830b57cec5SDimitry Andric    return __r;
2840b57cec5SDimitry Andric}
2850b57cec5SDimitry Andric
286480093f4SDimitry Andric// constexpr versions of move/copy/assign.
287480093f4SDimitry Andric
288480093f4SDimitry Andrictemplate <class _CharT>
289af732203SDimitry Andricstatic inline _LIBCPP_CONSTEXPR_AFTER_CXX17
290480093f4SDimitry Andric_CharT* __move_constexpr(_CharT* __s1, const _CharT* __s2, size_t __n) _NOEXCEPT
291480093f4SDimitry Andric{
292480093f4SDimitry Andric    if (__n == 0) return __s1;
293480093f4SDimitry Andric    if (__s1 < __s2) {
294480093f4SDimitry Andric      _VSTD::copy(__s2, __s2 + __n, __s1);
295480093f4SDimitry Andric    } else if (__s2 < __s1) {
296480093f4SDimitry Andric      _VSTD::copy_backward(__s2, __s2 + __n, __s1 + __n);
297480093f4SDimitry Andric    }
298480093f4SDimitry Andric    return __s1;
299480093f4SDimitry Andric}
300480093f4SDimitry Andric
301480093f4SDimitry Andrictemplate <class _CharT>
302af732203SDimitry Andricstatic inline _LIBCPP_CONSTEXPR_AFTER_CXX17
303480093f4SDimitry Andric_CharT* __copy_constexpr(_CharT* __s1, const _CharT* __s2, size_t __n) _NOEXCEPT
304480093f4SDimitry Andric{
305480093f4SDimitry Andric    _VSTD::copy_n(__s2, __n, __s1);
306480093f4SDimitry Andric    return __s1;
307480093f4SDimitry Andric}
308480093f4SDimitry Andric
309480093f4SDimitry Andrictemplate <class _CharT>
310af732203SDimitry Andricstatic inline _LIBCPP_CONSTEXPR_AFTER_CXX17
311480093f4SDimitry Andric_CharT* __assign_constexpr(_CharT* __s, size_t __n, _CharT __a) _NOEXCEPT
312480093f4SDimitry Andric{
313480093f4SDimitry Andric     _VSTD::fill_n(__s, __n, __a);
314480093f4SDimitry Andric     return __s;
315480093f4SDimitry Andric}
316480093f4SDimitry Andric
3170b57cec5SDimitry Andric// char_traits<char>
3180b57cec5SDimitry Andric
3190b57cec5SDimitry Andrictemplate <>
3200b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits<char>
3210b57cec5SDimitry Andric{
3220b57cec5SDimitry Andric    typedef char      char_type;
3230b57cec5SDimitry Andric    typedef int       int_type;
3240b57cec5SDimitry Andric    typedef streamoff off_type;
3250b57cec5SDimitry Andric    typedef streampos pos_type;
3260b57cec5SDimitry Andric    typedef mbstate_t state_type;
3270b57cec5SDimitry Andric
3280b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
3290b57cec5SDimitry Andric    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
3300b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
3310b57cec5SDimitry Andric            {return __c1 == __c2;}
3320b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
3330b57cec5SDimitry Andric        {return (unsigned char)__c1 < (unsigned char)__c2;}
3340b57cec5SDimitry Andric
3350b57cec5SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
3360b57cec5SDimitry Andric    int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
3370b57cec5SDimitry Andric    static inline size_t _LIBCPP_CONSTEXPR_AFTER_CXX14
3380b57cec5SDimitry Andric    length(const char_type* __s)  _NOEXCEPT {return __builtin_strlen(__s);}
3390b57cec5SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
3400b57cec5SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
341af732203SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
342480093f4SDimitry Andric    char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
343480093f4SDimitry Andric        {
344480093f4SDimitry Andric            return __libcpp_is_constant_evaluated()
345af732203SDimitry Andric                       ? _VSTD::__move_constexpr(__s1, __s2, __n)
346af732203SDimitry Andric                       : __n == 0 ? __s1 : (char_type*)_VSTD::memmove(__s1, __s2, __n);
347480093f4SDimitry Andric        }
348af732203SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
349480093f4SDimitry Andric    char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
3500b57cec5SDimitry Andric        {
3510b57cec5SDimitry Andric            _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
352480093f4SDimitry Andric            return __libcpp_is_constant_evaluated()
353af732203SDimitry Andric                       ? _VSTD::__copy_constexpr(__s1, __s2, __n)
354af732203SDimitry Andric                       : __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
3550b57cec5SDimitry Andric        }
356af732203SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
357480093f4SDimitry Andric    char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
358480093f4SDimitry Andric        {
359480093f4SDimitry Andric            return __libcpp_is_constant_evaluated()
360af732203SDimitry Andric                       ? _VSTD::__assign_constexpr(__s, __n, __a)
361af732203SDimitry Andric                       : __n == 0 ? __s : (char_type*)_VSTD::memset(__s, to_int_type(__a), __n);
362480093f4SDimitry Andric        }
3630b57cec5SDimitry Andric
3640b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
3650b57cec5SDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
3660b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
3670b57cec5SDimitry Andric        {return char_type(__c);}
3680b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
3690b57cec5SDimitry Andric        {return int_type((unsigned char)__c);}
3700b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
3710b57cec5SDimitry Andric        {return __c1 == __c2;}
3720b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  eof() _NOEXCEPT
3730b57cec5SDimitry Andric        {return int_type(EOF);}
3740b57cec5SDimitry Andric};
3750b57cec5SDimitry Andric
3760b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
3770b57cec5SDimitry Andricint
3780b57cec5SDimitry Andricchar_traits<char>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
3790b57cec5SDimitry Andric{
3800b57cec5SDimitry Andric    if (__n == 0)
3810b57cec5SDimitry Andric        return 0;
3820b57cec5SDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
3830b57cec5SDimitry Andric    return __builtin_memcmp(__s1, __s2, __n);
3840b57cec5SDimitry Andric#elif _LIBCPP_STD_VER <= 14
385af732203SDimitry Andric    return _VSTD::memcmp(__s1, __s2, __n);
3860b57cec5SDimitry Andric#else
3870b57cec5SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
3880b57cec5SDimitry Andric    {
3890b57cec5SDimitry Andric        if (lt(*__s1, *__s2))
3900b57cec5SDimitry Andric            return -1;
3910b57cec5SDimitry Andric        if (lt(*__s2, *__s1))
3920b57cec5SDimitry Andric            return 1;
3930b57cec5SDimitry Andric    }
3940b57cec5SDimitry Andric    return 0;
3950b57cec5SDimitry Andric#endif
3960b57cec5SDimitry Andric}
3970b57cec5SDimitry Andric
3980b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
3990b57cec5SDimitry Andricconst char*
4000b57cec5SDimitry Andricchar_traits<char>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
4010b57cec5SDimitry Andric{
4020b57cec5SDimitry Andric    if (__n == 0)
4030b57cec5SDimitry Andric        return nullptr;
4040b57cec5SDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
4050b57cec5SDimitry Andric    return __builtin_char_memchr(__s, to_int_type(__a), __n);
4060b57cec5SDimitry Andric#elif _LIBCPP_STD_VER <= 14
407af732203SDimitry Andric    return (const char_type*) _VSTD::memchr(__s, to_int_type(__a), __n);
4080b57cec5SDimitry Andric#else
4090b57cec5SDimitry Andric    for (; __n; --__n)
4100b57cec5SDimitry Andric    {
4110b57cec5SDimitry Andric        if (eq(*__s, __a))
4120b57cec5SDimitry Andric            return __s;
4130b57cec5SDimitry Andric        ++__s;
4140b57cec5SDimitry Andric    }
4150b57cec5SDimitry Andric    return nullptr;
4160b57cec5SDimitry Andric#endif
4170b57cec5SDimitry Andric}
4180b57cec5SDimitry Andric
4190b57cec5SDimitry Andric
4200b57cec5SDimitry Andric// char_traits<wchar_t>
4210b57cec5SDimitry Andric
4220b57cec5SDimitry Andrictemplate <>
4230b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
4240b57cec5SDimitry Andric{
4250b57cec5SDimitry Andric    typedef wchar_t   char_type;
4260b57cec5SDimitry Andric    typedef wint_t    int_type;
4270b57cec5SDimitry Andric    typedef streamoff off_type;
4280b57cec5SDimitry Andric    typedef streampos pos_type;
4290b57cec5SDimitry Andric    typedef mbstate_t state_type;
4300b57cec5SDimitry Andric
4310b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
4320b57cec5SDimitry Andric    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
4330b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
4340b57cec5SDimitry Andric        {return __c1 == __c2;}
4350b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
4360b57cec5SDimitry Andric        {return __c1 < __c2;}
4370b57cec5SDimitry Andric
4380b57cec5SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
4390b57cec5SDimitry Andric    int compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
4400b57cec5SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
4410b57cec5SDimitry Andric    size_t length(const char_type* __s) _NOEXCEPT;
4420b57cec5SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX14
4430b57cec5SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
444af732203SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
445480093f4SDimitry Andric    char_type* move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
446480093f4SDimitry Andric        {
447480093f4SDimitry Andric            return __libcpp_is_constant_evaluated()
448af732203SDimitry Andric                       ? _VSTD::__move_constexpr(__s1, __s2, __n)
449af732203SDimitry Andric                       : __n == 0 ? __s1 : _VSTD::wmemmove(__s1, __s2, __n);
450480093f4SDimitry Andric        }
451af732203SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
452480093f4SDimitry Andric    char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
4530b57cec5SDimitry Andric        {
4540b57cec5SDimitry Andric            _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
455480093f4SDimitry Andric            return __libcpp_is_constant_evaluated()
456af732203SDimitry Andric                       ? _VSTD::__copy_constexpr(__s1, __s2, __n)
457af732203SDimitry Andric                       : __n == 0 ? __s1 : _VSTD::wmemcpy(__s1, __s2, __n);
4580b57cec5SDimitry Andric        }
459af732203SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
460480093f4SDimitry Andric    char_type* assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
461480093f4SDimitry Andric        {
462480093f4SDimitry Andric            return __libcpp_is_constant_evaluated()
463af732203SDimitry Andric                       ? _VSTD::__assign_constexpr(__s, __n, __a)
464af732203SDimitry Andric                       : __n == 0 ? __s : _VSTD::wmemset(__s, __a, __n);
465480093f4SDimitry Andric        }
4660b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
4670b57cec5SDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
4680b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
4690b57cec5SDimitry Andric        {return char_type(__c);}
4700b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
4710b57cec5SDimitry Andric        {return int_type(__c);}
4720b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
4730b57cec5SDimitry Andric        {return __c1 == __c2;}
4740b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
4750b57cec5SDimitry Andric        {return int_type(WEOF);}
4760b57cec5SDimitry Andric};
4770b57cec5SDimitry Andric
4780b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
4790b57cec5SDimitry Andricint
4800b57cec5SDimitry Andricchar_traits<wchar_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
4810b57cec5SDimitry Andric{
4820b57cec5SDimitry Andric    if (__n == 0)
4830b57cec5SDimitry Andric        return 0;
4840b57cec5SDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
4850b57cec5SDimitry Andric    return __builtin_wmemcmp(__s1, __s2, __n);
4860b57cec5SDimitry Andric#elif _LIBCPP_STD_VER <= 14
487af732203SDimitry Andric    return _VSTD::wmemcmp(__s1, __s2, __n);
4880b57cec5SDimitry Andric#else
4890b57cec5SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
4900b57cec5SDimitry Andric    {
4910b57cec5SDimitry Andric        if (lt(*__s1, *__s2))
4920b57cec5SDimitry Andric            return -1;
4930b57cec5SDimitry Andric        if (lt(*__s2, *__s1))
4940b57cec5SDimitry Andric            return 1;
4950b57cec5SDimitry Andric    }
4960b57cec5SDimitry Andric    return 0;
4970b57cec5SDimitry Andric#endif
4980b57cec5SDimitry Andric}
4990b57cec5SDimitry Andric
500e40139ffSDimitry Andric
501e40139ffSDimitry Andrictemplate <class _Traits>
502e40139ffSDimitry Andric_LIBCPP_INLINE_VISIBILITY
503e40139ffSDimitry Andric_LIBCPP_CONSTEXPR
504e40139ffSDimitry Andricinline size_t __char_traits_length_checked(const typename _Traits::char_type* __s) _NOEXCEPT {
505e40139ffSDimitry Andric#if _LIBCPP_DEBUG_LEVEL >= 1
506e40139ffSDimitry Andric  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);
507e40139ffSDimitry Andric#else
508e40139ffSDimitry Andric  return _Traits::length(__s);
509e40139ffSDimitry Andric#endif
510e40139ffSDimitry Andric}
511e40139ffSDimitry Andric
5120b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
5130b57cec5SDimitry Andricsize_t
5140b57cec5SDimitry Andricchar_traits<wchar_t>::length(const char_type* __s) _NOEXCEPT
5150b57cec5SDimitry Andric{
5160b57cec5SDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
5170b57cec5SDimitry Andric    return __builtin_wcslen(__s);
5180b57cec5SDimitry Andric#elif _LIBCPP_STD_VER <= 14
519af732203SDimitry Andric    return _VSTD::wcslen(__s);
5200b57cec5SDimitry Andric#else
5210b57cec5SDimitry Andric    size_t __len = 0;
5220b57cec5SDimitry Andric    for (; !eq(*__s, char_type(0)); ++__s)
5230b57cec5SDimitry Andric        ++__len;
5240b57cec5SDimitry Andric    return __len;
5250b57cec5SDimitry Andric#endif
5260b57cec5SDimitry Andric}
5270b57cec5SDimitry Andric
5280b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
5290b57cec5SDimitry Andricconst wchar_t*
5300b57cec5SDimitry Andricchar_traits<wchar_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
5310b57cec5SDimitry Andric{
5320b57cec5SDimitry Andric    if (__n == 0)
5330b57cec5SDimitry Andric        return nullptr;
5340b57cec5SDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
5350b57cec5SDimitry Andric    return __builtin_wmemchr(__s, __a, __n);
5360b57cec5SDimitry Andric#elif _LIBCPP_STD_VER <= 14
537af732203SDimitry Andric    return _VSTD::wmemchr(__s, __a, __n);
5380b57cec5SDimitry Andric#else
5390b57cec5SDimitry Andric    for (; __n; --__n)
5400b57cec5SDimitry Andric    {
5410b57cec5SDimitry Andric        if (eq(*__s, __a))
5420b57cec5SDimitry Andric            return __s;
5430b57cec5SDimitry Andric        ++__s;
5440b57cec5SDimitry Andric    }
5450b57cec5SDimitry Andric    return nullptr;
5460b57cec5SDimitry Andric#endif
5470b57cec5SDimitry Andric}
5480b57cec5SDimitry Andric
5490b57cec5SDimitry Andric
550*5f7ddb14SDimitry Andric#ifndef _LIBCPP_HAS_NO_CHAR8_T
5510b57cec5SDimitry Andric
5520b57cec5SDimitry Andrictemplate <>
5530b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
5540b57cec5SDimitry Andric{
5550b57cec5SDimitry Andric    typedef char8_t        char_type;
5560b57cec5SDimitry Andric    typedef unsigned int   int_type;
5570b57cec5SDimitry Andric    typedef streamoff      off_type;
5580b57cec5SDimitry Andric    typedef u8streampos    pos_type;
5590b57cec5SDimitry Andric    typedef mbstate_t      state_type;
5600b57cec5SDimitry Andric
5610b57cec5SDimitry Andric    static inline constexpr void assign(char_type& __c1, const char_type& __c2) noexcept
5620b57cec5SDimitry Andric        {__c1 = __c2;}
5630b57cec5SDimitry Andric    static inline constexpr bool eq(char_type __c1, char_type __c2) noexcept
5640b57cec5SDimitry Andric        {return __c1 == __c2;}
5650b57cec5SDimitry Andric    static inline constexpr bool lt(char_type __c1, char_type __c2) noexcept
5660b57cec5SDimitry Andric        {return __c1 < __c2;}
5670b57cec5SDimitry Andric
5680b57cec5SDimitry Andric    static constexpr
5690b57cec5SDimitry Andric    int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
5700b57cec5SDimitry Andric
5710b57cec5SDimitry Andric    static constexpr
5720b57cec5SDimitry Andric    size_t           length(const char_type* __s) _NOEXCEPT;
5730b57cec5SDimitry Andric
5740b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static constexpr
5750b57cec5SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
5760b57cec5SDimitry Andric
577af732203SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX17
578480093f4SDimitry Andric    char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
5790b57cec5SDimitry Andric        {
580480093f4SDimitry Andric            return __libcpp_is_constant_evaluated()
581af732203SDimitry Andric                       ? _VSTD::__move_constexpr(__s1, __s2, __n)
582af732203SDimitry Andric                       : __n == 0 ? __s1 : (char_type*)_VSTD::memmove(__s1, __s2, __n);
5830b57cec5SDimitry Andric        }
5840b57cec5SDimitry Andric
585af732203SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX17
586480093f4SDimitry Andric    char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
587480093f4SDimitry Andric       {
588480093f4SDimitry Andric            _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
589480093f4SDimitry Andric            return __libcpp_is_constant_evaluated()
590af732203SDimitry Andric                       ? _VSTD::__copy_constexpr(__s1, __s2, __n)
591af732203SDimitry Andric                       : __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
592480093f4SDimitry Andric        }
593480093f4SDimitry Andric
594af732203SDimitry Andric    static _LIBCPP_CONSTEXPR_AFTER_CXX17
595480093f4SDimitry Andric    char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
596480093f4SDimitry Andric        {
597480093f4SDimitry Andric            return __libcpp_is_constant_evaluated()
598af732203SDimitry Andric                       ? _VSTD::__assign_constexpr(__s, __n, __a)
599af732203SDimitry Andric                       : __n == 0 ? __s : (char_type*)_VSTD::memset(__s, to_int_type(__a), __n);
600480093f4SDimitry Andric        }
6010b57cec5SDimitry Andric
6020b57cec5SDimitry Andric    static inline constexpr int_type  not_eof(int_type __c) noexcept
6030b57cec5SDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
6040b57cec5SDimitry Andric    static inline constexpr char_type to_char_type(int_type __c) noexcept
6050b57cec5SDimitry Andric        {return char_type(__c);}
6060b57cec5SDimitry Andric    static inline constexpr int_type to_int_type(char_type __c) noexcept
6070b57cec5SDimitry Andric        {return int_type(__c);}
6080b57cec5SDimitry Andric    static inline constexpr bool eq_int_type(int_type __c1, int_type __c2) noexcept
6090b57cec5SDimitry Andric        {return __c1 == __c2;}
6100b57cec5SDimitry Andric    static inline constexpr int_type eof() noexcept
6110b57cec5SDimitry Andric        {return int_type(EOF);}
6120b57cec5SDimitry Andric};
6130b57cec5SDimitry Andric
6140b57cec5SDimitry Andric// TODO use '__builtin_strlen' if it ever supports char8_t ??
6150b57cec5SDimitry Andricinline constexpr
6160b57cec5SDimitry Andricsize_t
6170b57cec5SDimitry Andricchar_traits<char8_t>::length(const char_type* __s) _NOEXCEPT
6180b57cec5SDimitry Andric{
6190b57cec5SDimitry Andric    size_t __len = 0;
6200b57cec5SDimitry Andric    for (; !eq(*__s, char_type(0)); ++__s)
6210b57cec5SDimitry Andric        ++__len;
6220b57cec5SDimitry Andric    return __len;
6230b57cec5SDimitry Andric}
6240b57cec5SDimitry Andric
6250b57cec5SDimitry Andricinline constexpr
6260b57cec5SDimitry Andricint
6270b57cec5SDimitry Andricchar_traits<char8_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
6280b57cec5SDimitry Andric{
6290b57cec5SDimitry Andric#if __has_feature(cxx_constexpr_string_builtins)
6300b57cec5SDimitry Andric    return __builtin_memcmp(__s1, __s2, __n);
6310b57cec5SDimitry Andric#else
6320b57cec5SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
6330b57cec5SDimitry Andric    {
6340b57cec5SDimitry Andric        if (lt(*__s1, *__s2))
6350b57cec5SDimitry Andric            return -1;
6360b57cec5SDimitry Andric        if (lt(*__s2, *__s1))
6370b57cec5SDimitry Andric            return 1;
6380b57cec5SDimitry Andric    }
6390b57cec5SDimitry Andric    return 0;
6400b57cec5SDimitry Andric#endif
6410b57cec5SDimitry Andric}
6420b57cec5SDimitry Andric
6430b57cec5SDimitry Andric// TODO use '__builtin_char_memchr' if it ever supports char8_t ??
6440b57cec5SDimitry Andricinline constexpr
6450b57cec5SDimitry Andricconst char8_t*
6460b57cec5SDimitry Andricchar_traits<char8_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
6470b57cec5SDimitry Andric{
6480b57cec5SDimitry Andric    for (; __n; --__n)
6490b57cec5SDimitry Andric    {
6500b57cec5SDimitry Andric        if (eq(*__s, __a))
6510b57cec5SDimitry Andric            return __s;
6520b57cec5SDimitry Andric        ++__s;
6530b57cec5SDimitry Andric    }
654af732203SDimitry Andric    return nullptr;
6550b57cec5SDimitry Andric}
6560b57cec5SDimitry Andric
657*5f7ddb14SDimitry Andric#endif // #_LIBCPP_HAS_NO_CHAR8_T
6580b57cec5SDimitry Andric
6590b57cec5SDimitry Andric#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS
6600b57cec5SDimitry Andric
6610b57cec5SDimitry Andrictemplate <>
6620b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
6630b57cec5SDimitry Andric{
6640b57cec5SDimitry Andric    typedef char16_t       char_type;
6650b57cec5SDimitry Andric    typedef uint_least16_t int_type;
6660b57cec5SDimitry Andric    typedef streamoff      off_type;
6670b57cec5SDimitry Andric    typedef u16streampos   pos_type;
6680b57cec5SDimitry Andric    typedef mbstate_t      state_type;
6690b57cec5SDimitry Andric
6700b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
6710b57cec5SDimitry Andric    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
6720b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
6730b57cec5SDimitry Andric        {return __c1 == __c2;}
6740b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
6750b57cec5SDimitry Andric        {return __c1 < __c2;}
6760b57cec5SDimitry Andric
6770b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
6780b57cec5SDimitry Andric    int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
6790b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
6800b57cec5SDimitry Andric    size_t           length(const char_type* __s) _NOEXCEPT;
6810b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
6820b57cec5SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
683480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
6840b57cec5SDimitry Andric    static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
685480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
6860b57cec5SDimitry Andric    static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
687480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
6880b57cec5SDimitry Andric    static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
6890b57cec5SDimitry Andric
6900b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
6910b57cec5SDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
6920b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
6930b57cec5SDimitry Andric        {return char_type(__c);}
6940b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
6950b57cec5SDimitry Andric        {return int_type(__c);}
6960b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
6970b57cec5SDimitry Andric        {return __c1 == __c2;}
6980b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
6990b57cec5SDimitry Andric        {return int_type(0xFFFF);}
7000b57cec5SDimitry Andric};
7010b57cec5SDimitry Andric
7020b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
7030b57cec5SDimitry Andricint
7040b57cec5SDimitry Andricchar_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
7050b57cec5SDimitry Andric{
7060b57cec5SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
7070b57cec5SDimitry Andric    {
7080b57cec5SDimitry Andric        if (lt(*__s1, *__s2))
7090b57cec5SDimitry Andric            return -1;
7100b57cec5SDimitry Andric        if (lt(*__s2, *__s1))
7110b57cec5SDimitry Andric            return 1;
7120b57cec5SDimitry Andric    }
7130b57cec5SDimitry Andric    return 0;
7140b57cec5SDimitry Andric}
7150b57cec5SDimitry Andric
7160b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
7170b57cec5SDimitry Andricsize_t
7180b57cec5SDimitry Andricchar_traits<char16_t>::length(const char_type* __s) _NOEXCEPT
7190b57cec5SDimitry Andric{
7200b57cec5SDimitry Andric    size_t __len = 0;
7210b57cec5SDimitry Andric    for (; !eq(*__s, char_type(0)); ++__s)
7220b57cec5SDimitry Andric        ++__len;
7230b57cec5SDimitry Andric    return __len;
7240b57cec5SDimitry Andric}
7250b57cec5SDimitry Andric
7260b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
7270b57cec5SDimitry Andricconst char16_t*
7280b57cec5SDimitry Andricchar_traits<char16_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
7290b57cec5SDimitry Andric{
7300b57cec5SDimitry Andric    for (; __n; --__n)
7310b57cec5SDimitry Andric    {
7320b57cec5SDimitry Andric        if (eq(*__s, __a))
7330b57cec5SDimitry Andric            return __s;
7340b57cec5SDimitry Andric        ++__s;
7350b57cec5SDimitry Andric    }
736af732203SDimitry Andric    return nullptr;
7370b57cec5SDimitry Andric}
7380b57cec5SDimitry Andric
739480093f4SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX17
7400b57cec5SDimitry Andricchar16_t*
7410b57cec5SDimitry Andricchar_traits<char16_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
7420b57cec5SDimitry Andric{
743480093f4SDimitry Andric    if (__n == 0) return __s1;
7440b57cec5SDimitry Andric    char_type* __r = __s1;
7450b57cec5SDimitry Andric    if (__s1 < __s2)
7460b57cec5SDimitry Andric    {
7470b57cec5SDimitry Andric        for (; __n; --__n, ++__s1, ++__s2)
7480b57cec5SDimitry Andric            assign(*__s1, *__s2);
7490b57cec5SDimitry Andric    }
7500b57cec5SDimitry Andric    else if (__s2 < __s1)
7510b57cec5SDimitry Andric    {
7520b57cec5SDimitry Andric        __s1 += __n;
7530b57cec5SDimitry Andric        __s2 += __n;
7540b57cec5SDimitry Andric        for (; __n; --__n)
7550b57cec5SDimitry Andric            assign(*--__s1, *--__s2);
7560b57cec5SDimitry Andric    }
7570b57cec5SDimitry Andric    return __r;
7580b57cec5SDimitry Andric}
7590b57cec5SDimitry Andric
760480093f4SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX17
7610b57cec5SDimitry Andricchar16_t*
7620b57cec5SDimitry Andricchar_traits<char16_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
7630b57cec5SDimitry Andric{
7640b57cec5SDimitry Andric    _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
7650b57cec5SDimitry Andric    char_type* __r = __s1;
7660b57cec5SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
7670b57cec5SDimitry Andric        assign(*__s1, *__s2);
7680b57cec5SDimitry Andric    return __r;
7690b57cec5SDimitry Andric}
7700b57cec5SDimitry Andric
771480093f4SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX17
7720b57cec5SDimitry Andricchar16_t*
7730b57cec5SDimitry Andricchar_traits<char16_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
7740b57cec5SDimitry Andric{
7750b57cec5SDimitry Andric    char_type* __r = __s;
7760b57cec5SDimitry Andric    for (; __n; --__n, ++__s)
7770b57cec5SDimitry Andric        assign(*__s, __a);
7780b57cec5SDimitry Andric    return __r;
7790b57cec5SDimitry Andric}
7800b57cec5SDimitry Andric
7810b57cec5SDimitry Andrictemplate <>
7820b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
7830b57cec5SDimitry Andric{
7840b57cec5SDimitry Andric    typedef char32_t       char_type;
7850b57cec5SDimitry Andric    typedef uint_least32_t int_type;
7860b57cec5SDimitry Andric    typedef streamoff      off_type;
7870b57cec5SDimitry Andric    typedef u32streampos   pos_type;
7880b57cec5SDimitry Andric    typedef mbstate_t      state_type;
7890b57cec5SDimitry Andric
7900b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR_AFTER_CXX14
7910b57cec5SDimitry Andric    void assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {__c1 = __c2;}
7920b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT
7930b57cec5SDimitry Andric        {return __c1 == __c2;}
7940b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT
7950b57cec5SDimitry Andric        {return __c1 < __c2;}
7960b57cec5SDimitry Andric
7970b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
7980b57cec5SDimitry Andric    int              compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
7990b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
8000b57cec5SDimitry Andric    size_t           length(const char_type* __s) _NOEXCEPT;
8010b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY static _LIBCPP_CONSTEXPR_AFTER_CXX14
8020b57cec5SDimitry Andric    const char_type* find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT;
803480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
8040b57cec5SDimitry Andric    static char_type*       move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
805480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
8060b57cec5SDimitry Andric    static char_type*       copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
807480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
8080b57cec5SDimitry Andric    static char_type*       assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT;
8090b57cec5SDimitry Andric
8100b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type  not_eof(int_type __c) _NOEXCEPT
8110b57cec5SDimitry Andric        {return eq_int_type(__c, eof()) ? ~eof() : __c;}
8120b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT
8130b57cec5SDimitry Andric        {return char_type(__c);}
8140b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT
8150b57cec5SDimitry Andric        {return int_type(__c);}
8160b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT
8170b57cec5SDimitry Andric        {return __c1 == __c2;}
8180b57cec5SDimitry Andric    static inline _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT
8190b57cec5SDimitry Andric        {return int_type(0xFFFFFFFF);}
8200b57cec5SDimitry Andric};
8210b57cec5SDimitry Andric
8220b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
8230b57cec5SDimitry Andricint
8240b57cec5SDimitry Andricchar_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
8250b57cec5SDimitry Andric{
8260b57cec5SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
8270b57cec5SDimitry Andric    {
8280b57cec5SDimitry Andric        if (lt(*__s1, *__s2))
8290b57cec5SDimitry Andric            return -1;
8300b57cec5SDimitry Andric        if (lt(*__s2, *__s1))
8310b57cec5SDimitry Andric            return 1;
8320b57cec5SDimitry Andric    }
8330b57cec5SDimitry Andric    return 0;
8340b57cec5SDimitry Andric}
8350b57cec5SDimitry Andric
8360b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
8370b57cec5SDimitry Andricsize_t
8380b57cec5SDimitry Andricchar_traits<char32_t>::length(const char_type* __s) _NOEXCEPT
8390b57cec5SDimitry Andric{
8400b57cec5SDimitry Andric    size_t __len = 0;
8410b57cec5SDimitry Andric    for (; !eq(*__s, char_type(0)); ++__s)
8420b57cec5SDimitry Andric        ++__len;
8430b57cec5SDimitry Andric    return __len;
8440b57cec5SDimitry Andric}
8450b57cec5SDimitry Andric
8460b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX14
8470b57cec5SDimitry Andricconst char32_t*
8480b57cec5SDimitry Andricchar_traits<char32_t>::find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT
8490b57cec5SDimitry Andric{
8500b57cec5SDimitry Andric    for (; __n; --__n)
8510b57cec5SDimitry Andric    {
8520b57cec5SDimitry Andric        if (eq(*__s, __a))
8530b57cec5SDimitry Andric            return __s;
8540b57cec5SDimitry Andric        ++__s;
8550b57cec5SDimitry Andric    }
856af732203SDimitry Andric    return nullptr;
8570b57cec5SDimitry Andric}
8580b57cec5SDimitry Andric
859480093f4SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX17
8600b57cec5SDimitry Andricchar32_t*
8610b57cec5SDimitry Andricchar_traits<char32_t>::move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
8620b57cec5SDimitry Andric{
863480093f4SDimitry Andric    if (__n == 0) return __s1;
8640b57cec5SDimitry Andric    char_type* __r = __s1;
8650b57cec5SDimitry Andric    if (__s1 < __s2)
8660b57cec5SDimitry Andric    {
8670b57cec5SDimitry Andric        for (; __n; --__n, ++__s1, ++__s2)
8680b57cec5SDimitry Andric            assign(*__s1, *__s2);
8690b57cec5SDimitry Andric    }
8700b57cec5SDimitry Andric    else if (__s2 < __s1)
8710b57cec5SDimitry Andric    {
8720b57cec5SDimitry Andric        __s1 += __n;
8730b57cec5SDimitry Andric        __s2 += __n;
8740b57cec5SDimitry Andric        for (; __n; --__n)
8750b57cec5SDimitry Andric            assign(*--__s1, *--__s2);
8760b57cec5SDimitry Andric    }
8770b57cec5SDimitry Andric    return __r;
8780b57cec5SDimitry Andric}
8790b57cec5SDimitry Andric
880480093f4SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX17
8810b57cec5SDimitry Andricchar32_t*
8820b57cec5SDimitry Andricchar_traits<char32_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
8830b57cec5SDimitry Andric{
8840b57cec5SDimitry Andric    _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
8850b57cec5SDimitry Andric    char_type* __r = __s1;
8860b57cec5SDimitry Andric    for (; __n; --__n, ++__s1, ++__s2)
8870b57cec5SDimitry Andric        assign(*__s1, *__s2);
8880b57cec5SDimitry Andric    return __r;
8890b57cec5SDimitry Andric}
8900b57cec5SDimitry Andric
891480093f4SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX17
8920b57cec5SDimitry Andricchar32_t*
8930b57cec5SDimitry Andricchar_traits<char32_t>::assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT
8940b57cec5SDimitry Andric{
8950b57cec5SDimitry Andric    char_type* __r = __s;
8960b57cec5SDimitry Andric    for (; __n; --__n, ++__s)
8970b57cec5SDimitry Andric        assign(*__s, __a);
8980b57cec5SDimitry Andric    return __r;
8990b57cec5SDimitry Andric}
9000b57cec5SDimitry Andric
9010b57cec5SDimitry Andric#endif // _LIBCPP_HAS_NO_UNICODE_CHARS
9020b57cec5SDimitry Andric
9030b57cec5SDimitry Andric// helper fns for basic_string and string_view
9040b57cec5SDimitry Andric
9050b57cec5SDimitry Andric// __str_find
9060b57cec5SDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
9070b57cec5SDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
9080b57cec5SDimitry Andric__str_find(const _CharT *__p, _SizeT __sz,
9090b57cec5SDimitry Andric             _CharT __c, _SizeT __pos) _NOEXCEPT
9100b57cec5SDimitry Andric{
9110b57cec5SDimitry Andric    if (__pos >= __sz)
9120b57cec5SDimitry Andric        return __npos;
9130b57cec5SDimitry Andric    const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
914af732203SDimitry Andric    if (__r == nullptr)
9150b57cec5SDimitry Andric        return __npos;
9160b57cec5SDimitry Andric    return static_cast<_SizeT>(__r - __p);
9170b57cec5SDimitry Andric}
9180b57cec5SDimitry Andric
9190b57cec5SDimitry Andrictemplate <class _CharT, class _Traits>
9200b57cec5SDimitry Andricinline _LIBCPP_CONSTEXPR_AFTER_CXX11 const _CharT *
9210b57cec5SDimitry Andric__search_substring(const _CharT *__first1, const _CharT *__last1,
922*5f7ddb14SDimitry Andric                   const _CharT *__first2, const _CharT *__last2) _NOEXCEPT {
9230b57cec5SDimitry Andric  // Take advantage of knowing source and pattern lengths.
9240b57cec5SDimitry Andric  // Stop short when source is smaller than pattern.
9250b57cec5SDimitry Andric  const ptrdiff_t __len2 = __last2 - __first2;
9260b57cec5SDimitry Andric  if (__len2 == 0)
9270b57cec5SDimitry Andric    return __first1;
9280b57cec5SDimitry Andric
9290b57cec5SDimitry Andric  ptrdiff_t __len1 = __last1 - __first1;
9300b57cec5SDimitry Andric  if (__len1 < __len2)
9310b57cec5SDimitry Andric    return __last1;
9320b57cec5SDimitry Andric
9330b57cec5SDimitry Andric  // First element of __first2 is loop invariant.
9340b57cec5SDimitry Andric  _CharT __f2 = *__first2;
9350b57cec5SDimitry Andric  while (true) {
9360b57cec5SDimitry Andric    __len1 = __last1 - __first1;
9370b57cec5SDimitry Andric    // Check whether __first1 still has at least __len2 bytes.
9380b57cec5SDimitry Andric    if (__len1 < __len2)
9390b57cec5SDimitry Andric      return __last1;
9400b57cec5SDimitry Andric
9410b57cec5SDimitry Andric    // Find __f2 the first byte matching in __first1.
9420b57cec5SDimitry Andric    __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2);
943af732203SDimitry Andric    if (__first1 == nullptr)
9440b57cec5SDimitry Andric      return __last1;
9450b57cec5SDimitry Andric
9460b57cec5SDimitry Andric    // It is faster to compare from the first byte of __first1 even if we
9470b57cec5SDimitry Andric    // already know that it matches the first byte of __first2: this is because
9480b57cec5SDimitry Andric    // __first2 is most likely aligned, as it is user's "pattern" string, and
9490b57cec5SDimitry Andric    // __first1 + 1 is most likely not aligned, as the match is in the middle of
9500b57cec5SDimitry Andric    // the string.
9510b57cec5SDimitry Andric    if (_Traits::compare(__first1, __first2, __len2) == 0)
9520b57cec5SDimitry Andric      return __first1;
9530b57cec5SDimitry Andric
9540b57cec5SDimitry Andric    ++__first1;
9550b57cec5SDimitry Andric  }
9560b57cec5SDimitry Andric}
9570b57cec5SDimitry Andric
9580b57cec5SDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
9590b57cec5SDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
9600b57cec5SDimitry Andric__str_find(const _CharT *__p, _SizeT __sz,
9610b57cec5SDimitry Andric       const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
9620b57cec5SDimitry Andric{
9630b57cec5SDimitry Andric    if (__pos > __sz)
9640b57cec5SDimitry Andric        return __npos;
9650b57cec5SDimitry Andric
9660b57cec5SDimitry Andric    if (__n == 0) // There is nothing to search, just return __pos.
9670b57cec5SDimitry Andric        return __pos;
9680b57cec5SDimitry Andric
9690b57cec5SDimitry Andric    const _CharT *__r = __search_substring<_CharT, _Traits>(
9700b57cec5SDimitry Andric        __p + __pos, __p + __sz, __s, __s + __n);
9710b57cec5SDimitry Andric
9720b57cec5SDimitry Andric    if (__r == __p + __sz)
9730b57cec5SDimitry Andric        return __npos;
9740b57cec5SDimitry Andric    return static_cast<_SizeT>(__r - __p);
9750b57cec5SDimitry Andric}
9760b57cec5SDimitry Andric
9770b57cec5SDimitry Andric
9780b57cec5SDimitry Andric// __str_rfind
9790b57cec5SDimitry Andric
9800b57cec5SDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
9810b57cec5SDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
9820b57cec5SDimitry Andric__str_rfind(const _CharT *__p, _SizeT __sz,
9830b57cec5SDimitry Andric              _CharT __c, _SizeT __pos) _NOEXCEPT
9840b57cec5SDimitry Andric{
9850b57cec5SDimitry Andric    if (__sz < 1)
9860b57cec5SDimitry Andric        return __npos;
9870b57cec5SDimitry Andric    if (__pos < __sz)
9880b57cec5SDimitry Andric        ++__pos;
9890b57cec5SDimitry Andric    else
9900b57cec5SDimitry Andric        __pos = __sz;
9910b57cec5SDimitry Andric    for (const _CharT* __ps = __p + __pos; __ps != __p;)
9920b57cec5SDimitry Andric    {
9930b57cec5SDimitry Andric        if (_Traits::eq(*--__ps, __c))
9940b57cec5SDimitry Andric            return static_cast<_SizeT>(__ps - __p);
9950b57cec5SDimitry Andric    }
9960b57cec5SDimitry Andric    return __npos;
9970b57cec5SDimitry Andric}
9980b57cec5SDimitry Andric
9990b57cec5SDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
10000b57cec5SDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
10010b57cec5SDimitry Andric__str_rfind(const _CharT *__p, _SizeT __sz,
10020b57cec5SDimitry Andric        const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
10030b57cec5SDimitry Andric{
10040b57cec5SDimitry Andric    __pos = _VSTD::min(__pos, __sz);
10050b57cec5SDimitry Andric    if (__n < __sz - __pos)
10060b57cec5SDimitry Andric        __pos += __n;
10070b57cec5SDimitry Andric    else
10080b57cec5SDimitry Andric        __pos = __sz;
10090b57cec5SDimitry Andric    const _CharT* __r = _VSTD::__find_end(
10100b57cec5SDimitry Andric                  __p, __p + __pos, __s, __s + __n, _Traits::eq,
10110b57cec5SDimitry Andric                        random_access_iterator_tag(), random_access_iterator_tag());
10120b57cec5SDimitry Andric    if (__n > 0 && __r == __p + __pos)
10130b57cec5SDimitry Andric        return __npos;
10140b57cec5SDimitry Andric    return static_cast<_SizeT>(__r - __p);
10150b57cec5SDimitry Andric}
10160b57cec5SDimitry Andric
10170b57cec5SDimitry Andric// __str_find_first_of
10180b57cec5SDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
10190b57cec5SDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
10200b57cec5SDimitry Andric__str_find_first_of(const _CharT *__p, _SizeT __sz,
10210b57cec5SDimitry Andric                const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
10220b57cec5SDimitry Andric{
10230b57cec5SDimitry Andric    if (__pos >= __sz || __n == 0)
10240b57cec5SDimitry Andric        return __npos;
10250b57cec5SDimitry Andric    const _CharT* __r = _VSTD::__find_first_of_ce
10260b57cec5SDimitry Andric        (__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq );
10270b57cec5SDimitry Andric    if (__r == __p + __sz)
10280b57cec5SDimitry Andric        return __npos;
10290b57cec5SDimitry Andric    return static_cast<_SizeT>(__r - __p);
10300b57cec5SDimitry Andric}
10310b57cec5SDimitry Andric
10320b57cec5SDimitry Andric
10330b57cec5SDimitry Andric// __str_find_last_of
10340b57cec5SDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
10350b57cec5SDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
10360b57cec5SDimitry Andric__str_find_last_of(const _CharT *__p, _SizeT __sz,
10370b57cec5SDimitry Andric               const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
10380b57cec5SDimitry Andric    {
10390b57cec5SDimitry Andric    if (__n != 0)
10400b57cec5SDimitry Andric    {
10410b57cec5SDimitry Andric        if (__pos < __sz)
10420b57cec5SDimitry Andric            ++__pos;
10430b57cec5SDimitry Andric        else
10440b57cec5SDimitry Andric            __pos = __sz;
10450b57cec5SDimitry Andric        for (const _CharT* __ps = __p + __pos; __ps != __p;)
10460b57cec5SDimitry Andric        {
10470b57cec5SDimitry Andric            const _CharT* __r = _Traits::find(__s, __n, *--__ps);
10480b57cec5SDimitry Andric            if (__r)
10490b57cec5SDimitry Andric                return static_cast<_SizeT>(__ps - __p);
10500b57cec5SDimitry Andric        }
10510b57cec5SDimitry Andric    }
10520b57cec5SDimitry Andric    return __npos;
10530b57cec5SDimitry Andric}
10540b57cec5SDimitry Andric
10550b57cec5SDimitry Andric
10560b57cec5SDimitry Andric// __str_find_first_not_of
10570b57cec5SDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
10580b57cec5SDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
10590b57cec5SDimitry Andric__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
10600b57cec5SDimitry Andric                    const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
10610b57cec5SDimitry Andric{
10620b57cec5SDimitry Andric    if (__pos < __sz)
10630b57cec5SDimitry Andric    {
10640b57cec5SDimitry Andric        const _CharT* __pe = __p + __sz;
10650b57cec5SDimitry Andric        for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
1066af732203SDimitry Andric            if (_Traits::find(__s, __n, *__ps) == nullptr)
10670b57cec5SDimitry Andric                return static_cast<_SizeT>(__ps - __p);
10680b57cec5SDimitry Andric    }
10690b57cec5SDimitry Andric    return __npos;
10700b57cec5SDimitry Andric}
10710b57cec5SDimitry Andric
10720b57cec5SDimitry Andric
10730b57cec5SDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
10740b57cec5SDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
10750b57cec5SDimitry Andric__str_find_first_not_of(const _CharT *__p, _SizeT __sz,
10760b57cec5SDimitry Andric                          _CharT __c, _SizeT __pos) _NOEXCEPT
10770b57cec5SDimitry Andric{
10780b57cec5SDimitry Andric    if (__pos < __sz)
10790b57cec5SDimitry Andric    {
10800b57cec5SDimitry Andric        const _CharT* __pe = __p + __sz;
10810b57cec5SDimitry Andric        for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
10820b57cec5SDimitry Andric            if (!_Traits::eq(*__ps, __c))
10830b57cec5SDimitry Andric                return static_cast<_SizeT>(__ps - __p);
10840b57cec5SDimitry Andric    }
10850b57cec5SDimitry Andric    return __npos;
10860b57cec5SDimitry Andric}
10870b57cec5SDimitry Andric
10880b57cec5SDimitry Andric
10890b57cec5SDimitry Andric// __str_find_last_not_of
10900b57cec5SDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
10910b57cec5SDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
10920b57cec5SDimitry Andric__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
10930b57cec5SDimitry Andric                   const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT
10940b57cec5SDimitry Andric{
10950b57cec5SDimitry Andric    if (__pos < __sz)
10960b57cec5SDimitry Andric        ++__pos;
10970b57cec5SDimitry Andric    else
10980b57cec5SDimitry Andric        __pos = __sz;
10990b57cec5SDimitry Andric    for (const _CharT* __ps = __p + __pos; __ps != __p;)
1100af732203SDimitry Andric        if (_Traits::find(__s, __n, *--__ps) == nullptr)
11010b57cec5SDimitry Andric            return static_cast<_SizeT>(__ps - __p);
11020b57cec5SDimitry Andric    return __npos;
11030b57cec5SDimitry Andric}
11040b57cec5SDimitry Andric
11050b57cec5SDimitry Andric
11060b57cec5SDimitry Andrictemplate<class _CharT, class _SizeT, class _Traits, _SizeT __npos>
11070b57cec5SDimitry Andricinline _SizeT _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
11080b57cec5SDimitry Andric__str_find_last_not_of(const _CharT *__p, _SizeT __sz,
11090b57cec5SDimitry Andric                         _CharT __c, _SizeT __pos) _NOEXCEPT
11100b57cec5SDimitry Andric{
11110b57cec5SDimitry Andric    if (__pos < __sz)
11120b57cec5SDimitry Andric        ++__pos;
11130b57cec5SDimitry Andric    else
11140b57cec5SDimitry Andric        __pos = __sz;
11150b57cec5SDimitry Andric    for (const _CharT* __ps = __p + __pos; __ps != __p;)
11160b57cec5SDimitry Andric        if (!_Traits::eq(*--__ps, __c))
11170b57cec5SDimitry Andric            return static_cast<_SizeT>(__ps - __p);
11180b57cec5SDimitry Andric    return __npos;
11190b57cec5SDimitry Andric}
11200b57cec5SDimitry Andric
11210b57cec5SDimitry Andrictemplate<class _Ptr>
11220b57cec5SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
11230b57cec5SDimitry Andricsize_t __do_string_hash(_Ptr __p, _Ptr __e)
11240b57cec5SDimitry Andric{
11250b57cec5SDimitry Andric    typedef typename iterator_traits<_Ptr>::value_type value_type;
11260b57cec5SDimitry Andric    return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type));
11270b57cec5SDimitry Andric}
11280b57cec5SDimitry Andric
11290b57cec5SDimitry Andrictemplate <class _CharT, class _Iter, class _Traits=char_traits<_CharT> >
11300b57cec5SDimitry Andricstruct __quoted_output_proxy
11310b57cec5SDimitry Andric{
11320b57cec5SDimitry Andric    _Iter  __first;
11330b57cec5SDimitry Andric    _Iter  __last;
11340b57cec5SDimitry Andric    _CharT  __delim;
11350b57cec5SDimitry Andric    _CharT  __escape;
11360b57cec5SDimitry Andric
11370b57cec5SDimitry Andric    __quoted_output_proxy(_Iter __f, _Iter __l, _CharT __d, _CharT __e)
11380b57cec5SDimitry Andric    : __first(__f), __last(__l), __delim(__d), __escape(__e) {}
11390b57cec5SDimitry Andric    //  This would be a nice place for a string_ref
11400b57cec5SDimitry Andric};
11410b57cec5SDimitry Andric
11420b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
11430b57cec5SDimitry Andric
11440b57cec5SDimitry Andric_LIBCPP_POP_MACROS
11450b57cec5SDimitry Andric
11460b57cec5SDimitry Andric#endif // _LIBCPP___STRING
1147