Home | History | Annotate | Download | only in src
      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*
     48 __iostream_category::name() const _NOEXCEPT
     49 {
     50     return "iostream";
     51 }
     52 
     53 string
     54 __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&
     68 iostream_category() _NOEXCEPT
     69 {
     70     static __iostream_category s;
     71     return s;
     72 }
     73 
     74 // ios_base::failure
     75 
     76 ios_base::failure::failure(const string& msg, const error_code& ec)
     77     : system_error(ec, msg)
     78 {
     79 }
     80 
     81 ios_base::failure::failure(const char* msg, const error_code& ec)
     82     : system_error(ec, msg)
     83 {
     84 }
     85 
     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
    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
    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
    147 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
    161 ios_base::xalloc()
    162 {
    163     return __xindex_++;
    164 }
    165 
    166 long&
    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*&
    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
    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 
    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
    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
    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
    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
    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
    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
    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
    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
    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