1//===----------------------------------------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include <__assert>
10#include <__utility/unreachable.h>
11#include <algorithm>
12#include <climits>
13#include <cstdlib>
14#include <cstring>
15#include <strstream>
16
17_LIBCPP_PUSH_MACROS
18#include <__undef_macros>
19
20_LIBCPP_BEGIN_NAMESPACE_STD
21_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
22
23strstreambuf::strstreambuf(streamsize __alsize)
24 : __strmode_(__dynamic), __alsize_(__alsize), __palloc_(nullptr), __pfree_(nullptr) {}
25
26strstreambuf::strstreambuf(void* (*__palloc)(size_t), void (*__pfree)(void*))
27 : __strmode_(__dynamic), __alsize_(__default_alsize), __palloc_(__palloc), __pfree_(__pfree) {}
28
29void strstreambuf::__init(char* __gnext, streamsize __n, char* __pbeg) {
30 if (__n == 0)
31 __n = static_cast<streamsize>(strlen(s: __gnext));
32 else if (__n < 0)
33 __n = INT_MAX;
34 if (__pbeg == nullptr)
35 setg(gbeg: __gnext, __gnext, gend: __gnext + __n);
36 else {
37 setg(gbeg: __gnext, __gnext, gend: __pbeg);
38 setp(__pbeg, pend: __pbeg + __n);
39 }
40}
41
42strstreambuf::strstreambuf(char* __gnext, streamsize __n, char* __pbeg)
43 : __strmode_(), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {
44 __init(__gnext, __n, __pbeg);
45}
46
47strstreambuf::strstreambuf(const char* __gnext, streamsize __n)
48 : __strmode_(__constant), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {
49 __init(gnext: const_cast<char*>(__gnext), __n, pbeg: nullptr);
50}
51
52strstreambuf::strstreambuf(signed char* __gnext, streamsize __n, signed char* __pbeg)
53 : __strmode_(), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {
54 __init(gnext: const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, pbeg: reinterpret_cast<char*>(__pbeg));
55}
56
57strstreambuf::strstreambuf(const signed char* __gnext, streamsize __n)
58 : __strmode_(__constant), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {
59 __init(gnext: const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, pbeg: nullptr);
60}
61
62strstreambuf::strstreambuf(unsigned char* __gnext, streamsize __n, unsigned char* __pbeg)
63 : __strmode_(), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {
64 __init(gnext: const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, pbeg: reinterpret_cast<char*>(__pbeg));
65}
66
67strstreambuf::strstreambuf(const unsigned char* __gnext, streamsize __n)
68 : __strmode_(__constant), __alsize_(__default_alsize), __palloc_(nullptr), __pfree_(nullptr) {
69 __init(gnext: const_cast<char*>(reinterpret_cast<const char*>(__gnext)), __n, pbeg: nullptr);
70}
71
72strstreambuf::~strstreambuf() {
73 if (eback() && (__strmode_ & __allocated) != 0 && (__strmode_ & __frozen) == 0) {
74 if (__pfree_)
75 __pfree_(eback());
76 else
77 delete[] eback();
78 }
79}
80
81void strstreambuf::swap(strstreambuf& __rhs) {
82 streambuf::swap(sb&: __rhs);
83 std::swap(x&: __strmode_, y&: __rhs.__strmode_);
84 std::swap(x&: __alsize_, y&: __rhs.__alsize_);
85 std::swap(x&: __palloc_, y&: __rhs.__palloc_);
86 std::swap(x&: __pfree_, y&: __rhs.__pfree_);
87}
88
89void strstreambuf::freeze(bool __freezefl) {
90 if (__strmode_ & __dynamic) {
91 if (__freezefl)
92 __strmode_ |= __frozen;
93 else
94 __strmode_ &= ~__frozen;
95 }
96}
97
98char* strstreambuf::str() {
99 if (__strmode_ & __dynamic)
100 __strmode_ |= __frozen;
101 return eback();
102}
103
104int strstreambuf::pcount() const { return static_cast<int>(pptr() - pbase()); }
105
106strstreambuf::int_type strstreambuf::overflow(int_type __c) {
107 if (__c == EOF)
108 return int_type(0);
109 if (pptr() == epptr()) {
110 if ((__strmode_ & __dynamic) == 0 || (__strmode_ & __frozen) != 0)
111 return int_type(EOF);
112 size_t old_size = static_cast<size_t>((epptr() ? epptr() : egptr()) - eback());
113 size_t new_size = max<size_t>(a: static_cast<size_t>(__alsize_), b: 2 * old_size);
114 if (new_size == 0)
115 new_size = __default_alsize;
116 char* buf = nullptr;
117 if (__palloc_)
118 buf = static_cast<char*>(__palloc_(new_size));
119 else
120 buf = new char[new_size];
121 if (buf == nullptr)
122 return int_type(EOF);
123 if (old_size != 0) {
124 _LIBCPP_ASSERT_INTERNAL(eback(), "strstreambuf::overflow reallocating but the get area is a null pointer");
125 memcpy(dest: buf, src: eback(), n: static_cast<size_t>(old_size));
126 }
127 ptrdiff_t ninp = gptr() - eback();
128 ptrdiff_t einp = egptr() - eback();
129 ptrdiff_t nout = pptr() - pbase();
130 if (__strmode_ & __allocated) {
131 if (__pfree_)
132 __pfree_(eback());
133 else
134 delete[] eback();
135 }
136 setg(gbeg: buf, gnext: buf + ninp, gend: buf + einp);
137 setp(pbeg: buf + einp, pend: buf + new_size);
138 __pbump(n: nout);
139 __strmode_ |= __allocated;
140 }
141 *pptr() = static_cast<char>(__c);
142 pbump(n: 1);
143 return int_type(static_cast<unsigned char>(__c));
144}
145
146strstreambuf::int_type strstreambuf::pbackfail(int_type __c) {
147 if (eback() == gptr())
148 return EOF;
149 if (__c == EOF) {
150 gbump(n: -1);
151 return int_type(0);
152 }
153 if (__strmode_ & __constant) {
154 if (gptr()[-1] == static_cast<char>(__c)) {
155 gbump(n: -1);
156 return __c;
157 }
158 return EOF;
159 }
160 gbump(n: -1);
161 *gptr() = static_cast<char>(__c);
162 return __c;
163}
164
165strstreambuf::int_type strstreambuf::underflow() {
166 if (gptr() == egptr()) {
167 if (egptr() >= pptr())
168 return EOF;
169 setg(gbeg: eback(), gnext: gptr(), gend: pptr());
170 }
171 return int_type(static_cast<unsigned char>(*gptr()));
172}
173
174strstreambuf::pos_type strstreambuf::seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __which) {
175 bool pos_in = (__which & ios::in) != 0;
176 bool pos_out = (__which & ios::out) != 0;
177 switch (__way) {
178 case ios::beg:
179 case ios::end:
180 if (!pos_in && !pos_out)
181 return pos_type(off_type(-1));
182 break;
183 case ios::cur:
184 if (pos_in == pos_out)
185 return pos_type(off_type(-1));
186 break;
187 }
188
189 if (pos_in && gptr() == nullptr)
190 return pos_type(off_type(-1));
191 if (pos_out && pptr() == nullptr)
192 return pos_type(off_type(-1));
193
194 off_type newoff;
195 char* seekhigh = epptr() ? epptr() : egptr();
196 switch (__way) {
197 case ios::beg:
198 newoff = 0;
199 break;
200 case ios::cur:
201 newoff = (pos_in ? gptr() : pptr()) - eback();
202 break;
203 case ios::end:
204 newoff = seekhigh - eback();
205 break;
206 default:
207 __libcpp_unreachable();
208 }
209 newoff += __off;
210 if (newoff < 0 || newoff > seekhigh - eback())
211 return pos_type(off_type(-1));
212
213 char* newpos = eback() + newoff;
214 if (pos_in)
215 setg(gbeg: eback(), gnext: newpos, gend: std::max(a: newpos, b: egptr()));
216 if (pos_out) {
217 // min(pbase, newpos), newpos, epptr()
218 __off = epptr() - newpos;
219 setp(pbeg: min(a: pbase(), b: newpos), pend: epptr());
220 __pbump(n: (epptr() - pbase()) - __off);
221 }
222 return pos_type(newoff);
223}
224
225strstreambuf::pos_type strstreambuf::seekpos(pos_type __sp, ios_base::openmode __which) {
226 bool pos_in = (__which & ios::in) != 0;
227 bool pos_out = (__which & ios::out) != 0;
228 if (!pos_in && !pos_out)
229 return pos_type(off_type(-1));
230
231 if ((pos_in && gptr() == nullptr) || (pos_out && pptr() == nullptr))
232 return pos_type(off_type(-1));
233
234 off_type newoff = __sp;
235 char* seekhigh = epptr() ? epptr() : egptr();
236 if (newoff < 0 || newoff > seekhigh - eback())
237 return pos_type(off_type(-1));
238
239 char* newpos = eback() + newoff;
240 if (pos_in)
241 setg(gbeg: eback(), gnext: newpos, gend: std::max(a: newpos, b: egptr()));
242 if (pos_out) {
243 // min(pbase, newpos), newpos, epptr()
244 off_type temp = epptr() - newpos;
245 setp(pbeg: min(a: pbase(), b: newpos), pend: epptr());
246 __pbump(n: (epptr() - pbase()) - temp);
247 }
248 return pos_type(newoff);
249}
250
251istrstream::~istrstream() {}
252
253ostrstream::~ostrstream() {}
254
255strstream::~strstream() {}
256
257_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
258_LIBCPP_END_NAMESPACE_STD
259
260_LIBCPP_POP_MACROS
261