Philippe Liard | b59d908 | 2011-08-18 11:41:24 +0000 | [diff] [blame] | 1 | // Copyright (C) 2011 The Libphonenumber Authors |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 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 | |
Philippe Liard | 7b30af6 | 2011-09-21 17:43:54 +0000 | [diff] [blame] | 17 | #include <algorithm> |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 18 | #include <cassert> |
| 19 | #include <cstring> |
| 20 | #include <sstream> |
| 21 | |
Philippe Liard | 32b0fe6 | 2011-07-01 08:22:06 +0000 | [diff] [blame] | 22 | #include "phonenumbers/stringutil.h" |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 23 | |
| 24 | namespace i18n { |
| 25 | namespace phonenumbers { |
| 26 | |
Philippe Liard | 7b30af6 | 2011-09-21 17:43:54 +0000 | [diff] [blame] | 27 | using std::equal; |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 28 | using std::stringstream; |
| 29 | |
Philippe Liard | 1b09e6d | 2012-05-23 09:20:57 +0000 | [diff] [blame] | 30 | string operator+(const string& s, int n) { // NOLINT(runtime/string) |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 31 | stringstream stream; |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 32 | |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 33 | stream << s << n; |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 34 | string result; |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 35 | stream >> result; |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 36 | |
| 37 | return result; |
| 38 | } |
| 39 | |
Philip Liard | d4e1c73 | 2011-02-25 15:51:21 +0000 | [diff] [blame] | 40 | template <typename T> |
| 41 | string GenericSimpleItoa(const T& n) { |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 42 | stringstream stream; |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 43 | |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 44 | stream << n; |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 45 | string result; |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 46 | stream >> result; |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 47 | |
| 48 | return result; |
| 49 | } |
| 50 | |
Philip Liard | d4e1c73 | 2011-02-25 15:51:21 +0000 | [diff] [blame] | 51 | string SimpleItoa(int n) { |
| 52 | return GenericSimpleItoa(n); |
| 53 | } |
| 54 | |
| 55 | string SimpleItoa(uint64 n) { |
| 56 | return GenericSimpleItoa(n); |
| 57 | } |
| 58 | |
Philippe Liard | 31b1598 | 2012-06-01 15:33:18 +0000 | [diff] [blame] | 59 | string SimpleItoa(int64 n) { |
| 60 | return GenericSimpleItoa(n); |
| 61 | } |
| 62 | |
Philippe Liard | 7b30af6 | 2011-09-21 17:43:54 +0000 | [diff] [blame] | 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 | |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 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 | |
Philip Liard | e578692 | 2011-04-26 09:04:58 +0000 | [diff] [blame] | 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 | |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 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 | } |
Philip Liard | d4e1c73 | 2011-02-25 15:51:21 +0000 | [diff] [blame] | 139 | |
Philippe Liard | 31b1598 | 2012-06-01 15:33:18 +0000 | [diff] [blame] | 140 | void safe_strto64(const string& s, int64* n) { |
| 141 | GenericAtoi(s, n); |
| 142 | } |
| 143 | |
Philip Liard | e578692 | 2011-04-26 09:04:58 +0000 | [diff] [blame] | 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 | } |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 152 | } |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 153 | } |
| 154 | |
Philip Liard | 791ec35 | 2011-05-16 16:12:25 +0000 | [diff] [blame] | 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 | |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 180 | // StringHolder class |
| 181 | |
Philippe Liard | 1b09e6d | 2012-05-23 09:20:57 +0000 | [diff] [blame] | 182 | StringHolder::StringHolder(const string& s) |
| 183 | : string_(&s), |
| 184 | cstring_(NULL), |
| 185 | len_(s.size()) |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 186 | {} |
| 187 | |
Philippe Liard | 1b09e6d | 2012-05-23 09:20:57 +0000 | [diff] [blame] | 188 | StringHolder::StringHolder(const char* s) |
| 189 | : string_(NULL), |
| 190 | cstring_(s), |
| 191 | len_(std::strlen(s)) |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 192 | {} |
| 193 | |
Philippe Liard | 1b09e6d | 2012-05-23 09:20:57 +0000 | [diff] [blame] | 194 | StringHolder::StringHolder(uint64 n) |
| 195 | : converted_string_(SimpleItoa(n)), |
| 196 | string_(&converted_string_), |
| 197 | cstring_(NULL), |
| 198 | len_(converted_string_.length()) |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 199 | {} |
| 200 | |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 201 | StringHolder::~StringHolder() {} |
| 202 | |
| 203 | // StrCat |
| 204 | |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 205 | // Implements s += sh; (s: string, sh: StringHolder) |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 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, |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 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, |
Philippe Liard | 7b30af6 | 2011-09-21 17:43:54 +0000 | [diff] [blame] | 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, |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 324 | const StringHolder& s7, const StringHolder& s8, |
Philippe Liard | 4567abf | 2011-08-12 07:44:38 +0000 | [diff] [blame] | 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, |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 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 | |
Lara Scheidegger | 7ae82ad | 2012-09-06 09:48:57 +0000 | [diff] [blame] | 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 | |
Philip Liard | 6f1ba2d | 2011-04-07 07:27:47 +0000 | [diff] [blame] | 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 | |
Philippe Liard | e55d384 | 2012-03-15 17:04:03 +0000 | [diff] [blame] | 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 | |
Philip Liard | dbb360c | 2011-02-25 09:02:23 +0000 | [diff] [blame] | 447 | } // namespace phonenumbers |
| 448 | } // namespace i18n |