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