Whole document tree fstream.tccGo to the documentation of this file.00001 // File based streams -*- C++ -*- 00002 00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 2, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // You should have received a copy of the GNU General Public License along 00017 // with this library; see the file COPYING. If not, write to the Free 00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00019 // USA. 00020 00021 // As a special exception, you may use this file as part of a free software 00022 // library without restriction. Specifically, if other files instantiate 00023 // templates or use macros or inline functions from this file, or you compile 00024 // this file and link it with other files to produce an executable, this 00025 // file does not by itself cause the resulting executable to be covered by 00026 // the GNU General Public License. This exception does not however 00027 // invalidate any other reasons why the executable file might be covered by 00028 // the GNU General Public License. 00029 00030 // 00031 // ISO C++ 14882: 27.8 File-based streams 00032 // 00033 00034 #ifndef _CPP_BITS_FSTREAM_TCC 00035 #define _CPP_BITS_FSTREAM_TCC 1 00036 00037 namespace std 00038 { 00039 template<typename _CharT, typename _Traits> 00040 void 00041 basic_filebuf<_CharT, _Traits>:: 00042 _M_allocate_file() 00043 { 00044 if (!_M_file) 00045 { 00046 _M_buf_unified = true; // Tie input to output for basic_filebuf. 00047 try 00048 { _M_file = new __file_type(&_M_lock); } 00049 catch(...) 00050 { 00051 delete _M_file; 00052 __throw_exception_again; 00053 } 00054 } 00055 } 00056 00057 template<typename _CharT, typename _Traits> 00058 void 00059 basic_filebuf<_CharT, _Traits>:: 00060 _M_allocate_internal_buffer() 00061 { 00062 if (!_M_buf && _M_buf_size_opt) 00063 { 00064 _M_buf_size = _M_buf_size_opt; 00065 00066 // Allocate internal buffer. 00067 try { _M_buf = new char_type[_M_buf_size]; } 00068 catch(...) 00069 { 00070 delete [] _M_buf; 00071 __throw_exception_again; 00072 } 00073 _M_buf_allocated = true; 00074 } 00075 } 00076 00077 // Both close and setbuf need to deallocate internal buffers, if it exists. 00078 template<typename _CharT, typename _Traits> 00079 void 00080 basic_filebuf<_CharT, _Traits>:: 00081 _M_destroy_internal_buffer() 00082 { 00083 if (_M_buf_allocated) 00084 { 00085 delete [] _M_buf; 00086 _M_buf = NULL; 00087 _M_buf_allocated = false; 00088 this->setg(NULL, NULL, NULL); 00089 this->setp(NULL, NULL); 00090 } 00091 } 00092 00093 template<typename _CharT, typename _Traits> 00094 void 00095 basic_filebuf<_CharT, _Traits>:: 00096 _M_allocate_pback_buffer() 00097 { 00098 if (!_M_pback && _M_pback_size) 00099 { 00100 // Allocate pback buffer. 00101 try 00102 { _M_pback = new char_type[_M_pback_size]; } 00103 catch(...) 00104 { 00105 delete [] _M_pback; 00106 __throw_exception_again; 00107 } 00108 } 00109 } 00110 00111 template<typename _CharT, typename _Traits> 00112 basic_filebuf<_CharT, _Traits>:: 00113 basic_filebuf() 00114 : __streambuf_type(), _M_file(NULL), _M_state_cur(__state_type()), 00115 _M_state_beg(__state_type()), _M_buf_allocated(false), 00116 _M_last_overflowed(false) 00117 { } 00118 00119 template<typename _CharT, typename _Traits> 00120 basic_filebuf<_CharT, _Traits>:: 00121 basic_filebuf(__c_file_type* __f, ios_base::openmode __mode, int_type __s) 00122 : __streambuf_type(), _M_file(NULL), _M_state_cur(__state_type()), 00123 _M_state_beg(__state_type()), _M_buf_allocated(false), 00124 _M_last_overflowed(false) 00125 { 00126 _M_allocate_file(); 00127 _M_file->sys_open(__f, __mode); 00128 if (this->is_open()) 00129 { 00130 _M_mode = __mode; 00131 if (__s) 00132 { 00133 _M_buf_size_opt = __s; 00134 _M_allocate_internal_buffer(); 00135 _M_set_indeterminate(); 00136 } 00137 _M_allocate_pback_buffer(); 00138 } 00139 } 00140 00141 template<typename _CharT, typename _Traits> 00142 typename basic_filebuf<_CharT, _Traits>::__filebuf_type* 00143 basic_filebuf<_CharT, _Traits>:: 00144 open(const char* __s, ios_base::openmode __mode) 00145 { 00146 __filebuf_type *__ret = NULL; 00147 if (!this->is_open()) 00148 { 00149 _M_allocate_file(); 00150 _M_file->open(__s, __mode); 00151 if (this->is_open()) 00152 { 00153 _M_allocate_internal_buffer(); 00154 _M_allocate_pback_buffer(); 00155 _M_mode = __mode; 00156 00157 // For time being, set both (in/out) sets of pointers. 00158 _M_set_indeterminate(); 00159 if (__mode & ios_base::ate 00160 && this->seekoff(0, ios_base::end, __mode) < 0) 00161 this->close(); 00162 __ret = this; 00163 } 00164 } 00165 return __ret; 00166 } 00167 00168 template<typename _CharT, typename _Traits> 00169 typename basic_filebuf<_CharT, _Traits>::__filebuf_type* 00170 basic_filebuf<_CharT, _Traits>:: 00171 close() 00172 { 00173 __filebuf_type *__ret = NULL; 00174 if (this->is_open()) 00175 { 00176 bool __testput = _M_out_cur && _M_out_beg < _M_out_end; 00177 if (__testput) 00178 _M_really_overflow(traits_type::eof()); 00179 00180 // NB: Do this here so that re-opened filebufs will be cool... 00181 _M_pback_destroy(); 00182 00183 #if 0 00184 // XXX not done 00185 if (_M_last_overflowed) 00186 { 00187 _M_output_unshift(); 00188 _M_really_overflow(traits_type::eof()); 00189 } 00190 #endif 00191 00192 _M_mode = ios_base::openmode(0); 00193 _M_destroy_internal_buffer(); 00194 00195 if (_M_pback) 00196 { 00197 delete [] _M_pback; 00198 _M_pback = NULL; 00199 } 00200 __ret = this; 00201 } 00202 00203 // Can actually allocate this file as part of an open and never 00204 // have it be opened..... 00205 if (_M_file) 00206 { 00207 delete _M_file; 00208 _M_file = NULL; 00209 } 00210 _M_last_overflowed = false; 00211 return __ret; 00212 } 00213 00214 template<typename _CharT, typename _Traits> 00215 streamsize 00216 basic_filebuf<_CharT, _Traits>:: 00217 showmanyc() 00218 { 00219 streamsize __ret = -1; 00220 bool __testin = _M_mode & ios_base::in; 00221 00222 if (__testin) 00223 { 00224 bool __testeof = false; 00225 if (_M_in_cur >= _M_in_end) 00226 __testeof = this->underflow() == traits_type::eof(); 00227 if (!__testeof) 00228 __ret = _M_in_end - _M_in_cur; 00229 } 00230 _M_last_overflowed = false; 00231 return __ret; 00232 } 00233 00234 template<typename _CharT, typename _Traits> 00235 typename basic_filebuf<_CharT, _Traits>::int_type 00236 basic_filebuf<_CharT, _Traits>:: 00237 underflow() 00238 { 00239 int_type __ret = traits_type::eof(); 00240 bool __testin = _M_mode & ios_base::in; 00241 bool __testout = _M_mode & ios_base::out; 00242 00243 // XXX Should re-enable codecvt bits disabled after 2.90.8. 00244 if (__testin) 00245 { 00246 // Check for pback madness, and if so swich back to the 00247 // normal buffers and jet outta here before expensive 00248 // fileops happen... 00249 if (_M_pback_init) 00250 { 00251 _M_pback_destroy(); 00252 if (_M_in_cur < _M_in_end) 00253 return traits_type::to_int_type(*_M_in_cur); 00254 } 00255 00256 bool __testget = _M_in_cur && _M_in_beg < _M_in_cur; 00257 bool __testinit = _M_is_indeterminate(); 00258 // Sync internal and external buffers. 00259 // NB: __testget -> __testput as _M_buf_unified here. 00260 if (__testget) 00261 { 00262 if (__testout) 00263 _M_really_overflow(); 00264 #if _GLIBCPP_AVOID_FSEEK 00265 else if ((_M_in_cur - _M_in_beg) == 1) 00266 _M_file->sys_getc(); 00267 #endif 00268 else 00269 _M_file->seekoff(_M_in_cur - _M_in_beg, 00270 ios_base::cur, ios_base::in); 00271 } 00272 00273 if (__testinit || __testget) 00274 { 00275 // Assume buffered case, need to refill internal buffers. 00276 streamsize __size = _M_file->xsgetn(_M_in_beg, _M_buf_size); 00277 if (0 < __size) 00278 { 00279 _M_set_determinate(__size); 00280 if (__testout) 00281 _M_out_cur = _M_in_cur; 00282 __ret = traits_type::to_int_type(*_M_in_cur); 00283 #if _GLIBCPP_AVOID_FSEEK 00284 if (__size == 1) 00285 _M_file->sys_ungetc(*_M_in_cur); 00286 else 00287 { 00288 #endif 00289 streamoff __p = _M_file->seekoff(0 - __size, ios_base::cur, 00290 ios_base::in); 00291 if (__p == -1) 00292 { 00293 // XXX Something is wrong, do error checking. 00294 } 00295 #if _GLIBCPP_AVOID_FSEEK 00296 } 00297 #endif 00298 } 00299 } 00300 } 00301 _M_last_overflowed = false; 00302 return __ret; 00303 } 00304 00305 template<typename _CharT, typename _Traits> 00306 typename basic_filebuf<_CharT, _Traits>::int_type 00307 basic_filebuf<_CharT, _Traits>:: 00308 pbackfail(int_type __i) 00309 { 00310 int_type __ret = traits_type::eof(); 00311 bool __testin = _M_mode & ios_base::in; 00312 00313 if (__testin) 00314 { 00315 bool __testpb = _M_in_beg < _M_in_cur; 00316 char_type __c = traits_type::to_char_type(__i); 00317 bool __testeof = traits_type::eq_int_type(__i, __ret); 00318 00319 if (__testpb) 00320 { 00321 bool __testout = _M_mode & ios_base::out; 00322 bool __testeq = traits_type::eq(__c, this->gptr()[-1]); 00323 00324 // Try to put back __c into input sequence in one of three ways. 00325 // Order these tests done in is unspecified by the standard. 00326 if (!__testeof && __testeq) 00327 { 00328 --_M_in_cur; 00329 if (__testout) 00330 --_M_out_cur; 00331 __ret = __i; 00332 } 00333 else if (__testeof) 00334 { 00335 --_M_in_cur; 00336 if (__testout) 00337 --_M_out_cur; 00338 __ret = traits_type::not_eof(__i); 00339 } 00340 else if (!__testeof) 00341 { 00342 --_M_in_cur; 00343 if (__testout) 00344 --_M_out_cur; 00345 _M_pback_create(); 00346 *_M_in_cur = __c; 00347 __ret = __i; 00348 } 00349 } 00350 else 00351 { 00352 // At the beginning of the buffer, need to make a 00353 // putback position available. 00354 this->seekoff(-1, ios_base::cur); 00355 this->underflow(); 00356 if (!__testeof) 00357 { 00358 if (!traits_type::eq(__c, *_M_in_cur)) 00359 { 00360 _M_pback_create(); 00361 *_M_in_cur = __c; 00362 } 00363 __ret = __i; 00364 } 00365 else 00366 __ret = traits_type::not_eof(__i); 00367 } 00368 } 00369 _M_last_overflowed = false; 00370 return __ret; 00371 } 00372 00373 template<typename _CharT, typename _Traits> 00374 typename basic_filebuf<_CharT, _Traits>::int_type 00375 basic_filebuf<_CharT, _Traits>:: 00376 overflow(int_type __c) 00377 { 00378 int_type __ret = traits_type::eof(); 00379 bool __testput = _M_out_cur && _M_out_cur < _M_buf + _M_buf_size; 00380 bool __testout = _M_mode & ios_base::out; 00381 00382 if (__testout) 00383 { 00384 if (__testput) 00385 { 00386 *_M_out_cur = traits_type::to_char_type(__c); 00387 _M_out_cur_move(1); 00388 __ret = traits_type::not_eof(__c); 00389 } 00390 else 00391 __ret = this->_M_really_overflow(__c); 00392 } 00393 00394 _M_last_overflowed = false; // Set in _M_really_overflow, below. 00395 return __ret; 00396 } 00397 00398 template<typename _CharT, typename _Traits> 00399 typename basic_filebuf<_CharT, _Traits>::int_type 00400 basic_filebuf<_CharT, _Traits>:: 00401 _M_really_overflow(int_type __c) 00402 { 00403 int_type __ret = traits_type::eof(); 00404 bool __testput = _M_out_cur && _M_out_beg < _M_out_end; 00405 bool __testunbuffered = _M_file && !_M_buf_size; 00406 00407 if (__testput || __testunbuffered) 00408 { 00409 #if 1 00410 int __plen = _M_out_end - _M_out_beg; 00411 streamsize __len = 0; 00412 00413 if (__plen) 00414 __len = _M_file->xsputn(_M_out_beg, __plen); 00415 00416 if (__c !=traits_type::eof()) 00417 { 00418 char_type __pending = traits_type::to_char_type(__c); 00419 __len += _M_file->xsputn(&__pending, 1); 00420 ++__plen; 00421 } 00422 00423 // NB: Need this so that external byte sequence reflects 00424 // internal buffer. 00425 _M_file->sync(); 00426 if (__len == __plen) 00427 { 00428 _M_set_indeterminate(); 00429 __ret = traits_type::not_eof(__c); 00430 } 00431 #else 00432 // Part one: Allocate temporary conversion buffer on 00433 // stack. Convert internal buffer plus __c (ie, 00434 // "pending sequence") to temporary conversion buffer. 00435 int __plen = _M_out_end - _M_out_beg; 00436 char_type* __pbuf = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen + 1)); 00437 traits_type::copy(__pbuf, this->pbase(), __plen); 00438 if (!__testeof) 00439 { 00440 __pbuf[__plen] = traits_type::to_char_type(__c); 00441 ++__plen; 00442 } 00443 00444 char_type* __pend; 00445 char* __conv_buf = static_cast<char*>(__builtin_alloca(__plen)); 00446 char* __conv_end; 00447 _M_state_beg = _M_state_cur; 00448 00449 __res_type __r = _M_fcvt->out(_M_state_cur, 00450 __pbuf, __pbuf + __plen, 00451 const_cast<const char_type*&>(__pend), 00452 __conv_buf, __conv_buf + __plen, 00453 __conv_end); 00454 00455 // Part two: (Re)spill converted "pending sequence" 00456 // contents (now in temporary conversion buffer) to 00457 // external buffer (_M_file->_IO_*) using 00458 // _M_file->sys_write(), and do error (minimal) checking. 00459 if (__r != codecvt_base::error) 00460 { 00461 streamsize __len = _M_file->xsputn(__conv_buf, __plen); 00462 // NB: Need this so that external byte sequence reflects 00463 // internal buffer. 00464 _M_file->sync(); 00465 if (__len == __plen) 00466 { 00467 _M_set_indeterminate(); 00468 __ret = traits_type::not_eof(__c); 00469 } 00470 } 00471 #endif 00472 } 00473 _M_last_overflowed = true; 00474 return __ret; 00475 } 00476 00477 template<typename _CharT, typename _Traits> 00478 typename basic_filebuf<_CharT, _Traits>::__streambuf_type* 00479 basic_filebuf<_CharT, _Traits>:: 00480 setbuf(char_type* __s, streamsize __n) 00481 { 00482 if (!this->is_open() && __s == 0 && __n == 0) 00483 _M_buf_size_opt = 0; 00484 else if (__s && __n) 00485 { 00486 // This is implementation-defined behavior, and assumes 00487 // that an external char_type array of length (__s + __n) 00488 // exists and has been pre-allocated. If this is not the 00489 // case, things will quickly blow up. 00490 // Step 1: Destroy the current internal array. 00491 _M_destroy_internal_buffer(); 00492 00493 // Step 2: Use the external array. 00494 _M_buf = __s; 00495 _M_buf_size_opt = _M_buf_size = __n; 00496 _M_set_indeterminate(); 00497 00498 // Step 3: Make sure a pback buffer is allocated. 00499 _M_allocate_pback_buffer(); 00500 } 00501 _M_last_overflowed = false; 00502 return this; 00503 } 00504 00505 template<typename _CharT, typename _Traits> 00506 typename basic_filebuf<_CharT, _Traits>::pos_type 00507 basic_filebuf<_CharT, _Traits>:: 00508 seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode) 00509 { 00510 pos_type __ret = pos_type(off_type(-1)); 00511 bool __testopen = this->is_open(); 00512 bool __testin = __mode & ios_base::in && _M_mode & ios_base::in; 00513 bool __testout = __mode & ios_base::out && _M_mode & ios_base::out; 00514 00515 // Should probably do has_facet checks here. 00516 int __width = use_facet<__codecvt_type>(_M_buf_locale).encoding(); 00517 if (__width < 0) 00518 __width = 0; 00519 bool __testfail = __off != 0 && __width <= 0; 00520 00521 if (__testopen && !__testfail && (__testin || __testout)) 00522 { 00523 // Ditch any pback buffers to avoid confusion. 00524 _M_pback_destroy(); 00525 00526 if (__way != ios_base::cur || __off != 0) 00527 { 00528 off_type __computed_off = __width * __off; 00529 00530 bool __testget = _M_in_cur && _M_in_beg < _M_in_end; 00531 bool __testput = _M_out_cur && _M_out_beg < _M_out_end; 00532 // Sync the internal and external streams. 00533 // out 00534 if (__testput || _M_last_overflowed) 00535 { 00536 // Part one: update the output sequence. 00537 this->sync(); 00538 // Part two: output unshift sequence. 00539 _M_output_unshift(); 00540 } 00541 //in 00542 // NB: underflow() rewinds the external buffer. 00543 else if (__testget && __way == ios_base::cur) 00544 __computed_off += _M_in_cur - _M_in_beg; 00545 00546 __ret = _M_file->seekoff(__computed_off, __way, __mode); 00547 _M_set_indeterminate(); 00548 } 00549 // NB: Need to do this in case _M_file in indeterminate 00550 // state, ie _M_file->_offset == -1 00551 else 00552 { 00553 __ret = _M_file->seekoff(__off, ios_base::cur, __mode); 00554 __ret += max(_M_out_cur, _M_in_cur) - _M_buf; 00555 } 00556 } 00557 _M_last_overflowed = false; 00558 return __ret; 00559 } 00560 00561 template<typename _CharT, typename _Traits> 00562 typename basic_filebuf<_CharT, _Traits>::pos_type 00563 basic_filebuf<_CharT, _Traits>:: 00564 seekpos(pos_type __pos, ios_base::openmode __mode) 00565 { 00566 pos_type __ret; 00567 off_type __off = __pos; 00568 00569 __ret = this->seekoff(__off, ios_base::beg, __mode); 00570 00571 _M_last_overflowed = false; 00572 return __ret; 00573 } 00574 00575 template<typename _CharT, typename _Traits> 00576 void 00577 basic_filebuf<_CharT, _Traits>:: 00578 _M_output_unshift() 00579 { } 00580 00581 template<typename _CharT, typename _Traits> 00582 void 00583 basic_filebuf<_CharT, _Traits>:: 00584 imbue(const locale& __loc) 00585 { 00586 bool __testbeg = gptr() == eback() && pptr() == pbase(); 00587 00588 if (__testbeg && _M_buf_locale != __loc) 00589 { 00590 _M_buf_locale = __loc; 00591 _M_buf_locale_init = true; 00592 } 00593 00594 // NB this may require the reconversion of previously 00595 // converted chars. This in turn may cause the reconstruction 00596 // of the original file. YIKES!! 00597 // XXX The part in the above comment is not done. 00598 _M_last_overflowed = false; 00599 } 00600 00601 } // namespace std 00602 00603 #endif // _CPP_BITS_FSTREAM_TCC 00604 00605 Generated on Mon Apr 8 03:11:25 2002 for libstdc++-v3 Source by ![]() |