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