1 | // Iostreams base classes -*- C++ -*-
|
---|
2 |
|
---|
3 | // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
|
---|
4 | // Free Software Foundation, Inc.
|
---|
5 | //
|
---|
6 | // This file is part of the GNU ISO C++ Library. This library is free
|
---|
7 | // software; you can redistribute it and/or modify it under the
|
---|
8 | // terms of the GNU General Public License as published by the
|
---|
9 | // Free Software Foundation; either version 2, or (at your option)
|
---|
10 | // any later version.
|
---|
11 |
|
---|
12 | // This library is distributed in the hope that it will be useful,
|
---|
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
15 | // GNU General Public License for more details.
|
---|
16 |
|
---|
17 | // You should have received a copy of the GNU General Public License along
|
---|
18 | // with this library; see the file COPYING. If not, write to the Free
|
---|
19 | // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
---|
20 | // USA.
|
---|
21 |
|
---|
22 | // As a special exception, you may use this file as part of a free software
|
---|
23 | // library without restriction. Specifically, if other files instantiate
|
---|
24 | // templates or use macros or inline functions from this file, or you compile
|
---|
25 | // this file and link it with other files to produce an executable, this
|
---|
26 | // file does not by itself cause the resulting executable to be covered by
|
---|
27 | // the GNU General Public License. This exception does not however
|
---|
28 | // invalidate any other reasons why the executable file might be covered by
|
---|
29 | // the GNU General Public License.
|
---|
30 |
|
---|
31 | //
|
---|
32 | // ISO C++ 14882: 27.4 Iostreams base classes
|
---|
33 | //
|
---|
34 |
|
---|
35 | #include <ios>
|
---|
36 | #include <ostream>
|
---|
37 | #include <istream>
|
---|
38 | #include <fstream>
|
---|
39 | #include <bits/atomicity.h>
|
---|
40 | #include <ext/stdio_filebuf.h>
|
---|
41 | #ifdef _GLIBCPP_HAVE_UNISTD_H
|
---|
42 | #include <unistd.h>
|
---|
43 | #endif
|
---|
44 |
|
---|
45 | namespace __gnu_cxx
|
---|
46 | {
|
---|
47 | // Extern declarations for global objects in src/globals.cc.
|
---|
48 | extern stdio_filebuf<char> buf_cout;
|
---|
49 | extern stdio_filebuf<char> buf_cin;
|
---|
50 | extern stdio_filebuf<char> buf_cerr;
|
---|
51 |
|
---|
52 | #ifdef _GLIBCPP_USE_WCHAR_T
|
---|
53 | extern stdio_filebuf<wchar_t> buf_wcout;
|
---|
54 | extern stdio_filebuf<wchar_t> buf_wcin;
|
---|
55 | extern stdio_filebuf<wchar_t> buf_wcerr;
|
---|
56 | #endif
|
---|
57 | } // namespace __gnu_cxx
|
---|
58 |
|
---|
59 | namespace std
|
---|
60 | {
|
---|
61 | using namespace __gnu_cxx;
|
---|
62 |
|
---|
63 | extern istream cin;
|
---|
64 | extern ostream cout;
|
---|
65 | extern ostream cerr;
|
---|
66 | extern ostream clog;
|
---|
67 |
|
---|
68 | #ifdef _GLIBCPP_USE_WCHAR_T
|
---|
69 | extern wistream wcin;
|
---|
70 | extern wostream wcout;
|
---|
71 | extern wostream wcerr;
|
---|
72 | extern wostream wclog;
|
---|
73 | #endif
|
---|
74 |
|
---|
75 | // Definitions for static const data members of __ios_flags.
|
---|
76 | const __ios_flags::__int_type __ios_flags::_S_boolalpha;
|
---|
77 | const __ios_flags::__int_type __ios_flags::_S_dec;
|
---|
78 | const __ios_flags::__int_type __ios_flags::_S_fixed;
|
---|
79 | const __ios_flags::__int_type __ios_flags::_S_hex;
|
---|
80 | const __ios_flags::__int_type __ios_flags::_S_internal;
|
---|
81 | const __ios_flags::__int_type __ios_flags::_S_left;
|
---|
82 | const __ios_flags::__int_type __ios_flags::_S_oct;
|
---|
83 | const __ios_flags::__int_type __ios_flags::_S_right;
|
---|
84 | const __ios_flags::__int_type __ios_flags::_S_scientific;
|
---|
85 | const __ios_flags::__int_type __ios_flags::_S_showbase;
|
---|
86 | const __ios_flags::__int_type __ios_flags::_S_showpoint;
|
---|
87 | const __ios_flags::__int_type __ios_flags::_S_showpos;
|
---|
88 | const __ios_flags::__int_type __ios_flags::_S_skipws;
|
---|
89 | const __ios_flags::__int_type __ios_flags::_S_unitbuf;
|
---|
90 | const __ios_flags::__int_type __ios_flags::_S_uppercase;
|
---|
91 | const __ios_flags::__int_type __ios_flags::_S_adjustfield;
|
---|
92 | const __ios_flags::__int_type __ios_flags::_S_basefield;
|
---|
93 | const __ios_flags::__int_type __ios_flags::_S_floatfield;
|
---|
94 |
|
---|
95 | const __ios_flags::__int_type __ios_flags::_S_badbit;
|
---|
96 | const __ios_flags::__int_type __ios_flags::_S_eofbit;
|
---|
97 | const __ios_flags::__int_type __ios_flags::_S_failbit;
|
---|
98 |
|
---|
99 | const __ios_flags::__int_type __ios_flags::_S_app;
|
---|
100 | const __ios_flags::__int_type __ios_flags::_S_ate;
|
---|
101 | const __ios_flags::__int_type __ios_flags::_S_bin;
|
---|
102 | const __ios_flags::__int_type __ios_flags::_S_in;
|
---|
103 | const __ios_flags::__int_type __ios_flags::_S_out;
|
---|
104 | const __ios_flags::__int_type __ios_flags::_S_trunc;
|
---|
105 |
|
---|
106 | // Definitions for static const members of ios_base.
|
---|
107 | const ios_base::fmtflags ios_base::boolalpha;
|
---|
108 | const ios_base::fmtflags ios_base::dec;
|
---|
109 | const ios_base::fmtflags ios_base::fixed;
|
---|
110 | const ios_base::fmtflags ios_base::hex;
|
---|
111 | const ios_base::fmtflags ios_base::internal;
|
---|
112 | const ios_base::fmtflags ios_base::left;
|
---|
113 | const ios_base::fmtflags ios_base::oct;
|
---|
114 | const ios_base::fmtflags ios_base::right;
|
---|
115 | const ios_base::fmtflags ios_base::scientific;
|
---|
116 | const ios_base::fmtflags ios_base::showbase;
|
---|
117 | const ios_base::fmtflags ios_base::showpoint;
|
---|
118 | const ios_base::fmtflags ios_base::showpos;
|
---|
119 | const ios_base::fmtflags ios_base::skipws;
|
---|
120 | const ios_base::fmtflags ios_base::unitbuf;
|
---|
121 | const ios_base::fmtflags ios_base::uppercase;
|
---|
122 | const ios_base::fmtflags ios_base::adjustfield;
|
---|
123 | const ios_base::fmtflags ios_base::basefield;
|
---|
124 | const ios_base::fmtflags ios_base::floatfield;
|
---|
125 |
|
---|
126 | const ios_base::iostate ios_base::badbit;
|
---|
127 | const ios_base::iostate ios_base::eofbit;
|
---|
128 | const ios_base::iostate ios_base::failbit;
|
---|
129 | const ios_base::iostate ios_base::goodbit;
|
---|
130 |
|
---|
131 | const ios_base::openmode ios_base::app;
|
---|
132 | const ios_base::openmode ios_base::ate;
|
---|
133 | const ios_base::openmode ios_base::binary;
|
---|
134 | const ios_base::openmode ios_base::in;
|
---|
135 | const ios_base::openmode ios_base::out;
|
---|
136 | const ios_base::openmode ios_base::trunc;
|
---|
137 |
|
---|
138 | const ios_base::seekdir ios_base::beg;
|
---|
139 | const ios_base::seekdir ios_base::cur;
|
---|
140 | const ios_base::seekdir ios_base::end;
|
---|
141 |
|
---|
142 | const int ios_base::_S_local_word_size;
|
---|
143 | int ios_base::Init::_S_ios_base_init = 0;
|
---|
144 | bool ios_base::Init::_S_synced_with_stdio = true;
|
---|
145 |
|
---|
146 | ios_base::failure::failure(const string& __str) throw()
|
---|
147 | {
|
---|
148 | strncpy(_M_name, __str.c_str(), _M_bufsize);
|
---|
149 | _M_name[_M_bufsize - 1] = '\0';
|
---|
150 | }
|
---|
151 |
|
---|
152 | ios_base::failure::~failure() throw()
|
---|
153 | { }
|
---|
154 |
|
---|
155 | const char*
|
---|
156 | ios_base::failure::what() const throw()
|
---|
157 | { return _M_name; }
|
---|
158 |
|
---|
159 | void
|
---|
160 | ios_base::Init::_S_ios_create(bool __sync)
|
---|
161 | {
|
---|
162 | size_t __out_size = __sync ? 0 : static_cast<size_t>(BUFSIZ);
|
---|
163 | #ifdef _GLIBCPP_HAVE_ISATTY
|
---|
164 | size_t __in_size =
|
---|
165 | (__sync || isatty (0)) ? 1 : static_cast<size_t>(BUFSIZ);
|
---|
166 | #else
|
---|
167 | size_t __in_size = 1;
|
---|
168 | #endif
|
---|
169 |
|
---|
170 | // NB: The file globals.cc creates the four standard files
|
---|
171 | // with NULL buffers. At this point, we swap out the dummy NULL
|
---|
172 | // [io]stream objects and buffers with the real deal.
|
---|
173 | new (&buf_cout) stdio_filebuf<char>(stdout, ios_base::out, __out_size);
|
---|
174 | new (&buf_cin) stdio_filebuf<char>(stdin, ios_base::in, __in_size);
|
---|
175 | new (&buf_cerr) stdio_filebuf<char>(stderr, ios_base::out, __out_size);
|
---|
176 |
|
---|
177 | new (&cout) ostream(&buf_cout);
|
---|
178 | new (&cin) istream(&buf_cin);
|
---|
179 | new (&cerr) ostream(&buf_cerr);
|
---|
180 | new (&clog) ostream(&buf_cerr);
|
---|
181 | cout.init(&buf_cout);
|
---|
182 | cin.init(&buf_cin);
|
---|
183 | cerr.init(&buf_cerr);
|
---|
184 | clog.init(&buf_cerr);
|
---|
185 | cin.tie(&cout);
|
---|
186 | cerr.flags(ios_base::unitbuf);
|
---|
187 |
|
---|
188 | #ifdef _GLIBCPP_USE_WCHAR_T
|
---|
189 | new (&buf_wcout) stdio_filebuf<wchar_t>(stdout, ios_base::out, __out_size);
|
---|
190 | new (&buf_wcin) stdio_filebuf<wchar_t>(stdin, ios_base::in, __in_size);
|
---|
191 | new (&buf_wcerr) stdio_filebuf<wchar_t>(stderr, ios_base::out, __out_size);
|
---|
192 | new (&wcout) wostream(&buf_wcout);
|
---|
193 | new (&wcin) wistream(&buf_wcin);
|
---|
194 | new (&wcerr) wostream(&buf_wcerr);
|
---|
195 | new (&wclog) wostream(&buf_wcerr);
|
---|
196 | wcout.init(&buf_wcout);
|
---|
197 | wcin.init(&buf_wcin);
|
---|
198 | wcerr.init(&buf_wcerr);
|
---|
199 | wclog.init(&buf_wcerr);
|
---|
200 | wcin.tie(&wcout);
|
---|
201 | wcerr.flags(ios_base::unitbuf);
|
---|
202 | #endif
|
---|
203 | }
|
---|
204 |
|
---|
205 | void
|
---|
206 | ios_base::Init::_S_ios_destroy()
|
---|
207 | {
|
---|
208 | // Explicitly call dtors to free any memory that is dynamically
|
---|
209 | // allocated by filebuf ctor or member functions, but don't
|
---|
210 | // deallocate all memory by calling operator delete.
|
---|
211 | buf_cout.~stdio_filebuf();
|
---|
212 | buf_cin.~stdio_filebuf();
|
---|
213 | buf_cerr.~stdio_filebuf();
|
---|
214 |
|
---|
215 | #ifdef _GLIBCPP_USE_WCHAR_T
|
---|
216 | buf_wcout.~stdio_filebuf();
|
---|
217 | buf_wcin.~stdio_filebuf();
|
---|
218 | buf_wcerr.~stdio_filebuf();
|
---|
219 | #endif
|
---|
220 | }
|
---|
221 |
|
---|
222 | ios_base::Init::Init()
|
---|
223 | {
|
---|
224 | if (_S_ios_base_init == 0)
|
---|
225 | {
|
---|
226 | // Standard streams default to synced with "C" operations.
|
---|
227 | ios_base::Init::_S_synced_with_stdio = true;
|
---|
228 | _S_ios_create(ios_base::Init::_S_synced_with_stdio);
|
---|
229 | }
|
---|
230 | ++_S_ios_base_init;
|
---|
231 | }
|
---|
232 |
|
---|
233 | ios_base::Init::~Init()
|
---|
234 | {
|
---|
235 | if (--_S_ios_base_init == 0)
|
---|
236 | _S_ios_destroy();
|
---|
237 | }
|
---|
238 |
|
---|
239 | // 27.4.2.5 ios_base storage functions
|
---|
240 | int
|
---|
241 | ios_base::xalloc() throw()
|
---|
242 | {
|
---|
243 | // Implementation note: Initialize top to zero to ensure that
|
---|
244 | // initialization occurs before main() is started.
|
---|
245 | static _Atomic_word _S_top = 0;
|
---|
246 | return __exchange_and_add(&_S_top, 1) + 4;
|
---|
247 | }
|
---|
248 |
|
---|
249 | // 27.4.2.5 iword/pword storage
|
---|
250 | ios_base::_Words&
|
---|
251 | ios_base::_M_grow_words(int ix)
|
---|
252 | {
|
---|
253 | // Precondition: _M_word_size <= ix
|
---|
254 | int newsize = _S_local_word_size;
|
---|
255 | _Words* words = _M_local_word;
|
---|
256 | if (ix > _S_local_word_size - 1)
|
---|
257 | {
|
---|
258 | if (ix < numeric_limits<int>::max())
|
---|
259 | {
|
---|
260 | newsize = ix + 1;
|
---|
261 | try
|
---|
262 | { words = new _Words[newsize]; }
|
---|
263 | catch (...)
|
---|
264 | {
|
---|
265 | _M_streambuf_state |= badbit;
|
---|
266 | if (_M_streambuf_state & _M_exception)
|
---|
267 | __throw_ios_failure("ios_base::_M_grow_words failure");
|
---|
268 | return _M_word_zero;
|
---|
269 | }
|
---|
270 | for (int i = 0; i < _M_word_size; i++)
|
---|
271 | words[i] = _M_word[i];
|
---|
272 | if (_M_word && _M_word != _M_local_word)
|
---|
273 | {
|
---|
274 | delete [] _M_word;
|
---|
275 | _M_word = 0;
|
---|
276 | }
|
---|
277 | }
|
---|
278 | else
|
---|
279 | {
|
---|
280 | _M_streambuf_state |= badbit;
|
---|
281 | if (_M_streambuf_state & _M_exception)
|
---|
282 | __throw_ios_failure("ios_base::_M_grow_words failure");
|
---|
283 | return _M_word_zero;
|
---|
284 | }
|
---|
285 | }
|
---|
286 | _M_word = words;
|
---|
287 | _M_word_size = newsize;
|
---|
288 | return _M_word[ix];
|
---|
289 | }
|
---|
290 |
|
---|
291 | // Called only by basic_ios<>::init.
|
---|
292 | void
|
---|
293 | ios_base::_M_init()
|
---|
294 | {
|
---|
295 | // NB: May be called more than once
|
---|
296 | _M_precision = 6;
|
---|
297 | _M_width = 0;
|
---|
298 | _M_flags = skipws | dec;
|
---|
299 | _M_ios_locale = locale();
|
---|
300 | }
|
---|
301 |
|
---|
302 | // 27.4.2.3 ios_base locale functions
|
---|
303 | locale
|
---|
304 | ios_base::imbue(const locale& __loc)
|
---|
305 | {
|
---|
306 | locale __old = _M_ios_locale;
|
---|
307 | _M_ios_locale = __loc;
|
---|
308 | _M_call_callbacks(imbue_event);
|
---|
309 | return __old;
|
---|
310 | }
|
---|
311 |
|
---|
312 | ios_base::ios_base() : _M_callbacks(0), _M_word_size(_S_local_word_size),
|
---|
313 | _M_word(_M_local_word)
|
---|
314 | {
|
---|
315 | // Do nothing: basic_ios::init() does it.
|
---|
316 | // NB: _M_callbacks and _M_word must be zero for non-initialized
|
---|
317 | // ios_base to go through ~ios_base gracefully.
|
---|
318 | }
|
---|
319 |
|
---|
320 | // 27.4.2.7 ios_base constructors/destructors
|
---|
321 | ios_base::~ios_base()
|
---|
322 | {
|
---|
323 | _M_call_callbacks(erase_event);
|
---|
324 | _M_dispose_callbacks();
|
---|
325 | if (_M_word != _M_local_word)
|
---|
326 | {
|
---|
327 | delete [] _M_word;
|
---|
328 | _M_word = 0;
|
---|
329 | }
|
---|
330 | }
|
---|
331 |
|
---|
332 | void
|
---|
333 | ios_base::register_callback(event_callback __fn, int __index)
|
---|
334 | { _M_callbacks = new _Callback_list(__fn, __index, _M_callbacks); }
|
---|
335 |
|
---|
336 | void
|
---|
337 | ios_base::_M_call_callbacks(event __e) throw()
|
---|
338 | {
|
---|
339 | _Callback_list* __p = _M_callbacks;
|
---|
340 | while (__p)
|
---|
341 | {
|
---|
342 | try
|
---|
343 | { (*__p->_M_fn) (__e, *this, __p->_M_index); }
|
---|
344 | catch (...)
|
---|
345 | { }
|
---|
346 | __p = __p->_M_next;
|
---|
347 | }
|
---|
348 | }
|
---|
349 |
|
---|
350 | void
|
---|
351 | ios_base::_M_dispose_callbacks(void)
|
---|
352 | {
|
---|
353 | _Callback_list* __p = _M_callbacks;
|
---|
354 | while (__p && __p->_M_remove_reference() == 0)
|
---|
355 | {
|
---|
356 | _Callback_list* __next = __p->_M_next;
|
---|
357 | delete __p;
|
---|
358 | __p = __next;
|
---|
359 | }
|
---|
360 | _M_callbacks = 0;
|
---|
361 | }
|
---|
362 |
|
---|
363 | bool
|
---|
364 | ios_base::sync_with_stdio(bool __sync)
|
---|
365 | {
|
---|
366 | #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
|
---|
367 | // 49. Underspecification of ios_base::sync_with_stdio
|
---|
368 | bool __ret = ios_base::Init::_S_synced_with_stdio;
|
---|
369 | #endif
|
---|
370 |
|
---|
371 | // Turn off sync with C FILE* for cin, cout, cerr, clog iff
|
---|
372 | // currently synchronized.
|
---|
373 | if (!__sync && __ret)
|
---|
374 | {
|
---|
375 | ios_base::Init::_S_synced_with_stdio = false;
|
---|
376 | ios_base::Init::_S_ios_destroy();
|
---|
377 | ios_base::Init::_S_ios_create(ios_base::Init::_S_synced_with_stdio);
|
---|
378 | }
|
---|
379 | return __ret;
|
---|
380 | }
|
---|
381 | } // namespace std
|
---|