diff -r e1b950c65cb4 -r 837f303aceeb epoc32/include/stdapis/stlportv5/stl/_fstream.c --- a/epoc32/include/stdapis/stlportv5/stl/_fstream.c Wed Mar 31 12:27:01 2010 +0100 +++ b/epoc32/include/stdapis/stlportv5/stl/_fstream.c Wed Mar 31 12:33:34 2010 +0100 @@ -1,16 +1,14 @@ /* - * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved. - * * Copyright (c) 1996,1997 * Silicon Graphics Computer Systems, Inc. * - * Copyright (c) 1999 + * Copyright (c) 1999 * Boris Fomitchev * * This material is provided "as is", with absolutely no warranty expressed * or implied. Any use is at your own risk. * - * Permission to use or copy this software for any purpose is hereby granted + * Permission to use or copy this software for any purpose is hereby granted * without fee, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was @@ -20,11 +18,13 @@ #ifndef _STLP_FSTREAM_C #define _STLP_FSTREAM_C -# ifndef _STLP_INTERNAL_FSTREAM_H +#ifndef _STLP_INTERNAL_FSTREAM_H # include -# endif +#endif -# if defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION) +#ifndef _STLP_INTERNAL_LIMITS +# include +#endif _STLP_BEGIN_NAMESPACE @@ -60,7 +60,7 @@ _M_codecvt(0), _M_width(1), _M_max_width(1) { - this->_M_setup_codecvt(locale()); + this->_M_setup_codecvt(locale(), false); } template @@ -71,16 +71,14 @@ template -_STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::int_type -basic_filebuf<_CharT, _Traits>::underflow() -{ +_STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::int_type +basic_filebuf<_CharT, _Traits>::underflow() { return _Underflow<_CharT, _Traits>::_M_doit(this); } template -basic_filebuf<_CharT, _Traits>* -basic_filebuf<_CharT, _Traits>::close() -{ +basic_filebuf<_CharT, _Traits>* +basic_filebuf<_CharT, _Traits>::close() { bool __ok = this->is_open(); if (_M_in_output_mode) { @@ -102,14 +100,8 @@ _M_mmap_base = 0; _M_mmap_len = 0; -#ifdef __SYMBIAN32__ - if (__ok) { -#endif // __SYMBIAN32__ this->setg(0, 0, 0); this->setp(0, 0); -#ifdef __SYMBIAN32__ - } -#endif // __SYMBIAN32__ _M_saved_eback = _M_saved_gptr = _M_saved_egptr = 0; @@ -121,12 +113,11 @@ // This member function is called whenever we exit input mode. // It unmaps the memory-mapped file, if any, and sets -// _M_in_input_mode to false. +// _M_in_input_mode to false. template -void basic_filebuf<_CharT, _Traits>::_M_exit_input_mode() -{ +void basic_filebuf<_CharT, _Traits>::_M_exit_input_mode() { if (_M_mmap_base != 0) - _M_base._M_unmap(_M_mmap_base, _M_mmap_len); + _M_base._M_unmap(_M_mmap_base, _M_mmap_len); _M_in_input_mode = false; _M_mmap_base = 0; } @@ -136,35 +127,23 @@ // basic_filebuf<> overridden protected virtual member functions template -streamsize basic_filebuf<_CharT, _Traits>::showmanyc() -{ +streamsize basic_filebuf<_CharT, _Traits>::showmanyc() { // Is there any possibility that reads can succeed? -#ifdef __SYMBIAN32__ - if (!this->is_open() || !(_M_base.__o_mode() & (int)ios_base::in) || _M_in_error_mode) -#else if (!this->is_open() || _M_in_output_mode || _M_in_error_mode) -#endif return -1; - else if (_M_in_putback_mode) return this->egptr() - this->gptr(); - else if (_M_constant_width) { streamoff __pos = _M_base._M_seek(0, ios_base::cur); streamoff __size = _M_base._M_file_size(); -#ifdef __SYMBIAN32__ - if(__size == 0) - return 0; -#endif - return __pos >= 0 && __size > __pos ? __size - __pos : -1; + return __pos >= 0 && __size > __pos ? __size - __pos : 0; } - - else + else return 0; } -// Make a putback position available, if necessary, by switching to a +// Make a putback position available, if necessary, by switching to a // special internal buffer used only for putback. The buffer is // [_M_pback_buf, _M_pback_buf + _S_pback_buf_size), but the base // class only sees a piece of it at a time. (We want to make sure @@ -172,9 +151,8 @@ // The end of the putback buffer is always _M_pback_buf + _S_pback_buf_size, // but the beginning is usually not _M_pback_buf. template -__BF_int_type__ -basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c) -{ +__BF_int_type__ +basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c) { const int_type __eof = traits_type::eof(); // If we aren't already in input mode, pushback is impossible. @@ -197,7 +175,7 @@ _CharT* __pback_end = _M_pback_buf + __STATIC_CAST(int,_S_pback_buf_size); if (_M_in_putback_mode) { // Do we have more room in the putback buffer? - if (this->eback() != _M_pback_buf) + if (this->eback() != _M_pback_buf) this->setg(this->egptr() - 1, this->egptr() - 1, __pback_end); else return __eof; // No more room in the buffer, so fail. @@ -211,45 +189,8 @@ } } else - { -#ifdef __SYMBIAN32__ - if (traits_type::eq_int_type(__c, __eof) ) - { - if(_M_in_putback_mode) - { - _M_in_putback_mode = false; - // we are at putback mode - if(_M_saved_eback != _M_saved_gptr) - { - this->setg(_M_saved_eback, _M_saved_gptr - 1, _M_saved_egptr); - return *this->gptr(); - } - else - this->setg(_M_saved_eback, _M_saved_gptr, _M_saved_egptr); - - } - else - { - if(!this->eback()) - { - streamoff __pos = _M_base._M_seek(0, ios_base::cur); - streamoff __size = _M_base._M_file_size(); - if( __size > 0 && __pos > 0 && __pos == __size) - __pos = _M_base._M_seek(__pos - 1, ios_base::beg); - this->underflow(); - this->setg(this->eback(), this->gptr(), this->egptr()); - return *this->gptr(); - } - else - { - this->setg(this->eback(), this->gptr() - 1, this->egptr()); - return *this->gptr(); - } - } - } -#endif return __eof; - } + // We have made a putback position available. Assign to it, and return. *this->gptr() = traits_type::to_char_type(__c); return __c; @@ -262,32 +203,19 @@ // the base class only sees [_M_int_buf, _M_int_buf_EOS - 1). template __BF_int_type__ -basic_filebuf<_CharT, _Traits>::overflow(int_type __c) -{ +basic_filebuf<_CharT, _Traits>::overflow(int_type __c) { // Switch to output mode, if necessary. - bool putflag = false; if (!_M_in_output_mode) - { -#ifdef __SYMBIAN32__ - if(this->_M_int_buf) - putflag = true; -#endif if (!_M_switch_to_output_mode()) return traits_type::eof(); - } + _CharT* __ibegin = this->_M_int_buf; _CharT* __iend = this->pptr(); this->setp(_M_int_buf, _M_int_buf_EOS - 1); // Put __c at the end of the internal buffer. if (!traits_type::eq_int_type(__c, traits_type::eof())) - *__iend++ = __c; -#ifdef __SYMBIAN32__ - int current_pos = this->gptr() - this->eback(); - streamoff __size = _M_base._M_file_size(); - if(current_pos > 0 && current_pos < __size && _M_base.__is_open()) - _M_base._M_seek(current_pos, ios_base::beg); -#endif + *__iend++ = _Traits::to_char_type(__c); // For variable-width encodings, output may take more than one pass. while (__ibegin != __iend) { @@ -295,37 +223,21 @@ char* __enext = _M_ext_buf; typename _Codecvt::result __status = _M_codecvt->out(_M_state, __ibegin, __iend, __inext, - _M_ext_buf, _M_ext_buf_EOS, __enext); - if (__status == _Codecvt::noconv) -#ifdef __SYMBIAN32__ - { - if(_Noconv_output<_Traits>::_M_doit(this, __ibegin, __iend)) - { - if (this->eback()) - { - *(this->gptr()) = __c; - this->setg(this->eback(), this->gptr() + 1, this->egptr()); - } - if(putflag && this->pptr() < this->epptr()) - this->setp(this->pptr() + 1, this->epptr()); - return traits_type::not_eof(__c); - } - else - return _M_output_error(); - } -#else + _M_ext_buf, _M_ext_buf_EOS, __enext); + if (__status == _Codecvt::noconv) { return _Noconv_output<_Traits>::_M_doit(this, __ibegin, __iend) ? traits_type::not_eof(__c) : _M_output_error(); -#endif + } + // For a constant-width encoding we know that the external buffer // is large enough, so failure to consume the entire internal buffer // or to produce the correct number of external characters, is an error. - // For a variable-width encoding, however, we require only that we + // For a variable-width encoding, however, we require only that we // consume at least one internal character - else if (__status != _Codecvt::error && - ((__inext == __iend && (__enext - _M_ext_buf == - _M_width * (__iend - __ibegin))) || + else if (__status != _Codecvt::error && + (((__inext == __iend) && + (__enext - _M_ext_buf == _M_width * (__iend - __ibegin))) || (!_M_constant_width && __inext != __ibegin))) { // We successfully converted part or all of the internal buffer. ptrdiff_t __n = __enext - _M_ext_buf; @@ -344,15 +256,14 @@ // This member function must be called before any I/O has been // performed on the stream, otherwise it has no effect. // -// __buf == 0 && __n == 0 means to make ths stream unbuffered. +// __buf == 0 && __n == 0 means to make this stream unbuffered. // __buf != 0 && __n > 0 means to use __buf as the stream's internal // buffer, rather than the buffer that would otherwise be allocated // automatically. __buf must be a pointer to an array of _CharT whose // size is at least __n. template basic_streambuf<_CharT, _Traits>* -basic_filebuf<_CharT, _Traits>::setbuf(_CharT* __buf, streamsize __n) -{ +basic_filebuf<_CharT, _Traits>::setbuf(_CharT* __buf, streamsize __n) { if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode && _M_int_buf == 0) { if (__buf == 0 && __n == 0) @@ -367,8 +278,7 @@ __BF_pos_type__ basic_filebuf<_CharT, _Traits>::seekoff(off_type __off, ios_base::seekdir __whence, - ios_base::openmode /* dummy */) -{ + ios_base::openmode /* dummy */) { if (this->is_open() && (__off == 0 || (_M_constant_width && this->_M_base._M_in_binary_mode()))) { @@ -380,9 +290,8 @@ return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence), _State_type()); - // Seek relative to current position. Complicated if we're in input mode. + // Seek relative to current position. Complicated if we're in input mode. else if (__whence == ios_base::cur) { - if (!_M_in_input_mode) return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence), _State_type()); @@ -392,91 +301,74 @@ streamoff __adjust = _M_mmap_len - (this->gptr() - (_CharT*) _M_mmap_base); // if __off == 0, we do not need to exit input mode and to shift file pointer - if (__off == 0) { - return pos_type(_M_base._M_seek(0, ios_base::cur) - __adjust); - } - else -#ifdef __SYMBIAN32__ - return _M_seek_return(_M_base._M_seek(__off, ios_base::cur), _State_type()); -#else - return _M_seek_return(_M_base._M_seek(__off - __adjust, ios_base::cur), _State_type()); -#endif + return __off == 0 ? pos_type(_M_base._M_seek(0, ios_base::cur) - __adjust) + : _M_seek_return(_M_base._M_seek(__off - __adjust, ios_base::cur), _State_type()); } - else if (_M_constant_width) { // Get or set the position. + else if (_M_constant_width) { // Get or set the position. + streamoff __iadj = _M_width * (this->gptr() - this->eback()); - streamoff __iadj = _M_width * (this->gptr() - this->eback()); - // Compensate for offset relative to gptr versus offset relative - // to external pointer. For a text-oriented stream, where the + // to external pointer. For a text-oriented stream, where the // compensation is more than just pointer arithmetic, we may get // but not set the current position. - + if (__iadj <= _M_ext_buf_end - _M_ext_buf) { - - streamoff __eadj = _M_base._M_get_offset(_M_ext_buf + __iadj, _M_ext_buf_end); + streamoff __eadj = _M_base._M_get_offset(_M_ext_buf + __STATIC_CAST(ptrdiff_t, __iadj), _M_ext_buf_end); - if (__off == 0) { - return pos_type(_M_base._M_seek(0, ios_base::cur) - __eadj); - } else { - return _M_seek_return(_M_base._M_seek(__off - __eadj, ios_base::cur), _State_type()); - } + return __off == 0 ? pos_type(_M_base._M_seek(0, ios_base::cur) - __eadj) + : _M_seek_return(_M_base._M_seek(__off - __eadj, ios_base::cur), _State_type()); } - else - return pos_type(-1); - } - else { // Get the position. Encoding is var width. + } else { // Get the position. Encoding is var width. // Get position in internal buffer. ptrdiff_t __ipos = this->gptr() - this->eback(); - + // Get corresponding position in external buffer. _State_type __state = _M_state; int __epos = _M_codecvt->length(__state, _M_ext_buf, _M_ext_buf_end, __ipos); - // Sanity check (expensive): make sure __epos is the right answer. - _State_type __tmp_state = _M_state; - _Filebuf_Tmp_Buf<_CharT> __buf(__ipos); - _CharT* __ibegin = __buf._M_ptr; - _CharT* __inext = __ibegin; + if (__epos >= 0) { + // Sanity check (expensive): make sure __epos is the right answer. + _State_type __tmp_state = _M_state; + _Filebuf_Tmp_Buf<_CharT> __buf(__ipos); + _CharT* __ibegin = __buf._M_ptr; + _CharT* __inext = __ibegin; - const char* __dummy; - typename _Codecvt::result __status - = _M_codecvt->in(__tmp_state, - _M_ext_buf, _M_ext_buf + __epos, __dummy, - __ibegin, __ibegin + __ipos, __inext); - if (__status != _Codecvt::error && - (__status == _Codecvt::noconv || - (__inext == __ibegin + __ipos && - equal(this->gptr(), this->eback(), __ibegin, - _Eq_traits())))) { - // Get the current position (at the end of the external buffer), - // then adjust it. Again, it might be a text-oriented stream. - streamoff __cur = _M_base._M_seek(0, ios_base::cur); - streamoff __adj = - _M_base._M_get_offset(_M_ext_buf, _M_ext_buf + __epos) - - _M_base._M_get_offset(_M_ext_buf, _M_ext_buf_end); - if (__cur != -1 && __cur + __adj >= 0) - return _M_seek_return(__cur + __adj, __state); - else - return pos_type(-1); + const char* __dummy; + typename _Codecvt::result __status + = _M_codecvt->in(__tmp_state, + _M_ext_buf, _M_ext_buf + __epos, __dummy, + __ibegin, __ibegin + __ipos, __inext); + if (__status != _Codecvt::error && + (__status == _Codecvt::noconv || + (__inext == __ibegin + __ipos && + equal(this->eback(), this->gptr(), __ibegin, _STLP_PRIV _Eq_traits())))) { + // Get the current position (at the end of the external buffer), + // then adjust it. Again, it might be a text-oriented stream. + streamoff __cur = _M_base._M_seek(0, ios_base::cur); + streamoff __adj = + _M_base._M_get_offset(_M_ext_buf, _M_ext_buf + __epos) - + _M_base._M_get_offset(_M_ext_buf, _M_ext_buf_end); + if (__cur != -1 && __cur + __adj >= 0) + return __off == 0 ? pos_type(__cur + __adj) + : _M_seek_return(__cur + __adj, __state); + //return _M_seek_return(__cur + __adj, __state); + } + // We failed the sanity check here. } - else // We failed the sanity check. - return pos_type(-1); } } - else // Unrecognized value for __whence. - return pos_type(-1); + // Unrecognized value for __whence here. } - else - return pos_type(-1); + + return pos_type(-1); } template __BF_pos_type__ basic_filebuf<_CharT, _Traits>::seekpos(pos_type __pos, - ios_base::openmode /* dummy */) -{ + ios_base::openmode /* dummy */) { if (this->is_open()) { if (!_M_seek_init(true)) return pos_type(-1); @@ -486,33 +378,26 @@ _M_state = __pos.state(); return _M_seek_return(__off, __pos.state()); } - else - return pos_type(-1); } - else - return pos_type(-1); + + return pos_type(-1); } template -int basic_filebuf<_CharT, _Traits>::sync() -{ +int basic_filebuf<_CharT, _Traits>::sync() { if (_M_in_output_mode) return traits_type::eq_int_type(this->overflow(traits_type::eof()), - traits_type::eof()) - ? -1 - : 0; - else - return 0; + traits_type::eof()) ? -1 : 0; + return 0; } // Change the filebuf's locale. This member function has no effect // unless it is called before any I/O is performed on the stream. template -void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc) -{ - if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode) { +void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc) { + if (!_M_in_input_mode && !_M_in_output_mode && !_M_in_error_mode) { this->_M_setup_codecvt(__loc); } } @@ -524,27 +409,13 @@ // Helper functions for switching between modes. // This member function is called if we're performing the first I/O -// operation on a filebuf, or if we're performing an input operation +// operation on a filebuf, or if we're performing an input operation // immediately after a seek. template -bool basic_filebuf<_CharT, _Traits>::_M_switch_to_input_mode() -{ - - if (this->is_open() && (((int)_M_base.__o_mode() & (int)ios_base::in) !=0) -#ifndef __SYMBIAN32__ - && (_M_in_output_mode == 0) -#endif - && (_M_in_error_mode == 0)) { -#ifdef __STLP_NO_WRITE_SIDE_BUFFERING__ - // If file has been opened in input|output mode - if ((((int)_M_base.__o_mode() & (int)ios_base::out) !=0) -#ifndef __SYMBIAN32__ - && sync() -#endif - && !_M_int_buf && !_M_allocate_buffers(0, 1)) -#else +bool basic_filebuf<_CharT, _Traits>::_M_switch_to_input_mode() { + if (this->is_open() && (((int)_M_base.__o_mode() & (int)ios_base::in) != 0) + && (_M_in_output_mode == 0) && (_M_in_error_mode == 0)) { if (!_M_int_buf && !_M_allocate_buffers()) -#endif return false; _M_ext_buf_converted = _M_ext_buf; @@ -555,30 +426,20 @@ _M_in_input_mode = true; return true; } - else - return false; + return false; } // This member function is called if we're performing the first I/O -// operation on a filebuf, or if we're performing an output operation +// operation on a filebuf, or if we're performing an output operation // immediately after a seek. template -bool basic_filebuf<_CharT, _Traits>::_M_switch_to_output_mode() -{ +bool basic_filebuf<_CharT, _Traits>::_M_switch_to_output_mode() { if (this->is_open() && (_M_base.__o_mode() & (int)ios_base::out) && -#ifdef __SYMBIAN32__ - _M_in_error_mode == 0) { -#else _M_in_input_mode == 0 && _M_in_error_mode == 0) { -#endif //__SYMBIAN32__ -#ifdef __STLP_NO_WRITE_SIDE_BUFFERING__ - if (!_M_int_buf && !_M_allocate_buffers(0, 1)) -#else if (!_M_int_buf && !_M_allocate_buffers()) -#endif return false; // In append mode, every write does an implicit seek to the end @@ -589,11 +450,10 @@ this->setp(_M_int_buf, _M_int_buf_EOS - 1); _M_in_output_mode = true; - return true; } - else - return false; + + return false; } @@ -608,9 +468,8 @@ template __BF_int_type__ -basic_filebuf<_CharT, _Traits>::_M_input_error() -{ - this->_M_exit_input_mode(); +basic_filebuf<_CharT, _Traits>::_M_input_error() { + this->_M_exit_input_mode(); _M_in_output_mode = false; _M_in_error_mode = true; this->setg(0, 0, 0); @@ -618,9 +477,8 @@ } template -__BF_int_type__ -basic_filebuf<_CharT, _Traits>::_M_underflow_aux() -{ +__BF_int_type__ +basic_filebuf<_CharT, _Traits>::_M_underflow_aux() { // We have the state and file position from the end of the internal // buffer. This round, they become the beginning of the internal buffer. _M_state = _M_end_state; @@ -631,33 +489,23 @@ _M_ext_buf_end = copy(_M_ext_buf_converted, _M_ext_buf_end, _M_ext_buf); // boris : copy_backward did not work - //_M_ext_buf_end = copy_backward(_M_ext_buf_converted, _M_ext_buf_end, + //_M_ext_buf_end = copy_backward(_M_ext_buf_converted, _M_ext_buf_end, //_M_ext_buf+ (_M_ext_buf_end - _M_ext_buf_converted)); else - { -#ifdef __SYMBIAN32__ - if(_M_ext_buf == NULL) - _M_allocate_buffers(0, MMAP_CHUNK); -#endif _M_ext_buf_end = _M_ext_buf; - } + // Now fill the external buffer with characters from the file. This is - // a loop because occasonally we don't get enough external characters + // a loop because occasionally we don't get enough external characters // to make progress. - while (true) { + for (;;) { ptrdiff_t __n = _M_base._M_read(_M_ext_buf_end, _M_ext_buf_EOS - _M_ext_buf_end); - + // Don't enter error mode for a failed read. Error mode is sticky, // and we might succeed if we try again. -#ifdef __SYMBIAN32__ //plum hall bug 577 - int nn = (char*)_M_ext_buf_end-(char*)_M_ext_buf; //number of chars unconverted last time - if ( (__n <= 0) && ( nn<=0 ) ) -#else - if (__n <= 0) -#endif + if (__n <= 0) return traits_type::eof(); - // Convert the external buffer to internal characters. + // Convert the external buffer to internal characters. _M_ext_buf_end += __n; const char* __enext; _CharT* __inext; @@ -670,12 +518,11 @@ // Error conditions: (1) Return value of error. (2) Producing internal // characters without consuming external characters. (3) In fixed-width // encodings, producing an internal sequence whose length is inconsistent - // with that of the internal sequence. (4) Failure to produce any + // with that of the internal sequence. (4) Failure to produce any // characters if we have enough characters in the external buffer, where // "enough" means the largest possible width of a single character. if (__status == _Codecvt::noconv) return _Noconv_input<_Traits>::_M_doit(this); - else if (__status == _Codecvt::error || (__inext != _M_int_buf && __enext == _M_ext_buf) || (_M_constant_width && @@ -683,14 +530,13 @@ (__inext - _M_int_buf) * _M_width != (__enext - _M_ext_buf)) || (__inext == _M_int_buf && __enext - _M_ext_buf >= _M_max_width)) return _M_input_error(); - else if (__inext != _M_int_buf) { _M_ext_buf_converted = _M_ext_buf + (__enext - _M_ext_buf); this->setg(_M_int_buf, _M_int_buf, __inext); return traits_type::to_int_type(*_M_int_buf); } // We need to go around the loop again to get more external characters. - } + } } //---------------------------------------- @@ -702,8 +548,7 @@ // seek. template __BF_int_type__ -basic_filebuf<_CharT, _Traits>::_M_output_error() -{ +basic_filebuf<_CharT, _Traits>::_M_output_error() { _M_in_output_mode = false; _M_in_input_mode = false; _M_in_error_mode = true; @@ -717,8 +562,7 @@ // buffer, changes the external file position, and changes the state. // Precondition: the internal buffer is empty. template -bool basic_filebuf<_CharT, _Traits>::_M_unshift() -{ +bool basic_filebuf<_CharT, _Traits>::_M_unshift() { if (_M_in_output_mode && !_M_constant_width) { typename _Codecvt::result __status; do { @@ -732,7 +576,7 @@ return false; else if (!_M_write(_M_ext_buf, __enext - _M_ext_buf)) return false; - } while(__status == _Codecvt::partial); + } while (__status == _Codecvt::partial); } return true; @@ -746,22 +590,31 @@ // internal and external buffers. The argument is the size of the // internal buffer; the external buffer is sized using the character // width in the current encoding. Preconditions: the buffers are currently -// null. __n >= 1. __buf is either a null pointer or a pointer to an +// null. __n >= 1. __buf is either a null pointer or a pointer to an // array show size is at least __n. // We need __n >= 1 for two different reasons. For input, the base -// class always needs a buffer because of the sementics of underflow(). +// class always needs a buffer because of the semantics of underflow(). // For output, we want to have an internal buffer that's larger by one -// element than the buffer that the base class knows about. (See +// element than the buffer that the base class knows about. (See // basic_filebuf<>::overflow() for the reason.) template -bool -basic_filebuf<_CharT, _Traits>::_M_allocate_buffers(_CharT* __buf, streamsize __n) -{ +bool basic_filebuf<_CharT, _Traits>::_M_allocate_buffers(_CharT* __buf, streamsize __n) { + //The major hypothesis in the following implementation is that size_t is unsigned. + //We also need streamsize byte representation to be larger or equal to the int + //representation to correctly store the encoding information. + _STLP_STATIC_ASSERT(!numeric_limits::is_signed && + sizeof(streamsize) >= sizeof(int)) if (__buf == 0) { - _M_int_buf = __STATIC_CAST(_CharT*,malloc(__n * sizeof(_CharT))); - if (! _M_int_buf) + streamsize __bufsize = __n * sizeof(_CharT); + //We first check that the streamsize representation can't overflow a size_t one. + //If it can, we check that __bufsize is not higher than the size_t max value. + if ((sizeof(streamsize) > sizeof(size_t)) && + (__bufsize > __STATIC_CAST(streamsize, (numeric_limits::max)()))) + return false; + _M_int_buf = __STATIC_CAST(_CharT*, malloc(__STATIC_CAST(size_t, __bufsize))); + if (!_M_int_buf) return false; _M_int_buf_dynamic = true; } @@ -769,25 +622,29 @@ _M_int_buf = __buf; _M_int_buf_dynamic = false; } - - size_t __ebufsiz = (max)(__n * (max)(_M_codecvt->encoding(), 1), - streamsize(_M_codecvt->max_length())); - _M_ext_buf = __STATIC_CAST(char*,malloc(__ebufsiz)); + streamsize __ebufsiz = (max)(__n * __STATIC_CAST(streamsize, _M_width), + __STATIC_CAST(streamsize, _M_codecvt->max_length())); + _M_ext_buf = 0; + if ((sizeof(streamsize) < sizeof(size_t)) || + ((sizeof(streamsize) == sizeof(size_t)) && numeric_limits::is_signed) || + (__ebufsiz <= __STATIC_CAST(streamsize, (numeric_limits::max)()))) { + _M_ext_buf = __STATIC_CAST(char*, malloc(__STATIC_CAST(size_t, __ebufsiz))); + } + if (!_M_ext_buf) { _M_deallocate_buffers(); return false; } - _M_int_buf_EOS = _M_int_buf + __n; - _M_ext_buf_EOS = _M_ext_buf + __ebufsiz; + _M_int_buf_EOS = _M_int_buf + __STATIC_CAST(ptrdiff_t, __n); + _M_ext_buf_EOS = _M_ext_buf + __STATIC_CAST(ptrdiff_t, __ebufsiz); return true; } // Abbreviation for the most common case. template -bool basic_filebuf<_CharT, _Traits>::_M_allocate_buffers() -{ +bool basic_filebuf<_CharT, _Traits>::_M_allocate_buffers() { // Choose a buffer that's at least 4096 characters long and that's a // multiple of the page size. streamsize __default_bufsiz = @@ -796,8 +653,7 @@ } template -void basic_filebuf<_CharT, _Traits>::_M_deallocate_buffers() -{ +void basic_filebuf<_CharT, _Traits>::_M_deallocate_buffers() { if (_M_int_buf_dynamic) free(_M_int_buf); free(_M_ext_buf); @@ -815,7 +671,7 @@ bool basic_filebuf<_CharT, _Traits>::_M_seek_init(bool __do_unshift) { // If we're in error mode, leave it. _M_in_error_mode = false; - + // Flush the output buffer if we're in output mode, and (conditionally) // emit an unshift sequence. if (_M_in_output_mode) { @@ -839,53 +695,43 @@ } -// Change the filebuf's locale. This member function has no effect -// unless it is called before any I/O is performed on the stream. +/* Change the filebuf's locale. This member function has no effect + * unless it is called before any I/O is performed on the stream. + * This function is called on construction and on an imbue call. In the + * case of the construction the codecvt facet might be a custom one if + * the basic_filebuf user has instanciate it with a custom char_traits. + * The user will have to call imbue before any I/O operation. + */ template -void basic_filebuf<_CharT, _Traits>::_M_setup_codecvt(const locale& __loc) -{ - _M_codecvt = &use_facet<_Codecvt>(__loc) ; - int __encoding = _M_codecvt->encoding(); +void basic_filebuf<_CharT, _Traits>::_M_setup_codecvt(const locale& __loc, bool __on_imbue) { + if (has_facet<_Codecvt>(__loc)) { + _M_codecvt = &use_facet<_Codecvt>(__loc) ; + int __encoding = _M_codecvt->encoding(); - _M_width = (max)(__encoding, 1); - _M_max_width = _M_codecvt->max_length(); - _M_constant_width = __encoding > 0; - _M_always_noconv = _M_codecvt->always_noconv(); + _M_width = (max)(__encoding, 1); + _M_max_width = _M_codecvt->max_length(); + _M_constant_width = __encoding > 0; + _M_always_noconv = _M_codecvt->always_noconv(); + } + else { + _M_codecvt = 0; + _M_width = _M_max_width = 1; + _M_constant_width = _M_always_noconv = false; + if (__on_imbue) { + //This call will generate an exception reporting the problem. + use_facet<_Codecvt>(__loc); + } + } } - - -template - _STLP_EXP_DECLSPEC basic_fstream<_CharT, _Traits>::basic_fstream() - : basic_ios<_CharT, _Traits>(), basic_iostream<_CharT, _Traits>(0), _M_buf() { - this->init(&_M_buf); - } - - -template - _STLP_EXP_DECLSPEC basic_fstream<_CharT, _Traits>::~basic_fstream(){} - -#ifdef __SYMBIAN32__ -template -int basic_filebuf<_CharT, _Traits>::save_read_buffer () - { - return _M_in_putback_mode ? _M_saved_egptr - _M_saved_gptr : 0; - } -template -void basic_filebuf<_CharT, _Traits>::_change_input_mode () - { - _M_in_input_mode = 1; - } - -#endif - _STLP_END_NAMESPACE # undef __BF_int_type__ # undef __BF_pos_type__ # undef __BF_off_type__ -# endif /* defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION) */ - #endif /* _STLP_FSTREAM_C */ +// Local Variables: +// mode:C++ +// End: