00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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 {
00050 template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
00051 class stdio_sync_filebuf : public std::basic_streambuf<_CharT, _Traits>
00052 {
00053 public:
00054
00055 typedef _CharT char_type;
00056 typedef _Traits traits_type;
00057 typedef typename traits_type::int_type int_type;
00058 typedef typename traits_type::pos_type pos_type;
00059 typedef typename traits_type::off_type off_type;
00060
00061 private:
00062
00063 std::__c_file* const _M_file;
00064
00065
00066
00067 int_type _M_unget_buf;
00068
00069 public:
00070 explicit
00071 stdio_sync_filebuf(std::__c_file* __f)
00072 : _M_file(__f), _M_unget_buf(traits_type::eof())
00073 { }
00074
00082 std::__c_file* const
00083 file() { return this->_M_file; }
00084
00085 protected:
00086 int_type
00087 syncgetc();
00088
00089 int_type
00090 syncungetc(int_type __c);
00091
00092 int_type
00093 syncputc(int_type __c);
00094
00095 virtual int_type
00096 underflow()
00097 {
00098 int_type __c = this->syncgetc();
00099 return this->syncungetc(__c);
00100 }
00101
00102 virtual int_type
00103 uflow()
00104 {
00105
00106 _M_unget_buf = this->syncgetc();
00107 return _M_unget_buf;
00108 }
00109
00110 virtual int_type
00111 pbackfail(int_type __c = traits_type::eof())
00112 {
00113 int_type __ret;
00114 const int_type __eof = traits_type::eof();
00115
00116
00117 if (traits_type::eq_int_type(__c, __eof))
00118 {
00119 if (!traits_type::eq_int_type(_M_unget_buf, __eof))
00120 __ret = this->syncungetc(_M_unget_buf);
00121 else
00122 __ret = __eof;
00123 }
00124 else
00125 __ret = this->syncungetc(__c);
00126
00127
00128 _M_unget_buf = __eof;
00129 return __ret;
00130 }
00131
00132 virtual std::streamsize
00133 xsgetn(char_type* __s, std::streamsize __n);
00134
00135 virtual int_type
00136 overflow(int_type __c = traits_type::eof())
00137 {
00138 int_type __ret;
00139 if (traits_type::eq_int_type(__c, traits_type::eof()))
00140 {
00141 if (std::fflush(_M_file))
00142 __ret = traits_type::eof();
00143 else
00144 __ret = traits_type::not_eof(__c);
00145 }
00146 else
00147 __ret = this->syncputc(__c);
00148 return __ret;
00149 }
00150
00151 virtual std::streamsize
00152 xsputn(const char_type* __s, std::streamsize __n);
00153
00154 virtual int
00155 sync()
00156 { return std::fflush(_M_file); }
00157
00158 virtual std::streampos
00159 seekoff(std::streamoff __off, std::ios_base::seekdir __dir,
00160 std::ios_base::openmode = std::ios_base::in | std::ios_base::out)
00161 {
00162 std::streampos __ret(std::streamoff(-1));
00163 int __whence;
00164 if (__dir == std::ios_base::beg)
00165 __whence = SEEK_SET;
00166 else if (__dir == std::ios_base::cur)
00167 __whence = SEEK_CUR;
00168 else
00169 __whence = SEEK_END;
00170 #ifdef _GLIBCXX_USE_LFS
00171 if (!fseeko64(_M_file, __off, __whence))
00172 __ret = std::streampos(ftello64(_M_file));
00173 #else
00174 if (!fseek(_M_file, __off, __whence))
00175 __ret = std::streampos(std::ftell(_M_file));
00176 #endif
00177 return __ret;
00178 }
00179
00180 virtual std::streampos
00181 seekpos(std::streampos __pos,
00182 std::ios_base::openmode __mode =
00183 std::ios_base::in | std::ios_base::out)
00184 { return seekoff(std::streamoff(__pos), std::ios_base::beg, __mode); }
00185 };
00186
00187 template<>
00188 inline stdio_sync_filebuf<char>::int_type
00189 stdio_sync_filebuf<char>::syncgetc()
00190 { return std::getc(_M_file); }
00191
00192 template<>
00193 inline stdio_sync_filebuf<char>::int_type
00194 stdio_sync_filebuf<char>::syncungetc(int_type __c)
00195 { return std::ungetc(__c, _M_file); }
00196
00197 template<>
00198 inline stdio_sync_filebuf<char>::int_type
00199 stdio_sync_filebuf<char>::syncputc(int_type __c)
00200 { return std::putc(__c, _M_file); }
00201
00202 template<>
00203 inline std::streamsize
00204 stdio_sync_filebuf<char>::xsgetn(char* __s, std::streamsize __n)
00205 {
00206 std::streamsize __ret = std::fread(__s, 1, __n, _M_file);
00207 if (__ret > 0)
00208 _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]);
00209 else
00210 _M_unget_buf = traits_type::eof();
00211 return __ret;
00212 }
00213
00214 template<>
00215 inline std::streamsize
00216 stdio_sync_filebuf<char>::xsputn(const char* __s, std::streamsize __n)
00217 { return std::fwrite(__s, 1, __n, _M_file); }
00218
00219 #ifdef _GLIBCXX_USE_WCHAR_T
00220 template<>
00221 inline stdio_sync_filebuf<wchar_t>::int_type
00222 stdio_sync_filebuf<wchar_t>::syncgetc()
00223 { return std::getwc(_M_file); }
00224
00225 template<>
00226 inline stdio_sync_filebuf<wchar_t>::int_type
00227 stdio_sync_filebuf<wchar_t>::syncungetc(int_type __c)
00228 { return std::ungetwc(__c, _M_file); }
00229
00230 template<>
00231 inline stdio_sync_filebuf<wchar_t>::int_type
00232 stdio_sync_filebuf<wchar_t>::syncputc(int_type __c)
00233 { return std::putwc(__c, _M_file); }
00234
00235 template<>
00236 inline std::streamsize
00237 stdio_sync_filebuf<wchar_t>::xsgetn(wchar_t* __s, std::streamsize __n)
00238 {
00239 std::streamsize __ret = 0;
00240 const int_type __eof = traits_type::eof();
00241 while (__n--)
00242 {
00243 int_type __c = this->syncgetc();
00244 if (traits_type::eq_int_type(__c, __eof))
00245 break;
00246 __s[__ret] = traits_type::to_char_type(__c);
00247 ++__ret;
00248 }
00249
00250 if (__ret > 0)
00251 _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]);
00252 else
00253 _M_unget_buf = traits_type::eof();
00254 return __ret;
00255 }
00256
00257 template<>
00258 inline std::streamsize
00259 stdio_sync_filebuf<wchar_t>::xsputn(const wchar_t* __s,
00260 std::streamsize __n)
00261 {
00262 std::streamsize __ret = 0;
00263 const int_type __eof = traits_type::eof();
00264 while (__n--)
00265 {
00266 if (traits_type::eq_int_type(this->syncputc(*__s++), __eof))
00267 break;
00268 ++__ret;
00269 }
00270 return __ret;
00271 }
00272 #endif
00273
00274 #if _GLIBCXX_EXTERN_TEMPLATE
00275 extern template class stdio_sync_filebuf<char>;
00276 #ifdef _GLIBCXX_USE_WCHAR_T
00277 extern template class stdio_sync_filebuf<wchar_t>;
00278 #endif
00279 #endif
00280 }
00281
00282 #endif