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