1 | // Iostreams base classes -*- C++ -*- |
2 | |
3 | // Copyright (C) 1997-2024 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file bits/basic_ios.h |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{ios} |
28 | */ |
29 | |
30 | #ifndef _BASIC_IOS_H |
31 | #define _BASIC_IOS_H 1 |
32 | |
33 | #pragma GCC system_header |
34 | |
35 | #include <bits/localefwd.h> |
36 | #include <bits/locale_classes.h> |
37 | #include <bits/locale_facets.h> |
38 | #include <bits/streambuf_iterator.h> |
39 | #include <bits/move.h> |
40 | |
41 | namespace std _GLIBCXX_VISIBILITY(default) |
42 | { |
43 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
44 | |
45 | template<typename _Facet> |
46 | inline const _Facet& |
47 | __check_facet(const _Facet* __f) |
48 | { |
49 | if (!__f) |
50 | __throw_bad_cast(); |
51 | return *__f; |
52 | } |
53 | |
54 | /** |
55 | * @brief Template class basic_ios, virtual base class for all |
56 | * stream classes. |
57 | * @ingroup io |
58 | * |
59 | * @tparam _CharT Type of character stream. |
60 | * @tparam _Traits Traits for character type, defaults to |
61 | * char_traits<_CharT>. |
62 | * |
63 | * Most of the member functions called dispatched on stream objects |
64 | * (e.g., @c std::cout.foo(bar);) are consolidated in this class. |
65 | */ |
66 | template<typename _CharT, typename _Traits> |
67 | class basic_ios : public ios_base |
68 | { |
69 | #if __cplusplus >= 202002L |
70 | static_assert(is_same_v<_CharT, typename _Traits::char_type>); |
71 | #endif |
72 | |
73 | public: |
74 | ///@{ |
75 | /** |
76 | * These are standard types. They permit a standardized way of |
77 | * referring to names of (or names dependent on) the template |
78 | * parameters, which are specific to the implementation. |
79 | */ |
80 | typedef _CharT char_type; |
81 | typedef typename _Traits::int_type int_type; |
82 | typedef typename _Traits::pos_type pos_type; |
83 | typedef typename _Traits::off_type off_type; |
84 | typedef _Traits traits_type; |
85 | ///@} |
86 | |
87 | ///@{ |
88 | /** |
89 | * These are non-standard types. |
90 | */ |
91 | typedef ctype<_CharT> __ctype_type; |
92 | typedef num_put<_CharT, ostreambuf_iterator<_CharT, _Traits> > |
93 | __num_put_type; |
94 | typedef num_get<_CharT, istreambuf_iterator<_CharT, _Traits> > |
95 | __num_get_type; |
96 | ///@} |
97 | |
98 | // Data members: |
99 | protected: |
100 | basic_ostream<_CharT, _Traits>* _M_tie; |
101 | mutable char_type _M_fill; |
102 | mutable bool _M_fill_init; |
103 | basic_streambuf<_CharT, _Traits>* _M_streambuf; |
104 | |
105 | // Cached use_facet<ctype>, which is based on the current locale info. |
106 | const __ctype_type* _M_ctype; |
107 | // For ostream. |
108 | const __num_put_type* _M_num_put; |
109 | // For istream. |
110 | const __num_get_type* _M_num_get; |
111 | |
112 | public: |
113 | ///@{ |
114 | /** |
115 | * @brief The quick-and-easy status check. |
116 | * |
117 | * This allows you to write constructs such as |
118 | * <code>if (!a_stream) ...</code> and <code>while (a_stream) ...</code> |
119 | */ |
120 | #if __cplusplus >= 201103L |
121 | explicit operator bool() const |
122 | { return !this->fail(); } |
123 | #else |
124 | operator void*() const |
125 | { return this->fail() ? 0 : const_cast<basic_ios*>(this); } |
126 | #endif |
127 | |
128 | bool |
129 | operator!() const |
130 | { return this->fail(); } |
131 | ///@} |
132 | |
133 | /** |
134 | * @brief Returns the error state of the stream buffer. |
135 | * @return A bit pattern (well, isn't everything?) |
136 | * |
137 | * See std::ios_base::iostate for the possible bit values. Most |
138 | * users will call one of the interpreting wrappers, e.g., good(). |
139 | */ |
140 | iostate |
141 | rdstate() const |
142 | { return _M_streambuf_state; } |
143 | |
144 | /** |
145 | * @brief [Re]sets the error state. |
146 | * @param __state The new state flag(s) to set. |
147 | * |
148 | * See std::ios_base::iostate for the possible bit values. Most |
149 | * users will not need to pass an argument. |
150 | */ |
151 | void |
152 | clear(iostate __state = goodbit); |
153 | |
154 | /** |
155 | * @brief Sets additional flags in the error state. |
156 | * @param __state The additional state flag(s) to set. |
157 | * |
158 | * See std::ios_base::iostate for the possible bit values. |
159 | */ |
160 | void |
161 | setstate(iostate __state) |
162 | { this->clear(this->rdstate() | __state); } |
163 | |
164 | // Flips the internal state on for the proper state bits, then |
165 | // rethrows the propagated exception if bit also set in |
166 | // exceptions(). Must only be called within a catch handler. |
167 | void |
168 | _M_setstate(iostate __state) |
169 | { |
170 | // 27.6.1.2.1 Common requirements. |
171 | // Turn this on without causing an ios::failure to be thrown. |
172 | _M_streambuf_state |= __state; |
173 | if (this->exceptions() & __state) |
174 | __throw_exception_again; |
175 | } |
176 | |
177 | /** |
178 | * @brief Fast error checking. |
179 | * @return True if no error flags are set. |
180 | * |
181 | * A wrapper around rdstate. |
182 | */ |
183 | bool |
184 | good() const |
185 | { return this->rdstate() == 0; } |
186 | |
187 | /** |
188 | * @brief Fast error checking. |
189 | * @return True if the eofbit is set. |
190 | * |
191 | * Note that other iostate flags may also be set. |
192 | */ |
193 | bool |
194 | eof() const |
195 | { return (this->rdstate() & eofbit) != 0; } |
196 | |
197 | /** |
198 | * @brief Fast error checking. |
199 | * @return True if either the badbit or the failbit is set. |
200 | * |
201 | * Checking the badbit in fail() is historical practice. |
202 | * Note that other iostate flags may also be set. |
203 | */ |
204 | bool |
205 | fail() const |
206 | { return (this->rdstate() & (badbit | failbit)) != 0; } |
207 | |
208 | /** |
209 | * @brief Fast error checking. |
210 | * @return True if the badbit is set. |
211 | * |
212 | * Note that other iostate flags may also be set. |
213 | */ |
214 | bool |
215 | bad() const |
216 | { return (this->rdstate() & badbit) != 0; } |
217 | |
218 | /** |
219 | * @brief Throwing exceptions on errors. |
220 | * @return The current exceptions mask. |
221 | * |
222 | * This changes nothing in the stream. See the one-argument version |
223 | * of exceptions(iostate) for the meaning of the return value. |
224 | */ |
225 | iostate |
226 | exceptions() const |
227 | { return _M_exception; } |
228 | |
229 | /** |
230 | * @brief Throwing exceptions on errors. |
231 | * @param __except The new exceptions mask. |
232 | * |
233 | * By default, error flags are set silently. You can set an |
234 | * exceptions mask for each stream; if a bit in the mask becomes set |
235 | * in the error flags, then an exception of type |
236 | * std::ios_base::failure is thrown. |
237 | * |
238 | * If the error flag is already set when the exceptions mask is |
239 | * added, the exception is immediately thrown. Try running the |
240 | * following under GCC 3.1 or later: |
241 | * @code |
242 | * #include <iostream> |
243 | * #include <fstream> |
244 | * #include <exception> |
245 | * |
246 | * int main() |
247 | * { |
248 | * std::set_terminate (__gnu_cxx::__verbose_terminate_handler); |
249 | * |
250 | * std::ifstream f ("/etc/motd"); |
251 | * |
252 | * std::cerr << "Setting badbit\n"; |
253 | * f.setstate (std::ios_base::badbit); |
254 | * |
255 | * std::cerr << "Setting exception mask\n"; |
256 | * f.exceptions (std::ios_base::badbit); |
257 | * } |
258 | * @endcode |
259 | */ |
260 | void |
261 | exceptions(iostate __except) |
262 | { |
263 | _M_exception = __except; |
264 | this->clear(_M_streambuf_state); |
265 | } |
266 | |
267 | // Constructor/destructor: |
268 | /** |
269 | * @brief Constructor performs initialization. |
270 | * |
271 | * The parameter is passed by derived streams. |
272 | */ |
273 | explicit |
274 | basic_ios(basic_streambuf<_CharT, _Traits>* __sb) |
275 | : ios_base(), _M_tie(0), _M_fill(), _M_fill_init(false), _M_streambuf(0), |
276 | _M_ctype(0), _M_num_put(0), _M_num_get(0) |
277 | { this->init(__sb); } |
278 | |
279 | /** |
280 | * @brief Empty. |
281 | * |
282 | * The destructor does nothing. More specifically, it does not |
283 | * destroy the streambuf held by rdbuf(). |
284 | */ |
285 | virtual |
286 | ~basic_ios() { } |
287 | |
288 | // Members: |
289 | /** |
290 | * @brief Fetches the current @e tied stream. |
291 | * @return A pointer to the tied stream, or NULL if the stream is |
292 | * not tied. |
293 | * |
294 | * A stream may be @e tied (or synchronized) to a second output |
295 | * stream. When this stream performs any I/O, the tied stream is |
296 | * first flushed. For example, @c std::cin is tied to @c std::cout. |
297 | */ |
298 | basic_ostream<_CharT, _Traits>* |
299 | tie() const |
300 | { return _M_tie; } |
301 | |
302 | /** |
303 | * @brief Ties this stream to an output stream. |
304 | * @param __tiestr The output stream. |
305 | * @return The previously tied output stream, or NULL if the stream |
306 | * was not tied. |
307 | * |
308 | * This sets up a new tie; see tie() for more. |
309 | */ |
310 | basic_ostream<_CharT, _Traits>* |
311 | tie(basic_ostream<_CharT, _Traits>* __tiestr) |
312 | { |
313 | basic_ostream<_CharT, _Traits>* __old = _M_tie; |
314 | _M_tie = __tiestr; |
315 | return __old; |
316 | } |
317 | |
318 | /** |
319 | * @brief Accessing the underlying buffer. |
320 | * @return The current stream buffer. |
321 | * |
322 | * This does not change the state of the stream. |
323 | */ |
324 | basic_streambuf<_CharT, _Traits>* |
325 | rdbuf() const |
326 | { return _M_streambuf; } |
327 | |
328 | /** |
329 | * @brief Changing the underlying buffer. |
330 | * @param __sb The new stream buffer. |
331 | * @return The previous stream buffer. |
332 | * |
333 | * Associates a new buffer with the current stream, and clears the |
334 | * error state. |
335 | * |
336 | * Due to historical accidents which the LWG refuses to correct, the |
337 | * I/O library suffers from a design error: this function is hidden |
338 | * in derived classes by overrides of the zero-argument @c rdbuf(), |
339 | * which is non-virtual for hysterical raisins. As a result, you |
340 | * must use explicit qualifications to access this function via any |
341 | * derived class. For example: |
342 | * |
343 | * @code |
344 | * std::fstream foo; // or some other derived type |
345 | * std::streambuf* p = .....; |
346 | * |
347 | * foo.ios::rdbuf(p); // ios == basic_ios<char> |
348 | * @endcode |
349 | */ |
350 | basic_streambuf<_CharT, _Traits>* |
351 | rdbuf(basic_streambuf<_CharT, _Traits>* __sb); |
352 | |
353 | /** |
354 | * @brief Copies fields of __rhs into this. |
355 | * @param __rhs The source values for the copies. |
356 | * @return Reference to this object. |
357 | * |
358 | * All fields of __rhs are copied into this object except that rdbuf() |
359 | * and rdstate() remain unchanged. All values in the pword and iword |
360 | * arrays are copied. Before copying, each callback is invoked with |
361 | * erase_event. After copying, each (new) callback is invoked with |
362 | * copyfmt_event. The final step is to copy exceptions(). |
363 | */ |
364 | basic_ios& |
365 | copyfmt(const basic_ios& __rhs); |
366 | |
367 | /** |
368 | * @brief Retrieves the @a empty character. |
369 | * @return The current fill character. |
370 | * |
371 | * It defaults to a space (' ') in the current locale. |
372 | */ |
373 | char_type |
374 | fill() const |
375 | { |
376 | if (!_M_fill_init) |
377 | { |
378 | _M_fill = this->widen(' '); |
379 | _M_fill_init = true; |
380 | } |
381 | return _M_fill; |
382 | } |
383 | |
384 | /** |
385 | * @brief Sets a new @a empty character. |
386 | * @param __ch The new character. |
387 | * @return The previous fill character. |
388 | * |
389 | * The fill character is used to fill out space when P+ characters |
390 | * have been requested (e.g., via setw), Q characters are actually |
391 | * used, and Q<P. It defaults to a space (' ') in the current locale. |
392 | */ |
393 | char_type |
394 | fill(char_type __ch) |
395 | { |
396 | char_type __old = this->fill(); |
397 | _M_fill = __ch; |
398 | return __old; |
399 | } |
400 | |
401 | // Locales: |
402 | /** |
403 | * @brief Moves to a new locale. |
404 | * @param __loc The new locale. |
405 | * @return The previous locale. |
406 | * |
407 | * Calls @c ios_base::imbue(loc), and if a stream buffer is associated |
408 | * with this stream, calls that buffer's @c pubimbue(loc). |
409 | * |
410 | * Additional l10n notes are at |
411 | * http://gcc.gnu.org/onlinedocs/libstdc++/manual/localization.html |
412 | */ |
413 | locale |
414 | imbue(const locale& __loc); |
415 | |
416 | /** |
417 | * @brief Squeezes characters. |
418 | * @param __c The character to narrow. |
419 | * @param __dfault The character to narrow. |
420 | * @return The narrowed character. |
421 | * |
422 | * Maps a character of @c char_type to a character of @c char, |
423 | * if possible. |
424 | * |
425 | * Returns the result of |
426 | * @code |
427 | * std::use_facet<ctype<char_type> >(getloc()).narrow(c,dfault) |
428 | * @endcode |
429 | * |
430 | * Additional l10n notes are at |
431 | * http://gcc.gnu.org/onlinedocs/libstdc++/manual/localization.html |
432 | */ |
433 | char |
434 | narrow(char_type __c, char __dfault) const |
435 | { return __check_facet(_M_ctype).narrow(__c, __dfault); } |
436 | |
437 | /** |
438 | * @brief Widens characters. |
439 | * @param __c The character to widen. |
440 | * @return The widened character. |
441 | * |
442 | * Maps a character of @c char to a character of @c char_type. |
443 | * |
444 | * Returns the result of |
445 | * @code |
446 | * std::use_facet<ctype<char_type> >(getloc()).widen(c) |
447 | * @endcode |
448 | * |
449 | * Additional l10n notes are at |
450 | * http://gcc.gnu.org/onlinedocs/libstdc++/manual/localization.html |
451 | */ |
452 | char_type |
453 | widen(char __c) const |
454 | { return __check_facet(_M_ctype).widen(__c); } |
455 | |
456 | protected: |
457 | // 27.4.5.1 basic_ios constructors |
458 | /** |
459 | * @brief Empty. |
460 | * |
461 | * The default constructor does nothing and is not normally |
462 | * accessible to users. |
463 | */ |
464 | basic_ios() |
465 | : ios_base(), _M_tie(0), _M_fill(char_type()), _M_fill_init(false), |
466 | _M_streambuf(0), _M_ctype(0), _M_num_put(0), _M_num_get(0) |
467 | { } |
468 | |
469 | /** |
470 | * @brief All setup is performed here. |
471 | * |
472 | * This is called from the public constructor. It is not virtual and |
473 | * cannot be redefined. |
474 | */ |
475 | void |
476 | init(basic_streambuf<_CharT, _Traits>* __sb); |
477 | |
478 | #if __cplusplus >= 201103L |
479 | basic_ios(const basic_ios&) = delete; |
480 | basic_ios& operator=(const basic_ios&) = delete; |
481 | |
482 | void |
483 | move(basic_ios& __rhs) |
484 | { |
485 | ios_base::_M_move(__rhs); |
486 | _M_cache_locale(loc: _M_ios_locale); |
487 | this->tie(__rhs.tie(nullptr)); |
488 | _M_fill = __rhs._M_fill; |
489 | _M_fill_init = __rhs._M_fill_init; |
490 | _M_streambuf = nullptr; |
491 | } |
492 | |
493 | void |
494 | move(basic_ios&& __rhs) |
495 | { this->move(__rhs); } |
496 | |
497 | void |
498 | swap(basic_ios& __rhs) noexcept |
499 | { |
500 | ios_base::_M_swap(__rhs); |
501 | _M_cache_locale(loc: _M_ios_locale); |
502 | __rhs._M_cache_locale(__rhs._M_ios_locale); |
503 | std::swap(_M_tie, __rhs._M_tie); |
504 | std::swap(_M_fill, __rhs._M_fill); |
505 | std::swap(_M_fill_init, __rhs._M_fill_init); |
506 | } |
507 | |
508 | void |
509 | set_rdbuf(basic_streambuf<_CharT, _Traits>* __sb) |
510 | { _M_streambuf = __sb; } |
511 | #endif |
512 | |
513 | void |
514 | _M_cache_locale(const locale& __loc); |
515 | }; |
516 | |
517 | _GLIBCXX_END_NAMESPACE_VERSION |
518 | } // namespace |
519 | |
520 | #include <bits/basic_ios.tcc> |
521 | |
522 | #endif /* _BASIC_IOS_H */ |
523 | |