namespace std {
template<class charT, class traits = char_traits<charT>,
class Allocator = allocator<charT>>
class basic_stringbuf : public basic_streambuf<charT, traits> {
public:
using char_type = charT;
using int_type = typename traits::int_type;
using pos_type = typename traits::pos_type;
using off_type = typename traits::off_type;
using traits_type = traits;
using allocator_type = Allocator;
basic_stringbuf() : basic_stringbuf(ios_base::in | ios_base::out) {}
explicit basic_stringbuf(ios_base::openmode which);
explicit basic_stringbuf(
const basic_string<charT, traits, Allocator>& s,
ios_base::openmode which = ios_base::in | ios_base::out);
explicit basic_stringbuf(const Allocator& a)
: basic_stringbuf(ios_base::in | ios_base::out, a) {}
basic_stringbuf(ios_base::openmode which, const Allocator& a);
explicit basic_stringbuf(
basic_string<charT, traits, Allocator>&& s,
ios_base::openmode which = ios_base::in | ios_base::out);
template<class SAlloc>
basic_stringbuf(
const basic_string<charT, traits, SAlloc>& s, const Allocator& a)
: basic_stringbuf(s, ios_base::in | ios_base::out, a) {}
template<class SAlloc>
basic_stringbuf(
const basic_string<charT, traits, SAlloc>& s,
ios_base::openmode which, const Allocator& a);
template<class SAlloc>
explicit basic_stringbuf(
const basic_string<charT, traits, SAlloc>& s,
ios_base::openmode which = ios_base::in | ios_base::out);
basic_stringbuf(const basic_stringbuf&) = delete;
basic_stringbuf(basic_stringbuf&& rhs);
basic_stringbuf(basic_stringbuf&& rhs, const Allocator& a);
basic_stringbuf& operator=(const basic_stringbuf&) = delete;
basic_stringbuf& operator=(basic_stringbuf&& rhs);
void swap(basic_stringbuf& rhs) noexcept(see below);
allocator_type get_allocator() const noexcept;
basic_string<charT, traits, Allocator> str() const &;
template<class SAlloc>
basic_string<charT,traits,SAlloc> str(const SAlloc& sa) const;
basic_string<charT, traits, Allocator> str() &&;
basic_string_view<charT, traits> view() const noexcept;
void str(const basic_string<charT, traits, Allocator>& s);
template<class SAlloc>
void str(const basic_string<charT, traits, SAlloc>& s);
void str(basic_string<charT, traits, Allocator>&& s);
protected:
int_type underflow() override;
int_type pbackfail(int_type c = traits::eof()) override;
int_type overflow (int_type c = traits::eof()) override;
basic_streambuf<charT, traits>* setbuf(charT*, streamsize) override;
pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which
= ios_base::in | ios_base::out) override;
pos_type seekpos(pos_type sp,
ios_base::openmode which
= ios_base::in | ios_base::out) override;
private:
ios_base::openmode mode;
basic_string<charT, traits, Allocator> buf;
void init_buf_ptrs();
};
template<class charT, class traits, class Allocator>
void swap(basic_stringbuf<charT, traits, Allocator>& x,
basic_stringbuf<charT, traits, Allocator>& y) noexcept(noexcept(x.swap(y)));
}
The class
basic_stringbuf
is derived from
basic_streambuf
to associate possibly the input sequence and possibly
the output sequence with a sequence of arbitrary
characters. The sequence can be initialized from, or made available as, an object of class
basic_string.For the sake of exposition,
the maintained data and internal pointer initialization is presented here as:
- ios_base::openmode mode, has
in set if the input sequence can be read, and
out set if the output sequence can be written.
- basic_string<charT, traits, Allocator> buf
contains the underlying character sequence.
- init_buf_ptrs() sets the base class'
get area ([streambuf.get.area]) and
put area ([streambuf.put.area]) pointers
after initializing, moving from, or assigning to buf accordingly.
explicit basic_stringbuf(ios_base::openmode which);
Effects: Initializes the base class with
basic_streambuf() (
[streambuf.cons]), and
mode
with
which. It is
implementation-defined
whether the sequence pointers
(
eback(),
gptr(),
egptr(),
pbase(),
pptr(),
epptr())
are initialized to null pointers
.Postconditions: str().empty() is
true. explicit basic_stringbuf(
const basic_string<charT, traits, Allocator>& s,
ios_base::openmode which = ios_base::in | ios_base::out);
Effects: Initializes the base class with
basic_streambuf() (
[streambuf.cons]),
mode with
which, and
buf with
s,
then calls
init_buf_ptrs(). basic_stringbuf(ios_base::openmode which, const Allocator &a);
Effects: Initializes the base class with
basic_streambuf() (
[streambuf.cons]),
mode with
which, and
buf with
a,
then calls
init_buf_ptrs(). Postconditions: str().empty() is
true. explicit basic_stringbuf(
basic_string<charT, traits, Allocator>&& s,
ios_base::openmode which = ios_base::in | ios_base::out);
Effects: Initializes the base class with
basic_streambuf() (
[streambuf.cons]),
mode with
which, and
buf with
std::move(s),
then calls
init_buf_ptrs(). template<class SAlloc>
basic_stringbuf(
const basic_string<charT, traits, SAlloc>& s,
ios_base::openmode which, const Allocator &a);
Effects: Initializes the base class with
basic_streambuf() (
[streambuf.cons]),
mode with
which, and
buf with
{s,a},
then calls
init_buf_ptrs(). template<class SAlloc>
explicit basic_stringbuf(
const basic_string<charT, traits, SAlloc>& s,
ios_base::openmode which = ios_base::in | ios_base::out);
Constraints: is_same_v<SAlloc,Allocator> is
false. Effects: Initializes the base class with
basic_streambuf() (
[streambuf.cons]),
mode with
which, and
buf with
s,
then calls
init_buf_ptrs(). basic_stringbuf(basic_stringbuf&& rhs);
basic_stringbuf(basic_stringbuf&& rhs, const Allocator& a);
Effects: Copy constructs the base class from
rhs and
initializes
mode with
rhs.mode. In the first form
buf is initialized
from
std::move(rhs).str(). In the second form
buf is initialized
from
{std::move(rhs).str(), a}. It is
implementation-defined whether the sequence pointers in
*this
(
eback(),
gptr(),
egptr(),
pbase(),
pptr(),
epptr()) obtain
the values which
rhs had
.Postconditions: Let
rhs_p refer to the state of
rhs just prior to this construction and let
rhs_a
refer to the state of
rhs just after this construction
. str() == rhs_p.str()
gptr() - eback() == rhs_p.gptr() - rhs_p.eback()
egptr() - eback() == rhs_p.egptr() - rhs_p.eback()
pptr() - pbase() == rhs_p.pptr() - rhs_p.pbase()
epptr() - pbase() == rhs_p.epptr() - rhs_p.pbase()
if (eback()) eback() != rhs_a.eback()
if (gptr()) gptr() != rhs_a.gptr()
if (egptr()) egptr() != rhs_a.egptr()
if (pbase()) pbase() != rhs_a.pbase()
if (pptr()) pptr() != rhs_a.pptr()
if (epptr()) epptr() != rhs_a.epptr()
getloc() == rhs_p.getloc()
rhs is empty but usable,
as if
std::move(rhs).str() was called
.
basic_stringbuf& operator=(basic_stringbuf&& rhs);
Effects: After the move assignment
*this has the observable state it would
have had if it had been move constructed from
rhs (see
[stringbuf.cons])
. void swap(basic_stringbuf& rhs) noexcept(see below);
Preconditions: allocator_traits<Allocator>::propagate_on_container_swap::value
is
true or
get_allocator() == s.get_allocator() is
true. Effects: Exchanges the state of
*this
and
rhs. Remarks: The expression inside noexcept is equivalent to:
allocator_traits<Allocator>::propagate_on_container_swap::value ||
allocator_traits<Allocator>::is_always_equal::value. template<class charT, class traits, class Allocator>
void swap(basic_stringbuf<charT, traits, Allocator>& x,
basic_stringbuf<charT, traits, Allocator>& y) noexcept(noexcept(x.swap(y)));
Effects: Equivalent to:
x.swap(y). The member functions getting the underlying character sequence
all refer to a
high_mark value,
where
high_mark represents the position
one past the highest initialized character in the buffer
. Characters can be initialized by writing to the stream,
by constructing the
basic_stringbuf
passing a
basic_string argument, or
by calling one of the
str member functions
passing a
basic_string as an argument
. In the latter case, all characters initialized prior to the call
are now considered uninitialized
(except for those characters re-initialized by the new
basic_string)
.Effects: Initializes the input and output sequences from
buf
according to
mode. Postconditions: - If ios_base::out is set in mode,
pbase() points to buf.front() and
epptr() >= pbase() + buf.size() is true;
- in addition, if ios_base::ate is set in mode,
pptr() == pbase() + buf.size() is true,
- otherwise pptr() == pbase() is true.
- If ios_base::in is set in mode,
eback() points to buf.front(), and
(gptr() == eback() && egptr() == eback() + buf.size())
is true.
[
Note: For efficiency reasons,
stream buffer operations might violate invariants of
buf
while it is held encapsulated in the
basic_stringbuf,
e.g., by writing to characters in the range
[
buf.data() + buf.size(), buf.data() + buf.capacity())
. All operations retrieving a
basic_string from
buf
ensure that the
basic_string invariants hold on the returned value
. —
end note ]
allocator_type get_allocator() const noexcept;
Returns: buf.get_allocator(). basic_string<charT, traits, Allocator> str() const &;
Effects: Equivalent to:
return basic_string<charT, traits, Allocator>(view(), get_allocator());
template<class SAlloc>
basic_string<charT, traits, SAlloc> str(const SAlloc& sa) const;
Effects: Equivalent to:
return basic_string<charT, traits, SAlloc>(view(), sa);
basic_string<charT, traits, Allocator> str() &&;
Returns: A
basic_string<charT, traits, Allocator> object
move constructed from
the
basic_stringbuf's underlying character sequence in
buf. This can be achieved by first adjusting
buf to have
the same content as
view().Postconditions: The underlying character sequence
buf is empty and
pbase(),
pptr(),
epptr(),
eback(),
gptr(), and
egptr()
are initialized as if by calling
init_buf_ptrs()
with an empty
buf. basic_string_view<charT, traits> view() const noexcept;
Let
sv be
basic_string_view<charT, traits>.Returns: A
sv object referring to
the
basic_stringbuf's underlying character sequence in
buf:
- If ios_base::out is set in mode,
then sv(pbase(), high_mark-pbase()) is returned.
- Otherwise, if ios_base::in is set in mode,
then sv(eback(), egptr()-eback()) is returned.
- Otherwise, sv() is returned.
[
Note: Using the returned
sv object after
destruction or invalidation of the character sequence underlying
*this
is undefined behavior, unless
sv.empty() is
true. —
end note ]
void str(const basic_string<charT, traits, Allocator>& s);
Effects: Equivalent to:
buf = s;
init_buf_ptrs();
template<class SAlloc>
void str(const basic_string<charT, traits, SAlloc>& s);
Constraints: is_same_v<SAlloc,Allocator> is
false. Effects: Equivalent to:
buf = s;
init_buf_ptrs();
void str(basic_string<charT, traits, Allocator>&& s);
Effects: Equivalent to:
buf = std::move(s);
init_buf_ptrs();
int_type underflow() override;
Returns: If the input sequence has a read position available,
returns
traits::to_int_type(*gptr()). Otherwise, returns
traits::eof(). Any character in the underlying buffer which has been initialized is considered
to be part of the input sequence
.int_type pbackfail(int_type c = traits::eof()) override;
Effects: Puts back the character designated by
c to the input
sequence, if possible, in one of three ways:
- If
traits::eq_int_type(c, traits::eof())
returns
false
and
if the input sequence has a putback position available, and
if
traits::eq(to_char_type(c), gptr()[-1])
returns
true,
assigns
gptr() - 1
to
gptr().Returns:
c.
- If
traits::eq_int_type(c, traits::eof())
returns
false
and if the input sequence
has a putback position available, and
if mode
&
ios_base::out is
nonzero,
assigns c to
*--gptr().Returns:
c.
- If
traits::eq_int_type(c, traits::eof())
returns
true
and if the input sequence has a putback position available,
assigns
gptr() - 1
to
gptr().Returns:
traits::not_eof(c).
Returns: As specified above, or
traits::eof()
to indicate failure
. Remarks: If the function can succeed in more than one of these ways, it is
unspecified which way is chosen
. int_type overflow(int_type c = traits::eof()) override;
Effects: Appends the character designated by
c to the output
sequence, if possible, in one of two ways:
- If
traits::eq_int_type(c, traits::eof())
returns
false
and if either
the output sequence has a write position available or
the function makes a write position available
(as described below),
the function calls
sputc(c).Signals success by returning c.
- If
traits::eq_int_type(c, traits::eof())
returns
true,
there is no character to append.Signals success by returning a value other than
traits::eof().
Remarks: The function can alter the number of write positions available as a
result of any call
. Returns: As specified above, or
traits::eof()
to indicate failure
. The function can make a write position available only if
ios_base::out is set in
mode. To make a write position available,
the function reallocates (or initially allocates) an array object
with a sufficient number of elements to hold
the current array object (if any), plus
at least
one additional write position
. If
ios_base::in is set in
mode,
the function alters the read end pointer
egptr()
to point just past the new write position
.pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which
= ios_base::in | ios_base::out) override;
Effects: Alters the stream position within one of the
controlled sequences, if possible, as indicated in Table
124. Table
124:
seekoff positioning [tab:stringbuf.seekoff.pos]
Conditions | Result |
ios_base::in is set in which | positions the input sequence |
ios_base::out is set in which | positions the output sequence |
both ios_base::in and ios_base::out are
set in which and either way == ios_base::beg or way == ios_base::end | positions both the input and the output sequences |
Otherwise | the positioning operation fails . |
For a sequence to be positioned,
the function determines
newoff as indicated in
Table
125. If the sequence's next pointer
(either
gptr()
or
pptr())
is a null pointer and
newoff is nonzero,
the positioning operation fails
.Table
125:
newoff values [tab:stringbuf.seekoff.newoff]
Condition | newoff Value |
way == ios_base::beg | 0 |
way == ios_base::cur | the next pointer minus the beginning pointer ( xnext - xbeg) . |
way == ios_base::end | the high mark pointer minus the beginning pointer ( high_mark - xbeg) . |
If
(newoff + off) < 0,
or if
newoff + off refers to an uninitialized
character (
[stringbuf.members]),
the positioning operation fails
. Otherwise, the function assigns
xbeg + newoff + off
to the next pointer
xnext.Returns: pos_type(newoff),
constructed from the resultant offset
newoff
(of type
off_type),
that stores the resultant stream position, if possible
. If the positioning operation fails, or
if the constructed object cannot represent the resultant stream position,
the return value is
pos_type(off_type(-1)).pos_type seekpos(pos_type sp,
ios_base::openmode which
= ios_base::in | ios_base::out) override;
Effects: Equivalent to
seekoff(off_type(sp), ios_base::beg, which). Returns: sp
to indicate success, or
pos_type(off_type(-1))
to indicate failure
. basic_streambuf<charT, traits>* setbuf(charT* s, streamsize n);
Effects: implementation-defined,
except that
setbuf(0, 0)
has no effect
.