]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/libc++/src/ios.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / libc++ / src / ios.cpp
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*
46 __iostream_category::name() const _NOEXCEPT
47 {
48     return "iostream";
49 }
50
51 string
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
63 const error_category&
64 iostream_category()
65 {
66     static __iostream_category s;
67     return s;
68 }
69
70 // ios_base::failure
71
72 ios_base::failure::failure(const string& msg, const error_code& ec)
73     : system_error(ec, msg)
74 {
75 }
76
77 ios_base::failure::failure(const char* msg, const error_code& ec)
78     : system_error(ec, msg)
79 {
80 }
81
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
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
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
143 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
154 ios_base::xalloc()
155 {
156     return __xindex_++;
157 }
158
159 long&
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*&
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
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
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
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
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
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
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
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
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
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
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