Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (c) 1999
      3  * Silicon Graphics Computer Systems, Inc.
      4  *
      5  * Copyright (c) 1999
      6  * Boris Fomitchev
      7  *
      8  * This material is provided "as is", with absolutely no warranty expressed
      9  * or implied. Any use is at your own risk.
     10  *
     11  * Permission to use or copy this software for any purpose is hereby granted
     12  * without fee, provided the above notices are retained on all copies.
     13  * Permission to modify the code and to distribute modified code is granted,
     14  * provided the above notices are retained, and a notice that the code was
     15  * modified is included with the above copyright notice.
     16  *
     17  */
     18 
     19 #include "stlport_prefix.h"
     20 
     21 #include <algorithm>
     22 #include <ios>
     23 #include <locale>
     24 #include <ostream> // for __get_ostreambuf definition
     25 
     26 #include "aligned_buffer.h"
     27 
     28 _STLP_BEGIN_NAMESPACE
     29 
     30 //----------------------------------------------------------------------
     31 // ios_base members
     32 
     33 // class ios_base::failure, a subclass of exception.  It's used solely
     34 // for reporting errors.
     35 
     36 ios_base::failure::failure(const string& s)
     37   : __Named_exception(s)
     38 {}
     39 
     40 ios_base::failure::~failure() _STLP_NOTHROW_INHERENTLY {}
     41 
     42 #if !defined (_STLP_STATIC_CONST_INIT_BUG) && !defined (_STLP_NO_STATIC_CONST_DEFINITION)
     43 // Definitions of ios_base's formatting flags.
     44 const ios_base::fmtflags ios_base::left;
     45 const ios_base::fmtflags ios_base::right;
     46 const ios_base::fmtflags ios_base::internal;
     47 const ios_base::fmtflags ios_base::dec;
     48 const ios_base::fmtflags ios_base::hex;
     49 const ios_base::fmtflags ios_base::oct;
     50 const ios_base::fmtflags ios_base::fixed;
     51 const ios_base::fmtflags ios_base::scientific;
     52 const ios_base::fmtflags ios_base::boolalpha;
     53 const ios_base::fmtflags ios_base::showbase;
     54 const ios_base::fmtflags ios_base::showpoint;
     55 const ios_base::fmtflags ios_base::showpos;
     56 const ios_base::fmtflags ios_base::skipws;
     57 const ios_base::fmtflags ios_base::unitbuf;
     58 const ios_base::fmtflags ios_base::uppercase;
     59 const ios_base::fmtflags ios_base::adjustfield;
     60 const ios_base::fmtflags ios_base::basefield;
     61 const ios_base::fmtflags ios_base::floatfield;
     62 
     63 // Definitions of ios_base's state flags.
     64 const ios_base::iostate ios_base::goodbit;
     65 const ios_base::iostate ios_base::badbit;
     66 const ios_base::iostate ios_base::eofbit;
     67 const ios_base::iostate ios_base::failbit;
     68 
     69 // Definitions of ios_base's openmode flags.
     70 const ios_base::openmode ios_base::app;
     71 const ios_base::openmode ios_base::ate;
     72 const ios_base::openmode ios_base::binary;
     73 const ios_base::openmode ios_base::in;
     74 const ios_base::openmode ios_base::out;
     75 const ios_base::openmode ios_base::trunc;
     76 
     77 // Definitions of ios_base's seekdir flags.
     78 const ios_base::seekdir ios_base::beg;
     79 const ios_base::seekdir ios_base::cur;
     80 const ios_base::seekdir ios_base::end;
     81 
     82 #endif
     83 
     84 // Internal functions used for managing exponentially-growing arrays of
     85 // POD types.
     86 
     87 // array is a pointer to N elements of type PODType.  Expands the array,
     88 // if necessary, so that array[index] is meaningful.  All new elements are
     89 // initialized to zero.  Returns a pointer to the new array, and the new
     90 // size.
     91 
     92 template <class PODType>
     93 static pair<PODType*, size_t>
     94 _Stl_expand_array(PODType* __array, size_t N, int index) {
     95   if ((int)N < index + 1) {
     96     size_t new_N = (max)(2 * N, size_t(index + 1));
     97     PODType* new_array
     98       = __STATIC_CAST(PODType*,realloc(__array, new_N * sizeof(PODType)));
     99     if (new_array) {
    100       fill(new_array + N, new_array + new_N, PODType());
    101       return pair<PODType*, size_t>(new_array, new_N);
    102     }
    103     else
    104       return pair<PODType*, size_t>(__STATIC_CAST(PODType*,0), 0);
    105   }
    106   else
    107     return pair<PODType*, size_t>(__array, N);
    108 }
    109 
    110 // array is a pointer to N elements of type PODType.  Allocate a new
    111 // array of N elements, copying the values from the old array to the new.
    112 // Return a pointer to the new array.  It is assumed that array is non-null
    113 // and N is nonzero.
    114 template <class PODType>
    115 static PODType* _Stl_copy_array(const PODType* __array, size_t N) {
    116   PODType* result = __STATIC_CAST(PODType*,malloc(N * sizeof(PODType)));
    117   if (result)
    118     copy(__array, __array + N, result);
    119   return result;
    120 }
    121 
    122 locale ios_base::imbue(const locale& loc) {
    123   if (loc != _M_locale) {
    124     locale previous = _M_locale;
    125     _M_locale = loc;
    126     _M_invoke_callbacks(imbue_event);
    127     return previous;
    128   }
    129   else {
    130     _M_invoke_callbacks(imbue_event);
    131     return _M_locale;
    132   }
    133 }
    134 
    135 int _STLP_CALL ios_base::xalloc() {
    136 #if defined (_STLP_THREADS) && \
    137     defined (_STLP_WIN32THREADS) && defined (_STLP_NEW_PLATFORM_SDK)
    138   static volatile __stl_atomic_t _S_index = 0;
    139   return _STLP_ATOMIC_INCREMENT(&_S_index);
    140 #else
    141   static int _S_index = 0;
    142   static _STLP_STATIC_MUTEX __lock _STLP_MUTEX_INITIALIZER;
    143   _STLP_auto_lock sentry(__lock);
    144   return _S_index++;
    145 #endif
    146 }
    147 
    148 long& ios_base::iword(int index) {
    149   static long dummy = 0;
    150 
    151   pair<long*, size_t> tmp = _Stl_expand_array(_M_iwords, _M_num_iwords, index);
    152   if (tmp.first) {              // The allocation, if any, succeeded.
    153     _M_iwords = tmp.first;
    154     _M_num_iwords = tmp.second;
    155     return _M_iwords[index];
    156   }
    157   else {
    158     _M_setstate_nothrow(badbit);
    159     _M_check_exception_mask();
    160     return dummy;
    161   }
    162 }
    163 
    164 
    165 void*& ios_base::pword(int index) {
    166   static void* dummy = 0;
    167 
    168   pair<void**, size_t> tmp = _Stl_expand_array(_M_pwords, _M_num_pwords, index);
    169   if (tmp.first) {              // The allocation, if any, succeeded.
    170     _M_pwords = tmp.first;
    171     _M_num_pwords = tmp.second;
    172     return _M_pwords[index];
    173   }
    174   else {
    175     _M_setstate_nothrow(badbit);
    176     _M_check_exception_mask();
    177     return dummy;
    178   }
    179 }
    180 
    181 void ios_base::register_callback(event_callback __fn, int index) {
    182   pair<pair<event_callback, int>*, size_t> tmp
    183     = _Stl_expand_array(_M_callbacks, _M_num_callbacks, (int)_M_callback_index /* fbp: index ??? */ );
    184   if (tmp.first) {
    185     _M_callbacks = tmp.first;
    186     _M_num_callbacks = tmp.second;
    187     _M_callbacks[_M_callback_index++] = make_pair(__fn, index);
    188   }
    189   else {
    190     _M_setstate_nothrow(badbit);
    191     _M_check_exception_mask();
    192   }
    193 }
    194 
    195 // Invokes all currently registered callbacks for a particular event.
    196 // Behaves correctly even if one of the callbacks adds a new callback.
    197 void ios_base::_M_invoke_callbacks(event E) {
    198   for (size_t i = _M_callback_index; i > 0; --i) {
    199     event_callback f = _M_callbacks[i-1].first;
    200     int n = _M_callbacks[i-1].second;
    201     f(E, *this, n);
    202   }
    203 }
    204 
    205 // This function is called if the state, rdstate(), has a bit set
    206 // that is also set in the exception mask exceptions().
    207 void ios_base::_M_throw_failure() {
    208   const char* arg ;
    209 # if 0
    210   char buffer[256];
    211   char* ptr;
    212   strcpy(buffer, "ios failure: rdstate = 0x");
    213   ptr = __write_integer(buffer+strlen(buffer), ios_base::hex, __STATIC_CAST(unsigned long,_M_iostate));
    214   strcpy(ptr, " mask = 0x");
    215   ptr = __write_integer(buffer+strlen(buffer), ios_base::hex, __STATIC_CAST(unsigned long,_M_exception_mask));
    216   *ptr = 0;
    217   arg = buffer;
    218 # else
    219   arg = "ios failure";
    220 # endif
    221 
    222 # ifndef _STLP_USE_EXCEPTIONS
    223   fputs(arg, stderr);
    224 # else
    225   throw failure(arg);
    226 # endif
    227 }
    228 
    229 // Copy x's state to *this.  This member function is used in the
    230 // implementation of basic_ios::copyfmt.  Does not copy _M_exception_mask
    231 // or _M_iostate.
    232 void ios_base::_M_copy_state(const ios_base& x) {
    233   _M_fmtflags  = x._M_fmtflags; // Copy the flags, except for _M_iostate
    234   _M_openmode  = x._M_openmode; // and _M_exception_mask.
    235   _M_seekdir   = x._M_seekdir;
    236   _M_precision = x._M_precision;
    237   _M_width     = x._M_width;
    238   _M_locale    = x._M_locale;
    239 
    240   if (x._M_callbacks) {
    241     pair<event_callback, int>* tmp = _Stl_copy_array(x._M_callbacks, x._M_callback_index);
    242     if (tmp) {
    243       free(_M_callbacks);
    244       _M_callbacks = tmp;
    245       _M_num_callbacks = _M_callback_index = x._M_callback_index;
    246     }
    247     else {
    248       _M_setstate_nothrow(badbit);
    249       _M_check_exception_mask();
    250     }
    251   }
    252 
    253   if (x._M_iwords) {
    254     long* tmp = _Stl_copy_array(x._M_iwords, x._M_num_iwords);
    255     if (tmp) {
    256       free(_M_iwords);
    257       _M_iwords = tmp;
    258       _M_num_iwords = x._M_num_iwords;
    259     }
    260     else {
    261       _M_setstate_nothrow(badbit);
    262       _M_check_exception_mask();
    263     }
    264   }
    265 
    266   if (x._M_pwords) {
    267     void** tmp = _Stl_copy_array(x._M_pwords, x._M_num_pwords);
    268     if (tmp) {
    269       free(_M_pwords);
    270       _M_pwords = tmp;
    271       _M_num_pwords = x._M_num_pwords;
    272     }
    273     else {
    274       _M_setstate_nothrow(badbit);
    275       _M_check_exception_mask();
    276     }
    277   }
    278 }
    279 
    280 // ios's (protected) default constructor.  The standard says that all
    281 // fields have indeterminate values; we initialize them to zero for
    282 // simplicity.  The only thing that really matters is that the arrays
    283 // are all initially null pointers, and the array element counts are all
    284 // initially zero.
    285 ios_base::ios_base()
    286   : _M_fmtflags(0), _M_iostate(0), _M_openmode(0), _M_seekdir(0),
    287     _M_exception_mask(0),
    288     _M_precision(0), _M_width(0),
    289     _M_locale(),
    290     _M_callbacks(0), _M_num_callbacks(0), _M_callback_index(0),
    291     _M_iwords(0), _M_num_iwords(0),
    292     _M_pwords(0),
    293     _M_num_pwords(0)
    294 {}
    295 
    296 // ios's destructor.
    297 ios_base::~ios_base() {
    298   _M_invoke_callbacks(erase_event);
    299   free(_M_callbacks);
    300   free(_M_iwords);
    301   free(_M_pwords);
    302 }
    303 
    304 //----------------------------------------------------------------------
    305 // Force instantiation of basic_ios
    306 // For DLL exports, they are already instantiated.
    307 #if !defined(_STLP_NO_FORCE_INSTANTIATE)
    308 template class _STLP_CLASS_DECLSPEC basic_ios<char, char_traits<char> >;
    309 #  if !defined (_STLP_NO_WCHAR_T)
    310 template class _STLP_CLASS_DECLSPEC basic_ios<wchar_t, char_traits<wchar_t> >;
    311 #  endif /* _STLP_NO_WCHAR_T */
    312 #endif
    313 
    314 _STLP_END_NAMESPACE
    315 
    316 // Local Variables:
    317 // mode:C++
    318 // End:
    319