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