29 #ifndef Pt_TextBuffer_h
30 #define Pt_TextBuffer_h
33 #include <Pt/String.h>
34 #include <Pt/TextCodec.h>
35 #include <Pt/StreamBuffer.h>
36 #include <Pt/ConversionError.h>
50 template <
typename CharT,
typename ByteT>
67 typedef typename traits_type::int_type
int_type;
70 typedef typename traits_type::pos_type
pos_type;
73 typedef typename traits_type::off_type
off_type;
78 typedef typename CodecType::result CodecResult;
79 typedef MBState state_type;
142 _state = state_type();
148 _codecRefs = codec ? codec->refs() : 0;
153 void attach(std::basic_ios<extern_type>& target)
181 void reset(std::basic_ios<extern_type>& target)
195 _state = state_type();
202 std::streamsize
import(std::streamsize size = 0)
211 this->setg(_ibuf, _ibuf, _ibuf);
214 std::streamsize n = 0;
215 std::basic_streambuf<extern_type>* rdbuf = _target ? _target->rdbuf()
219 if(size == 0 && rdbuf)
220 size = rdbuf->in_avail();
223 const std::streamsize ebufavail = _ebufmax - _ebufsize;
224 size = ebufavail < size ? ebufavail : size;
226 if(size > 0 && rdbuf)
228 n = rdbuf->sgetn( _ebuf + _ebufsize, size );
229 _ebufsize +=
static_cast<int>(n);
237 if( this->gptr() - this->eback() > _pbmax)
239 std::streamsize movelen = this->egptr() - this->gptr() + _pbmax;
240 std::char_traits<char_type>::move( _ibuf,
241 this->gptr() - _pbmax,
242 static_cast<std::size_t>(movelen));
243 this->setg(_ibuf, _ibuf + _pbmax, _ibuf + movelen);
246 typename CodecType::result r = decode();
250 if( rdbuf == 0 && _ebufsize == 0 && r == CodecType::partial)
260 std::streamsize
import(
const extern_type* buf, std::streamsize size)
269 this->setg(_ibuf, _ibuf, _ibuf);
272 const std::streamsize bufavail = _ebufmax - _ebufsize;
273 size = bufavail < size ? bufavail : size;
276 std::char_traits<extern_type>::copy( _ebuf + _ebufsize, buf, static_cast<std::size_t>(size) );
277 _ebufsize +=
static_cast<int>(size);
280 if( this->gptr() - this->eback() > _pbmax)
282 std::streamsize movelen = this->egptr() - this->gptr() + _pbmax;
283 std::char_traits<char_type>::move( _ibuf,
284 this->gptr() - _pbmax,
285 static_cast<std::size_t>(movelen));
286 this->setg(_ibuf, _ibuf + _pbmax, _ibuf + movelen);
302 while( this->pptr() > this->pbase() )
304 if( this->overflow( traits_type::eof() ) == traits_type::eof() )
309 if( _target && _target->rdbuf() && _codec )
311 typename CodecType::result res = CodecType::error;
316 res = _codec->
unshift(_state, _ebuf, _ebuf + _ebufmax, next);
317 if(res == CodecType::noconv)
320 if(res == CodecType::error)
321 throw ConversionError(
"character encoding");
323 std::streamsize n =
static_cast<std::streamsize
>(next - _ebuf);
324 if( n != _target->rdbuf()->sputn(_ebuf, n) )
327 while(res == CodecType::partial);
336 virtual std::streamsize showmanyc()
346 return _target && _target->rdbuf() ? 0 : -1;
352 if( ! _target || ! _target->rdbuf() || this->gptr() )
353 return traits_type::eof();
357 this->setp( _ibuf, _ibuf + _ibufmax );
360 while( this->pptr() > this->pbase() )
369 typename CodecType::result res = CodecType::noconv;
371 res = _codec->
out(_state, fromBegin, fromEnd, fromNext, toBegin, toEnd, toNext);
373 if(res == CodecType::noconv)
375 std::size_t fromSize = fromEnd - fromBegin;
376 std::size_t toSize = toEnd - toBegin;
377 std::size_t size = toSize < fromSize ? toSize : fromSize;
379 this->copyChars( toBegin, fromBegin, size );
385 _ebufsize +=
static_cast<int>(toNext - toBegin);
386 std::size_t leftover = fromEnd - fromNext;
387 if(leftover && fromNext > fromBegin)
389 std::char_traits<char_type>::move(_ibuf, fromNext, leftover);
392 this->setp( _ibuf, _ibuf + _ibufmax );
393 this->pbump( static_cast<int>(leftover) );
395 if(res == CodecType::error)
396 throw ConversionError(
"character encoding");
398 if(res == CodecType::partial && _ebufsize == 0)
401 _ebufsize -=
static_cast<int>(_target->rdbuf()->sputn(_ebuf, _ebufsize));
403 return traits_type::eof();
406 if( ! traits_type::eq_int_type(ch, traits_type::eof()) )
408 *( this->pptr() ) = traits_type::to_char_type(ch);
412 return traits_type::not_eof(ch);
418 if( this->gptr() < this->egptr() )
419 return traits_type::to_int_type( *this->gptr() );
423 return this->gptr() < this->egptr() ? traits_type::to_int_type( *this->gptr() )
438 typename CodecType::result r = CodecType::noconv;
440 r = _codec->
in(_state, fromBegin, fromEnd, fromNext, toBegin, toEnd, toNext);
442 if(r == CodecType::noconv)
445 int n =_ebufsize > _ibufmax ? _ibufmax : _ebufsize ;
446 this->copyChars(toBegin, fromBegin, n);
451 std::streamsize consumed = fromNext - fromBegin;
454 _ebufsize -=
static_cast<int>(consumed);
455 std::char_traits<extern_type>::move( _ebuf, _ebuf + consumed, _ebufsize);
458 std::streamsize generated = toNext - toBegin;
461 this->setg(this->eback(),
463 this->egptr() + generated );
466 if(r == CodecType::error)
467 throw ConversionError(
"character encoding");
473 template <
typename T>
474 void copyChars(T* s1,
const T* s2, std::size_t n)
476 std::char_traits<T>::copy(s1, s2, n);
480 template <
typename A,
typename B>
481 void copyChars(A* s1,
const B* s2, std::size_t n)
492 template <
typename A>
493 void copyChars(A* s1,
const Char* s2, std::size_t n)
497 *s1 =
static_cast<A
>(s2->value());
504 static const int _pbmax = 4;
506 static const int _ebufmax = 256;
510 static const int _ibufmax = 256;
515 std::size_t _codecRefs;
516 std::basic_ios<extern_type>* _target;
531 typedef BasicTextBuffer<Pt::Char, char> TextBuffer;
550 #endif // Pt_TextBuffer_h
Converts character sequences with different encodings.
Definition: TextBuffer.h:51
TextCodec< char_type, extern_type > CodecType
Codec type.
Definition: TextBuffer.h:76
void reset(std::basic_ios< extern_type > &target)
Resets the buffer and target.
Definition: TextBuffer.h:181
void discard()
Discards the buffer.
Definition: TextBuffer.h:189
result unshift(MBState &state, ByteT *to, ByteT *to_end, ByteT *&to_next) const
Unshifts a character sequence.
Indicates a failed conversion.
Definition: ConversionError.h:45
BasicTextBuffer(CodecType *codec=0)
Construct with codec.
Definition: TextBuffer.h:108
traits_type::int_type int_type
Integer type.
Definition: TextBuffer.h:67
Buffer for input and output streams.
Definition: StreamBuffer.h:51
CodecType * codec()
Returns the used codec or a nullptr.
Definition: TextBuffer.h:132
Converts between character encodings.
Definition: TextCodec.h:38
ByteT extern_type
External character type.
Definition: TextBuffer.h:55
traits_type::off_type off_type
Stream offset type.
Definition: TextBuffer.h:73
result out(MBState &state, const CharT *fbeg, const CharT *fend, const CharT *&fnext, ByteT *tbeg, ByteT *tend, ByteT *&tnext) const
Encodes a character sequence.
CharT intern_type
Internal character type.
Definition: TextBuffer.h:58
traits_type::pos_type pos_type
Stream position type.
Definition: TextBuffer.h:70
void reset()
Resets the buffer and target.
Definition: TextBuffer.h:170
CharT char_type
Internal character type.
Definition: TextBuffer.h:61
result in(MBState &s, const ByteT *fbeg, const ByteT *fend, const ByteT *&fnext, CharT *tbeg, CharT *tend, CharT *&tnext) const
Decodes a character sequence.
void setCodec(CodecType *codec)
Sets the text codec.
Definition: TextBuffer.h:140
void detach()
Detach from external target.
Definition: TextBuffer.h:160
BasicTextBuffer(std::basic_ios< extern_type > &target, CodecType *codec=0)
Construct with external device and codec.
Definition: TextBuffer.h:90
std::char_traits< CharT > traits_type
Internal character traits.
Definition: TextBuffer.h:64
~BasicTextBuffer()
Destructor.
Definition: TextBuffer.h:120
void attach(std::basic_ios< extern_type > &target)
Attach to external target.
Definition: TextBuffer.h:153