• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&reg, regStr.c_str(), flags);
497     // free regex
498     regfree(&reg);
499     return (status == REG_OK);
500 }
501 } // namespace StringUtil
502 } // namespace HiviewDFX
503 } // namespace OHOS
504