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 37 ios_base::failure::failure(const string& s) 38 : __Named_exception(s) 39 {} 40 41 ios_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. 46 const ios_base::fmtflags ios_base::left; 47 const ios_base::fmtflags ios_base::right; 48 const ios_base::fmtflags ios_base::internal; 49 const ios_base::fmtflags ios_base::dec; 50 const ios_base::fmtflags ios_base::hex; 51 const ios_base::fmtflags ios_base::oct; 52 const ios_base::fmtflags ios_base::fixed; 53 const ios_base::fmtflags ios_base::scientific; 54 const ios_base::fmtflags ios_base::boolalpha; 55 const ios_base::fmtflags ios_base::showbase; 56 const ios_base::fmtflags ios_base::showpoint; 57 const ios_base::fmtflags ios_base::showpos; 58 const ios_base::fmtflags ios_base::skipws; 59 const ios_base::fmtflags ios_base::unitbuf; 60 const ios_base::fmtflags ios_base::uppercase; 61 const ios_base::fmtflags ios_base::adjustfield; 62 const ios_base::fmtflags ios_base::basefield; 63 const ios_base::fmtflags ios_base::floatfield; 64 65 // Definitions of ios_base's state flags. 66 const ios_base::iostate ios_base::goodbit; 67 const ios_base::iostate ios_base::badbit; 68 const ios_base::iostate ios_base::eofbit; 69 const ios_base::iostate ios_base::failbit; 70 71 // Definitions of ios_base's openmode flags. 72 const ios_base::openmode ios_base::app; 73 const ios_base::openmode ios_base::ate; 74 const ios_base::openmode ios_base::binary; 75 const ios_base::openmode ios_base::in; 76 const ios_base::openmode ios_base::out; 77 const ios_base::openmode ios_base::trunc; 78 79 // Definitions of ios_base's seekdir flags. 80 const ios_base::seekdir ios_base::beg; 81 const ios_base::seekdir ios_base::cur; 82 const 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 94 template <class PODType> 95 static 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. 116 template <class PODType> 117 static 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 124 locale 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 137 int _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 150 long& 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 167 void*& 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 183 void 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. 199 void 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(). 209 void 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. 234 void 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. 287 ios_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. 299 ios_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) 310 template class _STLP_CLASS_DECLSPEC basic_ios<char, char_traits<char> >; 311 # if !defined (_STLP_NO_WCHAR_T) 312 template 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