blob: c0e8fcd29461509bacd8cc9678a8d3f6556ac8f9 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the SmallString class.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_ADT_SMALLSTRING_H
14#define LLVM_ADT_SMALLSTRING_H
15
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/StringRef.h"
18#include <cstddef>
19
20namespace llvm {
21
22/// SmallString - A SmallString is just a SmallVector with methods and accessors
23/// that make it work better as a string (e.g. operator+ etc).
24template<unsigned InternalLen>
25class SmallString : public SmallVector<char, InternalLen> {
26public:
27 /// Default ctor - Initialize to empty.
28 SmallString() = default;
29
30 /// Initialize from a StringRef.
31 SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {}
32
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020033 /// Initialize by concatenating a list of StringRefs.
34 SmallString(std::initializer_list<StringRef> Refs)
35 : SmallVector<char, InternalLen>() {
36 this->append(Refs);
37 }
38
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010039 /// Initialize with a range.
40 template<typename ItTy>
41 SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {}
42
43 // Note that in order to add new overloads for append & assign, we have to
44 // duplicate the inherited versions so as not to inadvertently hide them.
45
46 /// @}
47 /// @name String Assignment
48 /// @{
49
50 /// Assign from a repeated element.
51 void assign(size_t NumElts, char Elt) {
52 this->SmallVectorImpl<char>::assign(NumElts, Elt);
53 }
54
55 /// Assign from an iterator pair.
56 template<typename in_iter>
57 void assign(in_iter S, in_iter E) {
58 this->clear();
59 SmallVectorImpl<char>::append(S, E);
60 }
61
62 /// Assign from a StringRef.
63 void assign(StringRef RHS) {
64 this->clear();
65 SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
66 }
67
68 /// Assign from a SmallVector.
69 void assign(const SmallVectorImpl<char> &RHS) {
70 this->clear();
71 SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
72 }
73
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020074 /// Assign from a list of StringRefs.
75 void assign(std::initializer_list<StringRef> Refs) {
76 this->clear();
77 append(Refs);
78 }
79
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010080 /// @}
81 /// @name String Concatenation
82 /// @{
83
84 /// Append from an iterator pair.
85 template<typename in_iter>
86 void append(in_iter S, in_iter E) {
87 SmallVectorImpl<char>::append(S, E);
88 }
89
90 void append(size_t NumInputs, char Elt) {
91 SmallVectorImpl<char>::append(NumInputs, Elt);
92 }
93
94 /// Append from a StringRef.
95 void append(StringRef RHS) {
96 SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
97 }
98
99 /// Append from a SmallVector.
100 void append(const SmallVectorImpl<char> &RHS) {
101 SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
102 }
103
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200104 /// Append from a list of StringRefs.
105 void append(std::initializer_list<StringRef> Refs) {
106 size_t SizeNeeded = this->size();
107 for (const StringRef &Ref : Refs)
108 SizeNeeded += Ref.size();
109 this->reserve(SizeNeeded);
110 auto CurEnd = this->end();
111 for (const StringRef &Ref : Refs) {
112 this->uninitialized_copy(Ref.begin(), Ref.end(), CurEnd);
113 CurEnd += Ref.size();
114 }
115 this->set_size(SizeNeeded);
116 }
117
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100118 /// @}
119 /// @name String Comparison
120 /// @{
121
122 /// Check for string equality. This is more efficient than compare() when
123 /// the relative ordering of inequal strings isn't needed.
124 bool equals(StringRef RHS) const {
125 return str().equals(RHS);
126 }
127
128 /// Check for string equality, ignoring case.
129 bool equals_lower(StringRef RHS) const {
130 return str().equals_lower(RHS);
131 }
132
133 /// Compare two strings; the result is -1, 0, or 1 if this string is
134 /// lexicographically less than, equal to, or greater than the \p RHS.
135 int compare(StringRef RHS) const {
136 return str().compare(RHS);
137 }
138
139 /// compare_lower - Compare two strings, ignoring case.
140 int compare_lower(StringRef RHS) const {
141 return str().compare_lower(RHS);
142 }
143
144 /// compare_numeric - Compare two strings, treating sequences of digits as
145 /// numbers.
146 int compare_numeric(StringRef RHS) const {
147 return str().compare_numeric(RHS);
148 }
149
150 /// @}
151 /// @name String Predicates
152 /// @{
153
154 /// startswith - Check if this string starts with the given \p Prefix.
155 bool startswith(StringRef Prefix) const {
156 return str().startswith(Prefix);
157 }
158
159 /// endswith - Check if this string ends with the given \p Suffix.
160 bool endswith(StringRef Suffix) const {
161 return str().endswith(Suffix);
162 }
163
164 /// @}
165 /// @name String Searching
166 /// @{
167
168 /// find - Search for the first character \p C in the string.
169 ///
170 /// \return - The index of the first occurrence of \p C, or npos if not
171 /// found.
172 size_t find(char C, size_t From = 0) const {
173 return str().find(C, From);
174 }
175
176 /// Search for the first string \p Str in the string.
177 ///
178 /// \returns The index of the first occurrence of \p Str, or npos if not
179 /// found.
180 size_t find(StringRef Str, size_t From = 0) const {
181 return str().find(Str, From);
182 }
183
184 /// Search for the last character \p C in the string.
185 ///
186 /// \returns The index of the last occurrence of \p C, or npos if not
187 /// found.
188 size_t rfind(char C, size_t From = StringRef::npos) const {
189 return str().rfind(C, From);
190 }
191
192 /// Search for the last string \p Str in the string.
193 ///
194 /// \returns The index of the last occurrence of \p Str, or npos if not
195 /// found.
196 size_t rfind(StringRef Str) const {
197 return str().rfind(Str);
198 }
199
200 /// Find the first character in the string that is \p C, or npos if not
201 /// found. Same as find.
202 size_t find_first_of(char C, size_t From = 0) const {
203 return str().find_first_of(C, From);
204 }
205
206 /// Find the first character in the string that is in \p Chars, or npos if
207 /// not found.
208 ///
209 /// Complexity: O(size() + Chars.size())
210 size_t find_first_of(StringRef Chars, size_t From = 0) const {
211 return str().find_first_of(Chars, From);
212 }
213
214 /// Find the first character in the string that is not \p C or npos if not
215 /// found.
216 size_t find_first_not_of(char C, size_t From = 0) const {
217 return str().find_first_not_of(C, From);
218 }
219
220 /// Find the first character in the string that is not in the string
221 /// \p Chars, or npos if not found.
222 ///
223 /// Complexity: O(size() + Chars.size())
224 size_t find_first_not_of(StringRef Chars, size_t From = 0) const {
225 return str().find_first_not_of(Chars, From);
226 }
227
228 /// Find the last character in the string that is \p C, or npos if not
229 /// found.
230 size_t find_last_of(char C, size_t From = StringRef::npos) const {
231 return str().find_last_of(C, From);
232 }
233
234 /// Find the last character in the string that is in \p C, or npos if not
235 /// found.
236 ///
237 /// Complexity: O(size() + Chars.size())
238 size_t find_last_of(
239 StringRef Chars, size_t From = StringRef::npos) const {
240 return str().find_last_of(Chars, From);
241 }
242
243 /// @}
244 /// @name Helpful Algorithms
245 /// @{
246
247 /// Return the number of occurrences of \p C in the string.
248 size_t count(char C) const {
249 return str().count(C);
250 }
251
252 /// Return the number of non-overlapped occurrences of \p Str in the
253 /// string.
254 size_t count(StringRef Str) const {
255 return str().count(Str);
256 }
257
258 /// @}
259 /// @name Substring Operations
260 /// @{
261
262 /// Return a reference to the substring from [Start, Start + N).
263 ///
264 /// \param Start The index of the starting character in the substring; if
265 /// the index is npos or greater than the length of the string then the
266 /// empty substring will be returned.
267 ///
268 /// \param N The number of characters to included in the substring. If \p N
269 /// exceeds the number of characters remaining in the string, the string
270 /// suffix (starting with \p Start) will be returned.
271 StringRef substr(size_t Start, size_t N = StringRef::npos) const {
272 return str().substr(Start, N);
273 }
274
275 /// Return a reference to the substring from [Start, End).
276 ///
277 /// \param Start The index of the starting character in the substring; if
278 /// the index is npos or greater than the length of the string then the
279 /// empty substring will be returned.
280 ///
281 /// \param End The index following the last character to include in the
282 /// substring. If this is npos, or less than \p Start, or exceeds the
283 /// number of characters remaining in the string, the string suffix
284 /// (starting with \p Start) will be returned.
285 StringRef slice(size_t Start, size_t End) const {
286 return str().slice(Start, End);
287 }
288
289 // Extra methods.
290
291 /// Explicit conversion to StringRef.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200292 StringRef str() const { return StringRef(this->data(), this->size()); }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100293
294 // TODO: Make this const, if it's safe...
295 const char* c_str() {
296 this->push_back(0);
297 this->pop_back();
298 return this->data();
299 }
300
301 /// Implicit conversion to StringRef.
302 operator StringRef() const { return str(); }
303
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200304 explicit operator std::string() const {
305 return std::string(this->data(), this->size());
306 }
307
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100308 // Extra operators.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200309 SmallString &operator=(StringRef RHS) {
310 this->assign(RHS);
311 return *this;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100312 }
313
314 SmallString &operator+=(StringRef RHS) {
315 this->append(RHS.begin(), RHS.end());
316 return *this;
317 }
318 SmallString &operator+=(char C) {
319 this->push_back(C);
320 return *this;
321 }
322};
323
324} // end namespace llvm
325
326#endif // LLVM_ADT_SMALLSTRING_H