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
23 template class basic_ios<char>;
24 template class basic_ios<wchar_t>;
25
26 template class basic_streambuf<char>;
27 template class basic_streambuf<wchar_t>;
28
29 template class basic_istream<char>;
30 template class basic_istream<wchar_t>;
31
32 template class basic_ostream<char>;
33 template class basic_ostream<wchar_t>;
34
35 template class basic_iostream<char>;
36
37 class _LIBCPP_HIDDEN __iostream_category
38 : public __do_message
39 {
40 public:
41 virtual const char* name() const _NOEXCEPT;
42 virtual string message(int ev) const;
43 };
44
45 const char*
name() const46 __iostream_category::name() const _NOEXCEPT
47 {
48 return "iostream";
49 }
50
51 string
message(int ev) const52 __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
63 const error_category&
iostream_category()64 iostream_category()
65 {
66 static __iostream_category s;
67 return s;
68 }
69
70 // ios_base::failure
71
failure(const string & msg,const error_code & ec)72 ios_base::failure::failure(const string& msg, const error_code& ec)
73 : system_error(ec, msg)
74 {
75 }
76
failure(const char * msg,const error_code & ec)77 ios_base::failure::failure(const char* msg, const error_code& ec)
78 : system_error(ec, msg)
79 {
80 }
81
~failure()82 ios_base::failure::~failure() throw()
83 {
84 }
85
86 // ios_base locale
87
88 const ios_base::fmtflags ios_base::boolalpha;
89 const ios_base::fmtflags ios_base::dec;
90 const ios_base::fmtflags ios_base::fixed;
91 const ios_base::fmtflags ios_base::hex;
92 const ios_base::fmtflags ios_base::internal;
93 const ios_base::fmtflags ios_base::left;
94 const ios_base::fmtflags ios_base::oct;
95 const ios_base::fmtflags ios_base::right;
96 const ios_base::fmtflags ios_base::scientific;
97 const ios_base::fmtflags ios_base::showbase;
98 const ios_base::fmtflags ios_base::showpoint;
99 const ios_base::fmtflags ios_base::showpos;
100 const ios_base::fmtflags ios_base::skipws;
101 const ios_base::fmtflags ios_base::unitbuf;
102 const ios_base::fmtflags ios_base::uppercase;
103 const ios_base::fmtflags ios_base::adjustfield;
104 const ios_base::fmtflags ios_base::basefield;
105 const ios_base::fmtflags ios_base::floatfield;
106
107 const ios_base::iostate ios_base::badbit;
108 const ios_base::iostate ios_base::eofbit;
109 const ios_base::iostate ios_base::failbit;
110 const ios_base::iostate ios_base::goodbit;
111
112 const ios_base::openmode ios_base::app;
113 const ios_base::openmode ios_base::ate;
114 const ios_base::openmode ios_base::binary;
115 const ios_base::openmode ios_base::in;
116 const ios_base::openmode ios_base::out;
117 const ios_base::openmode ios_base::trunc;
118
119 void
__call_callbacks(event ev)120 ios_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
131 locale
imbue(const locale & newloc)132 ios_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
142 locale
getloc() const143 ios_base::getloc() const
144 {
145 const locale& loc_storage = *(locale*)&__loc_;
146 return loc_storage;
147 }
148
149 // xalloc
150
151 int ios_base::__xindex_ = 0;
152
153 int
xalloc()154 ios_base::xalloc()
155 {
156 return __xindex_++;
157 }
158
159 long&
iword(int index)160 ios_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
187 void*&
pword(int index)188 ios_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
217 void
register_callback(event_callback fn,int index)218 ios_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
~ios_base()243 ios_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
256 void
clear(iostate state)257 ios_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
271 void
init(void * sb)272 ios_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
293 void
copyfmt(const ios_base & rhs)294 ios_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
369 void
move(ios_base & rhs)370 ios_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
403 void
swap(ios_base & rhs)404 ios_base::swap(ios_base& rhs) _NOEXCEPT
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
426 void
__set_badbit_and_consider_rethrow()427 ios_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
436 void
__set_failbit_and_consider_rethrow()437 ios_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
446 bool
sync_with_stdio(bool sync)447 ios_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