1227825Stheraven//===-------------------------- ios.cpp -----------------------------------===//
2227825Stheraven//
3227825Stheraven//                     The LLVM Compiler Infrastructure
4227825Stheraven//
5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
6227825Stheraven// Source Licenses. See LICENSE.TXT for details.
7227825Stheraven//
8227825Stheraven//===----------------------------------------------------------------------===//
9227825Stheraven
10278724Sdim#include "__config"
11227825Stheraven#include "ios"
12227825Stheraven#include "streambuf"
13227825Stheraven#include "istream"
14227825Stheraven#include "string"
15227825Stheraven#include "__locale"
16227825Stheraven#include "algorithm"
17227825Stheraven#include "memory"
18227825Stheraven#include "new"
19227825Stheraven#include "limits"
20227825Stheraven#include <stdlib.h>
21227825Stheraven
22227825Stheraven_LIBCPP_BEGIN_NAMESPACE_STD
23227825Stheraven
24227825Stheraventemplate class basic_ios<char>;
25227825Stheraventemplate class basic_ios<wchar_t>;
26227825Stheraven
27227825Stheraventemplate class basic_streambuf<char>;
28227825Stheraventemplate class basic_streambuf<wchar_t>;
29227825Stheraven
30227825Stheraventemplate class basic_istream<char>;
31227825Stheraventemplate class basic_istream<wchar_t>;
32227825Stheraven
33227825Stheraventemplate class basic_ostream<char>;
34227825Stheraventemplate class basic_ostream<wchar_t>;
35227825Stheraven
36227825Stheraventemplate class basic_iostream<char>;
37227825Stheraven
38227825Stheravenclass _LIBCPP_HIDDEN __iostream_category
39227825Stheraven    : public __do_message
40227825Stheraven{
41227825Stheravenpublic:
42227825Stheraven    virtual const char* name() const _NOEXCEPT;
43227825Stheraven    virtual string message(int ev) const;
44227825Stheraven};
45227825Stheraven
46227825Stheravenconst char*
47227825Stheraven__iostream_category::name() const _NOEXCEPT
48227825Stheraven{
49227825Stheraven    return "iostream";
50227825Stheraven}
51227825Stheraven
52227825Stheravenstring
53227825Stheraven__iostream_category::message(int ev) const
54227825Stheraven{
55227825Stheraven    if (ev != static_cast<int>(io_errc::stream)
56278724Sdim#ifdef _LIBCPP_ELAST
57278724Sdim        && ev <= _LIBCPP_ELAST
58278724Sdim#endif  // _LIBCPP_ELAST
59227825Stheraven        )
60227825Stheraven        return __do_message::message(ev);
61227825Stheraven    return string("unspecified iostream_category error");
62227825Stheraven}
63227825Stheraven
64227825Stheravenconst error_category&
65262801Sdimiostream_category() _NOEXCEPT
66227825Stheraven{
67227825Stheraven    static __iostream_category s;
68227825Stheraven    return s;
69227825Stheraven}
70227825Stheraven
71227825Stheraven// ios_base::failure
72227825Stheraven
73227825Stheravenios_base::failure::failure(const string& msg, const error_code& ec)
74227825Stheraven    : system_error(ec, msg)
75227825Stheraven{
76227825Stheraven}
77227825Stheraven
78227825Stheravenios_base::failure::failure(const char* msg, const error_code& ec)
79227825Stheraven    : system_error(ec, msg)
80227825Stheraven{
81227825Stheraven}
82227825Stheraven
83227825Stheravenios_base::failure::~failure() throw()
84227825Stheraven{
85227825Stheraven}
86227825Stheraven
87227825Stheraven// ios_base locale
88227825Stheraven
89227825Stheravenconst ios_base::fmtflags ios_base::boolalpha;
90227825Stheravenconst ios_base::fmtflags ios_base::dec;
91227825Stheravenconst ios_base::fmtflags ios_base::fixed;
92227825Stheravenconst ios_base::fmtflags ios_base::hex;
93227825Stheravenconst ios_base::fmtflags ios_base::internal;
94227825Stheravenconst ios_base::fmtflags ios_base::left;
95227825Stheravenconst ios_base::fmtflags ios_base::oct;
96227825Stheravenconst ios_base::fmtflags ios_base::right;
97227825Stheravenconst ios_base::fmtflags ios_base::scientific;
98227825Stheravenconst ios_base::fmtflags ios_base::showbase;
99227825Stheravenconst ios_base::fmtflags ios_base::showpoint;
100227825Stheravenconst ios_base::fmtflags ios_base::showpos;
101227825Stheravenconst ios_base::fmtflags ios_base::skipws;
102227825Stheravenconst ios_base::fmtflags ios_base::unitbuf;
103227825Stheravenconst ios_base::fmtflags ios_base::uppercase;
104227825Stheravenconst ios_base::fmtflags ios_base::adjustfield;
105227825Stheravenconst ios_base::fmtflags ios_base::basefield;
106227825Stheravenconst ios_base::fmtflags ios_base::floatfield;
107227825Stheraven
108227825Stheravenconst ios_base::iostate ios_base::badbit;
109227825Stheravenconst ios_base::iostate ios_base::eofbit;
110227825Stheravenconst ios_base::iostate ios_base::failbit;
111227825Stheravenconst ios_base::iostate ios_base::goodbit;
112227825Stheraven
113227825Stheravenconst ios_base::openmode ios_base::app;
114227825Stheravenconst ios_base::openmode ios_base::ate;
115227825Stheravenconst ios_base::openmode ios_base::binary;
116227825Stheravenconst ios_base::openmode ios_base::in;
117227825Stheravenconst ios_base::openmode ios_base::out;
118227825Stheravenconst ios_base::openmode ios_base::trunc;
119227825Stheraven
120227825Stheravenvoid
121227825Stheravenios_base::__call_callbacks(event ev)
122227825Stheraven{
123227825Stheraven    for (size_t i = __event_size_; i;)
124227825Stheraven    {
125227825Stheraven        --i;
126227825Stheraven        __fn_[i](ev, *this, __index_[i]);
127227825Stheraven    }
128227825Stheraven}
129227825Stheraven
130227825Stheraven// locale
131227825Stheraven
132227825Stheravenlocale
133227825Stheravenios_base::imbue(const locale& newloc)
134227825Stheraven{
135227825Stheraven    static_assert(sizeof(locale) == sizeof(__loc_), "");
136278724Sdim    locale& loc_storage = *reinterpret_cast<locale*>(&__loc_);
137227825Stheraven    locale oldloc = loc_storage;
138227825Stheraven    loc_storage = newloc;
139227825Stheraven    __call_callbacks(imbue_event);
140227825Stheraven    return oldloc;
141227825Stheraven}
142227825Stheraven
143227825Stheravenlocale
144227825Stheravenios_base::getloc() const
145227825Stheraven{
146278724Sdim    const locale& loc_storage = *reinterpret_cast<const locale*>(&__loc_);
147227825Stheraven    return loc_storage;
148227825Stheraven}
149227825Stheraven
150227825Stheraven// xalloc
151278724Sdim#if __has_feature(cxx_atomic) && !defined(_LIBCPP_HAS_NO_THREADS)
152262801Sdimatomic<int> ios_base::__xindex_ = ATOMIC_VAR_INIT(0);
153262801Sdim#else
154227825Stheravenint ios_base::__xindex_ = 0;
155262801Sdim#endif
156227825Stheraven
157278724Sdimtemplate <typename _Tp>
158278724Sdimstatic size_t __ios_new_cap(size_t __req_size, size_t __current_cap)
159278724Sdim{ // Precondition: __req_size > __current_cap
160278724Sdim	const size_t mx = std::numeric_limits<size_t>::max() / sizeof(_Tp);
161278724Sdim	if (__req_size < mx/2)
162278724Sdim		return _VSTD::max(2 * __current_cap, __req_size);
163278724Sdim	else
164278724Sdim		return mx;
165278724Sdim}
166278724Sdim
167227825Stheravenint
168227825Stheravenios_base::xalloc()
169227825Stheraven{
170227825Stheraven    return __xindex_++;
171227825Stheraven}
172227825Stheraven
173227825Stheravenlong&
174227825Stheravenios_base::iword(int index)
175227825Stheraven{
176227825Stheraven    size_t req_size = static_cast<size_t>(index)+1;
177227825Stheraven    if (req_size > __iarray_cap_)
178227825Stheraven    {
179278724Sdim        size_t newcap = __ios_new_cap<long>(req_size, __iarray_cap_);
180278724Sdim        long* iarray = static_cast<long*>(realloc(__iarray_, newcap * sizeof(long)));
181227825Stheraven        if (iarray == 0)
182227825Stheraven        {
183227825Stheraven            setstate(badbit);
184227825Stheraven            static long error;
185227825Stheraven            error = 0;
186227825Stheraven            return error;
187227825Stheraven        }
188227825Stheraven        __iarray_ = iarray;
189278724Sdim        for (long* p = __iarray_ + __iarray_size_; p < __iarray_ + newcap; ++p)
190227825Stheraven            *p = 0;
191278724Sdim        __iarray_cap_ = newcap;
192227825Stheraven    }
193227825Stheraven    __iarray_size_ = max<size_t>(__iarray_size_, req_size);
194227825Stheraven    return __iarray_[index];
195227825Stheraven}
196227825Stheraven
197227825Stheravenvoid*&
198227825Stheravenios_base::pword(int index)
199227825Stheraven{
200227825Stheraven    size_t req_size = static_cast<size_t>(index)+1;
201227825Stheraven    if (req_size > __parray_cap_)
202227825Stheraven    {
203278724Sdim        size_t newcap = __ios_new_cap<void *>(req_size, __iarray_cap_);
204278724Sdim        void** parray = static_cast<void**>(realloc(__parray_, newcap * sizeof(void *)));
205227825Stheraven        if (parray == 0)
206227825Stheraven        {
207227825Stheraven            setstate(badbit);
208227825Stheraven            static void* error;
209227825Stheraven            error = 0;
210227825Stheraven            return error;
211227825Stheraven        }
212227825Stheraven        __parray_ = parray;
213278724Sdim        for (void** p = __parray_ + __parray_size_; p < __parray_ + newcap; ++p)
214227825Stheraven            *p = 0;
215278724Sdim        __parray_cap_ = newcap;
216227825Stheraven    }
217227825Stheraven    __parray_size_ = max<size_t>(__parray_size_, req_size);
218227825Stheraven    return __parray_[index];
219227825Stheraven}
220227825Stheraven
221227825Stheraven// register_callback
222227825Stheraven
223227825Stheravenvoid
224227825Stheravenios_base::register_callback(event_callback fn, int index)
225227825Stheraven{
226227825Stheraven    size_t req_size = __event_size_ + 1;
227227825Stheraven    if (req_size > __event_cap_)
228227825Stheraven    {
229278724Sdim        size_t newcap = __ios_new_cap<event_callback>(req_size, __event_cap_);
230278724Sdim        event_callback* fns = static_cast<event_callback*>(realloc(__fn_, newcap * sizeof(event_callback)));
231227825Stheraven        if (fns == 0)
232227825Stheraven            setstate(badbit);
233227825Stheraven        __fn_ = fns;
234278724Sdim        int* indxs = static_cast<int *>(realloc(__index_, newcap * sizeof(int)));
235227825Stheraven        if (indxs == 0)
236227825Stheraven            setstate(badbit);
237227825Stheraven        __index_ = indxs;
238278724Sdim        __event_cap_ = newcap;
239227825Stheraven    }
240227825Stheraven    __fn_[__event_size_] = fn;
241227825Stheraven    __index_[__event_size_] = index;
242227825Stheraven    ++__event_size_;
243227825Stheraven}
244227825Stheraven
245227825Stheravenios_base::~ios_base()
246227825Stheraven{
247227825Stheraven    __call_callbacks(erase_event);
248278724Sdim    locale& loc_storage = *reinterpret_cast<locale*>(&__loc_);
249227825Stheraven    loc_storage.~locale();
250227825Stheraven    free(__fn_);
251227825Stheraven    free(__index_);
252227825Stheraven    free(__iarray_);
253227825Stheraven    free(__parray_);
254227825Stheraven}
255227825Stheraven
256227825Stheraven// iostate
257227825Stheraven
258227825Stheravenvoid
259227825Stheravenios_base::clear(iostate state)
260227825Stheraven{
261227825Stheraven    if (__rdbuf_)
262227825Stheraven        __rdstate_ = state;
263227825Stheraven    else
264227825Stheraven        __rdstate_ = state | badbit;
265227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
266227825Stheraven    if (((state | (__rdbuf_ ? goodbit : badbit)) & __exceptions_) != 0)
267227825Stheraven        throw failure("ios_base::clear");
268227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
269227825Stheraven}
270227825Stheraven
271227825Stheraven// init
272227825Stheraven
273227825Stheravenvoid
274227825Stheravenios_base::init(void* sb)
275227825Stheraven{
276227825Stheraven    __rdbuf_ = sb;
277227825Stheraven    __rdstate_ = __rdbuf_ ? goodbit : badbit;
278227825Stheraven    __exceptions_ = goodbit;
279227825Stheraven    __fmtflags_ = skipws | dec;
280227825Stheraven    __width_ = 0;
281227825Stheraven    __precision_ = 6;
282227825Stheraven    __fn_ = 0;
283227825Stheraven    __index_ = 0;
284227825Stheraven    __event_size_ = 0;
285227825Stheraven    __event_cap_ = 0;
286227825Stheraven    __iarray_ = 0;
287227825Stheraven    __iarray_size_ = 0;
288227825Stheraven    __iarray_cap_ = 0;
289227825Stheraven    __parray_ = 0;
290227825Stheraven    __parray_size_ = 0;
291227825Stheraven    __parray_cap_ = 0;
292227825Stheraven    ::new(&__loc_) locale;
293227825Stheraven}
294227825Stheraven
295227825Stheravenvoid
296227825Stheravenios_base::copyfmt(const ios_base& rhs)
297227825Stheraven{
298227825Stheraven    // If we can't acquire the needed resources, throw bad_alloc (can't set badbit)
299278724Sdim    // Don't alter *this until all needed resources are acquired
300227825Stheraven    unique_ptr<event_callback, void (*)(void*)> new_callbacks(0, free);
301227825Stheraven    unique_ptr<int, void (*)(void*)> new_ints(0, free);
302227825Stheraven    unique_ptr<long, void (*)(void*)> new_longs(0, free);
303227825Stheraven    unique_ptr<void*, void (*)(void*)> new_pointers(0, free);
304227825Stheraven    if (__event_cap_ < rhs.__event_size_)
305227825Stheraven    {
306278724Sdim        size_t newesize = sizeof(event_callback) * rhs.__event_size_;
307278724Sdim        new_callbacks.reset(static_cast<event_callback*>(malloc(newesize)));
308227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
309227825Stheraven        if (!new_callbacks)
310227825Stheraven            throw bad_alloc();
311227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
312278724Sdim
313278724Sdim        size_t newisize = sizeof(int) * rhs.__event_size_;
314278724Sdim        new_ints.reset(static_cast<int *>(malloc(newisize)));
315227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
316227825Stheraven        if (!new_ints)
317227825Stheraven            throw bad_alloc();
318227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
319227825Stheraven    }
320227825Stheraven    if (__iarray_cap_ < rhs.__iarray_size_)
321227825Stheraven    {
322278724Sdim        size_t newsize = sizeof(long) * rhs.__iarray_size_;
323278724Sdim        new_longs.reset(static_cast<long*>(malloc(newsize)));
324227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
325227825Stheraven        if (!new_longs)
326227825Stheraven            throw bad_alloc();
327227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
328227825Stheraven    }
329227825Stheraven    if (__parray_cap_ < rhs.__parray_size_)
330227825Stheraven    {
331278724Sdim        size_t newsize = sizeof(void*) * rhs.__parray_size_;
332278724Sdim        new_pointers.reset(static_cast<void**>(malloc(newsize)));
333227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
334227825Stheraven        if (!new_pointers)
335227825Stheraven            throw bad_alloc();
336227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
337227825Stheraven    }
338227825Stheraven    // Got everything we need.  Copy everything but __rdstate_, __rdbuf_ and __exceptions_
339227825Stheraven    __fmtflags_ = rhs.__fmtflags_;
340227825Stheraven    __precision_ = rhs.__precision_;
341227825Stheraven    __width_ = rhs.__width_;
342278724Sdim    locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_);
343278724Sdim    const locale& rhs_loc = *reinterpret_cast<const locale*>(&rhs.__loc_);
344227825Stheraven    lhs_loc = rhs_loc;
345227825Stheraven    if (__event_cap_ < rhs.__event_size_)
346227825Stheraven    {
347227825Stheraven        free(__fn_);
348227825Stheraven        __fn_ = new_callbacks.release();
349227825Stheraven        free(__index_);
350227825Stheraven        __index_ = new_ints.release();
351227825Stheraven        __event_cap_ = rhs.__event_size_;
352227825Stheraven    }
353227825Stheraven    for (__event_size_ = 0; __event_size_ < rhs.__event_size_; ++__event_size_)
354227825Stheraven    {
355227825Stheraven        __fn_[__event_size_] = rhs.__fn_[__event_size_];
356227825Stheraven        __index_[__event_size_] = rhs.__index_[__event_size_];
357227825Stheraven    }
358227825Stheraven    if (__iarray_cap_ < rhs.__iarray_size_)
359227825Stheraven    {
360227825Stheraven        free(__iarray_);
361227825Stheraven        __iarray_ = new_longs.release();
362227825Stheraven        __iarray_cap_ = rhs.__iarray_size_;
363227825Stheraven    }
364227825Stheraven    for (__iarray_size_ = 0; __iarray_size_ < rhs.__iarray_size_; ++__iarray_size_)
365227825Stheraven        __iarray_[__iarray_size_] = rhs.__iarray_[__iarray_size_];
366227825Stheraven    if (__parray_cap_ < rhs.__parray_size_)
367227825Stheraven    {
368227825Stheraven        free(__parray_);
369227825Stheraven        __parray_ = new_pointers.release();
370227825Stheraven        __parray_cap_ = rhs.__parray_size_;
371227825Stheraven    }
372227825Stheraven    for (__parray_size_ = 0; __parray_size_ < rhs.__parray_size_; ++__parray_size_)
373227825Stheraven        __parray_[__parray_size_] = rhs.__parray_[__parray_size_];
374227825Stheraven}
375227825Stheraven
376227825Stheravenvoid
377227825Stheravenios_base::move(ios_base& rhs)
378227825Stheraven{
379227825Stheraven    // *this is uninitialized
380227825Stheraven    __fmtflags_ = rhs.__fmtflags_;
381227825Stheraven    __precision_ = rhs.__precision_;
382227825Stheraven    __width_ = rhs.__width_;
383227825Stheraven    __rdstate_ = rhs.__rdstate_;
384227825Stheraven    __exceptions_ = rhs.__exceptions_;
385227825Stheraven    __rdbuf_ = 0;
386278724Sdim    locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_);
387227825Stheraven    ::new(&__loc_) locale(rhs_loc);
388227825Stheraven    __fn_ = rhs.__fn_;
389227825Stheraven    rhs.__fn_ = 0;
390227825Stheraven    __index_ = rhs.__index_;
391227825Stheraven    rhs.__index_ = 0;
392227825Stheraven    __event_size_ = rhs.__event_size_;
393227825Stheraven    rhs.__event_size_ = 0;
394227825Stheraven    __event_cap_ = rhs.__event_cap_;
395227825Stheraven    rhs.__event_cap_ = 0;
396227825Stheraven    __iarray_ = rhs.__iarray_;
397227825Stheraven    rhs.__iarray_ = 0;
398227825Stheraven    __iarray_size_ = rhs.__iarray_size_;
399227825Stheraven    rhs.__iarray_size_ = 0;
400227825Stheraven    __iarray_cap_ = rhs.__iarray_cap_;
401227825Stheraven    rhs.__iarray_cap_ = 0;
402227825Stheraven    __parray_ = rhs.__parray_;
403227825Stheraven    rhs.__parray_ = 0;
404227825Stheraven    __parray_size_ = rhs.__parray_size_;
405227825Stheraven    rhs.__parray_size_ = 0;
406227825Stheraven    __parray_cap_ = rhs.__parray_cap_;
407227825Stheraven    rhs.__parray_cap_ = 0;
408227825Stheraven}
409227825Stheraven
410227825Stheravenvoid
411241903Sdimios_base::swap(ios_base& rhs) _NOEXCEPT
412227825Stheraven{
413227825Stheraven    _VSTD::swap(__fmtflags_, rhs.__fmtflags_);
414227825Stheraven    _VSTD::swap(__precision_, rhs.__precision_);
415227825Stheraven    _VSTD::swap(__width_, rhs.__width_);
416227825Stheraven    _VSTD::swap(__rdstate_, rhs.__rdstate_);
417227825Stheraven    _VSTD::swap(__exceptions_, rhs.__exceptions_);
418278724Sdim    locale& lhs_loc = *reinterpret_cast<locale*>(&__loc_);
419278724Sdim    locale& rhs_loc = *reinterpret_cast<locale*>(&rhs.__loc_);
420227825Stheraven    _VSTD::swap(lhs_loc, rhs_loc);
421227825Stheraven    _VSTD::swap(__fn_, rhs.__fn_);
422227825Stheraven    _VSTD::swap(__index_, rhs.__index_);
423227825Stheraven    _VSTD::swap(__event_size_, rhs.__event_size_);
424227825Stheraven    _VSTD::swap(__event_cap_, rhs.__event_cap_);
425227825Stheraven    _VSTD::swap(__iarray_, rhs.__iarray_);
426227825Stheraven    _VSTD::swap(__iarray_size_, rhs.__iarray_size_);
427227825Stheraven    _VSTD::swap(__iarray_cap_, rhs.__iarray_cap_);
428227825Stheraven    _VSTD::swap(__parray_, rhs.__parray_);
429227825Stheraven    _VSTD::swap(__parray_size_, rhs.__parray_size_);
430227825Stheraven    _VSTD::swap(__parray_cap_, rhs.__parray_cap_);
431227825Stheraven}
432227825Stheraven
433227825Stheravenvoid
434227825Stheravenios_base::__set_badbit_and_consider_rethrow()
435227825Stheraven{
436227825Stheraven    __rdstate_ |= badbit;
437227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
438227825Stheraven    if (__exceptions_ & badbit)
439227825Stheraven        throw;
440227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
441227825Stheraven}
442227825Stheraven
443227825Stheravenvoid
444227825Stheravenios_base::__set_failbit_and_consider_rethrow()
445227825Stheraven{
446227825Stheraven    __rdstate_ |= failbit;
447227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
448227825Stheraven    if (__exceptions_ & failbit)
449227825Stheraven        throw;
450227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
451227825Stheraven}
452227825Stheraven
453227825Stheravenbool
454227825Stheravenios_base::sync_with_stdio(bool sync)
455227825Stheraven{
456227825Stheraven    static bool previous_state = true;
457227825Stheraven    bool r = previous_state;
458227825Stheraven    previous_state = sync;
459227825Stheraven    return r;
460227825Stheraven}
461227825Stheraven
462227825Stheraven_LIBCPP_END_NAMESPACE_STD
463