From d2d30cf64032a6c5dfc2398a946f49a44d972713 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 3 Jul 2012 14:58:18 +0000 Subject: [PATCH] added: convert (functions for converting) currently only int(long) -> string added: textstream (an efficient memory stream for creating strings -- it's using MemBuffer) git-svn-id: svn://ttmath.org/publicrep/pikotools/trunk@425 e52654a7-88a9-db11-a3e9-0013d4bc506e --- convert/convert.h | 45 +++++ convert/inttostr.h | 156 ++++++++++++++ membuffer/membuffer.h | 335 ++++++++++++++++++------------ textstream/textstream.h | 437 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 839 insertions(+), 134 deletions(-) create mode 100644 convert/convert.h create mode 100644 convert/inttostr.h create mode 100644 textstream/textstream.h diff --git a/convert/convert.h b/convert/convert.h new file mode 100644 index 0000000..c370307 --- /dev/null +++ b/convert/convert.h @@ -0,0 +1,45 @@ +/* + * This file is a part of PikoTools + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2012, 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_membuffer_convert_convert +#define headerfile_picotools_membuffer_convert_convert + + +#include "inttostr.h" + + +#endif diff --git a/convert/inttostr.h b/convert/inttostr.h new file mode 100644 index 0000000..9020a1c --- /dev/null +++ b/convert/inttostr.h @@ -0,0 +1,156 @@ +/* + * This file is a part of PikoTools + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2012, 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_membuffer_convert_inttostr +#define headerfile_picotools_membuffer_convert_inttostr + + + + +namespace PT +{ + + +// if the buffer is too small it will be terminated at the beginning (empty string) +// and the function returns false +template +bool Toa(unsigned long value, CharType * buffer, size_t buf_len, int base = 10, size_t * len_out = 0) +{ +size_t i1, i2; +long rest; + + if( len_out ) + *len_out = 0; + + if( buf_len == 0 ) + return false; + + i1 = i2 = 0; + + if( base < 2 ) base = 2; + if( base > 16 ) base = 16; + + do + { + rest = value % base; + value = value / base; + buffer[i2++] = (rest < 10) ? char(rest) + '0' : char(rest) - 10 + 'A'; + } + while(value != 0 && i2 < buf_len); + + if( i2 >= buf_len ) + { + buffer[0] = 0; // ops, the buffer was too small + return false; + } + + if( len_out ) + *len_out = i2 - i1; + + buffer[i2--] = 0; + + for( ; i1 < i2 ; ++i1, --i2) + { + CharType temp = buffer[i1]; + buffer[i1] = buffer[i2]; + buffer[i2] = temp; + } + +return true; +} + + + + + + +// if the buffer is too small it will be terminated at the beginning (empty string) +// and the function returns false +template +bool Toa(long value, CharType * buffer, size_t buf_len, int base = 10, size_t * len_out = 0) +{ + if( len_out ) + *len_out = 0; + + if( buf_len == 0 ) + return false; + + CharType * buf = buffer; + bool is_sign = false; + + if( value < 0 ) + { + buffer[0] = '-'; + buf += 1; + buf_len -= 1; + value = -value; + is_sign = true; + } + + bool res = Toa(static_cast(value), buf, buf_len, base, len_out); + + if( res ) + { + if( len_out && is_sign ) + *len_out += 1; + } + else + { + buffer[0] = 0; + // len_out is set to zero by Toa() + } + +return res; +} + + + + + + + + + + + + + + +} + + +#endif diff --git a/membuffer/membuffer.h b/membuffer/membuffer.h index 1ddda2e..6accc92 100644 --- a/membuffer/membuffer.h +++ b/membuffer/membuffer.h @@ -47,25 +47,25 @@ namespace PT */ -template +template class MemBuffer { public: - class Iterator + class iterator { public: - bool operator==(const Iterator & i); - bool operator!=(const Iterator & i); + bool operator==(const iterator & i); + bool operator!=(const iterator & i); - Iterator & operator++(); // prefix ++ - Iterator operator++(int); // postfix ++ + iterator & operator++(); // prefix ++ + iterator operator++(int); // postfix ++ - Iterator & operator--(); // prefix -- - Iterator operator--(int); // postfix -- + iterator & operator--(); // prefix -- + iterator operator--(int); // postfix -- - ItemType & operator*(); + item_type & operator*(); private: @@ -77,20 +77,26 @@ public: }; - class ConstIterator + class const_iterator { public: - bool operator==(const ConstIterator & i); - bool operator!=(const ConstIterator & i); + const_iterator(); + const_iterator(const const_iterator & i); + const_iterator(const iterator & i); + const_iterator & operator=(const const_iterator & i); + const_iterator & operator=(const iterator & i); - ConstIterator & operator++(); // prefix ++ - ConstIterator operator++(int); // postfix ++ + bool operator==(const const_iterator & i); + bool operator!=(const const_iterator & i); - ConstIterator & operator--(); // prefix -- - ConstIterator operator--(int); // postfix -- + const_iterator & operator++(); // prefix ++ + const_iterator operator++(int); // postfix ++ - ItemType operator*(); + const_iterator & operator--(); // prefix -- + const_iterator operator--(int); // postfix -- + + item_type operator*(); private: @@ -105,26 +111,30 @@ public: MemBuffer(); ~MemBuffer(); - MemBuffer(const MemBuffer & arg); - MemBuffer & operator=(const MemBuffer & arg); + MemBuffer(const MemBuffer & arg); + MemBuffer & operator=(const MemBuffer & arg); - void Append(ItemType item); - void Append(ItemType * item_array, size_t len); - size_t Size() const; - bool Empty() const; + void append(item_type item); + void append(item_type * item_array, size_t len); + + template + void append(const MemBuffer & arg); - void Reserve(size_t len); - size_t Capacity() const; - void Clear(); // frees memory but only to Capacity() + size_t size() const; + bool empty() const; - Iterator Begin(); - Iterator End(); + void reserve(size_t len); + size_t capacity() const; + void clear(); // frees memory but only to capacity() - ConstIterator Begin() const; - ConstIterator End() const; + iterator begin(); + iterator end(); - ItemType & operator[](size_t i); - const ItemType operator[](size_t i) const; + const_iterator begin() const; + const_iterator end() const; + + item_type & operator[](size_t i); + const item_type operator[](size_t i) const; private: @@ -132,10 +142,10 @@ private: struct MemArray { size_t size_used; - ItemType * buf; + item_type * buf; }; - ItemType stack_array[stack_size]; + item_type stack_array[stack_size]; MemArray * dynamic_array; // dynamic array of MemArray descriptors size_t dynamic_array_index; // index of a MemArray to which the last insertion was made // size_t(-1) means the stack_array @@ -144,21 +154,21 @@ private: size_t size_used; // the size of all valid items size_t size_allocated; // how many memory is reserved - size_t size_reserved; // memory reserved by Reserve(), it is used by Clear() + size_t size_reserved; // memory reserved by reserve(), it is used by clear() - void AddDynamicNode(); + void add_dynamic_node(); }; /* - Iterator + iterator */ -template -typename MemBuffer::Iterator & -MemBuffer::Iterator::operator++() +template +typename MemBuffer::iterator & +MemBuffer::iterator::operator++() { if( dynamic_array_index == size_t(-1) ) { @@ -185,11 +195,11 @@ return *this; } -template -typename MemBuffer::Iterator -MemBuffer::Iterator::operator++(int) +template +typename MemBuffer::iterator +MemBuffer::iterator::operator++(int) { - Iterator old(*this); + iterator old(*this); operator++(); return old; @@ -197,9 +207,9 @@ return old; -template -typename MemBuffer::Iterator & -MemBuffer::Iterator::operator--() +template +typename MemBuffer::iterator & +MemBuffer::iterator::operator--() { if( index == 0 ) { @@ -219,11 +229,11 @@ return *this; } -template -typename MemBuffer::Iterator -MemBuffer::Iterator::operator--(int) +template +typename MemBuffer::iterator +MemBuffer::iterator::operator--(int) { - Iterator old(*this); + iterator old(*this); operator++(); return old; @@ -231,8 +241,8 @@ return old; -template -ItemType & MemBuffer::Iterator::operator*() +template +item_type & MemBuffer::iterator::operator*() { if( dynamic_array_index == size_t(-1) ) { @@ -245,8 +255,8 @@ ItemType & MemBuffer::Iterator::operator* } -template -bool MemBuffer::Iterator::operator==(const Iterator & i) +template +bool MemBuffer::iterator::operator==(const iterator & i) { return mem_buffer == i.mem_buffer && dynamic_array_index == i.dynamic_array_index && @@ -254,8 +264,8 @@ bool MemBuffer::Iterator::operator==(cons } -template -bool MemBuffer::Iterator::operator!=(const Iterator & i) +template +bool MemBuffer::iterator::operator!=(const iterator & i) { return mem_buffer != i.mem_buffer || dynamic_array_index != i.dynamic_array_index || @@ -265,13 +275,58 @@ bool MemBuffer::Iterator::operator!=(cons /* - ConstIterator + const_iterator */ -template -typename MemBuffer::ConstIterator & -MemBuffer::ConstIterator::operator++() +template +MemBuffer::const_iterator::const_iterator() +{ +} + + +template +MemBuffer::const_iterator::const_iterator(const const_iterator & i) +{ + operator=(i); +} + + +template +MemBuffer::const_iterator::const_iterator(const iterator & i) +{ + operator=(i); +} + + +template +typename MemBuffer::const_iterator & +MemBuffer::const_iterator::operator=(const const_iterator & i) +{ + mem_buffer = i.mem_buffer; + dynamic_array_index = i.dynamic_array_index; + index = i.index; + +return *this; +} + + +template +typename MemBuffer::const_iterator & +MemBuffer::const_iterator::operator=(const iterator & i) +{ + mem_buffer = i.mem_buffer; + dynamic_array_index = i.dynamic_array_index; + index = i.index; + +return *this; +} + + + +template +typename MemBuffer::const_iterator & +MemBuffer::const_iterator::operator++() { if( dynamic_array_index == size_t(-1) ) { @@ -298,11 +353,11 @@ return *this; } -template -typename MemBuffer::ConstIterator -MemBuffer::ConstIterator::operator++(int) +template +typename MemBuffer::const_iterator +MemBuffer::const_iterator::operator++(int) { - ConstIterator old(*this); + const_iterator old(*this); operator++(); return old; @@ -310,9 +365,9 @@ return old; -template -typename MemBuffer::ConstIterator & -MemBuffer::ConstIterator::operator--() +template +typename MemBuffer::const_iterator & +MemBuffer::const_iterator::operator--() { if( index == 0 ) { @@ -332,11 +387,11 @@ return *this; } -template -typename MemBuffer::ConstIterator -MemBuffer::ConstIterator::operator--(int) +template +typename MemBuffer::const_iterator +MemBuffer::const_iterator::operator--(int) { - ConstIterator old(*this); + const_iterator old(*this); operator++(); return old; @@ -344,8 +399,8 @@ return old; -template -ItemType MemBuffer::ConstIterator::operator*() +template +item_type MemBuffer::const_iterator::operator*() { if( dynamic_array_index == size_t(-1) ) { @@ -358,8 +413,8 @@ ItemType MemBuffer::ConstIterator::operat } -template -bool MemBuffer::ConstIterator::operator==(const ConstIterator & i) +template +bool MemBuffer::const_iterator::operator==(const const_iterator & i) { return mem_buffer == i.mem_buffer && dynamic_array_index == i.dynamic_array_index && @@ -367,8 +422,8 @@ bool MemBuffer::ConstIterator::operator== } -template -bool MemBuffer::ConstIterator::operator!=(const ConstIterator & i) +template +bool MemBuffer::const_iterator::operator!=(const const_iterator & i) { return mem_buffer != i.mem_buffer || dynamic_array_index != i.dynamic_array_index || @@ -384,8 +439,8 @@ bool MemBuffer::ConstIterator::operator!= */ -template -MemBuffer::MemBuffer() +template +MemBuffer::MemBuffer() { size_reserved = 0; size_used = 0; @@ -397,8 +452,8 @@ MemBuffer::MemBuffer() } -template -MemBuffer::~MemBuffer() +template +MemBuffer::~MemBuffer() { if( dynamic_array ) { @@ -410,32 +465,32 @@ MemBuffer::~MemBuffer() } -template -MemBuffer::MemBuffer(const MemBuffer & arg) +template +MemBuffer::MemBuffer(const MemBuffer & arg) { operator=(arg); } -template -MemBuffer & -MemBuffer::operator=(const MemBuffer & arg) +template +MemBuffer & +MemBuffer::operator=(const MemBuffer & arg) { if( size_used > 0 ) - Clear(); + clear(); - ConstIterator i = arg.Begin(); + const_iterator i = arg.begin(); - for( ; i != arg.End() ; ++i) - Append(*i); + for( ; i != arg.end() ; ++i) + append(*i); return *this; } -template -void MemBuffer::AddDynamicNode() +template +void MemBuffer::add_dynamic_node() { if( dynamic_array_used >= dynamic_array_size ) { @@ -451,7 +506,7 @@ void MemBuffer::AddDynamicNode() } dynamic_array[dynamic_array_used].size_used = 0; - dynamic_array[dynamic_array_used].buf = new ItemType[heap_block_size]; + dynamic_array[dynamic_array_used].buf = new item_type[heap_block_size]; dynamic_array_used += 1; size_allocated += heap_block_size; @@ -460,8 +515,8 @@ void MemBuffer::AddDynamicNode() -template -void MemBuffer::Append(ItemType item) +template +void MemBuffer::append(item_type item) { if( size_used < stack_size ) { @@ -474,7 +529,7 @@ void MemBuffer::Append(ItemType item) dynamic_array_index = 0; if( dynamic_array_index >= dynamic_array_used ) - AddDynamicNode(); + add_dynamic_node(); dynamic_array[dynamic_array_index].size_used = 0; } @@ -484,7 +539,7 @@ void MemBuffer::Append(ItemType item) dynamic_array_index += 1; if( dynamic_array_index >= dynamic_array_used ) - AddDynamicNode(); + add_dynamic_node(); dynamic_array[dynamic_array_index].size_used = 0; } @@ -497,8 +552,8 @@ void MemBuffer::Append(ItemType item) } -template -void MemBuffer::Append(ItemType * item_array, size_t len) +template +void MemBuffer::append(item_type * item_array, size_t len) { if( size_used + len <= stack_size ) { @@ -511,7 +566,7 @@ void MemBuffer::Append(ItemType * item_ar if( dynamic_array_index != size_t(-1) && dynamic_array[dynamic_array_index].size_used + len <= heap_block_size ) { - ItemType * buf = dynamic_array[dynamic_array_index].buf; + item_type * buf = dynamic_array[dynamic_array_index].buf; size_t bufsize = dynamic_array[dynamic_array_index].size_used; for(size_t i=0 ; i::Append(ItemType * item_ar } for(size_t i=0 ; i +template +void MemBuffer::append( + const MemBuffer & arg) +{ + typename MemBuffer::const_iterator i = arg.begin(); + + for( ; i != arg.end() ; ++i) + append(static_cast(*i)); } - -template -ItemType & MemBuffer::operator[](size_t i) +template +item_type & MemBuffer::operator[](size_t i) { if( i < stack_size ) { @@ -549,8 +616,8 @@ ItemType & MemBuffer::operator[](size_t i } -template -const ItemType MemBuffer::operator[](size_t i) const +template +const item_type MemBuffer::operator[](size_t i) const { if( i < stack_size ) { @@ -567,26 +634,26 @@ const ItemType MemBuffer::operator[](size } -template -size_t MemBuffer::Size() const +template +size_t MemBuffer::size() const { return size_used; } -template -bool MemBuffer::Empty() const +template +bool MemBuffer::empty() const { return size_used == 0; } -template -typename MemBuffer::Iterator -MemBuffer::Begin() +template +typename MemBuffer::iterator +MemBuffer::begin() { -Iterator i; +iterator i; i.mem_buffer = this; i.dynamic_array_index = size_t(-1); @@ -596,11 +663,11 @@ return i; } -template -typename MemBuffer::Iterator -MemBuffer::End() +template +typename MemBuffer::iterator +MemBuffer::end() { -Iterator i; +iterator i; i.mem_buffer = this; @@ -632,11 +699,11 @@ return i; -template -typename MemBuffer::ConstIterator -MemBuffer::Begin() const +template +typename MemBuffer::const_iterator +MemBuffer::begin() const { -ConstIterator i; +const_iterator i; i.mem_buffer = this; i.dynamic_array_index = size_t(-1); @@ -646,11 +713,11 @@ return i; } -template -typename MemBuffer::ConstIterator -MemBuffer::End() const +template +typename MemBuffer::const_iterator +MemBuffer::end() const { -ConstIterator i; +const_iterator i; i.mem_buffer = this; @@ -682,25 +749,25 @@ return i; -template -void MemBuffer::Reserve(size_t len) +template +void MemBuffer::reserve(size_t len) { size_reserved = len; while( size_allocated < size_reserved ) - AddDynamicNode(); + add_dynamic_node(); } -template -size_t MemBuffer::Capacity() const +template +size_t MemBuffer::capacity() const { return size_allocated; } -template -void MemBuffer::Clear() +template +void MemBuffer::clear() { size_t index = 0; diff --git a/textstream/textstream.h b/textstream/textstream.h new file mode 100644 index 0000000..ec7db84 --- /dev/null +++ b/textstream/textstream.h @@ -0,0 +1,437 @@ +/* + * This file is a part of PikoTools + * and is distributed under the (new) BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2012, 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_textstream +#define headerfile_picotools_textstream_textstream + +#include +#include "space/space.h" +#include "date/date.h" +#include "convert/convert.h" +#include "membuffer/membuffer.h" + +// for sprintf +#include + +namespace PT +{ + + +/* + a special class representing a stream buffer + 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 +{ +public: + + TextStreamBase(); + + typedef MemBuffer buffer_type; + typedef typename buffer_type::iterator iterator; + typedef typename buffer_type::const_iterator const_iterator; + + void clear(); + bool empty() const; + size_t size() const; + void reserve(size_t len); + size_t capacity() const; + + iterator begin(); + iterator end(); + + const_iterator begin() const; + const_iterator end() const; + + void to_string(std::string & str, bool clear_string = true) const; + void to_string(std::wstring & str, bool clear_string = true) 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); + TextStreamBase & operator<<(const std::wstring & str); + + TextStreamBase & operator<<(char); + TextStreamBase & operator<<(wchar_t); + TextStreamBase & operator<<(int); + TextStreamBase & operator<<(long); + TextStreamBase & operator<<(unsigned int); + TextStreamBase & operator<<(unsigned long); + TextStreamBase & operator<<(double); + TextStreamBase & operator<<(const void *);// printing a pointer + TextStreamBase & operator<<(const PT::Space & space); + TextStreamBase & operator<<(const PT::Date & date); + + TextStreamBase & write(const char * buf, size_t len); + TextStreamBase & write(const wchar_t * buf, size_t len); + +protected: + + int radix; + buffer_type buffer; +}; + + + +template +TextStreamBase::TextStreamBase() +{ + radix = 10; +} + + +template +void TextStreamBase::clear() +{ + buffer.clear(); +} + +template +bool TextStreamBase::empty() const +{ + return buffer.empty(); +} + +template +size_t TextStreamBase::size() const +{ + return buffer.size(); +} + +template +void TextStreamBase::reserve(size_t len) +{ + buffer.reserve(len); +} + +template +size_t TextStreamBase::capacity() const +{ + return buffer.capacity(); +} + +template +typename TextStreamBase::iterator +TextStreamBase::begin() +{ + return buffer.begin(); +} + + +template +typename TextStreamBase::iterator +TextStreamBase::end() +{ + return buffer.end(); +} + + +template +typename TextStreamBase::const_iterator +TextStreamBase::begin() const +{ + return buffer.begin(); +} + + +template +typename TextStreamBase::const_iterator +TextStreamBase::end() const +{ + return buffer.end(); +} + + +template +void TextStreamBase::to_string(std::string & str, bool clear_string) const +{ + if( clear_string ) + str.clear(); + + if( str.capacity() < str.size() + size() ) + str.reserve(str.size() + size()); + + const_iterator i = begin(); + + for( ; i != end() ; ++i) + str += static_cast(*i); +} + + + +template +void TextStreamBase::to_string(std::wstring & str, bool clear_string) const +{ + if( clear_string ) + str.clear(); + + if( str.capacity() < str.size() + size() ) + str.reserve(str.size() + size()); + + const_iterator i = begin(); + + for( ; i != end() ; ++i) + str += static_cast(*i); +} + + + + +template +char_type & TextStreamBase::operator[](size_t index) +{ + return buffer[index]; +} + + +template +char_type TextStreamBase::operator[](size_t index) const +{ + return buffer[index]; +} + + +template +TextStreamBase & +TextStreamBase::operator<<(const char * str) +{ + for( ; *str ; ++str) + buffer.append(static_cast(*str)); + +return *this; +} + + +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()); + +return *this; +} + + + +template +TextStreamBase & +TextStreamBase::operator<<(const wchar_t * str) +{ + for( ; *str ; ++str) + buffer.append(static_cast(*str)); + +return *this; +} + + + +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()); + +return *this; +} + + + +template +TextStreamBase & +TextStreamBase::operator<<(char v) +{ + buffer.append(static_cast(v)); + +return *this; +} + + +template +TextStreamBase & +TextStreamBase::operator<<(wchar_t v) +{ + buffer.append(static_cast(v)); + +return *this; +} + + +template +TextStreamBase & +TextStreamBase::operator<<(int v) +{ + return operator<<(static_cast(v)); +} + + +template +TextStreamBase & +TextStreamBase::operator<<(long v) +{ +char_type buf[50]; +size_t len = sizeof(buf) / sizeof(char_type); +size_t lenout; + + if( Toa(v, buf, len, radix, &lenout) ) + buffer.append(buf, lenout); + +return *this; +} + + +template +TextStreamBase & +TextStreamBase::operator<<(unsigned int v) +{ + return operator<<(static_cast(v)); +} + + +template +TextStreamBase & +TextStreamBase::operator<<(unsigned long v) +{ +char_type buf[50]; +size_t len = sizeof(buf) / sizeof(char_type); +size_t lenout; + + if( Toa(v, buf, len, radix, &lenout) ) + buffer.append(buf, lenout); + +return *this; +} + + +template +TextStreamBase & +TextStreamBase::operator<<(double v) +{ +char buf[50]; + + // !! IMPROVE ME we need our own double->string convertion + sprintf(buf, "%f", v); + return operator<<(buf); +} + + +template +TextStreamBase & +TextStreamBase::operator<<(const void * v) +{ +char_type buf[50]; +size_t len = sizeof(buf) / sizeof(char_type); +size_t lenout; + + buf[0] = '0'; + buf[1] = 'x'; + + if( Toa(reinterpret_cast(v), buf+2, len-2, 16, &lenout) ) + buffer.append(buf, lenout+2); + +return *this; +} + + + +template +TextStreamBase & +TextStreamBase::write(const char * buf, size_t len) +{ + if( sizeof(char_type) == sizeof(char) ) + buffer.append(buf, len); + else + operator<<(buf); + +return *this; +} + + + +template +TextStreamBase & +TextStreamBase::write(const wchar_t * buf, size_t len) +{ + if( sizeof(char_type) == sizeof(wchar_t) ) + buffer.append(buf, len); + else + operator<<(buf); + +return *this; +} + + +template +TextStreamBase & +TextStreamBase::operator<<(const PT::Space & space) +{ + space.Serialize(*this, true, false); + +return *this; +} + + + +template +TextStreamBase & +TextStreamBase::operator<<(const PT::Date & date) +{ + date.Serialize(*this); + +return *this; +} + + +} // namespace + + + +#endif