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