home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 14 / hacker14.iso / programacao / cwin / c.exe / $INSTDIR / include / c++ / bits / fstream.tcc < prev    next >
Encoding:
Text File  |  2003-12-15  |  14.0 KB  |  490 lines

  1. // File based streams -*- C++ -*-
  2.  
  3. // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
  4. // Free Software Foundation, Inc.
  5. //
  6. // This file is part of the GNU ISO C++ Library.  This library is free
  7. // software; you can redistribute it and/or modify it under the
  8. // terms of the GNU General Public License as published by the
  9. // Free Software Foundation; either version 2, or (at your option)
  10. // any later version.
  11.  
  12. // This library is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. // GNU General Public License for more details.
  16.  
  17. // You should have received a copy of the GNU General Public License along
  18. // with this library; see the file COPYING.  If not, write to the Free
  19. // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  20. // USA.
  21.  
  22. // As a special exception, you may use this file as part of a free software
  23. // library without restriction.  Specifically, if other files instantiate
  24. // templates or use macros or inline functions from this file, or you compile
  25. // this file and link it with other files to produce an executable, this
  26. // file does not by itself cause the resulting executable to be covered by
  27. // the GNU General Public License.  This exception does not however
  28. // invalidate any other reasons why the executable file might be covered by
  29. // the GNU General Public License.
  30.  
  31. //
  32. // ISO C++ 14882: 27.8  File-based streams
  33. //
  34.  
  35. #ifndef _CPP_BITS_FSTREAM_TCC
  36. #define _CPP_BITS_FSTREAM_TCC 1
  37.  
  38. #pragma GCC system_header
  39.  
  40. namespace std
  41. {
  42.   template<typename _CharT, typename _Traits>
  43.     void
  44.     basic_filebuf<_CharT, _Traits>::
  45.     _M_allocate_internal_buffer()
  46.     {
  47.       if (!_M_buf && _M_buf_size_opt)
  48.     {
  49.       _M_buf_size = _M_buf_size_opt;
  50.  
  51.       // Allocate internal buffer.
  52.       _M_buf = new char_type[_M_buf_size]; 
  53.       _M_buf_allocated = true;
  54.     }
  55.     }
  56.  
  57.   // Both close and setbuf need to deallocate internal buffers, if it exists.
  58.   template<typename _CharT, typename _Traits>
  59.     void
  60.     basic_filebuf<_CharT, _Traits>::
  61.     _M_destroy_internal_buffer()
  62.     {
  63.       if (_M_buf_allocated)
  64.     {
  65.       delete [] _M_buf;
  66.       _M_buf = NULL;
  67.       _M_buf_allocated = false;
  68.       this->setg(NULL, NULL, NULL);
  69.       this->setp(NULL, NULL);
  70.     }
  71.     }
  72.  
  73.   template<typename _CharT, typename _Traits>
  74.     basic_filebuf<_CharT, _Traits>::
  75.     basic_filebuf() : __streambuf_type(), _M_file(&_M_lock), 
  76.     _M_state_cur(__state_type()), _M_state_beg(__state_type()), 
  77.     _M_buf_allocated(false), _M_last_overflowed(false)
  78.     { _M_buf_unified = true; }
  79.  
  80.   template<typename _CharT, typename _Traits>
  81.     typename basic_filebuf<_CharT, _Traits>::__filebuf_type* 
  82.     basic_filebuf<_CharT, _Traits>::
  83.     open(const char* __s, ios_base::openmode __mode)
  84.     {
  85.       __filebuf_type *__ret = NULL;
  86.       if (!this->is_open())
  87.     {
  88.       _M_file.open(__s, __mode);
  89.       if (this->is_open())
  90.         {
  91.           _M_allocate_internal_buffer();
  92.           _M_mode = __mode;
  93.           _M_set_indeterminate();
  94.  
  95.           if ((__mode & ios_base::ate)
  96.           && this->seekoff(0, ios_base::end, __mode) < 0)
  97.         this->close();
  98.           __ret = this;
  99.         }
  100.     }
  101.       return __ret;
  102.     }
  103.  
  104.   template<typename _CharT, typename _Traits>
  105.     typename basic_filebuf<_CharT, _Traits>::__filebuf_type* 
  106.     basic_filebuf<_CharT, _Traits>::
  107.     close()
  108.     {
  109.       __filebuf_type *__ret = NULL;
  110.       if (this->is_open())
  111.     {
  112.       const int_type __eof = traits_type::eof();
  113.       bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
  114.       if (__testput 
  115.           && traits_type::eq_int_type(_M_really_overflow(__eof), __eof))
  116.         return __ret;
  117.  
  118.       // NB: Do this here so that re-opened filebufs will be cool...
  119.       _M_mode = ios_base::openmode(0);
  120.       _M_destroy_internal_buffer();
  121.       _M_pback_destroy();
  122.       
  123. #if 0
  124.       // XXX not done
  125.       if (_M_last_overflowed)
  126.         {
  127.           _M_output_unshift();
  128.           _M_really_overflow(__eof);
  129.         }
  130. #endif
  131.  
  132.       if (_M_file.close())
  133.         __ret = this;
  134.     }
  135.  
  136.       _M_last_overflowed = false;    
  137.       return __ret;
  138.     }
  139.  
  140.   template<typename _CharT, typename _Traits>
  141.     streamsize 
  142.     basic_filebuf<_CharT, _Traits>::
  143.     showmanyc()
  144.     {
  145.       streamsize __ret = -1;
  146.       bool __testin = _M_mode & ios_base::in;
  147.  
  148.       if (__testin && this->is_open())
  149.     __ret = _M_in_end - _M_in_cur;
  150.       _M_last_overflowed = false;    
  151.       return __ret;
  152.     }
  153.   
  154.   template<typename _CharT, typename _Traits>
  155.     typename basic_filebuf<_CharT, _Traits>::int_type 
  156.     basic_filebuf<_CharT, _Traits>::
  157.     pbackfail(int_type __i)
  158.     {
  159.       int_type __ret = traits_type::eof();
  160.       bool __testin = _M_mode & ios_base::in;
  161.  
  162.       if (__testin)
  163.     {
  164.       bool __testpb = _M_in_beg < _M_in_cur;
  165.       char_type __c = traits_type::to_char_type(__i);
  166.       bool __testeof = traits_type::eq_int_type(__i, __ret);
  167.  
  168.       if (__testpb)
  169.         {
  170.           bool __testout = _M_mode & ios_base::out;
  171.           bool __testeq = traits_type::eq(__c, this->gptr()[-1]);
  172.  
  173.           // Try to put back __c into input sequence in one of three ways.
  174.           // Order these tests done in is unspecified by the standard.
  175.           if (!__testeof && __testeq)
  176.         {
  177.           --_M_in_cur;
  178.           if (__testout)
  179.             --_M_out_cur;
  180.           __ret = __i;
  181.         }
  182.           else if (__testeof)
  183.         {
  184.           --_M_in_cur;
  185.           if (__testout)
  186.             --_M_out_cur;
  187.           __ret = traits_type::not_eof(__i);
  188.         }
  189.           else if (!__testeof)
  190.         {
  191.           --_M_in_cur;
  192.           if (__testout)
  193.             --_M_out_cur;
  194.           _M_pback_create();
  195.           *_M_in_cur = __c; 
  196.           __ret = __i;
  197.         }
  198.         }
  199.       else
  200.         {     
  201.            // At the beginning of the buffer, need to make a
  202.           // putback position available.
  203.           this->seekoff(-1, ios_base::cur);
  204.           this->underflow();
  205.            if (!__testeof)
  206.          {
  207.           if (!traits_type::eq(__c, *_M_in_cur))
  208.             {
  209.               _M_pback_create();
  210.               *_M_in_cur = __c;
  211.             }
  212.            __ret = __i;
  213.          }
  214.            else
  215.          __ret = traits_type::not_eof(__i);
  216.          }
  217.     }
  218.       _M_last_overflowed = false;    
  219.       return __ret;
  220.     }
  221.  
  222.   template<typename _CharT, typename _Traits>
  223.     typename basic_filebuf<_CharT, _Traits>::int_type 
  224.     basic_filebuf<_CharT, _Traits>::
  225.     overflow(int_type __c)
  226.     {
  227.       int_type __ret = traits_type::eof();
  228.       bool __testput = _M_out_cur && _M_out_cur < _M_buf + _M_buf_size;
  229.       bool __testout = _M_mode & ios_base::out;
  230.       
  231.       if (__testout)
  232.     {
  233.       if (__testput)
  234.         {
  235.           *_M_out_cur = traits_type::to_char_type(__c);
  236.           _M_out_cur_move(1);
  237.           __ret = traits_type::not_eof(__c);
  238.         }
  239.       else 
  240.         __ret = this->_M_really_overflow(__c);
  241.     }
  242.  
  243.       _M_last_overflowed = false;    // Set in _M_really_overflow, below.
  244.       return __ret;
  245.     }
  246.   
  247.   template<typename _CharT, typename _Traits>
  248.     void
  249.     basic_filebuf<_CharT, _Traits>::
  250.     _M_convert_to_external(_CharT* __ibuf, streamsize __ilen,
  251.                streamsize& __elen, streamsize& __plen)
  252.     {
  253.       const locale __loc = this->getloc();
  254.       const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
  255.       
  256.       if (__cvt.always_noconv() && __ilen)
  257.     {
  258.       __elen += _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen);
  259.       __plen += __ilen;
  260.     }
  261.       else
  262.     {
  263.       // Worst-case number of external bytes needed.
  264.       int __ext_multiplier = __cvt.encoding();
  265.       if (__ext_multiplier ==  -1 || __ext_multiplier == 0)
  266.         __ext_multiplier = sizeof(char_type);
  267.       streamsize __blen = __ilen * __ext_multiplier;
  268.       char* __buf = static_cast<char*>(__builtin_alloca(__blen));
  269.       char* __bend;
  270.       const char_type* __iend;
  271.       __res_type __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen, 
  272.                       __iend, __buf, __buf + __blen, __bend);
  273.       // Result == ok, partial, noconv
  274.       if (__r != codecvt_base::error)
  275.         __blen = __bend - __buf;
  276.       // Result == error
  277.       else 
  278.         __blen = 0;
  279.       
  280.       if (__blen)
  281.         {
  282.           __elen += _M_file.xsputn(__buf, __blen);
  283.           __plen += __blen;
  284.         }
  285.  
  286.       // Try once more for partial conversions.
  287.       if (__r == codecvt_base::partial)
  288.         {
  289.           const char_type* __iresume = __iend;
  290.           streamsize __rlen = _M_out_end - __iend;
  291.           __r = __cvt.out(_M_state_cur, __iresume, __iresume + __rlen, 
  292.                   __iend, __buf, __buf + __blen, __bend);
  293.           if (__r != codecvt_base::error)
  294.         __rlen = __bend - __buf;
  295.           else 
  296.         __rlen = 0;
  297.           if (__rlen)
  298.         {
  299.           __elen += _M_file.xsputn(__buf, __rlen);
  300.           __plen += __rlen;
  301.         }
  302.         }
  303.     }
  304.     }
  305.  
  306.   template<typename _CharT, typename _Traits>
  307.     typename basic_filebuf<_CharT, _Traits>::int_type 
  308.     basic_filebuf<_CharT, _Traits>::
  309.     _M_really_overflow(int_type __c)
  310.     {
  311.       int_type __ret = traits_type::eof();
  312.       bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
  313.       bool __testunbuffered = _M_file.is_open() && !_M_buf_size_opt;
  314.  
  315.       if (__testput || __testunbuffered)
  316.     {
  317.       // Sizes of external and pending output.
  318.       streamsize __elen = 0;
  319.       streamsize __plen = 0;
  320.  
  321.       // Need to restore current position. The position of the external
  322.       // byte sequence (_M_file) corresponds to _M_filepos, and we need
  323.       // to move it to _M_out_beg for the write.
  324.       if (_M_filepos && _M_filepos != _M_out_beg)
  325.         {
  326.           off_type __off = _M_out_beg - _M_filepos;
  327.           _M_file.seekoff(__off, ios_base::cur);
  328.         }
  329.  
  330.       // Convert internal buffer to external representation, output.
  331.       // NB: In the unbuffered case, no internal buffer exists. 
  332.       if (!__testunbuffered)
  333.         _M_convert_to_external(_M_out_beg,  _M_out_end - _M_out_beg, 
  334.                    __elen, __plen);
  335.  
  336.       // Convert pending sequence to external representation, output.
  337.       // If eof, then just attempt sync.
  338.       if (!traits_type::eq_int_type(__c, traits_type::eof()))
  339.         {
  340.           char_type __pending = traits_type::to_char_type(__c);
  341.           _M_convert_to_external(&__pending, 1, __elen, __plen);
  342.  
  343.           // User code must flush when switching modes (thus don't sync).
  344.           if (__elen == __plen)
  345.         {
  346.           _M_set_indeterminate();
  347.           __ret = traits_type::not_eof(__c);
  348.         }
  349.         }
  350.       else if (!_M_file.sync())
  351.         {
  352.           _M_set_indeterminate();
  353.           __ret = traits_type::not_eof(__c);
  354.         }
  355.     }          
  356.       _M_last_overflowed = true;    
  357.       return __ret;
  358.     }
  359.  
  360.   template<typename _CharT, typename _Traits>
  361.     typename basic_filebuf<_CharT, _Traits>::__streambuf_type* 
  362.     basic_filebuf<_CharT, _Traits>::
  363.     setbuf(char_type* __s, streamsize __n)
  364.     {
  365.       if (!this->is_open() && __s == 0 && __n == 0)
  366.     _M_buf_size_opt = 0;
  367.       else if (__s && __n)
  368.     {
  369.       // This is implementation-defined behavior, and assumes
  370.       // that an external char_type array of length (__s + __n)
  371.       // exists and has been pre-allocated. If this is not the
  372.       // case, things will quickly blow up.
  373.       // Step 1: Destroy the current internal array.
  374.       _M_destroy_internal_buffer();
  375.       
  376.       // Step 2: Use the external array.
  377.       _M_buf = __s;
  378.       _M_buf_size_opt = _M_buf_size = __n;
  379.       _M_set_indeterminate();
  380.     }
  381.       _M_last_overflowed = false;    
  382.       return this; 
  383.     }
  384.   
  385.   template<typename _CharT, typename _Traits>
  386.     typename basic_filebuf<_CharT, _Traits>::pos_type
  387.     basic_filebuf<_CharT, _Traits>::
  388.     seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
  389.     {
  390.       pos_type __ret =  pos_type(off_type(-1)); 
  391.       bool __testin = (ios_base::in & _M_mode & __mode) != 0;
  392.       bool __testout = (ios_base::out & _M_mode & __mode) != 0;
  393.  
  394.       // Should probably do has_facet checks here.
  395.       int __width = use_facet<__codecvt_type>(_M_buf_locale).encoding();
  396.       if (__width < 0)
  397.     __width = 0;
  398.       bool __testfail = __off != 0 && __width <= 0;
  399.       
  400.       if (this->is_open() && !__testfail && (__testin || __testout)) 
  401.     {
  402.       // Ditch any pback buffers to avoid confusion.
  403.       _M_pback_destroy();
  404.  
  405.       if (__way != ios_base::cur || __off != 0)
  406.         { 
  407.           off_type __computed_off = __width * __off;
  408.           
  409.           bool __testget = _M_in_cur && _M_in_beg < _M_in_end;
  410.           bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
  411.           // Sync the internal and external streams.
  412.           // out
  413.           if (__testput || _M_last_overflowed)
  414.         {
  415.           // Part one: update the output sequence.
  416.           this->sync();
  417.           // Part two: output unshift sequence.
  418.           _M_output_unshift();
  419.         }
  420.           //in
  421.           else if (__testget && __way == ios_base::cur)
  422.         __computed_off += _M_in_cur - _M_filepos;
  423.       
  424.           __ret = _M_file.seekoff(__computed_off, __way, __mode);
  425.           _M_set_indeterminate();
  426.         }
  427.       // NB: Need to do this in case _M_file in indeterminate
  428.       // state, ie _M_file._offset == -1
  429.       else
  430.         {
  431.           __ret = _M_file.seekoff(__off, ios_base::cur, __mode);
  432.           __ret += max(_M_out_cur, _M_in_cur) - _M_filepos;
  433.         }
  434.     }
  435.       _M_last_overflowed = false;    
  436.       return __ret;
  437.     }
  438.  
  439.   template<typename _CharT, typename _Traits>
  440.     typename basic_filebuf<_CharT, _Traits>::pos_type
  441.     basic_filebuf<_CharT, _Traits>::
  442.     seekpos(pos_type __pos, ios_base::openmode __mode)
  443.     {
  444. #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
  445. // 171. Strange seekpos() semantics due to joint position
  446.       return this->seekoff(off_type(__pos), ios_base::beg, __mode);
  447. #endif
  448.     }
  449.  
  450.   template<typename _CharT, typename _Traits>
  451.     void 
  452.     basic_filebuf<_CharT, _Traits>::
  453.     _M_output_unshift()
  454.     { }
  455.  
  456.   template<typename _CharT, typename _Traits>
  457.     void
  458.     basic_filebuf<_CharT, _Traits>::
  459.     imbue(const locale& __loc)
  460.     {
  461.       bool __testbeg = gptr() == eback() && pptr() == pbase();
  462.  
  463.       if (__testbeg && _M_buf_locale != __loc)
  464.     {
  465.       _M_buf_locale = __loc;
  466.       _M_buf_locale_init = true;
  467.     }
  468.  
  469.       // NB this may require the reconversion of previously
  470.       // converted chars. This in turn may cause the reconstruction
  471.       // of the original file. YIKES!!
  472.       // XXX The part in the above comment is not done.
  473.       _M_last_overflowed = false;    
  474.     }
  475.  
  476.   // Inhibit implicit instantiations for required instantiations,
  477.   // which are defined via explicit instantiations elsewhere.  
  478.   // NB:  This syntax is a GNU extension.
  479.   extern template class basic_filebuf<char>;
  480.   extern template class basic_filebuf<wchar_t>;
  481.   extern template class basic_ifstream<char>;
  482.   extern template class basic_ifstream<wchar_t>;
  483.   extern template class basic_ofstream<char>;
  484.   extern template class basic_ofstream<wchar_t>;
  485.   extern template class basic_fstream<char>;
  486.   extern template class basic_fstream<wchar_t>;
  487. } // namespace std
  488.  
  489. #endif 
  490.