• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_UTILS_STRING_UTILS_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_UTILS_STRING_UTILS_H
18 
19 #include <climits>
20 #include <cmath>
21 #include <codecvt>
22 #include <cstring>
23 #include <locale>
24 #include <sstream>
25 #include <string>
26 #include <vector>
27 
28 #include "base/geometry/calc_dimension.h"
29 #include "base/geometry/dimension.h"
30 #include "base/utils/linear_map.h"
31 #include "base/utils/utils.h"
32 
33 namespace OHOS::Ace::StringUtils {
34 
35 ACE_FORCE_EXPORT  extern const char DEFAULT_STRING[];
36 ACE_EXPORT extern const std::wstring DEFAULT_WSTRING;
37 ACE_FORCE_EXPORT  extern const std::u16string DEFAULT_USTRING;
38 ACE_EXPORT extern const std::u32string DEFAULT_U32STRING;
39 constexpr int32_t TEXT_CASE_LOWERCASE = 1;
40 constexpr int32_t TEXT_CASE_UPPERCASE = 2;
41 constexpr double PERCENT_VALUE = 100.0;
42 constexpr double DEGREES_VALUE = 360.0; // one turn means 360 deg
43 constexpr double GRADIANS_VALUE = 400.0; // one turn means 400 grad
44 constexpr double RADIANS_VALUE = 2 * M_PI; // one turn means 2*pi rad
45 const char ELLIPSIS[] = "...";
46 
Str8ToStr16(const std::string & str)47 inline std::u16string Str8ToStr16(const std::string& str)
48 {
49     if (str == DEFAULT_STRING) {
50         return DEFAULT_USTRING;
51     }
52     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert(DEFAULT_STRING, DEFAULT_USTRING);
53     std::u16string result = convert.from_bytes(str);
54     return result == DEFAULT_USTRING ? u"" : result;
55 }
56 
Str16ToStr8(const std::u16string & str)57 inline std::string Str16ToStr8(const std::u16string& str)
58 {
59     if (str == DEFAULT_USTRING) {
60         return DEFAULT_STRING;
61     }
62     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert(DEFAULT_STRING);
63     std::string result = convert.to_bytes(str);
64     return result == DEFAULT_STRING ? "" : result;
65 }
66 
ToWstring(const std::string & str)67 inline std::wstring ToWstring(const std::string& str)
68 {
69     if (str == DEFAULT_STRING) {
70         return DEFAULT_WSTRING;
71     }
72 #ifdef PREVIEW
73     std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert(DEFAULT_STRING, DEFAULT_WSTRING);
74 #elif WINDOWS_PLATFORM
75     std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> convert(DEFAULT_STRING, DEFAULT_WSTRING);
76 #else
77     std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert(DEFAULT_STRING, DEFAULT_WSTRING);
78 #endif
79     std::wstring result = convert.from_bytes(str);
80     return result == DEFAULT_WSTRING ? L"" : result;
81 }
82 
IsLetterOrNumberForWchar(wchar_t chr)83 inline bool IsLetterOrNumberForWchar(wchar_t chr)
84 {
85     return (chr >= L'0' && chr <= L'9') || (chr >= L'a' && chr <= L'z') || (chr >= L'A' && chr <= L'Z');
86 }
87 
IsLetterOrNumberForChar16(char16_t chr)88 inline bool IsLetterOrNumberForChar16(char16_t chr)
89 {
90     return (chr >= u'0' && chr <= u'9') || (chr >= u'a' && chr <= u'z') || (chr >= u'A' && chr <= u'Z');
91 }
92 
ToString(const std::wstring & str)93 inline std::string ToString(const std::wstring& str)
94 {
95     if (str == DEFAULT_WSTRING) {
96         return DEFAULT_STRING;
97     }
98 #ifdef PREVIEW
99     std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert(DEFAULT_STRING);
100 #elif WINDOWS_PLATFORM
101     std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> convert(DEFAULT_STRING);
102 #else
103     std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert(DEFAULT_STRING);
104 #endif
105     std::string result = convert.to_bytes(str);
106     return result == DEFAULT_STRING ? "" : result;
107 }
108 
ToU32string(const std::string & str)109 inline std::u32string ToU32string(const std::string& str)
110 {
111     if (str == DEFAULT_STRING) {
112         return DEFAULT_U32STRING;
113     }
114     std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert(DEFAULT_STRING, DEFAULT_U32STRING);
115     std::u32string result = convert.from_bytes(str);
116     return result == DEFAULT_U32STRING ? U"" : result;
117 }
118 
U32StringToString(const std::u32string & str)119 inline std::string U32StringToString(const std::u32string& str)
120 {
121     if (str == DEFAULT_U32STRING) {
122         return DEFAULT_STRING;
123     }
124     std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert(DEFAULT_STRING);
125     std::string result = convert.to_bytes(str);
126     return result == DEFAULT_STRING ? "" : result;
127 }
128 
NotInUtf16Bmp(char16_t c)129 inline bool NotInUtf16Bmp(char16_t c)
130 {
131     return (c & 0xF800) == 0xD800;
132 }
133 
NotInBmp(wchar_t ch)134 inline bool NotInBmp(wchar_t ch)
135 {
136     return ch >= 0xD800 && ch <= 0xDBFF;
137 }
138 
IsNumber(const std::string & value)139 inline bool IsNumber(const std::string& value)
140 {
141     if (value.empty()) {
142         return false;
143     }
144     return std::all_of(value.begin(), value.end(), [](char i) { return isdigit(i); });
145 }
146 
ReplaceSpace(std::string & data)147 inline void ReplaceSpace(std::string& data)
148 {
149     bool isFirstSpace = true;
150     auto iter = data.begin();
151     while (iter != data.end()) {
152         if (*iter == ' ') {
153             if (isFirstSpace) {
154                 iter++;
155                 isFirstSpace = false;
156             } else {
157                 iter = data.erase(iter);
158             }
159         } else if (*iter == '\t') {
160             *iter = ' ';
161         } else {
162             isFirstSpace = true;
163             iter++;
164         }
165     }
166 }
167 
ReplaceTabAndNewLine(std::string & data)168 inline void ReplaceTabAndNewLine(std::string& data)
169 {
170     for (auto& i : data) {
171         if (i == '\r' || i == '\n') {
172             i = ' ';
173         }
174     }
175     ReplaceSpace(data);
176 }
177 
RestoreEscape(const std::string & src)178 inline std::string RestoreEscape(const std::string& src)
179 {
180     std::string res;
181     for (auto &c : src) {
182         switch (c) {
183             case '\n':
184                 res += "\\n";
185                 break;
186             case '\r':
187                 res += "\\r";
188                 break;
189             case '\t':
190                 res += "\\t";
191                 break;
192             default:
193                 res.push_back(c);
194                 break;
195         }
196     }
197     return res;
198 }
199 
RestoreBackslash(const std::string & src)200 inline std::string RestoreBackslash(const std::string& src)
201 {
202     std::string res;
203     for (auto &c : src) {
204         if (c != '\\') {
205             res.push_back(c);
206         }
207     }
208     return res;
209 }
210 
211 inline int32_t StringToInt(const std::string& value, int64_t defaultErr = 0)
212 {
213     errno = 0;
214     char* pEnd = nullptr;
215     int64_t result = std::strtol(value.c_str(), &pEnd, 10);
216     if (pEnd == value.c_str() || (result < INT_MIN || result > INT_MAX) || errno == ERANGE) {
217         return defaultErr;
218     } else {
219         return result;
220     }
221 }
222 
223 inline int64_t StringToLongInt(const std::string& value, int64_t defaultErr = 0)
224 {
225     errno = 0;
226     char* pEnd = nullptr;
227     int64_t result = std::strtoll(value.c_str(), &pEnd, 10);
228     if (pEnd == value.c_str() || errno == ERANGE) {
229         return defaultErr;
230     } else {
231         return result;
232     }
233 }
234 
235 inline uint64_t StringToLongUint(const std::string& value, uint64_t defaultErr = 0)
236 {
237     errno = 0;
238     char* pEnd = nullptr;
239     uint64_t result = std::strtoull(value.c_str(), &pEnd, 10);
240     if (pEnd == value.c_str() || errno == ERANGE) {
241         return defaultErr;
242     } else {
243         return result;
244     }
245 }
246 
247 inline uint32_t StringToUintCheck(const std::string& value, uint32_t defaultErr = 0)
248 {
249     errno = 0;
250     char* pEnd = nullptr;
251     uint64_t result = std::strtoull(value.c_str(), &pEnd, 10);
252     if ((pEnd == value.c_str()) || ((pEnd != nullptr) && (*pEnd != '\0')) || result > UINT32_MAX || errno == ERANGE) {
253         return defaultErr;
254     } else {
255         return result;
256     }
257 }
258 
259 inline uint32_t StringToUint(const std::string& value, uint32_t defaultErr = 0)
260 {
261     errno = 0;
262     char* pEnd = nullptr;
263     uint64_t result = std::strtoull(value.c_str(), &pEnd, 10);
264     if (pEnd == value.c_str() || result > UINT32_MAX || errno == ERANGE) {
265         return defaultErr;
266     } else {
267         return result;
268     }
269 }
270 
271 // generic string to double value method without success check
StringToDouble(const std::string & value)272 inline double StringToDouble(const std::string& value)
273 {
274     char* pEnd = nullptr;
275     errno = 0;
276     double result = std::strtod(value.c_str(), &pEnd);
277     if (pEnd == value.c_str() || errno == ERANGE) {
278         return 0.0;
279     } else {
280         return result;
281     }
282 }
283 // string to double method with success check, and support for parsing number string with percentage case
StringToDouble(const std::string & value,double & result)284 inline bool StringToDouble(const std::string& value, double& result)
285 {
286     errno = 0;
287     char* pEnd = nullptr;
288     double res = std::strtod(value.c_str(), &pEnd);
289     if (pEnd == value.c_str() || errno == ERANGE) {
290         return false;
291     } else if (pEnd != nullptr) {
292         if (std::strcmp(pEnd, "%") == 0) {
293             result = res / PERCENT_VALUE;
294             return true;
295         } else if (std::strcmp(pEnd, "") == 0) {
296             result = res;
297             return true;
298         }
299     }
300     return false;
301 }
302 
StringToFloat(const std::string & value)303 inline float StringToFloat(const std::string& value)
304 {
305     errno = 0;
306     char* pEnd = nullptr;
307     float result = std::strtof(value.c_str(), &pEnd);
308     if (pEnd == value.c_str() || errno == ERANGE) {
309         return 0.0f;
310     } else {
311         return result;
312     }
313 }
314 
315 static Dimension StringToDimensionWithUnit(const std::string& value, DimensionUnit defaultUnit = DimensionUnit::PX,
316     float defaultValue = 0.0f, bool isCalc = false)
317 {
318     errno = 0;
319     if (std::strcmp(value.c_str(), "auto") == 0) {
320         return Dimension(defaultValue, DimensionUnit::AUTO);
321     }
322     char* pEnd = nullptr;
323     double result = std::strtod(value.c_str(), &pEnd);
324     if (pEnd == value.c_str() || errno == ERANGE) {
325         return Dimension(defaultValue, defaultUnit);
326     }
327     if (pEnd != nullptr) {
328         if (std::strcmp(pEnd, "%") == 0) {
329             // Parse percent, transfer from [0, 100] to [0, 1]
330             return Dimension(result / 100.0, DimensionUnit::PERCENT);
331         }
332         if (std::strcmp(pEnd, "px") == 0) {
333             return Dimension(result, DimensionUnit::PX);
334         }
335         if (std::strcmp(pEnd, "vp") == 0) {
336             return Dimension(result, DimensionUnit::VP);
337         }
338         if (std::strcmp(pEnd, "fp") == 0) {
339             return Dimension(result, DimensionUnit::FP);
340         }
341         if (std::strcmp(pEnd, "lpx") == 0) {
342             return Dimension(result, DimensionUnit::LPX);
343         }
344         if ((std::strcmp(pEnd, "\0") == 0) && isCalc) {
345             return Dimension(result, DimensionUnit::NONE);
346         }
347         if (isCalc) {
348             return Dimension(result, DimensionUnit::INVALID);
349         }
350     }
351     return Dimension(result, defaultUnit);
352 }
353 
354 inline CalcDimension StringToCalcDimension(
355     const std::string& value, bool useVp = false, DimensionUnit defaultUnit = DimensionUnit::PX)
356 {
357     if (value.find("calc") != std::string::npos) {
358         return CalcDimension(value, DimensionUnit::CALC);
359     } else {
360         if (useVp) {
361             return StringToDimensionWithUnit(value, DimensionUnit::VP);
362         }
363         return StringToDimensionWithUnit(value, defaultUnit);
364     }
365 }
366 
367 inline Dimension StringToDimension(const std::string& value, bool useVp = false)
368 {
369     return StringToDimensionWithUnit(value, useVp ? DimensionUnit::VP : DimensionUnit::PX);
370 }
371 
StringToDimensionWithThemeValue(const std::string & value,bool useVp,const Dimension & themeValue)372 inline Dimension StringToDimensionWithThemeValue(const std::string& value, bool useVp, const Dimension& themeValue)
373 {
374     errno = 0;
375     char* pEnd = nullptr;
376     std::strtod(value.c_str(), &pEnd);
377     if (pEnd == value.c_str() || errno == ERANGE) {
378         return themeValue;
379     }
380 
381     return StringToDimensionWithUnit(value, useVp ? DimensionUnit::VP : DimensionUnit::PX);
382 }
383 
384 static bool StringToDimensionWithUnitNG(const std::string& value, Dimension& dimensionResult,
385     DimensionUnit defaultUnit = DimensionUnit::PX, float defaultValue = 0.0f, bool isCalc = false)
386 {
387     errno = 0;
388     if (std::strcmp(value.c_str(), "auto") == 0) {
389         dimensionResult = Dimension(defaultValue, DimensionUnit::AUTO);
390         return true;
391     }
392     char* pEnd = nullptr;
393     double result = std::strtod(value.c_str(), &pEnd);
394     if (pEnd == value.c_str() || errno == ERANGE) {
395         dimensionResult = Dimension(defaultValue, defaultUnit);
396         return false;
397     }
398     if (pEnd != nullptr) {
399         if (std::strcmp(pEnd, "%") == 0) {
400             // Parse percent, transfer from [0, 100] to [0, 1]
401             dimensionResult = Dimension(result / 100.0, DimensionUnit::PERCENT);
402             return true;
403         }
404         if (std::strcmp(pEnd, "px") == 0) {
405             dimensionResult = Dimension(result, DimensionUnit::PX);
406             return true;
407         }
408         if (std::strcmp(pEnd, "vp") == 0) {
409             dimensionResult = Dimension(result, DimensionUnit::VP);
410             return true;
411         }
412         if (std::strcmp(pEnd, "fp") == 0) {
413             dimensionResult = Dimension(result, DimensionUnit::FP);
414             return true;
415         }
416         if (std::strcmp(pEnd, "lpx") == 0) {
417             dimensionResult = Dimension(result, DimensionUnit::LPX);
418             return true;
419         }
420         if ((std::strcmp(pEnd, "\0") == 0) && isCalc) {
421             dimensionResult = Dimension(result, DimensionUnit::NONE);
422             return true;
423         }
424         if (isCalc) {
425             dimensionResult = Dimension(result, DimensionUnit::INVALID);
426             return true;
427         }
428         if ((std::strcmp(pEnd, "\0") != 0)) {
429             dimensionResult = Dimension(result, DimensionUnit::NONE);
430             return false;
431         }
432     }
433     dimensionResult = Dimension(result, defaultUnit);
434     return true;
435 }
436 
437 inline bool StringToCalcDimensionNG(
438     const std::string& value, CalcDimension& result, bool useVp = false,
439     DimensionUnit defaultUnit = DimensionUnit::PX)
440 {
441     if (value.find("calc") != std::string::npos) {
442         result = CalcDimension(value, DimensionUnit::CALC);
443         return true;
444     } else {
445         return StringToDimensionWithUnitNG(value, result, useVp ? DimensionUnit::VP : defaultUnit);
446     }
447 }
448 
ReplaceChar(std::string str,char old_char,char new_char)449 inline std::string ReplaceChar(std::string str, char old_char, char new_char)
450 {
451     for (char& it : str) {
452         if (it == old_char) {
453             it = new_char;
454         }
455     }
456     return str;
457 }
458 
StringToDegree(const std::string & value)459 inline double StringToDegree(const std::string& value)
460 {
461     // https://developer.mozilla.org/zh-CN/docs/Web/CSS/angle
462 
463     errno = 0;
464     char* pEnd = nullptr;
465     double result = std::strtod(value.c_str(), &pEnd);
466     if (pEnd == value.c_str() || errno == ERANGE) {
467         return 0.0;
468     } else if (pEnd) {
469         if ((std::strcmp(pEnd, "deg")) == 0) {
470             return result;
471         } else if (std::strcmp(pEnd, "grad") == 0) {
472             return result / GRADIANS_VALUE * DEGREES_VALUE;
473         } else if (std::strcmp(pEnd, "rad") == 0) {
474             return result / RADIANS_VALUE * DEGREES_VALUE;
475         } else if (std::strcmp(pEnd, "turn") == 0) {
476             return result * DEGREES_VALUE;
477         }
478     }
479     return StringToDouble(value);
480 }
481 
482 // StringToDegree with check. If the string is valid, change result and return true, otherwise return false.
StringToDegree(const std::string & value,double & result)483 inline bool StringToDegree(const std::string& value, double& result)
484 {
485     errno = 0;
486     char* pEnd = nullptr;
487     double temp = std::strtod(value.c_str(), &pEnd);
488     if (pEnd == value.c_str() || errno == ERANGE) {
489         return false;
490     } else if (pEnd) {
491         if (*pEnd == '\0') {
492             result = temp;
493             return true;
494         }
495         if (std::strcmp(pEnd, "deg") == 0) {
496             result = temp;
497             return true;
498         }
499         if (std::strcmp(pEnd, "grad") == 0) {
500             result = temp / GRADIANS_VALUE * DEGREES_VALUE;
501             return true;
502         }
503         if (std::strcmp(pEnd, "rad") == 0) {
504             result = temp / RADIANS_VALUE * DEGREES_VALUE;
505             return true;
506         }
507         if (std::strcmp(pEnd, "turn") == 0) {
508             result = temp * DEGREES_VALUE;
509             return true;
510         }
511     }
512     return false;
513 }
514 
515 template<class T>
StringSplitter(const std::string & source,char delimiter,T (* func)(const std::string &),std::vector<T> & out)516 inline void StringSplitter(
517     const std::string& source, char delimiter, T (*func)(const std::string&), std::vector<T>& out)
518 {
519     out.erase(out.begin(), out.end());
520 
521     if (source.empty()) {
522         return;
523     }
524 
525     std::size_t startIndex = 0;
526     for (std::size_t index = 0; index < source.size(); index++) {
527         if (source[index] != delimiter) {
528             continue;
529         }
530 
531         if (index > startIndex) {
532             out.emplace_back(func(source.substr(startIndex, index - startIndex)));
533         }
534         startIndex = index + 1;
535     }
536 
537     if (startIndex < source.size()) {
538         out.emplace_back(func(source.substr(startIndex)));
539     }
540 }
541 
ParseStringToArray(const std::string & input,std::vector<float> & output)542 inline bool ParseStringToArray(const std::string& input, std::vector<float>& output)
543 {
544     std::istringstream iss(StringUtils::ReplaceChar(input, ',', ' '));
545     std::string token;
546 
547     while (iss >> token) {
548         double value;
549         if (!StringToDouble(token, value)) {
550             return false;
551         }
552         output.emplace_back(value);
553     }
554 
555     return true;
556 }
557 
StringSplitter(const std::string & source,char delimiter,std::vector<std::string> & out)558 inline void StringSplitter(const std::string& source, char delimiter, std::vector<std::string>& out)
559 {
560     using Func = std::string (*)(const std::string&);
561     Func func = [](const std::string& value) { return value; };
562     StringSplitter(source, delimiter, func, out);
563 }
564 
StringSplitter(const std::string & source,char delimiter,std::vector<double> & out)565 inline void StringSplitter(const std::string& source, char delimiter, std::vector<double>& out)
566 {
567     using Func = double (*)(const std::string&);
568     Func func = [](const std::string& value) { return StringToDouble(value); };
569     StringSplitter(source, delimiter, func, out);
570 }
571 
StringSplitter(const std::string & source,char delimiter,std::vector<float> & out)572 inline void StringSplitter(const std::string& source, char delimiter, std::vector<float>& out)
573 {
574     using Func = float (*)(const std::string&);
575     Func func = [](const std::string& value) { return StringToFloat(value); };
576     StringSplitter(source, delimiter, func, out);
577 }
578 
StringSplitter(const std::string & source,char delimiter,std::vector<int> & out)579 inline void StringSplitter(const std::string& source, char delimiter, std::vector<int>& out)
580 {
581     using Func = int32_t (*)(const std::string&);
582     Func func = [](const std::string& value) { return StringToInt(value); };
583     StringSplitter(source, delimiter, func, out);
584 }
585 
StringSplitter(const std::string & source,char delimiter,std::vector<Dimension> & out)586 inline void StringSplitter(const std::string& source, char delimiter, std::vector<Dimension>& out)
587 {
588     using Func = Dimension (*)(const std::string&);
589     Func func = [](const std::string& value) { return StringToDimension(value); };
590     StringSplitter(source, delimiter, func, out);
591 }
592 
593 inline std::string DoubleToString(double value, int32_t precision = 2)
594 {
595     std::ostringstream result;
596     result.precision(precision);
597     if (NearEqual(value, Infinity<double>())) {
598         result << "Infinity";
599     } else {
600         result << std::fixed << value;
601     }
602     return result.str();
603 }
604 
DeleteAllMark(std::string & str,const char mark)605 inline void DeleteAllMark(std::string& str, const char mark)
606 {
607     str.erase(std::remove(str.begin(), str.end(), mark), str.end());
608 }
609 
610 inline std::string TrimStr(const std::string& str, char cTrim = ' ')
611 {
612     auto firstPos = str.find_first_not_of(cTrim);
613     if (firstPos == std::string::npos) {
614         return str;
615     }
616     auto endPos = str.find_last_not_of(cTrim);
617     return str.substr(firstPos, endPos - firstPos + 1);
618 }
619 
620 inline void TrimStrLeadingAndTrailing(std::string& str, char cTrim = ' ')
621 {
622     auto firstIndexNotOfSpace = str.find_first_not_of(" ");
623     if (firstIndexNotOfSpace == std::string::npos) {
624         str = "";
625         return;
626     }
627     str.erase(0, firstIndexNotOfSpace);
628     auto lastIndexNotOfSpace = str.find_last_not_of(" ");
629     if (lastIndexNotOfSpace == std::string::npos) {
630         str = "";
631         return;
632     }
633     str.erase(lastIndexNotOfSpace + 1);
634 }
635 
636 inline void SplitStr(
637     const std::string& str, const std::string& sep, std::vector<std::string>& out, bool needTrim = true)
638 {
639     out.erase(out.begin(), out.end());
640 
641     if (str.empty() || sep.empty()) {
642         return;
643     }
644 
645     std::string strPart;
646     std::string::size_type startPos = 0;
647     std::string::size_type pos = str.find_first_of(sep, startPos);
648     while (pos != std::string::npos) {
649         if (pos > startPos) {
650             strPart = needTrim ? TrimStr(str.substr(startPos, pos - startPos)) : str.substr(startPos, pos - startPos);
651             out.emplace_back(std::move(strPart));
652         }
653         startPos = pos + sep.size();
654         pos = str.find_first_of(sep, startPos);
655     }
656 
657     if (startPos < str.size()) {
658         strPart = needTrim ? TrimStr(str.substr(startPos)) : str.substr(startPos);
659         out.emplace_back(std::move(strPart));
660     }
661 }
662 
663 inline void SplitStr(const std::string& str, const std::string& sep, std::vector<Dimension>& out, bool needTrim = true)
664 {
665     out.erase(out.begin(), out.end());
666     if (str.empty() || sep.empty()) {
667         return;
668     }
669     std::string strPart;
670     std::string::size_type startPos = 0;
671     std::string::size_type pos = str.find_first_of(sep, startPos);
672     while (pos != std::string::npos) {
673         if (pos > startPos) {
674             strPart = needTrim ? TrimStr(str.substr(startPos, pos - startPos)) : str.substr(startPos, pos - startPos);
675             if (!strPart.empty()) {
676                 out.emplace_back(StringToDimension(std::move(strPart)));
677             }
678         }
679         startPos = pos + sep.size();
680         pos = str.find_first_of(sep, startPos);
681     }
682     if (startPos < str.size()) {
683         strPart = needTrim ? TrimStr(str.substr(startPos)) : str.substr(startPos);
684         if (!strPart.empty()) {
685             out.emplace_back(StringToDimension(std::move(strPart)));
686         }
687     }
688 }
689 
CStringEqual(const char * first,const char * second)690 inline bool CStringEqual(const char* first, const char* second)
691 {
692     if (first == nullptr && second == nullptr) {
693         return true;
694     }
695     if (first && second) {
696         return std::strcmp(first, second) == 0;
697     }
698     return false;
699 }
700 
701 const std::string ACE_FORCE_EXPORT FormatString(const char* fmt, ...);
702 
StartWith(const std::string & dst,const std::string & prefix)703 inline bool StartWith(const std::string& dst, const std::string& prefix)
704 {
705     return dst.compare(0, prefix.size(), prefix) == 0;
706 }
707 
StartWith(const std::string & str,const char * prefix,size_t prefixLen)708 inline bool StartWith(const std::string& str, const char* prefix, size_t prefixLen)
709 {
710     return ((str.length() >= prefixLen) && (str.compare(0, prefixLen, prefix) == 0));
711 }
712 
EndWith(const std::string & dst,const std::string & suffix)713 inline bool EndWith(const std::string& dst, const std::string& suffix)
714 {
715     return (dst.size() >= suffix.size()) && dst.compare(dst.size() - suffix.size(), suffix.size(), suffix) == 0;
716 }
717 
EndWith(const std::string & str,const char * suffix,size_t suffixLen)718 inline bool EndWith(const std::string& str, const char* suffix, size_t suffixLen)
719 {
720     size_t len = str.length();
721     return ((len >= suffixLen) && (str.compare(len - suffixLen, suffixLen, suffix) == 0));
722 }
723 
724 template<typename T>
TransformStrCase(T & str,int32_t textCase)725 inline void TransformStrCase(T& str, int32_t textCase)
726 {
727     if (str.empty()) {
728         return;
729     }
730 
731     switch (textCase) {
732         case TEXT_CASE_LOWERCASE:
733             transform(str.begin(), str.end(), str.begin(), ::tolower);
734             break;
735         case TEXT_CASE_UPPERCASE:
736             transform(str.begin(), str.end(), str.begin(), ::toupper);
737             break;
738         default:
739             break;
740     }
741 }
742 
743 ACE_FORCE_EXPORT bool IsAscii(const std::string& str);
744 } // namespace OHOS::Ace::StringUtils
745 
746 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_UTILS_STRING_UTILS_H
747