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