1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
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 #include "string_util.h"
16 #include <climits>
17 #include <iomanip>
18 #include <iostream>
19 #include <sstream>
20 #include <string>
21 #include <vector>
22
23 namespace OHOS {
24 namespace HiviewDFX {
25 namespace StringUtil {
26 using namespace std;
27 const char INDICATE_VALUE_CHAR = ':';
28 const char KEY_VALUE_END_CHAR = ';';
29 constexpr int SKIP_NEXT_INDEX_LENGTH = 2;
30 const std::string EMPTY_STRING = "";
ConvertVectorToStr(const std::vector<std::string> & listStr,const std::string & split)31 std::string ConvertVectorToStr(const std::vector<std::string> &listStr, const std::string &split)
32 {
33 std::string str("");
34 for (auto &item : listStr) {
35 if (str == "") {
36 str = item;
37 } else {
38 str += split + item;
39 }
40 }
41 return str;
42 }
43
ReplaceStr(const string & str,const string & src,const string & dst)44 string ReplaceStr(const string& str, const string& src, const string& dst)
45 {
46 if (src.empty()) {
47 return str;
48 }
49
50 string::size_type pos = 0;
51 string strTmp = str;
52 while ((pos = strTmp.find(src, pos)) != string::npos) {
53 strTmp.replace(pos, src.length(), dst);
54 pos += dst.length();
55 }
56
57 return strTmp;
58 }
59
TrimStr(const string & str,const char cTrim)60 string TrimStr(const string& str, const char cTrim)
61 {
62 string strTmp = str;
63 strTmp.erase(0, strTmp.find_first_not_of(cTrim));
64 strTmp.erase(strTmp.find_last_not_of(cTrim) + sizeof(char));
65 return strTmp;
66 }
67
SplitStr(const string & str,const string & sep,vector<string> & strs,bool canEmpty,bool needTrim)68 void SplitStr(const string& str, const string& sep, vector<string>& strs,
69 bool canEmpty, bool needTrim)
70 {
71 strs.clear();
72 string strTmp = needTrim ? TrimStr(str) : str;
73 string strPart;
74 while (true) {
75 string::size_type pos = strTmp.find(sep);
76 if (string::npos == pos || sep.empty()) {
77 strPart = needTrim ? TrimStr(strTmp) : strTmp;
78 if (!strPart.empty() || canEmpty) {
79 strs.push_back(strPart);
80 }
81 break;
82 } else {
83 strPart = needTrim ? TrimStr(strTmp.substr(0, pos)) : strTmp.substr(0, pos);
84 if (!strPart.empty() || canEmpty) {
85 strs.push_back(strPart);
86 }
87 strTmp = strTmp.substr(sep.size() + pos, strTmp.size() - sep.size() - pos);
88 }
89 }
90 }
91
StrToInt(const string & str,int & value)92 bool StrToInt(const string& str, int& value)
93 {
94 if (str.empty() || (!isdigit(str.front()) && (str.front() != '-'))) {
95 return false;
96 }
97
98 char* end = nullptr;
99 const int base = 10;
100 errno = 0;
101 auto addr = str.c_str();
102 auto result = strtol(addr, &end, base);
103 if (end == addr || end[0] != '\0' || errno == ERANGE) {
104 return false;
105 }
106
107 value = static_cast<int>(result);
108 return true;
109 }
110
StrToInt(const string & str)111 int StrToInt(const string& str)
112 {
113 int id = -1;
114 StrToInt(str, id);
115 return id;
116 }
117
DexToHexString(int value,bool upper)118 string DexToHexString(int value, bool upper)
119 {
120 stringstream ioss;
121 string hexString;
122 if (upper) {
123 ioss << setiosflags(ios::uppercase) << hex << value;
124 } else {
125 ioss << hex << value;
126 }
127
128 ioss >> hexString;
129 return hexString;
130 }
131
GetKeyValueByString(size_t & start,const std::string & inputString)132 KeyValuePair GetKeyValueByString(size_t &start, const std::string &inputString)
133 {
134 std::string key;
135 std::string value;
136 auto length = inputString.size();
137 while (start < length) {
138 if (inputString[start] == INDICATE_VALUE_CHAR) {
139 start++;
140 break;
141 }
142 key.append(1, inputString[start]);
143 start++;
144 }
145
146 while (start < length) {
147 if (inputString[start] == KEY_VALUE_END_CHAR) {
148 // replace ;; to ; in value;
149 // one ';' means the end of a "key:value;"
150 if (start + 1 < length && inputString[start + 1] == KEY_VALUE_END_CHAR) {
151 value.append(1, inputString[start]);
152 start = start + SKIP_NEXT_INDEX_LENGTH;
153 continue;
154 } else {
155 start++;
156 break;
157 }
158 }
159 if (inputString[start] == INDICATE_VALUE_CHAR && start + 1 < length &&
160 inputString[start + 1] == INDICATE_VALUE_CHAR) {
161 // replace :: to :
162 value.append(1, inputString[start]);
163 start = start + SKIP_NEXT_INDEX_LENGTH;
164 continue;
165 }
166 value.append(1, inputString[start]);
167 start++;
168 }
169 return make_pair(key, make_pair(value, 0));
170 }
171
IsValidFloatNum(const std::string & value)172 bool IsValidFloatNum(const std::string &value)
173 {
174 int len = value.size();
175 int pointNum = 0;
176
177 for (int i = 0; i < len; i++) {
178 if (isdigit(value[i])) {
179 continue;
180 }
181 if (value[i] == '.') {
182 pointNum++;
183 } else {
184 // the string contains not valid num;
185 return false;
186 }
187 }
188 // the string contains more than one character '.'
189 if (pointNum > 1) {
190 return false;
191 }
192 // the string format is .111/111.
193 return isdigit(value[0]) && isdigit(value[len - 1]);
194 }
195
SplitStr(const std::string & str,char delimiter)196 std::list<std::string> SplitStr(const std::string& str, char delimiter)
197 {
198 std::list<std::string> tokens;
199 std::string token;
200 std::istringstream tokenStream(str);
201 while (std::getline(tokenStream, token, delimiter)) {
202 tokens.push_back(token);
203 }
204 return tokens;
205 }
206
GetLeftSubstr(const string & input,const string & split)207 string GetLeftSubstr(const string& input, const string& split)
208 {
209 size_t pos = input.find(split, 0);
210 if (pos == string::npos) {
211 return input;
212 }
213 return input.substr(0, pos);
214 }
215
GetRightSubstr(const string & input,const string & split)216 string GetRightSubstr(const string& input, const string& split)
217 {
218 size_t pos = input.find(split, 0);
219 if (pos == string::npos) {
220 return "none";
221 }
222 return input.substr(pos + split.size(), input.size() - pos);
223 }
224
GetRleftSubstr(const string & input,const string & split)225 string GetRleftSubstr(const string& input, const string& split)
226 {
227 size_t pos = input.rfind(split, string::npos);
228 if (pos == string::npos) {
229 return input;
230 }
231 return input.substr(0, pos);
232 }
233
GetRrightSubstr(const string & input,const string & split)234 string GetRrightSubstr(const string& input, const string& split)
235 {
236 size_t pos = input.rfind(split, string::npos);
237 if (pos == string::npos) {
238 return "none";
239 }
240 return input.substr(pos + 1, input.size() - pos);
241 }
242
EraseString(const string & input,const string & toErase)243 string EraseString(const string& input, const string& toErase)
244 {
245 size_t pos = 0;
246 string out = input;
247 while ((pos = out.find(toErase, pos)) != string::npos) {
248 out.erase(pos, toErase.size());
249 pos = (pos == 0) ? (0) : (pos - 1);
250 }
251 return out;
252 }
253
GetMidSubstr(const string & input,const string & begin,const string & end)254 string GetMidSubstr(const string& input, const string& begin, const string& end)
255 {
256 string midstr = "";
257 size_t beginPos = input.find(begin, 0);
258 if (beginPos == string::npos) {
259 return midstr;
260 }
261 beginPos = beginPos + begin.size();
262 size_t endPos = input.find(end, beginPos);
263 if (endPos == string::npos) {
264 return midstr;
265 }
266 return input.substr(beginPos, endPos - beginPos);
267 }
268
VectorToString(const vector<string> & src,bool reverse,const string & tag)269 string VectorToString(const vector<string>& src, bool reverse, const string& tag)
270 {
271 string str;
272 for (auto element : src) {
273 if (element.empty()) {
274 continue;
275 }
276 if (reverse) {
277 str = element + tag + str;
278 } else {
279 str = str + element + tag;
280 }
281 }
282 return str;
283 }
284
StringToUl(const string & flag,int base)285 uint64_t StringToUl(const string& flag, int base)
286 {
287 uint64_t ret = strtoul(flag.c_str(), NULL, base);
288 if (ret == ULONG_MAX) {
289 return 0;
290 }
291 return ret;
292 }
293
StringToDouble(const string & input)294 double StringToDouble(const string& input)
295 {
296 if (input.empty()) {
297 return 0;
298 }
299 char *e = nullptr;
300 errno = 0;
301 double temp = std::strtod(input.c_str(), &e);
302
303 if (errno != 0) { // error, overflow or underflow
304 return 0;
305 }
306 return temp;
307 }
308
FindMatchSubString(const std::string & target,const std::string & begin,int offset,const std::string & end)309 std::string FindMatchSubString(const std::string& target, const std::string& begin, int offset,
310 const std::string& end)
311 {
312 auto matchPos = target.find_first_of(begin);
313 if (matchPos == std::string::npos) {
314 return "";
315 }
316 auto beginPos = matchPos + offset;
317 if (beginPos > target.length()) {
318 return "";
319 }
320 auto endPos = target.find_first_of(end, beginPos);
321 if (endPos == std::string::npos) {
322 return target.substr(beginPos);
323 }
324 return target.substr(beginPos, endPos);
325 }
326
EscapeJsonStringValue(const std::string & value)327 std::string EscapeJsonStringValue(const std::string &value)
328 {
329 std::string escapeValue;
330 for (auto it = value.begin(); it != value.end(); it++) {
331 switch (*it) {
332 case '\\':
333 escapeValue.push_back('\\');
334 escapeValue.push_back('\\');
335 break;
336 case '\"':
337 escapeValue.push_back('\\');
338 escapeValue.push_back('"');
339 break;
340 case '\b':
341 escapeValue.push_back('\\');
342 escapeValue.push_back('b');
343 break;
344 case '\f':
345 escapeValue.push_back('\\');
346 escapeValue.push_back('f');
347 break;
348 case '\n':
349 escapeValue.push_back('\\');
350 escapeValue.push_back('n');
351 break;
352 case '\r':
353 escapeValue.push_back('\\');
354 escapeValue.push_back('r');
355 break;
356 case '\t':
357 escapeValue.push_back('\\');
358 escapeValue.push_back('t');
359 break;
360 default:
361 escapeValue.push_back(*it);
362 break;
363 }
364 }
365 return escapeValue;
366 }
367
UnescapeJsonStringValue(const std::string & value)368 std::string UnescapeJsonStringValue(const std::string &value)
369 {
370 bool isEscaped = true;
371 std::string unescapeValue;
372 for (auto it = value.begin(); it != value.end(); it++) {
373 if (isEscaped) {
374 switch (*it) {
375 case '"':
376 unescapeValue.push_back('\"');
377 break;
378 case '/':
379 unescapeValue.push_back('/');
380 break;
381 case 'b':
382 unescapeValue.push_back('\b');
383 break;
384 case 'f':
385 unescapeValue.push_back('\f');
386 break;
387 case 'n':
388 unescapeValue.push_back('\n');
389 break;
390 case 'r':
391 unescapeValue.push_back('\r');
392 break;
393 case 't':
394 unescapeValue.push_back('\t');
395 break;
396 case '\\':
397 unescapeValue.push_back('\\');
398 break;
399 default:
400 unescapeValue.push_back(*it);
401 break;
402 }
403 isEscaped = false;
404 } else {
405 switch (*it) {
406 case '\\':
407 isEscaped = true;
408 break;
409 default:
410 unescapeValue.push_back(*it);
411 break;
412 }
413 }
414 }
415 return unescapeValue;
416 }
417 } // namespace StringUtil
418 } // namespace HiviewDFX
419 } // namespace OHOS
420