diff --git a/src/textstream/stream.h b/src/textstream/stream.h new file mode 100644 index 0000000..6bb9a07 --- /dev/null +++ b/src/textstream/stream.h @@ -0,0 +1,117 @@ +/* + * This file is a part of PikoTools + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2021, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name Tomasz Sowa nor the names of contributors to this + * project may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef headerfile_picotools_textstream_stream +#define headerfile_picotools_textstream_stream + +#include + + +namespace pt +{ +class Space; +class Date; + + + + +class Stream +{ +public: + + virtual ~Stream() {}; + + virtual void clear() = 0; + virtual bool empty() const = 0; + virtual size_t size() const = 0; + virtual void reserve(size_t len) = 0; + virtual size_t capacity() const = 0; + + virtual void to_string(std::string & str, bool clear_string = true) const = 0; + virtual void to_string(std::wstring & str, bool clear_string = true) const = 0; + + virtual Stream & operator<<(const char * str) = 0; + virtual Stream & operator<<(const std::string & str) = 0; + + virtual Stream & operator<<(const wchar_t * str) = 0; + virtual Stream & operator<<(const std::wstring & str) = 0; + + virtual Stream & operator<<(char) = 0; + virtual Stream & operator<<(unsigned char) = 0; + virtual Stream & operator<<(wchar_t) = 0; + virtual Stream & operator<<(bool) = 0; + virtual Stream & operator<<(short) = 0; + virtual Stream & operator<<(int) = 0; + virtual Stream & operator<<(long) = 0; + virtual Stream & operator<<(long long) = 0; + virtual Stream & operator<<(unsigned short) = 0; + virtual Stream & operator<<(unsigned int) = 0; + virtual Stream & operator<<(unsigned long) = 0; + virtual Stream & operator<<(unsigned long long) = 0; + virtual Stream & operator<<(float) = 0; + virtual Stream & operator<<(double) = 0; + virtual Stream & operator<<(long double) = 0; + virtual Stream & operator<<(const void *) = 0; // printing a pointer + virtual Stream & operator<<(const Space & space) = 0; + virtual Stream & operator<<(const Date & date) = 0; + + // min width for integer output + // if the output value has less digits then first zeroes are added + // (0 turn off) + //Stream & int_min_width(size_t min_width); + +// template +// Stream & operator<<(const Stream & arg); + +// template +// Stream & write(const in_buffer_type * 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) + //virtual Stream & write(const char * format, double val) = 0; + //virtual Stream & write(const wchar_t * format, double val) = 0; + + // what is it? + //Stream & fill_up_if_needed(wchar_t fill_up_char, size_t existing_length); + +}; + + +} + + +#endif diff --git a/src/textstream/textstream.h b/src/textstream/textstream.h index d62ec97..726d0bb 100644 --- a/src/textstream/textstream.h +++ b/src/textstream/textstream.h @@ -39,11 +39,13 @@ #define headerfile_picotools_textstream_textstream #include +#include "stream.h" #include "space/space.h" #include "date/date.h" #include "convert/inttostr.h" #include "membuffer/membuffer.h" #include "types.h" +#include "utf8/utf8.h" // for snprintf #include @@ -58,10 +60,9 @@ namespace pt similar to std::ostringstream StringType can be either std::string or std::wstring - this class doesn't use UTF-8 in any kind */ template -class TextStreamBase +class TextStreamBase : public Stream { public: @@ -128,13 +129,13 @@ public: template TextStreamBase & operator<<(const TextStreamBase & arg); - template - TextStreamBase & write(const in_buffer_type * buf, size_t len); + 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 & 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); @@ -231,10 +232,19 @@ void TextStreamBase::to_string(std::stri if( str.capacity() < str.size() + size() ) str.reserve(str.size() + size()); - const_iterator i = begin(); - for( ; i != end() ; ++i) - str += static_cast(*i); + if constexpr (sizeof(char_type) == sizeof(char) ) + { + const_iterator i = begin(); + + for( ; i != end() ; ++i) + str += *i; + } + else + { + // test me + wide_stream_to_utf8(*this, str); + } } @@ -248,10 +258,20 @@ void TextStreamBase::to_string(std::wstr if( str.capacity() < str.size() + size() ) str.reserve(str.size() + size()); - const_iterator i = begin(); + if constexpr (sizeof(char_type) == sizeof(wchar_t) ) + { + const_iterator i = begin(); - for( ; i != end() ; ++i) - str += static_cast(*i); + for( ; i != end() ; ++i) + str += *i; + } + else + { + // IMPROVE ME don't use a temporary object + std::string utf8; + to_string(utf8); + utf8_to_wide(utf8, str, false); + } } @@ -275,8 +295,15 @@ template TextStreamBase & TextStreamBase::operator<<(const char * str) { - for( ; *str ; ++str) - buffer.append(static_cast(*str)); + if constexpr ( sizeof(char_type) == sizeof(char) ) + { + for( ; *str ; ++str) + buffer.append(*str); + } + else + { + utf8_to_wide(str, *this, false); + } return *this; } @@ -286,10 +313,7 @@ template TextStreamBase & TextStreamBase::operator<<(const std::string & str) { - if( sizeof(char_type) == sizeof(char) ) - buffer.append(str.c_str(), str.size()); - else - operator<<(str.c_str()); + operator<<(str.c_str()); return *this; } @@ -300,8 +324,15 @@ template TextStreamBase & TextStreamBase::operator<<(const wchar_t * str) { - for( ; *str ; ++str) - buffer.append(static_cast(*str)); + if constexpr (sizeof(char_type) == sizeof(wchar_t) ) + { + for( ; *str ; ++str) + buffer.append(*str); + } + else + { + wide_to_utf8(str, *this); + } return *this; } @@ -312,10 +343,7 @@ template TextStreamBase & TextStreamBase::operator<<(const std::wstring & str) { - if( sizeof(char_type) == sizeof(wchar_t) ) - buffer.append(str.c_str(), str.size()); - else - operator<<(str.c_str()); + operator<<(str.c_str()); return *this; } @@ -496,12 +524,20 @@ return *this; + template -template TextStreamBase & -TextStreamBase::write(const in_buffer_type * buf, size_t len) +TextStreamBase::write(const char * str, size_t len) { - buffer.append(buf, len); + if constexpr ( sizeof(char_type) == sizeof(char) ) + { + for(size_t i=0 ; i < len ; ++i) + buffer.append(str[i]); + } + else + { + utf8_to_wide(str, *this, false); + } return *this; } @@ -509,24 +545,42 @@ return *this; template TextStreamBase & -TextStreamBase::write(const char * format, double val) +TextStreamBase::write(const wchar_t * str, size_t len) { -char buf[100]; + if constexpr (sizeof(char_type) == sizeof(wchar_t) ) + { + for(size_t i=0 ; i < len ; ++i) + buffer.append(str[i]); + } + else + { + wide_to_utf8(str, *this); + } - snprintf(buf, sizeof(buf)/sizeof(char), format, val); - return operator<<(buf); +return *this; } -template -TextStreamBase & -TextStreamBase::write(const wchar_t * format, double val) -{ -wchar_t buf[100]; - - swprintf(buf, sizeof(buf)/sizeof(wchar_t), format, val); - return operator<<(buf); -} +//template +//TextStreamBase & +//TextStreamBase::write(const char * format, double val) +//{ +//char buf[100]; +// +// snprintf(buf, sizeof(buf)/sizeof(char), format, val); +// return operator<<(buf); +//} +// +// +//template +//TextStreamBase & +//TextStreamBase::write(const wchar_t * format, double val) +//{ +//wchar_t buf[100]; +// +// swprintf(buf, sizeof(buf)/sizeof(wchar_t), format, val); +// return operator<<(buf); +//} diff --git a/src/utf8/utf8_private.h b/src/utf8/utf8_private.h index 42091a4..8028259 100644 --- a/src/utf8/utf8_private.h +++ b/src/utf8/utf8_private.h @@ -183,9 +183,8 @@ void int_to_wide(int c, StreamType & res) } -// not tested // FIX ME it is not using surrogate pairs from input stream -// and mode parameter +// and is not using mode parameter template void wide_to_utf8_generic(StreamType & buffer, int mode, function_type write_function) {