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 | |