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