Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #ifndef CORE_CORE_STRING_SPSTRINGSTREAM_H_
24 : #define CORE_CORE_STRING_SPSTRINGSTREAM_H_
25 :
26 : #include "SPStringView.h"
27 :
28 : namespace STAPPLER_VERSIONIZED stappler {
29 :
30 : namespace string {
31 :
32 : template <typename Interface>
33 : auto toUtf16(const StringView &data) -> typename Interface::WideStringType;
34 :
35 : template <typename Interface>
36 : auto toUtf16(char32_t) -> typename Interface::WideStringType;
37 :
38 : template <typename Interface>
39 : auto toUtf16Html(const StringView &data) -> typename Interface::WideStringType;
40 :
41 : template <typename Interface>
42 : auto toUtf8(const WideStringView &data) -> typename Interface::StringType;
43 :
44 : template <typename Interface>
45 : auto toUtf8(char16_t c) -> typename Interface::StringType;
46 :
47 : template <typename Interface>
48 : auto toUtf8(char32_t c) -> typename Interface::StringType;
49 :
50 : }
51 :
52 : namespace detail {
53 :
54 : template <typename FunctionalStreamArg>
55 : struct FunctionalStreamCharTraits { };
56 :
57 : template <typename Char>
58 : struct FunctionalStreamCharTraits<StringViewBase<Char>> {
59 : using CharType = Char;
60 : };
61 :
62 : template <>
63 : struct FunctionalStreamCharTraits<StringViewUtf8> {
64 : using CharType = StringViewUtf8::CharType;
65 : };
66 :
67 : template <typename FunctionalStream>
68 : struct FunctionalStreamTraits { };
69 :
70 : template <typename Arg>
71 : struct FunctionalStreamTraits<Callback<void(Arg)>> {
72 : using ArgType = Arg;
73 : using CharType = typename FunctionalStreamCharTraits<ArgType>::CharType;
74 : };
75 :
76 : template <typename Arg>
77 : struct FunctionalStreamTraits<std::function<void(Arg)>> {
78 : using ArgType = Arg;
79 : using CharType = typename FunctionalStreamCharTraits<ArgType>::CharType;
80 : };
81 :
82 : template <typename Arg>
83 : struct FunctionalStreamTraits<memory::function<void(Arg)>> {
84 : using ArgType = Arg;
85 : using CharType = typename FunctionalStreamCharTraits<ArgType>::CharType;
86 : };
87 :
88 : template <typename FunctionalStream>
89 898096725 : inline void streamWrite(const FunctionalStream &stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType str) {
90 898096725 : stream(str);
91 898096725 : }
92 :
93 : template <typename FunctionalStream>
94 1646000 : inline void streamWrite(const FunctionalStream &stream, const typename FunctionalStreamTraits<FunctionalStream>::CharType *str) {
95 1646000 : streamWrite(stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType(str));
96 1646000 : }
97 :
98 : template <typename FunctionalStream, size_t N>
99 : inline void streamWrite(const FunctionalStream &stream, const typename FunctionalStreamTraits<FunctionalStream>::CharType str[N]) {
100 : streamWrite(stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType(str, N));
101 : }
102 :
103 : template <typename FunctionalStream>
104 6550 : inline void streamWrite(const FunctionalStream &stream, double d) {
105 6550 : std::array<typename FunctionalStreamTraits<FunctionalStream>::CharType, string::DOUBLE_MAX_DIGITS> buf = { 0 };
106 6550 : auto ret = string::_dtoa(d, buf.data(), buf.size());
107 6550 : streamWrite(stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType(buf.data(), ret));
108 6550 : }
109 :
110 : template <typename FunctionalStream>
111 : inline void streamWrite(const FunctionalStream &stream, float f) {
112 : streamWrite(stream, double(f));
113 : }
114 :
115 : template <typename FunctionalStream>
116 653775 : inline void streamWrite(const FunctionalStream &stream, int64_t i) {
117 653775 : std::array<typename FunctionalStreamTraits<FunctionalStream>::CharType, std::numeric_limits<int64_t>::digits10 + 2> buf = { 0 };
118 653775 : auto ret = string::_itoa(i, buf.data(), buf.size());
119 653775 : streamWrite(stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType(buf.data() + buf.size() - ret, ret));
120 653775 : }
121 :
122 : template <typename FunctionalStream>
123 29850 : inline void streamWrite(const FunctionalStream &stream, uint64_t i) {
124 29850 : std::array<typename FunctionalStreamTraits<FunctionalStream>::CharType, std::numeric_limits<int64_t>::digits10 + 2> buf = { 0 };
125 29850 : auto ret = string::_itoa(i, buf.data(), buf.size());
126 29850 : streamWrite(stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType(buf.data() + buf.size() - ret, ret));
127 29850 : }
128 :
129 : template <typename FunctionalStream>
130 : inline void streamWrite(const FunctionalStream &stream, int32_t i) {
131 : streamWrite(stream, int64_t(i));
132 : }
133 :
134 : template <typename FunctionalStream>
135 13750 : inline void streamWrite(const FunctionalStream &stream, uint32_t i) {
136 13750 : streamWrite(stream, uint64_t(i));
137 13750 : }
138 :
139 : template <typename FunctionalStream>
140 : inline void streamWrite(const FunctionalStream &stream, int16_t i) {
141 : streamWrite(stream, int64_t(i));
142 : }
143 :
144 : template <typename FunctionalStream>
145 15725 : inline void streamWrite(const FunctionalStream &stream, uint16_t i) {
146 15725 : streamWrite(stream, uint64_t(i));
147 15725 : }
148 :
149 : template <typename FunctionalStream>
150 : inline void streamWrite(const FunctionalStream &stream, int8_t i) {
151 : streamWrite(stream, int64_t(i));
152 : }
153 :
154 : template <typename FunctionalStream>
155 0 : inline void streamWrite(const FunctionalStream &stream, uint8_t i) {
156 0 : streamWrite(stream, uint64_t(i));
157 0 : }
158 :
159 : template <typename FunctionalStream>
160 50 : inline void streamWrite(const FunctionalStream &stream, char32_t c) {
161 : if constexpr (sizeof(typename FunctionalStreamTraits<FunctionalStream>::CharType) == 1) {
162 25 : std::array<typename FunctionalStreamTraits<FunctionalStream>::CharType, 6> buf = { 0 };
163 25 : streamWrite(stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType(buf.data(), unicode::utf8EncodeBuf(buf.data(), c)));
164 : } else {
165 25 : std::array<typename FunctionalStreamTraits<FunctionalStream>::CharType, 6> buf = { 0 };
166 25 : streamWrite(stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType(buf.data(), unicode::utf16EncodeBuf(buf.data(), c)));
167 : }
168 50 : }
169 :
170 : template <typename FunctionalStream>
171 50 : inline void streamWrite(const FunctionalStream &stream, char16_t c) {
172 : if constexpr (sizeof(typename FunctionalStreamTraits<FunctionalStream>::CharType) == 1) {
173 25 : std::array<typename FunctionalStreamTraits<FunctionalStream>::CharType, 4> buf = { 0 };
174 25 : streamWrite(stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType(buf.data(), unicode::utf8EncodeBuf(buf.data(), c)));
175 : } else {
176 25 : streamWrite(stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType(&c, 1));
177 : }
178 50 : }
179 :
180 : template <typename FunctionalStream>
181 894570725 : inline void streamWrite(const FunctionalStream &stream, char c) {
182 : if constexpr (sizeof(typename FunctionalStreamTraits<FunctionalStream>::CharType) == 1) {
183 894570700 : streamWrite(stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType(&c, 1));
184 : } else {
185 25 : char16_t ch = c;
186 25 : streamWrite(stream, typename FunctionalStreamTraits<FunctionalStream>::ArgType(&ch, 1));
187 : }
188 894570725 : }
189 :
190 : }
191 :
192 : #define SP_DEFINE_STREAM_OVERLOADS(Type, Char) \
193 : inline auto operator<<(const Type &stream, const Char *val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
194 : template <size_t N> inline auto operator<<(const Type &stream, const Char val[N]) -> const Type & { detail::streamWrite(stream, val); return stream; } \
195 : inline auto operator<<(const Type &stream, double val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
196 : inline auto operator<<(const Type &stream, float val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
197 : inline auto operator<<(const Type &stream, int64_t val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
198 : inline auto operator<<(const Type &stream, uint64_t val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
199 : inline auto operator<<(const Type &stream, int32_t val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
200 : inline auto operator<<(const Type &stream, uint32_t val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
201 : inline auto operator<<(const Type &stream, int16_t val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
202 : inline auto operator<<(const Type &stream, uint16_t val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
203 : inline auto operator<<(const Type &stream, int8_t val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
204 : inline auto operator<<(const Type &stream, uint8_t val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
205 : inline auto operator<<(const Type &stream, char32_t val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
206 : inline auto operator<<(const Type &stream, char16_t val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
207 : inline auto operator<<(const Type &stream, char val) -> const Type & { detail::streamWrite(stream, val); return stream; } \
208 :
209 1189725 : inline auto operator<<(const Callback<void(StringViewBase<char>)> &cb, const StringViewBase<char> &val) -> const Callback<void(StringViewBase<char>)> & {
210 1189725 : detail::streamWrite(cb, val);
211 1189725 : return cb;
212 : }
213 :
214 : inline auto operator<<(const Callback<void(StringViewBase<char16_t>)> &cb, const StringViewBase<char16_t> &val) -> const Callback<void(StringViewBase<char16_t>)> & {
215 : detail::streamWrite(cb, val);
216 : return cb;
217 : }
218 :
219 : inline auto operator<<(const Callback<void(StringViewUtf8)> &cb, const StringViewUtf8 &val) -> const Callback<void(StringViewUtf8)> & {
220 : detail::streamWrite(cb, val);
221 : return cb;
222 : }
223 :
224 : inline auto operator<<(const std::function<void(StringViewBase<char>)> &cb, const StringViewBase<char> &val) -> const std::function<void(StringViewBase<char>)> & {
225 : detail::streamWrite(cb, val);
226 : return cb;
227 : }
228 :
229 : inline auto operator<<(const std::function<void(StringViewBase<char16_t>)> &cb, const StringViewBase<char16_t> &val) -> const std::function<void(StringViewBase<char16_t>)> & {
230 : detail::streamWrite(cb, val);
231 : return cb;
232 : }
233 :
234 : inline auto operator<<(const std::function<void(StringViewUtf8)> &cb, const StringViewUtf8 &val) -> const std::function<void(StringViewUtf8)> & {
235 : detail::streamWrite(cb, val);
236 : return cb;
237 : }
238 :
239 : inline auto operator<<(const memory::function<void(StringViewBase<char>)> &cb, const StringViewBase<char> &val) -> const memory::function<void(StringViewBase<char>)> & {
240 : detail::streamWrite(cb, val);
241 : return cb;
242 : }
243 :
244 : inline auto operator<<(const memory::function<void(StringViewBase<char16_t>)> &cb, const StringViewBase<char16_t> &val) -> const memory::function<void(StringViewBase<char16_t>)> & {
245 : detail::streamWrite(cb, val);
246 : return cb;
247 : }
248 :
249 : inline auto operator<<(const memory::function<void(StringViewUtf8)> &cb, const StringViewUtf8 &val) -> const memory::function<void(StringViewUtf8)> & {
250 : detail::streamWrite(cb, val);
251 : return cb;
252 : }
253 :
254 0 : inline auto operator<<(const Callback<void(BytesView)> &cb, const BytesView &val) -> const Callback<void(BytesView)> & {
255 0 : cb(val);
256 0 : return cb;
257 : }
258 :
259 0 : inline auto operator<<(const Callback<void(BytesView)> &cb, const uint8_t &val) -> const Callback<void(BytesView)> & {
260 0 : cb(BytesView(&val, 1));
261 0 : return cb;
262 : }
263 :
264 : inline auto operator<<(const std::function<void(BytesView)> &cb, const BytesView &val) -> const std::function<void(BytesView)> & {
265 : cb(val);
266 : return cb;
267 : }
268 :
269 : inline auto operator<<(const std::function<void(BytesView)> &cb, const uint8_t &val) -> const std::function<void(BytesView)> & {
270 : cb(BytesView(&val, 1));
271 : return cb;
272 : }
273 :
274 : inline auto operator<<(const memory::function<void(BytesView)> &cb, const BytesView &val) -> const memory::function<void(BytesView)> & {
275 : cb(val);
276 : return cb;
277 : }
278 :
279 : inline auto operator<<(const memory::function<void(BytesView)> &cb, const uint8_t &val) -> const memory::function<void(BytesView)> & {
280 : cb(BytesView(&val, 1));
281 : return cb;
282 : }
283 :
284 896906725 : SP_DEFINE_STREAM_OVERLOADS(Callback<void(StringViewBase<char>)>,char)
285 275 : SP_DEFINE_STREAM_OVERLOADS(Callback<void(StringViewBase<char16_t>)>,char16_t)
286 : SP_DEFINE_STREAM_OVERLOADS(Callback<void(StringViewUtf8)>,char)
287 :
288 : SP_DEFINE_STREAM_OVERLOADS(std::function<void(StringViewBase<char>)>,char)
289 : SP_DEFINE_STREAM_OVERLOADS(std::function<void(StringViewBase<char16_t>)>,char16_t)
290 : SP_DEFINE_STREAM_OVERLOADS(std::function<void(StringViewUtf8)>,char)
291 :
292 : SP_DEFINE_STREAM_OVERLOADS(memory::function<void(StringViewBase<char>)>,char)
293 : SP_DEFINE_STREAM_OVERLOADS(memory::function<void(StringViewBase<char16_t>)>,char16_t)
294 : SP_DEFINE_STREAM_OVERLOADS(memory::function<void(StringViewUtf8)>,char)
295 :
296 : #undef SP_DEFINE_STREAM_OVERLOADS
297 :
298 : namespace string {
299 :
300 : namespace detail {
301 :
302 2650 : inline size_t toStringValue(char *target, double val) {
303 2650 : return string::_dtoa(val, target, string::DOUBLE_MAX_DIGITS);
304 : }
305 :
306 518604 : inline size_t toStringValue(char *target, float val) {
307 518604 : return string::_dtoa(val, target, string::DOUBLE_MAX_DIGITS);
308 : }
309 :
310 1800 : inline size_t toStringValue(char *target, int64_t val) {
311 1800 : auto len = string::_itoa_len(val);
312 1800 : return string::_itoa(val, target, len);
313 : }
314 :
315 27468 : inline size_t toStringValue(char *target, uint64_t val) {
316 27468 : auto len = string::_itoa_len(val);
317 27468 : return string::_itoa(val, target, len);
318 : }
319 :
320 687628 : inline size_t toStringValue(char *target, int32_t val) {
321 687628 : auto len = string::_itoa_len(int64_t(val));
322 687628 : return string::_itoa(int64_t(val), target, len);
323 : }
324 :
325 11573 : inline size_t toStringValue(char *target, uint32_t val) {
326 11573 : auto len = string::_itoa_len(uint64_t(val));
327 11573 : return string::_itoa(uint64_t(val), target, len);
328 : }
329 :
330 : inline size_t toStringValue(char *target, char32_t val) {
331 : return unicode::utf8EncodeBuf(target, val);
332 : }
333 :
334 : inline size_t toStringValue(char *target, char16_t val) {
335 : return unicode::utf8EncodeBuf(target, val);
336 : }
337 :
338 200 : inline size_t toStringValue(char *target, char val) {
339 200 : *target = val;
340 200 : return 1;
341 : }
342 :
343 530919 : inline size_t toStringValue(char *target, const StringView &val) {
344 530919 : memcpy(target, val.data(), val.size());
345 530919 : return val.size();
346 : }
347 :
348 9769322 : inline size_t toStringValue(char *target, const char *val) {
349 9769322 : auto len = ::strlen(val);
350 9769322 : memcpy(target, val, len);
351 9769322 : return len;
352 : }
353 :
354 : template <size_t N>
355 : inline size_t toStringValue(char *target, const char val[N]) {
356 : memcpy(target, val, N);
357 : return N;
358 : }
359 :
360 6282 : inline size_t toStringValue(char *target, const std::string &val) {
361 6282 : memcpy(target, val.data(), val.size());
362 6282 : return val.size();
363 : }
364 :
365 6364 : inline size_t toStringValue(char *target, const memory::string &val) {
366 6364 : memcpy(target, val.data(), val.size());
367 6364 : return val.size();
368 : }
369 :
370 : inline size_t toStringValue(char *target, const StringViewUtf8 &val) {
371 : memcpy(target, val.data(), val.size());
372 : return val.size();
373 : }
374 :
375 : template <typename Interface>
376 : inline auto toStringType(const char16_t *val) -> typename Interface::StringType {
377 : return string::toUtf8<Interface>(WideStringView(val));
378 : }
379 :
380 : template <typename Interface>
381 : static auto toStringType(const WideStringView &val) -> typename Interface::StringType {
382 : return string::toUtf8<Interface>(val);
383 : }
384 :
385 : template <typename Interface>
386 : static auto toStringType(const std::u16string &val) -> typename Interface::StringType {
387 : return string::toUtf8<Interface>(val);
388 : }
389 :
390 : template <typename Interface>
391 : static auto toStringType(const memory::u16string &val) -> typename Interface::StringType {
392 : return string::toUtf8<Interface>(val);
393 : }
394 :
395 : template <typename Interface, typename T>
396 : static auto toStringType(const T &t) -> typename Interface::StringType {
397 : typename Interface::StringStreamType stream;
398 : stream << t;
399 : return stream.str();
400 : }
401 :
402 : template <typename T>
403 : struct IsFastToStringAvailableValue {
404 : static constexpr bool value = false;
405 : };
406 :
407 : template <size_t N> struct IsFastToStringAvailableValue<char[N]> { static constexpr bool value = true; };
408 : template <> struct IsFastToStringAvailableValue<char *> { static constexpr bool value = true; };
409 : template <> struct IsFastToStringAvailableValue<StringView> { static constexpr bool value = true; };
410 : template <> struct IsFastToStringAvailableValue<std::string> { static constexpr bool value = true; };
411 : template <> struct IsFastToStringAvailableValue<memory::string> { static constexpr bool value = true; };
412 : template <> struct IsFastToStringAvailableValue<char> { static constexpr bool value = true; };
413 : template <> struct IsFastToStringAvailableValue<char16_t> { static constexpr bool value = true; };
414 : template <> struct IsFastToStringAvailableValue<char32_t> { static constexpr bool value = true; };
415 : template <> struct IsFastToStringAvailableValue<int64_t> { static constexpr bool value = true; };
416 : template <> struct IsFastToStringAvailableValue<uint64_t> { static constexpr bool value = true; };
417 : template <> struct IsFastToStringAvailableValue<int32_t> { static constexpr bool value = true; };
418 : template <> struct IsFastToStringAvailableValue<uint32_t> { static constexpr bool value = true; };
419 : template <> struct IsFastToStringAvailableValue<int16_t> { static constexpr bool value = true; };
420 : template <> struct IsFastToStringAvailableValue<uint16_t> { static constexpr bool value = true; };
421 : template <> struct IsFastToStringAvailableValue<int8_t> { static constexpr bool value = true; };
422 : template <> struct IsFastToStringAvailableValue<uint8_t> { static constexpr bool value = true; };
423 : template <> struct IsFastToStringAvailableValue<double> { static constexpr bool value = true; };
424 : template <> struct IsFastToStringAvailableValue<float> { static constexpr bool value = true; };
425 :
426 : template <typename ... Args>
427 : struct IsFastToStringAvailable { };
428 :
429 : template <typename T, typename ... Args>
430 : struct IsFastToStringAvailable<T, Args...> {
431 : static constexpr bool value = IsFastToStringAvailableValue<std::remove_cv_t<std::remove_reference_t<T>>>::value
432 : && IsFastToStringAvailable<Args...>::value;
433 : };
434 :
435 : template <typename T>
436 : struct IsFastToStringAvailable<T> {
437 : static constexpr bool value = IsFastToStringAvailableValue<std::remove_cv_t<std::remove_reference_t<T>>>::value;
438 : };
439 :
440 9769322 : inline size_t getBufferSizeValue(const char *value) { return ::strlen(value); }
441 : template <size_t N> inline size_t getBufferSizeValue(const char value[N]) { return N; }
442 530918 : inline size_t getBufferSizeValue(const StringView &value) { return value.size(); }
443 : inline size_t getBufferSizeValue(const StringViewUtf8 &value) { return value.size(); }
444 6282 : inline size_t getBufferSizeValue(const std::string &value) { return value.size(); }
445 6364 : inline size_t getBufferSizeValue(const memory::string &value) { return value.size(); }
446 200 : inline size_t getBufferSizeValue(const char &value) { return 1; }
447 : inline size_t getBufferSizeValue(const char16_t &value) { return unicode::utf8EncodeLength(value); }
448 : inline size_t getBufferSizeValue(const char32_t &value) { return unicode::utf8EncodeLength(value); }
449 1800 : inline size_t getBufferSizeValue(const int64_t &value) { return string::_itoa_len(value); }
450 27468 : inline size_t getBufferSizeValue(const uint64_t &value) { return string::_itoa_len(value); }
451 45433 : inline size_t getBufferSizeValue(const int32_t &value) { return string::_itoa_len(int64_t(value)); }
452 11573 : inline size_t getBufferSizeValue(const uint32_t &value) { return string::_itoa_len(uint64_t(value)); }
453 25477 : inline size_t getBufferSizeValue(const int16_t &value) { return string::_itoa_len(int64_t(value)); }
454 298151 : inline size_t getBufferSizeValue(const uint16_t &value) { return string::_itoa_len(uint64_t(value)); }
455 : inline size_t getBufferSizeValue(const int8_t &value) { return string::_itoa_len(int64_t(value)); }
456 : inline size_t getBufferSizeValue(const uint8_t &value) { return string::_itoa_len(uint64_t(value)); }
457 2650 : inline size_t getBufferSizeValue(const double &value) { return string::_dtoa_len(value); }
458 518604 : inline size_t getBufferSizeValue(const float &value) { return string::_dtoa_len(value); }
459 :
460 1194731 : inline size_t getBufferSize() {
461 1194731 : return 0;
462 : }
463 :
464 : template <typename T>
465 2075908 : inline size_t getBufferSize(const T &t) {
466 2075908 : return getBufferSizeValue(t);
467 : }
468 :
469 : template <typename T, typename ... Args>
470 15426863 : inline size_t getBufferSize(T &&t, Args && ...args) {
471 15426863 : return getBufferSizeValue(t) + getBufferSize(std::forward<Args>(args)...);
472 : }
473 :
474 1194731 : inline size_t writeBuffer(char *target) {
475 1194731 : return 0;
476 : }
477 :
478 : template <typename T>
479 2075909 : inline size_t writeBuffer(char *target, const T &t) {
480 2075909 : return toStringValue(target, t);
481 : }
482 :
483 : template <typename T, typename ... Args>
484 15426866 : inline size_t writeBuffer(char *target, T &&t, Args && ...args) {
485 15426866 : auto off = toStringValue(target, t);
486 15426865 : target += off;
487 15426865 : return off + writeBuffer(target, std::forward<Args>(args)...);
488 : }
489 :
490 : template <typename Stream>
491 : inline void toStringStream(Stream &stream) { }
492 :
493 : template <typename Stream>
494 : inline void toStringStream(Stream &stream, char16_t val) {
495 : unicode::utf8Encode(stream, val);
496 : }
497 :
498 : template <typename Stream>
499 : inline void toStringStream(Stream &stream, const char16_t *val) {
500 : while (*val != char16_t(0)) {
501 : unicode::utf8Encode(stream, *val++);
502 : }
503 : }
504 :
505 : template <typename Stream>
506 : static void toStringStream(Stream &stream, const WideStringView &val) {
507 : for (auto &it : val) {
508 : unicode::utf8Encode(stream, it);
509 : }
510 : }
511 :
512 : template <typename Stream>
513 : static void toStringStream(Stream &stream, const std::u16string &val) {
514 : for (auto &it : val) {
515 : unicode::utf8Encode(stream, it);
516 : }
517 : }
518 :
519 : template <typename Stream>
520 : static void toStringStream(Stream &stream, const memory::u16string &val) {
521 : for (auto &it : val) {
522 : unicode::utf8Encode(stream, it);
523 : }
524 : }
525 :
526 : template <typename Stream, typename T>
527 13829 : inline void toStringStream(Stream &stream, T value) {
528 13829 : stream << value;
529 13829 : }
530 :
531 : template <typename Stream, typename T, typename... Args>
532 57481 : inline void toStringStream(Stream &stream, T value, Args && ... args) {
533 57481 : stream << value;
534 57481 : toStringStream(stream, std::forward<Args>(args)...);
535 57481 : }
536 :
537 : }
538 :
539 : template <typename Interface, typename... Args>
540 1207587 : static auto toString(Args && ... args) -> typename Interface::StringType {
541 : if constexpr (detail::IsFastToStringAvailable<Args ...>::value) {
542 : // fast toString with preallocated buffer
543 :
544 1200611 : auto size = detail::getBufferSize(std::forward<Args>(args)...);
545 1200614 : typename Interface::StringType ret; ret.resize(size);
546 :
547 1200614 : auto s = detail::writeBuffer(ret.data(), std::forward<Args>(args)...);
548 1200612 : if (s != size) {
549 0 : std::cout << "Invalid buffer size for toString<fast>\n";
550 0 : abort();
551 : }
552 1200612 : ret.resize(size);
553 :
554 2401225 : return ret;
555 1200614 : } else {
556 : if constexpr (sizeof...(args) == 1) {
557 : // optimal toString for single argument
558 : return detail::toStringType<Interface>(std::forward<Args>(args)...);
559 : }
560 :
561 : // fallback to StringStream
562 6976 : typename Interface::StringStreamType stream;
563 6976 : detail::toStringStream(stream, std::forward<Args>(args)...);
564 13952 : return stream.str();
565 6976 : }
566 : }
567 :
568 : }
569 :
570 : }
571 :
572 : #endif /* CORE_CORE_STRING_SPSTRINGSTREAM_H_ */
|