|
|
|
@ -75,6 +75,9 @@ public:
|
|
|
|
|
typedef typename buffer_type::const_iterator const_iterator;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool is_char_stream() const;
|
|
|
|
|
bool is_wchar_stream() const;
|
|
|
|
|
|
|
|
|
|
void clear();
|
|
|
|
|
bool empty() const;
|
|
|
|
|
size_t size() const;
|
|
|
|
@ -96,12 +99,14 @@ public:
|
|
|
|
|
std::string to_str() const;
|
|
|
|
|
std::wstring to_wstr() const;
|
|
|
|
|
|
|
|
|
|
char get_char(size_t index) const;
|
|
|
|
|
wchar_t get_wchar(size_t index) const;
|
|
|
|
|
|
|
|
|
|
char_type & operator[](size_t index);
|
|
|
|
|
char_type operator[](size_t index) const;
|
|
|
|
|
|
|
|
|
|
TextStreamBase & operator<<(const char * str);
|
|
|
|
|
TextStreamBase & operator<<(const std::string & str);
|
|
|
|
|
|
|
|
|
|
TextStreamBase & operator<<(const wchar_t * str);
|
|
|
|
|
TextStreamBase & operator<<(const std::wstring & str);
|
|
|
|
|
|
|
|
|
@ -121,11 +126,14 @@ public:
|
|
|
|
|
TextStreamBase & operator<<(double);
|
|
|
|
|
TextStreamBase & operator<<(long double);
|
|
|
|
|
TextStreamBase & operator<<(const void *); // printing a pointer
|
|
|
|
|
|
|
|
|
|
TextStreamBase & operator<<(const Stream & stream);
|
|
|
|
|
TextStreamBase & operator<<(const Space & space);
|
|
|
|
|
TextStreamBase & operator<<(const Date & date);
|
|
|
|
|
|
|
|
|
|
char get_char(size_t index) const;
|
|
|
|
|
wchar_t get_wchar(size_t index) const;
|
|
|
|
|
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
|
|
|
|
|
TextStreamBase & operator<<(const TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// min width for integer output
|
|
|
|
@ -133,17 +141,9 @@ public:
|
|
|
|
|
// (0 turn off)
|
|
|
|
|
TextStreamBase & int_min_width(size_t min_width);
|
|
|
|
|
|
|
|
|
|
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
|
|
|
|
|
TextStreamBase & operator<<(const TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg);
|
|
|
|
|
|
|
|
|
|
TextStreamBase & write(const char * buf, size_t len);
|
|
|
|
|
TextStreamBase & write(const wchar_t * buf, size_t len);
|
|
|
|
|
|
|
|
|
|
// write double value in a specified format
|
|
|
|
|
// format is the same as in the snprintf function, e.g. write("%f", 10.0)
|
|
|
|
|
// TextStreamBase & write(const char * format, double val);
|
|
|
|
|
// TextStreamBase & write(const wchar_t * format, double val);
|
|
|
|
|
|
|
|
|
|
TextStreamBase & fill_up_if_needed(wchar_t fill_up_char, size_t existing_length);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -152,6 +152,15 @@ public:
|
|
|
|
|
int radix;
|
|
|
|
|
size_t min_width_for_integers;
|
|
|
|
|
buffer_type buffer;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
|
|
void put_stream(const Stream & stream);
|
|
|
|
|
void put_utf8_to_wide(const Stream & stream);
|
|
|
|
|
void put_wide_to_utf8(const Stream & stream);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -166,6 +175,32 @@ TextStreamBase<char_type, stack_size, heap_block_size>::TextStreamBase()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
bool TextStreamBase<char_type, stack_size, heap_block_size>::is_char_stream() const
|
|
|
|
|
{
|
|
|
|
|
if constexpr (sizeof(char_type) == sizeof(char) )
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
bool TextStreamBase<char_type, stack_size, heap_block_size>::is_wchar_stream() const
|
|
|
|
|
{
|
|
|
|
|
if constexpr (sizeof(char_type) == sizeof(wchar_t) )
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
void TextStreamBase<char_type, stack_size, heap_block_size>::clear()
|
|
|
|
|
{
|
|
|
|
@ -302,6 +337,18 @@ std::wstring TextStreamBase<char_type, stack_size, heap_block_size>::to_wstr() c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
char TextStreamBase<char_type, stack_size, heap_block_size>::get_char(size_t index) const
|
|
|
|
|
{
|
|
|
|
|
return static_cast<char>(buffer[index]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
wchar_t TextStreamBase<char_type, stack_size, heap_block_size>::get_wchar(size_t index) const
|
|
|
|
|
{
|
|
|
|
|
return static_cast<wchar_t>(buffer[index]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -595,65 +642,142 @@ return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
//TextStreamBase<char_type, stack_size, heap_block_size> &
|
|
|
|
|
//TextStreamBase<char_type, stack_size, heap_block_size>::write(const char * format, double val)
|
|
|
|
|
//{
|
|
|
|
|
//char buf[100];
|
|
|
|
|
//
|
|
|
|
|
// snprintf(buf, sizeof(buf)/sizeof(char), format, val);
|
|
|
|
|
// return operator<<(buf);
|
|
|
|
|
//}
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
//template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
//TextStreamBase<char_type, stack_size, heap_block_size> &
|
|
|
|
|
//TextStreamBase<char_type, stack_size, heap_block_size>::write(const wchar_t * format, double val)
|
|
|
|
|
//{
|
|
|
|
|
//wchar_t buf[100];
|
|
|
|
|
//
|
|
|
|
|
// swprintf(buf, sizeof(buf)/sizeof(wchar_t), format, val);
|
|
|
|
|
// return operator<<(buf);
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size> &
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const Stream & stream)
|
|
|
|
|
{
|
|
|
|
|
put_stream(stream);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size> &
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const Space & space)
|
|
|
|
|
void TextStreamBase<char_type, stack_size, heap_block_size>::put_stream(const Stream & stream)
|
|
|
|
|
{
|
|
|
|
|
space.serialize_to_space_stream(*this, true);
|
|
|
|
|
if( sizeof(char_type) == sizeof(char) && stream.is_char_stream() )
|
|
|
|
|
{
|
|
|
|
|
// from utf8 to utf8
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
for(size_t i=0 ; i < stream.size() ; ++i)
|
|
|
|
|
{
|
|
|
|
|
char c = stream.get_char(i);
|
|
|
|
|
operator<<(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if( sizeof(char_type) == sizeof(wchar_t) && stream.is_char_stream() )
|
|
|
|
|
{
|
|
|
|
|
// from utf8 to wide
|
|
|
|
|
put_utf8_to_wide(stream);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if( sizeof(char_type) == sizeof(char) && stream.is_wchar_stream() )
|
|
|
|
|
{
|
|
|
|
|
// from wide to utf8
|
|
|
|
|
put_wide_to_utf8(stream);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
if( sizeof(char_type) == sizeof(wchar_t) && stream.is_wchar_stream() )
|
|
|
|
|
{
|
|
|
|
|
// from wide to wide
|
|
|
|
|
|
|
|
|
|
for(size_t i=0 ; i < stream.size() ; ++i)
|
|
|
|
|
{
|
|
|
|
|
wchar_t c = stream.get_wchar(i);
|
|
|
|
|
operator<<(c);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
operator<<("such conversion is not implemented");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// test me when sizeof(wchar_t) is 2
|
|
|
|
|
// or may move me to utf8 functions?
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size> &
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const Date & date)
|
|
|
|
|
void TextStreamBase<char_type, stack_size, heap_block_size>::put_utf8_to_wide(const Stream & stream)
|
|
|
|
|
{
|
|
|
|
|
date.Serialize(*this);
|
|
|
|
|
size_t len;
|
|
|
|
|
bool correct;
|
|
|
|
|
size_t index = 0;
|
|
|
|
|
int z;
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
len = utf8_to_int(stream, index, z, correct);
|
|
|
|
|
|
|
|
|
|
if( len > 0 )
|
|
|
|
|
{
|
|
|
|
|
if( !correct )
|
|
|
|
|
{
|
|
|
|
|
z = 0xFFFD; // U+FFFD "replacement character"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int_to_wide(z, *this);
|
|
|
|
|
index += len;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while( len > 0 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// test me when sizeof(wchar_t) is 2
|
|
|
|
|
// or may move me to utf8 functions?
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
char TextStreamBase<char_type, stack_size, heap_block_size>::get_char(size_t index) const
|
|
|
|
|
void TextStreamBase<char_type, stack_size, heap_block_size>::put_wide_to_utf8(const Stream & stream)
|
|
|
|
|
{
|
|
|
|
|
return static_cast<char>(buffer[index]);
|
|
|
|
|
char utf8_buf[10];
|
|
|
|
|
size_t utf8_buf_len = sizeof(utf8_buf) / sizeof(char);
|
|
|
|
|
|
|
|
|
|
for(size_t i=0 ; i < stream.size() ; ++i)
|
|
|
|
|
{
|
|
|
|
|
int c = static_cast<int>(stream.get_wchar(i));
|
|
|
|
|
|
|
|
|
|
if( is_first_surrogate_char(c) && i + 1 < stream.size() )
|
|
|
|
|
{
|
|
|
|
|
wchar_t c1 = static_cast<wchar_t>(c);
|
|
|
|
|
wchar_t c2 = stream.get_wchar(++i);
|
|
|
|
|
surrogate_pair_to_int(c1, c2, c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t len = int_to_utf8(c, utf8_buf, utf8_buf_len);
|
|
|
|
|
|
|
|
|
|
for(size_t u=0 ; u < len ; ++u)
|
|
|
|
|
{
|
|
|
|
|
operator<<(utf8_buf[u]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
wchar_t TextStreamBase<char_type, stack_size, heap_block_size>::get_wchar(size_t index) const
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size> &
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const Space & space)
|
|
|
|
|
{
|
|
|
|
|
return static_cast<wchar_t>(buffer[index]);
|
|
|
|
|
space.serialize_to_space_stream(*this, true);
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size> &
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(const Date & date)
|
|
|
|
|
{
|
|
|
|
|
date.Serialize(*this);
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
template<typename arg_char_type, size_t arg_stack_size, size_t arg_heap_block_size>
|
|
|
|
@ -661,13 +785,22 @@ TextStreamBase<char_type, stack_size, heap_block_size> &
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size>::operator<<(
|
|
|
|
|
const TextStreamBase<arg_char_type, arg_stack_size, arg_heap_block_size> & arg)
|
|
|
|
|
{
|
|
|
|
|
buffer.append(arg.buffer);
|
|
|
|
|
/*
|
|
|
|
|
* in the future we can have a faster implementation
|
|
|
|
|
* which uses iterators instead of get_char() and get_wchar() methods
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
put_stream(arg);
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<typename char_type, size_t stack_size, size_t heap_block_size>
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size> &
|
|
|
|
|
TextStreamBase<char_type, stack_size, heap_block_size>::int_min_width(size_t min_width)
|
|
|
|
|