Toolbox snapshot
The Reactive C++ Toolbox
Loading...
Searching...
No Matches
String.hpp
Go to the documentation of this file.
1// The Reactive C++ Toolbox.
2// Copyright (C) 2013-2019 Swirly Cloud Limited
3// Copyright (C) 2023 Reactive Markets Limited
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17#ifndef TOOLBOX_UTIL_STRING_HPP
18#define TOOLBOX_UTIL_STRING_HPP
19
22
23#include <charconv>
24#include <cstring>
25#include <sstream>
26
27namespace toolbox {
28inline namespace util {
29
30template <typename ValueT>
31constexpr ValueT from_string(std::string_view sv)
32{
34 return Traits::from_string(sv);
35}
36static_assert(from_string<int>(std::string_view{"-123"}) == -123);
37
38template <typename ValueT>
39constexpr ValueT from_string(const std::string& s)
40{
42 return Traits::from_string(s);
43}
44
45template <typename ValueT>
46constexpr ValueT from_string(const char* s)
47{
49 return Traits::from_string(std::string_view{s});
50}
51static_assert(from_string<int>("-123") == -123);
52
53template <typename ValueT>
54std::string to_string(ValueT&& val)
55{
56 std::stringstream ss;
57 ss << val;
58 return ss.str();
59}
60
61template <typename ValueT>
62// clang-format off
63requires Arithmetic<ValueT>
64std::string to_string(ValueT&& val)
65// clang-format on
66{
67 return std::to_string(val);
68}
69
70template <std::size_t SizeN>
71constexpr std::string_view to_string_view(const char (&val)[SizeN]) noexcept
72{
73 return {val, strnlen(val, SizeN)};
74}
75
76TOOLBOX_API void ltrim(std::string_view& s) noexcept;
77
78TOOLBOX_API void ltrim(std::string& s) noexcept;
79
80TOOLBOX_API void rtrim(std::string_view& s) noexcept;
81
82TOOLBOX_API void rtrim(std::string& s) noexcept;
83
84inline void trim(std::string_view& s) noexcept
85{
86 ltrim(s);
87 rtrim(s);
88}
89
90inline void trim(std::string& s) noexcept
91{
92 ltrim(s);
93 rtrim(s);
94}
95
96inline std::string_view ltrim_copy(std::string_view s) noexcept
97{
98 ltrim(s);
99 return s;
100}
101
102inline std::string ltrim_copy(std::string s) noexcept
103{
104 ltrim(s);
105 return s;
106}
107
108inline std::string_view rtrim_copy(std::string_view s) noexcept
109{
110 rtrim(s);
111 return s;
112}
113
114inline std::string rtrim_copy(std::string s) noexcept
115{
116 rtrim(s);
117 return s;
118}
119
120inline std::string_view trim_copy(std::string_view s) noexcept
121{
122 trim(s);
123 return s;
124}
125
126inline std::string trim_copy(std::string s) noexcept
127{
128 trim(s);
129 return s;
130}
131
132TOOLBOX_API std::pair<std::string_view, std::string_view> split_pair(std::string_view s,
133 char delim) noexcept;
134
135TOOLBOX_API std::pair<std::string, std::string> split_pair(const std::string& s, char delim);
136
142template <char PadC>
143constexpr std::size_t pstrlen(const char* src, std::size_t n) noexcept
144{
145 if constexpr (PadC == '\0') {
146 // Optimised case.
147 return strnlen(src, n);
148 } else {
149 std::size_t i{0};
150 while (i < n && src[i] != PadC) {
151 ++i;
152 }
153 return i;
154 }
155}
156
162template <char PadC, std::size_t SizeN>
163constexpr std::size_t pstrlen(const char (&src)[SizeN]) noexcept
164{
165 return pstrlen<PadC>(src, SizeN);
166}
167
174template <char PadC>
175constexpr std::size_t pstrcpy(char* dst, const char* src, std::size_t n) noexcept
176{
177 if constexpr (PadC == '\0') {
178#ifndef __clang__
179#pragma GCC diagnostic push
180#pragma GCC diagnostic ignored "-Wstringop-truncation"
181#endif
182 // Optimised case.
183 return stpncpy(dst, src, n) - dst;
184#ifndef __clang__
185#pragma GCC diagnostic pop
186#endif
187 } else {
188 std::size_t i{0};
189 for (; i < n && src[i] != '\0'; ++i) {
190 dst[i] = src[i];
191 }
192 if (i < n) {
193 std::memset(dst + i, PadC, n - i);
194 }
195 return i;
196 }
197}
198
205template <char PadC, std::size_t SizeN>
206constexpr std::size_t pstrcpy(char (&dst)[SizeN], const char* src) noexcept
207{
208 return pstrcpy<PadC>(dst, src, SizeN);
209}
210
217template <char PadC>
218constexpr std::size_t pstrcpy(char* dst, std::string_view src, std::size_t n) noexcept
219{
220 const std::size_t len{std::min(n, src.size())};
221 if (len > 0) {
222 std::memcpy(dst, src.data(), len);
223 }
224 if (len < n) {
225 std::memset(dst + len, PadC, n - len);
226 }
227 return len;
228}
229
236template <char PadC, std::size_t SizeN>
237constexpr std::size_t pstrcpy(char (&dst)[SizeN], std::string_view src) noexcept
238{
239 return pstrcpy<PadC>(dst, src, SizeN);
240}
241
242template <char PadC>
243constexpr std::size_t pstrcpyid(char* dst, std::int64_t id, std::size_t n) noexcept
244{
245 auto* end = dst + n;
246 const auto [eptr, ec] = std::to_chars(dst, end, id);
247 if (ec == std::errc::value_too_large) {
248 return 0;
249 }
250 if (eptr < end) {
251 std::memset(eptr, PadC, end - eptr);
252 }
253 return eptr - dst;
254}
255
256template <char PadC, std::size_t SizeN>
257constexpr std::size_t pstrcpyid(char (&dst)[SizeN], std::int64_t id) noexcept
258{
259 return pstrcpyid<PadC>(dst, id, SizeN);
260}
261
267template <char PadC>
268constexpr std::size_t lpstrlen(const char* src, std::size_t n) noexcept
269{
270 std::size_t i{0};
271 while (i < n && src[i] == PadC) {
272 ++i;
273 }
274 return n - i;
275}
276
282template <char PadC, std::size_t SizeN>
283constexpr std::size_t lpstrlen(const char (&src)[SizeN]) noexcept
284{
285 return lpstrlen<PadC>(src, SizeN);
286}
287
294template <char PadC>
295constexpr std::size_t lpstrcpy(char* dst, const char* src, std::size_t n) noexcept
296{
297 const std::size_t len{strnlen(src, n)};
298 if (len < n) {
299 std::memset(dst, PadC, n - len);
300 }
301 if (len > 0) {
302 std::memcpy(dst + (n - len), src, len);
303 }
304 return len;
305}
306
313template <char PadC, std::size_t SizeN>
314constexpr std::size_t lpstrcpy(char (&dst)[SizeN], const char* src) noexcept
315{
316 return lpstrcpy<PadC>(dst, src, SizeN);
317}
318
325template <char PadC>
326constexpr std::size_t lpstrcpy(char* dst, std::string_view src, std::size_t n) noexcept
327{
328 const std::size_t len{std::min(n, src.size())};
329 if (len < n) {
330 std::memset(dst, PadC, n - len);
331 }
332 if (len > 0) {
333 std::memcpy(dst + (n - len), src.data(), len);
334 }
335 return len;
336}
337
344template <char PadC, std::size_t SizeN>
345constexpr std::size_t lpstrcpy(char (&dst)[SizeN], std::string_view src) noexcept
346{
347 return lpstrcpy<PadC>(dst, src, SizeN);
348}
349
350template <typename... ArgsT>
351std::string make_string(ArgsT&&... args)
352{
353 std::stringstream os;
354 (os << ... << args);
355 return os.str();
356}
357} // namespace util
358} // namespace toolbox
359
360#endif // TOOLBOX_UTIL_STRING_HPP
#define TOOLBOX_API
Definition Config.h:39
std::string to_string(ValueT &&val)
Definition String.hpp:54
pair< string_view, string_view > split_pair(string_view s, char delim) noexcept
Definition String.cpp:51
void rtrim(string_view &s) noexcept
Definition String.cpp:39
void trim(std::string_view &s) noexcept
Definition String.hpp:84
constexpr std::size_t lpstrlen(const char *src, std::size_t n) noexcept
Definition String.hpp:268
std::string make_string(ArgsT &&... args)
Definition String.hpp:351
std::string_view ltrim_copy(std::string_view s) noexcept
Definition String.hpp:96
std::string_view rtrim_copy(std::string_view s) noexcept
Definition String.hpp:108
void ltrim(string_view &s) noexcept
Definition String.cpp:27
constexpr std::string_view to_string_view(const char(&val)[SizeN]) noexcept
Definition String.hpp:71
constexpr std::size_t pstrlen(const char *src, std::size_t n) noexcept
Definition String.hpp:143
constexpr ValueT from_string(std::string_view sv)
Definition String.hpp:31
std::string_view sv
Definition Tokeniser.hpp:26
std::string_view trim_copy(std::string_view s) noexcept
Definition String.hpp:120
constexpr std::size_t pstrcpy(char *dst, const char *src, std::size_t n) noexcept
Definition String.hpp:175
constexpr std::size_t pstrcpyid(char *dst, std::int64_t id, std::size_t n) noexcept
Definition String.hpp:243
constexpr std::size_t lpstrcpy(char *dst, const char *src, std::size_t n) noexcept
Definition String.hpp:295
constexpr auto bind() noexcept
Definition Slot.hpp:92