blob: 80917a046d2ff4701e6b21d2fba608051b441fb4 [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
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
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000023template 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:
Howard Hinnant1e15fd12011-05-26 19:48:01 +000041 virtual const char* name() const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000042 virtual string message(int ev) const;
43};
44
45const char*
Howard Hinnant1e15fd12011-05-26 19:48:01 +000046__iostream_category::name() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000047{
48 return "iostream";
49}
50
51string
52__iostream_category::message(int ev) const
53{
Howard Hinnantadff4892010-05-24 17:49:41 +000054 if (ev != static_cast<int>(io_errc::stream)
55#ifdef ELAST
56 && ev <= ELAST
57#endif
58 )
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000059 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)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000168 newcap = _VSTD::max(2 * __iarray_cap_, req_size);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000169 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)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000196 newcap = _VSTD::max(2 * __parray_cap_, req_size);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000197 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)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000226 newcap = _VSTD::max(2 * __event_cap_, req_size);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000227 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;
Howard Hinnantd4444702010-08-11 17:04:31 +0000263#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000264 if (((state | (__rdbuf_ ? goodbit : badbit)) & __exceptions_) != 0)
265 throw failure("ios_base::clear");
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000266#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000267}
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_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000305#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000306 if (!new_callbacks)
307 throw bad_alloc();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000308#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000309 new_ints.reset((int*)malloc(sizeof(int) * rhs.__event_size_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000310#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000311 if (!new_ints)
312 throw bad_alloc();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000313#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000314 }
315 if (__iarray_cap_ < rhs.__iarray_size_)
316 {
317 new_longs.reset((long*)malloc(sizeof(long) * rhs.__iarray_size_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000318#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000319 if (!new_longs)
320 throw bad_alloc();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000321#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000322 }
323 if (__parray_cap_ < rhs.__parray_size_)
324 {
325 new_pointers.reset((void**)malloc(sizeof(void*) * rhs.__parray_size_));
Howard Hinnantd4444702010-08-11 17:04:31 +0000326#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000327 if (!new_pointers)
328 throw bad_alloc();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000329#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000330 }
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{
Howard Hinnant0949eed2011-06-30 21:18:19 +0000406 _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_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000411 locale& lhs_loc = *(locale*)&__loc_;
412 locale& rhs_loc = *(locale*)&rhs.__loc_;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000413 _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_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000424}
425
426void
427ios_base::__set_badbit_and_consider_rethrow()
428{
429 __rdstate_ |= badbit;
Howard Hinnantd4444702010-08-11 17:04:31 +0000430#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000431 if (__exceptions_ & badbit)
432 throw;
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000433#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000434}
435
436void
437ios_base::__set_failbit_and_consider_rethrow()
438{
439 __rdstate_ |= failbit;
Howard Hinnantd4444702010-08-11 17:04:31 +0000440#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000441 if (__exceptions_ & failbit)
442 throw;
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000443#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000444}
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