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 // 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 20 namespace 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). 24 template<unsigned InternalLen> 25 class SmallString : public SmallVector<char, InternalLen> { 26 public: 27 /// Default ctor - Initialize to empty. 28 SmallString() = default; 29 30 /// Initialize from a StringRef. SmallString(StringRef S)31 SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {} 32 33 /// Initialize by concatenating a list of StringRefs. SmallString(std::initializer_list<StringRef> Refs)34 SmallString(std::initializer_list<StringRef> Refs) 35 : SmallVector<char, InternalLen>() { 36 this->append(Refs); 37 } 38 39 /// Initialize with a range. 40 template<typename ItTy> SmallString(ItTy S,ItTy E)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. assign(size_t NumElts,char Elt)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> assign(in_iter S,in_iter E)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. assign(StringRef RHS)63 void assign(StringRef RHS) { 64 this->clear(); 65 SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); 66 } 67 68 /// Assign from a SmallVector. assign(const SmallVectorImpl<char> & RHS)69 void assign(const SmallVectorImpl<char> &RHS) { 70 this->clear(); 71 SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); 72 } 73 74 /// Assign from a list of StringRefs. assign(std::initializer_list<StringRef> Refs)75 void assign(std::initializer_list<StringRef> Refs) { 76 this->clear(); 77 append(Refs); 78 } 79 80 /// @} 81 /// @name String Concatenation 82 /// @{ 83 84 /// Append from an iterator pair. 85 template<typename in_iter> append(in_iter S,in_iter E)86 void append(in_iter S, in_iter E) { 87 SmallVectorImpl<char>::append(S, E); 88 } 89 append(size_t NumInputs,char Elt)90 void append(size_t NumInputs, char Elt) { 91 SmallVectorImpl<char>::append(NumInputs, Elt); 92 } 93 94 /// Append from a StringRef. append(StringRef RHS)95 void append(StringRef RHS) { 96 SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); 97 } 98 99 /// Append from a SmallVector. append(const SmallVectorImpl<char> & RHS)100 void append(const SmallVectorImpl<char> &RHS) { 101 SmallVectorImpl<char>::append(RHS.begin(), RHS.end()); 102 } 103 104 /// Append from a list of StringRefs. append(std::initializer_list<StringRef> Refs)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 118 /// @} 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. equals(StringRef RHS)124 bool equals(StringRef RHS) const { 125 return str().equals(RHS); 126 } 127 128 /// Check for string equality, ignoring case. equals_lower(StringRef RHS)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. compare(StringRef RHS)135 int compare(StringRef RHS) const { 136 return str().compare(RHS); 137 } 138 139 /// compare_lower - Compare two strings, ignoring case. compare_lower(StringRef RHS)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. compare_numeric(StringRef RHS)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. startswith(StringRef 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. endswith(StringRef 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. rfind(StringRef Str)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. count(char C)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. count(StringRef Str)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. slice(size_t Start,size_t End)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. str()292 StringRef str() const { return StringRef(this->data(), this->size()); } 293 294 // TODO: Make this const, if it's safe... c_str()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. StringRef()302 operator StringRef() const { return str(); } 303 string()304 explicit operator std::string() const { 305 return std::string(this->data(), this->size()); 306 } 307 308 // Extra operators. 309 SmallString &operator=(StringRef RHS) { 310 this->assign(RHS); 311 return *this; 312 } 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 327