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 
16 #include "string_ex.h"
17 #include "unicode_ex.h"
18 #include "utils_log.h"
19 #include "securec.h"
20 #include <iostream>
21 #include <iomanip>
22 #include <sstream>
23 using namespace std;
24 
25 namespace OHOS {
26 
27 static const int CHAR16_TO_CHAR8_PARAM_INVALID = -1;
28 static const int CHAR16_TO_CHAR8_EMPTY_STR = -2;
29 static const int CHAR16_TO_CHAR8_INSUFFICIENT_BUFFER = -3;
30 
UpperStr(const string & str)31 string UpperStr(const string& str)
32 {
33     string upperString = str;
34     transform(upperString.begin(), upperString.end(), upperString.begin(), ::toupper);
35     return upperString;
36 }
37 
LowerStr(const string & str)38 string LowerStr(const string& str)
39 {
40     string lowerString = str;
41     transform(lowerString.begin(), lowerString.end(), lowerString.begin(), ::tolower);
42     return lowerString;
43 }
44 
ReplaceStr(const string & str,const string & src,const string & dst)45 string ReplaceStr(const string& str, const string& src, const string& dst)
46 {
47     if (src.empty()) {
48         return str;
49     }
50 
51     string::size_type pos = 0;
52     string strTmp = str;
53     while ((pos = strTmp.find(src, pos)) != string::npos) {
54         strTmp.replace(pos, src.length(), dst);
55         pos += dst.length();
56     }
57 
58     return strTmp;
59 }
60 
TrimStr(const string & str,const char cTrim)61 string TrimStr(const string& str, const char cTrim /*= ' '*/)
62 {
63     if (str.size() == 1 && str[0] == cTrim) {
64         return string{};
65     }
66 
67     string strTmp = str;
68     std::string::size_type firstBound = strTmp.find_first_not_of(cTrim);
69     if (firstBound != std::string::npos) {
70         strTmp.erase(0, firstBound);
71     }
72 
73     std::string::size_type lastBound = strTmp.find_last_not_of(cTrim);
74     if (lastBound != std::string::npos && lastBound != strTmp.size() - 1) {
75         strTmp.erase(lastBound + sizeof(char));
76     }
77 
78     return strTmp;
79 }
80 
DexToHexString(int value,bool upper)81 string DexToHexString(int value, bool upper /*= true*/)
82 {
83     stringstream ioss;
84     string hexString;
85     if (upper) {
86         ioss << setiosflags(ios::uppercase) << hex << value;
87     } else {
88         ioss << hex << value;
89     }
90 
91     ioss >> hexString;
92     return hexString;
93 }
94 
SplitStr(const string & str,const string & sep,vector<string> & strs,bool canEmpty,bool needTrim)95 void SplitStr(const string& str, const string& sep, vector<string>& strs, bool canEmpty, bool needTrim)
96 {
97     strs.clear();
98     string strTmp = needTrim ? TrimStr(str) : str;
99     string strPart;
100     while (true) {
101         string::size_type pos = strTmp.find(sep);
102         if (string::npos == pos || sep.empty()) {
103             strPart = needTrim ? TrimStr(strTmp) : strTmp;
104             if (!strPart.empty() || canEmpty) {
105                 strs.push_back(strPart);
106             }
107             break;
108         } else {
109             strPart = needTrim ? TrimStr(strTmp.substr(0, pos)) : strTmp.substr(0, pos);
110             if (!strPart.empty() || canEmpty) {
111                 strs.push_back(strPart);
112             }
113             strTmp = strTmp.substr(sep.size() + pos, strTmp.size() - sep.size() - pos);
114         }
115     }
116 }
117 
StrToInt(const string & str,int & value)118 bool StrToInt(const string& str, int& value)
119 {
120     if (str.empty() || (!isdigit(str.front()) && (str.front() != '-'))) {
121         return false;
122     }
123 
124     char* end = nullptr;
125     errno = 0;
126     auto addr = str.c_str();
127     auto result = strtol(addr, &end, 10); /* 10 means decimal */
128     if ((end == addr) || (end[0] != '\0') || (errno == ERANGE) ||
129             (result > INT_MAX) || (result < INT_MIN)) {
130         return false;
131     }
132     value = static_cast<int>(result);
133     return true;
134 }
135 
IsNumericStr(const string & str)136 bool IsNumericStr(const string& str)
137 {
138     if (str.empty()) {
139         return false;
140     }
141 
142     for (const auto& c : str) {
143         if (!isdigit(c)) {
144             return false;
145         }
146     }
147 
148     return true;
149 }
150 
IsAlphaStr(const string & str)151 bool IsAlphaStr(const string& str)
152 {
153     if (str.empty()) {
154         return false;
155     }
156 
157     for (const auto& c : str) {
158         if (!isalpha(c)) {
159             return false;
160         }
161     }
162 
163     return true;
164 }
165 
IsUpperStr(const string & str)166 bool IsUpperStr(const string& str)
167 {
168     if (str.empty()) {
169         return false;
170     }
171 
172     for (const auto& c : str) {
173         if (!isupper(c)) {
174             return false;
175         }
176     }
177 
178     return true;
179 }
180 
IsLowerStr(const string & str)181 bool IsLowerStr(const string& str)
182 {
183     if (str.empty()) {
184         return false;
185     }
186 
187     for (const auto& c : str) {
188         if (!islower(c)) {
189             return false;
190         }
191     }
192 
193     return true;
194 }
195 
IsSubStr(const string & str,const string & sub)196 bool IsSubStr(const string& str, const string& sub)
197 {
198     if (sub.empty() || str.empty()) {
199         return false;
200     }
201 
202     return str.find(sub) != string::npos;
203 }
204 
GetFirstSubStrBetween(const string & str,const string & left,const string & right,string & sub)205 string::size_type GetFirstSubStrBetween(const string& str, const string& left,
206     const string& right, string& sub)
207 {
208     string::size_type leftPos = str.find(left);
209     if (leftPos == string::npos) {
210         return string::npos;
211     }
212 
213     string::size_type rightPos = str.find(right, leftPos + left.length());
214     if (rightPos == string::npos) {
215         return string::npos;
216     }
217 
218     sub = str.substr((leftPos + left.length()), (rightPos - (leftPos + left.length())));
219     return rightPos;
220 }
221 
GetSubStrBetween(const string & str,const string & left,const string & right,vector<string> & sub)222 void GetSubStrBetween(const string& str, const string& left, const string& right, vector<string>& sub)
223 {
224     string subString;
225     string strTmp = str;
226     string::size_type pos = GetFirstSubStrBetween(strTmp, left, right, subString);
227     while (pos != string::npos) {
228         sub.push_back(subString);
229         strTmp = strTmp.substr(pos);
230         pos = GetFirstSubStrBetween(strTmp, left, right, subString);
231     }
232 }
233 
IsSameTextStr(const string & first,const string & second)234 bool IsSameTextStr(const string& first, const string& second)
235 {
236     return UpperStr(first) == UpperStr(second);
237 }
238 
239 /*
240  * utf8 rule
241  * 0000 ~ 007F        : 0xxxxxxx
242  * 0080 ~ 07FF        : 110xxxxx 10xxxxxx
243  * 0800 ~ FFFF        : 1110xxxx 10xxxxxx 10xxxxxx
244  * 10000 ~ 1FFFFF     : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
245  */
IsAsciiString(const string & str)246 bool IsAsciiString(const string& str)
247 {
248     size_t strLen = str.length();
249     for (size_t i = 0; i < strLen; ++i) {
250         if ((str[i] & 0x80) != 0) {
251             return false;
252         }
253     }
254 
255     return true;
256 }
257 
258 #ifndef IOS_PLATFORM
Str8ToStr16(const string & str)259 u16string Str8ToStr16(const string& str)
260 {
261     u16string str16Value;
262     if (!String8ToString16(str, str16Value)) {
263         return u16string();
264     }
265 
266     return str16Value;
267 }
268 
Str16ToStr8(const u16string & str16)269 string Str16ToStr8(const u16string& str16)
270 {
271     string str8Value;
272     if (!String16ToString8(str16, str8Value)) {
273         return string();
274     }
275 
276     return str8Value;
277 }
278 
GetUtf16ToUtf8Length(const u16string & str16)279 int GetUtf16ToUtf8Length(const u16string& str16)
280 {
281     size_t str16Len = str16.length();
282     if (str16Len == 0) {
283         return -1;
284     }
285     const char16_t *utf16Str = str16.c_str();
286     return Utf16ToUtf8Length(utf16Str, str16Len);
287 }
288 
Char16ToChar8(const u16string & str16,char * buffer,int bufferLen)289 int Char16ToChar8(const u16string& str16, char *buffer, int bufferLen)
290 {
291     if (buffer == nullptr || bufferLen <= 0) {
292         return CHAR16_TO_CHAR8_PARAM_INVALID;
293     }
294     size_t str16Len = str16.length();
295     if (str16Len == 0) {
296         return CHAR16_TO_CHAR8_EMPTY_STR;
297     }
298     const char16_t *utf16Str = str16.c_str();
299     int utf8Len = Utf16ToUtf8Length(utf16Str, str16Len);
300     if (utf8Len < 0 || utf8Len >= INT_MAX || (utf8Len + 1) > bufferLen) {
301         UTILS_LOGD("utf8buffer len:%{public}d, actual buffer len:%{public}d!", utf8Len + 1, bufferLen);
302         return CHAR16_TO_CHAR8_INSUFFICIENT_BUFFER;
303     }
304     StrncpyStr16ToStr8(utf16Str, str16Len, buffer, utf8Len + 1);
305     return utf8Len + 1;
306 }
307 
308 #endif
309 } // namespace OHOS
310