1 /*
2 * Copyright (c) 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
16 #ifndef UTIL_STRING_UTIL_H
17 #define UTIL_STRING_UTIL_H
18
19 #include <algorithm>
20 #include <cctype>
21 #include <cstdint>
22 #include <iterator>
23
24 #include <base/containers/string_view.h>
25 #include <base/containers/vector.h>
26 #include <render/namespace.h>
27
28 #include "util/log.h"
29
RENDER_BEGIN_NAMESPACE()30 RENDER_BEGIN_NAMESPACE()
31 namespace StringUtil {
32 template<class T, size_t N>
33 constexpr size_t MaxStringLengthFromArray(T (&)[N])
34 {
35 return N - 1u;
36 }
37
38 inline void CopyStringToArray(const BASE_NS::string_view source, char* target, size_t maxLength)
39 {
40 if (source.size() > maxLength) {
41 PLUGIN_LOG_W("CopyStringToArray: string (%zu) longer than %zu", source.size(), maxLength);
42 }
43 size_t const length = source.copy(target, maxLength);
44 target[length] = '\0';
45 }
46
47 inline bool NotSpace(unsigned char ch)
48 {
49 return !std::isspace(static_cast<int>(ch));
50 }
51
52 // trim from start (in place)
53 inline void LTrim(BASE_NS::string_view& string)
54 {
55 auto const count = size_t(std::find_if(string.begin(), string.end(), NotSpace) - string.begin());
56 string.remove_prefix(count);
57 }
58
59 // trim from end (in place)
60 inline void RTrim(BASE_NS::string_view& string)
61 {
62 auto const count =
63 size_t(std::distance(std::find_if(string.rbegin(), string.rend(), NotSpace).base(), string.end()));
64 string.remove_suffix(count);
65 }
66
67 // trim from both ends (in place)
68 inline size_t Trim(BASE_NS::string_view& string)
69 {
70 RTrim(string);
71 LTrim(string);
72 return string.length();
73 }
74
75 inline BASE_NS::vector<BASE_NS::string_view> Split(
76 const BASE_NS::string_view string, const BASE_NS::string_view delims = "|")
77 {
78 BASE_NS::vector<BASE_NS::string_view> output;
79 auto left = string;
80
81 while (!left.empty()) {
82 auto const pos = left.find_first_of(delims);
83
84 auto found = left.substr(0, pos);
85 if (Trim(found) > 0) {
86 output.push_back(found);
87 }
88 if (pos != BASE_NS::string_view::npos) {
89 left.remove_prefix(pos + 1);
90 } else {
91 break;
92 }
93 }
94
95 return output;
96 }
97
98 // find and replace first instance of "find" with "replace" in "source"
99 inline bool FindAndReplaceOne(
100 BASE_NS::string& source, const BASE_NS::string_view find, const BASE_NS::string_view replace)
101 {
102 const auto p = source.find(find);
103 if (p != BASE_NS::string::npos) {
104 source.replace(source.begin() + static_cast<BASE_NS::string::difference_type>(p),
105 source.begin() + static_cast<BASE_NS::string::difference_type>(p + find.length()), replace);
106 }
107 return (p != BASE_NS::string::npos);
108 }
109 // find and replace all instances of "find" with "replace" in "source"
110 inline void FindAndReplaceAll(
111 BASE_NS::string& source, const BASE_NS::string_view find, const BASE_NS::string_view replace)
112 {
113 while (FindAndReplaceOne(source, find, replace))
114 ;
115 }
116 } // namespace StringUtil
117 RENDER_END_NAMESPACE()
118
119 #endif // UTIL_STRING_UTIL_H
120