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