xref: /llvm-project/libc/src/__support/CPP/string_view.h (revision 111b062f63ba52552f41e425449ba1db048dc51a)
1aa59c981SGuillaume Chatelet //===-- Standalone implementation std::string_view --------------*- C++ -*-===//
2aa59c981SGuillaume Chatelet //
3aa59c981SGuillaume Chatelet // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4aa59c981SGuillaume Chatelet // See https://llvm.org/LICENSE.txt for license information.
5aa59c981SGuillaume Chatelet // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6aa59c981SGuillaume Chatelet //
7aa59c981SGuillaume Chatelet //===----------------------------------------------------------------------===//
8aa59c981SGuillaume Chatelet 
9270547f3SGuillaume Chatelet #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
10270547f3SGuillaume Chatelet #define LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
11aa59c981SGuillaume Chatelet 
1205d9cc47SSiva Chandra Reddy #include "src/__support/common.h"
135ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
1405d9cc47SSiva Chandra Reddy 
15aa59c981SGuillaume Chatelet #include <stddef.h>
16aa59c981SGuillaume Chatelet 
175ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
18aa59c981SGuillaume Chatelet namespace cpp {
19aa59c981SGuillaume Chatelet 
20aa59c981SGuillaume Chatelet // This is very simple alternate of the std::string_view class. There is no
21aa59c981SGuillaume Chatelet // bounds check performed in any of the methods. The callers are expected to
22aa59c981SGuillaume Chatelet // do the checks before invoking the methods.
23aa59c981SGuillaume Chatelet //
24aa59c981SGuillaume Chatelet // This class will be extended as needed in future.
25aa59c981SGuillaume Chatelet class string_view {
26aa59c981SGuillaume Chatelet private:
27aa59c981SGuillaume Chatelet   const char *Data;
28aa59c981SGuillaume Chatelet   size_t Len;
29aa59c981SGuillaume Chatelet 
30019a477cSRoland McGrath   LIBC_INLINE static size_t min(size_t A, size_t B) { return A <= B ? A : B; }
31aa59c981SGuillaume Chatelet 
3205d9cc47SSiva Chandra Reddy   LIBC_INLINE static int compareMemory(const char *Lhs, const char *Rhs,
3305d9cc47SSiva Chandra Reddy                                        size_t Length) {
34*111b062fSShourya Goel     for (size_t i = 0; i < Length; ++i)
35*111b062fSShourya Goel       if (int Diff = (int)Lhs[i] - (int)Rhs[i])
36aa59c981SGuillaume Chatelet         return Diff;
37aa59c981SGuillaume Chatelet     return 0;
38aa59c981SGuillaume Chatelet   }
39aa59c981SGuillaume Chatelet 
4005d9cc47SSiva Chandra Reddy   LIBC_INLINE static constexpr size_t length(const char *Str) {
411e5b3ce7SGuillaume Chatelet     for (const char *End = Str;; ++End)
421e5b3ce7SGuillaume Chatelet       if (*End == '\0')
431e5b3ce7SGuillaume Chatelet         return End - Str;
441e5b3ce7SGuillaume Chatelet   }
451e5b3ce7SGuillaume Chatelet 
4605d9cc47SSiva Chandra Reddy   LIBC_INLINE bool equals(string_view Other) const {
471e5b3ce7SGuillaume Chatelet     return (Len == Other.Len &&
481e5b3ce7SGuillaume Chatelet             compareMemory(Data, Other.Data, Other.Len) == 0);
491e5b3ce7SGuillaume Chatelet   }
501e5b3ce7SGuillaume Chatelet 
51aa59c981SGuillaume Chatelet public:
521e5b3ce7SGuillaume Chatelet   using value_type = char;
531e5b3ce7SGuillaume Chatelet   using size_type = size_t;
541e5b3ce7SGuillaume Chatelet   using difference_type = ptrdiff_t;
551e5b3ce7SGuillaume Chatelet   using pointer = char *;
561e5b3ce7SGuillaume Chatelet   using const_pointer = const char *;
571e5b3ce7SGuillaume Chatelet   using reference = char &;
581e5b3ce7SGuillaume Chatelet   using const_reference = const char &;
591e5b3ce7SGuillaume Chatelet   using const_iterator = char *;
601e5b3ce7SGuillaume Chatelet   using iterator = const_iterator;
611e5b3ce7SGuillaume Chatelet 
62aa59c981SGuillaume Chatelet   // special value equal to the maximum value representable by the type
63aa59c981SGuillaume Chatelet   // size_type.
645bf8efd2SRoland McGrath   LIBC_INLINE_VAR static constexpr size_t npos = -1;
65aa59c981SGuillaume Chatelet 
6605d9cc47SSiva Chandra Reddy   LIBC_INLINE constexpr string_view() : Data(nullptr), Len(0) {}
67aa59c981SGuillaume Chatelet 
68aa59c981SGuillaume Chatelet   // Assumes Str is a null-terminated string. The length of the string does
69aa59c981SGuillaume Chatelet   // not include the terminating null character.
701e5b3ce7SGuillaume Chatelet   // Preconditions: [Str, Str + ​length(Str)) is a valid range.
7105d9cc47SSiva Chandra Reddy   LIBC_INLINE constexpr string_view(const char *Str)
7205d9cc47SSiva Chandra Reddy       : Data(Str), Len(length(Str)) {}
73aa59c981SGuillaume Chatelet 
741e5b3ce7SGuillaume Chatelet   // Preconditions: [Str, Str + N) is a valid range.
7505d9cc47SSiva Chandra Reddy   LIBC_INLINE constexpr string_view(const char *Str, size_t N)
7605d9cc47SSiva Chandra Reddy       : Data(Str), Len(N) {}
77aa59c981SGuillaume Chatelet 
7805d9cc47SSiva Chandra Reddy   LIBC_INLINE constexpr const char *data() const { return Data; }
79aa59c981SGuillaume Chatelet 
80aa59c981SGuillaume Chatelet   // Returns the size of the string_view.
8105d9cc47SSiva Chandra Reddy   LIBC_INLINE constexpr size_t size() const { return Len; }
82aa59c981SGuillaume Chatelet 
83aa59c981SGuillaume Chatelet   // Returns whether the string_view is empty.
8405d9cc47SSiva Chandra Reddy   LIBC_INLINE constexpr bool empty() const { return Len == 0; }
85aa59c981SGuillaume Chatelet 
86aa59c981SGuillaume Chatelet   // Returns an iterator to the first character of the view.
8705d9cc47SSiva Chandra Reddy   LIBC_INLINE const char *begin() const { return Data; }
88aa59c981SGuillaume Chatelet 
89aa59c981SGuillaume Chatelet   // Returns an iterator to the character following the last character of the
90aa59c981SGuillaume Chatelet   // view.
9105d9cc47SSiva Chandra Reddy   LIBC_INLINE const char *end() const { return Data + Len; }
92aa59c981SGuillaume Chatelet 
93aa59c981SGuillaume Chatelet   // Returns a const reference to the character at specified location pos.
94aa59c981SGuillaume Chatelet   // No bounds checking is performed: the behavior is undefined if pos >=
95aa59c981SGuillaume Chatelet   // size().
9605d9cc47SSiva Chandra Reddy   LIBC_INLINE constexpr const char &operator[](size_t Index) const {
9705d9cc47SSiva Chandra Reddy     return Data[Index];
9805d9cc47SSiva Chandra Reddy   }
99aa59c981SGuillaume Chatelet 
100aa59c981SGuillaume Chatelet   /// compare - Compare two strings; the result is -1, 0, or 1 if this string
101aa59c981SGuillaume Chatelet   /// is lexicographically less than, equal to, or greater than the \p Other.
10205d9cc47SSiva Chandra Reddy   LIBC_INLINE int compare(string_view Other) const {
103aa59c981SGuillaume Chatelet     // Check the prefix for a mismatch.
104aa59c981SGuillaume Chatelet     if (int Res = compareMemory(Data, Other.Data, min(Len, Other.Len)))
105aa59c981SGuillaume Chatelet       return Res < 0 ? -1 : 1;
106aa59c981SGuillaume Chatelet     // Otherwise the prefixes match, so we only need to check the lengths.
107aa59c981SGuillaume Chatelet     if (Len == Other.Len)
108aa59c981SGuillaume Chatelet       return 0;
109aa59c981SGuillaume Chatelet     return Len < Other.Len ? -1 : 1;
110aa59c981SGuillaume Chatelet   }
111aa59c981SGuillaume Chatelet 
11205d9cc47SSiva Chandra Reddy   LIBC_INLINE bool operator==(string_view Other) const { return equals(Other); }
11305d9cc47SSiva Chandra Reddy   LIBC_INLINE bool operator!=(string_view Other) const {
11405d9cc47SSiva Chandra Reddy     return !(*this == Other);
11505d9cc47SSiva Chandra Reddy   }
11605d9cc47SSiva Chandra Reddy   LIBC_INLINE bool operator<(string_view Other) const {
1171e5b3ce7SGuillaume Chatelet     return compare(Other) == -1;
1181e5b3ce7SGuillaume Chatelet   }
11905d9cc47SSiva Chandra Reddy   LIBC_INLINE bool operator<=(string_view Other) const {
1201e5b3ce7SGuillaume Chatelet     return compare(Other) != 1;
1211e5b3ce7SGuillaume Chatelet   }
12205d9cc47SSiva Chandra Reddy   LIBC_INLINE bool operator>(string_view Other) const {
12305d9cc47SSiva Chandra Reddy     return compare(Other) == 1;
12405d9cc47SSiva Chandra Reddy   }
12505d9cc47SSiva Chandra Reddy   LIBC_INLINE bool operator>=(string_view Other) const {
126aa59c981SGuillaume Chatelet     return compare(Other) != -1;
127aa59c981SGuillaume Chatelet   }
128aa59c981SGuillaume Chatelet 
129aa59c981SGuillaume Chatelet   // Moves the start of the view forward by n characters.
130aa59c981SGuillaume Chatelet   // The behavior is undefined if n > size().
13105d9cc47SSiva Chandra Reddy   LIBC_INLINE void remove_prefix(size_t N) {
132aa59c981SGuillaume Chatelet     Len -= N;
133aa59c981SGuillaume Chatelet     Data += N;
134aa59c981SGuillaume Chatelet   }
135aa59c981SGuillaume Chatelet 
136aa59c981SGuillaume Chatelet   // Moves the end of the view back by n characters.
137aa59c981SGuillaume Chatelet   // The behavior is undefined if n > size().
13805d9cc47SSiva Chandra Reddy   LIBC_INLINE void remove_suffix(size_t N) { Len -= N; }
139aa59c981SGuillaume Chatelet 
140aa59c981SGuillaume Chatelet   // Check if this string starts with the given Prefix.
14105d9cc47SSiva Chandra Reddy   LIBC_INLINE bool starts_with(string_view Prefix) const {
142aa59c981SGuillaume Chatelet     return Len >= Prefix.Len &&
143aa59c981SGuillaume Chatelet            compareMemory(Data, Prefix.Data, Prefix.Len) == 0;
144aa59c981SGuillaume Chatelet   }
145aa59c981SGuillaume Chatelet 
146aa59c981SGuillaume Chatelet   // Check if this string starts with the given Prefix.
14705d9cc47SSiva Chandra Reddy   LIBC_INLINE bool starts_with(const char Prefix) const {
148aa59c981SGuillaume Chatelet     return !empty() && front() == Prefix;
149aa59c981SGuillaume Chatelet   }
150aa59c981SGuillaume Chatelet 
151aa59c981SGuillaume Chatelet   // Check if this string ends with the given Prefix.
15205d9cc47SSiva Chandra Reddy   LIBC_INLINE bool ends_with(const char Suffix) const {
153aa59c981SGuillaume Chatelet     return !empty() && back() == Suffix;
154aa59c981SGuillaume Chatelet   }
155aa59c981SGuillaume Chatelet 
156aa59c981SGuillaume Chatelet   // Check if this string ends with the given Suffix.
15705d9cc47SSiva Chandra Reddy   LIBC_INLINE bool ends_with(string_view Suffix) const {
158aa59c981SGuillaume Chatelet     return Len >= Suffix.Len &&
159aa59c981SGuillaume Chatelet            compareMemory(end() - Suffix.Len, Suffix.Data, Suffix.Len) == 0;
160aa59c981SGuillaume Chatelet   }
161aa59c981SGuillaume Chatelet 
162aa59c981SGuillaume Chatelet   // Return a reference to the substring from [Start, Start + N).
163aa59c981SGuillaume Chatelet   //
164aa59c981SGuillaume Chatelet   // Start The index of the starting character in the substring; if the index is
165aa59c981SGuillaume Chatelet   // npos or greater than the length of the string then the empty substring will
166aa59c981SGuillaume Chatelet   // be returned.
167aa59c981SGuillaume Chatelet   //
168aa59c981SGuillaume Chatelet   // N The number of characters to included in the substring. If N exceeds the
169aa59c981SGuillaume Chatelet   // number of characters remaining in the string, the string suffix (starting
170aa59c981SGuillaume Chatelet   // with Start) will be returned.
17105d9cc47SSiva Chandra Reddy   LIBC_INLINE string_view substr(size_t Start, size_t N = npos) const {
172aa59c981SGuillaume Chatelet     Start = min(Start, Len);
173aa59c981SGuillaume Chatelet     return string_view(Data + Start, min(N, Len - Start));
174aa59c981SGuillaume Chatelet   }
175aa59c981SGuillaume Chatelet 
176aa59c981SGuillaume Chatelet   // front - Get the first character in the string.
17705d9cc47SSiva Chandra Reddy   LIBC_INLINE char front() const { return Data[0]; }
178aa59c981SGuillaume Chatelet 
179aa59c981SGuillaume Chatelet   // back - Get the last character in the string.
18005d9cc47SSiva Chandra Reddy   LIBC_INLINE char back() const { return Data[Len - 1]; }
181aa59c981SGuillaume Chatelet 
1821e5b3ce7SGuillaume Chatelet   // Finds the first occurence of c in this view, starting at position From.
183f6f42af0SSchrodinger ZHU Yifan   LIBC_INLINE constexpr size_t find_first_of(const char c,
184f6f42af0SSchrodinger ZHU Yifan                                              size_t From = 0) const {
1851e5b3ce7SGuillaume Chatelet     for (size_t Pos = From; Pos < size(); ++Pos)
1861e5b3ce7SGuillaume Chatelet       if ((*this)[Pos] == c)
1871e5b3ce7SGuillaume Chatelet         return Pos;
1881e5b3ce7SGuillaume Chatelet     return npos;
189aa59c981SGuillaume Chatelet   }
190aa59c981SGuillaume Chatelet 
1911e5b3ce7SGuillaume Chatelet   // Finds the last occurence of c in this view, ending at position End.
192f6f42af0SSchrodinger ZHU Yifan   LIBC_INLINE constexpr size_t find_last_of(const char c,
193f6f42af0SSchrodinger ZHU Yifan                                             size_t End = npos) const {
1941e5b3ce7SGuillaume Chatelet     End = End >= size() ? size() : End + 1;
1951e5b3ce7SGuillaume Chatelet     for (; End > 0; --End)
1961e5b3ce7SGuillaume Chatelet       if ((*this)[End - 1] == c)
1971e5b3ce7SGuillaume Chatelet         return End - 1;
1981e5b3ce7SGuillaume Chatelet     return npos;
199aa59c981SGuillaume Chatelet   }
200f6f42af0SSchrodinger ZHU Yifan 
201f6f42af0SSchrodinger ZHU Yifan   // Finds the first character not equal to c in this view, starting at position
202f6f42af0SSchrodinger ZHU Yifan   // From.
203f6f42af0SSchrodinger ZHU Yifan   LIBC_INLINE constexpr size_t find_first_not_of(const char c,
204f6f42af0SSchrodinger ZHU Yifan                                                  size_t From = 0) const {
205f6f42af0SSchrodinger ZHU Yifan     for (size_t Pos = From; Pos < size(); ++Pos)
206f6f42af0SSchrodinger ZHU Yifan       if ((*this)[Pos] != c)
207f6f42af0SSchrodinger ZHU Yifan         return Pos;
208f6f42af0SSchrodinger ZHU Yifan     return npos;
209f6f42af0SSchrodinger ZHU Yifan   }
210f6f42af0SSchrodinger ZHU Yifan 
211f6f42af0SSchrodinger ZHU Yifan   // Check if this view contains the given character.
212f6f42af0SSchrodinger ZHU Yifan   LIBC_INLINE constexpr bool contains(char c) const {
213f6f42af0SSchrodinger ZHU Yifan     return find_first_of(c) != npos;
214f6f42af0SSchrodinger ZHU Yifan   }
215aa59c981SGuillaume Chatelet };
216aa59c981SGuillaume Chatelet 
217aa59c981SGuillaume Chatelet } // namespace cpp
2185ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
219aa59c981SGuillaume Chatelet 
220270547f3SGuillaume Chatelet #endif // LLVM_LIBC_SRC___SUPPORT_CPP_STRING_VIEW_H
221