1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #include <__utility/unreachable.h>
18 #include <__undef_macros>
20 _LIBCPP_BEGIN_NAMESPACE_STD
22 strstreambuf::strstreambuf(streamsize __alsize
)
23 : __strmode_(__dynamic
), __alsize_(__alsize
), __palloc_(nullptr), __pfree_(nullptr) {}
25 strstreambuf::strstreambuf(void* (*__palloc
)(size_t), void (*__pfree
)(void*))
26 : __strmode_(__dynamic
), __alsize_(__default_alsize
), __palloc_(__palloc
), __pfree_(__pfree
) {}
28 void strstreambuf::__init(char* __gnext
, streamsize __n
, char* __pbeg
) {
30 __n
= static_cast<streamsize
>(strlen(__gnext
));
33 if (__pbeg
== nullptr)
34 setg(__gnext
, __gnext
, __gnext
+ __n
);
36 setg(__gnext
, __gnext
, __pbeg
);
37 setp(__pbeg
, __pbeg
+ __n
);
41 strstreambuf::strstreambuf(char* __gnext
, streamsize __n
, char* __pbeg
)
42 : __strmode_(), __alsize_(__default_alsize
), __palloc_(nullptr), __pfree_(nullptr) {
43 __init(__gnext
, __n
, __pbeg
);
46 strstreambuf::strstreambuf(const char* __gnext
, streamsize __n
)
47 : __strmode_(__constant
), __alsize_(__default_alsize
), __palloc_(nullptr), __pfree_(nullptr) {
48 __init(const_cast<char*>(__gnext
), __n
, nullptr);
51 strstreambuf::strstreambuf(signed char* __gnext
, streamsize __n
, signed char* __pbeg
)
52 : __strmode_(), __alsize_(__default_alsize
), __palloc_(nullptr), __pfree_(nullptr) {
53 __init(const_cast<char*>(reinterpret_cast<const char*>(__gnext
)), __n
, reinterpret_cast<char*>(__pbeg
));
56 strstreambuf::strstreambuf(const signed char* __gnext
, streamsize __n
)
57 : __strmode_(__constant
), __alsize_(__default_alsize
), __palloc_(nullptr), __pfree_(nullptr) {
58 __init(const_cast<char*>(reinterpret_cast<const char*>(__gnext
)), __n
, nullptr);
61 strstreambuf::strstreambuf(unsigned char* __gnext
, streamsize __n
, unsigned char* __pbeg
)
62 : __strmode_(), __alsize_(__default_alsize
), __palloc_(nullptr), __pfree_(nullptr) {
63 __init(const_cast<char*>(reinterpret_cast<const char*>(__gnext
)), __n
, reinterpret_cast<char*>(__pbeg
));
66 strstreambuf::strstreambuf(const unsigned char* __gnext
, streamsize __n
)
67 : __strmode_(__constant
), __alsize_(__default_alsize
), __palloc_(nullptr), __pfree_(nullptr) {
68 __init(const_cast<char*>(reinterpret_cast<const char*>(__gnext
)), __n
, nullptr);
71 strstreambuf::~strstreambuf() {
72 if (eback() && (__strmode_
& __allocated
) != 0 && (__strmode_
& __frozen
) == 0) {
80 void strstreambuf::swap(strstreambuf
& __rhs
) {
81 streambuf::swap(__rhs
);
82 _VSTD::swap(__strmode_
, __rhs
.__strmode_
);
83 _VSTD::swap(__alsize_
, __rhs
.__alsize_
);
84 _VSTD::swap(__palloc_
, __rhs
.__palloc_
);
85 _VSTD::swap(__pfree_
, __rhs
.__pfree_
);
88 void strstreambuf::freeze(bool __freezefl
) {
89 if (__strmode_
& __dynamic
) {
91 __strmode_
|= __frozen
;
93 __strmode_
&= ~__frozen
;
97 char* strstreambuf::str() {
98 if (__strmode_
& __dynamic
)
99 __strmode_
|= __frozen
;
103 int strstreambuf::pcount() const { return static_cast<int>(pptr() - pbase()); }
105 strstreambuf::int_type
strstreambuf::overflow(int_type __c
) {
108 if (pptr() == epptr()) {
109 if ((__strmode_
& __dynamic
) == 0 || (__strmode_
& __frozen
) != 0)
110 return int_type(EOF
);
111 size_t old_size
= static_cast<size_t>((epptr() ? epptr() : egptr()) - eback());
112 size_t new_size
= max
<size_t>(static_cast<size_t>(__alsize_
), 2 * old_size
);
114 new_size
= __default_alsize
;
117 buf
= static_cast<char*>(__palloc_(new_size
));
119 buf
= new char[new_size
];
121 return int_type(EOF
);
123 _LIBCPP_ASSERT_UNCATEGORIZED(eback(), "overflow copying from NULL");
124 memcpy(buf
, eback(), static_cast<size_t>(old_size
));
126 ptrdiff_t ninp
= gptr() - eback();
127 ptrdiff_t einp
= egptr() - eback();
128 ptrdiff_t nout
= pptr() - pbase();
129 if (__strmode_
& __allocated
) {
135 setg(buf
, buf
+ ninp
, buf
+ einp
);
136 setp(buf
+ einp
, buf
+ new_size
);
138 __strmode_
|= __allocated
;
140 *pptr() = static_cast<char>(__c
);
142 return int_type(static_cast<unsigned char>(__c
));
145 strstreambuf::int_type
strstreambuf::pbackfail(int_type __c
) {
146 if (eback() == gptr())
152 if (__strmode_
& __constant
) {
153 if (gptr()[-1] == static_cast<char>(__c
)) {
160 *gptr() = static_cast<char>(__c
);
164 strstreambuf::int_type
strstreambuf::underflow() {
165 if (gptr() == egptr()) {
166 if (egptr() >= pptr())
168 setg(eback(), gptr(), pptr());
170 return int_type(static_cast<unsigned char>(*gptr()));
173 strstreambuf::pos_type
strstreambuf::seekoff(off_type __off
, ios_base::seekdir __way
, ios_base::openmode __which
) {
174 bool pos_in
= (__which
& ios::in
) != 0;
175 bool pos_out
= (__which
& ios::out
) != 0;
179 if (!pos_in
&& !pos_out
)
180 return pos_type(off_type(-1));
183 if (pos_in
== pos_out
)
184 return pos_type(off_type(-1));
188 if (pos_in
&& gptr() == nullptr)
189 return pos_type(off_type(-1));
190 if (pos_out
&& pptr() == nullptr)
191 return pos_type(off_type(-1));
194 char* seekhigh
= epptr() ? epptr() : egptr();
200 newoff
= (pos_in
? gptr() : pptr()) - eback();
203 newoff
= seekhigh
- eback();
206 __libcpp_unreachable();
209 if (newoff
< 0 || newoff
> seekhigh
- eback())
210 return pos_type(off_type(-1));
212 char* newpos
= eback() + newoff
;
214 setg(eback(), newpos
, _VSTD::max(newpos
, egptr()));
216 // min(pbase, newpos), newpos, epptr()
217 __off
= epptr() - newpos
;
218 setp(min(pbase(), newpos
), epptr());
219 __pbump((epptr() - pbase()) - __off
);
221 return pos_type(newoff
);
224 strstreambuf::pos_type
strstreambuf::seekpos(pos_type __sp
, ios_base::openmode __which
) {
225 bool pos_in
= (__which
& ios::in
) != 0;
226 bool pos_out
= (__which
& ios::out
) != 0;
227 if (!pos_in
&& !pos_out
)
228 return pos_type(off_type(-1));
230 if ((pos_in
&& gptr() == nullptr) || (pos_out
&& pptr() == nullptr))
231 return pos_type(off_type(-1));
233 off_type newoff
= __sp
;
234 char* seekhigh
= epptr() ? epptr() : egptr();
235 if (newoff
< 0 || newoff
> seekhigh
- eback())
236 return pos_type(off_type(-1));
238 char* newpos
= eback() + newoff
;
240 setg(eback(), newpos
, _VSTD::max(newpos
, egptr()));
242 // min(pbase, newpos), newpos, epptr()
243 off_type temp
= epptr() - newpos
;
244 setp(min(pbase(), newpos
), epptr());
245 __pbump((epptr() - pbase()) - temp
);
247 return pos_type(newoff
);
250 istrstream::~istrstream() {}
252 ostrstream::~ostrstream() {}
254 strstream::~strstream() {}
256 _LIBCPP_END_NAMESPACE_STD