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