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