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
31namespace ailego {
32
33/*! String Helper
34 */
35struct 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 LeftTrim(std::string &str);
64
65 // Trim from end (in place)
66 static void RightTrim(std::string &str);
67
68 // Trim from both ends (in place)
69 static void Trim(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
280inline std::string StringHelper::Concat(const internal::Alphameric &a) {
281 std::string result;
282 Append(&result, a);
283 return result;
284}
285
286inline 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
293inline 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
301inline 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