LCOV - code coverage report
Current view: top level - core/core/string - SPStringStream.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 126 137 92.0 %
Date: 2024-05-12 00:16:13 Functions: 1185 2177 54.4 %

          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_ */

Generated by: LCOV version 1.14