1193323Sed//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file defines the SmallString class.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed#ifndef LLVM_ADT_SMALLSTRING_H
15193323Sed#define LLVM_ADT_SMALLSTRING_H
16193323Sed
17193323Sed#include "llvm/ADT/SmallVector.h"
18198090Srdivacky#include "llvm/ADT/StringRef.h"
19193323Sed
20193323Sednamespace llvm {
21193323Sed
22193323Sed/// SmallString - A SmallString is just a SmallVector with methods and accessors
23193323Sed/// that make it work better as a string (e.g. operator+ etc).
24193323Sedtemplate<unsigned InternalLen>
25193323Sedclass SmallString : public SmallVector<char, InternalLen> {
26193323Sedpublic:
27234353Sdim  /// Default ctor - Initialize to empty.
28193323Sed  SmallString() {}
29193323Sed
30234353Sdim  /// Initialize from a StringRef.
31218893Sdim  SmallString(StringRef S) : SmallVector<char, InternalLen>(S.begin(), S.end()) {}
32218893Sdim
33234353Sdim  /// Initialize with a range.
34193323Sed  template<typename ItTy>
35193323Sed  SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {}
36193323Sed
37234353Sdim  /// Copy ctor.
38193323Sed  SmallString(const SmallString &RHS) : SmallVector<char, InternalLen>(RHS) {}
39193323Sed
40234353Sdim  // Note that in order to add new overloads for append & assign, we have to
41234353Sdim  // duplicate the inherited versions so as not to inadvertently hide them.
42193323Sed
43234353Sdim  /// @}
44234353Sdim  /// @name String Assignment
45234353Sdim  /// @{
46234353Sdim
47243830Sdim  /// Assign from a repeated element.
48239462Sdim  void assign(size_t NumElts, char Elt) {
49234353Sdim    this->SmallVectorImpl<char>::assign(NumElts, Elt);
50234353Sdim  }
51234353Sdim
52243830Sdim  /// Assign from an iterator pair.
53234353Sdim  template<typename in_iter>
54234353Sdim  void assign(in_iter S, in_iter E) {
55234353Sdim    this->clear();
56234353Sdim    SmallVectorImpl<char>::append(S, E);
57234353Sdim  }
58234353Sdim
59243830Sdim  /// Assign from a StringRef.
60234353Sdim  void assign(StringRef RHS) {
61234353Sdim    this->clear();
62234353Sdim    SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
63234353Sdim  }
64234353Sdim
65243830Sdim  /// Assign from a SmallVector.
66234353Sdim  void assign(const SmallVectorImpl<char> &RHS) {
67234353Sdim    this->clear();
68234353Sdim    SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
69234353Sdim  }
70234353Sdim
71234353Sdim  /// @}
72234353Sdim  /// @name String Concatenation
73234353Sdim  /// @{
74234353Sdim
75243830Sdim  /// Append from an iterator pair.
76234353Sdim  template<typename in_iter>
77234353Sdim  void append(in_iter S, in_iter E) {
78234353Sdim    SmallVectorImpl<char>::append(S, E);
79234353Sdim  }
80249423Sdim
81239462Sdim  void append(size_t NumInputs, char Elt) {
82239462Sdim    SmallVectorImpl<char>::append(NumInputs, Elt);
83239462Sdim  }
84234353Sdim
85239462Sdim
86243830Sdim  /// Append from a StringRef.
87234353Sdim  void append(StringRef RHS) {
88234353Sdim    SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
89234353Sdim  }
90234353Sdim
91243830Sdim  /// Append from a SmallVector.
92234353Sdim  void append(const SmallVectorImpl<char> &RHS) {
93234353Sdim    SmallVectorImpl<char>::append(RHS.begin(), RHS.end());
94234353Sdim  }
95234353Sdim
96234353Sdim  /// @}
97234353Sdim  /// @name String Comparison
98234353Sdim  /// @{
99234353Sdim
100243830Sdim  /// Check for string equality.  This is more efficient than compare() when
101243830Sdim  /// the relative ordering of inequal strings isn't needed.
102234353Sdim  bool equals(StringRef RHS) const {
103234353Sdim    return str().equals(RHS);
104234353Sdim  }
105234353Sdim
106243830Sdim  /// Check for string equality, ignoring case.
107234353Sdim  bool equals_lower(StringRef RHS) const {
108234353Sdim    return str().equals_lower(RHS);
109234353Sdim  }
110234353Sdim
111243830Sdim  /// Compare two strings; the result is -1, 0, or 1 if this string is
112243830Sdim  /// lexicographically less than, equal to, or greater than the \p RHS.
113234353Sdim  int compare(StringRef RHS) const {
114234353Sdim    return str().compare(RHS);
115234353Sdim  }
116234353Sdim
117234353Sdim  /// compare_lower - Compare two strings, ignoring case.
118234353Sdim  int compare_lower(StringRef RHS) const {
119234353Sdim    return str().compare_lower(RHS);
120234353Sdim  }
121234353Sdim
122234353Sdim  /// compare_numeric - Compare two strings, treating sequences of digits as
123234353Sdim  /// numbers.
124234353Sdim  int compare_numeric(StringRef RHS) const {
125234353Sdim    return str().compare_numeric(RHS);
126234353Sdim  }
127234353Sdim
128234353Sdim  /// @}
129234353Sdim  /// @name String Predicates
130234353Sdim  /// @{
131234353Sdim
132243830Sdim  /// startswith - Check if this string starts with the given \p Prefix.
133234353Sdim  bool startswith(StringRef Prefix) const {
134234353Sdim    return str().startswith(Prefix);
135234353Sdim  }
136234353Sdim
137243830Sdim  /// endswith - Check if this string ends with the given \p Suffix.
138234353Sdim  bool endswith(StringRef Suffix) const {
139234353Sdim    return str().endswith(Suffix);
140234353Sdim  }
141234353Sdim
142234353Sdim  /// @}
143234353Sdim  /// @name String Searching
144234353Sdim  /// @{
145234353Sdim
146243830Sdim  /// find - Search for the first character \p C in the string.
147234353Sdim  ///
148243830Sdim  /// \return - The index of the first occurrence of \p C, or npos if not
149234353Sdim  /// found.
150234353Sdim  size_t find(char C, size_t From = 0) const {
151234353Sdim    return str().find(C, From);
152234353Sdim  }
153234353Sdim
154243830Sdim  /// Search for the first string \p Str in the string.
155234353Sdim  ///
156243830Sdim  /// \returns The index of the first occurrence of \p Str, or npos if not
157234353Sdim  /// found.
158234353Sdim  size_t find(StringRef Str, size_t From = 0) const {
159234353Sdim    return str().find(Str, From);
160234353Sdim  }
161234353Sdim
162243830Sdim  /// Search for the last character \p C in the string.
163234353Sdim  ///
164243830Sdim  /// \returns The index of the last occurrence of \p C, or npos if not
165234353Sdim  /// found.
166234353Sdim  size_t rfind(char C, size_t From = StringRef::npos) const {
167234353Sdim    return str().rfind(C, From);
168234353Sdim  }
169234353Sdim
170243830Sdim  /// Search for the last string \p Str in the string.
171234353Sdim  ///
172243830Sdim  /// \returns The index of the last occurrence of \p Str, or npos if not
173234353Sdim  /// found.
174234353Sdim  size_t rfind(StringRef Str) const {
175234353Sdim    return str().rfind(Str);
176234353Sdim  }
177234353Sdim
178243830Sdim  /// Find the first character in the string that is \p C, or npos if not
179243830Sdim  /// found. Same as find.
180234353Sdim  size_t find_first_of(char C, size_t From = 0) const {
181234353Sdim    return str().find_first_of(C, From);
182234353Sdim  }
183234353Sdim
184243830Sdim  /// Find the first character in the string that is in \p Chars, or npos if
185243830Sdim  /// not found.
186234353Sdim  ///
187243830Sdim  /// Complexity: O(size() + Chars.size())
188234353Sdim  size_t find_first_of(StringRef Chars, size_t From = 0) const {
189234353Sdim    return str().find_first_of(Chars, From);
190234353Sdim  }
191234353Sdim
192243830Sdim  /// Find the first character in the string that is not \p C or npos if not
193243830Sdim  /// found.
194234353Sdim  size_t find_first_not_of(char C, size_t From = 0) const {
195234353Sdim    return str().find_first_not_of(C, From);
196234353Sdim  }
197234353Sdim
198243830Sdim  /// Find the first character in the string that is not in the string
199243830Sdim  /// \p Chars, or npos if not found.
200234353Sdim  ///
201243830Sdim  /// Complexity: O(size() + Chars.size())
202234353Sdim  size_t find_first_not_of(StringRef Chars, size_t From = 0) const {
203234353Sdim    return str().find_first_not_of(Chars, From);
204234353Sdim  }
205234353Sdim
206243830Sdim  /// Find the last character in the string that is \p C, or npos if not
207243830Sdim  /// found.
208234353Sdim  size_t find_last_of(char C, size_t From = StringRef::npos) const {
209234353Sdim    return str().find_last_of(C, From);
210234353Sdim  }
211234353Sdim
212243830Sdim  /// Find the last character in the string that is in \p C, or npos if not
213243830Sdim  /// found.
214234353Sdim  ///
215243830Sdim  /// Complexity: O(size() + Chars.size())
216234353Sdim  size_t find_last_of(
217234353Sdim      StringRef Chars, size_t From = StringRef::npos) const {
218234353Sdim    return str().find_last_of(Chars, From);
219234353Sdim  }
220234353Sdim
221234353Sdim  /// @}
222234353Sdim  /// @name Helpful Algorithms
223234353Sdim  /// @{
224234353Sdim
225243830Sdim  /// Return the number of occurrences of \p C in the string.
226234353Sdim  size_t count(char C) const {
227234353Sdim    return str().count(C);
228234353Sdim  }
229234353Sdim
230243830Sdim  /// Return the number of non-overlapped occurrences of \p Str in the
231243830Sdim  /// string.
232234353Sdim  size_t count(StringRef Str) const {
233234353Sdim    return str().count(Str);
234234353Sdim  }
235234353Sdim
236234353Sdim  /// @}
237234353Sdim  /// @name Substring Operations
238234353Sdim  /// @{
239234353Sdim
240243830Sdim  /// Return a reference to the substring from [Start, Start + N).
241234353Sdim  ///
242243830Sdim  /// \param Start The index of the starting character in the substring; if
243234353Sdim  /// the index is npos or greater than the length of the string then the
244234353Sdim  /// empty substring will be returned.
245234353Sdim  ///
246243830Sdim  /// \param N The number of characters to included in the substring. If \p N
247234353Sdim  /// exceeds the number of characters remaining in the string, the string
248243830Sdim  /// suffix (starting with \p Start) will be returned.
249234353Sdim  StringRef substr(size_t Start, size_t N = StringRef::npos) const {
250234353Sdim    return str().substr(Start, N);
251234353Sdim  }
252234353Sdim
253243830Sdim  /// Return a reference to the substring from [Start, End).
254234353Sdim  ///
255243830Sdim  /// \param Start The index of the starting character in the substring; if
256234353Sdim  /// the index is npos or greater than the length of the string then the
257234353Sdim  /// empty substring will be returned.
258234353Sdim  ///
259243830Sdim  /// \param End The index following the last character to include in the
260243830Sdim  /// substring. If this is npos, or less than \p Start, or exceeds the
261234353Sdim  /// number of characters remaining in the string, the string suffix
262243830Sdim  /// (starting with \p Start) will be returned.
263234353Sdim  StringRef slice(size_t Start, size_t End) const {
264234353Sdim    return str().slice(Start, End);
265234353Sdim  }
266234353Sdim
267193323Sed  // Extra methods.
268234353Sdim
269243830Sdim  /// Explicit conversion to StringRef.
270198090Srdivacky  StringRef str() const { return StringRef(this->begin(), this->size()); }
271198090Srdivacky
272218893Sdim  // TODO: Make this const, if it's safe...
273218893Sdim  const char* c_str() {
274198090Srdivacky    this->push_back(0);
275198090Srdivacky    this->pop_back();
276198090Srdivacky    return this->data();
277193323Sed  }
278199989Srdivacky
279234353Sdim  /// Implicit conversion to StringRef.
280218893Sdim  operator StringRef() const { return str(); }
281218893Sdim
282193323Sed  // Extra operators.
283198090Srdivacky  const SmallString &operator=(StringRef RHS) {
284193323Sed    this->clear();
285193323Sed    return *this += RHS;
286193323Sed  }
287193323Sed
288198090Srdivacky  SmallString &operator+=(StringRef RHS) {
289198090Srdivacky    this->append(RHS.begin(), RHS.end());
290193323Sed    return *this;
291193323Sed  }
292193323Sed  SmallString &operator+=(char C) {
293193323Sed    this->push_back(C);
294193323Sed    return *this;
295193323Sed  }
296193323Sed};
297193323Sed
298193323Sed}
299193323Sed
300193323Sed#endif
301