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