Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libcxx / src / ios.cpp
blobf17cd6e1dbbb14effb461d3f0be3f8b1495e9c0f
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 <__config>
10 #include <__locale>
11 #include <algorithm>
12 #include <ios>
13 #include <limits>
14 #include <memory>
15 #include <new>
16 #include <stdlib.h>
17 #include <string>
19 #include "include/config_elast.h"
21 _LIBCPP_PUSH_MACROS
22 #include <__undef_macros>
24 _LIBCPP_BEGIN_NAMESPACE_STD
26 class _LIBCPP_HIDDEN __iostream_category
27 : public __do_message
29 public:
30 virtual const char* name() const noexcept;
31 virtual string message(int ev) const;
34 const char*
35 __iostream_category::name() const noexcept
37 return "iostream";
40 string
41 __iostream_category::message(int ev) const
43 if (ev != static_cast<int>(io_errc::stream)
44 #ifdef _LIBCPP_ELAST
45 && ev <= _LIBCPP_ELAST
46 #endif // _LIBCPP_ELAST
48 return __do_message::message(ev);
49 return string("unspecified iostream_category error");
52 const error_category&
53 iostream_category() noexcept
55 union AvoidDestroyingIostreamCategory {
56 __iostream_category iostream_error_category;
57 constexpr explicit AvoidDestroyingIostreamCategory() : iostream_error_category() {}
58 ~AvoidDestroyingIostreamCategory() {}
60 constinit static AvoidDestroyingIostreamCategory helper;
61 return helper.iostream_error_category;
64 // ios_base::failure
66 ios_base::failure::failure(const string& msg, const error_code& ec)
67 : system_error(ec, msg)
71 ios_base::failure::failure(const char* msg, const error_code& ec)
72 : system_error(ec, msg)
76 ios_base::failure::~failure() throw()
80 // ios_base locale
82 const ios_base::fmtflags ios_base::boolalpha;
83 const ios_base::fmtflags ios_base::dec;
84 const ios_base::fmtflags ios_base::fixed;
85 const ios_base::fmtflags ios_base::hex;
86 const ios_base::fmtflags ios_base::internal;
87 const ios_base::fmtflags ios_base::left;
88 const ios_base::fmtflags ios_base::oct;
89 const ios_base::fmtflags ios_base::right;
90 const ios_base::fmtflags ios_base::scientific;
91 const ios_base::fmtflags ios_base::showbase;
92 const ios_base::fmtflags ios_base::showpoint;
93 const ios_base::fmtflags ios_base::showpos;
94 const ios_base::fmtflags ios_base::skipws;
95 const ios_base::fmtflags ios_base::unitbuf;
96 const ios_base::fmtflags ios_base::uppercase;
97 const ios_base::fmtflags ios_base::adjustfield;
98 const ios_base::fmtflags ios_base::basefield;
99 const ios_base::fmtflags ios_base::floatfield;
101 const ios_base::iostate ios_base::badbit;
102 const ios_base::iostate ios_base::eofbit;
103 const ios_base::iostate ios_base::failbit;
104 const ios_base::iostate ios_base::goodbit;
106 const ios_base::openmode ios_base::app;
107 const ios_base::openmode ios_base::ate;
108 const ios_base::openmode ios_base::binary;
109 const ios_base::openmode ios_base::in;
110 const ios_base::openmode ios_base::out;
111 const ios_base::openmode ios_base::trunc;
113 void
114 ios_base::__call_callbacks(event ev)
116 for (size_t i = __event_size_; i;)
118 --i;
119 __fn_[i](ev, *this, __index_[i]);
123 // locale
125 locale
126 ios_base::imbue(const locale& newloc)
128 static_assert(sizeof(locale) == sizeof(__loc_), "");
129 locale& loc_storage = *reinterpret_cast<locale*>(&__loc_);
130 locale oldloc = loc_storage;
131 loc_storage = newloc;
132 __call_callbacks(imbue_event);
133 return oldloc;
136 locale
137 ios_base::getloc() const
139 const locale& loc_storage = *reinterpret_cast<const locale*>(&__loc_);
140 return loc_storage;
143 // xalloc
144 #if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
145 atomic<int> ios_base::__xindex_{0};
146 #else
147 int ios_base::__xindex_ = 0;
148 #endif
150 template <typename _Tp>
151 static size_t __ios_new_cap(size_t __req_size, size_t __current_cap)
152 { // Precondition: __req_size > __current_cap
153 const size_t mx = std::numeric_limits<size_t>::max() / sizeof(_Tp);
154 if (__req_size < mx/2)
155 return _VSTD::max(2 * __current_cap, __req_size);
156 else
157 return mx;
161 ios_base::xalloc()
163 return __xindex_++;
166 long&
167 ios_base::iword(int index)
169 size_t req_size = static_cast<size_t>(index)+1;
170 if (req_size > __iarray_cap_)
172 size_t newcap = __ios_new_cap<long>(req_size, __iarray_cap_);
173 long* iarray = static_cast<long*>(realloc(__iarray_, newcap * sizeof(long)));
174 if (iarray == 0)
176 setstate(badbit);
177 static long error;
178 error = 0;
179 return error;
181 __iarray_ = iarray;
182 for (long* p = __iarray_ + __iarray_size_; p < __iarray_ + newcap; ++p)
183 *p = 0;
184 __iarray_cap_ = newcap;
186 __iarray_size_ = max<size_t>(__iarray_size_, req_size);
187 return __iarray_[index];
190 void*&
191 ios_base::pword(int index)
193 size_t req_size = static_cast<size_t>(index)+1;
194 if (req_size > __parray_cap_)
196 size_t newcap = __ios_new_cap<void *>(req_size, __iarray_cap_);
197 void** parray = static_cast<void**>(realloc(__parray_, newcap * sizeof(void *)));
198 if (parray == 0)
200 setstate(badbit);
201 static void* error;
202 error = 0;
203 return error;
205 __parray_ = parray;
206 for (void** p = __parray_ + __parray_size_; p < __parray_ + newcap; ++p)
207 *p = 0;
208 __parray_cap_ = newcap;
210 __parray_size_ = max<size_t>(__parray_size_, req_size);
211 return __parray_[index];
214 // register_callback
216 void
217 ios_base::register_callback(event_callback fn, int index)
219 size_t req_size = __event_size_ + 1;
220 if (req_size > __event_cap_)
222 size_t newcap = __ios_new_cap<event_callback>(req_size, __event_cap_);
223 event_callback* fns = static_cast<event_callback*>(realloc(__fn_, newcap * sizeof(event_callback)));
224 if (fns == 0)
225 setstate(badbit);
226 __fn_ = fns;
227 int* indxs = static_cast<int *>(realloc(__index_, newcap * sizeof(int)));
228 if (indxs == 0)
229 setstate(badbit);
230 __index_ = indxs;
231 __event_cap_ = newcap;
233 __fn_[__event_size_] = fn;
234 __index_[__event_size_] = index;
235 ++__event_size_;
238 ios_base::~ios_base()
240 __call_callbacks(erase_event);
241 locale& loc_storage = *reinterpret_cast<locale*>(&__loc_);
242 loc_storage.~locale();
243 free(__fn_);
244 free(__index_);
245 free(__iarray_);
246 free(__parray_);
249 // iostate
251 void
252 ios_base::clear(iostate state)
254 if (__rdbuf_)
255 __rdstate_ = state;
256 else
257 __rdstate_ = state | badbit;
259 if (((state | (__rdbuf_ ? goodbit : badbit)) & __exceptions_) != 0)
260 __throw_failure("ios_base::clear");
263 // init
265 void
266 ios_base::init(void* sb)
268 __rdbuf_ = sb;
269 __rdstate_ = __rdbuf_ ? goodbit : badbit;
270 __exceptions_ = goodbit;
271 __fmtflags_ = skipws | dec;
272 __width_ = 0;
273 __precision_ = 6;
274 __fn_ = 0;
275 __index_ = 0;
276 __event_size_ = 0;
277 __event_cap_ = 0;
278 __iarray_ = 0;
279 __iarray_size_ = 0;
280 __iarray_cap_ = 0;
281 __parray_ = 0;
282 __parray_size_ = 0;
283 __parray_cap_ = 0;
284 ::new(&__loc_) locale;
287 void
288 ios_base::copyfmt(const ios_base& rhs)
290 // If we can't acquire the needed resources, throw bad_alloc (can't set badbit)
291 // Don't alter *this until all needed resources are acquired
292 unique_ptr<event_callback, void (*)(void*)> new_callbacks(0, free);
293 unique_ptr<int, void (*)(void*)> new_ints(0, free);
294 unique_ptr<long, void (*)(void*)> new_longs(0, free);
295 unique_ptr<void*, void (*)(void*)> new_pointers(0, free);
296 if (__event_cap_ < rhs.__event_size_)
298 size_t newesize = sizeof(event_callback) * rhs.__event_size_;
299 new_callbacks.reset(static_cast<event_callback*>(malloc(newesize)));
300 if (!new_callbacks)
301 __throw_bad_alloc();
303 size_t newisize = sizeof(int) * rhs.__event_size_;
304 new_ints.reset(static_cast<int *>(malloc(newisize)));
305 if (!new_ints)
306 __throw_bad_alloc();
308 if (__iarray_cap_ < rhs.__iarray_size_)
310 size_t newsize = sizeof(long) * rhs.__iarray_size_;
311 new_longs.reset(static_cast<long*>(malloc(newsize)));
312 if (!new_longs)
313 __throw_bad_alloc();
315 if (__parray_cap_ < rhs.__parray_size_)
317 size_t newsize = sizeof(void*) * rhs.__parray_size_;
318 new_pointers.reset(static_cast<void**>(malloc(newsize)));
319 if (!new_pointers)
320 __throw_bad_alloc();
322 // Got everything we need. Copy everything but __rdstate_, __rdbuf_ and __exceptions_
323 __fmtflags_ = rhs.__fmtflags_;
324 __precision_ = rhs.__precision_;
325 __width_ = rhs.__width_;
326 locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_);
327 const locale& rhs_loc = *reinterpret_cast<const locale*>(&rhs.__loc_);
328 lhs_loc = rhs_loc;
329 if (__event_cap_ < rhs.__event_size_)
331 free(__fn_);
332 __fn_ = new_callbacks.release();
333 free(__index_);
334 __index_ = new_ints.release();
335 __event_cap_ = rhs.__event_size_;
337 for (__event_size_ = 0; __event_size_ < rhs.__event_size_; ++__event_size_)
339 __fn_[__event_size_] = rhs.__fn_[__event_size_];
340 __index_[__event_size_] = rhs.__index_[__event_size_];
342 if (__iarray_cap_ < rhs.__iarray_size_)
344 free(__iarray_);
345 __iarray_ = new_longs.release();
346 __iarray_cap_ = rhs.__iarray_size_;
348 for (__iarray_size_ = 0; __iarray_size_ < rhs.__iarray_size_; ++__iarray_size_)
349 __iarray_[__iarray_size_] = rhs.__iarray_[__iarray_size_];
350 if (__parray_cap_ < rhs.__parray_size_)
352 free(__parray_);
353 __parray_ = new_pointers.release();
354 __parray_cap_ = rhs.__parray_size_;
356 for (__parray_size_ = 0; __parray_size_ < rhs.__parray_size_; ++__parray_size_)
357 __parray_[__parray_size_] = rhs.__parray_[__parray_size_];
360 void
361 ios_base::move(ios_base& rhs)
363 // *this is uninitialized
364 __fmtflags_ = rhs.__fmtflags_;
365 __precision_ = rhs.__precision_;
366 __width_ = rhs.__width_;
367 __rdstate_ = rhs.__rdstate_;
368 __exceptions_ = rhs.__exceptions_;
369 __rdbuf_ = 0;
370 locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_);
371 ::new(&__loc_) locale(rhs_loc);
372 __fn_ = rhs.__fn_;
373 rhs.__fn_ = 0;
374 __index_ = rhs.__index_;
375 rhs.__index_ = 0;
376 __event_size_ = rhs.__event_size_;
377 rhs.__event_size_ = 0;
378 __event_cap_ = rhs.__event_cap_;
379 rhs.__event_cap_ = 0;
380 __iarray_ = rhs.__iarray_;
381 rhs.__iarray_ = 0;
382 __iarray_size_ = rhs.__iarray_size_;
383 rhs.__iarray_size_ = 0;
384 __iarray_cap_ = rhs.__iarray_cap_;
385 rhs.__iarray_cap_ = 0;
386 __parray_ = rhs.__parray_;
387 rhs.__parray_ = 0;
388 __parray_size_ = rhs.__parray_size_;
389 rhs.__parray_size_ = 0;
390 __parray_cap_ = rhs.__parray_cap_;
391 rhs.__parray_cap_ = 0;
394 void
395 ios_base::swap(ios_base& rhs) noexcept
397 _VSTD::swap(__fmtflags_, rhs.__fmtflags_);
398 _VSTD::swap(__precision_, rhs.__precision_);
399 _VSTD::swap(__width_, rhs.__width_);
400 _VSTD::swap(__rdstate_, rhs.__rdstate_);
401 _VSTD::swap(__exceptions_, rhs.__exceptions_);
402 locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_);
403 locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_);
404 _VSTD::swap(lhs_loc, rhs_loc);
405 _VSTD::swap(__fn_, rhs.__fn_);
406 _VSTD::swap(__index_, rhs.__index_);
407 _VSTD::swap(__event_size_, rhs.__event_size_);
408 _VSTD::swap(__event_cap_, rhs.__event_cap_);
409 _VSTD::swap(__iarray_, rhs.__iarray_);
410 _VSTD::swap(__iarray_size_, rhs.__iarray_size_);
411 _VSTD::swap(__iarray_cap_, rhs.__iarray_cap_);
412 _VSTD::swap(__parray_, rhs.__parray_);
413 _VSTD::swap(__parray_size_, rhs.__parray_size_);
414 _VSTD::swap(__parray_cap_, rhs.__parray_cap_);
417 void
418 ios_base::__set_badbit_and_consider_rethrow()
420 __rdstate_ |= badbit;
421 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
422 if (__exceptions_ & badbit)
423 throw;
424 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
427 void
428 ios_base::__set_failbit_and_consider_rethrow()
430 __rdstate_ |= failbit;
431 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
432 if (__exceptions_ & failbit)
433 throw;
434 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
437 bool
438 ios_base::sync_with_stdio(bool sync)
440 static bool previous_state = true;
441 bool r = previous_state;
442 previous_state = sync;
443 return r;
446 _LIBCPP_END_NAMESPACE_STD
448 _LIBCPP_POP_MACROS