1 //===-- Standalone implementation std::string_view --------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
10 #define LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
12 #include "src/__support/common.h"
13 #include "src/__support/macros/config.h"
17 namespace LIBC_NAMESPACE_DECL
{
20 // This is very simple alternate of the std::string_view class. There is no
21 // bounds check performed in any of the methods. The callers are expected to
22 // do the checks before invoking the methods.
24 // This class will be extended as needed in future.
30 LIBC_INLINE
static size_t min(size_t A
, size_t B
) { return A
<= B
? A
: B
; }
32 LIBC_INLINE
static int compareMemory(const char *Lhs
, const char *Rhs
,
34 for (size_t i
= 0; i
< Length
; ++i
)
35 if (int Diff
= (int)Lhs
[i
] - (int)Rhs
[i
])
40 LIBC_INLINE
static constexpr size_t length(const char *Str
) {
41 for (const char *End
= Str
;; ++End
)
46 LIBC_INLINE
bool equals(string_view Other
) const {
47 return (Len
== Other
.Len
&&
48 compareMemory(Data
, Other
.Data
, Other
.Len
) == 0);
52 using value_type
= char;
53 using size_type
= size_t;
54 using difference_type
= ptrdiff_t;
55 using pointer
= char *;
56 using const_pointer
= const char *;
57 using reference
= char &;
58 using const_reference
= const char &;
59 using const_iterator
= char *;
60 using iterator
= const_iterator
;
62 // special value equal to the maximum value representable by the type
64 LIBC_INLINE_VAR
static constexpr size_t npos
= -1;
66 LIBC_INLINE
constexpr string_view() : Data(nullptr), Len(0) {}
68 // Assumes Str is a null-terminated string. The length of the string does
69 // not include the terminating null character.
70 // Preconditions: [Str, Str + ​length(Str)) is a valid range.
71 LIBC_INLINE
constexpr string_view(const char *Str
)
72 : Data(Str
), Len(length(Str
)) {}
74 // Preconditions: [Str, Str + N) is a valid range.
75 LIBC_INLINE
constexpr string_view(const char *Str
, size_t N
)
76 : Data(Str
), Len(N
) {}
78 LIBC_INLINE
constexpr const char *data() const { return Data
; }
80 // Returns the size of the string_view.
81 LIBC_INLINE
constexpr size_t size() const { return Len
; }
83 // Returns whether the string_view is empty.
84 LIBC_INLINE
constexpr bool empty() const { return Len
== 0; }
86 // Returns an iterator to the first character of the view.
87 LIBC_INLINE
const char *begin() const { return Data
; }
89 // Returns an iterator to the character following the last character of the
91 LIBC_INLINE
const char *end() const { return Data
+ Len
; }
93 // Returns a const reference to the character at specified location pos.
94 // No bounds checking is performed: the behavior is undefined if pos >=
96 LIBC_INLINE
constexpr const char &operator[](size_t Index
) const {
100 /// compare - Compare two strings; the result is -1, 0, or 1 if this string
101 /// is lexicographically less than, equal to, or greater than the \p Other.
102 LIBC_INLINE
int compare(string_view Other
) const {
103 // Check the prefix for a mismatch.
104 if (int Res
= compareMemory(Data
, Other
.Data
, min(Len
, Other
.Len
)))
105 return Res
< 0 ? -1 : 1;
106 // Otherwise the prefixes match, so we only need to check the lengths.
107 if (Len
== Other
.Len
)
109 return Len
< Other
.Len
? -1 : 1;
112 LIBC_INLINE
bool operator==(string_view Other
) const { return equals(Other
); }
113 LIBC_INLINE
bool operator!=(string_view Other
) const {
114 return !(*this == Other
);
116 LIBC_INLINE
bool operator<(string_view Other
) const {
117 return compare(Other
) == -1;
119 LIBC_INLINE
bool operator<=(string_view Other
) const {
120 return compare(Other
) != 1;
122 LIBC_INLINE
bool operator>(string_view Other
) const {
123 return compare(Other
) == 1;
125 LIBC_INLINE
bool operator>=(string_view Other
) const {
126 return compare(Other
) != -1;
129 // Moves the start of the view forward by n characters.
130 // The behavior is undefined if n > size().
131 LIBC_INLINE
void remove_prefix(size_t N
) {
136 // Moves the end of the view back by n characters.
137 // The behavior is undefined if n > size().
138 LIBC_INLINE
void remove_suffix(size_t N
) { Len
-= N
; }
140 // Check if this string starts with the given Prefix.
141 LIBC_INLINE
bool starts_with(string_view Prefix
) const {
142 return Len
>= Prefix
.Len
&&
143 compareMemory(Data
, Prefix
.Data
, Prefix
.Len
) == 0;
146 // Check if this string starts with the given Prefix.
147 LIBC_INLINE
bool starts_with(const char Prefix
) const {
148 return !empty() && front() == Prefix
;
151 // Check if this string ends with the given Prefix.
152 LIBC_INLINE
bool ends_with(const char Suffix
) const {
153 return !empty() && back() == Suffix
;
156 // Check if this string ends with the given Suffix.
157 LIBC_INLINE
bool ends_with(string_view Suffix
) const {
158 return Len
>= Suffix
.Len
&&
159 compareMemory(end() - Suffix
.Len
, Suffix
.Data
, Suffix
.Len
) == 0;
162 // Return a reference to the substring from [Start, Start + N).
164 // Start The index of the starting character in the substring; if the index is
165 // npos or greater than the length of the string then the empty substring will
168 // N The number of characters to included in the substring. If N exceeds the
169 // number of characters remaining in the string, the string suffix (starting
170 // with Start) will be returned.
171 LIBC_INLINE string_view
substr(size_t Start
, size_t N
= npos
) const {
172 Start
= min(Start
, Len
);
173 return string_view(Data
+ Start
, min(N
, Len
- Start
));
176 // front - Get the first character in the string.
177 LIBC_INLINE
char front() const { return Data
[0]; }
179 // back - Get the last character in the string.
180 LIBC_INLINE
char back() const { return Data
[Len
- 1]; }
182 // Finds the first occurence of c in this view, starting at position From.
183 LIBC_INLINE
constexpr size_t find_first_of(const char c
,
184 size_t From
= 0) const {
185 for (size_t Pos
= From
; Pos
< size(); ++Pos
)
186 if ((*this)[Pos
] == c
)
191 // Finds the last occurence of c in this view, ending at position End.
192 LIBC_INLINE
constexpr size_t find_last_of(const char c
,
193 size_t End
= npos
) const {
194 End
= End
>= size() ? size() : End
+ 1;
195 for (; End
> 0; --End
)
196 if ((*this)[End
- 1] == c
)
201 // Finds the first character not equal to c in this view, starting at position
203 LIBC_INLINE
constexpr size_t find_first_not_of(const char c
,
204 size_t From
= 0) const {
205 for (size_t Pos
= From
; Pos
< size(); ++Pos
)
206 if ((*this)[Pos
] != c
)
211 // Check if this view contains the given character.
212 LIBC_INLINE
constexpr bool contains(char c
) const {
213 return find_first_of(c
) != npos
;
218 } // namespace LIBC_NAMESPACE_DECL
220 #endif // LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H