xref: /aosp_15_r20/external/cronet/base/strings/cstring_view.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2024 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_STRINGS_CSTRING_VIEW_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_STRINGS_CSTRING_VIEW_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <algorithm>
9*6777b538SAndroid Build Coastguard Worker #include <concepts>
10*6777b538SAndroid Build Coastguard Worker #include <cstddef>
11*6777b538SAndroid Build Coastguard Worker #include <iosfwd>
12*6777b538SAndroid Build Coastguard Worker #include <string>
13*6777b538SAndroid Build Coastguard Worker #include <string_view>
14*6777b538SAndroid Build Coastguard Worker 
15*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/containers/checked_iterators.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr_exclusion.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
20*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
21*6777b538SAndroid Build Coastguard Worker 
22*6777b538SAndroid Build Coastguard Worker namespace base {
23*6777b538SAndroid Build Coastguard Worker 
24*6777b538SAndroid Build Coastguard Worker // A CString is a NUL-terminated character array, which is the C programming
25*6777b538SAndroid Build Coastguard Worker // language representation of a string. This class (and its aliases below)
26*6777b538SAndroid Build Coastguard Worker // provides a non-owning and bounds-safe view of a CString, and can replace all
27*6777b538SAndroid Build Coastguard Worker // use of native pointers (such as `const char*`) for this purpose in C++ code.
28*6777b538SAndroid Build Coastguard Worker //
29*6777b538SAndroid Build Coastguard Worker // The basic_cstring_view class is followed by aliases for the various char
30*6777b538SAndroid Build Coastguard Worker // types:
31*6777b538SAndroid Build Coastguard Worker // * cstring_view provides a view of a `const char*`.
32*6777b538SAndroid Build Coastguard Worker // * u16cstring_view provides a view of a `const char16_t*`.
33*6777b538SAndroid Build Coastguard Worker // * u32cstring_view provides a view of a `const char32_t*`.
34*6777b538SAndroid Build Coastguard Worker // * wcstring_view provides a view of a `const wchar_t*`.
35*6777b538SAndroid Build Coastguard Worker template <class Char>
36*6777b538SAndroid Build Coastguard Worker class basic_cstring_view final {
37*6777b538SAndroid Build Coastguard Worker   static_assert(!std::is_const_v<Char>);
38*6777b538SAndroid Build Coastguard Worker   static_assert(!std::is_reference_v<Char>);
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker  public:
41*6777b538SAndroid Build Coastguard Worker   using value_type = Char;
42*6777b538SAndroid Build Coastguard Worker   using pointer = Char*;
43*6777b538SAndroid Build Coastguard Worker   using const_pointer = const Char*;
44*6777b538SAndroid Build Coastguard Worker   using reference = Char&;
45*6777b538SAndroid Build Coastguard Worker   using const_reference = const Char&;
46*6777b538SAndroid Build Coastguard Worker   using iterator = CheckedContiguousIterator<const Char>;
47*6777b538SAndroid Build Coastguard Worker   using const_iterator = CheckedContiguousIterator<const Char>;
48*6777b538SAndroid Build Coastguard Worker   using reverse_iterator = std::reverse_iterator<iterator>;
49*6777b538SAndroid Build Coastguard Worker   using const_reverse_iterator = std::reverse_iterator<iterator>;
50*6777b538SAndroid Build Coastguard Worker   using size_type = size_t;
51*6777b538SAndroid Build Coastguard Worker   using difference_type = ptrdiff_t;
52*6777b538SAndroid Build Coastguard Worker 
53*6777b538SAndroid Build Coastguard Worker   // The `npos` constant represents a non-existent position in the cstring view.
54*6777b538SAndroid Build Coastguard Worker   constexpr static auto npos = static_cast<size_t>(-1);
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker   // Constructs an empty cstring view, which points to an empty string with a
57*6777b538SAndroid Build Coastguard Worker   // terminating NUL.
basic_cstring_view()58*6777b538SAndroid Build Coastguard Worker   constexpr basic_cstring_view() noexcept : ptr_(kEmpty), len_(0u) {}
59*6777b538SAndroid Build Coastguard Worker 
60*6777b538SAndroid Build Coastguard Worker   // cstring views are trivially copyable, moveable, and destructible.
61*6777b538SAndroid Build Coastguard Worker 
62*6777b538SAndroid Build Coastguard Worker   // Constructs a cstring view that points at the contents of a string literal.
63*6777b538SAndroid Build Coastguard Worker   //
64*6777b538SAndroid Build Coastguard Worker   // Example:
65*6777b538SAndroid Build Coastguard Worker   // ```
66*6777b538SAndroid Build Coastguard Worker   // const char kLiteral[] = "hello world";
67*6777b538SAndroid Build Coastguard Worker   // auto s = base::cstring_view(kLiteral);
68*6777b538SAndroid Build Coastguard Worker   // CHECK(s == "hello world");
69*6777b538SAndroid Build Coastguard Worker   // auto s2 = base::cstring_view("this works too");
70*6777b538SAndroid Build Coastguard Worker   // CHECK(s == "this works too");
71*6777b538SAndroid Build Coastguard Worker   // ```
72*6777b538SAndroid Build Coastguard Worker   template <int&..., size_t M>
73*6777b538SAndroid Build Coastguard Worker   // NOLINTNEXTLINE(google-explicit-constructor)
basic_cstring_view(const Char (& lit LIFETIME_BOUND)[M])74*6777b538SAndroid Build Coastguard Worker   constexpr basic_cstring_view(const Char (&lit LIFETIME_BOUND)[M]) noexcept
75*6777b538SAndroid Build Coastguard Worker       ENABLE_IF_ATTR(lit[M - 1u] == Char{0}, "requires string literal as input")
76*6777b538SAndroid Build Coastguard Worker       : ptr_(lit), len_(M - 1u) {
77*6777b538SAndroid Build Coastguard Worker     // For non-clang compilers. On clang, the function is not even callable
78*6777b538SAndroid Build Coastguard Worker     // without this being known to pass at compile time.
79*6777b538SAndroid Build Coastguard Worker     //
80*6777b538SAndroid Build Coastguard Worker     // SAFETY: lit is an array of size M, so M-1 is in bounds.
81*6777b538SAndroid Build Coastguard Worker     DCHECK_EQ(UNSAFE_BUFFERS(lit[M - 1u]), Char{0});
82*6777b538SAndroid Build Coastguard Worker   }
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker   // Constructs a cstring view from a std::string (or other std::basic_string
85*6777b538SAndroid Build Coastguard Worker   // type). The string parameter must outlive the cstring view, including that
86*6777b538SAndroid Build Coastguard Worker   // it must not be moved-from or destroyed.
87*6777b538SAndroid Build Coastguard Worker   //
88*6777b538SAndroid Build Coastguard Worker   // This conversion is implicit, which matches the conversion from std::string
89*6777b538SAndroid Build Coastguard Worker   // to std::string_view (through string's `operator string_view()`).
90*6777b538SAndroid Build Coastguard Worker   //
91*6777b538SAndroid Build Coastguard Worker   // # Interaction with SSO
92*6777b538SAndroid Build Coastguard Worker   // std::string stores its contents inline when they fit (which is an
93*6777b538SAndroid Build Coastguard Worker   // implementation defined length), instead of in a heap-allocated buffer. This
94*6777b538SAndroid Build Coastguard Worker   // is referred to as the Small String Optimization. This means that moving or
95*6777b538SAndroid Build Coastguard Worker   // destring a std::string will invalidate a cstring view and leave it with
96*6777b538SAndroid Build Coastguard Worker   // dangling pointers. This differs from the behaviour of std::vector and span,
97*6777b538SAndroid Build Coastguard Worker   // since pointers into a std::vector remain valid after moving the std::vector
98*6777b538SAndroid Build Coastguard Worker   // and destroying the original.
99*6777b538SAndroid Build Coastguard Worker   //
100*6777b538SAndroid Build Coastguard Worker   // # Preventing implicit temporaries
101*6777b538SAndroid Build Coastguard Worker   // Because std::string can be implicitly constructed, the string constructor
102*6777b538SAndroid Build Coastguard Worker   // may unintentionally be called with a temporary `std::string` when called
103*6777b538SAndroid Build Coastguard Worker   // with values that convert to `std::string`. We prevent this templating this
104*6777b538SAndroid Build Coastguard Worker   // constructor and requiring the incoming type to actually be a `std::string`
105*6777b538SAndroid Build Coastguard Worker   // (or other `std::basic_string`). This also improves compiler errors,
106*6777b538SAndroid Build Coastguard Worker   // compared to deleting a string&& overload, when passed an array that does
107*6777b538SAndroid Build Coastguard Worker   // not match the `ENABLE_IF_ATTR` constructor condition by not sending it to a
108*6777b538SAndroid Build Coastguard Worker   // deleted overload receiving `std::string`.
109*6777b538SAndroid Build Coastguard Worker   template <std::same_as<std::basic_string<Char>> String>
110*6777b538SAndroid Build Coastguard Worker   // NOLINTNEXTLINE(google-explicit-constructor)
basic_cstring_view(const String & s LIFETIME_BOUND)111*6777b538SAndroid Build Coastguard Worker   constexpr basic_cstring_view(const String& s LIFETIME_BOUND) noexcept
112*6777b538SAndroid Build Coastguard Worker       : ptr_(s.c_str()), len_(s.size()) {}
113*6777b538SAndroid Build Coastguard Worker 
114*6777b538SAndroid Build Coastguard Worker   // Unsafe construction from a pointer and length. Prefer to construct cstring
115*6777b538SAndroid Build Coastguard Worker   // view from a string literal, std::string, or another cstring view.
116*6777b538SAndroid Build Coastguard Worker   //
117*6777b538SAndroid Build Coastguard Worker   // # Safety
118*6777b538SAndroid Build Coastguard Worker   // The `ptr` and `len` pair indicate a valid NUL-terminated string:
119*6777b538SAndroid Build Coastguard Worker   // * The `ptr` must not be null, and must point to a NUL-terminated string.
120*6777b538SAndroid Build Coastguard Worker   // * The `len` must be valid such that `ptr + len` gives a pointer to the
121*6777b538SAndroid Build Coastguard Worker   //   terminating NUL and is in the same allocation as `ptr`.
basic_cstring_view(const Char * ptr LIFETIME_BOUND,size_t len)122*6777b538SAndroid Build Coastguard Worker   UNSAFE_BUFFER_USAGE explicit constexpr basic_cstring_view(const Char* ptr
123*6777b538SAndroid Build Coastguard Worker                                                                 LIFETIME_BOUND,
124*6777b538SAndroid Build Coastguard Worker                                                             size_t len)
125*6777b538SAndroid Build Coastguard Worker       : ptr_(ptr), len_(len) {
126*6777b538SAndroid Build Coastguard Worker     // This method is marked UNSAFE_BUFFER_USAGE so we are trusting the caller
127*6777b538SAndroid Build Coastguard Worker     // to do things right, and expecting strong scrutiny at the call site, but
128*6777b538SAndroid Build Coastguard Worker     // we perform a debug check to help catch mistakes regardless.
129*6777b538SAndroid Build Coastguard Worker     //
130*6777b538SAndroid Build Coastguard Worker     // SAFETY: `ptr` points to `len` many chars and then a NUL, according to the
131*6777b538SAndroid Build Coastguard Worker     // caller of this method. So then `len` index will be in bounds and return
132*6777b538SAndroid Build Coastguard Worker     // the NUL.
133*6777b538SAndroid Build Coastguard Worker     DCHECK_EQ(UNSAFE_BUFFERS(ptr[len]), Char{0});
134*6777b538SAndroid Build Coastguard Worker   }
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to the NUL-terminated string, for passing to C-style APIs
137*6777b538SAndroid Build Coastguard Worker   // that require `const char*` (or whatever the `Char` type is).
138*6777b538SAndroid Build Coastguard Worker   //
139*6777b538SAndroid Build Coastguard Worker   // This is never null.
c_str()140*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const Char* c_str() const noexcept { return ptr_; }
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker   // Returns a pointer to underlying buffer. To get a string pointer, use
143*6777b538SAndroid Build Coastguard Worker   // `c_str()`.
144*6777b538SAndroid Build Coastguard Worker   //
145*6777b538SAndroid Build Coastguard Worker   // Pair with `size()` to construct a bounded non-NUL-terminated view, such as
146*6777b538SAndroid Build Coastguard Worker   // by `base::span`. This is never null.
data()147*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const Char* data() const noexcept { return ptr_; }
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker   // Returns the number of characters in the string, not including the
150*6777b538SAndroid Build Coastguard Worker   // terminating NUL.
size()151*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr size_t size() const noexcept { return len_; }
152*6777b538SAndroid Build Coastguard Worker   // An alias for `size()`, returning the number of characters in the string.
length()153*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr size_t length() const noexcept { return len_; }
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker   // Returns whether the cstring view is for an empty string. When empty, it is
156*6777b538SAndroid Build Coastguard Worker   // pointing to a cstring that contains only a NUL character.
empty()157*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr bool empty() const noexcept { return len_ == 0u; }
158*6777b538SAndroid Build Coastguard Worker 
159*6777b538SAndroid Build Coastguard Worker   // Returns the maximum number of characters that can be represented inside the
160*6777b538SAndroid Build Coastguard Worker   // cstring view for character type `Char`.
161*6777b538SAndroid Build Coastguard Worker   //
162*6777b538SAndroid Build Coastguard Worker   // This is the number of `Char` objects that can fit inside an addressable
163*6777b538SAndroid Build Coastguard Worker   // byte array. Since the number of bytes allowed is fixed, the number returned
164*6777b538SAndroid Build Coastguard Worker   // is smaller when the `Char` is a larger type.
max_size()165*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr size_t max_size() const noexcept {
166*6777b538SAndroid Build Coastguard Worker     return static_cast<size_t>(-1) / sizeof(Char);
167*6777b538SAndroid Build Coastguard Worker   }
168*6777b538SAndroid Build Coastguard Worker 
169*6777b538SAndroid Build Coastguard Worker   // Returns the number of bytes in the string, not including the terminating
170*6777b538SAndroid Build Coastguard Worker   // NUL. To include the NUL, add `sizeof(Char)` where `Char` is the character
171*6777b538SAndroid Build Coastguard Worker   // type of the cstring view (accessible as the `value_type` alias).
size_bytes()172*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr size_t size_bytes() const noexcept {
173*6777b538SAndroid Build Coastguard Worker     return len_ * sizeof(Char);
174*6777b538SAndroid Build Coastguard Worker   }
175*6777b538SAndroid Build Coastguard Worker 
176*6777b538SAndroid Build Coastguard Worker   // Produces an iterator over the cstring view, excluding the terminating NUL.
begin()177*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const iterator begin() const noexcept {
178*6777b538SAndroid Build Coastguard Worker     // SAFETY: `ptr_ + len_` for a cstring view always gives a pointer in
179*6777b538SAndroid Build Coastguard Worker     // the same allocation as `ptr_` based on the precondition of
180*6777b538SAndroid Build Coastguard Worker     // the type.
181*6777b538SAndroid Build Coastguard Worker     return UNSAFE_BUFFERS(iterator(ptr_, ptr_ + len_));
182*6777b538SAndroid Build Coastguard Worker   }
183*6777b538SAndroid Build Coastguard Worker   // Produces an iterator over the cstring view, excluding the terminating NUL.
end()184*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const iterator end() const noexcept {
185*6777b538SAndroid Build Coastguard Worker     // SAFETY: `ptr_ + len_` for a cstring view always gives a pointer in
186*6777b538SAndroid Build Coastguard Worker     // the same allocation as `ptr_` based on the precondition of
187*6777b538SAndroid Build Coastguard Worker     // the type.
188*6777b538SAndroid Build Coastguard Worker     return UNSAFE_BUFFERS(iterator(ptr_, ptr_ + len_, ptr_ + len_));
189*6777b538SAndroid Build Coastguard Worker   }
190*6777b538SAndroid Build Coastguard Worker   // Produces an iterator over the cstring view, excluding the terminating NUL.
cbegin()191*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const const_iterator cbegin() const noexcept {
192*6777b538SAndroid Build Coastguard Worker     return begin();
193*6777b538SAndroid Build Coastguard Worker   }
194*6777b538SAndroid Build Coastguard Worker   // Produces an iterator over the cstring view, excluding the terminating NUL.
cend()195*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const const_iterator cend() const noexcept {
196*6777b538SAndroid Build Coastguard Worker     return end();
197*6777b538SAndroid Build Coastguard Worker   }
198*6777b538SAndroid Build Coastguard Worker 
199*6777b538SAndroid Build Coastguard Worker   // Produces a reverse iterator over the cstring view, excluding the
200*6777b538SAndroid Build Coastguard Worker   // terminating NUL.
rbegin()201*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const reverse_iterator rbegin() const noexcept {
202*6777b538SAndroid Build Coastguard Worker     return std::reverse_iterator(end());
203*6777b538SAndroid Build Coastguard Worker   }
204*6777b538SAndroid Build Coastguard Worker   // Produces a reverse iterator over the cstring view, excluding the
205*6777b538SAndroid Build Coastguard Worker   // terminating NUL.
rend()206*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const reverse_iterator rend() const noexcept {
207*6777b538SAndroid Build Coastguard Worker     return std::reverse_iterator(begin());
208*6777b538SAndroid Build Coastguard Worker   }
209*6777b538SAndroid Build Coastguard Worker   // Produces a reverse iterator over the cstring view, excluding the
210*6777b538SAndroid Build Coastguard Worker   // terminating NUL.
rcbegin()211*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const const_reverse_iterator rcbegin()
212*6777b538SAndroid Build Coastguard Worker       const noexcept {
213*6777b538SAndroid Build Coastguard Worker     return std::reverse_iterator(cend());
214*6777b538SAndroid Build Coastguard Worker   }
215*6777b538SAndroid Build Coastguard Worker   // Produces a reverse iterator over the cstring view, excluding the
216*6777b538SAndroid Build Coastguard Worker   // terminating NUL.
rcend()217*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const const_reverse_iterator rcend() const noexcept {
218*6777b538SAndroid Build Coastguard Worker     return std::reverse_iterator(cbegin());
219*6777b538SAndroid Build Coastguard Worker   }
220*6777b538SAndroid Build Coastguard Worker 
221*6777b538SAndroid Build Coastguard Worker   // Returns the character at offset `idx`.
222*6777b538SAndroid Build Coastguard Worker   //
223*6777b538SAndroid Build Coastguard Worker   // This can be used to access any character in the ctring, as well as the NUL
224*6777b538SAndroid Build Coastguard Worker   // terminator.
225*6777b538SAndroid Build Coastguard Worker   //
226*6777b538SAndroid Build Coastguard Worker   // # Checks
227*6777b538SAndroid Build Coastguard Worker   // The function CHECKs that the `idx` is inside the cstring (including at its
228*6777b538SAndroid Build Coastguard Worker   // NUL terminator) and will terminate otherwise.
229*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const Char& operator[](size_t idx) const noexcept {
230*6777b538SAndroid Build Coastguard Worker     CHECK_LE(idx, len_);
231*6777b538SAndroid Build Coastguard Worker     // SAFETY: `ptr_` points `len_` many elements plus a NUL terminator, and
232*6777b538SAndroid Build Coastguard Worker     // `idx <= len_`, so `idx` is in range for `ptr_`.
233*6777b538SAndroid Build Coastguard Worker     return UNSAFE_BUFFERS(ptr_[idx]);
234*6777b538SAndroid Build Coastguard Worker   }
235*6777b538SAndroid Build Coastguard Worker 
236*6777b538SAndroid Build Coastguard Worker   // A named function that performs the same as `operator[]`.
at(size_t idx)237*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const Char& at(size_t idx) const noexcept {
238*6777b538SAndroid Build Coastguard Worker     return (*this)[idx];
239*6777b538SAndroid Build Coastguard Worker   }
240*6777b538SAndroid Build Coastguard Worker 
241*6777b538SAndroid Build Coastguard Worker   // Returns the first character in the cstring view.
242*6777b538SAndroid Build Coastguard Worker   //
243*6777b538SAndroid Build Coastguard Worker   // # Checks
244*6777b538SAndroid Build Coastguard Worker   // The function CHECKs that the string is non-empty, and will terminate
245*6777b538SAndroid Build Coastguard Worker   // otherwise.
front()246*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const Char& front() const noexcept {
247*6777b538SAndroid Build Coastguard Worker     CHECK(len_);
248*6777b538SAndroid Build Coastguard Worker     // Since `len_ > 0`, 0 is a valid offset into the string contents.
249*6777b538SAndroid Build Coastguard Worker     return UNSAFE_BUFFERS(ptr_[0u]);
250*6777b538SAndroid Build Coastguard Worker   }
251*6777b538SAndroid Build Coastguard Worker 
252*6777b538SAndroid Build Coastguard Worker   // Returns the last (non-NUL) character in the cstring view.
253*6777b538SAndroid Build Coastguard Worker   //
254*6777b538SAndroid Build Coastguard Worker   // # Checks
255*6777b538SAndroid Build Coastguard Worker   // The function CHECKs that the string is non-empty, and will terminate
256*6777b538SAndroid Build Coastguard Worker   // otherwise.
back()257*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr const Char& back() const noexcept {
258*6777b538SAndroid Build Coastguard Worker     CHECK(len_);
259*6777b538SAndroid Build Coastguard Worker     // Since `len_ > 0`, `len - 1` will not underflow. There are `len_` many
260*6777b538SAndroid Build Coastguard Worker     // chars in the string before a NUL, so `len_ - 1` is in range of the string
261*6777b538SAndroid Build Coastguard Worker     // contents.
262*6777b538SAndroid Build Coastguard Worker     return UNSAFE_BUFFERS(ptr_[len_ - 1u]);
263*6777b538SAndroid Build Coastguard Worker   }
264*6777b538SAndroid Build Coastguard Worker 
265*6777b538SAndroid Build Coastguard Worker   // Modifies the cstring view in place, moving the front ahead by `n`
266*6777b538SAndroid Build Coastguard Worker   // characters.
267*6777b538SAndroid Build Coastguard Worker   //
268*6777b538SAndroid Build Coastguard Worker   // # Checks
269*6777b538SAndroid Build Coastguard Worker   // The function CHECKs that `n <= size()`, and will terminate otherwise.
remove_prefix(size_t n)270*6777b538SAndroid Build Coastguard Worker   constexpr void remove_prefix(size_t n) noexcept {
271*6777b538SAndroid Build Coastguard Worker     CHECK_LE(n, len_);
272*6777b538SAndroid Build Coastguard Worker     // SAFETY: Since `n <= len_`, the pointer at offset `n` is inside the string
273*6777b538SAndroid Build Coastguard Worker     // (or at the terminating NUL) and the `len_ - n` value will not underflow.
274*6777b538SAndroid Build Coastguard Worker     // Thus the resulting pointer is still a NUL- terminated string of length
275*6777b538SAndroid Build Coastguard Worker     // `len_ - n`.
276*6777b538SAndroid Build Coastguard Worker     ptr_ = UNSAFE_BUFFERS(ptr_ + n);
277*6777b538SAndroid Build Coastguard Worker     len_ = len_ - n;
278*6777b538SAndroid Build Coastguard Worker   }
279*6777b538SAndroid Build Coastguard Worker 
280*6777b538SAndroid Build Coastguard Worker   // No `remove_suffix()` method exists as it would remove the terminating NUL
281*6777b538SAndroid Build Coastguard Worker   // character. Convert to a `std::string_view` (either by construction or with
282*6777b538SAndroid Build Coastguard Worker   // a `substr(0u)` call) to construct arbitrary substrings that are not
283*6777b538SAndroid Build Coastguard Worker   // NUL-terminated.
284*6777b538SAndroid Build Coastguard Worker   void remove_suffix(size_t n) = delete;
285*6777b538SAndroid Build Coastguard Worker 
286*6777b538SAndroid Build Coastguard Worker   // Modifies the cstring view in place, swapping its contents with another view
287*6777b538SAndroid Build Coastguard Worker   // of the same type.
swap(basic_cstring_view & other)288*6777b538SAndroid Build Coastguard Worker   constexpr void swap(basic_cstring_view& other) noexcept {
289*6777b538SAndroid Build Coastguard Worker     std::swap(ptr_, other.ptr_);
290*6777b538SAndroid Build Coastguard Worker     std::swap(len_, other.len_);
291*6777b538SAndroid Build Coastguard Worker   }
292*6777b538SAndroid Build Coastguard Worker 
293*6777b538SAndroid Build Coastguard Worker   // Returns a string view of the subrange starting as `pos` and including
294*6777b538SAndroid Build Coastguard Worker   // `count` characters. If `count` is not specified, or exceeds the length of
295*6777b538SAndroid Build Coastguard Worker   // the string after `pos`, the subrange returned will include all characters
296*6777b538SAndroid Build Coastguard Worker   // up to the terminating NUL.
297*6777b538SAndroid Build Coastguard Worker   //
298*6777b538SAndroid Build Coastguard Worker   // # Checks
299*6777b538SAndroid Build Coastguard Worker   // The function CHECKs that `pos` is in range for the string (or at the
300*6777b538SAndroid Build Coastguard Worker   // terminating NULL), and will terminate otherwise.
301*6777b538SAndroid Build Coastguard Worker   PURE_FUNCTION constexpr std::basic_string_view<Char> substr(
302*6777b538SAndroid Build Coastguard Worker       size_t pos,
303*6777b538SAndroid Build Coastguard Worker       size_t count = npos) const noexcept {
304*6777b538SAndroid Build Coastguard Worker     // Ensure `ptr_ + pos` is valid. and `len_ - pos` does not underflow.
305*6777b538SAndroid Build Coastguard Worker     CHECK_LE(pos, len_);
306*6777b538SAndroid Build Coastguard Worker     // SAFETY: We require that:
307*6777b538SAndroid Build Coastguard Worker     // * `ptr_ + pos` is a pointer in the string.
308*6777b538SAndroid Build Coastguard Worker     // * `pos + count <= len_` so that resulting substring's end is in range.
309*6777b538SAndroid Build Coastguard Worker     //
310*6777b538SAndroid Build Coastguard Worker     // The first follows directly from the CHECK above that `pos <= len_`. The
311*6777b538SAndroid Build Coastguard Worker     // second follows from clamping `count` to at most `len_ - pos`.
312*6777b538SAndroid Build Coastguard Worker     return UNSAFE_BUFFERS(
313*6777b538SAndroid Build Coastguard Worker         std::basic_string_view<Char>(ptr_ + pos, std::min(count, len_ - pos)));
314*6777b538SAndroid Build Coastguard Worker   }
315*6777b538SAndroid Build Coastguard Worker 
316*6777b538SAndroid Build Coastguard Worker   // Returns whether the cstring view starts with the given `prefix`. Will
317*6777b538SAndroid Build Coastguard Worker   // always return false if `prefix` is larger than the current cstring view.
starts_with(std::basic_string_view<Char> prefix)318*6777b538SAndroid Build Coastguard Worker   constexpr bool starts_with(
319*6777b538SAndroid Build Coastguard Worker       std::basic_string_view<Char> prefix) const noexcept {
320*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).starts_with(prefix);
321*6777b538SAndroid Build Coastguard Worker   }
322*6777b538SAndroid Build Coastguard Worker 
323*6777b538SAndroid Build Coastguard Worker   // Returns whether the cstring view starts with the given `character`.
starts_with(Char character)324*6777b538SAndroid Build Coastguard Worker   constexpr bool starts_with(Char character) const noexcept {
325*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).starts_with(character);
326*6777b538SAndroid Build Coastguard Worker   }
327*6777b538SAndroid Build Coastguard Worker 
328*6777b538SAndroid Build Coastguard Worker   // Returns whether the cstring view ends with the given `suffix`. Will
329*6777b538SAndroid Build Coastguard Worker   // always return false if `suffix` is larger than the current cstring view.
ends_with(std::basic_string_view<Char> suffix)330*6777b538SAndroid Build Coastguard Worker   constexpr bool ends_with(std::basic_string_view<Char> suffix) const noexcept {
331*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).ends_with(suffix);
332*6777b538SAndroid Build Coastguard Worker   }
333*6777b538SAndroid Build Coastguard Worker 
334*6777b538SAndroid Build Coastguard Worker   // Returns whether the cstring view starts with the given `character`.
ends_with(Char character)335*6777b538SAndroid Build Coastguard Worker   constexpr bool ends_with(Char character) const noexcept {
336*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).ends_with(character);
337*6777b538SAndroid Build Coastguard Worker   }
338*6777b538SAndroid Build Coastguard Worker 
339*6777b538SAndroid Build Coastguard Worker   // Returns the first position in the cstring view at which `search` is found,
340*6777b538SAndroid Build Coastguard Worker   // starting from the offset `pos`. If `pos` is not specified, the entire
341*6777b538SAndroid Build Coastguard Worker   // cstring view is searched. Returns `npos` if `search` is not found or if
342*6777b538SAndroid Build Coastguard Worker   // `pos` is out of range.
343*6777b538SAndroid Build Coastguard Worker   constexpr size_t find(std::basic_string_view<Char> search,
344*6777b538SAndroid Build Coastguard Worker                         size_t pos = 0u) const noexcept {
345*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).find(search, pos);
346*6777b538SAndroid Build Coastguard Worker   }
347*6777b538SAndroid Build Coastguard Worker   constexpr size_t find(Char search, size_t pos = 0u) const noexcept {
348*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).find(search, pos);
349*6777b538SAndroid Build Coastguard Worker   }
350*6777b538SAndroid Build Coastguard Worker 
351*6777b538SAndroid Build Coastguard Worker   // Returns the last position in the cstring view at which `search` is found,
352*6777b538SAndroid Build Coastguard Worker   // starting from the offset `pos`. If `pos` is not specified or is out of
353*6777b538SAndroid Build Coastguard Worker   // range, the entire cstring view is searched. Returns `npos` if `search` is
354*6777b538SAndroid Build Coastguard Worker   // not found.
355*6777b538SAndroid Build Coastguard Worker   constexpr size_t rfind(std::basic_string_view<Char> search,
356*6777b538SAndroid Build Coastguard Worker                          size_t pos = npos) const noexcept {
357*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).rfind(search, pos);
358*6777b538SAndroid Build Coastguard Worker   }
359*6777b538SAndroid Build Coastguard Worker   constexpr size_t rfind(Char search, size_t pos = npos) const noexcept {
360*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).rfind(search, pos);
361*6777b538SAndroid Build Coastguard Worker   }
362*6777b538SAndroid Build Coastguard Worker 
363*6777b538SAndroid Build Coastguard Worker   // Returns the first position in the cstring view at any character in the
364*6777b538SAndroid Build Coastguard Worker   // `search` is found, starting from the offset `pos`. If `pos` is not
365*6777b538SAndroid Build Coastguard Worker   // specified, the entire cstring view is searched. Returns `npos` if `search`
366*6777b538SAndroid Build Coastguard Worker   // is not found or if `pos` is out of range.
367*6777b538SAndroid Build Coastguard Worker   constexpr size_t find_first_of(std::basic_string_view<Char> search,
368*6777b538SAndroid Build Coastguard Worker                                  size_t pos = 0u) const noexcept {
369*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).find_first_of(search, pos);
370*6777b538SAndroid Build Coastguard Worker   }
371*6777b538SAndroid Build Coastguard Worker   constexpr size_t find_first_of(Char search, size_t pos = 0u) const noexcept {
372*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).find_first_of(search, pos);
373*6777b538SAndroid Build Coastguard Worker   }
374*6777b538SAndroid Build Coastguard Worker 
375*6777b538SAndroid Build Coastguard Worker   // Returns the last position in the cstring view at any character in the
376*6777b538SAndroid Build Coastguard Worker   // `search` is found, starting from the offset `pos`. If `pos` is not
377*6777b538SAndroid Build Coastguard Worker   // specified or is out of range, the entire cstring view is searched. Returns
378*6777b538SAndroid Build Coastguard Worker   // `npos` if `search` is not found.
379*6777b538SAndroid Build Coastguard Worker   constexpr size_t find_last_of(std::basic_string_view<Char> search,
380*6777b538SAndroid Build Coastguard Worker                                 size_t pos = npos) const noexcept {
381*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).find_last_of(search, pos);
382*6777b538SAndroid Build Coastguard Worker   }
383*6777b538SAndroid Build Coastguard Worker   constexpr size_t find_last_of(Char search, size_t pos = npos) const noexcept {
384*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).find_last_of(search, pos);
385*6777b538SAndroid Build Coastguard Worker   }
386*6777b538SAndroid Build Coastguard Worker 
387*6777b538SAndroid Build Coastguard Worker   // Returns the first position in the cstring view that is not equal to any
388*6777b538SAndroid Build Coastguard Worker   // character in the `search`, starting from the offset `pos`. If `pos` is not
389*6777b538SAndroid Build Coastguard Worker   // specified, the entire cstring view is searched. Returns `npos` if every
390*6777b538SAndroid Build Coastguard Worker   // character is part of `search` or if `pos` is out of range.
391*6777b538SAndroid Build Coastguard Worker   constexpr size_t find_first_not_of(std::basic_string_view<Char> search,
392*6777b538SAndroid Build Coastguard Worker                                      size_t pos = 0u) const noexcept {
393*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).find_first_not_of(search, pos);
394*6777b538SAndroid Build Coastguard Worker   }
395*6777b538SAndroid Build Coastguard Worker   constexpr size_t find_first_not_of(Char search,
396*6777b538SAndroid Build Coastguard Worker                                      size_t pos = 0u) const noexcept {
397*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).find_first_not_of(search, pos);
398*6777b538SAndroid Build Coastguard Worker   }
399*6777b538SAndroid Build Coastguard Worker 
400*6777b538SAndroid Build Coastguard Worker   // Returns the last position in the cstring view that is not equal to any
401*6777b538SAndroid Build Coastguard Worker   // character in the `search`, starting from the offset `pos`. If `pos` is not
402*6777b538SAndroid Build Coastguard Worker   // specified or is out of range, the entire cstring view is searched.  Returns
403*6777b538SAndroid Build Coastguard Worker   // `npos` if every character is part of `search`.
404*6777b538SAndroid Build Coastguard Worker   constexpr size_t find_last_not_of(std::basic_string_view<Char> search,
405*6777b538SAndroid Build Coastguard Worker                                     size_t pos = npos) const noexcept {
406*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).find_last_not_of(search, pos);
407*6777b538SAndroid Build Coastguard Worker   }
408*6777b538SAndroid Build Coastguard Worker   constexpr size_t find_last_not_of(Char search,
409*6777b538SAndroid Build Coastguard Worker                                     size_t pos = npos) const noexcept {
410*6777b538SAndroid Build Coastguard Worker     return std::basic_string_view<Char>(*this).find_last_not_of(search, pos);
411*6777b538SAndroid Build Coastguard Worker   }
412*6777b538SAndroid Build Coastguard Worker 
413*6777b538SAndroid Build Coastguard Worker   // Compare two cstring views for equality, comparing the string contents.
414*6777b538SAndroid Build Coastguard Worker   friend constexpr bool operator==(basic_cstring_view l, basic_cstring_view r) {
415*6777b538SAndroid Build Coastguard Worker     return std::ranges::equal(l, r);
416*6777b538SAndroid Build Coastguard Worker   }
417*6777b538SAndroid Build Coastguard Worker 
418*6777b538SAndroid Build Coastguard Worker   // Return an ordering between two cstring views, comparing the string
419*6777b538SAndroid Build Coastguard Worker   // contents.
420*6777b538SAndroid Build Coastguard Worker   //
421*6777b538SAndroid Build Coastguard Worker   // cstring views are weakly ordered, since string views pointing into
422*6777b538SAndroid Build Coastguard Worker   // different strings can compare as equal.
423*6777b538SAndroid Build Coastguard Worker   friend constexpr std::weak_ordering operator<=>(basic_cstring_view l,
424*6777b538SAndroid Build Coastguard Worker                                                   basic_cstring_view r) {
425*6777b538SAndroid Build Coastguard Worker     return std::lexicographical_compare_three_way(l.begin(), l.end(), r.begin(),
426*6777b538SAndroid Build Coastguard Worker                                                   r.end());
427*6777b538SAndroid Build Coastguard Worker   }
428*6777b538SAndroid Build Coastguard Worker 
429*6777b538SAndroid Build Coastguard Worker   // Implicitly converts from cstring_view to a non-NUL-terminated
430*6777b538SAndroid Build Coastguard Worker   // std::string_view. The std::string_view type implicitly constructs from
431*6777b538SAndroid Build Coastguard Worker   // `const char*` and cstring view is meant to replace the latter, so this acts
432*6777b538SAndroid Build Coastguard Worker   // like an implicit constructor on `std::string_view` for cstring views.
433*6777b538SAndroid Build Coastguard Worker   //
434*6777b538SAndroid Build Coastguard Worker   // This operator also avoids a requirement on having overloads for both
435*6777b538SAndroid Build Coastguard Worker   // std::string_view and cstring_view. Such overloads are ambiguous because
436*6777b538SAndroid Build Coastguard Worker   // both can construct from a character array.
437*6777b538SAndroid Build Coastguard Worker   //
438*6777b538SAndroid Build Coastguard Worker   // NOLINTNEXTLINE(google-explicit-constructor)
439*6777b538SAndroid Build Coastguard Worker   constexpr operator std::basic_string_view<Char>() const noexcept {
440*6777b538SAndroid Build Coastguard Worker     // SAFETY: The cstring view provides that `ptr_ + len_` to be valid.
441*6777b538SAndroid Build Coastguard Worker     return UNSAFE_BUFFERS(std::basic_string_view<Char>(ptr_, len_));
442*6777b538SAndroid Build Coastguard Worker   }
443*6777b538SAndroid Build Coastguard Worker 
444*6777b538SAndroid Build Coastguard Worker   // Converts from cstring_view to std::string. This allocates a new string
445*6777b538SAndroid Build Coastguard Worker   // backing and copies into it.
446*6777b538SAndroid Build Coastguard Worker   //
447*6777b538SAndroid Build Coastguard Worker   // The std::string type implicitly constructs from `const char*` however it
448*6777b538SAndroid Build Coastguard Worker   // does not implicitly construct from std::string_view. This type sits between
449*6777b538SAndroid Build Coastguard Worker   // these two, and opts towards making heap allocations explicit by requiring
450*6777b538SAndroid Build Coastguard Worker   // an explicit conversion.
451*6777b538SAndroid Build Coastguard Worker   constexpr explicit operator std::basic_string<Char>() const noexcept {
452*6777b538SAndroid Build Coastguard Worker     // SAFETY: The cstring view provides that `ptr_ + len_` to be valid.
453*6777b538SAndroid Build Coastguard Worker     return UNSAFE_BUFFERS(std::basic_string<Char>(ptr_, len_));
454*6777b538SAndroid Build Coastguard Worker   }
455*6777b538SAndroid Build Coastguard Worker 
456*6777b538SAndroid Build Coastguard Worker   // Concatenate a std::string with a cstring_view to produce another
457*6777b538SAndroid Build Coastguard Worker   // std::string.
458*6777b538SAndroid Build Coastguard Worker   //
459*6777b538SAndroid Build Coastguard Worker   // These act like overloads on `std::string` that work for concatenating
460*6777b538SAndroid Build Coastguard Worker   // `std::string` and `const char*`.
461*6777b538SAndroid Build Coastguard Worker   //
462*6777b538SAndroid Build Coastguard Worker   // The rvalue overloads allow `std::string` to reuse existing capacity, by
463*6777b538SAndroid Build Coastguard Worker   // calling through to the rvalue overloads on `std::string`.
464*6777b538SAndroid Build Coastguard Worker   template <class Traits, class Alloc>
465*6777b538SAndroid Build Coastguard Worker   friend constexpr std::basic_string<Char, Traits, Alloc> operator+(
466*6777b538SAndroid Build Coastguard Worker       basic_cstring_view lhs,
467*6777b538SAndroid Build Coastguard Worker       const std::basic_string<Char, Traits, Alloc>& rhs) {
468*6777b538SAndroid Build Coastguard Worker     return lhs.c_str() + rhs;
469*6777b538SAndroid Build Coastguard Worker   }
470*6777b538SAndroid Build Coastguard Worker   template <class Traits, class Alloc>
471*6777b538SAndroid Build Coastguard Worker   friend constexpr std::basic_string<Char, Traits, Alloc> operator+(
472*6777b538SAndroid Build Coastguard Worker       basic_cstring_view lhs,
473*6777b538SAndroid Build Coastguard Worker       std::basic_string<Char, Traits, Alloc>&& rhs) {
474*6777b538SAndroid Build Coastguard Worker     return lhs.c_str() + std::move(rhs);
475*6777b538SAndroid Build Coastguard Worker   }
476*6777b538SAndroid Build Coastguard Worker   template <class Traits, class Alloc>
477*6777b538SAndroid Build Coastguard Worker   friend constexpr std::basic_string<Char, Traits, Alloc> operator+(
478*6777b538SAndroid Build Coastguard Worker       const std::basic_string<Char, Traits, Alloc>& lhs,
479*6777b538SAndroid Build Coastguard Worker       basic_cstring_view rhs) {
480*6777b538SAndroid Build Coastguard Worker     return lhs + rhs.c_str();
481*6777b538SAndroid Build Coastguard Worker   }
482*6777b538SAndroid Build Coastguard Worker   template <class Traits, class Alloc>
483*6777b538SAndroid Build Coastguard Worker   friend constexpr std::basic_string<Char, Traits, Alloc> operator+(
484*6777b538SAndroid Build Coastguard Worker       std::basic_string<Char, Traits, Alloc>&& lhs,
485*6777b538SAndroid Build Coastguard Worker       basic_cstring_view rhs) {
486*6777b538SAndroid Build Coastguard Worker     return std::move(lhs) + rhs.c_str();
487*6777b538SAndroid Build Coastguard Worker   }
488*6777b538SAndroid Build Coastguard Worker 
489*6777b538SAndroid Build Coastguard Worker  private:
490*6777b538SAndroid Build Coastguard Worker   // An empty string literal for the `Char` type.
491*6777b538SAndroid Build Coastguard Worker   static constexpr Char kEmpty[] = {Char{0}};
492*6777b538SAndroid Build Coastguard Worker 
493*6777b538SAndroid Build Coastguard Worker   // An always-valid pointer (never null) to a NUL-terminated string.
494*6777b538SAndroid Build Coastguard Worker   //
495*6777b538SAndroid Build Coastguard Worker   // RAW_PTR_EXCLUSION: cstring_view is typically used on the stack as a local
496*6777b538SAndroid Build Coastguard Worker   // variable/function parameter, so no raw_ptr is used here.
497*6777b538SAndroid Build Coastguard Worker   RAW_PTR_EXCLUSION const Char* ptr_;
498*6777b538SAndroid Build Coastguard Worker   // The number of characters between `ptr_` and the NUL terminator.
499*6777b538SAndroid Build Coastguard Worker   //
500*6777b538SAndroid Build Coastguard Worker   // SAFETY: `ptr_ + len_` is always valid since `len_` must not exceed the
501*6777b538SAndroid Build Coastguard Worker   // number of characters in the allocation, or it would no longer indicate the
502*6777b538SAndroid Build Coastguard Worker   // position of the NUL terminator in the string allocation.
503*6777b538SAndroid Build Coastguard Worker   size_t len_;
504*6777b538SAndroid Build Coastguard Worker };
505*6777b538SAndroid Build Coastguard Worker 
506*6777b538SAndroid Build Coastguard Worker // cstring_view provides a view of a NUL-terminated string. It is a replacement
507*6777b538SAndroid Build Coastguard Worker // for all use of `const char*`, in order to provide bounds checks and prevent
508*6777b538SAndroid Build Coastguard Worker // unsafe pointer usage (otherwise prevented by `-Wunsafe-buffer-usage`).
509*6777b538SAndroid Build Coastguard Worker //
510*6777b538SAndroid Build Coastguard Worker // See basic_cstring_view for more.
511*6777b538SAndroid Build Coastguard Worker using cstring_view = basic_cstring_view<char>;
512*6777b538SAndroid Build Coastguard Worker 
513*6777b538SAndroid Build Coastguard Worker // u16cstring_view provides a view of a NUL-terminated string. It is a
514*6777b538SAndroid Build Coastguard Worker // replacement for all use of `const char16_t*`, in order to provide bounds
515*6777b538SAndroid Build Coastguard Worker // checks and prevent unsafe pointer usage (otherwise prevented by
516*6777b538SAndroid Build Coastguard Worker // `-Wunsafe-buffer-usage`).
517*6777b538SAndroid Build Coastguard Worker //
518*6777b538SAndroid Build Coastguard Worker // See basic_cstring_view for more.
519*6777b538SAndroid Build Coastguard Worker using u16cstring_view = basic_cstring_view<char16_t>;
520*6777b538SAndroid Build Coastguard Worker 
521*6777b538SAndroid Build Coastguard Worker // u32cstring_view provides a view of a NUL-terminated string. It is a
522*6777b538SAndroid Build Coastguard Worker // replacement for all use of `const char32_t*`, in order to provide bounds
523*6777b538SAndroid Build Coastguard Worker // checks and prevent unsafe pointer usage (otherwise prevented by
524*6777b538SAndroid Build Coastguard Worker // `-Wunsafe-buffer-usage`).
525*6777b538SAndroid Build Coastguard Worker //
526*6777b538SAndroid Build Coastguard Worker // See basic_cstring_view for more.
527*6777b538SAndroid Build Coastguard Worker using u32cstring_view = basic_cstring_view<char32_t>;
528*6777b538SAndroid Build Coastguard Worker 
529*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
530*6777b538SAndroid Build Coastguard Worker // wcstring_view provides a view of a NUL-terminated string. It is a
531*6777b538SAndroid Build Coastguard Worker // replacement for all use of `const wchar_t*`, in order to provide bounds
532*6777b538SAndroid Build Coastguard Worker // checks and prevent unsafe pointer usage (otherwise prevented by
533*6777b538SAndroid Build Coastguard Worker // `-Wunsafe-buffer-usage`).
534*6777b538SAndroid Build Coastguard Worker //
535*6777b538SAndroid Build Coastguard Worker // See basic_cstring_view for more.
536*6777b538SAndroid Build Coastguard Worker using wcstring_view = basic_cstring_view<wchar_t>;
537*6777b538SAndroid Build Coastguard Worker #endif
538*6777b538SAndroid Build Coastguard Worker 
539*6777b538SAndroid Build Coastguard Worker // Writes the contents of the cstring view to the stream.
540*6777b538SAndroid Build Coastguard Worker template <class Char, class Traits>
541*6777b538SAndroid Build Coastguard Worker std::basic_ostream<Char, Traits>& operator<<(
542*6777b538SAndroid Build Coastguard Worker     std::basic_ostream<Char, Traits>& os,
543*6777b538SAndroid Build Coastguard Worker     basic_cstring_view<Char> view) {
544*6777b538SAndroid Build Coastguard Worker   return os << std::basic_string_view<Char>(view);
545*6777b538SAndroid Build Coastguard Worker }
546*6777b538SAndroid Build Coastguard Worker 
547*6777b538SAndroid Build Coastguard Worker }  // namespace base
548*6777b538SAndroid Build Coastguard Worker 
549*6777b538SAndroid Build Coastguard Worker template <class Char>
550*6777b538SAndroid Build Coastguard Worker struct std::hash<base::basic_cstring_view<Char>> {
551*6777b538SAndroid Build Coastguard Worker   size_t operator()(const base::basic_cstring_view<Char>& t) const noexcept {
552*6777b538SAndroid Build Coastguard Worker     return std::hash<std::basic_string_view<Char>>()(t);
553*6777b538SAndroid Build Coastguard Worker   }
554*6777b538SAndroid Build Coastguard Worker };
555*6777b538SAndroid Build Coastguard Worker 
556*6777b538SAndroid Build Coastguard Worker template <class Char>
557*6777b538SAndroid Build Coastguard Worker inline constexpr bool
558*6777b538SAndroid Build Coastguard Worker     std::ranges::enable_borrowed_range<base::basic_cstring_view<Char>> = true;
559*6777b538SAndroid Build Coastguard Worker 
560*6777b538SAndroid Build Coastguard Worker template <class Char>
561*6777b538SAndroid Build Coastguard Worker inline constexpr bool std::ranges::enable_view<base::basic_cstring_view<Char>> =
562*6777b538SAndroid Build Coastguard Worker     true;
563*6777b538SAndroid Build Coastguard Worker 
564*6777b538SAndroid Build Coastguard Worker #endif  // BASE_STRINGS_CSTRING_VIEW_H_
565