xref: /reactos/sdk/lib/3rdparty/stlport/src/ios.cpp (revision c2c66aff)
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 
failure(const string & s)36 ios_base::failure::failure(const string& s)
37   : __Named_exception(s)
38 {}
39 
~failure()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>
_Stl_expand_array(PODType * __array,size_t N,int index)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>
_Stl_copy_array(const PODType * __array,size_t N)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 
imbue(const locale & loc)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 
xalloc()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 
iword(int index)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 
pword(int index)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 
register_callback(event_callback __fn,int index)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.
_M_invoke_callbacks(event E)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().
_M_throw_failure()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.
_M_copy_state(const ios_base & x)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.
ios_base()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.
~ios_base()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