Boost.Nowide
fstream.hpp
1 //
2 // Copyright (c) 2012 Artyom Beilis (Tonkikh)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //
8 #ifndef BOOST_NOWIDE_FSTREAM_HPP_INCLUDED
9 #define BOOST_NOWIDE_FSTREAM_HPP_INCLUDED
10 
11 #include <boost/nowide/config.hpp>
12 #include <boost/nowide/detail/is_path.hpp>
13 #include <boost/nowide/filebuf.hpp>
14 #include <istream>
15 #include <ostream>
16 #include <utility>
17 
18 namespace boost {
19 namespace nowide {
21  namespace detail {
22  // clang-format off
23  struct StreamTypeIn
24  {
25  static std::ios_base::openmode mode() { return std::ios_base::in; }
26  static std::ios_base::openmode mode_modifier() { return mode(); }
27  template<typename CharType, typename Traits>
28  struct stream_base{
29  using type = std::basic_istream<CharType, Traits>;
30  };
31  };
32  struct StreamTypeOut
33  {
34  static std::ios_base::openmode mode() { return std::ios_base::out; }
35  static std::ios_base::openmode mode_modifier() { return mode(); }
36  template<typename CharType, typename Traits>
37  struct stream_base{
38  using type = std::basic_ostream<CharType, Traits>;
39  };
40  };
41  struct StreamTypeInOut
42  {
43  static std::ios_base::openmode mode() { return std::ios_base::in | std::ios_base::out; }
44  static std::ios_base::openmode mode_modifier() { return std::ios_base::openmode(); }
45  template<typename CharType, typename Traits>
46  struct stream_base{
47  using type = std::basic_iostream<CharType, Traits>;
48  };
49  };
50  // clang-format on
51 
59  template<typename CharType,
60  typename Traits,
61  typename T_StreamType,
62  int FileBufType = BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT>
63  class fstream_impl;
64 
65  } // namespace detail
67 
72  template<typename CharType, typename Traits = std::char_traits<CharType>>
73  class basic_ifstream : public detail::fstream_impl<CharType, Traits, detail::StreamTypeIn>
74  {
75  using fstream_impl = detail::fstream_impl<CharType, Traits, detail::StreamTypeIn>;
76 
77  public:
79  {}
80 
81  explicit basic_ifstream(const char* file_name, std::ios_base::openmode mode = std::ios_base::in)
82  {
83  open(file_name, mode);
84  }
85 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
86  explicit basic_ifstream(const wchar_t* file_name, std::ios_base::openmode mode = std::ios_base::in)
87  {
88  open(file_name, mode);
89  }
90 #endif
91 
92  explicit basic_ifstream(const std::string& file_name, std::ios_base::openmode mode = std::ios_base::in)
93  {
94  open(file_name, mode);
95  }
96 
97  template<typename Path>
98  explicit basic_ifstream(const Path& file_name,
99  detail::enable_if_path_t<Path, std::ios_base::openmode> mode = std::ios_base::in)
100  {
101  open(file_name, mode);
102  }
103  using fstream_impl::open;
104  using fstream_impl::is_open;
105  using fstream_impl::close;
106  using fstream_impl::rdbuf;
107  using fstream_impl::swap;
108  basic_ifstream(const basic_ifstream&) = delete;
109  basic_ifstream& operator=(const basic_ifstream&) = delete;
110  basic_ifstream(basic_ifstream&& other) noexcept : fstream_impl(std::move(other))
111  {}
112  basic_ifstream& operator=(basic_ifstream&& rhs) noexcept
113  {
114  fstream_impl::operator=(std::move(rhs));
115  return *this;
116  }
117  };
118 
123  template<typename CharType, typename Traits = std::char_traits<CharType>>
124  class basic_ofstream : public detail::fstream_impl<CharType, Traits, detail::StreamTypeOut>
125  {
126  using fstream_impl = detail::fstream_impl<CharType, Traits, detail::StreamTypeOut>;
127 
128  public:
130  {}
131  explicit basic_ofstream(const char* file_name, std::ios_base::openmode mode = std::ios_base::out)
132  {
133  open(file_name, mode);
134  }
135 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
136  explicit basic_ofstream(const wchar_t* file_name, std::ios_base::openmode mode = std::ios_base::out)
137  {
138  open(file_name, mode);
139  }
140 #endif
141  explicit basic_ofstream(const std::string& file_name, std::ios_base::openmode mode = std::ios_base::out)
142  {
143  open(file_name, mode);
144  }
145  template<typename Path>
146  explicit basic_ofstream(const Path& file_name,
147  detail::enable_if_path_t<Path, std::ios_base::openmode> mode = std::ios_base::out)
148  {
149  open(file_name, mode);
150  }
151 
152  using fstream_impl::open;
153  using fstream_impl::is_open;
154  using fstream_impl::close;
155  using fstream_impl::rdbuf;
156  using fstream_impl::swap;
157  basic_ofstream(const basic_ofstream&) = delete;
158  basic_ofstream& operator=(const basic_ofstream&) = delete;
159  basic_ofstream(basic_ofstream&& other) noexcept : fstream_impl(std::move(other))
160  {}
161  basic_ofstream& operator=(basic_ofstream&& rhs)
162  {
163  fstream_impl::operator=(std::move(rhs));
164  return *this;
165  }
166  };
167 
168 #ifdef BOOST_MSVC
169 #pragma warning(push)
170 #pragma warning(disable : 4250) // <class> : inherits <method> via dominance
171 #endif
172  template<typename CharType, typename Traits = std::char_traits<CharType>>
177  class basic_fstream : public detail::fstream_impl<CharType, Traits, detail::StreamTypeInOut>
178  {
179  using fstream_impl = detail::fstream_impl<CharType, Traits, detail::StreamTypeInOut>;
180 
181  public:
182  basic_fstream()
183  {}
184  explicit basic_fstream(const char* file_name,
185  std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
186  {
187  open(file_name, mode);
188  }
189 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
190  explicit basic_fstream(const wchar_t* file_name,
191  std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
192  {
193  open(file_name, mode);
194  }
195 #endif
196  explicit basic_fstream(const std::string& file_name,
197  std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
198  {
199  open(file_name, mode);
200  }
201  template<typename Path>
202  explicit basic_fstream(const Path& file_name,
203  detail::enable_if_path_t<Path, std::ios_base::openmode> mode = std::ios_base::in
204  | std::ios_base::out)
205  {
206  open(file_name, mode);
207  }
208 
209  using fstream_impl::open;
210  using fstream_impl::is_open;
211  using fstream_impl::close;
212  using fstream_impl::rdbuf;
213  using fstream_impl::swap;
214  basic_fstream(const basic_fstream&) = delete;
215  basic_fstream& operator=(const basic_fstream&) = delete;
216  basic_fstream(basic_fstream&& other) noexcept : fstream_impl(std::move(other))
217  {}
218  basic_fstream& operator=(basic_fstream&& rhs)
219  {
220  fstream_impl::operator=(std::move(rhs));
221  return *this;
222  }
223  };
224 
225  template<typename CharType, typename Traits>
227  {
228  lhs.swap(rhs);
229  }
230  template<typename CharType, typename Traits>
231  void swap(basic_ofstream<CharType, Traits>& lhs, basic_ofstream<CharType, Traits>& rhs)
232  {
233  lhs.swap(rhs);
234  }
235  template<typename CharType, typename Traits>
236  void swap(basic_fstream<CharType, Traits>& lhs, basic_fstream<CharType, Traits>& rhs)
237  {
238  lhs.swap(rhs);
239  }
240 
244  using filebuf = basic_filebuf<char>;
260 
261  // Implementation
262  namespace detail {
265  template<typename T>
266  struct buf_holder
267  {
268  T buf_;
269  };
270  template<typename CharType, typename Traits, typename T_StreamType, int>
271  class fstream_impl : private buf_holder<basic_filebuf<CharType, Traits>>, // must be first due to init order
272  public T_StreamType::template stream_base<CharType, Traits>::type
273  {
274  using internal_buffer_type = basic_filebuf<CharType, Traits>;
275  using base_buf_holder = buf_holder<internal_buffer_type>;
276  using stream_base = typename T_StreamType::template stream_base<CharType, Traits>::type;
277 
278  public:
279  using stream_base::setstate;
280  using stream_base::clear;
281 
282  protected:
283  using base_buf_holder::buf_;
284 
285  fstream_impl() : stream_base(&buf_)
286  {}
287  fstream_impl(const fstream_impl&) = delete;
288  fstream_impl& operator=(const fstream_impl&) = delete;
289 
290  // coverity[exn_spec_violation]
291  fstream_impl(fstream_impl&& other) noexcept :
292  base_buf_holder(std::move(other)), stream_base(std::move(other))
293  {
294  this->set_rdbuf(rdbuf());
295  }
296  fstream_impl& operator=(fstream_impl&& rhs) noexcept
297  {
298  base_buf_holder::operator=(std::move(rhs));
299  stream_base::operator=(std::move(rhs));
300  return *this;
301  }
302  void swap(fstream_impl& other)
303  {
304  stream_base::swap(other);
305  rdbuf()->swap(*other.rdbuf());
306  }
307 
308  void open(const std::string& file_name, std::ios_base::openmode mode = T_StreamType::mode())
309  {
310  open(file_name.c_str(), mode);
311  }
312  template<typename Path>
313  detail::enable_if_path_t<Path, void> open(const Path& file_name,
314  std::ios_base::openmode mode = T_StreamType::mode())
315  {
316  open(file_name.c_str(), mode);
317  }
318  void open(const char* file_name, std::ios_base::openmode mode = T_StreamType::mode())
319  {
320  if(!rdbuf()->open(file_name, mode | T_StreamType::mode_modifier()))
321  setstate(std::ios_base::failbit);
322  else
323  clear();
324  }
325 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
326  void open(const wchar_t* file_name, std::ios_base::openmode mode = T_StreamType::mode())
327  {
328  if(!rdbuf()->open(file_name, mode | T_StreamType::mode_modifier()))
329  setstate(std::ios_base::failbit);
330  else
331  clear();
332  }
333 #endif
334  bool is_open()
335  {
336  return rdbuf()->is_open();
337  }
338  bool is_open() const
339  {
340  return rdbuf()->is_open();
341  }
342  void close()
343  {
344  if(!rdbuf()->close())
345  setstate(std::ios_base::failbit);
346  }
347 
348  internal_buffer_type* rdbuf() const
349  {
350  return const_cast<internal_buffer_type*>(&buf_);
351  }
352  };
353 #ifdef BOOST_MSVC
354 #pragma warning(pop)
355 #endif
356  } // namespace detail
357 } // namespace nowide
358 } // namespace boost
359 
360 #endif
basic_filebuf< char > filebuf
Convenience typedef.
Definition: filebuf.hpp:533
Same as std::basic_ifstream<char> but accepts UTF-8 strings under Windows.
Definition: fstream.hpp:73
This forward declaration defines the basic_filebuf type which is used when BOOST_NOWIDE_USE_FILEBUF_R...
Definition: filebuf.hpp:49
Same as std::basic_fstream<char> but accepts UTF-8 strings under Windows.
Definition: fstream.hpp:177
Same as std::basic_ofstream<char> but accepts UTF-8 strings under Windows.
Definition: fstream.hpp:124
#define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT
Define to 1 to use the class from <filebuf.hpp> that is used on Windows.
Definition: config.hpp:77
void swap(basic_filebuf< CharType, Traits > &lhs, basic_filebuf< CharType, Traits > &rhs)
Swap the basic_filebuf instances.
Definition: filebuf.hpp:537