michael@0: /* michael@0: * Copyright (c) 1999 michael@0: * Silicon Graphics Computer Systems, Inc. michael@0: * michael@0: * Copyright (c) 1999 michael@0: * Boris Fomitchev michael@0: * michael@0: * This material is provided "as is", with absolutely no warranty expressed michael@0: * or implied. Any use is at your own risk. michael@0: * michael@0: * Permission to use or copy this software for any purpose is hereby granted michael@0: * without fee, provided the above notices are retained on all copies. michael@0: * Permission to modify the code and to distribute modified code is granted, michael@0: * provided the above notices are retained, and a notice that the code was michael@0: * modified is included with the above copyright notice. michael@0: * michael@0: */ michael@0: michael@0: #include "stlport_prefix.h" michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include // for __get_ostreambuf definition michael@0: michael@0: #include "aligned_buffer.h" michael@0: michael@0: _STLP_BEGIN_NAMESPACE michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // ios_base members michael@0: michael@0: #ifdef _STLP_USE_EXCEPTIONS michael@0: // class ios_base::failure, a subclass of exception. It's used solely michael@0: // for reporting errors. michael@0: michael@0: ios_base::failure::failure(const string& s) michael@0: : __Named_exception(s) michael@0: {} michael@0: michael@0: ios_base::failure::~failure() _STLP_NOTHROW_INHERENTLY {} michael@0: #endif michael@0: michael@0: #if !defined (_STLP_STATIC_CONST_INIT_BUG) && !defined (_STLP_NO_STATIC_CONST_DEFINITION) michael@0: // Definitions of ios_base's formatting flags. michael@0: const ios_base::fmtflags ios_base::left; michael@0: const ios_base::fmtflags ios_base::right; michael@0: const ios_base::fmtflags ios_base::internal; michael@0: const ios_base::fmtflags ios_base::dec; michael@0: const ios_base::fmtflags ios_base::hex; michael@0: const ios_base::fmtflags ios_base::oct; michael@0: const ios_base::fmtflags ios_base::fixed; michael@0: const ios_base::fmtflags ios_base::scientific; michael@0: const ios_base::fmtflags ios_base::boolalpha; michael@0: const ios_base::fmtflags ios_base::showbase; michael@0: const ios_base::fmtflags ios_base::showpoint; michael@0: const ios_base::fmtflags ios_base::showpos; michael@0: const ios_base::fmtflags ios_base::skipws; michael@0: const ios_base::fmtflags ios_base::unitbuf; michael@0: const ios_base::fmtflags ios_base::uppercase; michael@0: const ios_base::fmtflags ios_base::adjustfield; michael@0: const ios_base::fmtflags ios_base::basefield; michael@0: const ios_base::fmtflags ios_base::floatfield; michael@0: michael@0: // Definitions of ios_base's state flags. michael@0: const ios_base::iostate ios_base::goodbit; michael@0: const ios_base::iostate ios_base::badbit; michael@0: const ios_base::iostate ios_base::eofbit; michael@0: const ios_base::iostate ios_base::failbit; michael@0: michael@0: // Definitions of ios_base's openmode flags. michael@0: const ios_base::openmode ios_base::app; michael@0: const ios_base::openmode ios_base::ate; michael@0: const ios_base::openmode ios_base::binary; michael@0: const ios_base::openmode ios_base::in; michael@0: const ios_base::openmode ios_base::out; michael@0: const ios_base::openmode ios_base::trunc; michael@0: michael@0: // Definitions of ios_base's seekdir flags. michael@0: const ios_base::seekdir ios_base::beg; michael@0: const ios_base::seekdir ios_base::cur; michael@0: const ios_base::seekdir ios_base::end; michael@0: michael@0: #endif michael@0: michael@0: // Internal functions used for managing exponentially-growing arrays of michael@0: // POD types. michael@0: michael@0: // array is a pointer to N elements of type PODType. Expands the array, michael@0: // if necessary, so that array[index] is meaningful. All new elements are michael@0: // initialized to zero. Returns a pointer to the new array, and the new michael@0: // size. michael@0: michael@0: template michael@0: static pair michael@0: _Stl_expand_array(PODType* __array, size_t N, int index) { michael@0: if ((int)N < index + 1) { michael@0: size_t new_N = (max)(2 * N, size_t(index + 1)); michael@0: PODType* new_array michael@0: = __STATIC_CAST(PODType*,realloc(__array, new_N * sizeof(PODType))); michael@0: if (new_array) { michael@0: fill(new_array + N, new_array + new_N, PODType()); michael@0: return pair(new_array, new_N); michael@0: } michael@0: else michael@0: return pair(__STATIC_CAST(PODType*,0), 0); michael@0: } michael@0: else michael@0: return pair(__array, N); michael@0: } michael@0: michael@0: // array is a pointer to N elements of type PODType. Allocate a new michael@0: // array of N elements, copying the values from the old array to the new. michael@0: // Return a pointer to the new array. It is assumed that array is non-null michael@0: // and N is nonzero. michael@0: template michael@0: static PODType* _Stl_copy_array(const PODType* __array, size_t N) { michael@0: PODType* result = __STATIC_CAST(PODType*,malloc(N * sizeof(PODType))); michael@0: if (result) michael@0: copy(__array, __array + N, result); michael@0: return result; michael@0: } michael@0: michael@0: locale ios_base::imbue(const locale& loc) { michael@0: if (loc != _M_locale) { michael@0: locale previous = _M_locale; michael@0: _M_locale = loc; michael@0: _M_invoke_callbacks(imbue_event); michael@0: return previous; michael@0: } michael@0: else { michael@0: _M_invoke_callbacks(imbue_event); michael@0: return _M_locale; michael@0: } michael@0: } michael@0: michael@0: int _STLP_CALL ios_base::xalloc() { michael@0: #if defined (_STLP_THREADS) && \ michael@0: defined (_STLP_WIN32THREADS) && defined (_STLP_NEW_PLATFORM_SDK) michael@0: static volatile __stl_atomic_t _S_index = 0; michael@0: return _STLP_ATOMIC_INCREMENT(&_S_index); michael@0: #else michael@0: static int _S_index = 0; michael@0: static _STLP_STATIC_MUTEX __lock _STLP_MUTEX_INITIALIZER; michael@0: _STLP_auto_lock sentry(__lock); michael@0: return _S_index++; michael@0: #endif michael@0: } michael@0: michael@0: long& ios_base::iword(int index) { michael@0: static long dummy = 0; michael@0: michael@0: pair tmp = _Stl_expand_array(_M_iwords, _M_num_iwords, index); michael@0: if (tmp.first) { // The allocation, if any, succeeded. michael@0: _M_iwords = tmp.first; michael@0: _M_num_iwords = tmp.second; michael@0: return _M_iwords[index]; michael@0: } michael@0: else { michael@0: _M_setstate_nothrow(badbit); michael@0: _M_check_exception_mask(); michael@0: return dummy; michael@0: } michael@0: } michael@0: michael@0: michael@0: void*& ios_base::pword(int index) { michael@0: static void* dummy = 0; michael@0: michael@0: pair tmp = _Stl_expand_array(_M_pwords, _M_num_pwords, index); michael@0: if (tmp.first) { // The allocation, if any, succeeded. michael@0: _M_pwords = tmp.first; michael@0: _M_num_pwords = tmp.second; michael@0: return _M_pwords[index]; michael@0: } michael@0: else { michael@0: _M_setstate_nothrow(badbit); michael@0: _M_check_exception_mask(); michael@0: return dummy; michael@0: } michael@0: } michael@0: michael@0: void ios_base::register_callback(event_callback __fn, int index) { michael@0: pair*, size_t> tmp michael@0: = _Stl_expand_array(_M_callbacks, _M_num_callbacks, (int)_M_callback_index /* fbp: index ??? */ ); michael@0: if (tmp.first) { michael@0: _M_callbacks = tmp.first; michael@0: _M_num_callbacks = tmp.second; michael@0: _M_callbacks[_M_callback_index++] = make_pair(__fn, index); michael@0: } michael@0: else { michael@0: _M_setstate_nothrow(badbit); michael@0: _M_check_exception_mask(); michael@0: } michael@0: } michael@0: michael@0: // Invokes all currently registered callbacks for a particular event. michael@0: // Behaves correctly even if one of the callbacks adds a new callback. michael@0: void ios_base::_M_invoke_callbacks(event E) { michael@0: for (size_t i = _M_callback_index; i > 0; --i) { michael@0: event_callback f = _M_callbacks[i-1].first; michael@0: int n = _M_callbacks[i-1].second; michael@0: f(E, *this, n); michael@0: } michael@0: } michael@0: michael@0: // This function is called if the state, rdstate(), has a bit set michael@0: // that is also set in the exception mask exceptions(). michael@0: void ios_base::_M_throw_failure() { michael@0: const char* arg ; michael@0: # if 0 michael@0: char buffer[256]; michael@0: char* ptr; michael@0: strcpy(buffer, "ios failure: rdstate = 0x"); michael@0: ptr = __write_integer(buffer+strlen(buffer), ios_base::hex, __STATIC_CAST(unsigned long,_M_iostate)); michael@0: strcpy(ptr, " mask = 0x"); michael@0: ptr = __write_integer(buffer+strlen(buffer), ios_base::hex, __STATIC_CAST(unsigned long,_M_exception_mask)); michael@0: *ptr = 0; michael@0: arg = buffer; michael@0: # else michael@0: arg = "ios failure"; michael@0: # endif michael@0: michael@0: # ifndef _STLP_USE_EXCEPTIONS michael@0: fputs(arg, stderr); michael@0: # else michael@0: throw failure(arg); michael@0: # endif michael@0: } michael@0: michael@0: // Copy x's state to *this. This member function is used in the michael@0: // implementation of basic_ios::copyfmt. Does not copy _M_exception_mask michael@0: // or _M_iostate. michael@0: void ios_base::_M_copy_state(const ios_base& x) { michael@0: _M_fmtflags = x._M_fmtflags; // Copy the flags, except for _M_iostate michael@0: _M_openmode = x._M_openmode; // and _M_exception_mask. michael@0: _M_seekdir = x._M_seekdir; michael@0: _M_precision = x._M_precision; michael@0: _M_width = x._M_width; michael@0: _M_locale = x._M_locale; michael@0: michael@0: if (x._M_callbacks) { michael@0: pair* tmp = _Stl_copy_array(x._M_callbacks, x._M_callback_index); michael@0: if (tmp) { michael@0: free(_M_callbacks); michael@0: _M_callbacks = tmp; michael@0: _M_num_callbacks = _M_callback_index = x._M_callback_index; michael@0: } michael@0: else { michael@0: _M_setstate_nothrow(badbit); michael@0: _M_check_exception_mask(); michael@0: } michael@0: } michael@0: michael@0: if (x._M_iwords) { michael@0: long* tmp = _Stl_copy_array(x._M_iwords, x._M_num_iwords); michael@0: if (tmp) { michael@0: free(_M_iwords); michael@0: _M_iwords = tmp; michael@0: _M_num_iwords = x._M_num_iwords; michael@0: } michael@0: else { michael@0: _M_setstate_nothrow(badbit); michael@0: _M_check_exception_mask(); michael@0: } michael@0: } michael@0: michael@0: if (x._M_pwords) { michael@0: void** tmp = _Stl_copy_array(x._M_pwords, x._M_num_pwords); michael@0: if (tmp) { michael@0: free(_M_pwords); michael@0: _M_pwords = tmp; michael@0: _M_num_pwords = x._M_num_pwords; michael@0: } michael@0: else { michael@0: _M_setstate_nothrow(badbit); michael@0: _M_check_exception_mask(); michael@0: } michael@0: } michael@0: } michael@0: michael@0: // ios's (protected) default constructor. The standard says that all michael@0: // fields have indeterminate values; we initialize them to zero for michael@0: // simplicity. The only thing that really matters is that the arrays michael@0: // are all initially null pointers, and the array element counts are all michael@0: // initially zero. michael@0: ios_base::ios_base() michael@0: : _M_fmtflags(0), _M_iostate(0), _M_openmode(0), _M_seekdir(0), michael@0: _M_exception_mask(0), michael@0: _M_precision(0), _M_width(0), michael@0: _M_locale(), michael@0: _M_callbacks(0), _M_num_callbacks(0), _M_callback_index(0), michael@0: _M_iwords(0), _M_num_iwords(0), michael@0: _M_pwords(0), michael@0: _M_num_pwords(0) michael@0: {} michael@0: michael@0: // ios's destructor. michael@0: ios_base::~ios_base() { michael@0: _M_invoke_callbacks(erase_event); michael@0: free(_M_callbacks); michael@0: free(_M_iwords); michael@0: free(_M_pwords); michael@0: } michael@0: michael@0: //---------------------------------------------------------------------- michael@0: // Force instantiation of basic_ios michael@0: // For DLL exports, they are already instantiated. michael@0: #if !defined(_STLP_NO_FORCE_INSTANTIATE) michael@0: template class _STLP_CLASS_DECLSPEC basic_ios >; michael@0: # if !defined (_STLP_NO_WCHAR_T) michael@0: template class _STLP_CLASS_DECLSPEC basic_ios >; michael@0: # endif /* _STLP_NO_WCHAR_T */ michael@0: #endif michael@0: michael@0: _STLP_END_NAMESPACE michael@0: michael@0: // Local Variables: michael@0: // mode:C++ michael@0: // End: