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