• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
operator <<(std::ostream & o,const StringPiece & piece)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 
operator ==(const StringPiece & x,const StringPiece & y)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 
CopyToString(std::string * target) const28 void StringPiece::CopyToString(std::string* target) const {
29   target->assign(!empty() ? data() : "", size());
30 }
31 
AppendToString(std::string * target) const32 void StringPiece::AppendToString(std::string* target) const {
33   if (!empty())
34     target->append(data(), size());
35 }
36 
copy(char * buf,size_type n,size_type pos) const37 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 
find(const StringPiece & s,size_type pos) const43 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 
find(char c,size_type pos) const53 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 
rfind(const StringPiece & s,size_type pos) const61 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 
rfind(char c,size_type pos) const73 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]
BuildLookupTable(const StringPiece & characters_wanted,bool * table)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 
find_first_of(const StringPiece & s,size_type pos) const103 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 
find_first_not_of(const StringPiece & s,size_type pos) const122 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 
find_first_not_of(char c,size_type pos) const144 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 
find_last_of(const StringPiece & s,size_type pos) const156 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 
find_last_not_of(const StringPiece & s,size_type pos) const175 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 
find_last_not_of(char c,size_type pos) const199 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 
substr(size_type pos,size_type n) const212 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