1 | // File based streams -*- C++ -*-
|
---|
2 |
|
---|
3 | // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
|
---|
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 | #include <fstream>
|
---|
36 |
|
---|
37 | namespace std
|
---|
38 | {
|
---|
39 | template<>
|
---|
40 | basic_filebuf<char>::int_type
|
---|
41 | basic_filebuf<char>::_M_underflow_common(bool __bump)
|
---|
42 | {
|
---|
43 | int_type __ret = traits_type::eof();
|
---|
44 | bool __testin = _M_mode & ios_base::in;
|
---|
45 | bool __testout = _M_mode & ios_base::out;
|
---|
46 |
|
---|
47 | if (__testin)
|
---|
48 | {
|
---|
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)
|
---|
53 | _M_pback_destroy();
|
---|
54 |
|
---|
55 | if (_M_in_cur && _M_in_cur < _M_in_end)
|
---|
56 | {
|
---|
57 | __ret = traits_type::to_int_type(*_M_in_cur);
|
---|
58 | if (__bump)
|
---|
59 | _M_in_cur_move(1);
|
---|
60 | return __ret;
|
---|
61 | }
|
---|
62 |
|
---|
63 | // Sync internal and external buffers.
|
---|
64 | // NB: __testget -> __testput as _M_buf_unified here.
|
---|
65 | bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
|
---|
66 | bool __testinit = _M_is_indeterminate();
|
---|
67 | if (__testget)
|
---|
68 | {
|
---|
69 | if (__testout)
|
---|
70 | _M_really_overflow();
|
---|
71 | else if (_M_in_cur != _M_filepos)
|
---|
72 | _M_file.seekoff(_M_in_cur - _M_filepos,
|
---|
73 | ios_base::cur, ios_base::in);
|
---|
74 | }
|
---|
75 |
|
---|
76 | if (__testinit || __testget)
|
---|
77 | {
|
---|
78 | streamsize __elen = 0;
|
---|
79 | streamsize __ilen = 0;
|
---|
80 | __elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),
|
---|
81 | _M_buf_size);
|
---|
82 | __ilen = __elen;
|
---|
83 |
|
---|
84 | if (0 < __ilen)
|
---|
85 | {
|
---|
86 | _M_set_determinate(__ilen);
|
---|
87 | if (__testout)
|
---|
88 | _M_out_cur = _M_in_cur;
|
---|
89 | __ret = traits_type::to_int_type(*_M_in_cur);
|
---|
90 | if (__bump)
|
---|
91 | _M_in_cur_move(1);
|
---|
92 | else if (_M_buf_size == 1)
|
---|
93 | {
|
---|
94 | // If we are synced with stdio, we have to unget the
|
---|
95 | // character we just read so that the file pointer
|
---|
96 | // doesn't move.
|
---|
97 | _M_file.sys_ungetc(traits_type::to_int_type(*_M_in_cur));
|
---|
98 | _M_set_indeterminate();
|
---|
99 | }
|
---|
100 | }
|
---|
101 | }
|
---|
102 | }
|
---|
103 | _M_last_overflowed = false;
|
---|
104 | return __ret;
|
---|
105 | }
|
---|
106 |
|
---|
107 | #ifdef _GLIBCPP_USE_WCHAR_T
|
---|
108 | template<>
|
---|
109 | basic_filebuf<wchar_t>::int_type
|
---|
110 | basic_filebuf<wchar_t>::_M_underflow_common(bool __bump)
|
---|
111 | {
|
---|
112 | int_type __ret = traits_type::eof();
|
---|
113 | bool __testin = _M_mode & ios_base::in;
|
---|
114 | bool __testout = _M_mode & ios_base::out;
|
---|
115 |
|
---|
116 | if (__testin)
|
---|
117 | {
|
---|
118 | // Check for pback madness, and if so swich back to the
|
---|
119 | // normal buffers and jet outta here before expensive
|
---|
120 | // fileops happen...
|
---|
121 | if (_M_pback_init)
|
---|
122 | _M_pback_destroy();
|
---|
123 |
|
---|
124 | if (_M_in_cur && _M_in_cur < _M_in_end)
|
---|
125 | {
|
---|
126 | __ret = traits_type::to_int_type(*_M_in_cur);
|
---|
127 | if (__bump)
|
---|
128 | _M_in_cur_move(1);
|
---|
129 | return __ret;
|
---|
130 | }
|
---|
131 |
|
---|
132 | // Sync internal and external buffers.
|
---|
133 | // NB: __testget -> __testput as _M_buf_unified here.
|
---|
134 | bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
|
---|
135 | bool __testinit = _M_is_indeterminate();
|
---|
136 | if (__testget)
|
---|
137 | {
|
---|
138 | if (__testout)
|
---|
139 | _M_really_overflow();
|
---|
140 | else if (_M_in_cur != _M_filepos)
|
---|
141 | _M_file.seekoff(_M_in_cur - _M_filepos,
|
---|
142 | ios_base::cur, ios_base::in);
|
---|
143 | }
|
---|
144 |
|
---|
145 | if (__testinit || __testget)
|
---|
146 | {
|
---|
147 | const locale __loc = this->getloc();
|
---|
148 | const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
|
---|
149 |
|
---|
150 | streamsize __elen = 0;
|
---|
151 | streamsize __ilen = 0;
|
---|
152 | if (__cvt.always_noconv())
|
---|
153 | {
|
---|
154 | __elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),
|
---|
155 | _M_buf_size);
|
---|
156 | __ilen = __elen;
|
---|
157 | }
|
---|
158 | else
|
---|
159 | {
|
---|
160 | char* __buf = static_cast<char*>(__builtin_alloca(_M_buf_size));
|
---|
161 | __elen = _M_file.xsgetn(__buf, _M_buf_size);
|
---|
162 |
|
---|
163 | const char* __eend;
|
---|
164 | char_type* __iend;
|
---|
165 | codecvt_base::result __r;
|
---|
166 | __r = __cvt.in(_M_state_cur, __buf,
|
---|
167 | __buf + __elen, __eend, _M_in_beg,
|
---|
168 | _M_in_beg + _M_buf_size, __iend);
|
---|
169 | if (__r == codecvt_base::ok)
|
---|
170 | __ilen = __iend - _M_in_beg;
|
---|
171 | else
|
---|
172 | {
|
---|
173 | // Unwind.
|
---|
174 | __ilen = 0;
|
---|
175 | _M_file.seekoff(-__elen, ios_base::cur, ios_base::in);
|
---|
176 | }
|
---|
177 | }
|
---|
178 |
|
---|
179 | if (0 < __ilen)
|
---|
180 | {
|
---|
181 | _M_set_determinate(__ilen);
|
---|
182 | if (__testout)
|
---|
183 | _M_out_cur = _M_in_cur;
|
---|
184 | __ret = traits_type::to_int_type(*_M_in_cur);
|
---|
185 | if (__bump)
|
---|
186 | _M_in_cur_move(1);
|
---|
187 | else if (_M_buf_size == 1)
|
---|
188 | {
|
---|
189 | // If we are synced with stdio, we have to unget the
|
---|
190 | // character we just read so that the file pointer
|
---|
191 | // doesn't move.
|
---|
192 | _M_file.sys_ungetc(traits_type::to_int_type(*_M_in_cur));
|
---|
193 | _M_set_indeterminate();
|
---|
194 | }
|
---|
195 | }
|
---|
196 | }
|
---|
197 | }
|
---|
198 | _M_last_overflowed = false;
|
---|
199 | return __ret;
|
---|
200 | }
|
---|
201 | #endif
|
---|
202 | } // namespace std
|
---|