xref: /openbsd-src/gnu/lib/libstdc++/libstdc++/src/fstream.cc (revision c2fb321235c8dbfba0909bc43913400e90646ae7)
103a78d15Sespie // File based streams -*- C++ -*-
203a78d15Sespie 
303a78d15Sespie // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
403a78d15Sespie // Free Software Foundation, Inc.
503a78d15Sespie //
603a78d15Sespie // This file is part of the GNU ISO C++ Library.  This library is free
703a78d15Sespie // software; you can redistribute it and/or modify it under the
803a78d15Sespie // terms of the GNU General Public License as published by the
903a78d15Sespie // Free Software Foundation; either version 2, or (at your option)
1003a78d15Sespie // any later version.
1103a78d15Sespie 
1203a78d15Sespie // This library is distributed in the hope that it will be useful,
1303a78d15Sespie // but WITHOUT ANY WARRANTY; without even the implied warranty of
1403a78d15Sespie // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1503a78d15Sespie // GNU General Public License for more details.
1603a78d15Sespie 
1703a78d15Sespie // You should have received a copy of the GNU General Public License along
1803a78d15Sespie // with this library; see the file COPYING.  If not, write to the Free
1903a78d15Sespie // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2003a78d15Sespie // USA.
2103a78d15Sespie 
2203a78d15Sespie // As a special exception, you may use this file as part of a free software
2303a78d15Sespie // library without restriction.  Specifically, if other files instantiate
2403a78d15Sespie // templates or use macros or inline functions from this file, or you compile
2503a78d15Sespie // this file and link it with other files to produce an executable, this
2603a78d15Sespie // file does not by itself cause the resulting executable to be covered by
2703a78d15Sespie // the GNU General Public License.  This exception does not however
2803a78d15Sespie // invalidate any other reasons why the executable file might be covered by
2903a78d15Sespie // the GNU General Public License.
3003a78d15Sespie 
3103a78d15Sespie //
3203a78d15Sespie // ISO C++ 14882: 27.8  File-based streams
3303a78d15Sespie //
3403a78d15Sespie 
3503a78d15Sespie #include <fstream>
3603a78d15Sespie 
3703a78d15Sespie namespace std
3803a78d15Sespie {
3903a78d15Sespie   template<>
4003a78d15Sespie     basic_filebuf<char>::int_type
_M_underflow_common(bool __bump)4103a78d15Sespie     basic_filebuf<char>::_M_underflow_common(bool __bump)
4203a78d15Sespie     {
4303a78d15Sespie       int_type __ret = traits_type::eof();
4403a78d15Sespie       bool __testin = _M_mode & ios_base::in;
4503a78d15Sespie       bool __testout = _M_mode & ios_base::out;
4603a78d15Sespie 
4703a78d15Sespie       if (__testin)
4803a78d15Sespie 	{
4903a78d15Sespie 	  // Check for pback madness, and if so swich back to the
5003a78d15Sespie 	  // normal buffers and jet outta here before expensive
5103a78d15Sespie 	  // fileops happen...
5203a78d15Sespie 	  if (_M_pback_init)
5303a78d15Sespie 	    _M_pback_destroy();
5403a78d15Sespie 
5503a78d15Sespie 	  if (_M_in_cur && _M_in_cur < _M_in_end)
5603a78d15Sespie 	    {
5703a78d15Sespie 	      __ret = traits_type::to_int_type(*_M_in_cur);
5803a78d15Sespie 	      if (__bump)
5903a78d15Sespie 		_M_in_cur_move(1);
6003a78d15Sespie 	      return __ret;
6103a78d15Sespie 	    }
6203a78d15Sespie 
6303a78d15Sespie 	  // Sync internal and external buffers.
6403a78d15Sespie 	  // NB: __testget -> __testput as _M_buf_unified here.
6503a78d15Sespie 	  bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
6603a78d15Sespie 	  bool __testinit = _M_is_indeterminate();
6703a78d15Sespie 	  if (__testget)
6803a78d15Sespie 	    {
6903a78d15Sespie 	      if (__testout)
7003a78d15Sespie 		_M_really_overflow();
7103a78d15Sespie 	      else if (_M_in_cur != _M_filepos)
7203a78d15Sespie 		_M_file.seekoff(_M_in_cur - _M_filepos,
7303a78d15Sespie 				ios_base::cur, ios_base::in);
7403a78d15Sespie 	    }
7503a78d15Sespie 
7603a78d15Sespie 	  if (__testinit || __testget)
7703a78d15Sespie 	    {
7803a78d15Sespie 	      streamsize __elen = 0;
7903a78d15Sespie 	      streamsize __ilen = 0;
8003a78d15Sespie 	      __elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),
8103a78d15Sespie 				      _M_buf_size);
8203a78d15Sespie 	      __ilen = __elen;
8303a78d15Sespie 
8403a78d15Sespie 	      if (0 < __ilen)
8503a78d15Sespie 		{
8603a78d15Sespie 		  _M_set_determinate(__ilen);
8703a78d15Sespie 		  if (__testout)
8803a78d15Sespie 		    _M_out_cur = _M_in_cur;
8903a78d15Sespie 		  __ret = traits_type::to_int_type(*_M_in_cur);
9003a78d15Sespie 		  if (__bump)
9103a78d15Sespie 		    _M_in_cur_move(1);
9203a78d15Sespie 		  else if (_M_buf_size == 1)
9303a78d15Sespie 		    {
9403a78d15Sespie 		      // If we are synced with stdio, we have to unget the
9503a78d15Sespie 		      // character we just read so that the file pointer
9603a78d15Sespie 		      // doesn't move.
9703a78d15Sespie 		      _M_file.sys_ungetc(traits_type::to_int_type(*_M_in_cur));
9803a78d15Sespie 		      _M_set_indeterminate();
9903a78d15Sespie 		    }
10003a78d15Sespie 		}
10103a78d15Sespie 	    }
10203a78d15Sespie 	}
10303a78d15Sespie       _M_last_overflowed = false;
10403a78d15Sespie       return __ret;
10503a78d15Sespie     }
10603a78d15Sespie 
107*c2fb3212Sespie #if defined(_GLIBCPP_USE_WCHAR_T) || defined(_GLIBCPP_USE_TYPE_WCHAR_T)
10803a78d15Sespie   template<>
10903a78d15Sespie     basic_filebuf<wchar_t>::int_type
_M_underflow_common(bool __bump)11003a78d15Sespie     basic_filebuf<wchar_t>::_M_underflow_common(bool __bump)
11103a78d15Sespie     {
11203a78d15Sespie       int_type __ret = traits_type::eof();
11303a78d15Sespie       bool __testin = _M_mode & ios_base::in;
11403a78d15Sespie       bool __testout = _M_mode & ios_base::out;
11503a78d15Sespie 
11603a78d15Sespie       if (__testin)
11703a78d15Sespie 	{
11803a78d15Sespie 	  // Check for pback madness, and if so swich back to the
11903a78d15Sespie 	  // normal buffers and jet outta here before expensive
12003a78d15Sespie 	  // fileops happen...
12103a78d15Sespie 	  if (_M_pback_init)
12203a78d15Sespie 	    _M_pback_destroy();
12303a78d15Sespie 
12403a78d15Sespie 	  if (_M_in_cur && _M_in_cur < _M_in_end)
12503a78d15Sespie 	    {
12603a78d15Sespie 	      __ret = traits_type::to_int_type(*_M_in_cur);
12703a78d15Sespie 	      if (__bump)
12803a78d15Sespie 		_M_in_cur_move(1);
12903a78d15Sespie 	      return __ret;
13003a78d15Sespie 	    }
13103a78d15Sespie 
13203a78d15Sespie 	  // Sync internal and external buffers.
13303a78d15Sespie 	  // NB: __testget -> __testput as _M_buf_unified here.
13403a78d15Sespie 	  bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
13503a78d15Sespie 	  bool __testinit = _M_is_indeterminate();
13603a78d15Sespie 	  if (__testget)
13703a78d15Sespie 	    {
13803a78d15Sespie 	      if (__testout)
13903a78d15Sespie 		_M_really_overflow();
14003a78d15Sespie 	      else if (_M_in_cur != _M_filepos)
14103a78d15Sespie 		_M_file.seekoff(_M_in_cur - _M_filepos,
14203a78d15Sespie 				ios_base::cur, ios_base::in);
14303a78d15Sespie 	    }
14403a78d15Sespie 
14503a78d15Sespie 	  if (__testinit || __testget)
14603a78d15Sespie 	    {
14703a78d15Sespie 	      const locale __loc = this->getloc();
14803a78d15Sespie 	      const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
14903a78d15Sespie 
15003a78d15Sespie 	      streamsize __elen = 0;
15103a78d15Sespie 	      streamsize __ilen = 0;
15203a78d15Sespie 	      if (__cvt.always_noconv())
15303a78d15Sespie 		{
15403a78d15Sespie 		  __elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),
15503a78d15Sespie 					  _M_buf_size);
15603a78d15Sespie 		  __ilen = __elen;
15703a78d15Sespie 		}
15803a78d15Sespie 	      else
15903a78d15Sespie 		{
16003a78d15Sespie 		  char* __buf = static_cast<char*>(__builtin_alloca(_M_buf_size));
16103a78d15Sespie 		  __elen = _M_file.xsgetn(__buf, _M_buf_size);
16203a78d15Sespie 
16303a78d15Sespie 		  const char* __eend;
16403a78d15Sespie 		  char_type* __iend;
16503a78d15Sespie 		  codecvt_base::result __r;
16603a78d15Sespie 		  __r = __cvt.in(_M_state_cur, __buf,
16703a78d15Sespie 				 __buf + __elen, __eend, _M_in_beg,
16803a78d15Sespie 				 _M_in_beg + _M_buf_size, __iend);
16903a78d15Sespie 		  if (__r == codecvt_base::ok)
17003a78d15Sespie 		    __ilen = __iend - _M_in_beg;
17103a78d15Sespie 		  else
17203a78d15Sespie 		    {
17303a78d15Sespie 		      // Unwind.
17403a78d15Sespie 		      __ilen = 0;
17503a78d15Sespie 		      _M_file.seekoff(-__elen, ios_base::cur, ios_base::in);
17603a78d15Sespie 		    }
17703a78d15Sespie 		}
17803a78d15Sespie 
17903a78d15Sespie 	      if (0 < __ilen)
18003a78d15Sespie 		{
18103a78d15Sespie 		  _M_set_determinate(__ilen);
18203a78d15Sespie 		  if (__testout)
18303a78d15Sespie 		    _M_out_cur = _M_in_cur;
18403a78d15Sespie 		  __ret = traits_type::to_int_type(*_M_in_cur);
18503a78d15Sespie 		  if (__bump)
18603a78d15Sespie 		    _M_in_cur_move(1);
18703a78d15Sespie 		  else if (_M_buf_size == 1)
18803a78d15Sespie 		    {
18903a78d15Sespie 		      // If we are synced with stdio, we have to unget the
19003a78d15Sespie 		      // character we just read so that the file pointer
19103a78d15Sespie 		      // doesn't move.
19203a78d15Sespie 		      _M_file.sys_ungetc(traits_type::to_int_type(*_M_in_cur));
19303a78d15Sespie 		      _M_set_indeterminate();
19403a78d15Sespie 		    }
19503a78d15Sespie 		}
19603a78d15Sespie 	    }
19703a78d15Sespie 	}
19803a78d15Sespie       _M_last_overflowed = false;
19903a78d15Sespie       return __ret;
20003a78d15Sespie     }
20103a78d15Sespie #endif
20203a78d15Sespie } // namespace std
203