• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2011 The Libphonenumber Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Author: Philippe Liard
16 
17 #include <algorithm>
18 #include <cassert>
19 #include <cstring>
20 #include <sstream>
21 
22 #include "phonenumbers/stringutil.h"
23 
24 namespace i18n {
25 namespace phonenumbers {
26 
27 using std::equal;
28 using std::stringstream;
29 
operator +(const string & s,int n)30 string operator+(const string& s, int n) {  // NOLINT(runtime/string)
31   stringstream stream;
32 
33   stream << s << n;
34   string result;
35   stream >> result;
36 
37   return result;
38 }
39 
40 template <typename T>
GenericSimpleItoa(const T & n)41 string GenericSimpleItoa(const T& n) {
42   stringstream stream;
43 
44   stream << n;
45   string result;
46   stream >> result;
47 
48   return result;
49 }
50 
SimpleItoa(int n)51 string SimpleItoa(int n) {
52   return GenericSimpleItoa(n);
53 }
54 
SimpleItoa(uint64 n)55 string SimpleItoa(uint64 n) {
56   return GenericSimpleItoa(n);
57 }
58 
SimpleItoa(int64 n)59 string SimpleItoa(int64 n) {
60   return GenericSimpleItoa(n);
61 }
62 
HasPrefixString(const string & s,const string & prefix)63 bool HasPrefixString(const string& s, const string& prefix) {
64   return s.size() >= prefix.size() &&
65       equal(s.begin(), s.begin() + prefix.size(), prefix.begin());
66 }
67 
FindNth(const string & s,char c,int n)68 size_t FindNth(const string& s, char c, int n) {
69   size_t pos = string::npos;
70 
71   for (int i = 0; i < n; ++i) {
72     pos = s.find_first_of(c, pos + 1);
73     if (pos == string::npos) {
74       break;
75     }
76   }
77   return pos;
78 }
79 
SplitStringUsing(const string & s,const string & delimiter,vector<string> * result)80 void SplitStringUsing(const string& s, const string& delimiter,
81                       vector<string>* result) {
82   assert(result);
83   size_t start_pos = 0;
84   size_t find_pos = string::npos;
85   if (delimiter.empty()) {
86     return;
87   }
88   while ((find_pos = s.find(delimiter, start_pos)) != string::npos) {
89     const string substring = s.substr(start_pos, find_pos - start_pos);
90     if (!substring.empty()) {
91       result->push_back(substring);
92     }
93     start_pos = find_pos + delimiter.length();
94   }
95   if (start_pos != s.length()) {
96     result->push_back(s.substr(start_pos));
97   }
98 }
99 
StripString(string * s,const char * remove,char replacewith)100 void StripString(string* s, const char* remove, char replacewith) {
101   const char* str_start = s->c_str();
102   const char* str = str_start;
103   for (str = strpbrk(str, remove);
104        str != NULL;
105        str = strpbrk(str + 1, remove)) {
106     (*s)[str - str_start] = replacewith;
107   }
108 }
109 
TryStripPrefixString(const string & in,const string & prefix,string * out)110 bool TryStripPrefixString(const string& in, const string& prefix, string* out) {
111   assert(out);
112   const bool has_prefix = in.compare(0, prefix.length(), prefix) == 0;
113   out->assign(has_prefix ? in.substr(prefix.length()) : in);
114 
115   return has_prefix;
116 }
117 
HasSuffixString(const string & s,const string & suffix)118 bool HasSuffixString(const string& s, const string& suffix) {
119   if (s.length() < suffix.length()) {
120     return false;
121   }
122   return s.compare(s.length() - suffix.length(), suffix.length(), suffix) == 0;
123 }
124 
125 template <typename T>
GenericAtoi(const string & s,T * out)126 void GenericAtoi(const string& s, T* out) {
127   stringstream stream;
128   stream << s;
129   stream >> *out;
130 }
131 
safe_strto32(const string & s,int32 * n)132 void safe_strto32(const string& s, int32 *n) {
133   GenericAtoi(s, n);
134 }
135 
safe_strtou64(const string & s,uint64 * n)136 void safe_strtou64(const string& s, uint64 *n) {
137   GenericAtoi(s, n);
138 }
139 
safe_strto64(const string & s,int64 * n)140 void safe_strto64(const string& s, int64* n) {
141   GenericAtoi(s, n);
142 }
143 
strrmm(string * s,const string & chars)144 void strrmm(string* s, const string& chars) {
145   for (string::iterator it = s->begin(); it != s->end(); ) {
146     const char current_char = *it;
147     if (chars.find(current_char) != string::npos) {
148       it = s->erase(it);
149     } else {
150       ++it;
151     }
152   }
153 }
154 
GlobalReplaceSubstring(const string & substring,const string & replacement,string * s)155 int GlobalReplaceSubstring(const string& substring,
156                            const string& replacement,
157                            string* s) {
158   assert(s != NULL);
159   if (s->empty() || substring.empty())
160     return 0;
161   string tmp;
162   int num_replacements = 0;
163   int pos = 0;
164   for (size_t match_pos = s->find(substring.data(), pos, substring.length());
165        match_pos != string::npos;
166        pos = match_pos + substring.length(),
167           match_pos = s->find(substring.data(), pos, substring.length())) {
168     ++num_replacements;
169     // Append the original content before the match.
170     tmp.append(*s, pos, match_pos - pos);
171     // Append the replacement for the match.
172     tmp.append(replacement.begin(), replacement.end());
173   }
174   // Append the content after the last match.
175   tmp.append(*s, pos, s->length() - pos);
176   s->swap(tmp);
177   return num_replacements;
178 }
179 
180 // StringHolder class
181 
StringHolder(const string & s)182 StringHolder::StringHolder(const string& s)
183   : string_(&s),
184     cstring_(NULL),
185     len_(s.size())
186 {}
187 
StringHolder(const char * s)188 StringHolder::StringHolder(const char* s)
189   : string_(NULL),
190     cstring_(s),
191     len_(std::strlen(s))
192 {}
193 
StringHolder(uint64 n)194 StringHolder::StringHolder(uint64 n)
195   : converted_string_(SimpleItoa(n)),
196     string_(&converted_string_),
197     cstring_(NULL),
198     len_(converted_string_.length())
199 {}
200 
~StringHolder()201 StringHolder::~StringHolder() {}
202 
203 // StrCat
204 
205 // Implements s += sh; (s: string, sh: StringHolder)
operator +=(string & lhs,const StringHolder & rhs)206 string& operator+=(string& lhs, const StringHolder& rhs) {
207   const string* const s = rhs.GetString();
208   if (s) {
209     lhs += *s;
210   } else {
211     const char* const cs = rhs.GetCString();
212     if (cs)
213       lhs.append(cs, rhs.Length());
214   }
215   return lhs;
216 }
217 
StrCat(const StringHolder & s1,const StringHolder & s2)218 string StrCat(const StringHolder& s1, const StringHolder& s2) {
219   string result;
220   result.reserve(s1.Length() + s2.Length() + 1);
221 
222   result += s1;
223   result += s2;
224 
225   return result;
226 }
227 
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3)228 string StrCat(const StringHolder& s1, const StringHolder& s2,
229               const StringHolder& s3) {
230   string result;
231   result.reserve(s1.Length() + s2.Length() + s3.Length() + 1);
232 
233   result += s1;
234   result += s2;
235   result += s3;
236 
237   return result;
238 }
239 
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4)240 string StrCat(const StringHolder& s1, const StringHolder& s2,
241               const StringHolder& s3, const StringHolder& s4) {
242   string result;
243   result.reserve(s1.Length() + s2.Length() + s3.Length() + s4.Length() + 1);
244 
245   result += s1;
246   result += s2;
247   result += s3;
248   result += s4;
249 
250   return result;
251 }
252 
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5)253 string StrCat(const StringHolder& s1, const StringHolder& s2,
254               const StringHolder& s3, const StringHolder& s4,
255               const StringHolder& s5) {
256   string result;
257   result.reserve(s1.Length() + s2.Length() + s3.Length() + s4.Length() +
258                  s5.Length() + 1);
259   result += s1;
260   result += s2;
261   result += s3;
262   result += s4;
263   result += s5;
264 
265   return result;
266 }
267 
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5,const StringHolder & s6)268 string StrCat(const StringHolder& s1, const StringHolder& s2,
269               const StringHolder& s3, const StringHolder& s4,
270               const StringHolder& s5, const StringHolder& s6) {
271   string result;
272   result.reserve(s1.Length() + s2.Length() + s3.Length() + s4.Length() +
273                  s5.Length() + s6.Length() + 1);
274   result += s1;
275   result += s2;
276   result += s3;
277   result += s4;
278   result += s5;
279   result += s6;
280 
281   return result;
282 }
283 
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5,const StringHolder & s6,const StringHolder & s7)284 string StrCat(const StringHolder& s1, const StringHolder& s2,
285               const StringHolder& s3, const StringHolder& s4,
286               const StringHolder& s5, const StringHolder& s6,
287               const StringHolder& s7) {
288   string result;
289   result.reserve(s1.Length() + s2.Length() + s3.Length() + s4.Length() +
290                  s5.Length() + s6.Length() + s7.Length() + 1);
291   result += s1;
292   result += s2;
293   result += s3;
294   result += s4;
295   result += s5;
296   result += s6;
297   result += s7;
298 
299   return result;
300 }
301 
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5,const StringHolder & s6,const StringHolder & s7,const StringHolder & s8)302 string StrCat(const StringHolder& s1, const StringHolder& s2,
303               const StringHolder& s3, const StringHolder& s4,
304               const StringHolder& s5, const StringHolder& s6,
305               const StringHolder& s7, const StringHolder& s8) {
306   string result;
307   result.reserve(s1.Length() + s2.Length() + s3.Length() + s4.Length() +
308                  s5.Length() + s6.Length() + s7.Length() + s8.Length() + 1);
309   result += s1;
310   result += s2;
311   result += s3;
312   result += s4;
313   result += s5;
314   result += s6;
315   result += s7;
316   result += s8;
317 
318   return result;
319 }
320 
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5,const StringHolder & s6,const StringHolder & s7,const StringHolder & s8,const StringHolder & s9)321 string StrCat(const StringHolder& s1, const StringHolder& s2,
322               const StringHolder& s3, const StringHolder& s4,
323               const StringHolder& s5, const StringHolder& s6,
324               const StringHolder& s7, const StringHolder& s8,
325               const StringHolder& s9) {
326   string result;
327   result.reserve(s1.Length() + s2.Length() + s3.Length() + s4.Length() +
328                  s5.Length() + s6.Length() + s7.Length() + s8.Length() +
329                  s9.Length() + 1);
330   result += s1;
331   result += s2;
332   result += s3;
333   result += s4;
334   result += s5;
335   result += s6;
336   result += s7;
337   result += s8;
338   result += s9;
339 
340   return result;
341 }
342 
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5,const StringHolder & s6,const StringHolder & s7,const StringHolder & s8,const StringHolder & s9,const StringHolder & s10,const StringHolder & s11)343 string StrCat(const StringHolder& s1, const StringHolder& s2,
344               const StringHolder& s3, const StringHolder& s4,
345               const StringHolder& s5, const StringHolder& s6,
346               const StringHolder& s7, const StringHolder& s8,
347               const StringHolder& s9, const StringHolder& s10,
348               const StringHolder& s11) {
349   string result;
350   result.reserve(s1.Length() + s2.Length()  + s3.Length() + s4.Length() +
351                  s5.Length() + s6.Length()  + s7.Length() + s8.Length() +
352                  s9.Length() + s10.Length() + s11.Length());
353   result += s1;
354   result += s2;
355   result += s3;
356   result += s4;
357   result += s5;
358   result += s6;
359   result += s7;
360   result += s8;
361   result += s9;
362   result += s10;
363   result += s11;
364 
365   return result;
366 }
367 
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5,const StringHolder & s6,const StringHolder & s7,const StringHolder & s8,const StringHolder & s9,const StringHolder & s10,const StringHolder & s11,const StringHolder & s12)368 string StrCat(const StringHolder& s1, const StringHolder& s2,
369               const StringHolder& s3, const StringHolder& s4,
370               const StringHolder& s5, const StringHolder& s6,
371               const StringHolder& s7, const StringHolder& s8,
372               const StringHolder& s9, const StringHolder& s10,
373               const StringHolder& s11, const StringHolder& s12) {
374   string result;
375   result.reserve(s1.Length() + s2.Length()  + s3.Length() + s4.Length() +
376                  s5.Length() + s6.Length()  + s7.Length() + s8.Length() +
377                  s9.Length() + s10.Length() + s11.Length() + s12.Length());
378   result += s1;
379   result += s2;
380   result += s3;
381   result += s4;
382   result += s5;
383   result += s6;
384   result += s7;
385   result += s8;
386   result += s9;
387   result += s10;
388   result += s11;
389   result += s12;
390 
391   return result;
392 }
393 
394 // StrAppend
395 
StrAppend(string * dest,const StringHolder & s1)396 void StrAppend(string* dest, const StringHolder& s1) {
397   assert(dest);
398 
399   dest->reserve(dest->length() + s1.Length() + 1);
400   *dest += s1;
401 }
402 
StrAppend(string * dest,const StringHolder & s1,const StringHolder & s2)403 void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2) {
404   assert(dest);
405 
406   dest->reserve(dest->length() + s1.Length() + s2.Length() + 1);
407   *dest += s1;
408   *dest += s2;
409 }
410 
StrAppend(string * dest,const StringHolder & s1,const StringHolder & s2,const StringHolder & s3)411 void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
412                const StringHolder& s3) {
413   assert(dest);
414 
415   dest->reserve(dest->length() + s1.Length() + s2.Length() + s3.Length() + 1);
416   *dest += s1;
417   *dest += s2;
418   *dest += s3;
419 }
420 
StrAppend(string * dest,const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4)421 void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
422                const StringHolder& s3, const StringHolder& s4) {
423   assert(dest);
424 
425   dest->reserve(dest->length() + s1.Length() + s2.Length() + s3.Length() +
426       s4.Length() + 1);
427   *dest += s1;
428   *dest += s2;
429   *dest += s3;
430   *dest += s4;
431 }
432 
StrAppend(string * dest,const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5)433 void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
434                const StringHolder& s3, const StringHolder& s4,
435                const StringHolder& s5) {
436   assert(dest);
437 
438   dest->reserve(dest->length() + s1.Length() + s2.Length() + s3.Length() +
439       s4.Length() + s5.Length() + 1);
440   *dest += s1;
441   *dest += s2;
442   *dest += s3;
443   *dest += s4;
444   *dest += s5;
445 }
446 
447 }  // namespace phonenumbers
448 }  // namespace i18n
449