Simplify print logic and make utf-8, utf-16, and utf-32 encodings detectible

This commit is contained in:
rexy712 2022-06-29 17:48:53 -07:00
parent 2f64eb40f0
commit 50f6f81a05
4 changed files with 53 additions and 41 deletions

View File

@ -23,6 +23,8 @@
#include <cstdio> //fputc, FILE
#include <cwchar> //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<class Char>
struct print_iterator;
template<>
struct print_iterator<char>
struct print_format_buffer : public format_output_buffer_base<Char>
{
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<wchar_t>
{
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");
}
}
};
}

View File

@ -148,9 +148,6 @@ namespace rexy::fmt::detail{
return this->m_size;
}
}
#endif

View File

@ -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<class T>
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<char8_t>{
static constexpr bool value = true;
};
struct is_utf8_encoded_string_type<char8_t> : public std::true_type{};
template<>
struct is_utf8_encoded_string_type<char>{
static constexpr bool value = is_utf8();
};
struct is_utf8_encoded_string_type<char> : public std::integral_constant<bool,is_utf8()>{};
template<class T>
static constexpr bool is_utf8_encoded_string_type_v = is_utf8_encoded_string_type<T>::value;
template<class T>
struct is_utf16_encoded_string_type : public std::false_type{};
template<>
struct is_utf16_encoded_string_type<char16_t> : public std::true_type{};
template<>
struct is_utf16_encoded_string_type<wchar_t> : public std::integral_constant<bool,is_wutf16()>{};
template<class T>
static constexpr bool is_utf16_encoded_string_type_v = is_utf16_encoded_string_type<T>::value;
template<class T>
struct is_utf32_encoded_string_type : public std::false_type{};
template<>
struct is_utf32_encoded_string_type<char32_t> : public std::true_type{};
template<>
struct is_utf32_encoded_string_type<wchar_t> : public std::integral_constant<bool,is_wutf32()>{};
template<class T>
static constexpr bool is_utf32_encoded_string_type_v = is_utf32_encoded_string_type<T>::value;
template<class T>
concept UTF8_String = is_utf8_encoded_string_type_v<T>;
template<class T>
concept UTF16_String = is_utf16_encoded_string_type_v<T>;
template<class T>
concept UTF32_String = is_utf32_encoded_string_type_v<T>;
}

View File

@ -267,37 +267,37 @@ namespace rexy{
//////////////////////////////////////print char overloads///////////////////////////////////////////////
template<class... Args>
std::size_t print(fmt::detail::format_string<Args...> fmt, Args&&... args){
fmt::detail::basic_format_output_buffer<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stdout}};
fmt::detail::print_format_buffer<char> out{stdout};
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(args)...));
return out.count();
}
template<class... Args>
std::size_t print(FILE* stream, fmt::detail::format_string<Args...> fmt, Args&&... args){
fmt::detail::basic_format_output_buffer<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stream}};
fmt::detail::print_format_buffer<char> out{stream};
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(args)...));
return out.count();
}
template<class... Args>
std::size_t println(fmt::detail::format_string<Args...> fmt, Args&&... args){
fmt::detail::basic_format_output_buffer<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stdout}};
fmt::detail::print_format_buffer<char> out{stdout};
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(args)...));
out.push_back('\n');
return out.count();
}
template<class... Args>
std::size_t println(FILE* stream, fmt::detail::format_string<Args...> fmt, Args&&... args){
fmt::detail::basic_format_output_buffer<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stream}};
fmt::detail::print_format_buffer<char> out{stream};
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(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<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stdout}};
fmt::detail::print_format_buffer<char> out{stdout};
vformat_to(fmt::detail::output_iterator_t<char>{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<char,fmt::detail::print_iterator<char>> out{fmt::detail::print_iterator<char>{stream}};
fmt::detail::print_format_buffer<char> out{stream};
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt, args);
return out.count();
}