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