Home | History | Annotate | Download | only in strings
      1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 // Copied from strings/stringpiece.cc with modifications
      5 
      6 #include <algorithm>
      7 #include <ostream>
      8 
      9 #include "phonenumbers/base/strings/string_piece.h"
     10 
     11 namespace i18n {
     12 namespace phonenumbers {
     13 
     14 typedef StringPiece::size_type size_type;
     15 
     16 std::ostream& operator<<(std::ostream& o, const StringPiece& piece) {
     17   o.write(piece.data(), static_cast<std::streamsize>(piece.size()));
     18   return o;
     19 }
     20 
     21 bool operator==(const StringPiece& x, const StringPiece& y) {
     22   if (x.size() != y.size())
     23     return false;
     24 
     25   return StringPiece::wordmemcmp(x.data(), y.data(), x.size()) == 0;
     26 }
     27 
     28 void StringPiece::CopyToString(std::string* target) const {
     29   target->assign(!empty() ? data() : "", size());
     30 }
     31 
     32 void StringPiece::AppendToString(std::string* target) const {
     33   if (!empty())
     34     target->append(data(), size());
     35 }
     36 
     37 size_type StringPiece::copy(char* buf, size_type n, size_type pos) const {
     38   size_type ret = std::min(length_ - pos, n);
     39   memcpy(buf, ptr_ + pos, ret);
     40   return ret;
     41 }
     42 
     43 size_type StringPiece::find(const StringPiece& s, size_type pos) const {
     44   if (pos > length_)
     45     return npos;
     46 
     47   const char* result = std::search(ptr_ + pos, ptr_ + length_,
     48                                    s.ptr_, s.ptr_ + s.length_);
     49   const size_type xpos = result - ptr_;
     50   return xpos + s.length_ <= length_ ? xpos : npos;
     51 }
     52 
     53 size_type StringPiece::find(char c, size_type pos) const {
     54   if (pos >= length_)
     55     return npos;
     56 
     57   const char* result = std::find(ptr_ + pos, ptr_ + length_, c);
     58   return result != ptr_ + length_ ? static_cast<size_t>(result - ptr_) : npos;
     59 }
     60 
     61 size_type StringPiece::rfind(const StringPiece& s, size_type pos) const {
     62   if (length_ < s.length_)
     63     return npos;
     64 
     65   if (s.empty())
     66     return std::min(length_, pos);
     67 
     68   const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_;
     69   const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
     70   return result != last ? static_cast<size_t>(result - ptr_) : npos;
     71 }
     72 
     73 size_type StringPiece::rfind(char c, size_type pos) const {
     74   if (length_ == 0)
     75     return npos;
     76 
     77   for (size_type i = std::min(pos, length_ - 1); ; --i) {
     78     if (ptr_[i] == c)
     79       return i;
     80     if (i == 0)
     81       break;
     82   }
     83   return npos;
     84 }
     85 
     86 // For each character in characters_wanted, sets the index corresponding
     87 // to the ASCII code of that character to 1 in table.  This is used by
     88 // the find_.*_of methods below to tell whether or not a character is in
     89 // the lookup table in constant time.
     90 // The argument `table' must be an array that is large enough to hold all
     91 // the possible values of an unsigned char.  Thus it should be be declared
     92 // as follows:
     93 //   bool table[UCHAR_MAX + 1]
     94 static inline void BuildLookupTable(const StringPiece& characters_wanted,
     95                                     bool* table) {
     96   const size_type length = characters_wanted.length();
     97   const char* const data = characters_wanted.data();
     98   for (size_type i = 0; i < length; ++i) {
     99     table[static_cast<unsigned char>(data[i])] = true;
    100   }
    101 }
    102 
    103 size_type StringPiece::find_first_of(const StringPiece& s,
    104                                      size_type pos) const {
    105   if (length_ == 0 || s.length_ == 0)
    106     return npos;
    107 
    108   // Avoid the cost of BuildLookupTable() for a single-character search.
    109   if (s.length_ == 1)
    110     return find_first_of(s.ptr_[0], pos);
    111 
    112   bool lookup[UCHAR_MAX + 1] = { false };
    113   BuildLookupTable(s, lookup);
    114   for (size_type i = pos; i < length_; ++i) {
    115     if (lookup[static_cast<unsigned char>(ptr_[i])]) {
    116       return i;
    117     }
    118   }
    119   return npos;
    120 }
    121 
    122 size_type StringPiece::find_first_not_of(const StringPiece& s,
    123                                          size_type pos) const {
    124   if (length_ == 0)
    125     return npos;
    126 
    127   if (s.length_ == 0)
    128     return 0;
    129 
    130   // Avoid the cost of BuildLookupTable() for a single-character search.
    131   if (s.length_ == 1)
    132     return find_first_not_of(s.ptr_[0], pos);
    133 
    134   bool lookup[UCHAR_MAX + 1] = { false };
    135   BuildLookupTable(s, lookup);
    136   for (size_type i = pos; i < length_; ++i) {
    137     if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
    138       return i;
    139     }
    140   }
    141   return npos;
    142 }
    143 
    144 size_type StringPiece::find_first_not_of(char c, size_type pos) const {
    145   if (length_ == 0)
    146     return npos;
    147 
    148   for (; pos < length_; ++pos) {
    149     if (ptr_[pos] != c) {
    150       return pos;
    151     }
    152   }
    153   return npos;
    154 }
    155 
    156 size_type StringPiece::find_last_of(const StringPiece& s, size_type pos) const {
    157   if (length_ == 0 || s.length_ == 0)
    158     return npos;
    159 
    160   // Avoid the cost of BuildLookupTable() for a single-character search.
    161   if (s.length_ == 1)
    162     return find_last_of(s.ptr_[0], pos);
    163 
    164   bool lookup[UCHAR_MAX + 1] = { false };
    165   BuildLookupTable(s, lookup);
    166   for (size_type i = std::min(pos, length_ - 1); ; --i) {
    167     if (lookup[static_cast<unsigned char>(ptr_[i])])
    168       return i;
    169     if (i == 0)
    170       break;
    171   }
    172   return npos;
    173 }
    174 
    175 size_type StringPiece::find_last_not_of(const StringPiece& s,
    176                                         size_type pos) const {
    177   if (length_ == 0)
    178     return npos;
    179 
    180   size_type i = std::min(pos, length_ - 1);
    181   if (s.length_ == 0)
    182     return i;
    183 
    184   // Avoid the cost of BuildLookupTable() for a single-character search.
    185   if (s.length_ == 1)
    186     return find_last_not_of(s.ptr_[0], pos);
    187 
    188   bool lookup[UCHAR_MAX + 1] = { false };
    189   BuildLookupTable(s, lookup);
    190   for (; ; --i) {
    191     if (!lookup[static_cast<unsigned char>(ptr_[i])])
    192       return i;
    193     if (i == 0)
    194       break;
    195   }
    196   return npos;
    197 }
    198 
    199 size_type StringPiece::find_last_not_of(char c, size_type pos) const {
    200   if (length_ == 0)
    201     return npos;
    202 
    203   for (size_type i = std::min(pos, length_ - 1); ; --i) {
    204     if (ptr_[i] != c)
    205       return i;
    206     if (i == 0)
    207       break;
    208   }
    209   return npos;
    210 }
    211 
    212 StringPiece StringPiece::substr(size_type pos, size_type n) const {
    213   if (pos > length_) pos = length_;
    214   if (n > length_ - pos) n = length_ - pos;
    215   return StringPiece(ptr_ + pos, n);
    216 }
    217 
    218 const StringPiece::size_type StringPiece::npos = size_type(-1);
    219 
    220 }  // namespace phonenumbers
    221 }  // namespace i18n
    222