|
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 |
|
37 ios_base::failure::failure(const string& s) |
|
38 : __Named_exception(s) |
|
39 {} |
|
40 |
|
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> |
|
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> |
|
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 |
|
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 |
|
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 |
|
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 |
|
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 |
|
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. |
|
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(). |
|
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. |
|
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. |
|
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. |
|
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: |