Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:14:04

0001 //===----------------------------------------------------------------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef _LIBCPP___STRING_CHAR_TRAITS_H
0010 #define _LIBCPP___STRING_CHAR_TRAITS_H
0011 
0012 #include <__algorithm/fill_n.h>
0013 #include <__algorithm/find.h>
0014 #include <__algorithm/find_end.h>
0015 #include <__algorithm/find_first_of.h>
0016 #include <__algorithm/min.h>
0017 #include <__assert>
0018 #include <__compare/ordering.h>
0019 #include <__config>
0020 #include <__cstddef/ptrdiff_t.h>
0021 #include <__functional/hash.h>
0022 #include <__functional/identity.h>
0023 #include <__iterator/iterator_traits.h>
0024 #include <__std_mbstate_t.h>
0025 #include <__string/constexpr_c_functions.h>
0026 #include <__type_traits/is_constant_evaluated.h>
0027 #include <__utility/is_pointer_in_range.h>
0028 #include <cstdint>
0029 #include <cstdio>
0030 #include <iosfwd>
0031 
0032 #if _LIBCPP_HAS_WIDE_CHARACTERS
0033 #  include <cwchar> // for wmemcpy
0034 #endif
0035 
0036 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0037 #  pragma GCC system_header
0038 #endif
0039 
0040 _LIBCPP_PUSH_MACROS
0041 #include <__undef_macros>
0042 
0043 _LIBCPP_BEGIN_NAMESPACE_STD
0044 
0045 template <class _CharT>
0046 struct char_traits;
0047 /*
0048 The Standard does not define the base template for char_traits because it is impossible to provide
0049 a correct definition for arbitrary character types. Instead, it requires implementations to provide
0050 specializations for predefined character types like `char`, `wchar_t` and others. We provide this as
0051 exposition-only to document what members a char_traits specialization should provide:
0052 {
0053     using char_type  = _CharT;
0054     using int_type   = ...;
0055     using off_type   = ...;
0056     using pos_type   = ...;
0057     using state_type = ...;
0058 
0059     static void assign(char_type&, const char_type&);
0060     static bool eq(char_type, char_type);
0061     static bool lt(char_type, char_type);
0062 
0063     static int              compare(const char_type*, const char_type*, size_t);
0064     static size_t           length(const char_type*);
0065     static const char_type* find(const char_type*, size_t, const char_type&);
0066     static char_type*       move(char_type*, const char_type*, size_t);
0067     static char_type*       copy(char_type*, const char_type*, size_t);
0068     static char_type*       assign(char_type*, size_t, char_type);
0069 
0070     static int_type  not_eof(int_type);
0071     static char_type to_char_type(int_type);
0072     static int_type  to_int_type(char_type);
0073     static bool      eq_int_type(int_type, int_type);
0074     static int_type  eof();
0075 };
0076 */
0077 
0078 // char_traits<char>
0079 
0080 template <>
0081 struct _LIBCPP_TEMPLATE_VIS char_traits<char> {
0082   using char_type  = char;
0083   using int_type   = int;
0084   using off_type   = streamoff;
0085   using pos_type   = streampos;
0086   using state_type = mbstate_t;
0087 #if _LIBCPP_STD_VER >= 20
0088   using comparison_category = strong_ordering;
0089 #endif
0090 
0091   static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 void
0092   assign(char_type& __c1, const char_type& __c2) _NOEXCEPT {
0093     __c1 = __c2;
0094   }
0095 
0096   // TODO: Make this _LIBCPP_HIDE_FROM_ABI
0097   static inline _LIBCPP_HIDDEN _LIBCPP_CONSTEXPR bool eq(char_type __c1, char_type __c2) _NOEXCEPT {
0098     return __c1 == __c2;
0099   }
0100   static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool lt(char_type __c1, char_type __c2) _NOEXCEPT {
0101     return (unsigned char)__c1 < (unsigned char)__c2;
0102   }
0103 
0104   // __constexpr_memcmp requires a trivially lexicographically comparable type, but char is not when char is a signed
0105   // type
0106   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
0107   compare(const char_type* __lhs, const char_type* __rhs, size_t __count) _NOEXCEPT {
0108     if (__libcpp_is_constant_evaluated()) {
0109 #ifdef _LIBCPP_COMPILER_CLANG_BASED
0110       return __builtin_memcmp(__lhs, __rhs, __count);
0111 #else
0112       while (__count != 0) {
0113         if (lt(*__lhs, *__rhs))
0114           return -1;
0115         if (lt(*__rhs, *__lhs))
0116           return 1;
0117 
0118         __count -= sizeof(char_type);
0119         ++__lhs;
0120         ++__rhs;
0121       }
0122       return 0;
0123 #endif // _LIBCPP_COMPILER_CLANG_BASED
0124     } else {
0125       return __builtin_memcmp(__lhs, __rhs, __count);
0126     }
0127   }
0128 
0129   static inline _LIBCPP_HIDE_FROM_ABI size_t _LIBCPP_CONSTEXPR_SINCE_CXX17 length(const char_type* __s) _NOEXCEPT {
0130     return std::__constexpr_strlen(__s);
0131   }
0132 
0133   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
0134   find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
0135     if (__n == 0)
0136       return nullptr;
0137     return std::__constexpr_memchr(__s, __a, __n);
0138   }
0139 
0140   static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
0141   move(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
0142     return std::__constexpr_memmove(__s1, __s2, __element_count(__n));
0143   }
0144 
0145   static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
0146   copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
0147     _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2),
0148                                           "char_traits::copy: source and destination ranges overlap");
0149     std::__constexpr_memmove(__s1, __s2, __element_count(__n));
0150     return __s1;
0151   }
0152 
0153   static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
0154   assign(char_type* __s, size_t __n, char_type __a) _NOEXCEPT {
0155     std::fill_n(__s, __n, __a);
0156     return __s;
0157   }
0158 
0159   static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
0160     return eq_int_type(__c, eof()) ? ~eof() : __c;
0161   }
0162   static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
0163     return char_type(__c);
0164   }
0165   static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT {
0166     return int_type((unsigned char)__c);
0167   }
0168   static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool eq_int_type(int_type __c1, int_type __c2) _NOEXCEPT {
0169     return __c1 == __c2;
0170   }
0171   static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return int_type(EOF); }
0172 };
0173 
0174 template <class _CharT, class _IntT, _IntT _EOFVal>
0175 struct __char_traits_base {
0176   using char_type  = _CharT;
0177   using int_type   = _IntT;
0178   using off_type   = streamoff;
0179   using state_type = mbstate_t;
0180 #if _LIBCPP_STD_VER >= 20
0181   using comparison_category = strong_ordering;
0182 #endif
0183 
0184   // There are different aliases for the different char types, but they are all aliases to this type
0185   using pos_type = fpos<mbstate_t>;
0186 
0187   _LIBCPP_HIDE_FROM_ABI static inline _LIBCPP_CONSTEXPR_SINCE_CXX17 void
0188   assign(char_type& __lhs, const char_type& __rhs) _NOEXCEPT {
0189     __lhs = __rhs;
0190   }
0191 
0192   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool eq(char_type __lhs, char_type __rhs) _NOEXCEPT {
0193     return __lhs == __rhs;
0194   }
0195 
0196   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool lt(char_type __lhs, char_type __rhs) _NOEXCEPT {
0197     return __lhs < __rhs;
0198   }
0199 
0200   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
0201   move(char_type* __dest, const char_type* __src, size_t __n) _NOEXCEPT {
0202     return std::__constexpr_memmove(__dest, __src, __element_count(__n));
0203   }
0204 
0205   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
0206   copy(char_type* __dest, const char_type* __src, size_t __n) _NOEXCEPT {
0207     _LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__dest, __dest + __n, __src),
0208                                           "char_traits::copy: source and destination ranges overlap");
0209     return std::__constexpr_memmove(__dest, __src, __element_count(__n));
0210   }
0211 
0212   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 char_type*
0213   assign(char_type* __str, size_t __n, char_type __fill_char) _NOEXCEPT {
0214     std::fill_n(__str, __n, __fill_char);
0215     return __str;
0216   }
0217 
0218   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR char_type to_char_type(int_type __c) _NOEXCEPT {
0219     return char_type(__c);
0220   }
0221 
0222   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type to_int_type(char_type __c) _NOEXCEPT { return int_type(__c); }
0223 
0224   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR bool eq_int_type(int_type __lhs, int_type __rhs) _NOEXCEPT {
0225     return __lhs == __rhs;
0226   }
0227 
0228   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type eof() _NOEXCEPT { return _EOFVal; }
0229 
0230   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int_type not_eof(int_type __c) _NOEXCEPT {
0231     return eq_int_type(__c, eof()) ? static_cast<int_type>(~eof()) : __c;
0232   }
0233 };
0234 
0235 // char_traits<wchar_t>
0236 
0237 #if _LIBCPP_HAS_WIDE_CHARACTERS
0238 template <>
0239 struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t> : __char_traits_base<wchar_t, wint_t, static_cast<wint_t>(WEOF)> {
0240   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 int
0241   compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
0242     if (__n == 0)
0243       return 0;
0244     return std::__constexpr_wmemcmp(__s1, __s2, __n);
0245   }
0246 
0247   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT {
0248     return std::__constexpr_wcslen(__s);
0249   }
0250 
0251   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
0252   find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
0253     if (__n == 0)
0254       return nullptr;
0255     return std::__constexpr_wmemchr(__s, __a, __n);
0256   }
0257 };
0258 #endif // _LIBCPP_HAS_WIDE_CHARACTERS
0259 
0260 #if _LIBCPP_HAS_CHAR8_T
0261 
0262 template <>
0263 struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
0264     : __char_traits_base<char8_t, unsigned int, static_cast<unsigned int>(EOF)> {
0265   static _LIBCPP_HIDE_FROM_ABI constexpr int
0266   compare(const char_type* __s1, const char_type* __s2, size_t __n) noexcept {
0267     return std::__constexpr_memcmp(__s1, __s2, __element_count(__n));
0268   }
0269 
0270   static _LIBCPP_HIDE_FROM_ABI constexpr size_t length(const char_type* __str) noexcept {
0271     return std::__constexpr_strlen(__str);
0272   }
0273 
0274   _LIBCPP_HIDE_FROM_ABI static constexpr const char_type*
0275   find(const char_type* __s, size_t __n, const char_type& __a) noexcept {
0276     return std::__constexpr_memchr(__s, __a, __n);
0277   }
0278 };
0279 
0280 #endif // _LIBCPP_HAS_CHAR8_T
0281 
0282 template <>
0283 struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
0284     : __char_traits_base<char16_t, uint_least16_t, static_cast<uint_least16_t>(0xFFFF)> {
0285   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
0286   compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
0287   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT;
0288 
0289   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
0290   find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
0291     __identity __proj;
0292     const char_type* __match = std::__find(__s, __s + __n, __a, __proj);
0293     if (__match == __s + __n)
0294       return nullptr;
0295     return __match;
0296   }
0297 };
0298 
0299 inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
0300 char_traits<char16_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
0301   for (; __n; --__n, ++__s1, ++__s2) {
0302     if (lt(*__s1, *__s2))
0303       return -1;
0304     if (lt(*__s2, *__s1))
0305       return 1;
0306   }
0307   return 0;
0308 }
0309 
0310 inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits<char16_t>::length(const char_type* __s) _NOEXCEPT {
0311   size_t __len = 0;
0312   for (; !eq(*__s, char_type(0)); ++__s)
0313     ++__len;
0314   return __len;
0315 }
0316 
0317 template <>
0318 struct _LIBCPP_TEMPLATE_VIS char_traits<char32_t>
0319     : __char_traits_base<char32_t, uint_least32_t, static_cast<uint_least32_t>(0xFFFFFFFF)> {
0320   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 int
0321   compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT;
0322   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t length(const char_type* __s) _NOEXCEPT;
0323 
0324   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX17 const char_type*
0325   find(const char_type* __s, size_t __n, const char_type& __a) _NOEXCEPT {
0326     __identity __proj;
0327     const char_type* __match = std::__find(__s, __s + __n, __a, __proj);
0328     if (__match == __s + __n)
0329       return nullptr;
0330     return __match;
0331   }
0332 };
0333 
0334 inline _LIBCPP_CONSTEXPR_SINCE_CXX17 int
0335 char_traits<char32_t>::compare(const char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
0336   for (; __n; --__n, ++__s1, ++__s2) {
0337     if (lt(*__s1, *__s2))
0338       return -1;
0339     if (lt(*__s2, *__s1))
0340       return 1;
0341   }
0342   return 0;
0343 }
0344 
0345 inline _LIBCPP_CONSTEXPR_SINCE_CXX17 size_t char_traits<char32_t>::length(const char_type* __s) _NOEXCEPT {
0346   size_t __len = 0;
0347   for (; !eq(*__s, char_type(0)); ++__s)
0348     ++__len;
0349   return __len;
0350 }
0351 
0352 // helper fns for basic_string and string_view
0353 
0354 // __str_find
0355 template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
0356 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
0357 __str_find(const _CharT* __p, _SizeT __sz, _CharT __c, _SizeT __pos) _NOEXCEPT {
0358   if (__pos >= __sz)
0359     return __npos;
0360   const _CharT* __r = _Traits::find(__p + __pos, __sz - __pos, __c);
0361   if (__r == nullptr)
0362     return __npos;
0363   return static_cast<_SizeT>(__r - __p);
0364 }
0365 
0366 template <class _CharT, class _Traits>
0367 _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 const _CharT* __search_substring(
0368     const _CharT* __first1, const _CharT* __last1, const _CharT* __first2, const _CharT* __last2) _NOEXCEPT {
0369   // Take advantage of knowing source and pattern lengths.
0370   // Stop short when source is smaller than pattern.
0371   const ptrdiff_t __len2 = __last2 - __first2;
0372   if (__len2 == 0)
0373     return __first1;
0374 
0375   ptrdiff_t __len1 = __last1 - __first1;
0376   if (__len1 < __len2)
0377     return __last1;
0378 
0379   // First element of __first2 is loop invariant.
0380   _CharT __f2 = *__first2;
0381   while (true) {
0382     __len1 = __last1 - __first1;
0383     // Check whether __first1 still has at least __len2 bytes.
0384     if (__len1 < __len2)
0385       return __last1;
0386 
0387     // Find __f2 the first byte matching in __first1.
0388     __first1 = _Traits::find(__first1, __len1 - __len2 + 1, __f2);
0389     if (__first1 == nullptr)
0390       return __last1;
0391 
0392     // It is faster to compare from the first byte of __first1 even if we
0393     // already know that it matches the first byte of __first2: this is because
0394     // __first2 is most likely aligned, as it is user's "pattern" string, and
0395     // __first1 + 1 is most likely not aligned, as the match is in the middle of
0396     // the string.
0397     if (_Traits::compare(__first1, __first2, __len2) == 0)
0398       return __first1;
0399 
0400     ++__first1;
0401   }
0402 }
0403 
0404 template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
0405 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
0406 __str_find(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT {
0407   if (__pos > __sz)
0408     return __npos;
0409 
0410   if (__n == 0) // There is nothing to search, just return __pos.
0411     return __pos;
0412 
0413   const _CharT* __r = std::__search_substring<_CharT, _Traits>(__p + __pos, __p + __sz, __s, __s + __n);
0414 
0415   if (__r == __p + __sz)
0416     return __npos;
0417   return static_cast<_SizeT>(__r - __p);
0418 }
0419 
0420 // __str_rfind
0421 
0422 template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
0423 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
0424 __str_rfind(const _CharT* __p, _SizeT __sz, _CharT __c, _SizeT __pos) _NOEXCEPT {
0425   if (__sz < 1)
0426     return __npos;
0427   if (__pos < __sz)
0428     ++__pos;
0429   else
0430     __pos = __sz;
0431   for (const _CharT* __ps = __p + __pos; __ps != __p;) {
0432     if (_Traits::eq(*--__ps, __c))
0433       return static_cast<_SizeT>(__ps - __p);
0434   }
0435   return __npos;
0436 }
0437 
0438 template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
0439 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
0440 __str_rfind(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT {
0441   __pos = std::min(__pos, __sz);
0442   if (__n < __sz - __pos)
0443     __pos += __n;
0444   else
0445     __pos = __sz;
0446   const _CharT* __r = std::__find_end_classic(__p, __p + __pos, __s, __s + __n, _Traits::eq);
0447   if (__n > 0 && __r == __p + __pos)
0448     return __npos;
0449   return static_cast<_SizeT>(__r - __p);
0450 }
0451 
0452 // __str_find_first_of
0453 template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
0454 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
0455 __str_find_first_of(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT {
0456   if (__pos >= __sz || __n == 0)
0457     return __npos;
0458   const _CharT* __r = std::__find_first_of_ce(__p + __pos, __p + __sz, __s, __s + __n, _Traits::eq);
0459   if (__r == __p + __sz)
0460     return __npos;
0461   return static_cast<_SizeT>(__r - __p);
0462 }
0463 
0464 // __str_find_last_of
0465 template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
0466 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
0467 __str_find_last_of(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT {
0468   if (__n != 0) {
0469     if (__pos < __sz)
0470       ++__pos;
0471     else
0472       __pos = __sz;
0473     for (const _CharT* __ps = __p + __pos; __ps != __p;) {
0474       const _CharT* __r = _Traits::find(__s, __n, *--__ps);
0475       if (__r)
0476         return static_cast<_SizeT>(__ps - __p);
0477     }
0478   }
0479   return __npos;
0480 }
0481 
0482 // __str_find_first_not_of
0483 template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
0484 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
0485 __str_find_first_not_of(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT {
0486   if (__pos < __sz) {
0487     const _CharT* __pe = __p + __sz;
0488     for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
0489       if (_Traits::find(__s, __n, *__ps) == nullptr)
0490         return static_cast<_SizeT>(__ps - __p);
0491   }
0492   return __npos;
0493 }
0494 
0495 template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
0496 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
0497 __str_find_first_not_of(const _CharT* __p, _SizeT __sz, _CharT __c, _SizeT __pos) _NOEXCEPT {
0498   if (__pos < __sz) {
0499     const _CharT* __pe = __p + __sz;
0500     for (const _CharT* __ps = __p + __pos; __ps != __pe; ++__ps)
0501       if (!_Traits::eq(*__ps, __c))
0502         return static_cast<_SizeT>(__ps - __p);
0503   }
0504   return __npos;
0505 }
0506 
0507 // __str_find_last_not_of
0508 template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
0509 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
0510 __str_find_last_not_of(const _CharT* __p, _SizeT __sz, const _CharT* __s, _SizeT __pos, _SizeT __n) _NOEXCEPT {
0511   if (__pos < __sz)
0512     ++__pos;
0513   else
0514     __pos = __sz;
0515   for (const _CharT* __ps = __p + __pos; __ps != __p;)
0516     if (_Traits::find(__s, __n, *--__ps) == nullptr)
0517       return static_cast<_SizeT>(__ps - __p);
0518   return __npos;
0519 }
0520 
0521 template <class _CharT, class _SizeT, class _Traits, _SizeT __npos>
0522 inline _SizeT _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
0523 __str_find_last_not_of(const _CharT* __p, _SizeT __sz, _CharT __c, _SizeT __pos) _NOEXCEPT {
0524   if (__pos < __sz)
0525     ++__pos;
0526   else
0527     __pos = __sz;
0528   for (const _CharT* __ps = __p + __pos; __ps != __p;)
0529     if (!_Traits::eq(*--__ps, __c))
0530       return static_cast<_SizeT>(__ps - __p);
0531   return __npos;
0532 }
0533 
0534 template <class _Ptr>
0535 inline _LIBCPP_HIDE_FROM_ABI size_t __do_string_hash(_Ptr __p, _Ptr __e) {
0536   typedef typename iterator_traits<_Ptr>::value_type value_type;
0537   return __murmur2_or_cityhash<size_t>()(__p, (__e - __p) * sizeof(value_type));
0538 }
0539 
0540 _LIBCPP_END_NAMESPACE_STD
0541 
0542 _LIBCPP_POP_MACROS
0543 
0544 #endif // _LIBCPP___STRING_CHAR_TRAITS_H