1 | /** |
2 | * Copyright 2021 Alibaba, Inc. and its affiliates. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | |
16 | * \author Hechong.xyf |
17 | * \date Dec 2017 |
18 | * \brief Interface of AiLego Utility String Helper |
19 | */ |
20 | |
21 | #ifndef __AILEGO_UTILITY_STRING_HELPER_H__ |
22 | #define __AILEGO_UTILITY_STRING_HELPER_H__ |
23 | |
24 | #include <algorithm> |
25 | #include <string> |
26 | #include <vector> |
27 | #include <ailego/internal/platform.h> |
28 | #include <ailego/string/string_concat_helper.h> |
29 | #include "string_helper_impl.h" |
30 | |
31 | namespace ailego { |
32 | |
33 | /*! String Helper |
34 | */ |
35 | struct StringHelper { |
36 | //! Return true if the `ref` starts with the given prefix |
37 | static bool StartsWith(const std::string &ref, const std::string &prefix); |
38 | |
39 | //! Return true if the `ref` ends with the given suffix |
40 | static bool EndsWith(const std::string &ref, const std::string &suffix); |
41 | |
42 | //! Split a string into a vector of T |
43 | //! NOTE: delim better NOT contain valid symbol for T, |
44 | //! i.e. digits + - for integers, |
45 | //! digits + - E e . for floating numbers |
46 | //! otherwise there will be performance overhead. |
47 | template <typename T> |
48 | static void Split(const std::string &str, char delim, std::vector<T> *out) { |
49 | return details::SplitImpl<char, T>(str, delim, out); |
50 | } |
51 | template <typename T> |
52 | static void Split(const std::string &str, const char *delim, |
53 | std::vector<T> *out) { |
54 | return details::SplitImpl<const char *, T>(str, delim, out); |
55 | } |
56 | template <typename T> |
57 | static void Split(const std::string &str, const std::string &delim, |
58 | std::vector<T> *out) { |
59 | return details::SplitImpl<const std::string &, T>(str, delim, out); |
60 | } |
61 | |
62 | // Trim from start (in place) |
63 | static void (std::string &str); |
64 | |
65 | // Trim from end (in place) |
66 | static void (std::string &str); |
67 | |
68 | // Trim from both ends (in place) |
69 | static void (std::string &str); |
70 | |
71 | // Trim from start (copying) |
72 | static std::string CopyLeftTrim(std::string str); |
73 | |
74 | // Trim from end (copying) |
75 | static std::string CopyRightTrim(std::string str); |
76 | |
77 | // Trim from both ends (copying) |
78 | static std::string CopyTrim(std::string str); |
79 | |
80 | //! Compare ignore case |
81 | static bool CompareIgnoreCase(const std::string &a, const std::string &b); |
82 | |
83 | //! Convert string to floating-point number (double) |
84 | static bool ToDouble(const std::string &str, double *val) { |
85 | char *endptr = nullptr; |
86 | *val = std::strtod(str.c_str(), &endptr); |
87 | return (endptr && *endptr == '\0'); |
88 | } |
89 | |
90 | //! Convert string to floating-point number (float) |
91 | static bool ToFloat(const std::string &str, float *val) { |
92 | char *endptr = nullptr; |
93 | *val = std::strtof(str.c_str(), &endptr); |
94 | return (endptr && *endptr == '\0'); |
95 | } |
96 | |
97 | //! Convert string to integer number (int8_t) |
98 | static bool ToInt8(const std::string &str, int8_t *val) { |
99 | char *endptr = nullptr; |
100 | *val = static_cast<int8_t>(std::strtol(str.c_str(), &endptr, 0)); |
101 | return (endptr && *endptr == '\0'); |
102 | } |
103 | |
104 | //! Convert string to integer number (int16_t) |
105 | static bool ToInt16(const std::string &str, int16_t *val) { |
106 | char *endptr = nullptr; |
107 | *val = static_cast<int16_t>(std::strtol(str.c_str(), &endptr, 0)); |
108 | return (endptr && *endptr == '\0'); |
109 | } |
110 | |
111 | //! Convert string to integer number (int32_t) |
112 | static bool ToInt32(const std::string &str, int32_t *val) { |
113 | char *endptr = nullptr; |
114 | *val = static_cast<int32_t>(std::strtol(str.c_str(), &endptr, 0)); |
115 | return (endptr && *endptr == '\0'); |
116 | } |
117 | |
118 | //! Convert string to integer number (int64_t) |
119 | static bool ToInt64(const std::string &str, int64_t *val) { |
120 | char *endptr = nullptr; |
121 | *val = static_cast<int64_t>(std::strtoll(str.c_str(), &endptr, 0)); |
122 | return (endptr && *endptr == '\0'); |
123 | } |
124 | |
125 | //! Convert string to unsigned integer number (uint8_t) |
126 | static bool ToUint8(const std::string &str, uint8_t *val) { |
127 | char *endptr = nullptr; |
128 | *val = static_cast<uint8_t>(std::strtoul(str.c_str(), &endptr, 0)); |
129 | return (endptr && *endptr == '\0'); |
130 | } |
131 | |
132 | //! Convert string to unsigned integer number (uint16_t) |
133 | static bool ToUint16(const std::string &str, uint16_t *val) { |
134 | char *endptr = nullptr; |
135 | *val = static_cast<uint16_t>(std::strtoul(str.c_str(), &endptr, 0)); |
136 | return (endptr && *endptr == '\0'); |
137 | } |
138 | |
139 | //! Convert string to unsigned integer number (uint32_t) |
140 | static bool ToUint32(const std::string &str, uint32_t *val) { |
141 | char *endptr = nullptr; |
142 | *val = static_cast<uint32_t>(std::strtoul(str.c_str(), &endptr, 0)); |
143 | return (endptr && *endptr == '\0'); |
144 | } |
145 | |
146 | //! Convert string to unsigned integer number (uint64_t) |
147 | static bool ToUint64(const std::string &str, uint64_t *val) { |
148 | char *endptr = nullptr; |
149 | *val = static_cast<uint64_t>(std::strtoull(str.c_str(), &endptr, 0)); |
150 | return (endptr && *endptr == '\0'); |
151 | } |
152 | |
153 | //! Convert floating-point number string (double) |
154 | static std::string ToString(double val) { |
155 | return std::to_string(val); |
156 | } |
157 | |
158 | //! Convert floating-point number string (float) |
159 | static std::string ToString(float val) { |
160 | return std::to_string(val); |
161 | } |
162 | |
163 | //! Convert integer number to string (int8_t) |
164 | static std::string ToString(int8_t val) { |
165 | return std::to_string(val); |
166 | } |
167 | |
168 | //! Convert integer number to string (int16_t) |
169 | static std::string ToString(int16_t val) { |
170 | return std::to_string(val); |
171 | } |
172 | |
173 | //! Convert integer number to string (int32_t) |
174 | static std::string ToString(int32_t val) { |
175 | return std::to_string(val); |
176 | } |
177 | |
178 | //! Convert integer number to string (int64_t) |
179 | static std::string ToString(int64_t val) { |
180 | return std::to_string(val); |
181 | } |
182 | |
183 | //! Convert unsigned integer number to string (uint8_t) |
184 | static std::string ToString(uint8_t val) { |
185 | return std::to_string(val); |
186 | } |
187 | |
188 | //! Convert unsigned integer number to string (uint16_t) |
189 | static std::string ToString(uint16_t val) { |
190 | return std::to_string(val); |
191 | } |
192 | |
193 | //! Convert unsigned integer number to string (uint32_t) |
194 | static std::string ToString(uint32_t val) { |
195 | return std::to_string(val); |
196 | } |
197 | |
198 | //! Convert unsigned integer number to string (uint64_t) |
199 | static std::string ToString(uint64_t val) { |
200 | return std::to_string(val); |
201 | } |
202 | |
203 | //! Concatenation of arbitrary number of std::string, c-string, integers, |
204 | //! floating point numbers with one memory allocation. |
205 | //! E.g. auto s = Concat("foo", 123, std::string("bar"), 3.14159); |
206 | //! |
207 | //! Do not do the following, use Append instead |
208 | //! str = Concat(str, ...); |
209 | //! str.append(Concat(str, ...)); |
210 | //! str += Concat(str, ...); |
211 | //! |
212 | //! NOTE: char literal(e.g. ':') is not allowed, |
213 | //! use string literal(e.g. ":") instead. |
214 | static std::string Concat() { |
215 | return {}; |
216 | } |
217 | static std::string Concat(const internal::Alphameric &a); |
218 | static std::string Concat(const internal::Alphameric &a, |
219 | const internal::Alphameric &b); |
220 | static std::string Concat(const internal::Alphameric &a, |
221 | const internal::Alphameric &b, |
222 | const internal::Alphameric &c); |
223 | static std::string Concat(const internal::Alphameric &a, |
224 | const internal::Alphameric &b, |
225 | const internal::Alphameric &c, |
226 | const internal::Alphameric &d); |
227 | // Support 5 or more arguments |
228 | template <typename... T> |
229 | static std::string Concat(const internal::Alphameric &a, |
230 | const internal::Alphameric &b, |
231 | const internal::Alphameric &c, |
232 | const internal::Alphameric &d, |
233 | const internal::Alphameric &e, const T &...args) { |
234 | std::string result; |
235 | Append(&result, a, b, c, d, e, args...); |
236 | return result; |
237 | } |
238 | |
239 | //! Append arbitrary number of std::string, c-string, integers, |
240 | //! floating point numbers to existing string with one memory allocation. |
241 | //! E.g. Append(&str, "foo", 123, std::string("bar"), 3.14159); |
242 | //! |
243 | //! WARNING: Append requires that none of the arguments be a reference to |
244 | //! destination str. |
245 | //! |
246 | //! Do not do the following |
247 | //! std::string s = "foo"; |
248 | //! Append(&s, s); |
249 | //! |
250 | //! NOTE: char literal(e.g. ':') is not allowed, |
251 | //! use string literal(e.g. ":") instead. |
252 | static void Append(std::string *) {} |
253 | static void Append(std::string *str, const internal::Alphameric &a); |
254 | static void Append(std::string *str, const internal::Alphameric &a, |
255 | const internal::Alphameric &b); |
256 | static void Append(std::string *str, const internal::Alphameric &a, |
257 | const internal::Alphameric &b, |
258 | const internal::Alphameric &c); |
259 | static void Append(std::string *str, const internal::Alphameric &a, |
260 | const internal::Alphameric &b, |
261 | const internal::Alphameric &c, |
262 | const internal::Alphameric &d); |
263 | // Support 5 or more arguments |
264 | template <typename... T> |
265 | static void Append(std::string *str, const internal::Alphameric &a, |
266 | const internal::Alphameric &b, |
267 | const internal::Alphameric &c, |
268 | const internal::Alphameric &d, |
269 | const internal::Alphameric &e, const T &...args) { |
270 | AppendViews(str, |
271 | {a.view(), b.view(), c.view(), d.view(), e.view(), |
272 | static_cast<const internal::Alphameric &>(args).view()...}); |
273 | } |
274 | |
275 | //! Append list of StringView to str. |
276 | static void AppendViews(std::string *str, |
277 | std::initializer_list<StringView> views); |
278 | }; |
279 | |
280 | inline std::string StringHelper::Concat(const internal::Alphameric &a) { |
281 | std::string result; |
282 | Append(&result, a); |
283 | return result; |
284 | } |
285 | |
286 | inline std::string StringHelper::Concat(const internal::Alphameric &a, |
287 | const internal::Alphameric &b) { |
288 | std::string result; |
289 | Append(&result, a, b); |
290 | return result; |
291 | } |
292 | |
293 | inline std::string StringHelper::Concat(const internal::Alphameric &a, |
294 | const internal::Alphameric &b, |
295 | const internal::Alphameric &c) { |
296 | std::string result; |
297 | Append(&result, a, b, c); |
298 | return result; |
299 | } |
300 | |
301 | inline std::string StringHelper::Concat(const internal::Alphameric &a, |
302 | const internal::Alphameric &b, |
303 | const internal::Alphameric &c, |
304 | const internal::Alphameric &d) { |
305 | std::string result; |
306 | Append(&result, a, b, c, d); |
307 | return result; |
308 | } |
309 | |
310 | |
311 | } // namespace ailego |
312 | |
313 | #endif // __AILEGO_UTILITY_STRING_HELPER_H__ |
314 | |