]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/nowide/fstream.hpp
5a8945c8b40fc1378c4155762d46d32a897ede47
[ceph.git] / ceph / src / boost / 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 {
20 /// \cond INTERNAL
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
52 /// Base class for all basic_*fstream classes
53 /// Contains basic_filebuf instance so its pointer can be used to construct basic_*stream
54 /// Provides common functions to reduce boilerplate code including inheriting from
55 /// the correct std::basic_[io]stream class and initializing it
56 /// \tparam T_StreamType One of StreamType* above.
57 /// Class used instead of value, because openmode::operator| may not be constexpr
58 /// \tparam FileBufType Discriminator to force a differing ABI if depending on the contained filebuf
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
66 /// \endcond
67
68 ///
69 /// \brief Same as std::basic_ifstream<char> but accepts UTF-8 strings under Windows
70 ///
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:
77 basic_ifstream()
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
118 ///
119 /// \brief Same as std::basic_ofstream<char> but accepts UTF-8 strings under Windows
120 ///
121
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:
128 basic_ofstream()
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
171 ///
172 /// \brief Same as std::basic_fstream<char> but accepts UTF-8 strings under Windows
173 ///
174 template<typename CharType, typename Traits = std::char_traits<CharType>>
175 class basic_fstream : public detail::fstream_impl<CharType, Traits, detail::StreamTypeInOut>
176 {
177 using fstream_impl = detail::fstream_impl<CharType, Traits, detail::StreamTypeInOut>;
178
179 public:
180 basic_fstream()
181 {}
182 explicit basic_fstream(const char* file_name,
183 std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
184 {
185 open(file_name, mode);
186 }
187 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
188 explicit basic_fstream(const wchar_t* file_name,
189 std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
190 {
191 open(file_name, mode);
192 }
193 #endif
194 explicit basic_fstream(const std::string& file_name,
195 std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out)
196 {
197 open(file_name, mode);
198 }
199 template<typename Path>
200 explicit basic_fstream(const Path& file_name,
201 detail::enable_if_path_t<Path, std::ios_base::openmode> mode = std::ios_base::in
202 | std::ios_base::out)
203 {
204 open(file_name, mode);
205 }
206
207 using fstream_impl::open;
208 using fstream_impl::is_open;
209 using fstream_impl::close;
210 using fstream_impl::rdbuf;
211 using fstream_impl::swap;
212 basic_fstream(const basic_fstream&) = delete;
213 basic_fstream& operator=(const basic_fstream&) = delete;
214 basic_fstream(basic_fstream&& other) noexcept : fstream_impl(std::move(other))
215 {}
216 basic_fstream& operator=(basic_fstream&& rhs)
217 {
218 fstream_impl::operator=(std::move(rhs));
219 return *this;
220 }
221 };
222 template<typename CharType, typename Traits>
223 void swap(basic_filebuf<CharType, Traits>& lhs, basic_filebuf<CharType, Traits>& rhs)
224 {
225 lhs.swap(rhs);
226 }
227 template<typename CharType, typename Traits>
228 void swap(basic_ifstream<CharType, Traits>& lhs, basic_ifstream<CharType, Traits>& rhs)
229 {
230 lhs.swap(rhs);
231 }
232 template<typename CharType, typename Traits>
233 void swap(basic_ofstream<CharType, Traits>& lhs, basic_ofstream<CharType, Traits>& rhs)
234 {
235 lhs.swap(rhs);
236 }
237 template<typename CharType, typename Traits>
238 void swap(basic_fstream<CharType, Traits>& lhs, basic_fstream<CharType, Traits>& rhs)
239 {
240 lhs.swap(rhs);
241 }
242
243 ///
244 /// Same as std::filebuf but accepts UTF-8 strings under Windows
245 ///
246 using filebuf = basic_filebuf<char>;
247 ///
248 /// Same as std::ifstream but accepts UTF-8 strings under Windows
249 /// and *\::filesystem::path on all systems
250 ///
251 using ifstream = basic_ifstream<char>;
252 ///
253 /// Same as std::ofstream but accepts UTF-8 strings under Windows
254 /// and *\::filesystem::path on all systems
255 ///
256 using ofstream = basic_ofstream<char>;
257 ///
258 /// Same as std::fstream but accepts UTF-8 strings under Windows
259 /// and *\::filesystem::path on all systems
260 ///
261 using fstream = basic_fstream<char>;
262
263 // Implementation
264 namespace detail {
265 /// Holds an instance of T
266 /// Required to make sure this is constructed first before passing it to sibling classes
267 template<typename T>
268 struct buf_holder
269 {
270 T buf_;
271 };
272 template<typename CharType, typename Traits, typename T_StreamType, int>
273 class fstream_impl : private buf_holder<basic_filebuf<CharType, Traits>>, // must be first due to init order
274 public T_StreamType::template stream_base<CharType, Traits>::type
275 {
276 using internal_buffer_type = basic_filebuf<CharType, Traits>;
277 using base_buf_holder = buf_holder<internal_buffer_type>;
278 using stream_base = typename T_StreamType::template stream_base<CharType, Traits>::type;
279
280 public:
281 using stream_base::setstate;
282 using stream_base::clear;
283
284 protected:
285 using base_buf_holder::buf_;
286
287 fstream_impl() : stream_base(&buf_)
288 {}
289 fstream_impl(const fstream_impl&) = delete;
290 fstream_impl& operator=(const fstream_impl&) = delete;
291
292 // coverity[exn_spec_violation]
293 fstream_impl(fstream_impl&& other) noexcept :
294 base_buf_holder(std::move(other)), stream_base(std::move(other))
295 {
296 this->set_rdbuf(rdbuf());
297 }
298 fstream_impl& operator=(fstream_impl&& rhs) noexcept
299 {
300 base_buf_holder::operator=(std::move(rhs));
301 stream_base::operator=(std::move(rhs));
302 return *this;
303 }
304 void swap(fstream_impl& other)
305 {
306 stream_base::swap(other);
307 rdbuf()->swap(*other.rdbuf());
308 }
309
310 void open(const std::string& file_name, std::ios_base::openmode mode = T_StreamType::mode())
311 {
312 open(file_name.c_str(), mode);
313 }
314 template<typename Path>
315 detail::enable_if_path_t<Path, void> open(const Path& file_name,
316 std::ios_base::openmode mode = T_StreamType::mode())
317 {
318 open(file_name.c_str(), mode);
319 }
320 void open(const char* file_name, std::ios_base::openmode mode = T_StreamType::mode())
321 {
322 if(!rdbuf()->open(file_name, mode | T_StreamType::mode_modifier()))
323 setstate(std::ios_base::failbit);
324 else
325 clear();
326 }
327 #if BOOST_NOWIDE_USE_WCHAR_OVERLOADS
328 void open(const wchar_t* file_name, std::ios_base::openmode mode = T_StreamType::mode())
329 {
330 if(!rdbuf()->open(file_name, mode | T_StreamType::mode_modifier()))
331 setstate(std::ios_base::failbit);
332 else
333 clear();
334 }
335 #endif
336 bool is_open()
337 {
338 return rdbuf()->is_open();
339 }
340 bool is_open() const
341 {
342 return rdbuf()->is_open();
343 }
344 void close()
345 {
346 if(!rdbuf()->close())
347 setstate(std::ios_base::failbit);
348 }
349
350 internal_buffer_type* rdbuf() const
351 {
352 return const_cast<internal_buffer_type*>(&buf_);
353 }
354 };
355 #ifdef BOOST_MSVC
356 #pragma warning(pop)
357 #endif
358 } // namespace detail
359 } // namespace nowide
360 } // namespace boost
361
362 #endif