epoc32/include/stdapis/stlport/stl/_fstream.c
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
     1 /*
     2  * © Portions copyright (c) 2006-2007 Nokia Corporation.  All rights reserved.
     3  *
     4  * Copyright (c) 1996,1997
     5  * Silicon Graphics Computer Systems, Inc.
     6  *
     7  * Copyright (c) 1999 
     8  * Boris Fomitchev
     9  *
    10  * This material is provided "as is", with absolutely no warranty expressed
    11  * or implied. Any use is at your own risk.
    12  *
    13  * Permission to use or copy this software for any purpose is hereby granted 
    14  * without fee, provided the above notices are retained on all copies.
    15  * Permission to modify the code and to distribute modified code is granted,
    16  * provided the above notices are retained, and a notice that the code was
    17  * modified is included with the above copyright notice.
    18  *
    19  */
    20 #ifndef _STLP_FSTREAM_C
    21 #define _STLP_FSTREAM_C
    22 
    23 # ifndef _STLP_INTERNAL_FSTREAM_H
    24 #  include <stl/_fstream.h>
    25 # endif
    26 
    27 # if defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION)
    28 
    29 _STLP_BEGIN_NAMESPACE
    30 
    31 # if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
    32 // no wchar_t is supported for this mode
    33 # define __BF_int_type__ int
    34 # define __BF_pos_type__ streampos
    35 # define __BF_off_type__ streamoff
    36 # else
    37 # define __BF_int_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::int_type
    38 # define __BF_pos_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::pos_type
    39 # define __BF_off_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::off_type
    40 # endif
    41 
    42 
    43 //----------------------------------------------------------------------
    44 // Public basic_filebuf<> member functions
    45 
    46 template <class _CharT, class _Traits>
    47 basic_filebuf<_CharT, _Traits>::basic_filebuf()
    48      :  basic_streambuf<_CharT, _Traits>(), _M_base(),
    49     _M_constant_width(false), _M_always_noconv(false),
    50     _M_int_buf_dynamic(false),
    51     _M_in_input_mode(false), _M_in_output_mode(false),
    52     _M_in_error_mode(false), _M_in_putback_mode(false),
    53     _M_int_buf(0), _M_int_buf_EOS(0),
    54     _M_ext_buf(0), _M_ext_buf_EOS(0),
    55     _M_ext_buf_converted(0), _M_ext_buf_end(0),
    56     _M_state(_STLP_DEFAULT_CONSTRUCTED(_State_type)),
    57     _M_end_state(_STLP_DEFAULT_CONSTRUCTED(_State_type)),
    58     _M_mmap_base(0), _M_mmap_len(0),
    59     _M_saved_eback(0), _M_saved_gptr(0), _M_saved_egptr(0),
    60     _M_codecvt(0),
    61     _M_width(1), _M_max_width(1)
    62 {
    63   this->_M_setup_codecvt(locale());
    64 }
    65 
    66 template <class _CharT, class _Traits>
    67 basic_filebuf<_CharT, _Traits>::~basic_filebuf() {
    68   this->close();
    69   _M_deallocate_buffers();
    70 }
    71 
    72 
    73 template <class _CharT, class _Traits>
    74 _STLP_TYPENAME_ON_RETURN_TYPE basic_filebuf<_CharT, _Traits>::int_type 
    75 basic_filebuf<_CharT, _Traits>::underflow() 
    76 {
    77   return _Underflow<_CharT, _Traits>::_M_doit(this);
    78 }
    79 
    80 template <class _CharT, class _Traits>
    81 basic_filebuf<_CharT, _Traits>* 
    82 basic_filebuf<_CharT, _Traits>::close()
    83 {
    84   bool __ok = this->is_open();
    85 
    86   if (_M_in_output_mode) {
    87     __ok = __ok && !_Traits::eq_int_type(this->overflow(traits_type::eof()),
    88                                          traits_type::eof());
    89     __ok == __ok && this->_M_unshift();
    90   }
    91   else if (_M_in_input_mode)
    92       this->_M_exit_input_mode();
    93 
    94   // Note order of arguments.  We close the file even if __ok is false.
    95   __ok = _M_base._M_close() && __ok;
    96 
    97   // Restore the initial state, except that we don't deallocate the buffer
    98   // or mess with the cached codecvt information.
    99   _M_state = _M_end_state = _State_type();
   100   _M_ext_buf_converted = _M_ext_buf_end = 0;
   101 
   102   _M_mmap_base = 0;
   103   _M_mmap_len = 0;
   104 
   105 #ifdef __SYMBIAN32__
   106   if (__ok) {
   107 #endif // __SYMBIAN32__
   108   this->setg(0, 0, 0);
   109   this->setp(0, 0);
   110 #ifdef __SYMBIAN32__  
   111   }
   112 #endif // __SYMBIAN32__
   113 
   114   _M_saved_eback = _M_saved_gptr = _M_saved_egptr = 0;
   115 
   116   _M_in_input_mode = _M_in_output_mode = _M_in_error_mode = _M_in_putback_mode
   117     = false;
   118 
   119   return __ok ? this : 0;
   120 }
   121 
   122 // This member function is called whenever we exit input mode.
   123 // It unmaps the memory-mapped file, if any, and sets
   124 // _M_in_input_mode to false.  
   125 template <class _CharT, class _Traits>
   126 void basic_filebuf<_CharT, _Traits>::_M_exit_input_mode()
   127 {
   128    if (_M_mmap_base != 0)
   129      _M_base._M_unmap(_M_mmap_base, _M_mmap_len); 
   130    _M_in_input_mode = false;
   131    _M_mmap_base = 0;
   132 }
   133 
   134 
   135 //----------------------------------------------------------------------
   136 // basic_filebuf<> overridden protected virtual member functions
   137 
   138 template <class _CharT, class _Traits>
   139 streamsize basic_filebuf<_CharT, _Traits>::showmanyc()
   140 {
   141   // Is there any possibility that reads can succeed?
   142 #ifdef __SYMBIAN32__
   143   if (!this->is_open() || !(_M_base.__o_mode() & (int)ios_base::in) || _M_in_error_mode)
   144 #else
   145   if (!this->is_open() || _M_in_output_mode || _M_in_error_mode)
   146 #endif
   147     return -1;
   148 
   149   else if (_M_in_putback_mode)
   150     return this->egptr() - this->gptr();
   151 
   152   else if (_M_constant_width) {
   153     streamoff __pos  = _M_base._M_seek(0, ios_base::cur);
   154     streamoff __size = _M_base._M_file_size();
   155 #ifdef __SYMBIAN32__
   156     if(__size == 0)
   157         return 0;
   158 #endif
   159     return __pos >= 0 && __size > __pos ? __size - __pos : -1;
   160   }
   161 
   162   else 
   163     return 0;
   164 }
   165 
   166 
   167 // Make a putback position available, if necessary, by switching to a 
   168 // special internal buffer used only for putback.  The buffer is
   169 // [_M_pback_buf, _M_pback_buf + _S_pback_buf_size), but the base
   170 // class only sees a piece of it at a time.  (We want to make sure
   171 // that we don't try to read a character that hasn't been initialized.)
   172 // The end of the putback buffer is always _M_pback_buf + _S_pback_buf_size,
   173 // but the beginning is usually not _M_pback_buf.
   174 template <class _CharT, class _Traits>
   175 __BF_int_type__ 
   176 basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c)
   177 {
   178   const int_type __eof = traits_type::eof();
   179 
   180   // If we aren't already in input mode, pushback is impossible.
   181   if (!_M_in_input_mode)
   182     return __eof;
   183 
   184   // We can use the ordinary get buffer if there's enough space, and
   185   // if it's a buffer that we're allowed to write to.
   186   if (this->gptr() != this->eback() &&
   187       (traits_type::eq_int_type(__c, __eof) ||
   188        traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]) ||
   189        !_M_mmap_base)) {
   190     this->gbump(-1);
   191     if (traits_type::eq_int_type(__c, __eof) ||
   192         traits_type::eq(traits_type::to_char_type(__c), *this->gptr()))
   193       return traits_type::to_int_type(*this->gptr());
   194   }
   195   else if (!traits_type::eq_int_type(__c, __eof)) {
   196     // Are we in the putback buffer already?
   197     _CharT* __pback_end = _M_pback_buf + __STATIC_CAST(int,_S_pback_buf_size);
   198     if (_M_in_putback_mode) {
   199       // Do we have more room in the putback buffer?
   200       if (this->eback() != _M_pback_buf) 
   201         this->setg(this->egptr() - 1, this->egptr() - 1, __pback_end);
   202       else
   203         return __eof;           // No more room in the buffer, so fail.
   204     }
   205     else {                      // We're not yet in the putback buffer.
   206       _M_saved_eback = this->eback();
   207       _M_saved_gptr  = this->gptr();
   208       _M_saved_egptr = this->egptr();
   209       this->setg(__pback_end - 1, __pback_end - 1, __pback_end);
   210       _M_in_putback_mode = true;
   211     }
   212   }
   213   else
   214   {
   215 #ifdef __SYMBIAN32__
   216     if (traits_type::eq_int_type(__c, __eof) )
   217     {
   218         if(_M_in_putback_mode)
   219         {
   220             _M_in_putback_mode = false;
   221             // we are at putback mode
   222             if(_M_saved_eback != _M_saved_gptr)
   223             {
   224                 this->setg(_M_saved_eback, _M_saved_gptr - 1, _M_saved_egptr);
   225                 return *this->gptr();
   226             }
   227             else
   228                 this->setg(_M_saved_eback, _M_saved_gptr, _M_saved_egptr);
   229          
   230          }
   231          else
   232          {
   233             if(!this->eback())
   234             {
   235                 streamoff __pos  = _M_base._M_seek(0, ios_base::cur);
   236                 streamoff __size = _M_base._M_file_size();
   237                 if( __size > 0 && __pos > 0 && __pos == __size)
   238                     __pos  = _M_base._M_seek(__pos - 1, ios_base::beg);
   239                 this->underflow();
   240                 this->setg(this->eback(), this->gptr(), this->egptr());
   241                 return *this->gptr();
   242             }
   243             else
   244             {
   245                 this->setg(this->eback(), this->gptr() - 1, this->egptr());
   246                 return *this->gptr();
   247             }
   248          }
   249     }
   250 #endif
   251     return __eof;
   252   }
   253   // We have made a putback position available.  Assign to it, and return.
   254   *this->gptr() = traits_type::to_char_type(__c);
   255   return __c;
   256 }
   257 
   258 // This member function flushes the put area, and also outputs the
   259 // character __c (unless __c is eof).  Invariant: we always leave room
   260 // in the internal buffer for one character more than the base class knows
   261 // about.  We see the internal buffer as [_M_int_buf, _M_int_buf_EOS), but
   262 // the base class only sees [_M_int_buf, _M_int_buf_EOS - 1).
   263 template <class _CharT, class _Traits>
   264 __BF_int_type__
   265 basic_filebuf<_CharT, _Traits>::overflow(int_type __c)
   266 {
   267   // Switch to output mode, if necessary.
   268   bool putflag = false;
   269   if (!_M_in_output_mode)
   270   {
   271 #ifdef __SYMBIAN32__
   272     if(this->_M_int_buf)
   273         putflag = true;
   274 #endif
   275     if (!_M_switch_to_output_mode())
   276       return traits_type::eof();
   277   }
   278   _CharT* __ibegin = this->_M_int_buf;
   279   _CharT* __iend   = this->pptr();
   280   this->setp(_M_int_buf, _M_int_buf_EOS - 1);
   281 
   282   // Put __c at the end of the internal buffer.
   283   if (!traits_type::eq_int_type(__c, traits_type::eof()))
   284     *__iend++ = __c;
   285 #ifdef __SYMBIAN32__
   286   int current_pos = this->gptr() - this->eback();
   287   streamoff __size = _M_base._M_file_size();
   288   if(current_pos > 0 && current_pos < __size && _M_base.__is_open())
   289     _M_base._M_seek(current_pos, ios_base::beg);
   290 #endif
   291 
   292   // For variable-width encodings, output may take more than one pass.
   293   while (__ibegin != __iend) {
   294     const _CharT* __inext = __ibegin;
   295     char* __enext         = _M_ext_buf;
   296     typename _Codecvt::result __status
   297       = _M_codecvt->out(_M_state, __ibegin, __iend, __inext,
   298                                   _M_ext_buf, _M_ext_buf_EOS, __enext);
   299     if (__status == _Codecvt::noconv)
   300 #ifdef __SYMBIAN32__    
   301     {
   302       if(_Noconv_output<_Traits>::_M_doit(this, __ibegin, __iend))
   303       {
   304         if (this->eback())
   305             {
   306             *(this->gptr()) = __c;
   307             this->setg(this->eback(), this->gptr() + 1, this->egptr());
   308             }
   309         if(putflag && this->pptr()  < this->epptr())
   310             this->setp(this->pptr() + 1, this->epptr());
   311         return traits_type::not_eof(__c);
   312       }
   313       else
   314         return _M_output_error();
   315     }
   316 #else
   317       return _Noconv_output<_Traits>::_M_doit(this, __ibegin, __iend)
   318         ? traits_type::not_eof(__c)
   319         : _M_output_error();
   320 #endif
   321     // For a constant-width encoding we know that the external buffer
   322     // is large enough, so failure to consume the entire internal buffer
   323     // or to produce the correct number of external characters, is an error.
   324     // For a variable-width encoding, however, we require only that we 
   325     // consume at least one internal character
   326     else if (__status != _Codecvt::error && 
   327              ((__inext == __iend && (__enext - _M_ext_buf == 
   328                                      _M_width * (__iend - __ibegin))) ||
   329               (!_M_constant_width && __inext != __ibegin))) {
   330         // We successfully converted part or all of the internal buffer.
   331       ptrdiff_t __n = __enext - _M_ext_buf;
   332       if (_M_write(_M_ext_buf, __n))
   333         __ibegin += __inext - __ibegin;
   334       else
   335         return _M_output_error();
   336     }
   337     else
   338       return _M_output_error();
   339   }
   340 
   341   return traits_type::not_eof(__c);
   342 }
   343 
   344 // This member function must be called before any I/O has been
   345 // performed on the stream, otherwise it has no effect.
   346 //
   347 // __buf == 0 && __n == 0 means to make ths stream unbuffered.
   348 // __buf != 0 && __n > 0 means to use __buf as the stream's internal
   349 // buffer, rather than the buffer that would otherwise be allocated
   350 // automatically.  __buf must be a pointer to an array of _CharT whose
   351 // size is at least __n.
   352 template <class _CharT, class _Traits>
   353 basic_streambuf<_CharT, _Traits>*
   354 basic_filebuf<_CharT, _Traits>::setbuf(_CharT* __buf, streamsize __n)
   355 {
   356   if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode &&
   357       _M_int_buf == 0) {
   358     if (__buf == 0 && __n == 0)
   359       _M_allocate_buffers(0, 1);
   360     else if (__buf != 0 && __n > 0)
   361       _M_allocate_buffers(__buf, __n);
   362   }
   363   return this;
   364 }
   365 
   366 template <class _CharT, class _Traits>
   367 __BF_pos_type__
   368 basic_filebuf<_CharT, _Traits>::seekoff(off_type __off,
   369                                         ios_base::seekdir __whence,
   370                                         ios_base::openmode /* dummy */)
   371 {
   372   if (this->is_open() &&
   373       (__off == 0 || (_M_constant_width && this->_M_base._M_in_binary_mode()))) {
   374 
   375     if (!_M_seek_init(__off != 0 || __whence != ios_base::cur))
   376       return pos_type(-1);
   377 
   378     // Seek to beginning or end, regardless of whether we're in input mode.
   379     if (__whence == ios_base::beg || __whence == ios_base::end)
   380       return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
   381                             _State_type());
   382 
   383     // Seek relative to current position.  Complicated if we're in input mode.
   384     else if (__whence == ios_base::cur) {
   385 
   386       if (!_M_in_input_mode)
   387         return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
   388                               _State_type());
   389       else if (_M_mmap_base != 0) {
   390         // __off is relative to gptr().  We need to do a bit of arithmetic
   391         // to get an offset relative to the external file pointer.
   392         streamoff __adjust = _M_mmap_len - (this->gptr() - (_CharT*) _M_mmap_base);
   393 
   394         // if __off == 0, we do not need to exit input mode and to shift file pointer
   395         if (__off == 0) {
   396           return pos_type(_M_base._M_seek(0, ios_base::cur) - __adjust);
   397         }
   398         else
   399 #ifdef __SYMBIAN32__       
   400         return _M_seek_return(_M_base._M_seek(__off, ios_base::cur), _State_type());
   401 #else      
   402           return _M_seek_return(_M_base._M_seek(__off - __adjust, ios_base::cur), _State_type());
   403 #endif
   404       }
   405       else if (_M_constant_width) { // Get or set the position.  
   406 
   407         streamoff __iadj = _M_width * (this->gptr() - this->eback());
   408         
   409         // Compensate for offset relative to gptr versus offset relative
   410         // to external pointer.  For a text-oriented stream, where the 
   411         // compensation is more than just pointer arithmetic, we may get
   412         // but not set the current position.
   413         
   414         if (__iadj <= _M_ext_buf_end - _M_ext_buf) {
   415           
   416           streamoff __eadj =  _M_base._M_get_offset(_M_ext_buf + __iadj, _M_ext_buf_end);
   417 
   418           if (__off == 0) {
   419             return pos_type(_M_base._M_seek(0, ios_base::cur) - __eadj);
   420           }  else {
   421             return _M_seek_return(_M_base._M_seek(__off - __eadj, ios_base::cur), _State_type());
   422           }
   423         }
   424         else
   425           return pos_type(-1);
   426       }
   427       else {                    // Get the position.  Encoding is var width.
   428         // Get position in internal buffer.
   429         ptrdiff_t __ipos = this->gptr() - this->eback();
   430         
   431         // Get corresponding position in external buffer.
   432         _State_type __state = _M_state;
   433         int __epos = _M_codecvt->length(__state, _M_ext_buf, _M_ext_buf_end,
   434                                         __ipos);
   435 
   436         // Sanity check (expensive): make sure __epos is the right answer.
   437         _State_type __tmp_state = _M_state;
   438         _Filebuf_Tmp_Buf<_CharT> __buf(__ipos);
   439         _CharT* __ibegin = __buf._M_ptr;
   440         _CharT* __inext  = __ibegin;
   441 
   442         const char* __dummy;
   443         typename _Codecvt::result __status
   444           = _M_codecvt->in(__tmp_state,
   445                            _M_ext_buf, _M_ext_buf + __epos, __dummy,
   446                            __ibegin, __ibegin + __ipos, __inext);
   447         if (__status != _Codecvt::error &&
   448             (__status == _Codecvt::noconv ||
   449              (__inext == __ibegin + __ipos &&
   450               equal(this->gptr(), this->eback(), __ibegin,
   451                     _Eq_traits<traits_type>())))) {
   452           // Get the current position (at the end of the external buffer),
   453           // then adjust it.  Again, it might be a text-oriented stream.
   454           streamoff __cur = _M_base._M_seek(0, ios_base::cur);
   455           streamoff __adj =
   456             _M_base._M_get_offset(_M_ext_buf, _M_ext_buf + __epos) -
   457             _M_base._M_get_offset(_M_ext_buf, _M_ext_buf_end);
   458           if (__cur != -1 && __cur + __adj >= 0)
   459             return _M_seek_return(__cur + __adj, __state);
   460           else
   461             return pos_type(-1);
   462         }
   463         else                    // We failed the sanity check.
   464           return pos_type(-1);
   465       }
   466     }
   467     else                        // Unrecognized value for __whence.
   468       return pos_type(-1);
   469   }
   470   else
   471     return pos_type(-1);
   472 }
   473 
   474 
   475 template <class _CharT, class _Traits>
   476 __BF_pos_type__
   477 basic_filebuf<_CharT, _Traits>::seekpos(pos_type __pos,
   478                                         ios_base::openmode /* dummy */)
   479 {
   480   if (this->is_open()) {
   481     if (!_M_seek_init(true))
   482       return pos_type(-1);
   483 
   484     streamoff __off = off_type(__pos);
   485     if (__off != -1 && _M_base._M_seek(__off, ios_base::beg) != -1) {
   486       _M_state = __pos.state();
   487       return _M_seek_return(__off, __pos.state());
   488     }
   489     else
   490       return pos_type(-1);
   491   }
   492   else
   493     return pos_type(-1);
   494 }
   495 
   496 
   497 template <class _CharT, class _Traits>
   498 int basic_filebuf<_CharT, _Traits>::sync()
   499 {
   500   if (_M_in_output_mode)
   501     return traits_type::eq_int_type(this->overflow(traits_type::eof()),
   502                                     traits_type::eof())
   503       ? -1
   504       : 0;
   505   else
   506     return 0;
   507 }
   508 
   509 
   510 // Change the filebuf's locale.  This member function has no effect
   511 // unless it is called before any I/O is performed on the stream.
   512 template <class _CharT, class _Traits>
   513 void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc)
   514 {
   515   if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode) {
   516     this->_M_setup_codecvt(__loc);
   517   }
   518 }
   519 
   520 //----------------------------------------------------------------------
   521 // basic_filebuf<> helper functions.
   522 
   523 //----------------------------------------
   524 // Helper functions for switching between modes.
   525 
   526 // This member function is called if we're performing the first I/O
   527 // operation on a filebuf, or if we're performing an input operation 
   528 // immediately after a seek.
   529 template <class _CharT, class _Traits>
   530 bool basic_filebuf<_CharT, _Traits>::_M_switch_to_input_mode()
   531 {
   532 
   533   if (this->is_open() && (((int)_M_base.__o_mode() & (int)ios_base::in) !=0)
   534 #ifndef __SYMBIAN32__
   535       && (_M_in_output_mode == 0) 
   536 #endif
   537       && (_M_in_error_mode == 0)) {
   538 #ifdef __STLP_NO_WRITE_SIDE_BUFFERING__
   539     // If file has been opened in input|output mode
   540     if ((((int)_M_base.__o_mode() & (int)ios_base::out) !=0) 
   541 #ifndef __SYMBIAN32__
   542         && sync()
   543 #endif
   544         && !_M_int_buf && !_M_allocate_buffers(0, 1))
   545 #else
   546     if (!_M_int_buf && !_M_allocate_buffers())
   547 #endif
   548       return false;
   549 
   550     _M_ext_buf_converted = _M_ext_buf;
   551     _M_ext_buf_end       = _M_ext_buf;
   552 
   553     _M_end_state    = _M_state;
   554 
   555     _M_in_input_mode = true;
   556     return true;
   557   }
   558   else
   559 
   560     return false;
   561 }
   562 
   563 
   564 // This member function is called if we're performing the first I/O
   565 // operation on a filebuf, or if we're performing an output operation 
   566 // immediately after a seek.
   567 template <class _CharT, class _Traits>
   568 bool basic_filebuf<_CharT, _Traits>::_M_switch_to_output_mode()
   569 {
   570   if (this->is_open() && (_M_base.__o_mode() & (int)ios_base::out) &&
   571 #ifdef __SYMBIAN32__  
   572       _M_in_error_mode == 0) {
   573 #else      
   574       _M_in_input_mode == 0 && _M_in_error_mode == 0) {
   575 #endif //__SYMBIAN32__      
   576 
   577 #ifdef __STLP_NO_WRITE_SIDE_BUFFERING__
   578     if (!_M_int_buf && !_M_allocate_buffers(0, 1))
   579 #else
   580     if (!_M_int_buf && !_M_allocate_buffers())
   581 #endif
   582       return false;
   583 
   584     // In append mode, every write does an implicit seek to the end
   585     // of the file.  Whenever leaving output mode, the end of file
   586     // get put in the initial shift state.
   587     if (_M_base.__o_mode() & ios_base::app)
   588       _M_state = _State_type();
   589 
   590     this->setp(_M_int_buf, _M_int_buf_EOS - 1);
   591     _M_in_output_mode = true;
   592 
   593     return true;
   594   }
   595   else
   596     return false;
   597 }
   598 
   599 
   600 //----------------------------------------
   601 // Helper functions for input
   602 
   603 // This member function is called if there is an error during input.
   604 // It puts the filebuf in error mode, clear the get area buffer, and
   605 // returns eof.
   606 // returns eof.  Error mode is sticky; it is cleared only by close or
   607 // seek.
   608 
   609 template <class _CharT, class _Traits>
   610 __BF_int_type__
   611 basic_filebuf<_CharT, _Traits>::_M_input_error()
   612 {
   613    this->_M_exit_input_mode();   
   614   _M_in_output_mode = false;
   615   _M_in_error_mode = true;
   616   this->setg(0, 0, 0);
   617   return traits_type::eof();
   618 }
   619 
   620 template <class _CharT, class _Traits>
   621 __BF_int_type__ 
   622 basic_filebuf<_CharT, _Traits>::_M_underflow_aux() 
   623 {
   624   // We have the state and file position from the end of the internal
   625   // buffer.  This round, they become the beginning of the internal buffer.
   626   _M_state    = _M_end_state;
   627 
   628   // Fill the external buffer.  Start with any leftover characters that
   629   // didn't get converted last time.
   630   if (_M_ext_buf_end > _M_ext_buf_converted)
   631 
   632     _M_ext_buf_end = copy(_M_ext_buf_converted, _M_ext_buf_end, _M_ext_buf);
   633     // boris : copy_backward did not work
   634     //_M_ext_buf_end = copy_backward(_M_ext_buf_converted, _M_ext_buf_end, 
   635     //_M_ext_buf+ (_M_ext_buf_end - _M_ext_buf_converted));
   636   else
   637     {
   638 #ifdef __SYMBIAN32__
   639      if(_M_ext_buf == NULL)
   640     _M_allocate_buffers(0, MMAP_CHUNK);
   641 #endif
   642     _M_ext_buf_end = _M_ext_buf;
   643     }
   644   // Now fill the external buffer with characters from the file.  This is
   645   // a loop because occasonally we don't get enough external characters
   646   // to make progress.
   647   while (true) {
   648     ptrdiff_t __n = _M_base._M_read(_M_ext_buf_end, _M_ext_buf_EOS - _M_ext_buf_end);
   649  
   650     // Don't enter error mode for a failed read.  Error mode is sticky,
   651     // and we might succeed if we try again.
   652 #ifdef __SYMBIAN32__    //plum hall bug 577
   653     int nn = (char*)_M_ext_buf_end-(char*)_M_ext_buf; //number of chars unconverted last time
   654     if ( (__n <= 0) && ( nn<=0 ) )
   655 #else
   656 	if (__n <= 0)
   657 #endif    
   658       return traits_type::eof();
   659 
   660     // Convert the external buffer to internal characters.  
   661     _M_ext_buf_end += __n;
   662     const char*   __enext;
   663     _CharT* __inext;
   664 
   665     typename _Codecvt::result __status
   666       = _M_codecvt->in(_M_end_state,
   667                        _M_ext_buf, _M_ext_buf_end, __enext,
   668                        _M_int_buf, _M_int_buf_EOS, __inext);
   669 
   670     // Error conditions: (1) Return value of error.  (2) Producing internal
   671     // characters without consuming external characters.  (3) In fixed-width
   672     // encodings, producing an internal sequence whose length is inconsistent
   673     // with that of the internal sequence.  (4) Failure to produce any 
   674     // characters if we have enough characters in the external buffer, where
   675     // "enough" means the largest possible width of a single character.
   676     if (__status == _Codecvt::noconv)
   677       return _Noconv_input<_Traits>::_M_doit(this);
   678 
   679     else if (__status == _Codecvt::error ||
   680              (__inext != _M_int_buf && __enext == _M_ext_buf) ||
   681              (_M_constant_width &&
   682               //         __inext - _M_int_buf != _M_width * (__enext - _M_ext_buf)) ||
   683               (__inext - _M_int_buf) *  _M_width != (__enext - _M_ext_buf)) ||
   684              (__inext == _M_int_buf && __enext - _M_ext_buf >= _M_max_width))
   685       return _M_input_error();
   686     
   687     else if (__inext != _M_int_buf) {
   688       _M_ext_buf_converted = _M_ext_buf + (__enext - _M_ext_buf);
   689       this->setg(_M_int_buf, _M_int_buf, __inext);
   690       return traits_type::to_int_type(*_M_int_buf);
   691     }
   692     // We need to go around the loop again to get more external characters.
   693   } 
   694 }
   695 
   696 //----------------------------------------
   697 // Helper functions for output
   698 
   699 // This member function is called if there is an error during output.
   700 // It puts the filebuf in error mode, clear the put area buffer, and
   701 // returns eof.  Error mode is sticky; it is cleared only by close or
   702 // seek.
   703 template <class _CharT, class _Traits>
   704 __BF_int_type__
   705 basic_filebuf<_CharT, _Traits>::_M_output_error()
   706 {
   707   _M_in_output_mode = false;
   708   _M_in_input_mode = false;
   709   _M_in_error_mode = true;
   710   this->setp(0, 0);
   711   return traits_type::eof();
   712 }
   713 
   714 
   715 // Write whatever sequence of characters is necessary to get back to
   716 // the initial shift state.  This function overwrites the external
   717 // buffer, changes the external file position, and changes the state.
   718 // Precondition: the internal buffer is empty.
   719 template <class _CharT, class _Traits>
   720 bool basic_filebuf<_CharT, _Traits>::_M_unshift()
   721 {
   722   if (_M_in_output_mode && !_M_constant_width) {
   723     typename _Codecvt::result __status;
   724     do {
   725       char* __enext = _M_ext_buf;
   726       __status = _M_codecvt->unshift(_M_state,
   727                                      _M_ext_buf, _M_ext_buf_EOS, __enext);
   728       if (__status == _Codecvt::noconv ||
   729           (__enext == _M_ext_buf && __status == _Codecvt::ok))
   730         return true;
   731       else if (__status == _Codecvt::error)
   732         return false;
   733       else if (!_M_write(_M_ext_buf, __enext - _M_ext_buf))
   734         return false;
   735     } while(__status == _Codecvt::partial);
   736   }
   737 
   738   return true;
   739 }
   740 
   741 
   742 //----------------------------------------
   743 // Helper functions for buffer allocation and deallocation
   744 
   745 // This member function is called when we're initializing a filebuf's
   746 // internal and external buffers.  The argument is the size of the
   747 // internal buffer; the external buffer is sized using the character
   748 // width in the current encoding.  Preconditions: the buffers are currently
   749 // null.  __n >= 1.  __buf is either a null pointer or a pointer to an 
   750 // array show size is at least __n.
   751 
   752 // We need __n >= 1 for two different reasons.  For input, the base
   753 // class always needs a buffer because of the sementics of underflow().
   754 // For output, we want to have an internal buffer that's larger by one
   755 // element than the buffer that the base class knows about.  (See 
   756 // basic_filebuf<>::overflow() for the reason.)
   757 template <class _CharT, class _Traits>
   758 bool 
   759 basic_filebuf<_CharT, _Traits>::_M_allocate_buffers(_CharT* __buf, streamsize __n)
   760 {
   761 
   762   if (__buf == 0) {
   763     _M_int_buf = __STATIC_CAST(_CharT*,malloc(__n * sizeof(_CharT)));
   764     if (! _M_int_buf)
   765       return false;
   766     _M_int_buf_dynamic = true;
   767   }
   768   else {
   769     _M_int_buf = __buf;
   770     _M_int_buf_dynamic = false;
   771   }
   772   
   773   size_t __ebufsiz = (max)(__n * (max)(_M_codecvt->encoding(), 1),
   774                       streamsize(_M_codecvt->max_length()));
   775 
   776   _M_ext_buf = __STATIC_CAST(char*,malloc(__ebufsiz));
   777   if (!_M_ext_buf) {
   778     _M_deallocate_buffers();
   779     return false;
   780   }
   781 
   782   _M_int_buf_EOS = _M_int_buf + __n;
   783   _M_ext_buf_EOS = _M_ext_buf + __ebufsiz;
   784   return true;
   785 }
   786 
   787 // Abbreviation for the most common case.
   788 template <class _CharT, class _Traits>
   789 bool basic_filebuf<_CharT, _Traits>::_M_allocate_buffers()
   790 {
   791   // Choose a buffer that's at least 4096 characters long and that's a
   792   // multiple of the page size.
   793   streamsize __default_bufsiz =
   794     ((_M_base.__page_size() + 4095UL) / _M_base.__page_size()) * _M_base.__page_size();
   795   return _M_allocate_buffers(0, __default_bufsiz);
   796 }
   797 
   798 template <class _CharT, class _Traits>
   799 void basic_filebuf<_CharT, _Traits>::_M_deallocate_buffers()
   800 {
   801   if (_M_int_buf_dynamic)
   802     free(_M_int_buf);
   803   free(_M_ext_buf);
   804   _M_int_buf     = 0;
   805   _M_int_buf_EOS = 0;
   806   _M_ext_buf     = 0;
   807   _M_ext_buf_EOS = 0;
   808 }
   809 
   810 
   811 //----------------------------------------
   812 // Helper functiosn for seek and imbue
   813 
   814 template <class _CharT, class _Traits>
   815 bool basic_filebuf<_CharT, _Traits>::_M_seek_init(bool __do_unshift) {
   816   // If we're in error mode, leave it.
   817    _M_in_error_mode = false;
   818    
   819   // Flush the output buffer if we're in output mode, and (conditionally)
   820   // emit an unshift sequence.
   821   if (_M_in_output_mode) {
   822     bool __ok = !traits_type::eq_int_type(this->overflow(traits_type::eof()),
   823                                           traits_type::eof());
   824     if (__do_unshift)
   825       __ok = __ok && this->_M_unshift();
   826     if (!__ok) {
   827       _M_in_output_mode = false;
   828       _M_in_error_mode = true;
   829       this->setp(0, 0);
   830       return false;
   831     }
   832   }
   833 
   834   // Discard putback characters, if any.
   835   if (_M_in_input_mode && _M_in_putback_mode)
   836     _M_exit_putback_mode();
   837 
   838   return true;
   839 }
   840 
   841 
   842 // Change the filebuf's locale.  This member function has no effect
   843 // unless it is called before any I/O is performed on the stream.
   844 template <class _CharT, class _Traits>
   845 void basic_filebuf<_CharT, _Traits>::_M_setup_codecvt(const locale& __loc)
   846 {
   847   _M_codecvt = &use_facet<_Codecvt>(__loc) ;
   848   int __encoding    = _M_codecvt->encoding();
   849 
   850   _M_width          = (max)(__encoding, 1);
   851   _M_max_width      = _M_codecvt->max_length();
   852   _M_constant_width = __encoding > 0;
   853   _M_always_noconv  = _M_codecvt->always_noconv();
   854 }
   855 
   856 
   857 
   858 template <class _CharT, class _Traits>
   859   _STLP_EXP_DECLSPEC basic_fstream<_CharT, _Traits>::basic_fstream()
   860     : basic_ios<_CharT, _Traits>(), basic_iostream<_CharT, _Traits>(0), _M_buf() {
   861       this->init(&_M_buf);
   862   }
   863 
   864 
   865 template <class _CharT, class _Traits>
   866   _STLP_EXP_DECLSPEC basic_fstream<_CharT, _Traits>::~basic_fstream(){}
   867   
   868 #ifdef __SYMBIAN32__
   869 template <class _CharT, class _Traits>
   870 int basic_filebuf<_CharT, _Traits>::save_read_buffer ()
   871     {
   872     return _M_in_putback_mode ? _M_saved_egptr - _M_saved_gptr : 0;
   873     }
   874 template <class _CharT, class _Traits>
   875 void basic_filebuf<_CharT, _Traits>::_change_input_mode ()
   876     {
   877     _M_in_input_mode = 1;
   878     }
   879 
   880 #endif
   881 
   882 _STLP_END_NAMESPACE
   883 
   884 # undef __BF_int_type__
   885 # undef __BF_pos_type__
   886 # undef __BF_off_type__
   887 
   888 # endif /* defined (_STLP_EXPOSE_STREAM_IMPLEMENTATION) */
   889 
   890 #endif /* _STLP_FSTREAM_C */
   891