xref: /freebsd/contrib/llvm-project/libcxx/include/streambuf (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
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_STREAMBUF
11#define _LIBCPP_STREAMBUF
12
13/*
14    streambuf synopsis
15
16namespace std
17{
18
19template <class charT, class traits = char_traits<charT> >
20class basic_streambuf
21{
22public:
23    // types:
24    typedef charT char_type;
25    typedef traits traits_type;
26    typedef typename traits_type::int_type int_type;
27    typedef typename traits_type::pos_type pos_type;
28    typedef typename traits_type::off_type off_type;
29
30    virtual ~basic_streambuf();
31
32    // 27.6.2.2.1 locales:
33    locale pubimbue(const locale& loc);
34    locale getloc() const;
35
36    // 27.6.2.2.2 buffer and positioning:
37    basic_streambuf* pubsetbuf(char_type* s, streamsize n);
38    pos_type pubseekoff(off_type off, ios_base::seekdir way,
39                        ios_base::openmode which = ios_base::in | ios_base::out);
40    pos_type pubseekpos(pos_type sp,
41                        ios_base::openmode which = ios_base::in | ios_base::out);
42    int pubsync();
43
44    // Get and put areas:
45    // 27.6.2.2.3 Get area:
46    streamsize in_avail();
47    int_type snextc();
48    int_type sbumpc();
49    int_type sgetc();
50    streamsize sgetn(char_type* s, streamsize n);
51
52    // 27.6.2.2.4 Putback:
53    int_type sputbackc(char_type c);
54    int_type sungetc();
55
56    // 27.6.2.2.5 Put area:
57    int_type sputc(char_type c);
58    streamsize sputn(const char_type* s, streamsize n);
59
60protected:
61    basic_streambuf();
62    basic_streambuf(const basic_streambuf& rhs);
63    basic_streambuf& operator=(const basic_streambuf& rhs);
64    void swap(basic_streambuf& rhs);
65
66    // 27.6.2.3.2 Get area:
67    char_type* eback() const;
68    char_type* gptr() const;
69    char_type* egptr() const;
70    void gbump(int n);
71    void setg(char_type* gbeg, char_type* gnext, char_type* gend);
72
73    // 27.6.2.3.3 Put area:
74    char_type* pbase() const;
75    char_type* pptr() const;
76    char_type* epptr() const;
77    void pbump(int n);
78    void setp(char_type* pbeg, char_type* pend);
79
80    // 27.6.2.4 virtual functions:
81    // 27.6.2.4.1 Locales:
82    virtual void imbue(const locale& loc);
83
84    // 27.6.2.4.2 Buffer management and positioning:
85    virtual basic_streambuf* setbuf(char_type* s, streamsize n);
86    virtual pos_type seekoff(off_type off, ios_base::seekdir way,
87                             ios_base::openmode which = ios_base::in | ios_base::out);
88    virtual pos_type seekpos(pos_type sp,
89                             ios_base::openmode which = ios_base::in | ios_base::out);
90    virtual int sync();
91
92    // 27.6.2.4.3 Get area:
93    virtual streamsize showmanyc();
94    virtual streamsize xsgetn(char_type* s, streamsize n);
95    virtual int_type underflow();
96    virtual int_type uflow();
97
98    // 27.6.2.4.4 Putback:
99    virtual int_type pbackfail(int_type c = traits_type::eof());
100
101    // 27.6.2.4.5 Put area:
102    virtual streamsize xsputn(const char_type* s, streamsize n);
103    virtual int_type overflow (int_type c = traits_type::eof());
104};
105
106}  // std
107
108*/
109
110#include <__config>
111#include <cstdint>
112#include <ios>
113#include <iosfwd>
114#include <version>
115
116#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
117#pragma GCC system_header
118#endif
119
120_LIBCPP_PUSH_MACROS
121#include <__undef_macros>
122
123_LIBCPP_BEGIN_NAMESPACE_STD
124
125template <class _CharT, class _Traits>
126class _LIBCPP_TEMPLATE_VIS basic_streambuf
127{
128public:
129    // types:
130    typedef _CharT                         char_type;
131    typedef _Traits                        traits_type;
132    typedef typename traits_type::int_type int_type;
133    typedef typename traits_type::pos_type pos_type;
134    typedef typename traits_type::off_type off_type;
135
136    static_assert((is_same<_CharT, typename traits_type::char_type>::value),
137                  "traits_type::char_type must be the same type as CharT");
138
139    virtual ~basic_streambuf();
140
141    // 27.6.2.2.1 locales:
142    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
143    locale pubimbue(const locale& __loc) {
144        imbue(__loc);
145        locale __r = __loc_;
146        __loc_ = __loc;
147        return __r;
148    }
149
150    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
151    locale getloc() const { return __loc_; }
152
153    // 27.6.2.2.2 buffer and positioning:
154    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
155    basic_streambuf* pubsetbuf(char_type* __s, streamsize __n)
156    { return setbuf(__s, __n); }
157
158    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
159    pos_type pubseekoff(off_type __off, ios_base::seekdir __way,
160                        ios_base::openmode __which = ios_base::in | ios_base::out)
161    { return seekoff(__off, __way, __which); }
162
163    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
164    pos_type pubseekpos(pos_type __sp,
165                        ios_base::openmode __which = ios_base::in | ios_base::out)
166    { return seekpos(__sp, __which); }
167
168    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
169    int pubsync() { return sync(); }
170
171    // Get and put areas:
172    // 27.6.2.2.3 Get area:
173    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
174    streamsize in_avail() {
175        if (__ninp_ < __einp_)
176            return static_cast<streamsize>(__einp_ - __ninp_);
177        return showmanyc();
178    }
179
180    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
181    int_type snextc() {
182        if (sbumpc() == traits_type::eof())
183            return traits_type::eof();
184        return sgetc();
185    }
186
187    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
188    int_type sbumpc() {
189        if (__ninp_ == __einp_)
190            return uflow();
191        return traits_type::to_int_type(*__ninp_++);
192    }
193
194    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
195    int_type sgetc() {
196        if (__ninp_ == __einp_)
197            return underflow();
198        return traits_type::to_int_type(*__ninp_);
199    }
200
201    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
202    streamsize sgetn(char_type* __s, streamsize __n)
203    { return xsgetn(__s, __n); }
204
205    // 27.6.2.2.4 Putback:
206    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
207    int_type sputbackc(char_type __c) {
208        if (__binp_ == __ninp_ || !traits_type::eq(__c, __ninp_[-1]))
209            return pbackfail(traits_type::to_int_type(__c));
210        return traits_type::to_int_type(*--__ninp_);
211    }
212
213    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
214    int_type sungetc() {
215        if (__binp_ == __ninp_)
216          return pbackfail();
217        return traits_type::to_int_type(*--__ninp_);
218    }
219
220    // 27.6.2.2.5 Put area:
221    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
222    int_type sputc(char_type __c) {
223        if (__nout_ == __eout_)
224            return overflow(traits_type::to_int_type(__c));
225        *__nout_++ = __c;
226        return traits_type::to_int_type(__c);
227    }
228
229    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
230    streamsize sputn(const char_type* __s, streamsize __n)
231    { return xsputn(__s, __n); }
232
233protected:
234    basic_streambuf();
235    basic_streambuf(const basic_streambuf& __rhs);
236    basic_streambuf& operator=(const basic_streambuf& __rhs);
237    void swap(basic_streambuf& __rhs);
238
239    // 27.6.2.3.2 Get area:
240    _LIBCPP_INLINE_VISIBILITY char_type* eback() const {return __binp_;}
241    _LIBCPP_INLINE_VISIBILITY char_type* gptr()  const {return __ninp_;}
242    _LIBCPP_INLINE_VISIBILITY char_type* egptr() const {return __einp_;}
243
244    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
245    void gbump(int __n) { __ninp_ += __n; }
246
247    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
248    void setg(char_type* __gbeg, char_type* __gnext, char_type* __gend) {
249        __binp_ = __gbeg;
250        __ninp_ = __gnext;
251        __einp_ = __gend;
252    }
253
254    // 27.6.2.3.3 Put area:
255    _LIBCPP_INLINE_VISIBILITY char_type* pbase() const {return __bout_;}
256    _LIBCPP_INLINE_VISIBILITY char_type* pptr()  const {return __nout_;}
257    _LIBCPP_INLINE_VISIBILITY char_type* epptr() const {return __eout_;}
258
259    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
260    void pbump(int __n) { __nout_ += __n; }
261
262    _LIBCPP_INLINE_VISIBILITY
263    void __pbump(streamsize __n) { __nout_ += __n; }
264
265    inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1
266    void setp(char_type* __pbeg, char_type* __pend) {
267        __bout_ = __nout_ = __pbeg;
268        __eout_ = __pend;
269    }
270
271    // 27.6.2.4 virtual functions:
272    // 27.6.2.4.1 Locales:
273    virtual void imbue(const locale& __loc);
274
275    // 27.6.2.4.2 Buffer management and positioning:
276    virtual basic_streambuf* setbuf(char_type* __s, streamsize __n);
277    virtual pos_type seekoff(off_type __off, ios_base::seekdir __way,
278                             ios_base::openmode __which = ios_base::in | ios_base::out);
279    virtual pos_type seekpos(pos_type __sp,
280                             ios_base::openmode __which = ios_base::in | ios_base::out);
281    virtual int sync();
282
283    // 27.6.2.4.3 Get area:
284    virtual streamsize showmanyc();
285    virtual streamsize xsgetn(char_type* __s, streamsize __n);
286    virtual int_type underflow();
287    virtual int_type uflow();
288
289    // 27.6.2.4.4 Putback:
290    virtual int_type pbackfail(int_type __c = traits_type::eof());
291
292    // 27.6.2.4.5 Put area:
293    virtual streamsize xsputn(const char_type* __s, streamsize __n);
294    virtual int_type overflow(int_type __c = traits_type::eof());
295
296private:
297    locale __loc_;
298    char_type* __binp_;
299    char_type* __ninp_;
300    char_type* __einp_;
301    char_type* __bout_;
302    char_type* __nout_;
303    char_type* __eout_;
304};
305
306template <class _CharT, class _Traits>
307basic_streambuf<_CharT, _Traits>::~basic_streambuf()
308{
309}
310
311template <class _CharT, class _Traits>
312basic_streambuf<_CharT, _Traits>::basic_streambuf()
313    : __binp_(nullptr),
314      __ninp_(nullptr),
315      __einp_(nullptr),
316      __bout_(nullptr),
317      __nout_(nullptr),
318      __eout_(nullptr)
319{
320}
321
322template <class _CharT, class _Traits>
323basic_streambuf<_CharT, _Traits>::basic_streambuf(const basic_streambuf& __sb)
324    : __loc_(__sb.__loc_),
325      __binp_(__sb.__binp_),
326      __ninp_(__sb.__ninp_),
327      __einp_(__sb.__einp_),
328      __bout_(__sb.__bout_),
329      __nout_(__sb.__nout_),
330      __eout_(__sb.__eout_)
331{
332}
333
334template <class _CharT, class _Traits>
335basic_streambuf<_CharT, _Traits>&
336basic_streambuf<_CharT, _Traits>::operator=(const basic_streambuf& __sb)
337{
338    __loc_ = __sb.__loc_;
339    __binp_ = __sb.__binp_;
340    __ninp_ = __sb.__ninp_;
341    __einp_ = __sb.__einp_;
342    __bout_ = __sb.__bout_;
343    __nout_ = __sb.__nout_;
344    __eout_ = __sb.__eout_;
345    return *this;
346}
347
348template <class _CharT, class _Traits>
349void
350basic_streambuf<_CharT, _Traits>::swap(basic_streambuf& __sb)
351{
352    _VSTD::swap(__loc_, __sb.__loc_);
353    _VSTD::swap(__binp_, __sb.__binp_);
354    _VSTD::swap(__ninp_, __sb.__ninp_);
355    _VSTD::swap(__einp_, __sb.__einp_);
356    _VSTD::swap(__bout_, __sb.__bout_);
357    _VSTD::swap(__nout_, __sb.__nout_);
358    _VSTD::swap(__eout_, __sb.__eout_);
359}
360
361template <class _CharT, class _Traits>
362void
363basic_streambuf<_CharT, _Traits>::imbue(const locale&)
364{
365}
366
367template <class _CharT, class _Traits>
368basic_streambuf<_CharT, _Traits>*
369basic_streambuf<_CharT, _Traits>::setbuf(char_type*, streamsize)
370{
371    return this;
372}
373
374template <class _CharT, class _Traits>
375typename basic_streambuf<_CharT, _Traits>::pos_type
376basic_streambuf<_CharT, _Traits>::seekoff(off_type, ios_base::seekdir,
377                                          ios_base::openmode)
378{
379    return pos_type(off_type(-1));
380}
381
382template <class _CharT, class _Traits>
383typename basic_streambuf<_CharT, _Traits>::pos_type
384basic_streambuf<_CharT, _Traits>::seekpos(pos_type, ios_base::openmode)
385{
386    return pos_type(off_type(-1));
387}
388
389template <class _CharT, class _Traits>
390int
391basic_streambuf<_CharT, _Traits>::sync()
392{
393    return 0;
394}
395
396template <class _CharT, class _Traits>
397streamsize
398basic_streambuf<_CharT, _Traits>::showmanyc()
399{
400    return 0;
401}
402
403template <class _CharT, class _Traits>
404streamsize
405basic_streambuf<_CharT, _Traits>::xsgetn(char_type* __s, streamsize __n)
406{
407    const int_type __eof = traits_type::eof();
408    int_type __c;
409    streamsize __i = 0;
410    while(__i < __n)
411    {
412        if (__ninp_ < __einp_)
413        {
414            const streamsize __len = _VSTD::min(static_cast<streamsize>(INT_MAX),
415                                _VSTD::min(__einp_ - __ninp_, __n - __i));
416            traits_type::copy(__s, __ninp_, __len);
417            __s +=  __len;
418            __i +=  __len;
419            this->gbump(__len);
420        }
421        else if ((__c = uflow()) != __eof)
422        {
423            *__s = traits_type::to_char_type(__c);
424            ++__s;
425            ++__i;
426        }
427        else
428            break;
429    }
430    return __i;
431}
432
433template <class _CharT, class _Traits>
434typename basic_streambuf<_CharT, _Traits>::int_type
435basic_streambuf<_CharT, _Traits>::underflow()
436{
437    return traits_type::eof();
438}
439
440template <class _CharT, class _Traits>
441typename basic_streambuf<_CharT, _Traits>::int_type
442basic_streambuf<_CharT, _Traits>::uflow()
443{
444    if (underflow() == traits_type::eof())
445        return traits_type::eof();
446    return traits_type::to_int_type(*__ninp_++);
447}
448
449template <class _CharT, class _Traits>
450typename basic_streambuf<_CharT, _Traits>::int_type
451basic_streambuf<_CharT, _Traits>::pbackfail(int_type)
452{
453    return traits_type::eof();
454}
455
456template <class _CharT, class _Traits>
457streamsize
458basic_streambuf<_CharT, _Traits>::xsputn(const char_type* __s, streamsize __n)
459{
460    streamsize __i = 0;
461    int_type __eof = traits_type::eof();
462    while( __i < __n)
463    {
464        if (__nout_ >= __eout_)
465        {
466            if (overflow(traits_type::to_int_type(*__s)) == __eof)
467                break;
468            ++__s;
469            ++__i;
470        }
471        else
472        {
473            streamsize __chunk_size = _VSTD::min(__eout_ - __nout_, __n - __i);
474            traits_type::copy(__nout_, __s, __chunk_size);
475            __nout_ += __chunk_size;
476            __s     += __chunk_size;
477            __i     += __chunk_size;
478        }
479    }
480    return __i;
481}
482
483template <class _CharT, class _Traits>
484typename basic_streambuf<_CharT, _Traits>::int_type
485basic_streambuf<_CharT, _Traits>::overflow(int_type)
486{
487    return traits_type::eof();
488}
489
490_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_streambuf<char>)
491_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_streambuf<wchar_t>)
492
493_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ios<char>)
494_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ios<wchar_t>)
495
496_LIBCPP_END_NAMESPACE_STD
497
498_LIBCPP_POP_MACROS
499
500#endif // _LIBCPP_STREAMBUF
501