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