blob: e2e0363fa861d0e6c3ff71e9be61b51bea288318 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001//===-------------------------- ios.cpp -----------------------------------===//
2//
Howard Hinnantf5256e12010-05-11 21:36:01 +00003// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00004//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
Dan Albert7112dae2014-11-20 15:55:17 -080010#include "__config"
Dan Albert938c6a02014-12-03 21:33:51 -080011
Dan Albert75746a32015-11-09 12:34:21 -080012#undef _LIBCPP_EXTERN_TEMPLATE
13#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
14
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000015#include "ios"
Dan Albertf608ad62015-01-06 17:34:51 +000016
17#include <stdlib.h>
18
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000019#include "__locale"
20#include "algorithm"
Dan Albert1d4a1ed2016-05-25 22:36:09 -070021#include "config_elast.h"
Dan Albertf608ad62015-01-06 17:34:51 +000022#include "istream"
23#include "limits"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000024#include "memory"
25#include "new"
Dan Albertf608ad62015-01-06 17:34:51 +000026#include "streambuf"
27#include "string"
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000028
29_LIBCPP_BEGIN_NAMESPACE_STD
30
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000031template class basic_ios<char>;
32template class basic_ios<wchar_t>;
33
34template class basic_streambuf<char>;
35template class basic_streambuf<wchar_t>;
36
37template class basic_istream<char>;
38template class basic_istream<wchar_t>;
39
40template class basic_ostream<char>;
41template class basic_ostream<wchar_t>;
42
43template class basic_iostream<char>;
44
45class _LIBCPP_HIDDEN __iostream_category
46 : public __do_message
47{
48public:
Howard Hinnant1e15fd12011-05-26 19:48:01 +000049 virtual const char* name() const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000050 virtual string message(int ev) const;
51};
52
53const char*
Howard Hinnant1e15fd12011-05-26 19:48:01 +000054__iostream_category::name() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000055{
56 return "iostream";
57}
58
59string
60__iostream_category::message(int ev) const
61{
Howard Hinnantadff4892010-05-24 17:49:41 +000062 if (ev != static_cast<int>(io_errc::stream)
Dan Albert7112dae2014-11-20 15:55:17 -080063#ifdef _LIBCPP_ELAST
64 && ev <= _LIBCPP_ELAST
65#endif // _LIBCPP_ELAST
Howard Hinnantadff4892010-05-24 17:49:41 +000066 )
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000067 return __do_message::message(ev);
68 return string("unspecified iostream_category error");
69}
70
71const error_category&
Marshall Clow61a84222013-10-12 22:49:56 +000072iostream_category() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000073{
74 static __iostream_category s;
75 return s;
76}
77
78// ios_base::failure
79
80ios_base::failure::failure(const string& msg, const error_code& ec)
81 : system_error(ec, msg)
82{
83}
84
85ios_base::failure::failure(const char* msg, const error_code& ec)
86 : system_error(ec, msg)
87{
88}
89
90ios_base::failure::~failure() throw()
91{
92}
93
94// ios_base locale
95
96const ios_base::fmtflags ios_base::boolalpha;
97const ios_base::fmtflags ios_base::dec;
98const ios_base::fmtflags ios_base::fixed;
99const ios_base::fmtflags ios_base::hex;
100const ios_base::fmtflags ios_base::internal;
101const ios_base::fmtflags ios_base::left;
102const ios_base::fmtflags ios_base::oct;
103const ios_base::fmtflags ios_base::right;
104const ios_base::fmtflags ios_base::scientific;
105const ios_base::fmtflags ios_base::showbase;
106const ios_base::fmtflags ios_base::showpoint;
107const ios_base::fmtflags ios_base::showpos;
108const ios_base::fmtflags ios_base::skipws;
109const ios_base::fmtflags ios_base::unitbuf;
110const ios_base::fmtflags ios_base::uppercase;
111const ios_base::fmtflags ios_base::adjustfield;
112const ios_base::fmtflags ios_base::basefield;
113const ios_base::fmtflags ios_base::floatfield;
114
115const ios_base::iostate ios_base::badbit;
116const ios_base::iostate ios_base::eofbit;
117const ios_base::iostate ios_base::failbit;
118const ios_base::iostate ios_base::goodbit;
119
120const ios_base::openmode ios_base::app;
121const ios_base::openmode ios_base::ate;
122const ios_base::openmode ios_base::binary;
123const ios_base::openmode ios_base::in;
124const ios_base::openmode ios_base::out;
125const ios_base::openmode ios_base::trunc;
126
127void
128ios_base::__call_callbacks(event ev)
129{
130 for (size_t i = __event_size_; i;)
131 {
132 --i;
133 __fn_[i](ev, *this, __index_[i]);
134 }
135}
136
137// locale
138
139locale
140ios_base::imbue(const locale& newloc)
141{
142 static_assert(sizeof(locale) == sizeof(__loc_), "");
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000143 locale& loc_storage = *reinterpret_cast<locale*>(&__loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000144 locale oldloc = loc_storage;
145 loc_storage = newloc;
146 __call_callbacks(imbue_event);
147 return oldloc;
148}
149
150locale
151ios_base::getloc() const
152{
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000153 const locale& loc_storage = *reinterpret_cast<const locale*>(&__loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000154 return loc_storage;
155}
156
157// xalloc
Dan Albert1d4a1ed2016-05-25 22:36:09 -0700158#if __has_feature(cxx_atomic) && !defined(_LIBCPP_HAS_NO_THREADS)
Marshall Clow206ce1f2013-10-12 19:13:52 +0000159atomic<int> ios_base::__xindex_ = ATOMIC_VAR_INIT(0);
160#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000161int ios_base::__xindex_ = 0;
Marshall Clow206ce1f2013-10-12 19:13:52 +0000162#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000163
Dan Albert7112dae2014-11-20 15:55:17 -0800164template <typename _Tp>
165static size_t __ios_new_cap(size_t __req_size, size_t __current_cap)
166{ // Precondition: __req_size > __current_cap
167 const size_t mx = std::numeric_limits<size_t>::max() / sizeof(_Tp);
168 if (__req_size < mx/2)
169 return _VSTD::max(2 * __current_cap, __req_size);
170 else
171 return mx;
172}
173
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000174int
175ios_base::xalloc()
176{
177 return __xindex_++;
178}
179
180long&
181ios_base::iword(int index)
182{
183 size_t req_size = static_cast<size_t>(index)+1;
184 if (req_size > __iarray_cap_)
185 {
Dan Albert7112dae2014-11-20 15:55:17 -0800186 size_t newcap = __ios_new_cap<long>(req_size, __iarray_cap_);
187 long* iarray = static_cast<long*>(realloc(__iarray_, newcap * sizeof(long)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000188 if (iarray == 0)
189 {
190 setstate(badbit);
191 static long error;
192 error = 0;
193 return error;
194 }
195 __iarray_ = iarray;
Dan Albert7112dae2014-11-20 15:55:17 -0800196 for (long* p = __iarray_ + __iarray_size_; p < __iarray_ + newcap; ++p)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000197 *p = 0;
Dan Albert7112dae2014-11-20 15:55:17 -0800198 __iarray_cap_ = newcap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000199 }
200 __iarray_size_ = max<size_t>(__iarray_size_, req_size);
201 return __iarray_[index];
202}
203
204void*&
205ios_base::pword(int index)
206{
207 size_t req_size = static_cast<size_t>(index)+1;
208 if (req_size > __parray_cap_)
209 {
Dan Albert7112dae2014-11-20 15:55:17 -0800210 size_t newcap = __ios_new_cap<void *>(req_size, __iarray_cap_);
211 void** parray = static_cast<void**>(realloc(__parray_, newcap * sizeof(void *)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000212 if (parray == 0)
213 {
214 setstate(badbit);
215 static void* error;
216 error = 0;
217 return error;
218 }
219 __parray_ = parray;
Dan Albert7112dae2014-11-20 15:55:17 -0800220 for (void** p = __parray_ + __parray_size_; p < __parray_ + newcap; ++p)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000221 *p = 0;
Dan Albert7112dae2014-11-20 15:55:17 -0800222 __parray_cap_ = newcap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000223 }
224 __parray_size_ = max<size_t>(__parray_size_, req_size);
225 return __parray_[index];
226}
227
228// register_callback
229
230void
231ios_base::register_callback(event_callback fn, int index)
232{
233 size_t req_size = __event_size_ + 1;
234 if (req_size > __event_cap_)
235 {
Dan Albert7112dae2014-11-20 15:55:17 -0800236 size_t newcap = __ios_new_cap<event_callback>(req_size, __event_cap_);
237 event_callback* fns = static_cast<event_callback*>(realloc(__fn_, newcap * sizeof(event_callback)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000238 if (fns == 0)
239 setstate(badbit);
240 __fn_ = fns;
Dan Albert7112dae2014-11-20 15:55:17 -0800241 int* indxs = static_cast<int *>(realloc(__index_, newcap * sizeof(int)));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000242 if (indxs == 0)
243 setstate(badbit);
244 __index_ = indxs;
Dan Albert7112dae2014-11-20 15:55:17 -0800245 __event_cap_ = newcap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000246 }
247 __fn_[__event_size_] = fn;
248 __index_[__event_size_] = index;
249 ++__event_size_;
250}
251
252ios_base::~ios_base()
253{
254 __call_callbacks(erase_event);
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000255 locale& loc_storage = *reinterpret_cast<locale*>(&__loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000256 loc_storage.~locale();
257 free(__fn_);
258 free(__index_);
259 free(__iarray_);
260 free(__parray_);
261}
262
263// iostate
264
265void
266ios_base::clear(iostate state)
267{
268 if (__rdbuf_)
269 __rdstate_ = state;
270 else
271 __rdstate_ = state | badbit;
Howard Hinnantd4444702010-08-11 17:04:31 +0000272#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000273 if (((state | (__rdbuf_ ? goodbit : badbit)) & __exceptions_) != 0)
274 throw failure("ios_base::clear");
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000275#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000276}
277
278// init
279
280void
281ios_base::init(void* sb)
282{
283 __rdbuf_ = sb;
284 __rdstate_ = __rdbuf_ ? goodbit : badbit;
285 __exceptions_ = goodbit;
286 __fmtflags_ = skipws | dec;
287 __width_ = 0;
288 __precision_ = 6;
289 __fn_ = 0;
290 __index_ = 0;
291 __event_size_ = 0;
292 __event_cap_ = 0;
293 __iarray_ = 0;
294 __iarray_size_ = 0;
295 __iarray_cap_ = 0;
296 __parray_ = 0;
297 __parray_size_ = 0;
298 __parray_cap_ = 0;
299 ::new(&__loc_) locale;
300}
301
302void
303ios_base::copyfmt(const ios_base& rhs)
304{
305 // If we can't acquire the needed resources, throw bad_alloc (can't set badbit)
Dan Albert90dc8dd2014-08-26 11:20:46 -0700306 // Don't alter *this until all needed resources are acquired
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000307 unique_ptr<event_callback, void (*)(void*)> new_callbacks(0, free);
308 unique_ptr<int, void (*)(void*)> new_ints(0, free);
309 unique_ptr<long, void (*)(void*)> new_longs(0, free);
310 unique_ptr<void*, void (*)(void*)> new_pointers(0, free);
311 if (__event_cap_ < rhs.__event_size_)
312 {
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000313 size_t newesize = sizeof(event_callback) * rhs.__event_size_;
314 new_callbacks.reset(static_cast<event_callback*>(malloc(newesize)));
Howard Hinnantd4444702010-08-11 17:04:31 +0000315#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000316 if (!new_callbacks)
317 throw bad_alloc();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000318#endif // _LIBCPP_NO_EXCEPTIONS
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000319
320 size_t newisize = sizeof(int) * rhs.__event_size_;
321 new_ints.reset(static_cast<int *>(malloc(newisize)));
Howard Hinnantd4444702010-08-11 17:04:31 +0000322#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000323 if (!new_ints)
324 throw bad_alloc();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000325#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000326 }
327 if (__iarray_cap_ < rhs.__iarray_size_)
328 {
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000329 size_t newsize = sizeof(long) * rhs.__iarray_size_;
330 new_longs.reset(static_cast<long*>(malloc(newsize)));
Howard Hinnantd4444702010-08-11 17:04:31 +0000331#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000332 if (!new_longs)
333 throw bad_alloc();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000334#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000335 }
336 if (__parray_cap_ < rhs.__parray_size_)
337 {
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000338 size_t newsize = sizeof(void*) * rhs.__parray_size_;
339 new_pointers.reset(static_cast<void**>(malloc(newsize)));
Howard Hinnantd4444702010-08-11 17:04:31 +0000340#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000341 if (!new_pointers)
342 throw bad_alloc();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000343#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000344 }
345 // Got everything we need. Copy everything but __rdstate_, __rdbuf_ and __exceptions_
346 __fmtflags_ = rhs.__fmtflags_;
347 __precision_ = rhs.__precision_;
348 __width_ = rhs.__width_;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000349 locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_);
350 const locale& rhs_loc = *reinterpret_cast<const locale*>(&rhs.__loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000351 lhs_loc = rhs_loc;
352 if (__event_cap_ < rhs.__event_size_)
353 {
354 free(__fn_);
355 __fn_ = new_callbacks.release();
356 free(__index_);
357 __index_ = new_ints.release();
358 __event_cap_ = rhs.__event_size_;
359 }
360 for (__event_size_ = 0; __event_size_ < rhs.__event_size_; ++__event_size_)
361 {
362 __fn_[__event_size_] = rhs.__fn_[__event_size_];
363 __index_[__event_size_] = rhs.__index_[__event_size_];
364 }
365 if (__iarray_cap_ < rhs.__iarray_size_)
366 {
367 free(__iarray_);
368 __iarray_ = new_longs.release();
369 __iarray_cap_ = rhs.__iarray_size_;
370 }
371 for (__iarray_size_ = 0; __iarray_size_ < rhs.__iarray_size_; ++__iarray_size_)
372 __iarray_[__iarray_size_] = rhs.__iarray_[__iarray_size_];
373 if (__parray_cap_ < rhs.__parray_size_)
374 {
375 free(__parray_);
376 __parray_ = new_pointers.release();
377 __parray_cap_ = rhs.__parray_size_;
378 }
379 for (__parray_size_ = 0; __parray_size_ < rhs.__parray_size_; ++__parray_size_)
380 __parray_[__parray_size_] = rhs.__parray_[__parray_size_];
381}
382
383void
384ios_base::move(ios_base& rhs)
385{
386 // *this is uninitialized
387 __fmtflags_ = rhs.__fmtflags_;
388 __precision_ = rhs.__precision_;
389 __width_ = rhs.__width_;
390 __rdstate_ = rhs.__rdstate_;
391 __exceptions_ = rhs.__exceptions_;
392 __rdbuf_ = 0;
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000393 locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000394 ::new(&__loc_) locale(rhs_loc);
395 __fn_ = rhs.__fn_;
396 rhs.__fn_ = 0;
397 __index_ = rhs.__index_;
398 rhs.__index_ = 0;
399 __event_size_ = rhs.__event_size_;
400 rhs.__event_size_ = 0;
401 __event_cap_ = rhs.__event_cap_;
402 rhs.__event_cap_ = 0;
403 __iarray_ = rhs.__iarray_;
404 rhs.__iarray_ = 0;
405 __iarray_size_ = rhs.__iarray_size_;
406 rhs.__iarray_size_ = 0;
407 __iarray_cap_ = rhs.__iarray_cap_;
408 rhs.__iarray_cap_ = 0;
409 __parray_ = rhs.__parray_;
410 rhs.__parray_ = 0;
411 __parray_size_ = rhs.__parray_size_;
412 rhs.__parray_size_ = 0;
413 __parray_cap_ = rhs.__parray_cap_;
414 rhs.__parray_cap_ = 0;
415}
416
417void
Howard Hinnantf57bd562012-07-21 01:03:40 +0000418ios_base::swap(ios_base& rhs) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000419{
Howard Hinnant0949eed2011-06-30 21:18:19 +0000420 _VSTD::swap(__fmtflags_, rhs.__fmtflags_);
421 _VSTD::swap(__precision_, rhs.__precision_);
422 _VSTD::swap(__width_, rhs.__width_);
423 _VSTD::swap(__rdstate_, rhs.__rdstate_);
424 _VSTD::swap(__exceptions_, rhs.__exceptions_);
Joerg Sonnenberger4c6acb52014-01-04 17:43:00 +0000425 locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_);
426 locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_);
Howard Hinnant0949eed2011-06-30 21:18:19 +0000427 _VSTD::swap(lhs_loc, rhs_loc);
428 _VSTD::swap(__fn_, rhs.__fn_);
429 _VSTD::swap(__index_, rhs.__index_);
430 _VSTD::swap(__event_size_, rhs.__event_size_);
431 _VSTD::swap(__event_cap_, rhs.__event_cap_);
432 _VSTD::swap(__iarray_, rhs.__iarray_);
433 _VSTD::swap(__iarray_size_, rhs.__iarray_size_);
434 _VSTD::swap(__iarray_cap_, rhs.__iarray_cap_);
435 _VSTD::swap(__parray_, rhs.__parray_);
436 _VSTD::swap(__parray_size_, rhs.__parray_size_);
437 _VSTD::swap(__parray_cap_, rhs.__parray_cap_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000438}
439
440void
441ios_base::__set_badbit_and_consider_rethrow()
442{
443 __rdstate_ |= badbit;
Howard Hinnantd4444702010-08-11 17:04:31 +0000444#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000445 if (__exceptions_ & badbit)
446 throw;
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000447#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000448}
449
450void
451ios_base::__set_failbit_and_consider_rethrow()
452{
453 __rdstate_ |= failbit;
Howard Hinnantd4444702010-08-11 17:04:31 +0000454#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000455 if (__exceptions_ & failbit)
456 throw;
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000457#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000458}
459
460bool
461ios_base::sync_with_stdio(bool sync)
462{
463 static bool previous_state = true;
464 bool r = previous_state;
465 previous_state = sync;
466 return r;
467}
468
469_LIBCPP_END_NAMESPACE_STD