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