1// Iostreams wrapper for stdio FILE* -*- C++ -*- 2 3// Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 2, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// You should have received a copy of the GNU General Public License along 17// with this library; see the file COPYING. If not, write to the Free 18// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 19// USA. 20 21// As a special exception, you may use this file as part of a free software 22// library without restriction. Specifically, if other files instantiate 23// templates or use macros or inline functions from this file, or you compile 24// this file and link it with other files to produce an executable, this 25// file does not by itself cause the resulting executable to be covered by 26// the GNU General Public License. This exception does not however 27// invalidate any other reasons why the executable file might be covered by 28// the GNU General Public License. 29 30/** @file ext/stdio_sync_filebuf.h 31 * This file is a GNU extension to the Standard C++ Library. 32 */ 33 34#ifndef _STDIO_SYNC_FILEBUF_H 35#define _STDIO_SYNC_FILEBUF_H 1 36 37#pragma GCC system_header 38 39#include <streambuf> 40#include <unistd.h> 41#include <cstdio> 42 43#ifdef _GLIBCXX_USE_WCHAR_T 44#include <cwchar> 45#endif 46 47_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 48 49 /// @brief class stdio_sync_filebuf. 50 template<typename _CharT, typename _Traits = std::char_traits<_CharT> > 51 class stdio_sync_filebuf : public std::basic_streambuf<_CharT, _Traits> 52 { 53 public: 54 // Types: 55 typedef _CharT char_type; 56 typedef _Traits traits_type; 57 typedef typename traits_type::int_type int_type; 58 typedef typename traits_type::pos_type pos_type; 59 typedef typename traits_type::off_type off_type; 60 61 private: 62 // Underlying stdio FILE 63 std::__c_file* const _M_file; 64 65 // Last character gotten. This is used when pbackfail is 66 // called from basic_streambuf::sungetc() 67 int_type _M_unget_buf; 68 69 public: 70 explicit 71 stdio_sync_filebuf(std::__c_file* __f) 72 : _M_file(__f), _M_unget_buf(traits_type::eof()) 73 { } 74 75#if BUILDING_LIBSTDCXX 76 __attribute__((used)) 77 virtual ~stdio_sync_filebuf() {} 78#endif 79 80 /** 81 * @return The underlying FILE*. 82 * 83 * This function can be used to access the underlying "C" file pointer. 84 * Note that there is no way for the library to track what you do 85 * with the file, so be careful. 86 */ 87 std::__c_file* const 88 file() { return this->_M_file; } 89 90 protected: 91 int_type 92 syncgetc(); 93 94 int_type 95 syncungetc(int_type __c); 96 97 int_type 98 syncputc(int_type __c); 99 100 virtual int_type 101 underflow() 102 { 103 int_type __c = this->syncgetc(); 104 return this->syncungetc(__c); 105 } 106 107 virtual int_type 108 uflow() 109 { 110 // Store the gotten character in case we need to unget it. 111 _M_unget_buf = this->syncgetc(); 112 return _M_unget_buf; 113 } 114 115 virtual int_type 116 pbackfail(int_type __c = traits_type::eof()) 117 { 118 int_type __ret; 119 const int_type __eof = traits_type::eof(); 120 121 // Check if the unget or putback was requested 122 if (traits_type::eq_int_type(__c, __eof)) // unget 123 { 124 if (!traits_type::eq_int_type(_M_unget_buf, __eof)) 125 __ret = this->syncungetc(_M_unget_buf); 126 else // buffer invalid, fail. 127 __ret = __eof; 128 } 129 else // putback 130 __ret = this->syncungetc(__c); 131 132 // The buffered character is no longer valid, discard it. 133 _M_unget_buf = __eof; 134 return __ret; 135 } 136 137 virtual std::streamsize 138 xsgetn(char_type* __s, std::streamsize __n); 139 140 virtual int_type 141 overflow(int_type __c = traits_type::eof()) 142 { 143 int_type __ret; 144 if (traits_type::eq_int_type(__c, traits_type::eof())) 145 { 146 if (std::fflush(_M_file)) 147 __ret = traits_type::eof(); 148 else 149 __ret = traits_type::not_eof(__c); 150 } 151 else 152 __ret = this->syncputc(__c); 153 return __ret; 154 } 155 156 virtual std::streamsize 157 xsputn(const char_type* __s, std::streamsize __n); 158 159 virtual int 160 sync() 161 { return std::fflush(_M_file); } 162 163 virtual std::streampos 164 seekoff(std::streamoff __off, std::ios_base::seekdir __dir, 165 std::ios_base::openmode = std::ios_base::in | std::ios_base::out) 166 { 167 std::streampos __ret(std::streamoff(-1)); 168 int __whence; 169 if (__dir == std::ios_base::beg) 170 __whence = SEEK_SET; 171 else if (__dir == std::ios_base::cur) 172 __whence = SEEK_CUR; 173 else 174 __whence = SEEK_END; 175#ifdef _GLIBCXX_USE_LFS 176 if (!fseeko64(_M_file, __off, __whence)) 177 __ret = std::streampos(ftello64(_M_file)); 178#else 179 if (!fseek(_M_file, __off, __whence)) 180 __ret = std::streampos(std::ftell(_M_file)); 181#endif 182 return __ret; 183 } 184 185 virtual std::streampos 186 seekpos(std::streampos __pos, 187 std::ios_base::openmode __mode = 188 std::ios_base::in | std::ios_base::out) 189 { return seekoff(std::streamoff(__pos), std::ios_base::beg, __mode); } 190 }; 191 192 template<> 193 inline stdio_sync_filebuf<char>::int_type 194 stdio_sync_filebuf<char>::syncgetc() 195 { return std::getc(_M_file); } 196 197 template<> 198 inline stdio_sync_filebuf<char>::int_type 199 stdio_sync_filebuf<char>::syncungetc(int_type __c) 200 { return std::ungetc(__c, _M_file); } 201 202 template<> 203 inline stdio_sync_filebuf<char>::int_type 204 stdio_sync_filebuf<char>::syncputc(int_type __c) 205 { return std::putc(__c, _M_file); } 206 207 template<> 208 inline std::streamsize 209 stdio_sync_filebuf<char>::xsgetn(char* __s, std::streamsize __n) 210 { 211 std::streamsize __ret = std::fread(__s, 1, __n, _M_file); 212 if (__ret > 0) 213 _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]); 214 else 215 _M_unget_buf = traits_type::eof(); 216 return __ret; 217 } 218 219 template<> 220 inline std::streamsize 221 stdio_sync_filebuf<char>::xsputn(const char* __s, std::streamsize __n) 222 { return std::fwrite(__s, 1, __n, _M_file); } 223 224#ifdef _GLIBCXX_USE_WCHAR_T 225 template<> 226 inline stdio_sync_filebuf<wchar_t>::int_type 227 stdio_sync_filebuf<wchar_t>::syncgetc() 228 { return std::getwc(_M_file); } 229 230 template<> 231 inline stdio_sync_filebuf<wchar_t>::int_type 232 stdio_sync_filebuf<wchar_t>::syncungetc(int_type __c) 233 { return std::ungetwc(__c, _M_file); } 234 235 template<> 236 inline stdio_sync_filebuf<wchar_t>::int_type 237 stdio_sync_filebuf<wchar_t>::syncputc(int_type __c) 238 { return std::putwc(__c, _M_file); } 239 240 template<> 241 inline std::streamsize 242 stdio_sync_filebuf<wchar_t>::xsgetn(wchar_t* __s, std::streamsize __n) 243 { 244 std::streamsize __ret = 0; 245 const int_type __eof = traits_type::eof(); 246 while (__n--) 247 { 248 int_type __c = this->syncgetc(); 249 if (traits_type::eq_int_type(__c, __eof)) 250 break; 251 __s[__ret] = traits_type::to_char_type(__c); 252 ++__ret; 253 } 254 255 if (__ret > 0) 256 _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]); 257 else 258 _M_unget_buf = traits_type::eof(); 259 return __ret; 260 } 261 262 template<> 263 inline std::streamsize 264 stdio_sync_filebuf<wchar_t>::xsputn(const wchar_t* __s, 265 std::streamsize __n) 266 { 267 std::streamsize __ret = 0; 268 const int_type __eof = traits_type::eof(); 269 while (__n--) 270 { 271 if (traits_type::eq_int_type(this->syncputc(*__s++), __eof)) 272 break; 273 ++__ret; 274 } 275 return __ret; 276 } 277#endif 278 279#if _GLIBCXX_EXTERN_TEMPLATE 280 extern template class stdio_sync_filebuf<char>; 281#ifdef _GLIBCXX_USE_WCHAR_T 282 extern template class stdio_sync_filebuf<wchar_t>; 283#endif 284#endif 285 286_GLIBCXX_END_NAMESPACE 287 288#endif 289