PR libstdc++/3584
[official-gcc.git] / libstdc++-v3 / src / fstream.cc
blobbe711339b72f7d69e27cbda99900cc90a91f13db
1 // File based streams -*- C++ -*-
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.
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.
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.
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.
32 // ISO C++ 14882: 27.8 File-based streams
35 #include <fstream>
37 namespace std
39 template<>
40 basic_filebuf<char>::int_type
41 basic_filebuf<char>::_M_underflow_common(bool __bump)
43 int_type __ret = traits_type::eof();
44 bool __testin = _M_mode & ios_base::in;
45 bool __testout = _M_mode & ios_base::out;
47 if (__testin)
49 // Check for pback madness, and if so swich back to the
50 // normal buffers and jet outta here before expensive
51 // fileops happen...
52 if (_M_pback_init)
54 _M_pback_destroy();
55 if (_M_in_cur < _M_in_end)
56 return traits_type::to_int_type(*_M_in_cur);
59 // Sync internal and external buffers.
60 // NB: __testget -> __testput as _M_buf_unified here.
61 bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
62 bool __testinit = _M_is_indeterminate();
63 if (__testget)
65 if (__testout)
66 _M_really_overflow();
67 else if (_M_in_cur != _M_filepos)
68 _M_file.seekoff(_M_in_cur - _M_filepos,
69 ios_base::cur, ios_base::in);
72 if (__testinit || __testget)
74 streamsize __elen = 0;
75 streamsize __ilen = 0;
76 __elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),
77 _M_buf_size);
78 __ilen = __elen;
80 if (0 < __ilen)
82 _M_set_determinate(__ilen);
83 if (__testout)
84 _M_out_cur = _M_in_cur;
85 __ret = traits_type::to_int_type(*_M_in_cur);
86 if (__bump)
87 _M_in_cur_move(1);
88 else if (_M_buf_size == 1)
90 // If we are synced with stdio, we have to unget the
91 // character we just read so that the file pointer
92 // doesn't move.
93 _M_file.sys_ungetc(traits_type::to_int_type(*_M_in_cur));
94 _M_set_indeterminate();
99 _M_last_overflowed = false;
100 return __ret;
103 #ifdef _GLIBCPP_USE_WCHAR_T
104 template<>
105 basic_filebuf<wchar_t>::int_type
106 basic_filebuf<wchar_t>::_M_underflow_common(bool __bump)
108 int_type __ret = traits_type::eof();
109 bool __testin = _M_mode & ios_base::in;
110 bool __testout = _M_mode & ios_base::out;
112 if (__testin)
114 // Check for pback madness, and if so swich back to the
115 // normal buffers and jet outta here before expensive
116 // fileops happen...
117 if (_M_pback_init)
119 _M_pback_destroy();
120 if (_M_in_cur < _M_in_end)
121 return traits_type::to_int_type(*_M_in_cur);
124 // Sync internal and external buffers.
125 // NB: __testget -> __testput as _M_buf_unified here.
126 bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
127 bool __testinit = _M_is_indeterminate();
128 if (__testget)
130 if (__testout)
131 _M_really_overflow();
132 else if (_M_in_cur != _M_filepos)
133 _M_file.seekoff(_M_in_cur - _M_filepos,
134 ios_base::cur, ios_base::in);
137 if (__testinit || __testget)
139 const locale __loc = this->getloc();
140 const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
142 streamsize __elen = 0;
143 streamsize __ilen = 0;
144 if (__cvt.always_noconv())
146 __elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),
147 _M_buf_size);
148 __ilen = __elen;
150 else
152 char* __buf = static_cast<char*>(__builtin_alloca(_M_buf_size));
153 __elen = _M_file.xsgetn(__buf, _M_buf_size);
155 const char* __eend;
156 char_type* __iend;
157 __res_type __r = __cvt.in(_M_state_cur, __buf,
158 __buf + __elen, __eend, _M_in_beg,
159 _M_in_beg + _M_buf_size, __iend);
160 if (__r == codecvt_base::ok)
161 __ilen = __iend - _M_in_beg;
162 else
164 // Unwind.
165 __ilen = 0;
166 _M_file.seekoff(-__elen, ios_base::cur, ios_base::in);
170 if (0 < __ilen)
172 _M_set_determinate(__ilen);
173 if (__testout)
174 _M_out_cur = _M_in_cur;
175 __ret = traits_type::to_int_type(*_M_in_cur);
176 if (__bump)
177 _M_in_cur_move(1);
178 else if (_M_buf_size == 1)
180 // If we are synced with stdio, we have to unget the
181 // character we just read so that the file pointer
182 // doesn't move.
183 _M_file.sys_ungetc(traits_type::to_int_type(*_M_in_cur));
184 _M_set_indeterminate();
189 _M_last_overflowed = false;
190 return __ret;
192 #endif
193 } // namespace std