Simplify print logic and make utf-8, utf-16, and utf-32 encodings detectible
This commit is contained in:
parent
2f64eb40f0
commit
50f6f81a05
@ -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");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -148,9 +148,6 @@ namespace rexy::fmt::detail{
|
||||
return this->m_size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -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>;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user