--- include/cpprest/streams.h.orig 2023-12-05 04:23:31 UTC +++ include/cpprest/streams.h @@ -16,6 +16,7 @@ #define CASA_STREAMS_H #include "cpprest/astreambuf.h" +#include "cpprest/details/char_traits.h" #include #include @@ -60,31 +61,96 @@ class basic_istream_helper (private) concurrency::streams::streambuf m_buffer; }; -template +template::TraitsType> struct Value2StringFormatter { + struct SanitizeInput + { + const std::basic_string &operator () (const std::basic_string &input) + { + return input; + } + template std::basic_string operator () (const std::basic_string &input) + { + return {reinterpret_cast(input.c_str()), input.size()}; + } + const char *operator () (const char *input) { + return input; + } + const char *operator () (const unsigned char *input) + { + return reinterpret_cast(input); + } + template T operator () (T input) + { + return input; + } + }; + struct GenerateFormatOutput + { + std::basic_string &&operator() (std::basic_string &&result) + { + return std::move(result); + } + std::basic_string operator() (const std::basic_string &intermediate) + { + return {reinterpret_cast(intermediate.c_str()), intermediate.size()}; + } + }; template - static std::basic_string format(const T& val) + static std::basic_string format(const T& val) { - std::basic_ostringstream ss; - ss << val; - return ss.str(); + typename std::conditional< + sizeof(CharType) == 1, + std::basic_ostringstream, + std::basic_ostringstream::type> + >::type ss; + SanitizeInput sanitizer; + ss << sanitizer(val); + typename std::conditional< + sizeof(CharType) == 1, + std::basic_string, + std::basic_string::type> + >::type str = ss.str(); + GenerateFormatOutput generateFormatOutput; + return generateFormatOutput(std::move(str)); } }; -template<> -struct Value2StringFormatter +template +struct Value2StringFormatterUint8Format { - template - static std::basic_string format(const T& val) + std::basic_string operator () (const T& val) { std::basic_ostringstream ss; ss << val; return reinterpret_cast(ss.str().c_str()); } +}; - static std::basic_string format(const utf16string& val) +template +struct Value2StringFormatterUint8Format> +{ + std::basic_string operator () ( + const std::basic_string::TraitsType>& val) { + Value2StringFormatterUint8Format> format; + return format(reinterpret_cast&>(val)); + } +}; + +template<> +struct Value2StringFormatter +{ + template ::TraitsType> + static std::basic_string format(const T& val) + { + Value2StringFormatterUint8Format format; + return format(val); + } + + static std::basic_string::TraitsType> format(const utf16string& val) + { return format(utility::conversions::utf16_to_utf8(val)); } }; @@ -262,7 +328,7 @@ class basic_ostream (public) /// Write the specified string to the output stream. /// /// Input string. - pplx::task print(const std::basic_string& str) const + pplx::task print(const std::basic_string& str) const { pplx::task result; if (!_verify_and_return_task(details::_out_stream_msg, result)) return result; @@ -273,7 +339,7 @@ class basic_ostream (public) } else { - auto sharedStr = std::make_shared>(str); + auto sharedStr = std::make_shared>(str); return helper()->m_buffer.putn_nocopy(sharedStr->c_str(), sharedStr->size()).then([sharedStr](size_t size) { return size; }); @@ -294,7 +360,7 @@ class basic_ostream (public) if (!_verify_and_return_task(details::_out_stream_msg, result)) return result; // TODO in the future this could be improved to have Value2StringFormatter avoid another unnecessary copy // by putting the string on the heap before calling the print string overload. - return print(details::Value2StringFormatter::format(val)); + return print(details::Value2StringFormatter::format(val)); } ///