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 <__config>
10#include <__locale>
11#include <algorithm>
12#include <atomic>
13#include <ios>
14#include <limits>
15#include <memory>
16#include <new>
17#include <stdlib.h>
18#include <string>
19
20#include "include/config_elast.h"
21
22_LIBCPP_PUSH_MACROS
23#include <__undef_macros>
24
25_LIBCPP_BEGIN_NAMESPACE_STD
26_LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
27
28class _LIBCPP_HIDDEN __iostream_category : public __do_message {
29public:
30 virtual const char* name() const noexcept;
31 virtual string message(int ev) const;
32};
33
34const char* __iostream_category::name() const noexcept { return "iostream"; }
35
36string __iostream_category::message(int ev) const {
37 if (ev != static_cast<int>(io_errc::stream)
38#ifdef _LIBCPP_ELAST
39 && ev <= _LIBCPP_ELAST
40#endif // _LIBCPP_ELAST
41 )
42 return __do_message::message(ev: ev);
43 return string("unspecified iostream_category error");
44}
45
46const error_category& iostream_category() noexcept {
47 union AvoidDestroyingIostreamCategory {
48 __iostream_category iostream_error_category;
49 constexpr explicit AvoidDestroyingIostreamCategory() : iostream_error_category() {}
50 ~AvoidDestroyingIostreamCategory() {}
51 };
52 constinit static AvoidDestroyingIostreamCategory helper;
53 return helper.iostream_error_category;
54}
55
56// ios_base::failure
57
58ios_base::failure::failure(const string& msg, const error_code& ec) : system_error(ec, msg) {}
59
60ios_base::failure::failure(const char* msg, const error_code& ec) : system_error(ec, msg) {}
61
62ios_base::failure::~failure() throw() {}
63
64// ios_base locale
65
66const ios_base::fmtflags ios_base::boolalpha;
67const ios_base::fmtflags ios_base::dec;
68const ios_base::fmtflags ios_base::fixed;
69const ios_base::fmtflags ios_base::hex;
70const ios_base::fmtflags ios_base::internal;
71const ios_base::fmtflags ios_base::left;
72const ios_base::fmtflags ios_base::oct;
73const ios_base::fmtflags ios_base::right;
74const ios_base::fmtflags ios_base::scientific;
75const ios_base::fmtflags ios_base::showbase;
76const ios_base::fmtflags ios_base::showpoint;
77const ios_base::fmtflags ios_base::showpos;
78const ios_base::fmtflags ios_base::skipws;
79const ios_base::fmtflags ios_base::unitbuf;
80const ios_base::fmtflags ios_base::uppercase;
81const ios_base::fmtflags ios_base::adjustfield;
82const ios_base::fmtflags ios_base::basefield;
83const ios_base::fmtflags ios_base::floatfield;
84
85const ios_base::iostate ios_base::badbit;
86const ios_base::iostate ios_base::eofbit;
87const ios_base::iostate ios_base::failbit;
88const ios_base::iostate ios_base::goodbit;
89
90const ios_base::openmode ios_base::app;
91const ios_base::openmode ios_base::ate;
92const ios_base::openmode ios_base::binary;
93const ios_base::openmode ios_base::in;
94const ios_base::openmode ios_base::out;
95const ios_base::openmode ios_base::trunc;
96
97void ios_base::__call_callbacks(event ev) {
98 for (size_t i = __event_size_; i;) {
99 --i;
100 __fn_[i](ev, *this, __index_[i]);
101 }
102}
103
104// locale
105
106locale ios_base::imbue(const locale& newloc) {
107 locale loc = newloc;
108 std::swap(x&: __loc_, y&: loc);
109 __call_callbacks(ev: imbue_event);
110 return loc;
111}
112
113locale ios_base::getloc() const { return __loc_; }
114
115template <typename _Tp>
116static size_t __ios_new_cap(size_t __req_size, size_t __current_cap) { // Precondition: __req_size > __current_cap
117 const size_t mx = std::numeric_limits<size_t>::max() / sizeof(_Tp);
118 if (__req_size < mx / 2)
119 return std::max(a: 2 * __current_cap, b: __req_size);
120 else
121 return mx;
122}
123
124int ios_base::xalloc() {
125 constinit static atomic<int> xindex = 0;
126 return xindex++;
127}
128
129long& ios_base::iword(int index) {
130 size_t req_size = static_cast<size_t>(index) + 1;
131 if (req_size > __iarray_cap_) {
132 size_t newcap = __ios_new_cap<long>(req_size: req_size, current_cap: __iarray_cap_);
133 long* iarray = static_cast<long*>(realloc(ptr: __iarray_, size: newcap * sizeof(long)));
134 if (iarray == 0) {
135 setstate(badbit);
136 static long error;
137 error = 0;
138 return error;
139 }
140 __iarray_ = iarray;
141 for (long* p = __iarray_ + __iarray_size_; p < __iarray_ + newcap; ++p)
142 *p = 0;
143 __iarray_cap_ = newcap;
144 }
145 __iarray_size_ = max<size_t>(a: __iarray_size_, b: req_size);
146 return __iarray_[index];
147}
148
149void*& ios_base::pword(int index) {
150 size_t req_size = static_cast<size_t>(index) + 1;
151 if (req_size > __parray_cap_) {
152 size_t newcap = __ios_new_cap<void*>(req_size: req_size, current_cap: __iarray_cap_);
153 void** parray = static_cast<void**>(realloc(ptr: __parray_, size: newcap * sizeof(void*)));
154 if (parray == 0) {
155 setstate(badbit);
156 static void* error;
157 error = 0;
158 return error;
159 }
160 __parray_ = parray;
161 for (void** p = __parray_ + __parray_size_; p < __parray_ + newcap; ++p)
162 *p = 0;
163 __parray_cap_ = newcap;
164 }
165 __parray_size_ = max<size_t>(a: __parray_size_, b: req_size);
166 return __parray_[index];
167}
168
169// register_callback
170
171void ios_base::register_callback(event_callback fn, int index) {
172 size_t req_size = __event_size_ + 1;
173 if (req_size > __event_cap_) {
174 size_t newcap = __ios_new_cap<event_callback>(req_size: req_size, current_cap: __event_cap_);
175 event_callback* fns = static_cast<event_callback*>(realloc(ptr: __fn_, size: newcap * sizeof(event_callback)));
176 if (fns == 0) {
177 setstate(badbit);
178 return;
179 }
180 __fn_ = fns;
181 int* indxs = static_cast<int*>(realloc(ptr: __index_, size: newcap * sizeof(int)));
182 if (indxs == 0) {
183 setstate(badbit);
184 return;
185 }
186 __index_ = indxs;
187 __event_cap_ = newcap;
188 }
189 __fn_[__event_size_] = fn;
190 __index_[__event_size_] = index;
191 ++__event_size_;
192}
193
194ios_base::~ios_base() {
195 // Avoid UB when not properly initialized. See ios_base::ios_base for
196 // more information.
197 if (!__loc_.__locale_)
198 return;
199 __call_callbacks(ev: erase_event);
200 __loc_.~locale();
201 free(ptr: __fn_);
202 free(ptr: __index_);
203 free(ptr: __iarray_);
204 free(ptr: __parray_);
205}
206
207// iostate
208
209void ios_base::clear(iostate state) {
210 if (__rdbuf_)
211 __rdstate_ = state;
212 else
213 __rdstate_ = state | badbit;
214
215 if (((state | (__rdbuf_ ? goodbit : badbit)) & __exceptions_) != 0)
216 std::__throw_failure(msg: "ios_base::clear");
217}
218
219// init
220
221void ios_base::init(void* sb) {
222 __rdbuf_ = sb;
223 __rdstate_ = __rdbuf_ ? goodbit : badbit;
224 __exceptions_ = goodbit;
225 __fmtflags_ = skipws | dec;
226 __width_ = 0;
227 __precision_ = 6;
228 __fn_ = 0;
229 __index_ = 0;
230 __event_size_ = 0;
231 __event_cap_ = 0;
232 __iarray_ = 0;
233 __iarray_size_ = 0;
234 __iarray_cap_ = 0;
235 __parray_ = 0;
236 __parray_size_ = 0;
237 __parray_cap_ = 0;
238 ::new (&__loc_) locale;
239}
240
241void ios_base::copyfmt(const ios_base& rhs) {
242 // If we can't acquire the needed resources, throw bad_alloc (can't set badbit)
243 // Don't alter *this until all needed resources are acquired
244 unique_ptr<event_callback, void (*)(void*)> new_callbacks(0, free);
245 unique_ptr<int, void (*)(void*)> new_ints(0, free);
246 unique_ptr<long, void (*)(void*)> new_longs(0, free);
247 unique_ptr<void*, void (*)(void*)> new_pointers(0, free);
248 if (__event_cap_ < rhs.__event_size_) {
249 size_t newesize = sizeof(event_callback) * rhs.__event_size_;
250 new_callbacks.reset(p: static_cast<event_callback*>(malloc(size: newesize)));
251 if (!new_callbacks)
252 std::__throw_bad_alloc();
253
254 size_t newisize = sizeof(int) * rhs.__event_size_;
255 new_ints.reset(p: static_cast<int*>(malloc(size: newisize)));
256 if (!new_ints)
257 std::__throw_bad_alloc();
258 }
259 if (__iarray_cap_ < rhs.__iarray_size_) {
260 size_t newsize = sizeof(long) * rhs.__iarray_size_;
261 new_longs.reset(p: static_cast<long*>(malloc(size: newsize)));
262 if (!new_longs)
263 std::__throw_bad_alloc();
264 }
265 if (__parray_cap_ < rhs.__parray_size_) {
266 size_t newsize = sizeof(void*) * rhs.__parray_size_;
267 new_pointers.reset(p: static_cast<void**>(malloc(size: newsize)));
268 if (!new_pointers)
269 std::__throw_bad_alloc();
270 }
271 // Got everything we need. Copy everything but __rdstate_, __rdbuf_ and __exceptions_
272 __fmtflags_ = rhs.__fmtflags_;
273 __precision_ = rhs.__precision_;
274 __width_ = rhs.__width_;
275 __loc_ = rhs.__loc_;
276 if (__event_cap_ < rhs.__event_size_) {
277 free(ptr: __fn_);
278 __fn_ = new_callbacks.release();
279 free(ptr: __index_);
280 __index_ = new_ints.release();
281 __event_cap_ = rhs.__event_size_;
282 }
283 for (__event_size_ = 0; __event_size_ < rhs.__event_size_; ++__event_size_) {
284 __fn_[__event_size_] = rhs.__fn_[__event_size_];
285 __index_[__event_size_] = rhs.__index_[__event_size_];
286 }
287 if (__iarray_cap_ < rhs.__iarray_size_) {
288 free(ptr: __iarray_);
289 __iarray_ = new_longs.release();
290 __iarray_cap_ = rhs.__iarray_size_;
291 }
292 for (__iarray_size_ = 0; __iarray_size_ < rhs.__iarray_size_; ++__iarray_size_)
293 __iarray_[__iarray_size_] = rhs.__iarray_[__iarray_size_];
294 if (__parray_cap_ < rhs.__parray_size_) {
295 free(ptr: __parray_);
296 __parray_ = new_pointers.release();
297 __parray_cap_ = rhs.__parray_size_;
298 }
299 for (__parray_size_ = 0; __parray_size_ < rhs.__parray_size_; ++__parray_size_)
300 __parray_[__parray_size_] = rhs.__parray_[__parray_size_];
301}
302
303void ios_base::move(ios_base& rhs) {
304 // *this is uninitialized
305 __fmtflags_ = rhs.__fmtflags_;
306 __precision_ = rhs.__precision_;
307 __width_ = rhs.__width_;
308 __rdstate_ = rhs.__rdstate_;
309 __exceptions_ = rhs.__exceptions_;
310 __rdbuf_ = 0;
311 ::new (&__loc_) locale(rhs.__loc_);
312 __fn_ = rhs.__fn_;
313 rhs.__fn_ = 0;
314 __index_ = rhs.__index_;
315 rhs.__index_ = 0;
316 __event_size_ = rhs.__event_size_;
317 rhs.__event_size_ = 0;
318 __event_cap_ = rhs.__event_cap_;
319 rhs.__event_cap_ = 0;
320 __iarray_ = rhs.__iarray_;
321 rhs.__iarray_ = 0;
322 __iarray_size_ = rhs.__iarray_size_;
323 rhs.__iarray_size_ = 0;
324 __iarray_cap_ = rhs.__iarray_cap_;
325 rhs.__iarray_cap_ = 0;
326 __parray_ = rhs.__parray_;
327 rhs.__parray_ = 0;
328 __parray_size_ = rhs.__parray_size_;
329 rhs.__parray_size_ = 0;
330 __parray_cap_ = rhs.__parray_cap_;
331 rhs.__parray_cap_ = 0;
332}
333
334void ios_base::swap(ios_base& rhs) noexcept {
335 std::swap(x&: __fmtflags_, y&: rhs.__fmtflags_);
336 std::swap(x&: __precision_, y&: rhs.__precision_);
337 std::swap(x&: __width_, y&: rhs.__width_);
338 std::swap(x&: __rdstate_, y&: rhs.__rdstate_);
339 std::swap(x&: __exceptions_, y&: rhs.__exceptions_);
340 std::swap(x&: __loc_, y&: rhs.__loc_);
341 std::swap(x&: __fn_, y&: rhs.__fn_);
342 std::swap(x&: __index_, y&: rhs.__index_);
343 std::swap(x&: __event_size_, y&: rhs.__event_size_);
344 std::swap(x&: __event_cap_, y&: rhs.__event_cap_);
345 std::swap(x&: __iarray_, y&: rhs.__iarray_);
346 std::swap(x&: __iarray_size_, y&: rhs.__iarray_size_);
347 std::swap(x&: __iarray_cap_, y&: rhs.__iarray_cap_);
348 std::swap(x&: __parray_, y&: rhs.__parray_);
349 std::swap(x&: __parray_size_, y&: rhs.__parray_size_);
350 std::swap(x&: __parray_cap_, y&: rhs.__parray_cap_);
351}
352
353void ios_base::__set_badbit_and_consider_rethrow() {
354 __rdstate_ |= badbit;
355#if _LIBCPP_HAS_EXCEPTIONS
356 if (__exceptions_ & badbit)
357 throw;
358#endif // _LIBCPP_HAS_EXCEPTIONS
359}
360
361void ios_base::__set_failbit_and_consider_rethrow() {
362 __rdstate_ |= failbit;
363#if _LIBCPP_HAS_EXCEPTIONS
364 if (__exceptions_ & failbit)
365 throw;
366#endif // _LIBCPP_HAS_EXCEPTIONS
367}
368
369bool ios_base::sync_with_stdio(bool sync) {
370 static bool previous_state = true;
371 bool r = previous_state;
372 previous_state = sync;
373 return r;
374}
375
376_LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
377_LIBCPP_END_NAMESPACE_STD
378
379_LIBCPP_POP_MACROS
380