stdio_sync_filebuf.h

00001 // Iostreams wrapper for stdio FILE* -*- C++ -*- 00002 00003 // Copyright (C) 2003, 2004 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 /** @file ext/stdiostream.h 00031 * This file is a GNU extension to the Standard C++ Library. 00032 */ 00033 00034 #ifndef _STDIO_SYNC_FILEBUF_H 00035 #define _STDIO_SYNC_FILEBUF_H 1 00036 00037 #pragma GCC system_header 00038 00039 #include <streambuf> 00040 #include <unistd.h> 00041 #include <cstdio> 00042 00043 #ifdef _GLIBCXX_USE_WCHAR_T 00044 #include <cwchar> 00045 #endif 00046 00047 namespace __gnu_cxx 00048 { 00049 template<typename _CharT, typename _Traits = std::char_traits<_CharT> > 00050 class stdio_sync_filebuf : public std::basic_streambuf<_CharT, _Traits> 00051 { 00052 public: 00053 // Types: 00054 typedef _CharT char_type; 00055 typedef _Traits traits_type; 00056 typedef typename traits_type::int_type int_type; 00057 typedef typename traits_type::pos_type pos_type; 00058 typedef typename traits_type::off_type off_type; 00059 00060 private: 00061 // Underlying stdio FILE 00062 std::__c_file* const _M_file; 00063 00064 // Last character gotten. This is used when pbackfail is 00065 // called from basic_streambuf::sungetc() 00066 int_type _M_unget_buf; 00067 00068 public: 00069 explicit 00070 stdio_sync_filebuf(std::__c_file* __f) 00071 : _M_file(__f), _M_unget_buf(traits_type::eof()) 00072 { } 00073 00074 /** 00075 * @return The underlying FILE*. 00076 * 00077 * This function can be used to access the underlying "C" file pointer. 00078 * Note that there is no way for the library to track what you do 00079 * with the file, so be careful. 00080 */ 00081 std::__c_file* const 00082 file() { return this->_M_file; } 00083 00084 protected: 00085 int_type 00086 syncgetc(); 00087 00088 int_type 00089 syncungetc(int_type __c); 00090 00091 int_type 00092 syncputc(int_type __c); 00093 00094 virtual int_type 00095 underflow() 00096 { 00097 int_type __c = this->syncgetc(); 00098 return this->syncungetc(__c); 00099 } 00100 00101 virtual int_type 00102 uflow() 00103 { 00104 // Store the gotten character in case we need to unget it. 00105 _M_unget_buf = this->syncgetc(); 00106 return _M_unget_buf; 00107 } 00108 00109 virtual int_type 00110 pbackfail(int_type __c = traits_type::eof()) 00111 { 00112 int_type __ret; 00113 const int_type __eof = traits_type::eof(); 00114 00115 // Check if the unget or putback was requested 00116 if (traits_type::eq_int_type(__c, __eof)) // unget 00117 { 00118 if (!traits_type::eq_int_type(_M_unget_buf, __eof)) 00119 __ret = this->syncungetc(_M_unget_buf); 00120 else // buffer invalid, fail. 00121 __ret = __eof; 00122 } 00123 else // putback 00124 __ret = this->syncungetc(__c); 00125 00126 // The buffered character is no longer valid, discard it. 00127 _M_unget_buf = __eof; 00128 return __ret; 00129 } 00130 00131 virtual std::streamsize 00132 xsgetn(char_type* __s, std::streamsize __n); 00133 00134 virtual int_type 00135 overflow(int_type __c = traits_type::eof()) 00136 { 00137 int_type __ret; 00138 if (traits_type::eq_int_type(__c, traits_type::eof())) 00139 { 00140 if (std::fflush(_M_file)) 00141 __ret = traits_type::eof(); 00142 else 00143 __ret = traits_type::not_eof(__c); 00144 } 00145 else 00146 __ret = this->syncputc(__c); 00147 return __ret; 00148 } 00149 00150 virtual std::streamsize 00151 xsputn(const char_type* __s, std::streamsize __n); 00152 00153 virtual int 00154 sync() 00155 { return std::fflush(_M_file); } 00156 00157 virtual std::streampos 00158 seekoff(std::streamoff __off, std::ios_base::seekdir __dir, 00159 std::ios_base::openmode = std::ios_base::in | std::ios_base::out) 00160 { 00161 std::streampos __ret(std::streamoff(-1)); 00162 int __whence; 00163 if (__dir == std::ios_base::beg) 00164 __whence = SEEK_SET; 00165 else if (__dir == std::ios_base::cur) 00166 __whence = SEEK_CUR; 00167 else 00168 __whence = SEEK_END; 00169 #ifdef _GLIBCXX_USE_LFS 00170 if (!fseeko64(_M_file, __off, __whence)) 00171 __ret = std::streampos(ftello64(_M_file)); 00172 #else 00173 if (!fseek(_M_file, __off, __whence)) 00174 __ret = std::streampos(std::ftell(_M_file)); 00175 #endif 00176 return __ret; 00177 } 00178 00179 virtual std::streampos 00180 seekpos(std::streampos __pos, 00181 std::ios_base::openmode __mode = 00182 std::ios_base::in | std::ios_base::out) 00183 { return seekoff(std::streamoff(__pos), std::ios_base::beg, __mode); } 00184 }; 00185 00186 template<> 00187 inline stdio_sync_filebuf<char>::int_type 00188 stdio_sync_filebuf<char>::syncgetc() 00189 { return std::getc(_M_file); } 00190 00191 template<> 00192 inline stdio_sync_filebuf<char>::int_type 00193 stdio_sync_filebuf<char>::syncungetc(int_type __c) 00194 { return std::ungetc(__c, _M_file); } 00195 00196 template<> 00197 inline stdio_sync_filebuf<char>::int_type 00198 stdio_sync_filebuf<char>::syncputc(int_type __c) 00199 { return std::putc(__c, _M_file); } 00200 00201 template<> 00202 inline std::streamsize 00203 stdio_sync_filebuf<char>::xsgetn(char* __s, std::streamsize __n) 00204 { 00205 std::streamsize __ret = std::fread(__s, 1, __n, _M_file); 00206 if (__ret > 0) 00207 _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]); 00208 else 00209 _M_unget_buf = traits_type::eof(); 00210 return __ret; 00211 } 00212 00213 template<> 00214 inline std::streamsize 00215 stdio_sync_filebuf<char>::xsputn(const char* __s, std::streamsize __n) 00216 { return std::fwrite(__s, 1, __n, _M_file); } 00217 00218 #ifdef _GLIBCXX_USE_WCHAR_T 00219 template<> 00220 inline stdio_sync_filebuf<wchar_t>::int_type 00221 stdio_sync_filebuf<wchar_t>::syncgetc() 00222 { return std::getwc(_M_file); } 00223 00224 template<> 00225 inline stdio_sync_filebuf<wchar_t>::int_type 00226 stdio_sync_filebuf<wchar_t>::syncungetc(int_type __c) 00227 { return std::ungetwc(__c, _M_file); } 00228 00229 template<> 00230 inline stdio_sync_filebuf<wchar_t>::int_type 00231 stdio_sync_filebuf<wchar_t>::syncputc(int_type __c) 00232 { return std::putwc(__c, _M_file); } 00233 00234 template<> 00235 inline std::streamsize 00236 stdio_sync_filebuf<wchar_t>::xsgetn(wchar_t* __s, std::streamsize __n) 00237 { 00238 std::streamsize __ret = 0; 00239 const int_type __eof = traits_type::eof(); 00240 while (__n--) 00241 { 00242 int_type __c = this->syncgetc(); 00243 if (traits_type::eq_int_type(__c, __eof)) 00244 break; 00245 __s[__ret] = traits_type::to_char_type(__c); 00246 ++__ret; 00247 } 00248 00249 if (__ret > 0) 00250 _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]); 00251 else 00252 _M_unget_buf = traits_type::eof(); 00253 return __ret; 00254 } 00255 00256 template<> 00257 inline std::streamsize 00258 stdio_sync_filebuf<wchar_t>::xsputn(const wchar_t* __s, 00259 std::streamsize __n) 00260 { 00261 std::streamsize __ret = 0; 00262 const int_type __eof = traits_type::eof(); 00263 while (__n--) 00264 { 00265 if (traits_type::eq_int_type(this->syncputc(*__s++), __eof)) 00266 break; 00267 ++__ret; 00268 } 00269 return __ret; 00270 } 00271 #endif 00272 00273 #if _GLIBCXX_EXTERN_TEMPLATE 00274 extern template class stdio_sync_filebuf<char>; 00275 #ifdef _GLIBCXX_USE_WCHAR_T 00276 extern template class stdio_sync_filebuf<wchar_t>; 00277 #endif 00278 #endif 00279 } // namespace __gnu_cxx 00280 00281 #endif

Generated on Wed Jun 9 11:18:53 2004 for libstdc++-v3 Source by doxygen 1.3.7