1 // Copyright 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_STRINGS_CHAR_TRAITS_H_ 6 #define BASE_STRINGS_CHAR_TRAITS_H_ 7 8 #include <stddef.h> 9 10 #include "base/compiler_specific.h" 11 12 namespace base { 13 14 // constexpr version of http://en.cppreference.com/w/cpp/string/char_traits. 15 // This currently just implements the bits needed to support a (mostly) 16 // constexpr StringPiece. 17 // 18 // TODO(dcheng): Once we switch to C++17, most methods will become constexpr and 19 // we can switch over to using the one in the standard library. 20 template <typename T> 21 struct CharTraits { 22 // Performs a lexographical comparison of the first N characters of |s1| and 23 // |s2|. Returns 0 if equal, -1 if |s1| is less than |s2|, and 1 if |s1| is 24 // greater than |s2|. 25 static constexpr int compare(const T* s1, const T* s2, size_t n) noexcept; 26 27 // Returns the length of |s|, assuming null termination (and not including the 28 // terminating null). 29 static constexpr size_t length(const T* s) noexcept; 30 }; 31 32 template <typename T> 33 constexpr int CharTraits<T>::compare(const T* s1, 34 const T* s2, 35 size_t n) noexcept { 36 for (; n; --n, ++s1, ++s2) { 37 if (*s1 < *s2) 38 return -1; 39 if (*s1 > *s2) 40 return 1; 41 } 42 return 0; 43 } 44 45 template <typename T> 46 constexpr size_t CharTraits<T>::length(const T* s) noexcept { 47 size_t i = 0; 48 for (; *s; ++s) 49 ++i; 50 return i; 51 } 52 53 // char specialization of CharTraits that can use clang's constexpr instrinsics, 54 // where available. 55 template <> 56 struct CharTraits<char> { 57 static constexpr int compare(const char* s1, 58 const char* s2, 59 size_t n) noexcept; 60 static constexpr size_t length(const char* s) noexcept; 61 }; 62 63 constexpr int CharTraits<char>::compare(const char* s1, 64 const char* s2, 65 size_t n) noexcept { 66 #if HAS_FEATURE(cxx_constexpr_string_builtins) 67 return __builtin_memcmp(s1, s2, n); 68 #else 69 for (; n; --n, ++s1, ++s2) { 70 if (*s1 < *s2) 71 return -1; 72 if (*s1 > *s2) 73 return 1; 74 } 75 return 0; 76 #endif 77 } 78 79 constexpr size_t CharTraits<char>::length(const char* s) noexcept { 80 #if defined(__clang__) 81 return __builtin_strlen(s); 82 #else 83 size_t i = 0; 84 for (; *s; ++s) 85 ++i; 86 return i; 87 #endif 88 } 89 90 } // namespace base 91 92 #endif // BASE_STRINGS_CHAR_TRAITS_H_ 93