Home | History | Annotate | Download | only in phonenumbers
      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 
     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>
     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 
     51 string SimpleItoa(int n) {
     52   return GenericSimpleItoa(n);
     53 }
     54 
     55 string SimpleItoa(uint64 n) {
     56   return GenericSimpleItoa(n);
     57 }
     58 
     59 string SimpleItoa(int64 n) {
     60   return GenericSimpleItoa(n);
     61 }
     62 
     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 
     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 
     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 
    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 
    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 
    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>
    126 void GenericAtoi(const string& s, T* out) {
    127   stringstream stream;
    128   stream << s;
    129   stream >> *out;
    130 }
    131 
    132 void safe_strto32(const string& s, int32 *n) {
    133   GenericAtoi(s, n);
    134 }
    135 
    136 void safe_strtou64(const string& s, uint64 *n) {
    137   GenericAtoi(s, n);
    138 }
    139 
    140 void safe_strto64(const string& s, int64* n) {
    141   GenericAtoi(s, n);
    142 }
    143 
    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 
    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 
    182 StringHolder::StringHolder(const string& s)
    183   : string_(&s),
    184     cstring_(NULL),
    185     len_(s.size())
    186 {}
    187 
    188 StringHolder::StringHolder(const char* s)
    189   : string_(NULL),
    190     cstring_(s),
    191     len_(std::strlen(s))
    192 {}
    193 
    194 StringHolder::StringHolder(uint64 n)
    195   : converted_string_(SimpleItoa(n)),
    196     string_(&converted_string_),
    197     cstring_(NULL),
    198     len_(converted_string_.length())
    199 {}
    200 
    201 StringHolder::~StringHolder() {}
    202 
    203 // StrCat
    204 
    205 // Implements s += sh; (s: string, sh: StringHolder)
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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