1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_FSTREAM
11#define _LIBCPP_FSTREAM
12
13/*
14 fstream synopsis
15
16template <class charT, class traits = char_traits<charT> >
17class basic_filebuf
18 : public basic_streambuf<charT, traits>
19{
20public:
21 typedef charT char_type;
22 typedef traits traits_type;
23 typedef typename traits_type::int_type int_type;
24 typedef typename traits_type::pos_type pos_type;
25 typedef typename traits_type::off_type off_type;
26
27 // 27.9.1.2 Constructors/destructor:
28 basic_filebuf();
29 basic_filebuf(basic_filebuf&& rhs);
30 virtual ~basic_filebuf();
31
32 // 27.9.1.3 Assign/swap:
33 basic_filebuf& operator=(basic_filebuf&& rhs);
34 void swap(basic_filebuf& rhs);
35
36 // 27.9.1.4 Members:
37 bool is_open() const;
38 basic_filebuf* open(const char* s, ios_base::openmode mode);
39 basic_filebuf* open(const string& s, ios_base::openmode mode);
40 basic_filebuf* open(const filesystem::path& p, ios_base::openmode mode); // C++17
41 basic_filebuf* close();
42
43protected:
44 // 27.9.1.5 Overridden virtual functions:
45 virtual streamsize showmanyc();
46 virtual int_type underflow();
47 virtual int_type uflow();
48 virtual int_type pbackfail(int_type c = traits_type::eof());
49 virtual int_type overflow (int_type c = traits_type::eof());
50 virtual basic_streambuf<char_type, traits_type>* setbuf(char_type* s, streamsize n);
51 virtual pos_type seekoff(off_type off, ios_base::seekdir way,
52 ios_base::openmode which = ios_base::in | ios_base::out);
53 virtual pos_type seekpos(pos_type sp,
54 ios_base::openmode which = ios_base::in | ios_base::out);
55 virtual int sync();
56 virtual void imbue(const locale& loc);
57};
58
59template <class charT, class traits>
60 void
61 swap(basic_filebuf<charT, traits>& x, basic_filebuf<charT, traits>& y);
62
63typedef basic_filebuf<char> filebuf;
64typedef basic_filebuf<wchar_t> wfilebuf;
65
66template <class charT, class traits = char_traits<charT> >
67class basic_ifstream
68 : public basic_istream<charT,traits>
69{
70public:
71 typedef charT char_type;
72 typedef traits traits_type;
73 typedef typename traits_type::int_type int_type;
74 typedef typename traits_type::pos_type pos_type;
75 typedef typename traits_type::off_type off_type;
76 using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; // Since C++26
77
78 basic_ifstream();
79 explicit basic_ifstream(const char* s, ios_base::openmode mode = ios_base::in);
80 explicit basic_ifstream(const string& s, ios_base::openmode mode = ios_base::in);
81 template<class T>
82 explicit basic_ifstream(const T& s, ios_base::openmode mode = ios_base::in); // Since C++17
83 basic_ifstream(basic_ifstream&& rhs);
84
85 basic_ifstream& operator=(basic_ifstream&& rhs);
86 void swap(basic_ifstream& rhs);
87
88 basic_filebuf<char_type, traits_type>* rdbuf() const;
89 native_handle_type native_handle() const noexcept; // Since C++26
90 bool is_open() const;
91 void open(const char* s, ios_base::openmode mode = ios_base::in);
92 void open(const string& s, ios_base::openmode mode = ios_base::in);
93 void open(const filesystem::path& s, ios_base::openmode mode = ios_base::in); // C++17
94
95 void close();
96};
97
98template <class charT, class traits>
99 void
100 swap(basic_ifstream<charT, traits>& x, basic_ifstream<charT, traits>& y);
101
102typedef basic_ifstream<char> ifstream;
103typedef basic_ifstream<wchar_t> wifstream;
104
105template <class charT, class traits = char_traits<charT> >
106class basic_ofstream
107 : public basic_ostream<charT,traits>
108{
109public:
110 typedef charT char_type;
111 typedef traits traits_type;
112 typedef typename traits_type::int_type int_type;
113 typedef typename traits_type::pos_type pos_type;
114 typedef typename traits_type::off_type off_type;
115 using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; // Since C++26
116
117 basic_ofstream();
118 explicit basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out);
119 explicit basic_ofstream(const string& s, ios_base::openmode mode = ios_base::out);
120 template<class T>
121 explicit basic_ofstream(const T& s, ios_base::openmode mode = ios_base::out); // Since C++17
122 basic_ofstream(basic_ofstream&& rhs);
123
124 basic_ofstream& operator=(basic_ofstream&& rhs);
125 void swap(basic_ofstream& rhs);
126
127 basic_filebuf<char_type, traits_type>* rdbuf() const;
128 native_handle_type native_handle() const noexcept; // Since C++26
129
130 bool is_open() const;
131 void open(const char* s, ios_base::openmode mode = ios_base::out);
132 void open(const string& s, ios_base::openmode mode = ios_base::out);
133 void open(const filesystem::path& p,
134 ios_base::openmode mode = ios_base::out); // C++17
135
136 void close();
137};
138
139template <class charT, class traits>
140 void
141 swap(basic_ofstream<charT, traits>& x, basic_ofstream<charT, traits>& y);
142
143typedef basic_ofstream<char> ofstream;
144typedef basic_ofstream<wchar_t> wofstream;
145
146template <class charT, class traits=char_traits<charT> >
147class basic_fstream
148 : public basic_iostream<charT,traits>
149{
150public:
151 typedef charT char_type;
152 typedef traits traits_type;
153 typedef typename traits_type::int_type int_type;
154 typedef typename traits_type::pos_type pos_type;
155 typedef typename traits_type::off_type off_type;
156 using native_handle_type = typename basic_filebuf<charT, traits>::native_handle_type; // Since C++26
157
158 basic_fstream();
159 explicit basic_fstream(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out);
160 explicit basic_fstream(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out);
161 template<class T>
162 explicit basic_fstream(const T& s, ios_base::openmode mode = ios_base::in | ios_base::out); // Since C++17
163 basic_fstream(basic_fstream&& rhs);
164
165 basic_fstream& operator=(basic_fstream&& rhs);
166 void swap(basic_fstream& rhs);
167
168 basic_filebuf<char_type, traits_type>* rdbuf() const;
169 native_handle_type native_handle() const noexcept; // Since C++26
170 bool is_open() const;
171 void open(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out);
172 void open(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out);
173 void open(const filesystem::path& s,
174 ios_base::openmode mode = ios_base::in|ios_base::out); // C++17
175
176 void close();
177};
178
179template <class charT, class traits>
180 void swap(basic_fstream<charT, traits>& x, basic_fstream<charT, traits>& y);
181
182typedef basic_fstream<char> fstream;
183typedef basic_fstream<wchar_t> wfstream;
184
185} // std
186
187*/
188
189#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
190# include <__cxx03/fstream>
191#else
192# include <__config>
193
194# if _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
195
196# include <__algorithm/max.h>
197# include <__assert>
198# include <__filesystem/path.h>
199# include <__fwd/fstream.h>
200# include <__locale>
201# include <__memory/addressof.h>
202# include <__memory/unique_ptr.h>
203# include <__ostream/basic_ostream.h>
204# include <__type_traits/enable_if.h>
205# include <__type_traits/is_same.h>
206# include <__utility/move.h>
207# include <__utility/swap.h>
208# include <__utility/unreachable.h>
209# include <cstdio>
210# include <istream>
211# include <streambuf>
212# include <typeinfo>
213# include <version>
214
215# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
216# pragma GCC system_header
217# endif
218
219_LIBCPP_PUSH_MACROS
220# include <__undef_macros>
221
222_LIBCPP_BEGIN_NAMESPACE_STD
223_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
224
225# if _LIBCPP_STD_VER >= 23 && defined(_LIBCPP_WIN32API)
226_LIBCPP_EXPORTED_FROM_ABI void* __filebuf_windows_native_handle(FILE* __file) noexcept;
227# endif
228
229template <class _CharT, class _Traits>
230class basic_filebuf : public basic_streambuf<_CharT, _Traits> {
231public:
232 typedef _CharT char_type;
233 typedef _Traits traits_type;
234 typedef typename traits_type::int_type int_type;
235 typedef typename traits_type::pos_type pos_type;
236 typedef typename traits_type::off_type off_type;
237 typedef typename traits_type::state_type state_type;
238# if _LIBCPP_STD_VER >= 26
239# if defined(_LIBCPP_WIN32API)
240 using native_handle_type = void*; // HANDLE
241# elif __has_include(<unistd.h>)
242 using native_handle_type = int; // POSIX file descriptor
243# else
244# error "Provide a native file handle!"
245# endif
246# endif
247
248 // 27.9.1.2 Constructors/destructor:
249 basic_filebuf();
250 basic_filebuf(basic_filebuf&& __rhs);
251 ~basic_filebuf() override;
252
253 // 27.9.1.3 Assign/swap:
254 _LIBCPP_HIDE_FROM_ABI basic_filebuf& operator=(basic_filebuf&& __rhs);
255 void swap(basic_filebuf& __rhs);
256
257 // 27.9.1.4 Members:
258 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_open() const;
259 basic_filebuf* open(const char* __s, ios_base::openmode __mode);
260# if _LIBCPP_HAS_OPEN_WITH_WCHAR
261 basic_filebuf* open(const wchar_t* __s, ios_base::openmode __mode);
262# endif
263 _LIBCPP_HIDE_FROM_ABI basic_filebuf* open(const string& __s, ios_base::openmode __mode);
264
265# if _LIBCPP_STD_VER >= 17
266 _LIBCPP_HIDE_FROM_ABI basic_filebuf* open(const filesystem::path& __p, ios_base::openmode __mode) {
267 return open(__p.c_str(), __mode);
268 }
269# endif
270 _LIBCPP_HIDE_FROM_ABI basic_filebuf* __open(int __fd, ios_base::openmode __mode);
271 basic_filebuf* close();
272# if _LIBCPP_STD_VER >= 26
273 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
274 _LIBCPP_ASSERT_UNCATEGORIZED(this->is_open(), "File must be opened");
275# if defined(_LIBCPP_WIN32API)
276 return std::__filebuf_windows_native_handle(__file_);
277# elif __has_include(<unistd.h>)
278 return fileno(stream: __file_);
279# else
280# error "Provide a way to determine the file native handle!"
281# endif
282 }
283# endif // _LIBCPP_STD_VER >= 26
284
285 _LIBCPP_HIDE_FROM_ABI inline static const char* __make_mdstring(ios_base::openmode __mode) _NOEXCEPT;
286# if _LIBCPP_HAS_OPEN_WITH_WCHAR
287 _LIBCPP_HIDE_FROM_ABI inline static const wchar_t* __make_mdwstring(ios_base::openmode __mode) _NOEXCEPT;
288# endif
289
290protected:
291 // 27.9.1.5 Overridden virtual functions:
292 int_type underflow() override;
293 int_type pbackfail(int_type __c = traits_type::eof()) override;
294 int_type overflow(int_type __c = traits_type::eof()) override;
295 basic_streambuf<char_type, traits_type>* setbuf(char_type* __s, streamsize __n) override;
296 pos_type
297 seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __wch = ios_base::in | ios_base::out) override;
298 pos_type seekpos(pos_type __sp, ios_base::openmode __wch = ios_base::in | ios_base::out) override;
299 int sync() override;
300 void imbue(const locale& __loc) override;
301
302 _LIBCPP_HIDE_FROM_ABI_VIRTUAL streamsize xsputn(const char_type* __str, streamsize __len) override {
303 if (__always_noconv_ && __len >= (this->epptr() - this->pbase())) {
304 if (traits_type::eq_int_type(overflow(), traits_type::eof()))
305 return 0;
306
307 return std::fwrite(ptr: __str, size: sizeof(char_type), n: __len, s: __file_);
308 }
309 return basic_streambuf<_CharT, _Traits>::xsputn(__str, __len);
310 }
311
312private:
313 char* __extbuf_;
314 const char* __extbufnext_;
315 const char* __extbufend_;
316 char __extbuf_min_[8];
317 size_t __ebs_;
318 char_type* __intbuf_;
319 size_t __ibs_;
320 FILE* __file_;
321 const codecvt<char_type, char, state_type>* __cv_;
322 state_type __st_;
323 state_type __st_last_;
324 ios_base::openmode __om_;
325 // There have been no file operations yet, which allows setting unbuffered
326 // I/O mode.
327 static const ios_base::openmode __no_io_operations = ios_base::trunc;
328 // Unbuffered I/O mode has been requested.
329 static const ios_base::openmode __use_unbuffered_io = ios_base::ate;
330 // Used to track the currently used mode and track whether the output should
331 // be unbuffered.
332 // [filebuf.virtuals]/12
333 // If setbuf(0, 0) is called on a stream before any I/O has occurred on
334 // that stream, the stream becomes unbuffered. Otherwise the results are
335 // implementation-defined.
336 // This allows calling setbuf(0, 0)
337 // - before opening a file,
338 // - after opening a file, before
339 // - a read
340 // - a write
341 // - a seek.
342 // Note that opening a file with ios_base::ate does a seek operation.
343 // Normally underflow, overflow, and sync change this flag to ios_base::in,
344 // ios_base_out, or 0.
345 //
346 // The ios_base::trunc and ios_base::ate flags are not used in __cm_. They
347 // are used to track the state of the unbuffered request. For readability
348 // they have the aliases __no_io_operations and __use_unbuffered_io
349 // respectively.
350 //
351 // The __no_io_operations and __use_unbuffered_io flags are used in the
352 // following way:
353 // - __no_io_operations is set upon construction to indicate the unbuffered
354 // state can be set.
355 // - When requesting unbuffered output:
356 // - If the file is open it sets the mode.
357 // - Else places a request by adding the __use_unbuffered_io flag.
358 // - When a file is opened it checks whether both __no_io_operations and
359 // __use_unbuffered_io are set. If so switches to unbuffered mode.
360 // - All file I/O operations change the mode effectively clearing the
361 // __no_io_operations and __use_unbuffered_io flags.
362 ios_base::openmode __cm_;
363 bool __owns_eb_;
364 bool __owns_ib_;
365 bool __always_noconv_;
366
367 bool __read_mode();
368 void __write_mode();
369
370 _LIBCPP_HIDE_FROM_ABI static int __fseek(FILE* __file, pos_type __offset, int __whence);
371 _LIBCPP_HIDE_FROM_ABI static pos_type __ftell(FILE* __file);
372
373 _LIBCPP_EXPORTED_FROM_ABI friend FILE* __get_ostream_file(ostream&);
374
375 // There are multiple (__)open function, they use different C-API open
376 // function. After that call these functions behave the same. This function
377 // does that part and determines the final return value.
378 _LIBCPP_HIDE_FROM_ABI basic_filebuf* __do_open(FILE* __file, ios_base::openmode __mode) {
379 __file_ = __file;
380 if (!__file_)
381 return nullptr;
382
383 __om_ = __mode;
384 if (__cm_ == (__no_io_operations | __use_unbuffered_io)) {
385 std::setbuf(stream: __file_, buf: nullptr);
386 __cm_ = 0;
387 }
388
389 if (__mode & ios_base::ate) {
390 __cm_ = 0;
391 if (fseek(stream: __file_, off: 0, SEEK_END)) {
392 fclose(stream: __file_);
393 __file_ = nullptr;
394 return nullptr;
395 }
396 }
397
398 return this;
399 }
400
401 // If the file is already open, switch to unbuffered mode. Otherwise, record
402 // the request to use unbuffered mode so that we use that mode when we
403 // eventually open the file.
404 _LIBCPP_HIDE_FROM_ABI void __request_unbuffered_mode() {
405 if (__file_) {
406 std::setbuf(stream: __file_, buf: nullptr);
407 __cm_ = 0;
408 } else {
409 __cm_ = __no_io_operations | __use_unbuffered_io;
410 }
411 }
412
413 _LIBCPP_HIDE_FROM_ABI typename traits_type::int_type __overflow_failed() {
414 if (this->pptr() == this->epptr() + 1) {
415 this->pbump(-1); // lose the character we overflowed above -- we don't really have a
416 // choice since we couldn't commit the contents of the put area
417 }
418 return traits_type::eof();
419 }
420};
421
422template <class _CharT, class _Traits>
423basic_filebuf<_CharT, _Traits>::basic_filebuf()
424 : __extbuf_(nullptr),
425 __extbufnext_(nullptr),
426 __extbufend_(nullptr),
427 __ebs_(0),
428 __intbuf_(nullptr),
429 __ibs_(0),
430 __file_(nullptr),
431 __cv_(nullptr),
432 __st_(),
433 __st_last_(),
434 __om_(0),
435 __cm_(__no_io_operations),
436 __owns_eb_(false),
437 __owns_ib_(false),
438 __always_noconv_(false) {
439 if (std::has_facet<codecvt<char_type, char, state_type> >(this->getloc())) {
440 __cv_ = std::addressof(std::use_facet<codecvt<char_type, char, state_type> >(this->getloc()));
441 __always_noconv_ = __cv_->always_noconv();
442 }
443 setbuf(s: nullptr, n: 4096);
444}
445
446template <class _CharT, class _Traits>
447basic_filebuf<_CharT, _Traits>::basic_filebuf(basic_filebuf&& __rhs) : basic_streambuf<_CharT, _Traits>(__rhs) {
448 if (__rhs.__extbuf_ == __rhs.__extbuf_min_) {
449 __extbuf_ = __extbuf_min_;
450 __extbufnext_ = __extbuf_ + (__rhs.__extbufnext_ - __rhs.__extbuf_);
451 __extbufend_ = __extbuf_ + (__rhs.__extbufend_ - __rhs.__extbuf_);
452 } else {
453 __extbuf_ = __rhs.__extbuf_;
454 __extbufnext_ = __rhs.__extbufnext_;
455 __extbufend_ = __rhs.__extbufend_;
456 }
457 __ebs_ = __rhs.__ebs_;
458 __intbuf_ = __rhs.__intbuf_;
459 __ibs_ = __rhs.__ibs_;
460 __file_ = __rhs.__file_;
461 __cv_ = __rhs.__cv_;
462 __st_ = __rhs.__st_;
463 __st_last_ = __rhs.__st_last_;
464 __om_ = __rhs.__om_;
465 __cm_ = __rhs.__cm_;
466 __owns_eb_ = __rhs.__owns_eb_;
467 __owns_ib_ = __rhs.__owns_ib_;
468 __always_noconv_ = __rhs.__always_noconv_;
469 if (__rhs.pbase()) {
470 if (__rhs.pbase() == __rhs.__intbuf_)
471 this->setp(__intbuf_, __intbuf_ + (__rhs.epptr() - __rhs.pbase()));
472 else
473 this->setp((char_type*)__extbuf_, (char_type*)__extbuf_ + (__rhs.epptr() - __rhs.pbase()));
474 this->__pbump(__rhs.pptr() - __rhs.pbase());
475 } else if (__rhs.eback()) {
476 if (__rhs.eback() == __rhs.__intbuf_)
477 this->setg(__intbuf_, __intbuf_ + (__rhs.gptr() - __rhs.eback()), __intbuf_ + (__rhs.egptr() - __rhs.eback()));
478 else
479 this->setg((char_type*)__extbuf_,
480 (char_type*)__extbuf_ + (__rhs.gptr() - __rhs.eback()),
481 (char_type*)__extbuf_ + (__rhs.egptr() - __rhs.eback()));
482 }
483 __rhs.__extbuf_ = nullptr;
484 __rhs.__extbufnext_ = nullptr;
485 __rhs.__extbufend_ = nullptr;
486 __rhs.__ebs_ = 0;
487 __rhs.__intbuf_ = 0;
488 __rhs.__ibs_ = 0;
489 __rhs.__file_ = nullptr;
490 __rhs.__st_ = state_type();
491 __rhs.__st_last_ = state_type();
492 __rhs.__om_ = 0;
493 __rhs.__cm_ = 0;
494 __rhs.__owns_eb_ = false;
495 __rhs.__owns_ib_ = false;
496 __rhs.setg(0, 0, 0);
497 __rhs.setp(0, 0);
498}
499
500template <class _CharT, class _Traits>
501inline basic_filebuf<_CharT, _Traits>& basic_filebuf<_CharT, _Traits>::operator=(basic_filebuf&& __rhs) {
502 close();
503 swap(__rhs);
504 return *this;
505}
506
507template <class _CharT, class _Traits>
508basic_filebuf<_CharT, _Traits>::~basic_filebuf() {
509# if _LIBCPP_HAS_EXCEPTIONS
510 try {
511# endif // _LIBCPP_HAS_EXCEPTIONS
512 close();
513# if _LIBCPP_HAS_EXCEPTIONS
514 } catch (...) {
515 }
516# endif // _LIBCPP_HAS_EXCEPTIONS
517 if (__owns_eb_)
518 delete[] __extbuf_;
519 if (__owns_ib_)
520 delete[] __intbuf_;
521}
522
523template <class _CharT, class _Traits>
524void basic_filebuf<_CharT, _Traits>::swap(basic_filebuf& __rhs) {
525 basic_streambuf<char_type, traits_type>::swap(__rhs);
526 if (__extbuf_ != __extbuf_min_ && __rhs.__extbuf_ != __rhs.__extbuf_min_) {
527 // Neither *this nor __rhs uses the small buffer, so we can simply swap the pointers.
528 std::swap(x&: __extbuf_, y&: __rhs.__extbuf_);
529 std::swap(x&: __extbufnext_, y&: __rhs.__extbufnext_);
530 std::swap(x&: __extbufend_, y&: __rhs.__extbufend_);
531 } else {
532 ptrdiff_t __ln = __extbufnext_ ? __extbufnext_ - __extbuf_ : 0;
533 ptrdiff_t __le = __extbufend_ ? __extbufend_ - __extbuf_ : 0;
534 ptrdiff_t __rn = __rhs.__extbufnext_ ? __rhs.__extbufnext_ - __rhs.__extbuf_ : 0;
535 ptrdiff_t __re = __rhs.__extbufend_ ? __rhs.__extbufend_ - __rhs.__extbuf_ : 0;
536 if (__extbuf_ == __extbuf_min_ && __rhs.__extbuf_ != __rhs.__extbuf_min_) {
537 // *this uses the small buffer, but __rhs doesn't.
538 __extbuf_ = __rhs.__extbuf_;
539 __rhs.__extbuf_ = __rhs.__extbuf_min_;
540 std::memmove(dest: __rhs.__extbuf_min_, src: __extbuf_min_, n: sizeof(__extbuf_min_));
541 } else if (__extbuf_ != __extbuf_min_ && __rhs.__extbuf_ == __rhs.__extbuf_min_) {
542 // *this doesn't use the small buffer, but __rhs does.
543 __rhs.__extbuf_ = __extbuf_;
544 __extbuf_ = __extbuf_min_;
545 std::memmove(dest: __extbuf_min_, src: __rhs.__extbuf_min_, n: sizeof(__extbuf_min_));
546 } else {
547 // Both *this and __rhs use the small buffer.
548 char __tmp[sizeof(__extbuf_min_)];
549 std::memmove(dest: __tmp, src: __extbuf_min_, n: sizeof(__extbuf_min_));
550 std::memmove(dest: __extbuf_min_, src: __rhs.__extbuf_min_, n: sizeof(__extbuf_min_));
551 std::memmove(dest: __rhs.__extbuf_min_, src: __tmp, n: sizeof(__extbuf_min_));
552 }
553 __extbufnext_ = __extbuf_ + __rn;
554 __extbufend_ = __extbuf_ + __re;
555 __rhs.__extbufnext_ = __rhs.__extbuf_ + __ln;
556 __rhs.__extbufend_ = __rhs.__extbuf_ + __le;
557 }
558 std::swap(x&: __ebs_, y&: __rhs.__ebs_);
559 std::swap(__intbuf_, __rhs.__intbuf_);
560 std::swap(x&: __ibs_, y&: __rhs.__ibs_);
561 std::swap(x&: __file_, y&: __rhs.__file_);
562 std::swap(__cv_, __rhs.__cv_);
563 std::swap(__st_, __rhs.__st_);
564 std::swap(__st_last_, __rhs.__st_last_);
565 std::swap(x&: __om_, y&: __rhs.__om_);
566 std::swap(x&: __cm_, y&: __rhs.__cm_);
567 std::swap(x&: __owns_eb_, y&: __rhs.__owns_eb_);
568 std::swap(x&: __owns_ib_, y&: __rhs.__owns_ib_);
569 std::swap(x&: __always_noconv_, y&: __rhs.__always_noconv_);
570 if (this->eback() == (char_type*)__rhs.__extbuf_min_) {
571 ptrdiff_t __n = this->gptr() - this->eback();
572 ptrdiff_t __e = this->egptr() - this->eback();
573 this->setg((char_type*)__extbuf_min_, (char_type*)__extbuf_min_ + __n, (char_type*)__extbuf_min_ + __e);
574 } else if (this->pbase() == (char_type*)__rhs.__extbuf_min_) {
575 ptrdiff_t __n = this->pptr() - this->pbase();
576 ptrdiff_t __e = this->epptr() - this->pbase();
577 this->setp((char_type*)__extbuf_min_, (char_type*)__extbuf_min_ + __e);
578 this->__pbump(__n);
579 }
580 if (__rhs.eback() == (char_type*)__extbuf_min_) {
581 ptrdiff_t __n = __rhs.gptr() - __rhs.eback();
582 ptrdiff_t __e = __rhs.egptr() - __rhs.eback();
583 __rhs.setg(
584 (char_type*)__rhs.__extbuf_min_, (char_type*)__rhs.__extbuf_min_ + __n, (char_type*)__rhs.__extbuf_min_ + __e);
585 } else if (__rhs.pbase() == (char_type*)__extbuf_min_) {
586 ptrdiff_t __n = __rhs.pptr() - __rhs.pbase();
587 ptrdiff_t __e = __rhs.epptr() - __rhs.pbase();
588 __rhs.setp((char_type*)__rhs.__extbuf_min_, (char_type*)__rhs.__extbuf_min_ + __e);
589 __rhs.__pbump(__n);
590 }
591}
592
593template <class _CharT, class _Traits>
594inline _LIBCPP_HIDE_FROM_ABI void swap(basic_filebuf<_CharT, _Traits>& __x, basic_filebuf<_CharT, _Traits>& __y) {
595 __x.swap(__y);
596}
597
598template <class _CharT, class _Traits>
599inline bool basic_filebuf<_CharT, _Traits>::is_open() const {
600 return __file_ != nullptr;
601}
602
603// Configures the fopen close-on-exec mode character, if any. This string will
604// be appended to any mode string used by fstream for fopen/fdopen.
605//
606// Not all platforms support this, but it helps avoid fd-leaks on platforms that
607// do.
608# if defined(__BIONIC__)
609# define _LIBCPP_FOPEN_CLOEXEC_MODE "e"
610# else
611# define _LIBCPP_FOPEN_CLOEXEC_MODE
612# endif
613
614template <class _CharT, class _Traits>
615const char* basic_filebuf<_CharT, _Traits>::__make_mdstring(ios_base::openmode __mode) _NOEXCEPT {
616 switch (__mode & ~ios_base::ate) {
617 case ios_base::out:
618 case ios_base::out | ios_base::trunc:
619 return "w" _LIBCPP_FOPEN_CLOEXEC_MODE;
620 case ios_base::out | ios_base::app:
621 case ios_base::app:
622 return "a" _LIBCPP_FOPEN_CLOEXEC_MODE;
623 case ios_base::in:
624 return "r" _LIBCPP_FOPEN_CLOEXEC_MODE;
625 case ios_base::in | ios_base::out:
626 return "r+" _LIBCPP_FOPEN_CLOEXEC_MODE;
627 case ios_base::in | ios_base::out | ios_base::trunc:
628 return "w+" _LIBCPP_FOPEN_CLOEXEC_MODE;
629 case ios_base::in | ios_base::out | ios_base::app:
630 case ios_base::in | ios_base::app:
631 return "a+" _LIBCPP_FOPEN_CLOEXEC_MODE;
632 case ios_base::out | ios_base::binary:
633 case ios_base::out | ios_base::trunc | ios_base::binary:
634 return "wb" _LIBCPP_FOPEN_CLOEXEC_MODE;
635 case ios_base::out | ios_base::app | ios_base::binary:
636 case ios_base::app | ios_base::binary:
637 return "ab" _LIBCPP_FOPEN_CLOEXEC_MODE;
638 case ios_base::in | ios_base::binary:
639 return "rb" _LIBCPP_FOPEN_CLOEXEC_MODE;
640 case ios_base::in | ios_base::out | ios_base::binary:
641 return "r+b" _LIBCPP_FOPEN_CLOEXEC_MODE;
642 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary:
643 return "w+b" _LIBCPP_FOPEN_CLOEXEC_MODE;
644 case ios_base::in | ios_base::out | ios_base::app | ios_base::binary:
645 case ios_base::in | ios_base::app | ios_base::binary:
646 return "a+b" _LIBCPP_FOPEN_CLOEXEC_MODE;
647# if _LIBCPP_STD_VER >= 23
648 case ios_base::out | ios_base::noreplace:
649 case ios_base::out | ios_base::trunc | ios_base::noreplace:
650 return "wx" _LIBCPP_FOPEN_CLOEXEC_MODE;
651 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::noreplace:
652 return "w+x" _LIBCPP_FOPEN_CLOEXEC_MODE;
653 case ios_base::out | ios_base::binary | ios_base::noreplace:
654 case ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
655 return "wbx" _LIBCPP_FOPEN_CLOEXEC_MODE;
656 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
657 return "w+bx" _LIBCPP_FOPEN_CLOEXEC_MODE;
658# endif // _LIBCPP_STD_VER >= 23
659 default:
660 return nullptr;
661 }
662 __libcpp_unreachable();
663}
664
665# if _LIBCPP_HAS_OPEN_WITH_WCHAR
666template <class _CharT, class _Traits>
667const wchar_t* basic_filebuf<_CharT, _Traits>::__make_mdwstring(ios_base::openmode __mode) _NOEXCEPT {
668 switch (__mode & ~ios_base::ate) {
669 case ios_base::out:
670 case ios_base::out | ios_base::trunc:
671 return L"w";
672 case ios_base::out | ios_base::app:
673 case ios_base::app:
674 return L"a";
675 case ios_base::in:
676 return L"r";
677 case ios_base::in | ios_base::out:
678 return L"r+";
679 case ios_base::in | ios_base::out | ios_base::trunc:
680 return L"w+";
681 case ios_base::in | ios_base::out | ios_base::app:
682 case ios_base::in | ios_base::app:
683 return L"a+";
684 case ios_base::out | ios_base::binary:
685 case ios_base::out | ios_base::trunc | ios_base::binary:
686 return L"wb";
687 case ios_base::out | ios_base::app | ios_base::binary:
688 case ios_base::app | ios_base::binary:
689 return L"ab";
690 case ios_base::in | ios_base::binary:
691 return L"rb";
692 case ios_base::in | ios_base::out | ios_base::binary:
693 return L"r+b";
694 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary:
695 return L"w+b";
696 case ios_base::in | ios_base::out | ios_base::app | ios_base::binary:
697 case ios_base::in | ios_base::app | ios_base::binary:
698 return L"a+b";
699# if _LIBCPP_STD_VER >= 23
700 case ios_base::out | ios_base::noreplace:
701 case ios_base::out | ios_base::trunc | ios_base::noreplace:
702 return L"wx";
703 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::noreplace:
704 return L"w+x";
705 case ios_base::out | ios_base::binary | ios_base::noreplace:
706 case ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
707 return L"wbx";
708 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
709 return L"w+bx";
710# endif // _LIBCPP_STD_VER >= 23
711 default:
712 return nullptr;
713 }
714 __libcpp_unreachable();
715}
716# endif
717
718template <class _CharT, class _Traits>
719basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
720 if (__file_)
721 return nullptr;
722 const char* __mdstr = __make_mdstring(__mode);
723 if (!__mdstr)
724 return nullptr;
725
726 return __do_open(file: std::fopen(filename: __s, modes: __mdstr), __mode);
727}
728
729template <class _CharT, class _Traits>
730inline basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) {
731 if (__file_)
732 return nullptr;
733 const char* __mdstr = __make_mdstring(__mode);
734 if (!__mdstr)
735 return nullptr;
736
737 return __do_open(file: fdopen(__fd, modes: __mdstr), __mode);
738}
739
740# if _LIBCPP_HAS_OPEN_WITH_WCHAR
741// This is basically the same as the char* overload except that it uses _wfopen
742// and long mode strings.
743template <class _CharT, class _Traits>
744basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) {
745 if (__file_)
746 return nullptr;
747 const wchar_t* __mdstr = __make_mdwstring(__mode);
748 if (!__mdstr)
749 return nullptr;
750
751 return __do_open(_wfopen(__s, __mdstr), __mode);
752}
753# endif
754
755template <class _CharT, class _Traits>
756inline basic_filebuf<_CharT, _Traits>*
757basic_filebuf<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode) {
758 return open(__s.c_str(), __mode);
759}
760
761template <class _CharT, class _Traits>
762basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::close() {
763 basic_filebuf<_CharT, _Traits>* __rt = nullptr;
764 if (__file_) {
765 __rt = this;
766 unique_ptr<FILE, int (*)(FILE*)> __h(__file_, fclose);
767 if (sync())
768 __rt = nullptr;
769 if (fclose(stream: __h.release()))
770 __rt = nullptr;
771 __file_ = nullptr;
772 // Reset the get and the put areas without getting rid of the underlying buffers,
773 // which might have been configured by the user. Make sure to keep the buffers
774 // since the user may re-open the stream.
775 this->setg(nullptr, nullptr, nullptr);
776 this->setp(nullptr, nullptr);
777 __cm_ = __no_io_operations;
778 }
779 return __rt;
780}
781
782template <class _CharT, class _Traits>
783typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits>::underflow() {
784 if (__file_ == nullptr)
785 return traits_type::eof();
786 bool __initial = __read_mode();
787 char_type __1buf;
788 if (this->gptr() == nullptr)
789 this->setg(std::addressof(__1buf), std::addressof(__1buf) + 1, std::addressof(__1buf) + 1);
790 const size_t __unget_sz = __initial ? 0 : std::min<size_t>((this->egptr() - this->eback()) / 2, 4);
791 int_type __c = traits_type::eof();
792 if (this->gptr() == this->egptr()) {
793 std::memmove(dest: this->eback(), src: this->egptr() - __unget_sz, n: __unget_sz * sizeof(char_type));
794 if (__always_noconv_) {
795 size_t __nmemb = static_cast<size_t>(this->egptr() - this->eback() - __unget_sz);
796 __nmemb = std::fread(ptr: this->eback() + __unget_sz, size: 1, n: __nmemb, stream: __file_);
797 if (__nmemb != 0) {
798 this->setg(this->eback(), this->eback() + __unget_sz, this->eback() + __unget_sz + __nmemb);
799 __c = traits_type::to_int_type(*this->gptr());
800 }
801 } else {
802 if (__extbufend_ != __extbufnext_) {
803 _LIBCPP_ASSERT_NON_NULL(__extbufnext_ != nullptr, "underflow moving from nullptr");
804 _LIBCPP_ASSERT_NON_NULL(__extbuf_ != nullptr, "underflow moving into nullptr");
805 std::memmove(dest: __extbuf_, src: __extbufnext_, n: __extbufend_ - __extbufnext_);
806 }
807 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
808 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
809 size_t __nmemb =
810 std::min(a: static_cast<size_t>(__ibs_ - __unget_sz), b: static_cast<size_t>(__extbufend_ - __extbufnext_));
811 codecvt_base::result __r;
812 __st_last_ = __st_;
813 size_t __nr = std::fread(ptr: (void*)const_cast<char*>(__extbufnext_), size: 1, n: __nmemb, stream: __file_);
814 if (__nr != 0) {
815 if (!__cv_)
816 std::__throw_bad_cast();
817
818 __extbufend_ = __extbufnext_ + __nr;
819 char_type* __inext;
820 __r = __cv_->in(
821 __st_, __extbuf_, __extbufend_, __extbufnext_, this->eback() + __unget_sz, this->eback() + __ibs_, __inext);
822 if (__r == codecvt_base::noconv) {
823 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)const_cast<char*>(__extbufend_));
824 __c = traits_type::to_int_type(*this->gptr());
825 } else if (__inext != this->eback() + __unget_sz) {
826 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
827 __c = traits_type::to_int_type(*this->gptr());
828 }
829 }
830 }
831 } else
832 __c = traits_type::to_int_type(*this->gptr());
833 if (this->eback() == std::addressof(__1buf))
834 this->setg(nullptr, nullptr, nullptr);
835 return __c;
836}
837
838template <class _CharT, class _Traits>
839typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c) {
840 if (__file_ && this->eback() < this->gptr()) {
841 if (traits_type::eq_int_type(__c, traits_type::eof())) {
842 this->gbump(-1);
843 return traits_type::not_eof(__c);
844 }
845 if ((__om_ & ios_base::out) || traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1])) {
846 this->gbump(-1);
847 *this->gptr() = traits_type::to_char_type(__c);
848 return __c;
849 }
850 }
851 return traits_type::eof();
852}
853
854template <class _CharT, class _Traits>
855typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits>::overflow(int_type __c) {
856 if (__file_ == nullptr)
857 return traits_type::eof();
858 __write_mode();
859 char_type __1buf;
860 char_type* __pb_save = this->pbase();
861 char_type* __epb_save = this->epptr();
862 if (!traits_type::eq_int_type(__c, traits_type::eof())) {
863 if (this->pptr() == nullptr)
864 this->setp(std::addressof(__1buf), std::addressof(__1buf) + 1);
865 *this->pptr() = traits_type::to_char_type(__c);
866 this->pbump(1);
867 }
868
869 // There is nothing to write, early return
870 if (this->pptr() == this->pbase()) {
871 return traits_type::not_eof(__c);
872 }
873
874 if (__always_noconv_) {
875 size_t __n = static_cast<size_t>(this->pptr() - this->pbase());
876 if (std::fwrite(ptr: this->pbase(), size: sizeof(char_type), __n, s: __file_) != __n) {
877 return __overflow_failed();
878 }
879 } else {
880 if (!__cv_)
881 std::__throw_bad_cast();
882
883 // See [filebuf.virtuals]
884 char_type* __b = this->pbase();
885 char_type* __p = this->pptr();
886 const char_type* __end;
887 char* __extbuf_end = __extbuf_;
888 do {
889 codecvt_base::result __r = __cv_->out(__st_, __b, __p, __end, __extbuf_, __extbuf_ + __ebs_, __extbuf_end);
890 if (__end == __b) {
891 return __overflow_failed();
892 }
893
894 // No conversion needed: output characters directly to the file, done.
895 if (__r == codecvt_base::noconv) {
896 size_t __n = static_cast<size_t>(__p - __b);
897 if (std::fwrite(ptr: __b, size: 1, __n, s: __file_) != __n) {
898 return __overflow_failed();
899 }
900 break;
901
902 // Conversion successful: output the converted characters to the file, done.
903 } else if (__r == codecvt_base::ok) {
904 size_t __n = static_cast<size_t>(__extbuf_end - __extbuf_);
905 if (std::fwrite(ptr: __extbuf_, size: 1, __n, s: __file_) != __n) {
906 return __overflow_failed();
907 }
908 break;
909
910 // Conversion partially successful: output converted characters to the file and repeat with the
911 // remaining characters.
912 } else if (__r == codecvt_base::partial) {
913 size_t __n = static_cast<size_t>(__extbuf_end - __extbuf_);
914 if (std::fwrite(ptr: __extbuf_, size: 1, __n, s: __file_) != __n) {
915 return __overflow_failed();
916 }
917 __b = const_cast<char_type*>(__end);
918 continue;
919
920 } else {
921 return __overflow_failed();
922 }
923 } while (true);
924 }
925 this->setp(__pb_save, __epb_save);
926 return traits_type::not_eof(__c);
927}
928
929template <class _CharT, class _Traits>
930basic_streambuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::setbuf(char_type* __s, streamsize __n) {
931 this->setg(nullptr, nullptr, nullptr);
932 this->setp(nullptr, nullptr);
933 // Calling setbuf(nullptr, 0) before any i/o operation switches the stream to unbuffered mode
934 if (__cm_ == __no_io_operations && __s == nullptr && __n == 0)
935 __request_unbuffered_mode();
936 if (__owns_eb_)
937 delete[] __extbuf_;
938 if (__owns_ib_)
939 delete[] __intbuf_;
940 __ebs_ = __n;
941 if (__ebs_ > sizeof(__extbuf_min_)) {
942 if (__always_noconv_ && __s) {
943 __extbuf_ = (char*)__s;
944 __owns_eb_ = false;
945 } else {
946 __extbuf_ = new char[__ebs_];
947 __owns_eb_ = true;
948 }
949 } else {
950 __extbuf_ = __extbuf_min_;
951 __ebs_ = sizeof(__extbuf_min_);
952 __owns_eb_ = false;
953 }
954 if (!__always_noconv_) {
955 __ibs_ = max<streamsize>(a: __n, b: sizeof(__extbuf_min_));
956 if (__s && __ibs_ > sizeof(__extbuf_min_)) {
957 __intbuf_ = __s;
958 __owns_ib_ = false;
959 } else {
960 __intbuf_ = new char_type[__ibs_];
961 __owns_ib_ = true;
962 }
963 } else {
964 __ibs_ = 0;
965 __intbuf_ = nullptr;
966 __owns_ib_ = false;
967 }
968 return this;
969}
970
971template <class _CharT, class _Traits>
972typename basic_filebuf<_CharT, _Traits>::pos_type
973basic_filebuf<_CharT, _Traits>::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode) {
974 if (!__cv_)
975 std::__throw_bad_cast();
976
977 int __width = __cv_->encoding();
978 if (__file_ == nullptr || (__width <= 0 && __off != 0) || sync())
979 return pos_type(off_type(-1));
980 // __width > 0 || __off == 0
981 int __whence;
982 switch (__way) {
983 case ios_base::beg:
984 __whence = SEEK_SET;
985 break;
986 case ios_base::cur:
987 __whence = SEEK_CUR;
988 break;
989 case ios_base::end:
990 __whence = SEEK_END;
991 break;
992 default:
993 return pos_type(off_type(-1));
994 }
995 if (__fseek(file: __file_, offset: __width > 0 ? __width * __off : 0, __whence))
996 return pos_type(off_type(-1));
997 pos_type __r = __ftell(file: __file_);
998 __r.state(__st_);
999 return __r;
1000}
1001
1002template <class _CharT, class _Traits>
1003int basic_filebuf<_CharT, _Traits>::__fseek(FILE* __file, pos_type __offset, int __whence) {
1004# if defined(_LIBCPP_MSVCRT_LIKE)
1005 return _fseeki64(__file, __offset, __whence);
1006# elif _LIBCPP_LIBC_NEWLIB
1007 return fseek(__file, __offset, __whence);
1008# else
1009 return ::fseeko(stream: __file, off: __offset, __whence);
1010# endif
1011}
1012
1013template <class _CharT, class _Traits>
1014typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>::__ftell(FILE* __file) {
1015# if defined(_LIBCPP_MSVCRT_LIKE)
1016 return _ftelli64(__file);
1017# elif _LIBCPP_LIBC_NEWLIB
1018 return ftell(__file);
1019# else
1020 return ftello(stream: __file);
1021# endif
1022}
1023
1024template <class _CharT, class _Traits>
1025typename basic_filebuf<_CharT, _Traits>::pos_type
1026basic_filebuf<_CharT, _Traits>::seekpos(pos_type __sp, ios_base::openmode) {
1027 if (__file_ == nullptr || sync())
1028 return pos_type(off_type(-1));
1029 if (__fseek(file: __file_, offset: __sp, SEEK_SET))
1030 return pos_type(off_type(-1));
1031 __st_ = __sp.state();
1032 return __sp;
1033}
1034
1035template <class _CharT, class _Traits>
1036int basic_filebuf<_CharT, _Traits>::sync() {
1037 if (__file_ == nullptr)
1038 return 0;
1039 if (!__cv_)
1040 std::__throw_bad_cast();
1041
1042 if (__cm_ & ios_base::out) {
1043 if (this->pptr() != this->pbase())
1044 if (overflow() == traits_type::eof())
1045 return -1;
1046 codecvt_base::result __r;
1047 do {
1048 char* __extbe;
1049 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
1050 size_t __nmemb = static_cast<size_t>(__extbe - __extbuf_);
1051 if (std::fwrite(ptr: __extbuf_, size: 1, n: __nmemb, s: __file_) != __nmemb)
1052 return -1;
1053 } while (__r == codecvt_base::partial);
1054 if (__r == codecvt_base::error)
1055 return -1;
1056 if (std::fflush(stream: __file_))
1057 return -1;
1058 } else if (__cm_ & ios_base::in) {
1059 off_type __c;
1060 state_type __state = __st_last_;
1061 bool __update_st = false;
1062 if (__always_noconv_)
1063 __c = this->egptr() - this->gptr();
1064 else {
1065 int __width = __cv_->encoding();
1066 __c = __extbufend_ - __extbufnext_;
1067 if (__width > 0)
1068 __c += __width * (this->egptr() - this->gptr());
1069 else {
1070 if (this->gptr() != this->egptr()) {
1071 const int __off = __cv_->length(__state, __extbuf_, __extbufnext_, this->gptr() - this->eback());
1072 __c += __extbufnext_ - __extbuf_ - __off;
1073 __update_st = true;
1074 }
1075 }
1076 }
1077 if (__fseek(file: __file_, offset: -__c, SEEK_CUR))
1078 return -1;
1079 if (__update_st)
1080 __st_ = __state;
1081 __extbufnext_ = __extbufend_ = __extbuf_;
1082 this->setg(nullptr, nullptr, nullptr);
1083 __cm_ = 0;
1084 }
1085 return 0;
1086}
1087
1088template <class _CharT, class _Traits>
1089void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc) {
1090 sync();
1091 __cv_ = std::addressof(std::use_facet<codecvt<char_type, char, state_type> >(__loc));
1092 bool __old_anc = __always_noconv_;
1093 __always_noconv_ = __cv_->always_noconv();
1094 if (__old_anc != __always_noconv_) {
1095 this->setg(nullptr, nullptr, nullptr);
1096 this->setp(nullptr, nullptr);
1097 // invariant, char_type is char, else we couldn't get here
1098 if (__always_noconv_) // need to dump __intbuf_
1099 {
1100 if (__owns_eb_)
1101 delete[] __extbuf_;
1102 __owns_eb_ = __owns_ib_;
1103 __ebs_ = __ibs_;
1104 __extbuf_ = (char*)__intbuf_;
1105 __ibs_ = 0;
1106 __intbuf_ = nullptr;
1107 __owns_ib_ = false;
1108 } else // need to obtain an __intbuf_.
1109 { // If __extbuf_ is user-supplied, use it, else new __intbuf_
1110 if (!__owns_eb_ && __extbuf_ != __extbuf_min_) {
1111 __ibs_ = __ebs_;
1112 __intbuf_ = (char_type*)__extbuf_;
1113 __owns_ib_ = false;
1114 __extbuf_ = new char[__ebs_];
1115 __owns_eb_ = true;
1116 } else {
1117 __ibs_ = __ebs_;
1118 __intbuf_ = new char_type[__ibs_];
1119 __owns_ib_ = true;
1120 }
1121 }
1122 }
1123}
1124
1125template <class _CharT, class _Traits>
1126bool basic_filebuf<_CharT, _Traits>::__read_mode() {
1127 if (!(__cm_ & ios_base::in)) {
1128 this->setp(nullptr, nullptr);
1129 if (__always_noconv_)
1130 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_ + __ebs_, (char_type*)__extbuf_ + __ebs_);
1131 else
1132 this->setg(__intbuf_, __intbuf_ + __ibs_, __intbuf_ + __ibs_);
1133 __cm_ = ios_base::in;
1134 return true;
1135 }
1136 return false;
1137}
1138
1139template <class _CharT, class _Traits>
1140void basic_filebuf<_CharT, _Traits>::__write_mode() {
1141 if (!(__cm_ & ios_base::out)) {
1142 this->setg(nullptr, nullptr, nullptr);
1143 if (__ebs_ > sizeof(__extbuf_min_)) {
1144 if (__always_noconv_)
1145 this->setp((char_type*)__extbuf_, (char_type*)__extbuf_ + (__ebs_ - 1));
1146 else
1147 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
1148 } else
1149 this->setp(nullptr, nullptr);
1150 __cm_ = ios_base::out;
1151 }
1152}
1153
1154// basic_ifstream
1155
1156template <class _CharT, class _Traits>
1157class basic_ifstream : public basic_istream<_CharT, _Traits> {
1158public:
1159 typedef _CharT char_type;
1160 typedef _Traits traits_type;
1161 typedef typename traits_type::int_type int_type;
1162 typedef typename traits_type::pos_type pos_type;
1163 typedef typename traits_type::off_type off_type;
1164# if _LIBCPP_STD_VER >= 26
1165 using native_handle_type = typename basic_filebuf<_CharT, _Traits>::native_handle_type;
1166# endif
1167
1168 _LIBCPP_HIDE_FROM_ABI basic_ifstream();
1169 _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in);
1170# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1171 _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const wchar_t* __s, ios_base::openmode __mode = ios_base::in);
1172# endif
1173 _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const string& __s, ios_base::openmode __mode = ios_base::in);
1174# if _LIBCPP_STD_VER >= 17
1175 template <class _Tp, class = enable_if_t<is_same_v<_Tp, filesystem::path>>>
1176 _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const _Tp& __p, ios_base::openmode __mode = ios_base::in)
1177 : basic_ifstream(__p.c_str(), __mode) {}
1178# endif // _LIBCPP_STD_VER >= 17
1179 _LIBCPP_HIDE_FROM_ABI basic_ifstream(basic_ifstream&& __rhs);
1180 _LIBCPP_HIDE_FROM_ABI basic_ifstream& operator=(basic_ifstream&& __rhs);
1181 _LIBCPP_HIDE_FROM_ABI void swap(basic_ifstream& __rhs);
1182
1183 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const;
1184# if _LIBCPP_STD_VER >= 26
1185 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
1186 return rdbuf()->native_handle();
1187 }
1188# endif
1189 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_open() const;
1190 void open(const char* __s, ios_base::openmode __mode = ios_base::in);
1191# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1192 void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in);
1193# endif
1194 void open(const string& __s, ios_base::openmode __mode = ios_base::in);
1195# if _LIBCPP_STD_VER >= 17
1196 _LIBCPP_HIDE_FROM_ABI void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in) {
1197 return open(__p.c_str(), __mode);
1198 }
1199# endif // _LIBCPP_STD_VER >= 17
1200
1201 _LIBCPP_HIDE_FROM_ABI void __open(int __fd, ios_base::openmode __mode);
1202 _LIBCPP_HIDE_FROM_ABI void close();
1203
1204private:
1205 basic_filebuf<char_type, traits_type> __sb_;
1206};
1207
1208template <class _CharT, class _Traits>
1209inline basic_ifstream<_CharT, _Traits>::basic_ifstream()
1210 : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {}
1211
1212template <class _CharT, class _Traits>
1213inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const char* __s, ios_base::openmode __mode)
1214 : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {
1215 if (__sb_.open(__s, __mode | ios_base::in) == nullptr)
1216 this->setstate(ios_base::failbit);
1217}
1218
1219# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1220template <class _CharT, class _Traits>
1221inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const wchar_t* __s, ios_base::openmode __mode)
1222 : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {
1223 if (__sb_.open(__s, __mode | ios_base::in) == nullptr)
1224 this->setstate(ios_base::failbit);
1225}
1226# endif
1227
1228// extension
1229template <class _CharT, class _Traits>
1230inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const string& __s, ios_base::openmode __mode)
1231 : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {
1232 if (__sb_.open(__s, __mode | ios_base::in) == nullptr)
1233 this->setstate(ios_base::failbit);
1234}
1235
1236template <class _CharT, class _Traits>
1237inline basic_ifstream<_CharT, _Traits>::basic_ifstream(basic_ifstream&& __rhs)
1238 : basic_istream<char_type, traits_type>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
1239 this->set_rdbuf(std::addressof(__sb_));
1240}
1241
1242template <class _CharT, class _Traits>
1243inline basic_ifstream<_CharT, _Traits>& basic_ifstream<_CharT, _Traits>::operator=(basic_ifstream&& __rhs) {
1244 basic_istream<char_type, traits_type>::operator=(std::move(__rhs));
1245 __sb_ = std::move(__rhs.__sb_);
1246 return *this;
1247}
1248
1249template <class _CharT, class _Traits>
1250inline void basic_ifstream<_CharT, _Traits>::swap(basic_ifstream& __rhs) {
1251 basic_istream<char_type, traits_type>::swap(__rhs);
1252 __sb_.swap(__rhs.__sb_);
1253}
1254
1255template <class _CharT, class _Traits>
1256inline _LIBCPP_HIDE_FROM_ABI void swap(basic_ifstream<_CharT, _Traits>& __x, basic_ifstream<_CharT, _Traits>& __y) {
1257 __x.swap(__y);
1258}
1259
1260template <class _CharT, class _Traits>
1261inline basic_filebuf<_CharT, _Traits>* basic_ifstream<_CharT, _Traits>::rdbuf() const {
1262 return const_cast<basic_filebuf<char_type, traits_type>*>(std::addressof(__sb_));
1263}
1264
1265template <class _CharT, class _Traits>
1266inline bool basic_ifstream<_CharT, _Traits>::is_open() const {
1267 return __sb_.is_open();
1268}
1269
1270template <class _CharT, class _Traits>
1271void basic_ifstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
1272 if (__sb_.open(__s, __mode | ios_base::in))
1273 this->clear();
1274 else
1275 this->setstate(ios_base::failbit);
1276}
1277
1278# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1279template <class _CharT, class _Traits>
1280void basic_ifstream<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) {
1281 if (__sb_.open(__s, __mode | ios_base::in))
1282 this->clear();
1283 else
1284 this->setstate(ios_base::failbit);
1285}
1286# endif
1287
1288template <class _CharT, class _Traits>
1289void basic_ifstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode) {
1290 if (__sb_.open(__s, __mode | ios_base::in))
1291 this->clear();
1292 else
1293 this->setstate(ios_base::failbit);
1294}
1295
1296template <class _CharT, class _Traits>
1297inline void basic_ifstream<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) {
1298 if (__sb_.__open(__fd, __mode | ios_base::in))
1299 this->clear();
1300 else
1301 this->setstate(ios_base::failbit);
1302}
1303
1304template <class _CharT, class _Traits>
1305inline void basic_ifstream<_CharT, _Traits>::close() {
1306 if (__sb_.close() == 0)
1307 this->setstate(ios_base::failbit);
1308}
1309
1310// basic_ofstream
1311
1312template <class _CharT, class _Traits>
1313class basic_ofstream : public basic_ostream<_CharT, _Traits> {
1314public:
1315 typedef _CharT char_type;
1316 typedef _Traits traits_type;
1317 typedef typename traits_type::int_type int_type;
1318 typedef typename traits_type::pos_type pos_type;
1319 typedef typename traits_type::off_type off_type;
1320# if _LIBCPP_STD_VER >= 26
1321 using native_handle_type = typename basic_filebuf<_CharT, _Traits>::native_handle_type;
1322# endif
1323
1324 _LIBCPP_HIDE_FROM_ABI basic_ofstream();
1325 _LIBCPP_HIDE_FROM_ABI explicit basic_ofstream(const char* __s, ios_base::openmode __mode = ios_base::out);
1326# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1327 _LIBCPP_HIDE_FROM_ABI explicit basic_ofstream(const wchar_t* __s, ios_base::openmode __mode = ios_base::out);
1328# endif
1329 _LIBCPP_HIDE_FROM_ABI explicit basic_ofstream(const string& __s, ios_base::openmode __mode = ios_base::out);
1330
1331# if _LIBCPP_STD_VER >= 17
1332 template <class _Tp, class = enable_if_t<is_same_v<_Tp, filesystem::path>>>
1333 _LIBCPP_HIDE_FROM_ABI explicit basic_ofstream(const _Tp& __p, ios_base::openmode __mode = ios_base::out)
1334 : basic_ofstream(__p.c_str(), __mode) {}
1335# endif // _LIBCPP_STD_VER >= 17
1336
1337 _LIBCPP_HIDE_FROM_ABI basic_ofstream(basic_ofstream&& __rhs);
1338 _LIBCPP_HIDE_FROM_ABI basic_ofstream& operator=(basic_ofstream&& __rhs);
1339 _LIBCPP_HIDE_FROM_ABI void swap(basic_ofstream& __rhs);
1340
1341 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const;
1342# if _LIBCPP_STD_VER >= 26
1343 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
1344 return rdbuf()->native_handle();
1345 }
1346# endif
1347 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_open() const;
1348 void open(const char* __s, ios_base::openmode __mode = ios_base::out);
1349# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1350 void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::out);
1351# endif
1352 void open(const string& __s, ios_base::openmode __mode = ios_base::out);
1353
1354# if _LIBCPP_STD_VER >= 17
1355 _LIBCPP_HIDE_FROM_ABI void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::out) {
1356 return open(__p.c_str(), __mode);
1357 }
1358# endif // _LIBCPP_STD_VER >= 17
1359
1360 _LIBCPP_HIDE_FROM_ABI void __open(int __fd, ios_base::openmode __mode);
1361 _LIBCPP_HIDE_FROM_ABI void close();
1362
1363private:
1364 basic_filebuf<char_type, traits_type> __sb_;
1365};
1366
1367template <class _CharT, class _Traits>
1368inline basic_ofstream<_CharT, _Traits>::basic_ofstream()
1369 : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {}
1370
1371template <class _CharT, class _Traits>
1372inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const char* __s, ios_base::openmode __mode)
1373 : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {
1374 if (__sb_.open(__s, __mode | ios_base::out) == nullptr)
1375 this->setstate(ios_base::failbit);
1376}
1377
1378# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1379template <class _CharT, class _Traits>
1380inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const wchar_t* __s, ios_base::openmode __mode)
1381 : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {
1382 if (__sb_.open(__s, __mode | ios_base::out) == nullptr)
1383 this->setstate(ios_base::failbit);
1384}
1385# endif
1386
1387// extension
1388template <class _CharT, class _Traits>
1389inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const string& __s, ios_base::openmode __mode)
1390 : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {
1391 if (__sb_.open(__s, __mode | ios_base::out) == nullptr)
1392 this->setstate(ios_base::failbit);
1393}
1394
1395template <class _CharT, class _Traits>
1396inline basic_ofstream<_CharT, _Traits>::basic_ofstream(basic_ofstream&& __rhs)
1397 : basic_ostream<char_type, traits_type>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
1398 this->set_rdbuf(std::addressof(__sb_));
1399}
1400
1401template <class _CharT, class _Traits>
1402inline basic_ofstream<_CharT, _Traits>& basic_ofstream<_CharT, _Traits>::operator=(basic_ofstream&& __rhs) {
1403 basic_ostream<char_type, traits_type>::operator=(std::move(__rhs));
1404 __sb_ = std::move(__rhs.__sb_);
1405 return *this;
1406}
1407
1408template <class _CharT, class _Traits>
1409inline void basic_ofstream<_CharT, _Traits>::swap(basic_ofstream& __rhs) {
1410 basic_ostream<char_type, traits_type>::swap(__rhs);
1411 __sb_.swap(__rhs.__sb_);
1412}
1413
1414template <class _CharT, class _Traits>
1415inline _LIBCPP_HIDE_FROM_ABI void swap(basic_ofstream<_CharT, _Traits>& __x, basic_ofstream<_CharT, _Traits>& __y) {
1416 __x.swap(__y);
1417}
1418
1419template <class _CharT, class _Traits>
1420inline basic_filebuf<_CharT, _Traits>* basic_ofstream<_CharT, _Traits>::rdbuf() const {
1421 return const_cast<basic_filebuf<char_type, traits_type>*>(std::addressof(__sb_));
1422}
1423
1424template <class _CharT, class _Traits>
1425inline bool basic_ofstream<_CharT, _Traits>::is_open() const {
1426 return __sb_.is_open();
1427}
1428
1429template <class _CharT, class _Traits>
1430void basic_ofstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
1431 if (__sb_.open(__s, __mode | ios_base::out))
1432 this->clear();
1433 else
1434 this->setstate(ios_base::failbit);
1435}
1436
1437# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1438template <class _CharT, class _Traits>
1439void basic_ofstream<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) {
1440 if (__sb_.open(__s, __mode | ios_base::out))
1441 this->clear();
1442 else
1443 this->setstate(ios_base::failbit);
1444}
1445# endif
1446
1447template <class _CharT, class _Traits>
1448void basic_ofstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode) {
1449 if (__sb_.open(__s, __mode | ios_base::out))
1450 this->clear();
1451 else
1452 this->setstate(ios_base::failbit);
1453}
1454
1455template <class _CharT, class _Traits>
1456inline void basic_ofstream<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) {
1457 if (__sb_.__open(__fd, __mode | ios_base::out))
1458 this->clear();
1459 else
1460 this->setstate(ios_base::failbit);
1461}
1462
1463template <class _CharT, class _Traits>
1464inline void basic_ofstream<_CharT, _Traits>::close() {
1465 if (__sb_.close() == nullptr)
1466 this->setstate(ios_base::failbit);
1467}
1468
1469// basic_fstream
1470
1471template <class _CharT, class _Traits>
1472class basic_fstream : public basic_iostream<_CharT, _Traits> {
1473public:
1474 typedef _CharT char_type;
1475 typedef _Traits traits_type;
1476 typedef typename traits_type::int_type int_type;
1477 typedef typename traits_type::pos_type pos_type;
1478 typedef typename traits_type::off_type off_type;
1479# if _LIBCPP_STD_VER >= 26
1480 using native_handle_type = typename basic_filebuf<_CharT, _Traits>::native_handle_type;
1481# endif
1482
1483 _LIBCPP_HIDE_FROM_ABI basic_fstream();
1484 _LIBCPP_HIDE_FROM_ABI explicit basic_fstream(const char* __s,
1485 ios_base::openmode __mode = ios_base::in | ios_base::out);
1486# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1487 _LIBCPP_HIDE_FROM_ABI explicit basic_fstream(const wchar_t* __s,
1488 ios_base::openmode __mode = ios_base::in | ios_base::out);
1489# endif
1490 _LIBCPP_HIDE_FROM_ABI explicit basic_fstream(const string& __s,
1491 ios_base::openmode __mode = ios_base::in | ios_base::out);
1492
1493# if _LIBCPP_STD_VER >= 17
1494 template <class _Tp, class = enable_if_t<is_same_v<_Tp, filesystem::path>>>
1495 _LIBCPP_HIDE_FROM_ABI explicit basic_fstream(const _Tp& __p, ios_base::openmode __mode = ios_base::in | ios_base::out)
1496 : basic_fstream(__p.c_str(), __mode) {}
1497# endif // _LIBCPP_STD_VER >= 17
1498
1499 _LIBCPP_HIDE_FROM_ABI basic_fstream(basic_fstream&& __rhs);
1500
1501 _LIBCPP_HIDE_FROM_ABI basic_fstream& operator=(basic_fstream&& __rhs);
1502
1503 _LIBCPP_HIDE_FROM_ABI void swap(basic_fstream& __rhs);
1504
1505 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const;
1506# if _LIBCPP_STD_VER >= 26
1507 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
1508 return rdbuf()->native_handle();
1509 }
1510# endif
1511 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_open() const;
1512 _LIBCPP_HIDE_FROM_ABI void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
1513# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1514 void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
1515# endif
1516 _LIBCPP_HIDE_FROM_ABI void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
1517
1518# if _LIBCPP_STD_VER >= 17
1519 _LIBCPP_HIDE_FROM_ABI void
1520 open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in | ios_base::out) {
1521 return open(__p.c_str(), __mode);
1522 }
1523# endif // _LIBCPP_STD_VER >= 17
1524
1525 _LIBCPP_HIDE_FROM_ABI void close();
1526
1527private:
1528 basic_filebuf<char_type, traits_type> __sb_;
1529};
1530
1531template <class _CharT, class _Traits>
1532inline basic_fstream<_CharT, _Traits>::basic_fstream()
1533 : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {}
1534
1535template <class _CharT, class _Traits>
1536inline basic_fstream<_CharT, _Traits>::basic_fstream(const char* __s, ios_base::openmode __mode)
1537 : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {
1538 if (__sb_.open(__s, __mode) == nullptr)
1539 this->setstate(ios_base::failbit);
1540}
1541
1542# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1543template <class _CharT, class _Traits>
1544inline basic_fstream<_CharT, _Traits>::basic_fstream(const wchar_t* __s, ios_base::openmode __mode)
1545 : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {
1546 if (__sb_.open(__s, __mode) == nullptr)
1547 this->setstate(ios_base::failbit);
1548}
1549# endif
1550
1551template <class _CharT, class _Traits>
1552inline basic_fstream<_CharT, _Traits>::basic_fstream(const string& __s, ios_base::openmode __mode)
1553 : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {
1554 if (__sb_.open(__s, __mode) == nullptr)
1555 this->setstate(ios_base::failbit);
1556}
1557
1558// extension
1559template <class _CharT, class _Traits>
1560inline basic_fstream<_CharT, _Traits>::basic_fstream(basic_fstream&& __rhs)
1561 : basic_iostream<char_type, traits_type>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
1562 this->set_rdbuf(std::addressof(__sb_));
1563}
1564
1565template <class _CharT, class _Traits>
1566inline basic_fstream<_CharT, _Traits>& basic_fstream<_CharT, _Traits>::operator=(basic_fstream&& __rhs) {
1567 basic_iostream<char_type, traits_type>::operator=(std::move(__rhs));
1568 __sb_ = std::move(__rhs.__sb_);
1569 return *this;
1570}
1571
1572template <class _CharT, class _Traits>
1573inline void basic_fstream<_CharT, _Traits>::swap(basic_fstream& __rhs) {
1574 basic_iostream<char_type, traits_type>::swap(__rhs);
1575 __sb_.swap(__rhs.__sb_);
1576}
1577
1578template <class _CharT, class _Traits>
1579inline _LIBCPP_HIDE_FROM_ABI void swap(basic_fstream<_CharT, _Traits>& __x, basic_fstream<_CharT, _Traits>& __y) {
1580 __x.swap(__y);
1581}
1582
1583template <class _CharT, class _Traits>
1584inline basic_filebuf<_CharT, _Traits>* basic_fstream<_CharT, _Traits>::rdbuf() const {
1585 return const_cast<basic_filebuf<char_type, traits_type>*>(std::addressof(__sb_));
1586}
1587
1588template <class _CharT, class _Traits>
1589inline bool basic_fstream<_CharT, _Traits>::is_open() const {
1590 return __sb_.is_open();
1591}
1592
1593template <class _CharT, class _Traits>
1594void basic_fstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
1595 if (__sb_.open(__s, __mode))
1596 this->clear();
1597 else
1598 this->setstate(ios_base::failbit);
1599}
1600
1601# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1602template <class _CharT, class _Traits>
1603void basic_fstream<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) {
1604 if (__sb_.open(__s, __mode))
1605 this->clear();
1606 else
1607 this->setstate(ios_base::failbit);
1608}
1609# endif
1610
1611template <class _CharT, class _Traits>
1612void basic_fstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode) {
1613 if (__sb_.open(__s, __mode))
1614 this->clear();
1615 else
1616 this->setstate(ios_base::failbit);
1617}
1618
1619template <class _CharT, class _Traits>
1620inline void basic_fstream<_CharT, _Traits>::close() {
1621 if (__sb_.close() == nullptr)
1622 this->setstate(ios_base::failbit);
1623}
1624
1625# if _LIBCPP_AVAILABILITY_HAS_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1
1626extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ifstream<char>;
1627extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ofstream<char>;
1628extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_filebuf<char>;
1629# endif
1630
1631_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
1632_LIBCPP_END_NAMESPACE_STD
1633
1634_LIBCPP_POP_MACROS
1635
1636# endif // _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
1637
1638# if defined(_LIBCPP_KEEP_TRANSITIVE_INCLUDES_LLVM23) && _LIBCPP_STD_VER <= 20
1639# include <atomic>
1640# include <concepts>
1641# include <cstdlib>
1642# include <iosfwd>
1643# include <limits>
1644# include <mutex>
1645# include <new>
1646# include <stdexcept>
1647# include <type_traits>
1648# endif
1649
1650# if defined(_LIBCPP_KEEP_TRANSITIVE_INCLUDES_LLVM23) && _LIBCPP_STD_VER <= 23
1651# include <filesystem>
1652# endif
1653#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
1654
1655#endif // _LIBCPP_FSTREAM
1656