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