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