121 _M_in_input_mode = false; |
109 _M_in_input_mode = false; |
122 _M_mmap_base = 0; |
110 _M_mmap_base = 0; |
123 } |
111 } |
124 |
112 |
125 |
113 |
126 //---------------------------------------------------------------------- |
|
127 // basic_filebuf<> overridden protected virtual member functions |
|
128 |
|
129 template <class _CharT, class _Traits> |
|
130 streamsize basic_filebuf<_CharT, _Traits>::showmanyc() { |
|
131 // Is there any possibility that reads can succeed? |
|
132 if (!this->is_open() || _M_in_output_mode || _M_in_error_mode) |
|
133 return -1; |
|
134 else if (_M_in_putback_mode) |
|
135 return this->egptr() - this->gptr(); |
|
136 else if (_M_constant_width) { |
|
137 streamoff __pos = _M_base._M_seek(0, ios_base::cur); |
|
138 streamoff __size = _M_base._M_file_size(); |
|
139 return __pos >= 0 && __size > __pos ? __size - __pos : 0; |
|
140 } |
|
141 else |
|
142 return 0; |
|
143 } |
|
144 |
|
145 |
|
146 // Make a putback position available, if necessary, by switching to a |
|
147 // special internal buffer used only for putback. The buffer is |
|
148 // [_M_pback_buf, _M_pback_buf + _S_pback_buf_size), but the base |
|
149 // class only sees a piece of it at a time. (We want to make sure |
|
150 // that we don't try to read a character that hasn't been initialized.) |
|
151 // The end of the putback buffer is always _M_pback_buf + _S_pback_buf_size, |
|
152 // but the beginning is usually not _M_pback_buf. |
|
153 template <class _CharT, class _Traits> |
|
154 __BF_int_type__ |
|
155 basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c) { |
|
156 const int_type __eof = traits_type::eof(); |
|
157 |
|
158 // If we aren't already in input mode, pushback is impossible. |
|
159 if (!_M_in_input_mode) |
|
160 return __eof; |
|
161 |
|
162 // We can use the ordinary get buffer if there's enough space, and |
|
163 // if it's a buffer that we're allowed to write to. |
|
164 if (this->gptr() != this->eback() && |
|
165 (traits_type::eq_int_type(__c, __eof) || |
|
166 traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1]) || |
|
167 !_M_mmap_base)) { |
|
168 this->gbump(-1); |
|
169 if (traits_type::eq_int_type(__c, __eof) || |
|
170 traits_type::eq(traits_type::to_char_type(__c), *this->gptr())) |
|
171 return traits_type::to_int_type(*this->gptr()); |
|
172 } |
|
173 else if (!traits_type::eq_int_type(__c, __eof)) { |
|
174 // Are we in the putback buffer already? |
|
175 _CharT* __pback_end = _M_pback_buf + __STATIC_CAST(int,_S_pback_buf_size); |
|
176 if (_M_in_putback_mode) { |
|
177 // Do we have more room in the putback buffer? |
|
178 if (this->eback() != _M_pback_buf) |
|
179 this->setg(this->egptr() - 1, this->egptr() - 1, __pback_end); |
|
180 else |
|
181 return __eof; // No more room in the buffer, so fail. |
|
182 } |
|
183 else { // We're not yet in the putback buffer. |
|
184 _M_saved_eback = this->eback(); |
|
185 _M_saved_gptr = this->gptr(); |
|
186 _M_saved_egptr = this->egptr(); |
|
187 this->setg(__pback_end - 1, __pback_end - 1, __pback_end); |
|
188 _M_in_putback_mode = true; |
|
189 } |
|
190 } |
|
191 else |
|
192 return __eof; |
|
193 |
|
194 // We have made a putback position available. Assign to it, and return. |
|
195 *this->gptr() = traits_type::to_char_type(__c); |
|
196 return __c; |
|
197 } |
|
198 |
|
199 // This member function flushes the put area, and also outputs the |
|
200 // character __c (unless __c is eof). Invariant: we always leave room |
|
201 // in the internal buffer for one character more than the base class knows |
|
202 // about. We see the internal buffer as [_M_int_buf, _M_int_buf_EOS), but |
|
203 // the base class only sees [_M_int_buf, _M_int_buf_EOS - 1). |
|
204 template <class _CharT, class _Traits> |
|
205 __BF_int_type__ |
|
206 basic_filebuf<_CharT, _Traits>::overflow(int_type __c) { |
|
207 // Switch to output mode, if necessary. |
|
208 if (!_M_in_output_mode) |
|
209 if (!_M_switch_to_output_mode()) |
|
210 return traits_type::eof(); |
|
211 |
|
212 _CharT* __ibegin = this->_M_int_buf; |
|
213 _CharT* __iend = this->pptr(); |
|
214 this->setp(_M_int_buf, _M_int_buf_EOS - 1); |
|
215 |
|
216 // Put __c at the end of the internal buffer. |
|
217 if (!traits_type::eq_int_type(__c, traits_type::eof())) |
|
218 *__iend++ = _Traits::to_char_type(__c); |
|
219 |
|
220 // For variable-width encodings, output may take more than one pass. |
|
221 while (__ibegin != __iend) { |
|
222 const _CharT* __inext = __ibegin; |
|
223 char* __enext = _M_ext_buf; |
|
224 typename _Codecvt::result __status |
|
225 = _M_codecvt->out(_M_state, __ibegin, __iend, __inext, |
|
226 _M_ext_buf, _M_ext_buf_EOS, __enext); |
|
227 if (__status == _Codecvt::noconv) { |
|
228 return _Noconv_output<_Traits>::_M_doit(this, __ibegin, __iend) |
|
229 ? traits_type::not_eof(__c) |
|
230 : _M_output_error(); |
|
231 } |
|
232 |
|
233 // For a constant-width encoding we know that the external buffer |
|
234 // is large enough, so failure to consume the entire internal buffer |
|
235 // or to produce the correct number of external characters, is an error. |
|
236 // For a variable-width encoding, however, we require only that we |
|
237 // consume at least one internal character |
|
238 else if (__status != _Codecvt::error && |
|
239 (((__inext == __iend) && |
|
240 (__enext - _M_ext_buf == _M_width * (__iend - __ibegin))) || |
|
241 (!_M_constant_width && __inext != __ibegin))) { |
|
242 // We successfully converted part or all of the internal buffer. |
|
243 ptrdiff_t __n = __enext - _M_ext_buf; |
|
244 if (_M_write(_M_ext_buf, __n)) |
|
245 __ibegin += __inext - __ibegin; |
|
246 else |
|
247 return _M_output_error(); |
|
248 } |
|
249 else |
|
250 return _M_output_error(); |
|
251 } |
|
252 |
|
253 return traits_type::not_eof(__c); |
|
254 } |
|
255 |
|
256 // This member function must be called before any I/O has been |
|
257 // performed on the stream, otherwise it has no effect. |
|
258 // |
|
259 // __buf == 0 && __n == 0 means to make this stream unbuffered. |
|
260 // __buf != 0 && __n > 0 means to use __buf as the stream's internal |
|
261 // buffer, rather than the buffer that would otherwise be allocated |
|
262 // automatically. __buf must be a pointer to an array of _CharT whose |
|
263 // size is at least __n. |
|
264 template <class _CharT, class _Traits> |
|
265 basic_streambuf<_CharT, _Traits>* |
|
266 basic_filebuf<_CharT, _Traits>::setbuf(_CharT* __buf, streamsize __n) { |
|
267 if (!_M_in_input_mode &&! _M_in_output_mode && !_M_in_error_mode && |
|
268 _M_int_buf == 0) { |
|
269 if (__buf == 0 && __n == 0) |
|
270 _M_allocate_buffers(0, 1); |
|
271 else if (__buf != 0 && __n > 0) |
|
272 _M_allocate_buffers(__buf, __n); |
|
273 } |
|
274 return this; |
|
275 } |
|
276 |
|
277 template <class _CharT, class _Traits> |
|
278 __BF_pos_type__ |
|
279 basic_filebuf<_CharT, _Traits>::seekoff(off_type __off, |
|
280 ios_base::seekdir __whence, |
|
281 ios_base::openmode /* dummy */) { |
|
282 if (this->is_open() && |
|
283 (__off == 0 || (_M_constant_width && this->_M_base._M_in_binary_mode()))) { |
|
284 |
|
285 if (!_M_seek_init(__off != 0 || __whence != ios_base::cur)) |
|
286 return pos_type(-1); |
|
287 |
|
288 // Seek to beginning or end, regardless of whether we're in input mode. |
|
289 if (__whence == ios_base::beg || __whence == ios_base::end) |
|
290 return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence), |
|
291 _State_type()); |
|
292 |
|
293 // Seek relative to current position. Complicated if we're in input mode. |
|
294 else if (__whence == ios_base::cur) { |
|
295 if (!_M_in_input_mode) |
|
296 return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence), |
|
297 _State_type()); |
|
298 else if (_M_mmap_base != 0) { |
|
299 // __off is relative to gptr(). We need to do a bit of arithmetic |
|
300 // to get an offset relative to the external file pointer. |
|
301 streamoff __adjust = _M_mmap_len - (this->gptr() - (_CharT*) _M_mmap_base); |
|
302 |
|
303 // if __off == 0, we do not need to exit input mode and to shift file pointer |
|
304 return __off == 0 ? pos_type(_M_base._M_seek(0, ios_base::cur) - __adjust) |
|
305 : _M_seek_return(_M_base._M_seek(__off - __adjust, ios_base::cur), _State_type()); |
|
306 } |
|
307 else if (_M_constant_width) { // Get or set the position. |
|
308 streamoff __iadj = _M_width * (this->gptr() - this->eback()); |
|
309 |
|
310 // Compensate for offset relative to gptr versus offset relative |
|
311 // to external pointer. For a text-oriented stream, where the |
|
312 // compensation is more than just pointer arithmetic, we may get |
|
313 // but not set the current position. |
|
314 |
|
315 if (__iadj <= _M_ext_buf_end - _M_ext_buf) { |
|
316 streamoff __eadj = _M_base._M_get_offset(_M_ext_buf + __STATIC_CAST(ptrdiff_t, __iadj), _M_ext_buf_end); |
|
317 |
|
318 return __off == 0 ? pos_type(_M_base._M_seek(0, ios_base::cur) - __eadj) |
|
319 : _M_seek_return(_M_base._M_seek(__off - __eadj, ios_base::cur), _State_type()); |
|
320 } |
|
321 } else { // Get the position. Encoding is var width. |
|
322 // Get position in internal buffer. |
|
323 ptrdiff_t __ipos = this->gptr() - this->eback(); |
|
324 |
|
325 // Get corresponding position in external buffer. |
|
326 _State_type __state = _M_state; |
|
327 int __epos = _M_codecvt->length(__state, _M_ext_buf, _M_ext_buf_end, |
|
328 __ipos); |
|
329 |
|
330 if (__epos >= 0) { |
|
331 // Sanity check (expensive): make sure __epos is the right answer. |
|
332 _State_type __tmp_state = _M_state; |
|
333 _Filebuf_Tmp_Buf<_CharT> __buf(__ipos); |
|
334 _CharT* __ibegin = __buf._M_ptr; |
|
335 _CharT* __inext = __ibegin; |
|
336 |
|
337 const char* __dummy; |
|
338 typename _Codecvt::result __status |
|
339 = _M_codecvt->in(__tmp_state, |
|
340 _M_ext_buf, _M_ext_buf + __epos, __dummy, |
|
341 __ibegin, __ibegin + __ipos, __inext); |
|
342 if (__status != _Codecvt::error && |
|
343 (__status == _Codecvt::noconv || |
|
344 (__inext == __ibegin + __ipos && |
|
345 equal(this->eback(), this->gptr(), __ibegin, _STLP_PRIV _Eq_traits<traits_type>())))) { |
|
346 // Get the current position (at the end of the external buffer), |
|
347 // then adjust it. Again, it might be a text-oriented stream. |
|
348 streamoff __cur = _M_base._M_seek(0, ios_base::cur); |
|
349 streamoff __adj = |
|
350 _M_base._M_get_offset(_M_ext_buf, _M_ext_buf + __epos) - |
|
351 _M_base._M_get_offset(_M_ext_buf, _M_ext_buf_end); |
|
352 if (__cur != -1 && __cur + __adj >= 0) |
|
353 return __off == 0 ? pos_type(__cur + __adj) |
|
354 : _M_seek_return(__cur + __adj, __state); |
|
355 //return _M_seek_return(__cur + __adj, __state); |
|
356 } |
|
357 // We failed the sanity check here. |
|
358 } |
|
359 } |
|
360 } |
|
361 // Unrecognized value for __whence here. |
|
362 } |
|
363 |
|
364 return pos_type(-1); |
|
365 } |
|
366 |
|
367 |
|
368 template <class _CharT, class _Traits> |
|
369 __BF_pos_type__ |
|
370 basic_filebuf<_CharT, _Traits>::seekpos(pos_type __pos, |
|
371 ios_base::openmode /* dummy */) { |
|
372 if (this->is_open()) { |
|
373 if (!_M_seek_init(true)) |
|
374 return pos_type(-1); |
|
375 |
|
376 streamoff __off = off_type(__pos); |
|
377 if (__off != -1 && _M_base._M_seek(__off, ios_base::beg) != -1) { |
|
378 _M_state = __pos.state(); |
|
379 return _M_seek_return(__off, __pos.state()); |
|
380 } |
|
381 } |
|
382 |
|
383 return pos_type(-1); |
|
384 } |
|
385 |
|
386 |
|
387 template <class _CharT, class _Traits> |
|
388 int basic_filebuf<_CharT, _Traits>::sync() { |
|
389 if (_M_in_output_mode) |
|
390 return traits_type::eq_int_type(this->overflow(traits_type::eof()), |
|
391 traits_type::eof()) ? -1 : 0; |
|
392 return 0; |
|
393 } |
|
394 |
|
395 |
|
396 // Change the filebuf's locale. This member function has no effect |
|
397 // unless it is called before any I/O is performed on the stream. |
|
398 template <class _CharT, class _Traits> |
|
399 void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc) { |
|
400 if (!_M_in_input_mode && !_M_in_output_mode && !_M_in_error_mode) { |
|
401 this->_M_setup_codecvt(__loc); |
|
402 } |
|
403 } |
|
404 |
114 |
405 //---------------------------------------------------------------------- |
115 //---------------------------------------------------------------------- |
406 // basic_filebuf<> helper functions. |
116 // basic_filebuf<> helper functions. |
407 |
117 |
408 //---------------------------------------- |
118 //---------------------------------------- |