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 _M_underflow_common(bool __bump)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 #if defined(_GLIBCPP_USE_WCHAR_T) || defined(_GLIBCPP_USE_TYPE_WCHAR_T) 108 template<> 109 basic_filebuf<wchar_t>::int_type _M_underflow_common(bool __bump)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 203