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