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