libstdc++
stdio_sync_filebuf.h
Go to the documentation of this file.
1 // Iostreams wrapper for stdio FILE* -*- C++ -*-
2 
3 // Copyright (C) 2003-2018 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 3, 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 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file ext/stdio_sync_filebuf.h
26  * This file is a GNU extension to the Standard C++ Library.
27  */
28 
29 #ifndef _STDIO_SYNC_FILEBUF_H
30 #define _STDIO_SYNC_FILEBUF_H 1
31 
32 #pragma GCC system_header
33 
34 #include <streambuf>
35 #include <unistd.h>
36 #include <cstdio>
37 #include <bits/c++io.h> // For __c_file
38 #include <bits/move.h> // For __exchange
39 
40 #ifdef _GLIBCXX_USE_WCHAR_T
41 #include <cwchar>
42 #endif
43 
44 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
45 {
46 _GLIBCXX_BEGIN_NAMESPACE_VERSION
47 
48  /**
49  * @brief Provides a layer of compatibility for C.
50  * @ingroup io
51  *
52  * This GNU extension provides extensions for working with standard
53  * C FILE*'s. It must be instantiated by the user with the type of
54  * character used in the file stream, e.g., stdio_filebuf<char>.
55  */
56  template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
57  class stdio_sync_filebuf : public std::basic_streambuf<_CharT, _Traits>
58  {
59  public:
60  // Types:
61  typedef _CharT char_type;
62  typedef _Traits traits_type;
63  typedef typename traits_type::int_type int_type;
64  typedef typename traits_type::pos_type pos_type;
65  typedef typename traits_type::off_type off_type;
66 
67  private:
69 
70  // Underlying stdio FILE
71  std::__c_file* _M_file;
72 
73  // Last character gotten. This is used when pbackfail is
74  // called from basic_streambuf::sungetc()
75  int_type _M_unget_buf;
76 
77  public:
78  explicit
79  stdio_sync_filebuf(std::__c_file* __f)
80  : _M_file(__f), _M_unget_buf(traits_type::eof())
81  { }
82 
83 #if __cplusplus >= 201103L
84  stdio_sync_filebuf(stdio_sync_filebuf&& __fb) noexcept
85  : __streambuf_type(std::move(__fb)),
86  _M_file(__fb._M_file), _M_unget_buf(__fb._M_unget_buf)
87  {
88  __fb._M_file = nullptr;
89  __fb._M_unget_buf = traits_type::eof();
90  }
91 
93  operator=(stdio_sync_filebuf&& __fb) noexcept
94  {
95  __streambuf_type::operator=(__fb);
96  _M_file = std::__exchange(__fb._M_file, nullptr);
97  _M_unget_buf = std::__exchange(__fb._M_unget_buf, traits_type::eof());
98  return *this;
99  }
100 
101  void
102  swap(stdio_sync_filebuf& __fb)
103  {
104  __streambuf_type::swap(__fb);
105  std::swap(_M_file, __fb._M_file);
106  std::swap(_M_unget_buf, __fb._M_unget_buf);
107  }
108 #endif
109 
110  /**
111  * @return The underlying FILE*.
112  *
113  * This function can be used to access the underlying C file pointer.
114  * Note that there is no way for the library to track what you do
115  * with the file, so be careful.
116  */
117  std::__c_file*
118  file() { return this->_M_file; }
119 
120  protected:
121  int_type
122  syncgetc();
123 
124  int_type
125  syncungetc(int_type __c);
126 
127  int_type
128  syncputc(int_type __c);
129 
130  virtual int_type
132  {
133  int_type __c = this->syncgetc();
134  return this->syncungetc(__c);
135  }
136 
137  virtual int_type
139  {
140  // Store the gotten character in case we need to unget it.
141  _M_unget_buf = this->syncgetc();
142  return _M_unget_buf;
143  }
144 
145  virtual int_type
146  pbackfail(int_type __c = traits_type::eof())
147  {
148  int_type __ret;
149  const int_type __eof = traits_type::eof();
150 
151  // Check if the unget or putback was requested
152  if (traits_type::eq_int_type(__c, __eof)) // unget
153  {
154  if (!traits_type::eq_int_type(_M_unget_buf, __eof))
155  __ret = this->syncungetc(_M_unget_buf);
156  else // buffer invalid, fail.
157  __ret = __eof;
158  }
159  else // putback
160  __ret = this->syncungetc(__c);
161 
162  // The buffered character is no longer valid, discard it.
163  _M_unget_buf = __eof;
164  return __ret;
165  }
166 
167  virtual std::streamsize
168  xsgetn(char_type* __s, std::streamsize __n);
169 
170  virtual int_type
171  overflow(int_type __c = traits_type::eof())
172  {
173  int_type __ret;
174  if (traits_type::eq_int_type(__c, traits_type::eof()))
175  {
176  if (std::fflush(_M_file))
177  __ret = traits_type::eof();
178  else
179  __ret = traits_type::not_eof(__c);
180  }
181  else
182  __ret = this->syncputc(__c);
183  return __ret;
184  }
185 
186  virtual std::streamsize
187  xsputn(const char_type* __s, std::streamsize __n);
188 
189  virtual int
191  { return std::fflush(_M_file); }
192 
193  virtual std::streampos
194  seekoff(std::streamoff __off, std::ios_base::seekdir __dir,
195  std::ios_base::openmode = std::ios_base::in | std::ios_base::out)
196  {
197  std::streampos __ret(std::streamoff(-1));
198  int __whence;
199  if (__dir == std::ios_base::beg)
200  __whence = SEEK_SET;
201  else if (__dir == std::ios_base::cur)
202  __whence = SEEK_CUR;
203  else
204  __whence = SEEK_END;
205 #ifdef _GLIBCXX_USE_LFS
206  if (!fseeko64(_M_file, __off, __whence))
207  __ret = std::streampos(ftello64(_M_file));
208 #else
209  if (!fseek(_M_file, __off, __whence))
210  __ret = std::streampos(std::ftell(_M_file));
211 #endif
212  return __ret;
213  }
214 
215  virtual std::streampos
216  seekpos(std::streampos __pos,
217  std::ios_base::openmode __mode =
219  { return seekoff(std::streamoff(__pos), std::ios_base::beg, __mode); }
220  };
221 
222  template<>
223  inline stdio_sync_filebuf<char>::int_type
224  stdio_sync_filebuf<char>::syncgetc()
225  { return std::getc(_M_file); }
226 
227  template<>
228  inline stdio_sync_filebuf<char>::int_type
229  stdio_sync_filebuf<char>::syncungetc(int_type __c)
230  { return std::ungetc(__c, _M_file); }
231 
232  template<>
233  inline stdio_sync_filebuf<char>::int_type
234  stdio_sync_filebuf<char>::syncputc(int_type __c)
235  { return std::putc(__c, _M_file); }
236 
237  template<>
238  inline std::streamsize
239  stdio_sync_filebuf<char>::xsgetn(char* __s, std::streamsize __n)
240  {
241  std::streamsize __ret = std::fread(__s, 1, __n, _M_file);
242  if (__ret > 0)
243  _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]);
244  else
245  _M_unget_buf = traits_type::eof();
246  return __ret;
247  }
248 
249  template<>
250  inline std::streamsize
251  stdio_sync_filebuf<char>::xsputn(const char* __s, std::streamsize __n)
252  { return std::fwrite(__s, 1, __n, _M_file); }
253 
254 #ifdef _GLIBCXX_USE_WCHAR_T
255  template<>
256  inline stdio_sync_filebuf<wchar_t>::int_type
257  stdio_sync_filebuf<wchar_t>::syncgetc()
258  { return std::getwc(_M_file); }
259 
260  template<>
261  inline stdio_sync_filebuf<wchar_t>::int_type
262  stdio_sync_filebuf<wchar_t>::syncungetc(int_type __c)
263  { return std::ungetwc(__c, _M_file); }
264 
265  template<>
266  inline stdio_sync_filebuf<wchar_t>::int_type
267  stdio_sync_filebuf<wchar_t>::syncputc(int_type __c)
268  { return std::putwc(__c, _M_file); }
269 
270  template<>
271  inline std::streamsize
272  stdio_sync_filebuf<wchar_t>::xsgetn(wchar_t* __s, std::streamsize __n)
273  {
274  std::streamsize __ret = 0;
275  const int_type __eof = traits_type::eof();
276  while (__n--)
277  {
278  int_type __c = this->syncgetc();
279  if (traits_type::eq_int_type(__c, __eof))
280  break;
281  __s[__ret] = traits_type::to_char_type(__c);
282  ++__ret;
283  }
284 
285  if (__ret > 0)
286  _M_unget_buf = traits_type::to_int_type(__s[__ret - 1]);
287  else
288  _M_unget_buf = traits_type::eof();
289  return __ret;
290  }
291 
292  template<>
293  inline std::streamsize
294  stdio_sync_filebuf<wchar_t>::xsputn(const wchar_t* __s,
295  std::streamsize __n)
296  {
297  std::streamsize __ret = 0;
298  const int_type __eof = traits_type::eof();
299  while (__n--)
300  {
301  if (traits_type::eq_int_type(this->syncputc(*__s++), __eof))
302  break;
303  ++__ret;
304  }
305  return __ret;
306  }
307 #endif
308 
309 #if _GLIBCXX_EXTERN_TEMPLATE
310  extern template class stdio_sync_filebuf<char>;
311 #ifdef _GLIBCXX_USE_WCHAR_T
312  extern template class stdio_sync_filebuf<wchar_t>;
313 #endif
314 #endif
315 
316 _GLIBCXX_END_NAMESPACE_VERSION
317 } // namespace
318 
319 #endif
static const seekdir cur
Request a seek relative to the current position within the sequence.
Definition: ios_base.h:467
Class representing stream positions.
Definition: postypes.h:112
virtual int_type underflow()
Fetches more data from the controlled sequence.
static const seekdir beg
Request a seek relative to the beginning of the stream.
Definition: ios_base.h:464
static const openmode out
Open for output. Default for ofstream and fstream.
Definition: ios_base.h:446
fpos< mbstate_t > streampos
File position for char streams.
Definition: postypes.h:228
ptrdiff_t streamsize
Integral type for I/O operation counts and buffer sizes.
Definition: postypes.h:98
traits_type::int_type int_type
Definition: streambuf:133
GNU extensions for public use.
The actual work of input and output (interface).
Definition: iosfwd:80
virtual int_type uflow()
Fetches more data from the controlled sequence.
virtual int sync()
Synchronizes the buffer arrays with the controlled sequences.
static const openmode in
Open for input. Default for ifstream and fstream.
Definition: ios_base.h:443
long long streamoff
Type used by fpos, char_traits<char>, and char_traits<wchar_t>.
Definition: postypes.h:94
_Traits traits_type
Definition: streambuf:132
traits_type::pos_type pos_type
Definition: streambuf:134
traits_type::off_type off_type
Definition: streambuf:135
Provides a layer of compatibility for C.This GNU extension provides extensions for working with stand...