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 <cstdio> //fputc, FILE
|
||||||
#include <cwchar> //fputwc
|
#include <cwchar> //fputwc
|
||||||
|
|
||||||
|
#include "format_error.hpp"
|
||||||
|
|
||||||
namespace rexy::fmt::detail{
|
namespace rexy::fmt::detail{
|
||||||
//polymorphic buffer of which a reference can be passed around to prevent
|
//polymorphic buffer of which a reference can be passed around to prevent
|
||||||
//passing around multiple output iterator types
|
//passing around multiple output iterator types
|
||||||
@ -96,34 +98,23 @@ namespace rexy::fmt::detail{
|
|||||||
|
|
||||||
|
|
||||||
template<class Char>
|
template<class Char>
|
||||||
struct print_iterator;
|
struct print_format_buffer : public format_output_buffer_base<Char>
|
||||||
template<>
|
|
||||||
struct print_iterator<char>
|
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
FILE* m_stream;
|
FILE* m_stream;
|
||||||
public:
|
public:
|
||||||
constexpr print_iterator(FILE* stream):
|
constexpr print_format_buffer(FILE* stream):
|
||||||
m_stream(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;}
|
std::size_t write_out(void)override{
|
||||||
constexpr print_iterator& operator++(void){return *this;}
|
const auto written = fwrite(this->m_data, sizeof(this->m_data[0]), this->m_size, m_stream);
|
||||||
constexpr print_iterator operator++(int){return *this;}
|
if(written != this->m_size){
|
||||||
};
|
REXY_THROW_FORMAT_ERROR("Failed to print data");
|
||||||
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;}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -148,9 +148,6 @@ namespace rexy::fmt::detail{
|
|||||||
return this->m_size;
|
return this->m_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -101,25 +101,49 @@ namespace rexy::fmt::detail{
|
|||||||
using uchar = unsigned char;
|
using uchar = unsigned char;
|
||||||
return (sizeof(utf_test) == 3) && (uchar(utf_test[0]) == 0xC2) && (uchar(utf_test[1]) == 0xB5);
|
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>
|
template<class T>
|
||||||
struct is_utf8_encoded_string_type{
|
struct is_utf8_encoded_string_type : public std::false_type{};
|
||||||
static constexpr bool value = false;
|
|
||||||
};
|
|
||||||
template<>
|
template<>
|
||||||
struct is_utf8_encoded_string_type<char8_t>{
|
struct is_utf8_encoded_string_type<char8_t> : public std::true_type{};
|
||||||
static constexpr bool value = true;
|
|
||||||
};
|
|
||||||
template<>
|
template<>
|
||||||
struct is_utf8_encoded_string_type<char>{
|
struct is_utf8_encoded_string_type<char> : public std::integral_constant<bool,is_utf8()>{};
|
||||||
static constexpr bool value = is_utf8();
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
static constexpr bool is_utf8_encoded_string_type_v = is_utf8_encoded_string_type<T>::value;
|
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>
|
template<class T>
|
||||||
concept UTF8_String = is_utf8_encoded_string_type_v<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///////////////////////////////////////////////
|
//////////////////////////////////////print char overloads///////////////////////////////////////////////
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
std::size_t print(fmt::detail::format_string<Args...> fmt, Args&&... 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)...));
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(args)...));
|
||||||
return out.count();
|
return out.count();
|
||||||
}
|
}
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
std::size_t print(FILE* stream, fmt::detail::format_string<Args...> fmt, Args&&... 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)...));
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(args)...));
|
||||||
return out.count();
|
return out.count();
|
||||||
}
|
}
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
std::size_t println(fmt::detail::format_string<Args...> fmt, Args&&... 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)...));
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(args)...));
|
||||||
out.push_back('\n');
|
out.push_back('\n');
|
||||||
return out.count();
|
return out.count();
|
||||||
}
|
}
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
std::size_t println(FILE* stream, fmt::detail::format_string<Args...> fmt, Args&&... 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)...));
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt.str, make_format_args(std::forward<Args>(args)...));
|
||||||
out.push_back('\n');
|
out.push_back('\n');
|
||||||
return out.count();
|
return out.count();
|
||||||
}
|
}
|
||||||
std::size_t vprint_unicode(string_view fmt, format_args args){
|
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);
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt, args);
|
||||||
return out.count();
|
return out.count();
|
||||||
}
|
}
|
||||||
std::size_t vprint_unicode(FILE* stream, string_view fmt, format_args args){
|
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);
|
vformat_to(fmt::detail::output_iterator_t<char>{out}, fmt, args);
|
||||||
return out.count();
|
return out.count();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user