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