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_1_0.txt 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/filebuf.hpp>
13 #include <istream>
14 #include <ostream>
15 
16 namespace boost {
17 namespace nowide {
19  namespace detail {
20  // clang-format off
21  struct StreamTypeIn
22  {
23  static std::ios_base::openmode mode() { return std::ios_base::in; }
24  static std::ios_base::openmode mode_modifier() { return mode(); }
25  template<typename CharType, typename Traits>
26  struct stream_base{
27  typedef std::basic_istream<CharType, Traits> type;
28  };
29  };
30  struct StreamTypeOut
31  {
32  static std::ios_base::openmode mode() { return std::ios_base::out; }
33  static std::ios_base::openmode mode_modifier() { return mode(); }
34  template<typename CharType, typename Traits>
35  struct stream_base{
36  typedef std::basic_ostream<CharType, Traits> type;
37  };
38  };
39  struct StreamTypeInOut
40  {
41  static std::ios_base::openmode mode() { return std::ios_base::in | std::ios_base::out; }
42  static std::ios_base::openmode mode_modifier() { return std::ios_base::openmode(); }
43  template<typename CharType, typename Traits>
44  struct stream_base{
45  typedef std::basic_iostream<CharType, Traits> type;
46  };
47  };
48  // clang-format on
49 
56  template<typename CharType, typename Traits, typename T_StreamType>
57  class fstream_impl;
58 
59  template<typename Path, typename Result>
60  struct enable_if_path;
61  } // namespace detail
63 
67  template<typename CharType, typename Traits = std::char_traits<CharType> >
68  class basic_ifstream : public detail::fstream_impl<CharType, Traits, detail::StreamTypeIn>
69  {
70  typedef detail::fstream_impl<CharType, Traits, detail::StreamTypeIn> fstream_impl;
71 
72  public:
74  {}
75 
76  explicit basic_ifstream(const char* file_name, std::ios_base::openmode mode = std::ios_base::in)
77  {
78  open(file_name, mode);
79  }
80 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
81  explicit basic_ifstream(const wchar_t* file_name, std::ios_base::openmode mode = std::ios_base::in)
82  {
83  open(file_name, mode);
84  }
85 #endif
86 
87  explicit basic_ifstream(const std::string& file_name, std::ios_base::openmode mode = std::ios_base::in)
88  {
89  open(file_name, mode);
90  }
91 
92  template<typename Path>
93  explicit basic_ifstream(
94  const Path& file_name,
95  typename detail::enable_if_path<Path, std::ios_base::openmode>::type mode = std::ios_base::in)
96  {
97  open(file_name, mode);
98  }
99  using fstream_impl::open;
100  using fstream_impl::is_open;
101  using fstream_impl::close;
102  using fstream_impl::rdbuf;
103 #if BOOST_NOWIDE_CXX11
104  using fstream_impl::swap;
105  basic_ifstream(const basic_ifstream& other) = delete;
106  basic_ifstream& operator=(const basic_ifstream& rhs) = delete;
107  basic_ifstream(basic_ifstream&& other) noexcept : fstream_impl(std::move(other))
108  {}
109  basic_ifstream& operator=(basic_ifstream&& rhs) noexcept
110  {
111  fstream_impl::operator=(std::move(rhs));
112  return *this;
113  }
114 #endif
115  };
116 
120 
121  template<typename CharType, typename Traits = std::char_traits<CharType> >
122  class basic_ofstream : public detail::fstream_impl<CharType, Traits, detail::StreamTypeOut>
123  {
124  typedef detail::fstream_impl<CharType, Traits, detail::StreamTypeOut> fstream_impl;
125 
126  public:
128  {}
129  explicit basic_ofstream(const char* file_name, std::ios_base::openmode mode = std::ios_base::out)
130  {
131  open(file_name, mode);
132  }
133 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
134  explicit basic_ofstream(const wchar_t* file_name, std::ios_base::openmode mode = std::ios_base::out)
135  {
136  open(file_name, mode);
137  }
138 #endif
139  explicit basic_ofstream(const std::string& file_name, std::ios_base::openmode mode = std::ios_base::out)
140  {
141  open(file_name, mode);
142  }
143  template<typename Path>
144  explicit basic_ofstream(
145  const Path& file_name,
146  typename detail::enable_if_path<Path, std::ios_base::openmode>::type mode = std::ios_base::out)
147  {
148  open(file_name, mode);
149  }
150 
151  using fstream_impl::open;
152  using fstream_impl::is_open;
153  using fstream_impl::close;
154  using fstream_impl::rdbuf;
155 #if BOOST_NOWIDE_CXX11
156  using fstream_impl::swap;
157  basic_ofstream(const basic_ofstream& other) = delete;
158  basic_ofstream& operator=(const basic_ofstream& rhs) = 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 #endif
167  };
168 
169 #ifdef BOOST_MSVC
170 #pragma warning(push)
171 #pragma warning(disable : 4250) // <class> : inherits <method> via dominance
172 #endif
173  template<typename CharType, typename Traits = std::char_traits<CharType> >
177  class basic_fstream : public detail::fstream_impl<CharType, Traits, detail::StreamTypeInOut>
178  {
179  typedef detail::fstream_impl<CharType, Traits, detail::StreamTypeInOut> fstream_impl;
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  typename detail::enable_if_path<Path, std::ios_base::openmode>::type mode =
204  std::ios_base::in | 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 #if BOOST_NOWIDE_CXX11
214  using fstream_impl::swap;
215  basic_fstream(const basic_fstream& other) = delete;
216  basic_fstream& operator=(const basic_fstream& rhs) = delete;
217  basic_fstream(basic_fstream&& other) noexcept : fstream_impl(std::move(other))
218  {}
219  basic_fstream& operator=(basic_fstream&& rhs)
220  {
221  fstream_impl::operator=(std::move(rhs));
222  return *this;
223  }
224 #endif
225  };
226 #if BOOST_NOWIDE_CXX11
227  template<typename CharType, typename Traits>
229  {
230  lhs.swap(rhs);
231  }
232  template<typename CharType, typename Traits>
233  void swap(basic_ifstream<CharType, Traits>& lhs, basic_ifstream<CharType, Traits>& rhs)
234  {
235  lhs.swap(rhs);
236  }
237  template<typename CharType, typename Traits>
238  void swap(basic_ofstream<CharType, Traits>& lhs, basic_ofstream<CharType, Traits>& rhs)
239  {
240  lhs.swap(rhs);
241  }
242  template<typename CharType, typename Traits>
243  void swap(basic_fstream<CharType, Traits>& lhs, basic_fstream<CharType, Traits>& rhs)
244  {
245  lhs.swap(rhs);
246  }
247 #endif
248 
252  typedef basic_filebuf<char> filebuf;
268 
269  // Implementation
270  namespace detail {
273  template<typename T>
274  struct buf_holder
275  {
276  T buf_;
277  };
278  template<typename CharType, typename Traits, typename T_StreamType>
279  class fstream_impl : private buf_holder<basic_filebuf<CharType, Traits> >, // must be first due to init order
280  public T_StreamType::template stream_base<CharType, Traits>::type
281  {
282  typedef basic_filebuf<CharType, Traits> internal_buffer_type;
283  typedef buf_holder<internal_buffer_type> base_buf_holder;
284  typedef typename T_StreamType::template stream_base<CharType, Traits>::type stream_base;
285 
286  public:
287  using stream_base::setstate;
288  using stream_base::clear;
289 
290  protected:
291  using base_buf_holder::buf_;
292 
293  fstream_impl() : stream_base(&buf_)
294  {}
295 
296 #if BOOST_NOWIDE_CXX11
297  fstream_impl(const fstream_impl& other) = delete;
298  fstream_impl& operator=(const fstream_impl& other) = delete;
299 
300  // coverity[exn_spec_violation]
301  fstream_impl(fstream_impl&& other) noexcept : base_buf_holder(std::move(other)),
302  stream_base(std::move(other))
303  {
304  this->set_rdbuf(rdbuf());
305  }
306  fstream_impl& operator=(fstream_impl&& rhs) noexcept
307  {
308  base_buf_holder::operator=(std::move(rhs));
309  stream_base::operator=(std::move(rhs));
310  return *this;
311  }
312  void swap(fstream_impl& other)
313  {
314  stream_base::swap(other);
315  rdbuf()->swap(*other.rdbuf());
316  }
317 #endif
318 
319  void open(const std::string& file_name, std::ios_base::openmode mode = T_StreamType::mode())
320  {
321  open(file_name.c_str(), mode);
322  }
323  template<typename Path>
324  typename detail::enable_if_path<Path, void>::type open(const Path& file_name,
325  std::ios_base::openmode mode = T_StreamType::mode())
326  {
327  open(file_name.c_str(), mode);
328  }
329  void open(const char* file_name, std::ios_base::openmode mode = T_StreamType::mode())
330  {
331  if(!rdbuf()->open(file_name, mode | T_StreamType::mode_modifier()))
332  setstate(std::ios_base::failbit);
333  else
334  clear();
335  }
336 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
337  void open(const wchar_t* file_name, std::ios_base::openmode mode = T_StreamType::mode())
338  {
339  if(!rdbuf()->open(file_name, mode | T_StreamType::mode_modifier()))
340  setstate(std::ios_base::failbit);
341  else
342  clear();
343  }
344 #endif
345  bool is_open()
346  {
347  return rdbuf()->is_open();
348  }
349  bool is_open() const
350  {
351  return rdbuf()->is_open();
352  }
353  void close()
354  {
355  if(!rdbuf()->close())
356  setstate(std::ios_base::failbit);
357  }
358 
359  internal_buffer_type* rdbuf() const
360  {
361  return const_cast<internal_buffer_type*>(&buf_);
362  }
363  };
364 #ifdef BOOST_MSVC
365 #pragma warning(pop)
366 #endif
367  template<typename T>
370  struct is_path
371  {
372  typedef char one;
373  struct two
374  {
375  char dummy[2];
376  };
377 
378  template<typename U, U& (U::*)(), U (U::*)() const>
379  struct Check;
380  template<typename U>
381  static one test(Check<U, &U::make_preferred, &U::filename>*);
382  template<typename U>
383  static two test(...);
384 
385  enum
386  {
387  value = sizeof(test<T>(0)) == sizeof(one)
388  };
389  };
390  template<bool B, typename T>
391  struct enable_if
392  {};
393  template<typename T>
394  struct enable_if<true, T>
395  {
396  typedef T type;
397  };
399  template<typename Path, typename Result>
400  struct enable_if_path : enable_if<is_path<Path>::value, Result>
401  {};
402  } // namespace detail
403 } // namespace nowide
404 } // namespace boost
405 
406 #endif
basic_ifstream< char > ifstream
Definition: fstream.hpp:257
basic_filebuf< char > filebuf
Convenience typedef.
Definition: filebuf.hpp:458
Same as std::basic_ifstream<char> but accepts UTF-8 strings under Windows.
Definition: fstream.hpp:68
basic_ofstream< char > ofstream
Definition: fstream.hpp:262
This forward declaration defines the basic_filebuf type.
Definition: filebuf.hpp:40
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:122
basic_fstream< char > fstream
Definition: fstream.hpp:267