Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / src / strstream.cpp
blobc97db698c0a1e95ec9606ef09750d09c0f96427b
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 //===----------------------------------------------------------------------===//
9 #include <__assert>
10 #include <__utility/unreachable.h>
11 #include <algorithm>
12 #include <climits>
13 #include <cstdlib>
14 #include <cstring>
15 #include <strstream>
17 _LIBCPP_PUSH_MACROS
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) {
29 if (__n == 0)
30 __n = static_cast<streamsize>(strlen(__gnext));
31 else if (__n < 0)
32 __n = INT_MAX;
33 if (__pbeg == nullptr)
34 setg(__gnext, __gnext, __gnext + __n);
35 else {
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) {
73 if (__pfree_)
74 __pfree_(eback());
75 else
76 delete[] eback();
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) {
90 if (__freezefl)
91 __strmode_ |= __frozen;
92 else
93 __strmode_ &= ~__frozen;
97 char* strstreambuf::str() {
98 if (__strmode_ & __dynamic)
99 __strmode_ |= __frozen;
100 return eback();
103 int strstreambuf::pcount() const { return static_cast<int>(pptr() - pbase()); }
105 strstreambuf::int_type strstreambuf::overflow(int_type __c) {
106 if (__c == EOF)
107 return int_type(0);
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);
113 if (new_size == 0)
114 new_size = __default_alsize;
115 char* buf = nullptr;
116 if (__palloc_)
117 buf = static_cast<char*>(__palloc_(new_size));
118 else
119 buf = new char[new_size];
120 if (buf == nullptr)
121 return int_type(EOF);
122 if (old_size != 0) {
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) {
130 if (__pfree_)
131 __pfree_(eback());
132 else
133 delete[] eback();
135 setg(buf, buf + ninp, buf + einp);
136 setp(buf + einp, buf + new_size);
137 __pbump(nout);
138 __strmode_ |= __allocated;
140 *pptr() = static_cast<char>(__c);
141 pbump(1);
142 return int_type(static_cast<unsigned char>(__c));
145 strstreambuf::int_type strstreambuf::pbackfail(int_type __c) {
146 if (eback() == gptr())
147 return EOF;
148 if (__c == EOF) {
149 gbump(-1);
150 return int_type(0);
152 if (__strmode_ & __constant) {
153 if (gptr()[-1] == static_cast<char>(__c)) {
154 gbump(-1);
155 return __c;
157 return EOF;
159 gbump(-1);
160 *gptr() = static_cast<char>(__c);
161 return __c;
164 strstreambuf::int_type strstreambuf::underflow() {
165 if (gptr() == egptr()) {
166 if (egptr() >= pptr())
167 return EOF;
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;
176 switch (__way) {
177 case ios::beg:
178 case ios::end:
179 if (!pos_in && !pos_out)
180 return pos_type(off_type(-1));
181 break;
182 case ios::cur:
183 if (pos_in == pos_out)
184 return pos_type(off_type(-1));
185 break;
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));
193 off_type newoff;
194 char* seekhigh = epptr() ? epptr() : egptr();
195 switch (__way) {
196 case ios::beg:
197 newoff = 0;
198 break;
199 case ios::cur:
200 newoff = (pos_in ? gptr() : pptr()) - eback();
201 break;
202 case ios::end:
203 newoff = seekhigh - eback();
204 break;
205 default:
206 __libcpp_unreachable();
208 newoff += __off;
209 if (newoff < 0 || newoff > seekhigh - eback())
210 return pos_type(off_type(-1));
212 char* newpos = eback() + newoff;
213 if (pos_in)
214 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
215 if (pos_out) {
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;
239 if (pos_in)
240 setg(eback(), newpos, _VSTD::max(newpos, egptr()));
241 if (pos_out) {
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
258 _LIBCPP_POP_MACROS