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(__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(__str, sizeof(char_type), __len, __file_);
308 }
309 return basic_streambuf<_CharT, _Traits>::xsputn(__str, __len);
310 }
311
312 _LIBCPP_HIDE_FROM_ABI_VIRTUAL streamsize xsgetn(char_type* __str, streamsize __len) override {
313 if (__file_ && __always_noconv_) {
314 char_type __1buf;
315 __read_guard __guard(__1buf, *this);
316 const streamsize __n = std::min(this->egptr() - this->gptr(), __len);
317 if (__n != 0) {
318 traits_type::copy(__str, this->gptr(), __n);
319 this->__gbump_ptrdiff(__n);
320 }
321 const streamsize __remainder = __len - __n;
322 const streamsize __buffer_space = this->egptr() - this->eback();
323
324 if (__remainder >= __buffer_space) {
325 auto __res = std::fread(__str + __n, sizeof(char_type), __remainder, __file_) + __n;
326
327 // Copy the buffer-sized tail into the buffer so that `unget`ting works correctly
328 auto __buf_size = std::min<size_t>(__res, this->egptr() - this->eback());
329 traits_type::copy(this->eback(), __str + __res - __buf_size, __buf_size);
330 this->setg(this->eback(), this->eback() + __buf_size, this->eback() + __buf_size);
331
332 return __res;
333 } else if (__remainder > 0)
334 return basic_streambuf<_CharT, _Traits>::xsgetn(__str + __n, __remainder) + __n;
335 return __n;
336 }
337 return basic_streambuf<_CharT, _Traits>::xsgetn(__str, __len);
338 }
339
340private:
341 char* __extbuf_;
342 const char* __extbufnext_;
343 const char* __extbufend_;
344 char __extbuf_min_[8];
345 size_t __ebs_;
346 char_type* __intbuf_;
347 size_t __ibs_;
348 FILE* __file_;
349 const codecvt<char_type, char, state_type>* __cv_;
350 state_type __st_;
351 state_type __st_last_;
352 ios_base::openmode __om_;
353 // There have been no file operations yet, which allows setting unbuffered
354 // I/O mode.
355 static const ios_base::openmode __no_io_operations = ios_base::trunc;
356 // Unbuffered I/O mode has been requested.
357 static const ios_base::openmode __use_unbuffered_io = ios_base::ate;
358 // Used to track the currently used mode and track whether the output should
359 // be unbuffered.
360 // [filebuf.virtuals]/12
361 // If setbuf(0, 0) is called on a stream before any I/O has occurred on
362 // that stream, the stream becomes unbuffered. Otherwise the results are
363 // implementation-defined.
364 // This allows calling setbuf(0, 0)
365 // - before opening a file,
366 // - after opening a file, before
367 // - a read
368 // - a write
369 // - a seek.
370 // Note that opening a file with ios_base::ate does a seek operation.
371 // Normally underflow, overflow, and sync change this flag to ios_base::in,
372 // ios_base_out, or 0.
373 //
374 // The ios_base::trunc and ios_base::ate flags are not used in __cm_. They
375 // are used to track the state of the unbuffered request. For readability
376 // they have the aliases __no_io_operations and __use_unbuffered_io
377 // respectively.
378 //
379 // The __no_io_operations and __use_unbuffered_io flags are used in the
380 // following way:
381 // - __no_io_operations is set upon construction to indicate the unbuffered
382 // state can be set.
383 // - When requesting unbuffered output:
384 // - If the file is open it sets the mode.
385 // - Else places a request by adding the __use_unbuffered_io flag.
386 // - When a file is opened it checks whether both __no_io_operations and
387 // __use_unbuffered_io are set. If so switches to unbuffered mode.
388 // - All file I/O operations change the mode effectively clearing the
389 // __no_io_operations and __use_unbuffered_io flags.
390 ios_base::openmode __cm_;
391 bool __owns_eb_;
392 bool __owns_ib_;
393 bool __always_noconv_;
394
395 bool __read_mode();
396
397 struct [[__nodiscard__]] __read_guard {
398 basic_filebuf& __self_;
399 size_t __unget_size_;
400 char_type& __1buf_;
401
402 _LIBCPP_HIDE_FROM_ABI __read_guard(char_type& __1buf, basic_filebuf& __self) : __self_(__self), __1buf_(__1buf) {
403 if (__self.__cm_ & ios_base::in) {
404 __unget_size_ = std::min<size_t>((__self.egptr() - __self.eback()) / 2, 4);
405 } else {
406 __self.setp(nullptr, nullptr);
407 if (__self.__always_noconv_) {
408 __self.setg(reinterpret_cast<char_type*>(__self.__extbuf_),
409 reinterpret_cast<char_type*>(__self.__extbuf_) + __self.__ebs_,
410 reinterpret_cast<char_type*>(__self.__extbuf_) + __self.__ebs_);
411 } else {
412 __self.setg(__self.__intbuf_, __self.__intbuf_ + __self.__ibs_, __self.__intbuf_ + __self.__ibs_);
413 }
414 __self.__cm_ = ios_base::in;
415 __unget_size_ = 0;
416 }
417
418 if (__self.gptr() == nullptr)
419 __self.setg(std::addressof(__1buf_), std::addressof(__1buf_) + 1, std::addressof(__1buf_) + 1);
420 }
421
422 _LIBCPP_HIDE_FROM_ABI size_t __unget_size() { return __unget_size_; }
423
424 _LIBCPP_HIDE_FROM_ABI ~__read_guard() {
425 if (__self_.eback() == std::addressof(__1buf_))
426 __self_.setg(nullptr, nullptr, nullptr);
427 }
428 };
429
430 void __write_mode();
431
432 _LIBCPP_HIDE_FROM_ABI static int __fseek(FILE* __file, pos_type __offset, int __whence);
433 _LIBCPP_HIDE_FROM_ABI static pos_type __ftell(FILE* __file);
434
435 _LIBCPP_EXPORTED_FROM_ABI friend FILE* __get_ostream_file(ostream&);
436
437 // There are multiple (__)open function, they use different C-API open
438 // function. After that call these functions behave the same. This function
439 // does that part and determines the final return value.
440 _LIBCPP_HIDE_FROM_ABI basic_filebuf* __do_open(FILE* __file, ios_base::openmode __mode) {
441 __file_ = __file;
442 if (!__file_)
443 return nullptr;
444
445 __om_ = __mode;
446 if (__cm_ == (__no_io_operations | __use_unbuffered_io)) {
447 std::setbuf(__file_, nullptr);
448 __cm_ = 0;
449 }
450
451 if (__mode & ios_base::ate) {
452 __cm_ = 0;
453 if (fseek(__file_, 0, SEEK_END)) {
454 fclose(__file_);
455 __file_ = nullptr;
456 return nullptr;
457 }
458 }
459
460 return this;
461 }
462
463 // If the file is already open, switch to unbuffered mode. Otherwise, record
464 // the request to use unbuffered mode so that we use that mode when we
465 // eventually open the file.
466 _LIBCPP_HIDE_FROM_ABI void __request_unbuffered_mode() {
467 if (__file_) {
468 std::setbuf(__file_, nullptr);
469 __cm_ = 0;
470 } else {
471 __cm_ = __no_io_operations | __use_unbuffered_io;
472 }
473 }
474
475 _LIBCPP_HIDE_FROM_ABI typename traits_type::int_type __overflow_failed() {
476 if (this->pptr() == this->epptr() + 1) {
477 this->pbump(-1); // lose the character we overflowed above -- we don't really have a
478 // choice since we couldn't commit the contents of the put area
479 }
480 return traits_type::eof();
481 }
482};
483
484template <class _CharT, class _Traits>
485basic_filebuf<_CharT, _Traits>::basic_filebuf()
486 : __extbuf_(nullptr),
487 __extbufnext_(nullptr),
488 __extbufend_(nullptr),
489 __ebs_(0),
490 __intbuf_(nullptr),
491 __ibs_(0),
492 __file_(nullptr),
493 __cv_(nullptr),
494 __st_(),
495 __st_last_(),
496 __om_(0),
497 __cm_(__no_io_operations),
498 __owns_eb_(false),
499 __owns_ib_(false),
500 __always_noconv_(false) {
501 if (std::has_facet<codecvt<char_type, char, state_type> >(this->getloc())) {
502 __cv_ = std::addressof(std::use_facet<codecvt<char_type, char, state_type> >(this->getloc()));
503 __always_noconv_ = __cv_->always_noconv();
504 }
505 setbuf(nullptr, 4096);
506}
507
508template <class _CharT, class _Traits>
509basic_filebuf<_CharT, _Traits>::basic_filebuf(basic_filebuf&& __rhs) : basic_streambuf<_CharT, _Traits>(__rhs) {
510 if (__rhs.__extbuf_ == __rhs.__extbuf_min_) {
511 __extbuf_ = __extbuf_min_;
512 __extbufnext_ = __extbuf_ + (__rhs.__extbufnext_ - __rhs.__extbuf_);
513 __extbufend_ = __extbuf_ + (__rhs.__extbufend_ - __rhs.__extbuf_);
514 } else {
515 __extbuf_ = __rhs.__extbuf_;
516 __extbufnext_ = __rhs.__extbufnext_;
517 __extbufend_ = __rhs.__extbufend_;
518 }
519 __ebs_ = __rhs.__ebs_;
520 __intbuf_ = __rhs.__intbuf_;
521 __ibs_ = __rhs.__ibs_;
522 __file_ = __rhs.__file_;
523 __cv_ = __rhs.__cv_;
524 __st_ = __rhs.__st_;
525 __st_last_ = __rhs.__st_last_;
526 __om_ = __rhs.__om_;
527 __cm_ = __rhs.__cm_;
528 __owns_eb_ = __rhs.__owns_eb_;
529 __owns_ib_ = __rhs.__owns_ib_;
530 __always_noconv_ = __rhs.__always_noconv_;
531 if (__rhs.pbase()) {
532 if (__rhs.pbase() == __rhs.__intbuf_)
533 this->setp(__intbuf_, __intbuf_ + (__rhs.epptr() - __rhs.pbase()));
534 else
535 this->setp((char_type*)__extbuf_, (char_type*)__extbuf_ + (__rhs.epptr() - __rhs.pbase()));
536 this->__pbump(__rhs.pptr() - __rhs.pbase());
537 } else if (__rhs.eback()) {
538 if (__rhs.eback() == __rhs.__intbuf_)
539 this->setg(__intbuf_, __intbuf_ + (__rhs.gptr() - __rhs.eback()), __intbuf_ + (__rhs.egptr() - __rhs.eback()));
540 else
541 this->setg((char_type*)__extbuf_,
542 (char_type*)__extbuf_ + (__rhs.gptr() - __rhs.eback()),
543 (char_type*)__extbuf_ + (__rhs.egptr() - __rhs.eback()));
544 }
545 __rhs.__extbuf_ = nullptr;
546 __rhs.__extbufnext_ = nullptr;
547 __rhs.__extbufend_ = nullptr;
548 __rhs.__ebs_ = 0;
549 __rhs.__intbuf_ = 0;
550 __rhs.__ibs_ = 0;
551 __rhs.__file_ = nullptr;
552 __rhs.__st_ = state_type();
553 __rhs.__st_last_ = state_type();
554 __rhs.__om_ = 0;
555 __rhs.__cm_ = 0;
556 __rhs.__owns_eb_ = false;
557 __rhs.__owns_ib_ = false;
558 __rhs.setg(0, 0, 0);
559 __rhs.setp(0, 0);
560}
561
562template <class _CharT, class _Traits>
563inline basic_filebuf<_CharT, _Traits>& basic_filebuf<_CharT, _Traits>::operator=(basic_filebuf&& __rhs) {
564 close();
565 swap(__rhs);
566 return *this;
567}
568
569template <class _CharT, class _Traits>
570basic_filebuf<_CharT, _Traits>::~basic_filebuf() {
571# if _LIBCPP_HAS_EXCEPTIONS
572 try {
573# endif // _LIBCPP_HAS_EXCEPTIONS
574 close();
575# if _LIBCPP_HAS_EXCEPTIONS
576 } catch (...) {
577 }
578# endif // _LIBCPP_HAS_EXCEPTIONS
579 if (__owns_eb_)
580 delete[] __extbuf_;
581 if (__owns_ib_)
582 delete[] __intbuf_;
583}
584
585template <class _CharT, class _Traits>
586void basic_filebuf<_CharT, _Traits>::swap(basic_filebuf& __rhs) {
587 basic_streambuf<char_type, traits_type>::swap(__rhs);
588 if (__extbuf_ != __extbuf_min_ && __rhs.__extbuf_ != __rhs.__extbuf_min_) {
589 // Neither *this nor __rhs uses the small buffer, so we can simply swap the pointers.
590 std::swap(__extbuf_, __rhs.__extbuf_);
591 std::swap(__extbufnext_, __rhs.__extbufnext_);
592 std::swap(__extbufend_, __rhs.__extbufend_);
593 } else {
594 ptrdiff_t __ln = __extbufnext_ ? __extbufnext_ - __extbuf_ : 0;
595 ptrdiff_t __le = __extbufend_ ? __extbufend_ - __extbuf_ : 0;
596 ptrdiff_t __rn = __rhs.__extbufnext_ ? __rhs.__extbufnext_ - __rhs.__extbuf_ : 0;
597 ptrdiff_t __re = __rhs.__extbufend_ ? __rhs.__extbufend_ - __rhs.__extbuf_ : 0;
598 if (__extbuf_ == __extbuf_min_ && __rhs.__extbuf_ != __rhs.__extbuf_min_) {
599 // *this uses the small buffer, but __rhs doesn't.
600 __extbuf_ = __rhs.__extbuf_;
601 __rhs.__extbuf_ = __rhs.__extbuf_min_;
602 std::memmove(__rhs.__extbuf_min_, __extbuf_min_, sizeof(__extbuf_min_));
603 } else if (__extbuf_ != __extbuf_min_ && __rhs.__extbuf_ == __rhs.__extbuf_min_) {
604 // *this doesn't use the small buffer, but __rhs does.
605 __rhs.__extbuf_ = __extbuf_;
606 __extbuf_ = __extbuf_min_;
607 std::memmove(__extbuf_min_, __rhs.__extbuf_min_, sizeof(__extbuf_min_));
608 } else {
609 // Both *this and __rhs use the small buffer.
610 char __tmp[sizeof(__extbuf_min_)];
611 std::memmove(__tmp, __extbuf_min_, sizeof(__extbuf_min_));
612 std::memmove(__extbuf_min_, __rhs.__extbuf_min_, sizeof(__extbuf_min_));
613 std::memmove(__rhs.__extbuf_min_, __tmp, sizeof(__extbuf_min_));
614 }
615 __extbufnext_ = __extbuf_ + __rn;
616 __extbufend_ = __extbuf_ + __re;
617 __rhs.__extbufnext_ = __rhs.__extbuf_ + __ln;
618 __rhs.__extbufend_ = __rhs.__extbuf_ + __le;
619 }
620 std::swap(__ebs_, __rhs.__ebs_);
621 std::swap(__intbuf_, __rhs.__intbuf_);
622 std::swap(__ibs_, __rhs.__ibs_);
623 std::swap(__file_, __rhs.__file_);
624 std::swap(__cv_, __rhs.__cv_);
625 std::swap(__st_, __rhs.__st_);
626 std::swap(__st_last_, __rhs.__st_last_);
627 std::swap(__om_, __rhs.__om_);
628 std::swap(__cm_, __rhs.__cm_);
629 std::swap(__owns_eb_, __rhs.__owns_eb_);
630 std::swap(__owns_ib_, __rhs.__owns_ib_);
631 std::swap(__always_noconv_, __rhs.__always_noconv_);
632 if (this->eback() == (char_type*)__rhs.__extbuf_min_) {
633 ptrdiff_t __n = this->gptr() - this->eback();
634 ptrdiff_t __e = this->egptr() - this->eback();
635 this->setg((char_type*)__extbuf_min_, (char_type*)__extbuf_min_ + __n, (char_type*)__extbuf_min_ + __e);
636 } else if (this->pbase() == (char_type*)__rhs.__extbuf_min_) {
637 ptrdiff_t __n = this->pptr() - this->pbase();
638 ptrdiff_t __e = this->epptr() - this->pbase();
639 this->setp((char_type*)__extbuf_min_, (char_type*)__extbuf_min_ + __e);
640 this->__pbump(__n);
641 }
642 if (__rhs.eback() == (char_type*)__extbuf_min_) {
643 ptrdiff_t __n = __rhs.gptr() - __rhs.eback();
644 ptrdiff_t __e = __rhs.egptr() - __rhs.eback();
645 __rhs.setg(
646 (char_type*)__rhs.__extbuf_min_, (char_type*)__rhs.__extbuf_min_ + __n, (char_type*)__rhs.__extbuf_min_ + __e);
647 } else if (__rhs.pbase() == (char_type*)__extbuf_min_) {
648 ptrdiff_t __n = __rhs.pptr() - __rhs.pbase();
649 ptrdiff_t __e = __rhs.epptr() - __rhs.pbase();
650 __rhs.setp((char_type*)__rhs.__extbuf_min_, (char_type*)__rhs.__extbuf_min_ + __e);
651 __rhs.__pbump(__n);
652 }
653}
654
655template <class _CharT, class _Traits>
656inline _LIBCPP_HIDE_FROM_ABI void swap(basic_filebuf<_CharT, _Traits>& __x, basic_filebuf<_CharT, _Traits>& __y) {
657 __x.swap(__y);
658}
659
660template <class _CharT, class _Traits>
661inline bool basic_filebuf<_CharT, _Traits>::is_open() const {
662 return __file_ != nullptr;
663}
664
665// Configures the fopen close-on-exec mode character, if any. This string will
666// be appended to any mode string used by fstream for fopen/fdopen.
667//
668// Not all platforms support this, but it helps avoid fd-leaks on platforms that
669// do.
670# if defined(__BIONIC__)
671# define _LIBCPP_FOPEN_CLOEXEC_MODE "e"
672# else
673# define _LIBCPP_FOPEN_CLOEXEC_MODE
674# endif
675
676template <class _CharT, class _Traits>
677const char* basic_filebuf<_CharT, _Traits>::__make_mdstring(ios_base::openmode __mode) _NOEXCEPT {
678 switch (__mode & ~ios_base::ate) {
679 case ios_base::out:
680 case ios_base::out | ios_base::trunc:
681 return "w" _LIBCPP_FOPEN_CLOEXEC_MODE;
682 case ios_base::out | ios_base::app:
683 case ios_base::app:
684 return "a" _LIBCPP_FOPEN_CLOEXEC_MODE;
685 case ios_base::in:
686 return "r" _LIBCPP_FOPEN_CLOEXEC_MODE;
687 case ios_base::in | ios_base::out:
688 return "r+" _LIBCPP_FOPEN_CLOEXEC_MODE;
689 case ios_base::in | ios_base::out | ios_base::trunc:
690 return "w+" _LIBCPP_FOPEN_CLOEXEC_MODE;
691 case ios_base::in | ios_base::out | ios_base::app:
692 case ios_base::in | ios_base::app:
693 return "a+" _LIBCPP_FOPEN_CLOEXEC_MODE;
694 case ios_base::out | ios_base::binary:
695 case ios_base::out | ios_base::trunc | ios_base::binary:
696 return "wb" _LIBCPP_FOPEN_CLOEXEC_MODE;
697 case ios_base::out | ios_base::app | ios_base::binary:
698 case ios_base::app | ios_base::binary:
699 return "ab" _LIBCPP_FOPEN_CLOEXEC_MODE;
700 case ios_base::in | ios_base::binary:
701 return "rb" _LIBCPP_FOPEN_CLOEXEC_MODE;
702 case ios_base::in | ios_base::out | ios_base::binary:
703 return "r+b" _LIBCPP_FOPEN_CLOEXEC_MODE;
704 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary:
705 return "w+b" _LIBCPP_FOPEN_CLOEXEC_MODE;
706 case ios_base::in | ios_base::out | ios_base::app | ios_base::binary:
707 case ios_base::in | ios_base::app | ios_base::binary:
708 return "a+b" _LIBCPP_FOPEN_CLOEXEC_MODE;
709# if _LIBCPP_STD_VER >= 23
710 case ios_base::out | ios_base::noreplace:
711 case ios_base::out | ios_base::trunc | ios_base::noreplace:
712 return "wx" _LIBCPP_FOPEN_CLOEXEC_MODE;
713 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::noreplace:
714 return "w+x" _LIBCPP_FOPEN_CLOEXEC_MODE;
715 case ios_base::out | ios_base::binary | ios_base::noreplace:
716 case ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
717 return "wbx" _LIBCPP_FOPEN_CLOEXEC_MODE;
718 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
719 return "w+bx" _LIBCPP_FOPEN_CLOEXEC_MODE;
720# endif // _LIBCPP_STD_VER >= 23
721 default:
722 return nullptr;
723 }
724 __libcpp_unreachable();
725}
726
727# if _LIBCPP_HAS_OPEN_WITH_WCHAR
728template <class _CharT, class _Traits>
729const wchar_t* basic_filebuf<_CharT, _Traits>::__make_mdwstring(ios_base::openmode __mode) _NOEXCEPT {
730 switch (__mode & ~ios_base::ate) {
731 case ios_base::out:
732 case ios_base::out | ios_base::trunc:
733 return L"w";
734 case ios_base::out | ios_base::app:
735 case ios_base::app:
736 return L"a";
737 case ios_base::in:
738 return L"r";
739 case ios_base::in | ios_base::out:
740 return L"r+";
741 case ios_base::in | ios_base::out | ios_base::trunc:
742 return L"w+";
743 case ios_base::in | ios_base::out | ios_base::app:
744 case ios_base::in | ios_base::app:
745 return L"a+";
746 case ios_base::out | ios_base::binary:
747 case ios_base::out | ios_base::trunc | ios_base::binary:
748 return L"wb";
749 case ios_base::out | ios_base::app | ios_base::binary:
750 case ios_base::app | ios_base::binary:
751 return L"ab";
752 case ios_base::in | ios_base::binary:
753 return L"rb";
754 case ios_base::in | ios_base::out | ios_base::binary:
755 return L"r+b";
756 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary:
757 return L"w+b";
758 case ios_base::in | ios_base::out | ios_base::app | ios_base::binary:
759 case ios_base::in | ios_base::app | ios_base::binary:
760 return L"a+b";
761# if _LIBCPP_STD_VER >= 23
762 case ios_base::out | ios_base::noreplace:
763 case ios_base::out | ios_base::trunc | ios_base::noreplace:
764 return L"wx";
765 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::noreplace:
766 return L"w+x";
767 case ios_base::out | ios_base::binary | ios_base::noreplace:
768 case ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
769 return L"wbx";
770 case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
771 return L"w+bx";
772# endif // _LIBCPP_STD_VER >= 23
773 default:
774 return nullptr;
775 }
776 __libcpp_unreachable();
777}
778# endif
779
780template <class _CharT, class _Traits>
781basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
782 if (__file_)
783 return nullptr;
784 const char* __mdstr = __make_mdstring(__mode);
785 if (!__mdstr)
786 return nullptr;
787
788 return __do_open(std::fopen(__s, __mdstr), __mode);
789}
790
791template <class _CharT, class _Traits>
792inline basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) {
793 if (__file_)
794 return nullptr;
795 const char* __mdstr = __make_mdstring(__mode);
796 if (!__mdstr)
797 return nullptr;
798
799 return __do_open(fdopen(__fd, __mdstr), __mode);
800}
801
802# if _LIBCPP_HAS_OPEN_WITH_WCHAR
803// This is basically the same as the char* overload except that it uses _wfopen
804// and long mode strings.
805template <class _CharT, class _Traits>
806basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) {
807 if (__file_)
808 return nullptr;
809 const wchar_t* __mdstr = __make_mdwstring(__mode);
810 if (!__mdstr)
811 return nullptr;
812
813 return __do_open(_wfopen(__s, __mdstr), __mode);
814}
815# endif
816
817template <class _CharT, class _Traits>
818inline basic_filebuf<_CharT, _Traits>*
819basic_filebuf<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode) {
820 return open(__s.c_str(), __mode);
821}
822
823template <class _CharT, class _Traits>
824basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::close() {
825 basic_filebuf<_CharT, _Traits>* __rt = nullptr;
826 if (__file_) {
827 __rt = this;
828 unique_ptr<FILE, int (*)(FILE*)> __h(__file_, fclose);
829 if (sync())
830 __rt = nullptr;
831 if (fclose(__h.release()))
832 __rt = nullptr;
833 __file_ = nullptr;
834 // Reset the get and the put areas without getting rid of the underlying buffers,
835 // which might have been configured by the user. Make sure to keep the buffers
836 // since the user may re-open the stream.
837 this->setg(nullptr, nullptr, nullptr);
838 this->setp(nullptr, nullptr);
839 __cm_ = __no_io_operations;
840 }
841 return __rt;
842}
843
844template <class _CharT, class _Traits>
845typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits>::underflow() {
846 if (__file_ == nullptr)
847 return traits_type::eof();
848
849 char_type __1buf;
850 __read_guard __guard(__1buf, *this);
851
852 const size_t __unget_sz = __guard.__unget_size();
853 int_type __c = traits_type::eof();
854 if (this->gptr() == this->egptr()) {
855 std::memmove(this->eback(), this->egptr() - __unget_sz, __unget_sz * sizeof(char_type));
856 if (__always_noconv_) {
857 size_t __nmemb = static_cast<size_t>(this->egptr() - this->eback() - __unget_sz);
858 __nmemb = std::fread(this->eback() + __unget_sz, 1, __nmemb, __file_);
859 if (__nmemb != 0) {
860 this->setg(this->eback(), this->eback() + __unget_sz, this->eback() + __unget_sz + __nmemb);
861 __c = traits_type::to_int_type(*this->gptr());
862 }
863 } else {
864 if (__extbufend_ != __extbufnext_) {
865 _LIBCPP_ASSERT_NON_NULL(__extbufnext_ != nullptr, "underflow moving from nullptr");
866 _LIBCPP_ASSERT_NON_NULL(__extbuf_ != nullptr, "underflow moving into nullptr");
867 std::memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_);
868 }
869 __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
870 __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
871 size_t __nmemb =
872 std::min(static_cast<size_t>(__ibs_ - __unget_sz), static_cast<size_t>(__extbufend_ - __extbufnext_));
873 codecvt_base::result __r;
874 __st_last_ = __st_;
875 size_t __nr = std::fread((void*)const_cast<char*>(__extbufnext_), 1, __nmemb, __file_);
876 if (__nr != 0) {
877 if (!__cv_)
878 std::__throw_bad_cast();
879
880 __extbufend_ = __extbufnext_ + __nr;
881 char_type* __inext;
882 __r = __cv_->in(
883 __st_, __extbuf_, __extbufend_, __extbufnext_, this->eback() + __unget_sz, this->eback() + __ibs_, __inext);
884 if (__r == codecvt_base::noconv) {
885 this->setg((char_type*)__extbuf_, (char_type*)__extbuf_, (char_type*)const_cast<char*>(__extbufend_));
886 __c = traits_type::to_int_type(*this->gptr());
887 } else if (__inext != this->eback() + __unget_sz) {
888 this->setg(this->eback(), this->eback() + __unget_sz, __inext);
889 __c = traits_type::to_int_type(*this->gptr());
890 }
891 }
892 }
893 } else
894 __c = traits_type::to_int_type(*this->gptr());
895 return __c;
896}
897
898template <class _CharT, class _Traits>
899typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits>::pbackfail(int_type __c) {
900 if (__file_ && this->eback() < this->gptr()) {
901 if (traits_type::eq_int_type(__c, traits_type::eof())) {
902 this->gbump(-1);
903 return traits_type::not_eof(__c);
904 }
905 if ((__om_ & ios_base::out) || traits_type::eq(traits_type::to_char_type(__c), this->gptr()[-1])) {
906 this->gbump(-1);
907 *this->gptr() = traits_type::to_char_type(__c);
908 return __c;
909 }
910 }
911 return traits_type::eof();
912}
913
914template <class _CharT, class _Traits>
915typename basic_filebuf<_CharT, _Traits>::int_type basic_filebuf<_CharT, _Traits>::overflow(int_type __c) {
916 if (__file_ == nullptr)
917 return traits_type::eof();
918 __write_mode();
919 char_type __1buf;
920 char_type* __pb_save = this->pbase();
921 char_type* __epb_save = this->epptr();
922 if (!traits_type::eq_int_type(__c, traits_type::eof())) {
923 if (this->pptr() == nullptr)
924 this->setp(std::addressof(__1buf), std::addressof(__1buf) + 1);
925 *this->pptr() = traits_type::to_char_type(__c);
926 this->pbump(1);
927 }
928
929 // There is nothing to write, early return
930 if (this->pptr() == this->pbase()) {
931 return traits_type::not_eof(__c);
932 }
933
934 if (__always_noconv_) {
935 size_t __n = static_cast<size_t>(this->pptr() - this->pbase());
936 if (std::fwrite(this->pbase(), sizeof(char_type), __n, __file_) != __n) {
937 return __overflow_failed();
938 }
939 } else {
940 if (!__cv_)
941 std::__throw_bad_cast();
942
943 // See [filebuf.virtuals]
944 char_type* __b = this->pbase();
945 char_type* __p = this->pptr();
946 const char_type* __end;
947 char* __extbuf_end = __extbuf_;
948 do {
949 codecvt_base::result __r = __cv_->out(__st_, __b, __p, __end, __extbuf_, __extbuf_ + __ebs_, __extbuf_end);
950 if (__end == __b) {
951 return __overflow_failed();
952 }
953
954 // No conversion needed: output characters directly to the file, done.
955 if (__r == codecvt_base::noconv) {
956 size_t __n = static_cast<size_t>(__p - __b);
957 if (std::fwrite(__b, 1, __n, __file_) != __n) {
958 return __overflow_failed();
959 }
960 break;
961
962 // Conversion successful: output the converted characters to the file, done.
963 } else if (__r == codecvt_base::ok) {
964 size_t __n = static_cast<size_t>(__extbuf_end - __extbuf_);
965 if (std::fwrite(__extbuf_, 1, __n, __file_) != __n) {
966 return __overflow_failed();
967 }
968 break;
969
970 // Conversion partially successful: output converted characters to the file and repeat with the
971 // remaining characters.
972 } else if (__r == codecvt_base::partial) {
973 size_t __n = static_cast<size_t>(__extbuf_end - __extbuf_);
974 if (std::fwrite(__extbuf_, 1, __n, __file_) != __n) {
975 return __overflow_failed();
976 }
977 __b = const_cast<char_type*>(__end);
978 continue;
979
980 } else {
981 return __overflow_failed();
982 }
983 } while (true);
984 }
985 this->setp(__pb_save, __epb_save);
986 return traits_type::not_eof(__c);
987}
988
989template <class _CharT, class _Traits>
990basic_streambuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::setbuf(char_type* __s, streamsize __n) {
991 this->setg(nullptr, nullptr, nullptr);
992 this->setp(nullptr, nullptr);
993 // Calling setbuf(nullptr, 0) before any i/o operation switches the stream to unbuffered mode
994 if (__cm_ == __no_io_operations && __s == nullptr && __n == 0)
995 __request_unbuffered_mode();
996 if (__owns_eb_)
997 delete[] __extbuf_;
998 if (__owns_ib_)
999 delete[] __intbuf_;
1000 __ebs_ = __n;
1001 if (__ebs_ > sizeof(__extbuf_min_)) {
1002 if (__always_noconv_ && __s) {
1003 __extbuf_ = (char*)__s;
1004 __owns_eb_ = false;
1005 } else {
1006 __extbuf_ = new char[__ebs_];
1007 __owns_eb_ = true;
1008 }
1009 } else {
1010 __extbuf_ = __extbuf_min_;
1011 __ebs_ = sizeof(__extbuf_min_);
1012 __owns_eb_ = false;
1013 }
1014 if (!__always_noconv_) {
1015 __ibs_ = max<streamsize>(__n, sizeof(__extbuf_min_));
1016 if (__s && __ibs_ > sizeof(__extbuf_min_)) {
1017 __intbuf_ = __s;
1018 __owns_ib_ = false;
1019 } else {
1020 __intbuf_ = new char_type[__ibs_];
1021 __owns_ib_ = true;
1022 }
1023 } else {
1024 __ibs_ = 0;
1025 __intbuf_ = nullptr;
1026 __owns_ib_ = false;
1027 }
1028 return this;
1029}
1030
1031template <class _CharT, class _Traits>
1032typename basic_filebuf<_CharT, _Traits>::pos_type
1033basic_filebuf<_CharT, _Traits>::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode) {
1034 if (!__cv_)
1035 std::__throw_bad_cast();
1036
1037 int __width = __cv_->encoding();
1038 if (__file_ == nullptr || (__width <= 0 && __off != 0) || sync())
1039 return pos_type(off_type(-1));
1040 // __width > 0 || __off == 0
1041 int __whence;
1042 switch (__way) {
1043 case ios_base::beg:
1044 __whence = SEEK_SET;
1045 break;
1046 case ios_base::cur:
1047 __whence = SEEK_CUR;
1048 break;
1049 case ios_base::end:
1050 __whence = SEEK_END;
1051 break;
1052 default:
1053 return pos_type(off_type(-1));
1054 }
1055 if (__fseek(__file_, __width > 0 ? __width * __off : 0, __whence))
1056 return pos_type(off_type(-1));
1057 pos_type __r = __ftell(__file_);
1058 __r.state(__st_);
1059 return __r;
1060}
1061
1062template <class _CharT, class _Traits>
1063int basic_filebuf<_CharT, _Traits>::__fseek(FILE* __file, pos_type __offset, int __whence) {
1064# if defined(_LIBCPP_MSVCRT_LIKE)
1065 return _fseeki64(__file, __offset, __whence);
1066# elif _LIBCPP_LIBC_NEWLIB
1067 return fseek(__file, __offset, __whence);
1068# else
1069 return ::fseeko(__file, __offset, __whence);
1070# endif
1071}
1072
1073template <class _CharT, class _Traits>
1074typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>::__ftell(FILE* __file) {
1075# if defined(_LIBCPP_MSVCRT_LIKE)
1076 return _ftelli64(__file);
1077# elif _LIBCPP_LIBC_NEWLIB
1078 return ftell(__file);
1079# else
1080 return ftello(__file);
1081# endif
1082}
1083
1084template <class _CharT, class _Traits>
1085typename basic_filebuf<_CharT, _Traits>::pos_type
1086basic_filebuf<_CharT, _Traits>::seekpos(pos_type __sp, ios_base::openmode) {
1087 if (__file_ == nullptr || sync())
1088 return pos_type(off_type(-1));
1089 if (__fseek(__file_, __sp, SEEK_SET))
1090 return pos_type(off_type(-1));
1091 __st_ = __sp.state();
1092 return __sp;
1093}
1094
1095template <class _CharT, class _Traits>
1096int basic_filebuf<_CharT, _Traits>::sync() {
1097 if (__file_ == nullptr)
1098 return 0;
1099 if (!__cv_)
1100 std::__throw_bad_cast();
1101
1102 if (__cm_ & ios_base::out) {
1103 if (this->pptr() != this->pbase())
1104 if (overflow() == traits_type::eof())
1105 return -1;
1106 codecvt_base::result __r;
1107 do {
1108 char* __extbe;
1109 __r = __cv_->unshift(__st_, __extbuf_, __extbuf_ + __ebs_, __extbe);
1110 size_t __nmemb = static_cast<size_t>(__extbe - __extbuf_);
1111 if (std::fwrite(__extbuf_, 1, __nmemb, __file_) != __nmemb)
1112 return -1;
1113 } while (__r == codecvt_base::partial);
1114 if (__r == codecvt_base::error)
1115 return -1;
1116 if (std::fflush(__file_))
1117 return -1;
1118 } else if (__cm_ & ios_base::in) {
1119 off_type __c;
1120 state_type __state = __st_last_;
1121 bool __update_st = false;
1122 if (__always_noconv_)
1123 __c = this->egptr() - this->gptr();
1124 else {
1125 int __width = __cv_->encoding();
1126 __c = __extbufend_ - __extbufnext_;
1127 if (__width > 0)
1128 __c += __width * (this->egptr() - this->gptr());
1129 else {
1130 if (this->gptr() != this->egptr()) {
1131 const int __off = __cv_->length(__state, __extbuf_, __extbufnext_, this->gptr() - this->eback());
1132 __c += __extbufnext_ - __extbuf_ - __off;
1133 __update_st = true;
1134 }
1135 }
1136 }
1137 if (__fseek(__file_, -__c, SEEK_CUR))
1138 return -1;
1139 if (__update_st)
1140 __st_ = __state;
1141 __extbufnext_ = __extbufend_ = __extbuf_;
1142 this->setg(nullptr, nullptr, nullptr);
1143 __cm_ = 0;
1144 }
1145 return 0;
1146}
1147
1148template <class _CharT, class _Traits>
1149void basic_filebuf<_CharT, _Traits>::imbue(const locale& __loc) {
1150 sync();
1151 __cv_ = std::addressof(std::use_facet<codecvt<char_type, char, state_type> >(__loc));
1152 bool __old_anc = __always_noconv_;
1153 __always_noconv_ = __cv_->always_noconv();
1154 if (__old_anc != __always_noconv_) {
1155 this->setg(nullptr, nullptr, nullptr);
1156 this->setp(nullptr, nullptr);
1157 // invariant, char_type is char, else we couldn't get here
1158 if (__always_noconv_) // need to dump __intbuf_
1159 {
1160 if (__owns_eb_)
1161 delete[] __extbuf_;
1162 __owns_eb_ = __owns_ib_;
1163 __ebs_ = __ibs_;
1164 __extbuf_ = (char*)__intbuf_;
1165 __ibs_ = 0;
1166 __intbuf_ = nullptr;
1167 __owns_ib_ = false;
1168 } else // need to obtain an __intbuf_.
1169 { // If __extbuf_ is user-supplied, use it, else new __intbuf_
1170 if (!__owns_eb_ && __extbuf_ != __extbuf_min_) {
1171 __ibs_ = __ebs_;
1172 __intbuf_ = (char_type*)__extbuf_;
1173 __owns_ib_ = false;
1174 __extbuf_ = new char[__ebs_];
1175 __owns_eb_ = true;
1176 } else {
1177 __ibs_ = __ebs_;
1178 __intbuf_ = new char_type[__ibs_];
1179 __owns_ib_ = true;
1180 }
1181 }
1182 }
1183}
1184
1185template <class _CharT, class _Traits>
1186void basic_filebuf<_CharT, _Traits>::__write_mode() {
1187 if (!(__cm_ & ios_base::out)) {
1188 this->setg(nullptr, nullptr, nullptr);
1189 if (__ebs_ > sizeof(__extbuf_min_)) {
1190 if (__always_noconv_)
1191 this->setp((char_type*)__extbuf_, (char_type*)__extbuf_ + (__ebs_ - 1));
1192 else
1193 this->setp(__intbuf_, __intbuf_ + (__ibs_ - 1));
1194 } else
1195 this->setp(nullptr, nullptr);
1196 __cm_ = ios_base::out;
1197 }
1198}
1199
1200// basic_ifstream
1201
1202template <class _CharT, class _Traits>
1203class basic_ifstream : public basic_istream<_CharT, _Traits> {
1204public:
1205 typedef _CharT char_type;
1206 typedef _Traits traits_type;
1207 typedef typename traits_type::int_type int_type;
1208 typedef typename traits_type::pos_type pos_type;
1209 typedef typename traits_type::off_type off_type;
1210# if _LIBCPP_STD_VER >= 26
1211 using native_handle_type = typename basic_filebuf<_CharT, _Traits>::native_handle_type;
1212# endif
1213
1214 _LIBCPP_HIDE_FROM_ABI basic_ifstream();
1215 _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in);
1216# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1217 _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const wchar_t* __s, ios_base::openmode __mode = ios_base::in);
1218# endif
1219 _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const string& __s, ios_base::openmode __mode = ios_base::in);
1220# if _LIBCPP_STD_VER >= 17
1221 template <class _Tp, class = enable_if_t<is_same_v<_Tp, filesystem::path>>>
1222 _LIBCPP_HIDE_FROM_ABI explicit basic_ifstream(const _Tp& __p, ios_base::openmode __mode = ios_base::in)
1223 : basic_ifstream(__p.c_str(), __mode) {}
1224# endif // _LIBCPP_STD_VER >= 17
1225 _LIBCPP_HIDE_FROM_ABI basic_ifstream(basic_ifstream&& __rhs);
1226 _LIBCPP_HIDE_FROM_ABI basic_ifstream& operator=(basic_ifstream&& __rhs);
1227 _LIBCPP_HIDE_FROM_ABI void swap(basic_ifstream& __rhs);
1228
1229 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const;
1230# if _LIBCPP_STD_VER >= 26
1231 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
1232 return rdbuf()->native_handle();
1233 }
1234# endif
1235 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_open() const;
1236 void open(const char* __s, ios_base::openmode __mode = ios_base::in);
1237# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1238 void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in);
1239# endif
1240 void open(const string& __s, ios_base::openmode __mode = ios_base::in);
1241# if _LIBCPP_STD_VER >= 17
1242 _LIBCPP_HIDE_FROM_ABI void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in) {
1243 return open(__p.c_str(), __mode);
1244 }
1245# endif // _LIBCPP_STD_VER >= 17
1246
1247 _LIBCPP_HIDE_FROM_ABI void __open(int __fd, ios_base::openmode __mode);
1248 _LIBCPP_HIDE_FROM_ABI void close();
1249
1250private:
1251 basic_filebuf<char_type, traits_type> __sb_;
1252};
1253
1254template <class _CharT, class _Traits>
1255inline basic_ifstream<_CharT, _Traits>::basic_ifstream()
1256 : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {}
1257
1258template <class _CharT, class _Traits>
1259inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const char* __s, ios_base::openmode __mode)
1260 : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {
1261 if (__sb_.open(__s, __mode | ios_base::in) == nullptr)
1262 this->setstate(ios_base::failbit);
1263}
1264
1265# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1266template <class _CharT, class _Traits>
1267inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const wchar_t* __s, ios_base::openmode __mode)
1268 : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {
1269 if (__sb_.open(__s, __mode | ios_base::in) == nullptr)
1270 this->setstate(ios_base::failbit);
1271}
1272# endif
1273
1274// extension
1275template <class _CharT, class _Traits>
1276inline basic_ifstream<_CharT, _Traits>::basic_ifstream(const string& __s, ios_base::openmode __mode)
1277 : basic_istream<char_type, traits_type>(std::addressof(__sb_)) {
1278 if (__sb_.open(__s, __mode | ios_base::in) == nullptr)
1279 this->setstate(ios_base::failbit);
1280}
1281
1282template <class _CharT, class _Traits>
1283inline basic_ifstream<_CharT, _Traits>::basic_ifstream(basic_ifstream&& __rhs)
1284 : basic_istream<char_type, traits_type>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
1285 this->set_rdbuf(std::addressof(__sb_));
1286}
1287
1288template <class _CharT, class _Traits>
1289inline basic_ifstream<_CharT, _Traits>& basic_ifstream<_CharT, _Traits>::operator=(basic_ifstream&& __rhs) {
1290 basic_istream<char_type, traits_type>::operator=(std::move(__rhs));
1291 __sb_ = std::move(__rhs.__sb_);
1292 return *this;
1293}
1294
1295template <class _CharT, class _Traits>
1296inline void basic_ifstream<_CharT, _Traits>::swap(basic_ifstream& __rhs) {
1297 basic_istream<char_type, traits_type>::swap(__rhs);
1298 __sb_.swap(__rhs.__sb_);
1299}
1300
1301template <class _CharT, class _Traits>
1302inline _LIBCPP_HIDE_FROM_ABI void swap(basic_ifstream<_CharT, _Traits>& __x, basic_ifstream<_CharT, _Traits>& __y) {
1303 __x.swap(__y);
1304}
1305
1306template <class _CharT, class _Traits>
1307inline basic_filebuf<_CharT, _Traits>* basic_ifstream<_CharT, _Traits>::rdbuf() const {
1308 return const_cast<basic_filebuf<char_type, traits_type>*>(std::addressof(__sb_));
1309}
1310
1311template <class _CharT, class _Traits>
1312inline bool basic_ifstream<_CharT, _Traits>::is_open() const {
1313 return __sb_.is_open();
1314}
1315
1316template <class _CharT, class _Traits>
1317void basic_ifstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
1318 if (__sb_.open(__s, __mode | ios_base::in))
1319 this->clear();
1320 else
1321 this->setstate(ios_base::failbit);
1322}
1323
1324# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1325template <class _CharT, class _Traits>
1326void basic_ifstream<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) {
1327 if (__sb_.open(__s, __mode | ios_base::in))
1328 this->clear();
1329 else
1330 this->setstate(ios_base::failbit);
1331}
1332# endif
1333
1334template <class _CharT, class _Traits>
1335void basic_ifstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode) {
1336 if (__sb_.open(__s, __mode | ios_base::in))
1337 this->clear();
1338 else
1339 this->setstate(ios_base::failbit);
1340}
1341
1342template <class _CharT, class _Traits>
1343inline void basic_ifstream<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) {
1344 if (__sb_.__open(__fd, __mode | ios_base::in))
1345 this->clear();
1346 else
1347 this->setstate(ios_base::failbit);
1348}
1349
1350template <class _CharT, class _Traits>
1351inline void basic_ifstream<_CharT, _Traits>::close() {
1352 if (__sb_.close() == 0)
1353 this->setstate(ios_base::failbit);
1354}
1355
1356// basic_ofstream
1357
1358template <class _CharT, class _Traits>
1359class basic_ofstream : public basic_ostream<_CharT, _Traits> {
1360public:
1361 typedef _CharT char_type;
1362 typedef _Traits traits_type;
1363 typedef typename traits_type::int_type int_type;
1364 typedef typename traits_type::pos_type pos_type;
1365 typedef typename traits_type::off_type off_type;
1366# if _LIBCPP_STD_VER >= 26
1367 using native_handle_type = typename basic_filebuf<_CharT, _Traits>::native_handle_type;
1368# endif
1369
1370 _LIBCPP_HIDE_FROM_ABI basic_ofstream();
1371 _LIBCPP_HIDE_FROM_ABI explicit basic_ofstream(const char* __s, ios_base::openmode __mode = ios_base::out);
1372# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1373 _LIBCPP_HIDE_FROM_ABI explicit basic_ofstream(const wchar_t* __s, ios_base::openmode __mode = ios_base::out);
1374# endif
1375 _LIBCPP_HIDE_FROM_ABI explicit basic_ofstream(const string& __s, ios_base::openmode __mode = ios_base::out);
1376
1377# if _LIBCPP_STD_VER >= 17
1378 template <class _Tp, class = enable_if_t<is_same_v<_Tp, filesystem::path>>>
1379 _LIBCPP_HIDE_FROM_ABI explicit basic_ofstream(const _Tp& __p, ios_base::openmode __mode = ios_base::out)
1380 : basic_ofstream(__p.c_str(), __mode) {}
1381# endif // _LIBCPP_STD_VER >= 17
1382
1383 _LIBCPP_HIDE_FROM_ABI basic_ofstream(basic_ofstream&& __rhs);
1384 _LIBCPP_HIDE_FROM_ABI basic_ofstream& operator=(basic_ofstream&& __rhs);
1385 _LIBCPP_HIDE_FROM_ABI void swap(basic_ofstream& __rhs);
1386
1387 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const;
1388# if _LIBCPP_STD_VER >= 26
1389 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
1390 return rdbuf()->native_handle();
1391 }
1392# endif
1393 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_open() const;
1394 void open(const char* __s, ios_base::openmode __mode = ios_base::out);
1395# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1396 void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::out);
1397# endif
1398 void open(const string& __s, ios_base::openmode __mode = ios_base::out);
1399
1400# if _LIBCPP_STD_VER >= 17
1401 _LIBCPP_HIDE_FROM_ABI void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::out) {
1402 return open(__p.c_str(), __mode);
1403 }
1404# endif // _LIBCPP_STD_VER >= 17
1405
1406 _LIBCPP_HIDE_FROM_ABI void __open(int __fd, ios_base::openmode __mode);
1407 _LIBCPP_HIDE_FROM_ABI void close();
1408
1409private:
1410 basic_filebuf<char_type, traits_type> __sb_;
1411};
1412
1413template <class _CharT, class _Traits>
1414inline basic_ofstream<_CharT, _Traits>::basic_ofstream()
1415 : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {}
1416
1417template <class _CharT, class _Traits>
1418inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const char* __s, ios_base::openmode __mode)
1419 : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {
1420 if (__sb_.open(__s, __mode | ios_base::out) == nullptr)
1421 this->setstate(ios_base::failbit);
1422}
1423
1424# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1425template <class _CharT, class _Traits>
1426inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const wchar_t* __s, ios_base::openmode __mode)
1427 : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {
1428 if (__sb_.open(__s, __mode | ios_base::out) == nullptr)
1429 this->setstate(ios_base::failbit);
1430}
1431# endif
1432
1433// extension
1434template <class _CharT, class _Traits>
1435inline basic_ofstream<_CharT, _Traits>::basic_ofstream(const string& __s, ios_base::openmode __mode)
1436 : basic_ostream<char_type, traits_type>(std::addressof(__sb_)) {
1437 if (__sb_.open(__s, __mode | ios_base::out) == nullptr)
1438 this->setstate(ios_base::failbit);
1439}
1440
1441template <class _CharT, class _Traits>
1442inline basic_ofstream<_CharT, _Traits>::basic_ofstream(basic_ofstream&& __rhs)
1443 : basic_ostream<char_type, traits_type>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
1444 this->set_rdbuf(std::addressof(__sb_));
1445}
1446
1447template <class _CharT, class _Traits>
1448inline basic_ofstream<_CharT, _Traits>& basic_ofstream<_CharT, _Traits>::operator=(basic_ofstream&& __rhs) {
1449 basic_ostream<char_type, traits_type>::operator=(std::move(__rhs));
1450 __sb_ = std::move(__rhs.__sb_);
1451 return *this;
1452}
1453
1454template <class _CharT, class _Traits>
1455inline void basic_ofstream<_CharT, _Traits>::swap(basic_ofstream& __rhs) {
1456 basic_ostream<char_type, traits_type>::swap(__rhs);
1457 __sb_.swap(__rhs.__sb_);
1458}
1459
1460template <class _CharT, class _Traits>
1461inline _LIBCPP_HIDE_FROM_ABI void swap(basic_ofstream<_CharT, _Traits>& __x, basic_ofstream<_CharT, _Traits>& __y) {
1462 __x.swap(__y);
1463}
1464
1465template <class _CharT, class _Traits>
1466inline basic_filebuf<_CharT, _Traits>* basic_ofstream<_CharT, _Traits>::rdbuf() const {
1467 return const_cast<basic_filebuf<char_type, traits_type>*>(std::addressof(__sb_));
1468}
1469
1470template <class _CharT, class _Traits>
1471inline bool basic_ofstream<_CharT, _Traits>::is_open() const {
1472 return __sb_.is_open();
1473}
1474
1475template <class _CharT, class _Traits>
1476void basic_ofstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
1477 if (__sb_.open(__s, __mode | ios_base::out))
1478 this->clear();
1479 else
1480 this->setstate(ios_base::failbit);
1481}
1482
1483# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1484template <class _CharT, class _Traits>
1485void basic_ofstream<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) {
1486 if (__sb_.open(__s, __mode | ios_base::out))
1487 this->clear();
1488 else
1489 this->setstate(ios_base::failbit);
1490}
1491# endif
1492
1493template <class _CharT, class _Traits>
1494void basic_ofstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode) {
1495 if (__sb_.open(__s, __mode | ios_base::out))
1496 this->clear();
1497 else
1498 this->setstate(ios_base::failbit);
1499}
1500
1501template <class _CharT, class _Traits>
1502inline void basic_ofstream<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) {
1503 if (__sb_.__open(__fd, __mode | ios_base::out))
1504 this->clear();
1505 else
1506 this->setstate(ios_base::failbit);
1507}
1508
1509template <class _CharT, class _Traits>
1510inline void basic_ofstream<_CharT, _Traits>::close() {
1511 if (__sb_.close() == nullptr)
1512 this->setstate(ios_base::failbit);
1513}
1514
1515// basic_fstream
1516
1517template <class _CharT, class _Traits>
1518class basic_fstream : public basic_iostream<_CharT, _Traits> {
1519public:
1520 typedef _CharT char_type;
1521 typedef _Traits traits_type;
1522 typedef typename traits_type::int_type int_type;
1523 typedef typename traits_type::pos_type pos_type;
1524 typedef typename traits_type::off_type off_type;
1525# if _LIBCPP_STD_VER >= 26
1526 using native_handle_type = typename basic_filebuf<_CharT, _Traits>::native_handle_type;
1527# endif
1528
1529 _LIBCPP_HIDE_FROM_ABI basic_fstream();
1530 _LIBCPP_HIDE_FROM_ABI explicit basic_fstream(const char* __s,
1531 ios_base::openmode __mode = ios_base::in | ios_base::out);
1532# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1533 _LIBCPP_HIDE_FROM_ABI explicit basic_fstream(const wchar_t* __s,
1534 ios_base::openmode __mode = ios_base::in | ios_base::out);
1535# endif
1536 _LIBCPP_HIDE_FROM_ABI explicit basic_fstream(const string& __s,
1537 ios_base::openmode __mode = ios_base::in | ios_base::out);
1538
1539# if _LIBCPP_STD_VER >= 17
1540 template <class _Tp, class = enable_if_t<is_same_v<_Tp, filesystem::path>>>
1541 _LIBCPP_HIDE_FROM_ABI explicit basic_fstream(const _Tp& __p, ios_base::openmode __mode = ios_base::in | ios_base::out)
1542 : basic_fstream(__p.c_str(), __mode) {}
1543# endif // _LIBCPP_STD_VER >= 17
1544
1545 _LIBCPP_HIDE_FROM_ABI basic_fstream(basic_fstream&& __rhs);
1546
1547 _LIBCPP_HIDE_FROM_ABI basic_fstream& operator=(basic_fstream&& __rhs);
1548
1549 _LIBCPP_HIDE_FROM_ABI void swap(basic_fstream& __rhs);
1550
1551 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const;
1552# if _LIBCPP_STD_VER >= 26
1553 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
1554 return rdbuf()->native_handle();
1555 }
1556# endif
1557 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_open() const;
1558 _LIBCPP_HIDE_FROM_ABI void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
1559# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1560 void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
1561# endif
1562 _LIBCPP_HIDE_FROM_ABI void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
1563
1564# if _LIBCPP_STD_VER >= 17
1565 _LIBCPP_HIDE_FROM_ABI void
1566 open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in | ios_base::out) {
1567 return open(__p.c_str(), __mode);
1568 }
1569# endif // _LIBCPP_STD_VER >= 17
1570
1571 _LIBCPP_HIDE_FROM_ABI void close();
1572
1573private:
1574 basic_filebuf<char_type, traits_type> __sb_;
1575};
1576
1577template <class _CharT, class _Traits>
1578inline basic_fstream<_CharT, _Traits>::basic_fstream()
1579 : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {}
1580
1581template <class _CharT, class _Traits>
1582inline basic_fstream<_CharT, _Traits>::basic_fstream(const char* __s, ios_base::openmode __mode)
1583 : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {
1584 if (__sb_.open(__s, __mode) == nullptr)
1585 this->setstate(ios_base::failbit);
1586}
1587
1588# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1589template <class _CharT, class _Traits>
1590inline basic_fstream<_CharT, _Traits>::basic_fstream(const wchar_t* __s, ios_base::openmode __mode)
1591 : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {
1592 if (__sb_.open(__s, __mode) == nullptr)
1593 this->setstate(ios_base::failbit);
1594}
1595# endif
1596
1597template <class _CharT, class _Traits>
1598inline basic_fstream<_CharT, _Traits>::basic_fstream(const string& __s, ios_base::openmode __mode)
1599 : basic_iostream<char_type, traits_type>(std::addressof(__sb_)) {
1600 if (__sb_.open(__s, __mode) == nullptr)
1601 this->setstate(ios_base::failbit);
1602}
1603
1604// extension
1605template <class _CharT, class _Traits>
1606inline basic_fstream<_CharT, _Traits>::basic_fstream(basic_fstream&& __rhs)
1607 : basic_iostream<char_type, traits_type>(std::move(__rhs)), __sb_(std::move(__rhs.__sb_)) {
1608 this->set_rdbuf(std::addressof(__sb_));
1609}
1610
1611template <class _CharT, class _Traits>
1612inline basic_fstream<_CharT, _Traits>& basic_fstream<_CharT, _Traits>::operator=(basic_fstream&& __rhs) {
1613 basic_iostream<char_type, traits_type>::operator=(std::move(__rhs));
1614 __sb_ = std::move(__rhs.__sb_);
1615 return *this;
1616}
1617
1618template <class _CharT, class _Traits>
1619inline void basic_fstream<_CharT, _Traits>::swap(basic_fstream& __rhs) {
1620 basic_iostream<char_type, traits_type>::swap(__rhs);
1621 __sb_.swap(__rhs.__sb_);
1622}
1623
1624template <class _CharT, class _Traits>
1625inline _LIBCPP_HIDE_FROM_ABI void swap(basic_fstream<_CharT, _Traits>& __x, basic_fstream<_CharT, _Traits>& __y) {
1626 __x.swap(__y);
1627}
1628
1629template <class _CharT, class _Traits>
1630inline basic_filebuf<_CharT, _Traits>* basic_fstream<_CharT, _Traits>::rdbuf() const {
1631 return const_cast<basic_filebuf<char_type, traits_type>*>(std::addressof(__sb_));
1632}
1633
1634template <class _CharT, class _Traits>
1635inline bool basic_fstream<_CharT, _Traits>::is_open() const {
1636 return __sb_.is_open();
1637}
1638
1639template <class _CharT, class _Traits>
1640void basic_fstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
1641 if (__sb_.open(__s, __mode))
1642 this->clear();
1643 else
1644 this->setstate(ios_base::failbit);
1645}
1646
1647# if _LIBCPP_HAS_OPEN_WITH_WCHAR
1648template <class _CharT, class _Traits>
1649void basic_fstream<_CharT, _Traits>::open(const wchar_t* __s, ios_base::openmode __mode) {
1650 if (__sb_.open(__s, __mode))
1651 this->clear();
1652 else
1653 this->setstate(ios_base::failbit);
1654}
1655# endif
1656
1657template <class _CharT, class _Traits>
1658void basic_fstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mode) {
1659 if (__sb_.open(__s, __mode))
1660 this->clear();
1661 else
1662 this->setstate(ios_base::failbit);
1663}
1664
1665template <class _CharT, class _Traits>
1666inline void basic_fstream<_CharT, _Traits>::close() {
1667 if (__sb_.close() == nullptr)
1668 this->setstate(ios_base::failbit);
1669}
1670
1671# if _LIBCPP_AVAILABILITY_HAS_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1
1672extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ifstream<char>;
1673extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ofstream<char>;
1674extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_filebuf<char>;
1675# endif
1676
1677_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
1678_LIBCPP_END_NAMESPACE_STD
1679
1680_LIBCPP_POP_MACROS
1681
1682# endif // _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
1683
1684# if defined(_LIBCPP_KEEP_TRANSITIVE_INCLUDES_LLVM23) && _LIBCPP_STD_VER <= 20
1685# include <atomic>
1686# include <concepts>
1687# include <cstdlib>
1688# include <iosfwd>
1689# include <limits>
1690# include <mutex>
1691# include <new>
1692# include <stdexcept>
1693# include <type_traits>
1694# endif
1695
1696# if defined(_LIBCPP_KEEP_TRANSITIVE_INCLUDES_LLVM23) && _LIBCPP_STD_VER <= 23
1697# include <filesystem>
1698# endif
1699#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
1700
1701#endif // _LIBCPP_FSTREAM