libstdc++
|
00001 // Iostreams wrapper for stdio FILE* -*- C++ -*- 00002 00003 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010 00004 // Free Software Foundation, Inc. 00005 // 00006 // This file is part of the GNU ISO C++ Library. This library is free 00007 // software; you can redistribute it and/or modify it under the 00008 // terms of the GNU General Public License as published by the 00009 // Free Software Foundation; either version 3, or (at your option) 00010 // any later version. 00011 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 00017 // Under Section 7 of GPL version 3, you are granted additional 00018 // permissions described in the GCC Runtime Library Exception, version 00019 // 3.1, as published by the Free Software Foundation. 00020 00021 // You should have received a copy of the GNU General Public License and 00022 // a copy of the GCC Runtime Library Exception along with this program; 00023 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00024 // <http://www.gnu.org/licenses/>. 00025 00026 /** @file ext/stdio_sync_filebuf.h 00027 * This file is a GNU extension to the Standard C++ Library. 00028 */ 00029 00030 #ifndef _STDIO_SYNC_FILEBUF_H 00031 #define _STDIO_SYNC_FILEBUF_H 1 00032 00033 #pragma GCC system_header 00034 00035 #include <streambuf> 00036 #include <unistd.h> 00037 #include <cstdio> 00038 #include <bits/c++io.h> // For __c_file 00039 00040 #ifdef _GLIBCXX_USE_WCHAR_T 00041 #include <cwchar> 00042 #endif 00043 00044 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) 00045 { 00046 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00047 00048 /** 00049 * @brief Provides a layer of compatibility for C. 00050 * @ingroup io 00051 * 00052 * This GNU extension provides extensions for working with standard 00053 * C FILE*'s. It must be instantiated by the user with the type of 00054 * character used in the file stream, e.g., stdio_filebuf<char>. 00055 */ 00056 template<typename _CharT, typename _Traits = std::char_traits<_CharT> > 00057 class stdio_sync_filebuf : public std::basic_streambuf<_CharT, _Traits> 00058 { 00059 public: 00060 // Types: 00061 typedef _CharT char_type; 00062 typedef _Traits traits_type; 00063 typedef typename traits_type::int_type int_type; 00064 typedef typename traits_type::pos_type pos_type; 00065 typedef typename traits_type::off_type off_type; 00066 00067 private: 00068 // Underlying stdio FILE 00069 std::__c_file* const _M_file; 00070 00071 // Last character gotten. This is used when pbackfail is 00072 // called from basic_streambuf::sungetc() 00073 int_type _M_unget_buf; 00074 00075 public: 00076 explicit 00077 stdio_sync_filebuf(std::__c_file* __f) 00078 : _M_file(__f), _M_unget_buf(traits_type::eof()) 00079 { } 00080 00081 /** 00082 * @return The underlying FILE*. 00083 * 00084 * This function can be used to access the underlying C file pointer. 00085 * Note that there is no way for the library to track what you do 00086 * with the file, so be careful. 00087 */ 00088 std::__c_file* const 00089 file() { return this->_M_file; } 00090 00091 protected: 00092 int_type 00093 syncgetc(); 00094 00095 int_type 00096 syncungetc(int_type __c); 00097 00098 int_type 00099 syncputc(int_type __c); 00100 00101 virtual int_type 00102 underflow() 00103 { 00104 int_type __c = this->syncgetc(); 00105 return this->syncungetc(__c); 00106 } 00107 00108 virtual int_type 00109 uflow() 00110 { 00111 // Store the gotten character in case we need to unget it. 00112 _M_unget_buf = this->syncgetc(); 00113 return _M_unget_buf; 00114 } 00115 00116 virtual int_type 00117 pbackfail(int_type __c = traits_type::eof()) 00118 { 00119 int_type __ret; 00120 const int_type __eof = traits_type::eof(); 00121 00122 // Check if the unget or putback was requested 00123 if (traits_type::eq_int_type(__c, __eof)) // unget 00124 { 00125 if (!traits_type::eq_int_type(_M_unget_buf, __eof)) 00126 __ret = this->syncungetc(_M_unget_buf); 00127 else // buffer invalid, fail. 00128 __ret = __eof; 00129 } 00130 else // putback 00131 __ret = this->syncungetc(__c); 00132 00133 // The buffered character is no longer valid, discard it. 00134 _M_unget_buf = __eof; 00135 return __ret; 00136 } 00137 00138 virtual std::streamsize 00139 xsgetn(char_type* __s, std::streamsize __n); 00140 00141 virtual int_type 00142 overflow(int_type __c = traits_type::eof()) 00143 { 00144 int_type __ret; 00145 if (traits_type::eq_int_type(__c, traits_type::eof())) 00146 { 00147 if (std::fflush(_M_file)) 00148 __ret = traits_type::eof(); 00149 else 00150 __ret = traits_type::not_eof(__c); 00151 } 00152 else 00153 __ret = this->syncputc(__c); 00154 return __ret; 00155 } 00156 00157 virtual std::streamsize 00158 xsputn(const char_type* __s, std::streamsize __n); 00159 00160 virtual int 00161 sync() 00162 { return std::fflush(_M_file); } 00163 00164 virtual std::streampos 00165 seekoff(std::streamoff __off, std::ios_base::seekdir __dir, 00166 std::ios_base::openmode = std::ios_base::in | std::ios_base::out) 00167 { 00168 std::streampos __ret(std::streamoff(-1)); 00169 int __whence; 00170 if (__dir == std::ios_base::beg) 00171 __whence = SEEK_SET; 00172 else if (__dir == std::ios_base::cur) 00173 __whence = SEEK_CUR; 00174 else 00175 __whence = SEEK_END; 00176 #ifdef _GLIBCXX_USE_LFS 00177 if (!fseeko64(_M_file, __off, __whence)) 00178 __ret = std::streampos(ftello64(_M_file)); 00179 #else 00180 if (!fseek(_M_file, __off, __whence)) 00181 __ret = std::streampos(std::ftell(_M_file)); 00182 #endif 00183 return __ret; 00184 } 00185 00186 virtual std::streampos 00187 seekpos(std::streampos __pos, 00188 std::ios_base::openmode __mode = 00189 std::ios_base::in | std::ios_base::out) 00190 { return seekoff(std::streamoff(__pos), std::ios_base::beg, __mode); } 00191 }; 00192 00193 template<> 00194 inline stdio_sync_filebuf<char>::int_type 00195 stdio_sync_filebuf<char>::syncgetc() 00196 { return std::getc(_M_file); } 00197 00198 template<> 00199 inline stdio_sync_filebuf<char>::int_type 00200 stdio_sync_filebuf<char>::syncungetc(int_type __c) 00201 { return std::ungetc(__c, _M_file); } 00202 00203 template<> 00204 inline stdio_sync_filebuf<char>::int_type 00205 stdio_sync_filebuf<char>::syncputc(int_type __c) 00206 { return std::putc(__c, _M_file); } 00207 00208 template<> 00209 inline std::streamsize 00210 stdio_sync_filebuf<char>::xsgetn(char* __s, std::streamsize __n) 00211 { 00212 std::streamsize __ret = std::fread(__s, 1, __n, _M_file); 00213 if (__ret > 0) 00214 _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]); 00215 else 00216 _M_unget_buf = traits_type::eof(); 00217 return __ret; 00218 } 00219 00220 template<> 00221 inline std::streamsize 00222 stdio_sync_filebuf<char>::xsputn(const char* __s, std::streamsize __n) 00223 { return std::fwrite(__s, 1, __n, _M_file); } 00224 00225 #ifdef _GLIBCXX_USE_WCHAR_T 00226 template<> 00227 inline stdio_sync_filebuf<wchar_t>::int_type 00228 stdio_sync_filebuf<wchar_t>::syncgetc() 00229 { return std::getwc(_M_file); } 00230 00231 template<> 00232 inline stdio_sync_filebuf<wchar_t>::int_type 00233 stdio_sync_filebuf<wchar_t>::syncungetc(int_type __c) 00234 { return std::ungetwc(__c, _M_file); } 00235 00236 template<> 00237 inline stdio_sync_filebuf<wchar_t>::int_type 00238 stdio_sync_filebuf<wchar_t>::syncputc(int_type __c) 00239 { return std::putwc(__c, _M_file); } 00240 00241 template<> 00242 inline std::streamsize 00243 stdio_sync_filebuf<wchar_t>::xsgetn(wchar_t* __s, std::streamsize __n) 00244 { 00245 std::streamsize __ret = 0; 00246 const int_type __eof = traits_type::eof(); 00247 while (__n--) 00248 { 00249 int_type __c = this->syncgetc(); 00250 if (traits_type::eq_int_type(__c, __eof)) 00251 break; 00252 __s[__ret] = traits_type::to_char_type(__c); 00253 ++__ret; 00254 } 00255 00256 if (__ret > 0) 00257 _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]); 00258 else 00259 _M_unget_buf = traits_type::eof(); 00260 return __ret; 00261 } 00262 00263 template<> 00264 inline std::streamsize 00265 stdio_sync_filebuf<wchar_t>::xsputn(const wchar_t* __s, 00266 std::streamsize __n) 00267 { 00268 std::streamsize __ret = 0; 00269 const int_type __eof = traits_type::eof(); 00270 while (__n--) 00271 { 00272 if (traits_type::eq_int_type(this->syncputc(*__s++), __eof)) 00273 break; 00274 ++__ret; 00275 } 00276 return __ret; 00277 } 00278 #endif 00279 00280 #if _GLIBCXX_EXTERN_TEMPLATE 00281 extern template class stdio_sync_filebuf<char>; 00282 #ifdef _GLIBCXX_USE_WCHAR_T 00283 extern template class stdio_sync_filebuf<wchar_t>; 00284 #endif 00285 #endif 00286 00287 _GLIBCXX_END_NAMESPACE_VERSION 00288 } // namespace 00289 00290 #endif