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 #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
    456