diff --git a/include/rexy/detail/format/output_buffer.hpp b/include/rexy/detail/format/output_buffer.hpp index 7e8b95c..40eb2c2 100644 --- a/include/rexy/detail/format/output_buffer.hpp +++ b/include/rexy/detail/format/output_buffer.hpp @@ -23,6 +23,8 @@ #include //fputc, FILE #include //fputwc +#include "format_error.hpp" + namespace rexy::fmt::detail{ //polymorphic buffer of which a reference can be passed around to prevent //passing around multiple output iterator types @@ -96,34 +98,23 @@ namespace rexy::fmt::detail{ template - struct print_iterator; - template<> - struct print_iterator + struct print_format_buffer : public format_output_buffer_base { private: FILE* m_stream; public: - constexpr print_iterator(FILE* stream): + constexpr print_format_buffer(FILE* stream): m_stream(stream){} - print_iterator& operator=(char c){fputc(c, m_stream);return *this;} + constexpr ~print_format_buffer(void){ + write_out(); + } - constexpr print_iterator& operator*(void){return *this;} - constexpr print_iterator& operator++(void){return *this;} - constexpr print_iterator operator++(int){return *this;} - }; - template<> - struct print_iterator - { - private: - FILE* m_stream; - public: - constexpr print_iterator(FILE* stream): - m_stream(stream){} - print_iterator& operator=(wchar_t c){fputwc(c, m_stream);return *this;} - - constexpr print_iterator& operator*(void){return *this;} - constexpr print_iterator& operator++(void){return *this;} - constexpr print_iterator operator++(int){return *this;} + std::size_t write_out(void)override{ + const auto written = fwrite(this->m_data, sizeof(this->m_data[0]), this->m_size, m_stream); + if(written != this->m_size){ + REXY_THROW_FORMAT_ERROR("Failed to print data"); + } + } }; } diff --git a/include/rexy/detail/format/output_buffer.tpp b/include/rexy/detail/format/output_buffer.tpp index 33cf483..9b13413 100644 --- a/include/rexy/detail/format/output_buffer.tpp +++ b/include/rexy/detail/format/output_buffer.tpp @@ -148,9 +148,6 @@ namespace rexy::fmt::detail{ return this->m_size; } - - - } #endif diff --git a/include/rexy/detail/format/traits.hpp b/include/rexy/detail/format/traits.hpp index 6d8a132..75c0c06 100644 --- a/include/rexy/detail/format/traits.hpp +++ b/include/rexy/detail/format/traits.hpp @@ -101,25 +101,49 @@ namespace rexy::fmt::detail{ using uchar = unsigned char; return (sizeof(utf_test) == 3) && (uchar(utf_test[0]) == 0xC2) && (uchar(utf_test[1]) == 0xB5); } + static constexpr wchar_t wutf_test[] = L"\U00010437"; + constexpr bool is_wutf16(void){ + return (sizeof(wutf_test) / sizeof(wutf_test[0]) == 3 && + wutf_test[0] == 0xD801 && wutf_test[1] == 0xDC37); + } + constexpr bool is_wutf32(void){ + return (sizeof(wutf_test) / sizeof(wutf_test[0]) == 2 && + wutf_test[0] == 0x00010437); + } template - struct is_utf8_encoded_string_type{ - static constexpr bool value = false; - }; + struct is_utf8_encoded_string_type : public std::false_type{}; template<> - struct is_utf8_encoded_string_type{ - static constexpr bool value = true; - }; + struct is_utf8_encoded_string_type : public std::true_type{}; template<> - struct is_utf8_encoded_string_type{ - static constexpr bool value = is_utf8(); - }; - + struct is_utf8_encoded_string_type : public std::integral_constant{}; template static constexpr bool is_utf8_encoded_string_type_v = is_utf8_encoded_string_type::value; + template + struct is_utf16_encoded_string_type : public std::false_type{}; + template<> + struct is_utf16_encoded_string_type : public std::true_type{}; + template<> + struct is_utf16_encoded_string_type : public std::integral_constant{}; + template + static constexpr bool is_utf16_encoded_string_type_v = is_utf16_encoded_string_type::value; + + template + struct is_utf32_encoded_string_type : public std::false_type{}; + template<> + struct is_utf32_encoded_string_type : public std::true_type{}; + template<> + struct is_utf32_encoded_string_type : public std::integral_constant{}; + template + static constexpr bool is_utf32_encoded_string_type_v = is_utf32_encoded_string_type::value; + template concept UTF8_String = is_utf8_encoded_string_type_v; + template + concept UTF16_String = is_utf16_encoded_string_type_v; + template + concept UTF32_String = is_utf32_encoded_string_type_v; } diff --git a/include/rexy/format.tpp b/include/rexy/format.tpp index 3033c81..dd0cc67 100644 --- a/include/rexy/format.tpp +++ b/include/rexy/format.tpp @@ -267,37 +267,37 @@ namespace rexy{ //////////////////////////////////////print char overloads/////////////////////////////////////////////// template std::size_t print(fmt::detail::format_string fmt, Args&&... args){ - fmt::detail::basic_format_output_buffer> out{fmt::detail::print_iterator{stdout}}; + fmt::detail::print_format_buffer out{stdout}; vformat_to(fmt::detail::output_iterator_t{out}, fmt.str, make_format_args(std::forward(args)...)); return out.count(); } template std::size_t print(FILE* stream, fmt::detail::format_string fmt, Args&&... args){ - fmt::detail::basic_format_output_buffer> out{fmt::detail::print_iterator{stream}}; + fmt::detail::print_format_buffer out{stream}; vformat_to(fmt::detail::output_iterator_t{out}, fmt.str, make_format_args(std::forward(args)...)); return out.count(); } template std::size_t println(fmt::detail::format_string fmt, Args&&... args){ - fmt::detail::basic_format_output_buffer> out{fmt::detail::print_iterator{stdout}}; + fmt::detail::print_format_buffer out{stdout}; vformat_to(fmt::detail::output_iterator_t{out}, fmt.str, make_format_args(std::forward(args)...)); out.push_back('\n'); return out.count(); } template std::size_t println(FILE* stream, fmt::detail::format_string fmt, Args&&... args){ - fmt::detail::basic_format_output_buffer> out{fmt::detail::print_iterator{stream}}; + fmt::detail::print_format_buffer out{stream}; vformat_to(fmt::detail::output_iterator_t{out}, fmt.str, make_format_args(std::forward(args)...)); out.push_back('\n'); return out.count(); } std::size_t vprint_unicode(string_view fmt, format_args args){ - fmt::detail::basic_format_output_buffer> out{fmt::detail::print_iterator{stdout}}; + fmt::detail::print_format_buffer out{stdout}; vformat_to(fmt::detail::output_iterator_t{out}, fmt, args); return out.count(); } std::size_t vprint_unicode(FILE* stream, string_view fmt, format_args args){ - fmt::detail::basic_format_output_buffer> out{fmt::detail::print_iterator{stream}}; + fmt::detail::print_format_buffer out{stream}; vformat_to(fmt::detail::output_iterator_t{out}, fmt, args); return out.count(); }