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 #include "absl/strings/str_replace.h"
25 #include "absl/strings/substitute.h"
26 #include "absl/strings/match.h"
27
28 namespace i18n {
29 namespace phonenumbers {
30
31 using std::equal;
32 using std::stringstream;
33
operator +(const string & s,int n)34 string operator+(const string& s, int n) { // NOLINT(runtime/string)
35 string result;
36 absl::StrAppend(&result,s,n);
37 return result;
38 }
39
SimpleItoa(int n)40 string SimpleItoa(int n) {
41 return absl::StrCat(n);
42 }
43
SimpleItoa(uint64 n)44 string SimpleItoa(uint64 n) {
45 return absl::StrCat(n);
46 }
47
SimpleItoa(int64 n)48 string SimpleItoa(int64 n) {
49 return absl::StrCat(n);
50 }
51
HasPrefixString(const string & s,const string & prefix)52 bool HasPrefixString(const string& s, const string& prefix) {
53 return absl::StartsWith(s, prefix);
54 }
55
FindNth(const string & s,char c,int n)56 size_t FindNth(const string& s, char c, int n) {
57 size_t pos = string::npos;
58
59 for (int i = 0; i < n; ++i) {
60 pos = s.find_first_of(c, pos + 1);
61 if (pos == string::npos) {
62 break;
63 }
64 }
65 return pos;
66 }
67
SplitStringUsing(const string & s,char delimiter,vector<string> * result)68 void SplitStringUsing(const string& s, char delimiter,
69 vector<string>* result) {
70 assert(result);
71 for (absl::string_view split_piece : absl::StrSplit(
72 s, absl::ByChar(delimiter), absl::SkipEmpty())) {
73 result->push_back(std::string(split_piece));
74 }
75 }
76
TryStripPrefixString(const string & in,const string & prefix,string * out)77 bool TryStripPrefixString(const string& in, const string& prefix, string* out) {
78 assert(out);
79 const bool has_prefix = in.compare(0, prefix.length(), prefix) == 0;
80 out->assign(has_prefix ? in.substr(prefix.length()) : in);
81
82 return has_prefix;
83 }
84
HasSuffixString(const string & s,const string & suffix)85 bool HasSuffixString(const string& s, const string& suffix) {
86 return absl::EndsWith(s, suffix);
87 }
88
89 template <typename T>
GenericAtoi(const string & s,T * out)90 void GenericAtoi(const string& s, T* out) {
91 if (!absl::SimpleAtoi(s, out))
92 *out = 0;
93 }
94
safe_strto32(const string & s,int32 * n)95 void safe_strto32(const string& s, int32 *n) {
96 GenericAtoi(s, n);
97 }
98
safe_strtou64(const string & s,uint64 * n)99 void safe_strtou64(const string& s, uint64 *n) {
100 GenericAtoi(s, n);
101 }
102
safe_strto64(const string & s,int64 * n)103 void safe_strto64(const string& s, int64* n) {
104 GenericAtoi(s, n);
105 }
106
strrmm(string * s,const string & chars)107 void strrmm(string* s, const string& chars) {
108 for (string::iterator it = s->begin(); it != s->end(); ) {
109 const char current_char = *it;
110 if (chars.find(current_char) != string::npos) {
111 it = s->erase(it);
112 } else {
113 ++it;
114 }
115 }
116 }
117
GlobalReplaceSubstring(const string & substring,const string & replacement,string * s)118 int GlobalReplaceSubstring(const string& substring,
119 const string& replacement,
120 string* s) {
121 return absl::StrReplaceAll({{substring, replacement}}, s);;
122 }
123
124 // StringHolder class
StringHolder(const string & s)125 StringHolder::StringHolder(const string& s)
126 : absl::AlphaNum(s)
127 {}
128
StringHolder(const char * cp)129 StringHolder::StringHolder(const char* cp)
130 : absl::AlphaNum(cp)
131 {}
132
StringHolder(uint64 n)133 StringHolder::StringHolder(uint64 n)
134 : absl::AlphaNum(n)
135 {}
136
~StringHolder()137 StringHolder::~StringHolder() {}
138
139 // StrCat
140
141 // Implements s += sh; (s: string, sh: StringHolder)
operator +=(string & lhs,const StringHolder & rhs)142 string& operator+=(string& lhs, const StringHolder& rhs) {
143 absl::string_view s = rhs.GetString();;
144 if (s.size() != 0) {
145 lhs += s.data();
146 } else {
147 const char* const cs = rhs.GetCString();
148 if (cs)
149 lhs.append(cs, rhs.Length());
150 }
151 return lhs;
152 }
153
StrCat(const StringHolder & s1,const StringHolder & s2)154 string StrCat(const StringHolder& s1, const StringHolder& s2) {
155 return absl::StrCat(s1, s2);
156 }
157
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3)158 string StrCat(const StringHolder& s1, const StringHolder& s2,
159 const StringHolder& s3) {
160 return absl::StrCat(s1, s2, s3);
161 }
162
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4)163 string StrCat(const StringHolder& s1, const StringHolder& s2,
164 const StringHolder& s3, const StringHolder& s4) {
165 return absl::StrCat(s1, s2, s3, s4);
166 }
167
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5)168 string StrCat(const StringHolder& s1, const StringHolder& s2,
169 const StringHolder& s3, const StringHolder& s4,
170 const StringHolder& s5) {
171 return absl::StrCat(s1, s2, s3, s4, s5);
172 }
173
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5,const StringHolder & s6)174 string StrCat(const StringHolder& s1, const StringHolder& s2,
175 const StringHolder& s3, const StringHolder& s4,
176 const StringHolder& s5, const StringHolder& s6) {
177 return absl::StrCat(s1, s2, s3, s4, s5, s6);
178 }
179
StrCat(const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5,const StringHolder & s6,const StringHolder & s7)180 string StrCat(const StringHolder& s1, const StringHolder& s2,
181 const StringHolder& s3, const StringHolder& s4,
182 const StringHolder& s5, const StringHolder& s6,
183 const StringHolder& s7) {
184 return absl::StrCat(s1, s2, s3, s4, s5, s6, s7);
185 }
186
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)187 string StrCat(const StringHolder& s1, const StringHolder& s2,
188 const StringHolder& s3, const StringHolder& s4,
189 const StringHolder& s5, const StringHolder& s6,
190 const StringHolder& s7, const StringHolder& s8) {
191 string result;
192 result.reserve(s1.Length() + s2.Length() + s3.Length() + s4.Length() +
193 s5.Length() + s6.Length() + s7.Length() + s8.Length() + 1);
194 return absl::StrCat(s1, s2, s3, s4, s5, s6, s7, s8);
195 }
196
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)197 string StrCat(const StringHolder& s1, const StringHolder& s2,
198 const StringHolder& s3, const StringHolder& s4,
199 const StringHolder& s5, const StringHolder& s6,
200 const StringHolder& s7, const StringHolder& s8,
201 const StringHolder& s9) {
202 return absl::StrCat(s1, s2, s3, s4, s5, s6, s7, s8, s9);
203 }
204
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)205 string StrCat(const StringHolder& s1, const StringHolder& s2,
206 const StringHolder& s3, const StringHolder& s4,
207 const StringHolder& s5, const StringHolder& s6,
208 const StringHolder& s7, const StringHolder& s8,
209 const StringHolder& s9, const StringHolder& s10,
210 const StringHolder& s11) {
211 return absl::StrCat(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11);
212 }
213
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)214 string StrCat(const StringHolder& s1, const StringHolder& s2,
215 const StringHolder& s3, const StringHolder& s4,
216 const StringHolder& s5, const StringHolder& s6,
217 const StringHolder& s7, const StringHolder& s8,
218 const StringHolder& s9, const StringHolder& s10,
219 const StringHolder& s11, const StringHolder& s12) {
220 return absl::StrCat(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12);
221 }
222
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,const StringHolder & s13)223 string StrCat(const StringHolder& s1, const StringHolder& s2,
224 const StringHolder& s3, const StringHolder& s4,
225 const StringHolder& s5, const StringHolder& s6,
226 const StringHolder& s7, const StringHolder& s8,
227 const StringHolder& s9, const StringHolder& s10,
228 const StringHolder& s11, const StringHolder& s12,
229 const StringHolder& s13) {
230 return absl::StrCat(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12,
231 s13);
232 }
233
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,const StringHolder & s13,const StringHolder & s14)234 string StrCat(const StringHolder& s1, const StringHolder& s2,
235 const StringHolder& s3, const StringHolder& s4,
236 const StringHolder& s5, const StringHolder& s6,
237 const StringHolder& s7, const StringHolder& s8,
238 const StringHolder& s9, const StringHolder& s10,
239 const StringHolder& s11, const StringHolder& s12,
240 const StringHolder& s13, const StringHolder& s14) {
241 return absl::StrCat(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12,
242 s13, s14);
243 }
244
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,const StringHolder & s13,const StringHolder & s14,const StringHolder & s15)245 string StrCat(const StringHolder& s1, const StringHolder& s2,
246 const StringHolder& s3, const StringHolder& s4,
247 const StringHolder& s5, const StringHolder& s6,
248 const StringHolder& s7, const StringHolder& s8,
249 const StringHolder& s9, const StringHolder& s10,
250 const StringHolder& s11, const StringHolder& s12,
251 const StringHolder& s13, const StringHolder& s14,
252 const StringHolder& s15) {
253 return absl::StrCat(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12,
254 s13, s14, s15);
255 }
256
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,const StringHolder & s13,const StringHolder & s14,const StringHolder & s15,const StringHolder & s16)257 string StrCat(const StringHolder& s1, const StringHolder& s2,
258 const StringHolder& s3, const StringHolder& s4,
259 const StringHolder& s5, const StringHolder& s6,
260 const StringHolder& s7, const StringHolder& s8,
261 const StringHolder& s9, const StringHolder& s10,
262 const StringHolder& s11, const StringHolder& s12,
263 const StringHolder& s13, const StringHolder& s14,
264 const StringHolder& s15, const StringHolder& s16) {
265 return absl::StrCat(s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12,
266 s13, s14, s15, s16);
267 }
268
269 // StrAppend
270
StrAppend(string * dest,const StringHolder & s1)271 void StrAppend(string* dest, const StringHolder& s1) {
272 absl::StrAppend(dest, s1);
273 }
274
StrAppend(string * dest,const StringHolder & s1,const StringHolder & s2)275 void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2) {
276 absl::StrAppend(dest, s1, s2);
277 }
278
StrAppend(string * dest,const StringHolder & s1,const StringHolder & s2,const StringHolder & s3)279 void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
280 const StringHolder& s3) {
281 absl::StrAppend(dest, s1, s2, s3);
282 }
283
StrAppend(string * dest,const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4)284 void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
285 const StringHolder& s3, const StringHolder& s4) {
286 absl::StrAppend(dest, s1, s2, s3, s4);
287 }
288
StrAppend(string * dest,const StringHolder & s1,const StringHolder & s2,const StringHolder & s3,const StringHolder & s4,const StringHolder & s5)289 void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
290 const StringHolder& s3, const StringHolder& s4,
291 const StringHolder& s5) {
292 absl::StrAppend(dest, s1, s2, s3, s4, s5);
293 }
294
295 } // namespace phonenumbers
296 } // namespace i18n
297