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 CORE_UTIL_STRING_UTIL_H
17 #define CORE_UTIL_STRING_UTIL_H
18 
19 #include <algorithm>
20 #include <cctype>
21 #include <cstdint>
22 #include <iterator>
23 
24 #include <3d/namespace.h>
25 #include <base/containers/string_view.h>
26 #include <base/containers/vector.h>
27 
CORE3D_BEGIN_NAMESPACE()28 CORE3D_BEGIN_NAMESPACE()
29 namespace StringUtil {
30 template<class T, size_t N>
31 constexpr size_t MaxStringLengthFromArray(T (&)[N])
32 {
33     return N - 1u;
34 }
35 
36 inline void CopyStringToArray(const BASE_NS::string_view source, char* target, size_t maxLength)
37 {
38     if (source.size() > maxLength) {
39         CORE_LOG_W("CopyStringToArray: string (%zu) longer than %zu", source.size(), maxLength);
40     }
41     size_t const length = source.copy(target, maxLength);
42     target[length] = '\0';
43 }
44 
45 inline bool NotSpace(unsigned char ch)
46 {
47     return !std::isspace(static_cast<int>(ch));
48 }
49 
50 // trim from start (in place)
51 inline void LTrim(BASE_NS::string_view& string)
52 {
53     auto const count = size_t(std::find_if(string.begin(), string.end(), NotSpace) - string.begin());
54     string.remove_prefix(count);
55 }
56 
57 // trim from end (in place)
58 inline void RTrim(BASE_NS::string_view& string)
59 {
60     auto const count =
61         size_t(std::distance(std::find_if(string.rbegin(), string.rend(), NotSpace).base(), string.end()));
62     string.remove_suffix(count);
63 }
64 
65 // trim from both ends (in place)
66 inline size_t Trim(BASE_NS::string_view& string)
67 {
68     RTrim(string);
69     LTrim(string);
70     return string.length();
71 }
72 
73 inline BASE_NS::vector<BASE_NS::string_view> Split(
74     const BASE_NS::string_view string, const BASE_NS::string_view delims = "|")
75 {
76     BASE_NS::vector<BASE_NS::string_view> output;
77     auto left = string;
78 
79     while (!left.empty()) {
80         auto const pos = left.find_first_of(delims);
81 
82         auto found = left.substr(0, pos);
83         if (Trim(found) > 0) {
84             output.push_back(found);
85         }
86         if (pos != BASE_NS::string_view::npos) {
87             left.remove_prefix(pos + 1);
88         } else {
89             break;
90         }
91     }
92 
93     return output;
94 }
95 } // namespace StringUtil
96 CORE3D_END_NAMESPACE()
97 
98 #endif // CORE_UTIL_STRING_UTIL_H
99