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
failure(const string & s)37 ios_base::failure::failure(const string& s)
38 : __Named_exception(s)
39 {}
40
~failure()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>
_Stl_expand_array(PODType * __array,size_t N,int index)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>
_Stl_copy_array(const PODType * __array,size_t N)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
imbue(const locale & loc)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
xalloc()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
iword(int index)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
pword(int index)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
register_callback(event_callback __fn,int index)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.
_M_invoke_callbacks(event E)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().
_M_throw_failure()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.
_M_copy_state(const ios_base & x)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.
ios_base()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.
~ios_base()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