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