1 /* This is part of libio/iostream, providing -*- C++ -*- input/output.
2 Copyright (C) 1993, 1997 Free Software Foundation, Inc.
4 This file is part of the GNU IO Library. This library is free
5 software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option)
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING. If not, write to the Free
17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 As a special exception, if you link this library with files
21 compiled with a GNU compiler to produce an executable, this does not cause
22 the resulting executable to be covered by the GNU General Public License.
23 This exception does not however invalidate any other reasons why
24 the executable file might be covered by the GNU General Public License. */
26 /* Written by Per Bothner (bothner@cygnus.com). */
29 #pragma implementation
31 #define _STREAM_COMPAT
34 #include <stdio.h> /* Needed for sprintf */
41 extern "C" int __printf_fp (_IO_FILE
*, const struct printf_info
*,
47 #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
49 //#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n')
51 istream::istream(streambuf
*sb
, ostream
* tied
)
57 int skip_ws(streambuf
* sb
)
62 if (ch
== EOF
|| !isspace(ch
))
67 istream
& istream::get(char& c
)
70 int ch
= _strbuf
->sbumpc();
72 set(ios::eofbit
|ios::failbit
);
89 if (_tie
&& rdbuf()->in_avail() == 0)
91 int ch
= _strbuf
->sgetc();
97 istream
& istream::ignore(int n
/* = 1 */, int delim
/* = EOF */)
101 register streambuf
* sb
= _strbuf
;
103 _gcount
= sb
->ignore(n
);
108 if (n
!= MAXINT
) // FIXME
112 int ch
= sb
->sbumpc();
114 set(ios::eofbit
|ios::failbit
);
125 istream
& istream::read(char *s
, streamsize n
)
128 _gcount
= _strbuf
->sgetn(s
, n
);
130 set(ios::failbit
|ios::eofbit
);
140 streambuf
*sb
= rdbuf ();
143 if (sb
->sync ()) // Later: pubsync
145 setstate (ios::badbit
);
152 istream
& istream::seekg(streampos pos
)
154 pos
= _strbuf
->pubseekpos(pos
, ios::in
);
155 if (pos
== streampos(EOF
))
160 istream
& istream::seekg(streamoff off
, _seek_dir dir
)
162 streampos pos
= _IO_seekoff (_strbuf
, off
, (int) dir
, _IOS_INPUT
);
163 if (pos
== streampos(EOF
))
168 streampos
istream::tellg()
171 streampos pos
= _strbuf
->pubseekoff(0, ios::cur
, ios::in
);
173 streampos pos
= _IO_seekoff (_strbuf
, 0, _IO_seek_cur
, _IOS_INPUT
);
175 if (pos
== streampos(EOF
))
180 istream
& istream::operator>>(char& c
)
183 int ch
= _strbuf
->sbumpc();
185 set(ios::eofbit
|ios::failbit
);
193 istream::operator>> (char* ptr
)
195 register char *p
= ptr
;
199 register streambuf
* sb
= _strbuf
;
202 int ch
= sb
->sbumpc();
208 else if (isspace(ch
) || w
== 1)
223 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
224 #define LONGEST long long
229 static int read_int(istream
& stream
, unsigned LONGEST
& val
, int& neg
)
233 register streambuf
* sb
= stream
.rdbuf();
236 register int ch
= skip_ws(sb
);
243 else if (ch
== '-') {
247 if (ch
== EOF
) goto eof_fail
;
248 if (!(stream
.flags() & ios::basefield
)) {
255 if (ch
== 'x' || ch
== 'X') {
258 if (ch
== EOF
) goto eof_fail
;
267 else if ((stream
.flags() & ios::basefield
) == ios::hex
)
269 else if ((stream
.flags() & ios::basefield
) == ios::oct
)
276 if (ch
>= '0' && ch
<= '9')
278 else if (ch
>= 'A' && ch
<= 'F')
279 digit
= ch
- 'A' + 10;
280 else if (ch
>= 'a' && ch
<= 'f')
281 digit
= ch
- 'a' + 10;
292 val
= base
* val
+ digit
;
297 stream
.set(ios::failbit
);
300 stream
.set(ios::failbit
|ios::eofbit
);
304 #define READ_INT(TYPE) \
305 istream& istream::operator>>(TYPE& i)\
307 unsigned LONGEST val; int neg;\
308 if (read_int(*this, val, neg)) {\
309 if (neg) val = -val;\
316 READ_INT(unsigned short)
318 READ_INT(unsigned int)
320 READ_INT(unsigned long)
321 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
323 READ_INT(unsigned long long)
329 istream
& istream::operator>>(long double& x
)
332 #if _G_HAVE_LONG_DOUBLE_IO
340 istream
& istream::operator>>(double& x
)
347 istream
& istream::operator>>(float& x
)
354 istream
& istream::operator>>(register streambuf
* sbuf
)
357 register streambuf
* inbuf
= rdbuf();
358 // FIXME: Should optimize!
360 register int ch
= inbuf
->sbumpc();
365 if (sbuf
->sputc(ch
) == EOF
) {
374 ostream
& ostream::operator<<(char c
)
377 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
380 // This is what the cfront implementation does.
381 if (_strbuf
->sputc(c
) == EOF
) {
386 // This is what cfront documentation and current ANSI drafts say.
388 char fill_char
= fill();
389 register int padding
= w
> 0 ? w
- 1 : 0;
390 register streambuf
*sb
= _strbuf
;
391 if (!(flags() & ios::left
) && padding
) // Default adjustment.
392 if (_IO_padn(sb
, fill_char
, padding
) < padding
) {
396 if (sb
->sputc(c
) == EOF
) {
400 if (flags() & ios::left
&& padding
) // Left adjustment.
401 if (_IO_padn(sb
, fill_char
, padding
) < padding
)
406 _IO_cleanup_region_end (0);
411 /* Write VAL on STREAM.
412 If SIGN<0, val is the absolute value of a negative number.
413 If SIGN>0, val is a signed non-negative number.
414 If SIGN==0, val is unsigned. */
416 static void write_int(ostream
& stream
, unsigned LONGEST val
, int sign
)
418 #define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3)
419 char buf
[WRITE_BUF_SIZE
];
420 register char *buf_ptr
= buf
+WRITE_BUF_SIZE
; // End of buf.
421 const char *show_base
= "";
422 int show_base_len
= 0;
423 int show_pos
= 0; // If 1, print a '+'.
425 // Now do the actual conversion, placing the result at the *end* of buf.
426 // Note that we use separate code for decimal, octal, and hex,
427 // so we can divide by optimizable constants.
428 if ((stream
.flags() & ios::basefield
) == ios::oct
) { // Octal
430 *--buf_ptr
= (val
& 7) + '0';
433 if ((stream
.flags() & ios::showbase
) && (*buf_ptr
!= '0'))
436 else if ((stream
.flags() & ios::basefield
) == ios::hex
) { // Hex
437 const char *xdigs
= (stream
.flags() & ios::uppercase
) ? "0123456789ABCDEF0X"
438 : "0123456789abcdef0x";
440 *--buf_ptr
= xdigs
[val
& 15];
443 if ((stream
.flags() & ios::showbase
)) {
444 show_base
= xdigs
+ 16; // Either "0X" or "0x".
449 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
450 // Optimization: Only use long long when we need to.
451 while (val
> UINT_MAX
) {
452 *--buf_ptr
= (val
% 10) + '0';
455 // Use more efficient (int) arithmetic for the rest.
456 register unsigned int ival
= (unsigned int)val
;
458 register unsigned LONGEST ival
= val
;
461 *--buf_ptr
= (ival
% 10) + '0';
464 if (sign
> 0 && (stream
.flags() & ios::showpos
))
468 int buf_len
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
469 int w
= stream
.width(0);
471 // Calculate padding.
472 int len
= buf_len
+show_pos
;
474 len
+= show_base_len
;
475 int padding
= len
> w
? 0 : w
- len
;
478 register streambuf
* sbuf
= stream
.rdbuf();
479 ios::fmtflags pad_kind
=
480 stream
.flags() & (ios::left
|ios::right
|ios::internal
);
481 char fill_char
= stream
.fill();
483 && pad_kind
!= (ios::fmtflags
)ios::left
484 && pad_kind
!= (ios::fmtflags
)ios::internal
) // Default (right) adjust.
485 if (_IO_padn(sbuf
, fill_char
, padding
) < padding
)
487 if (sign
< 0 || show_pos
)
489 char ch
= sign
< 0 ? '-' : '+';
490 if (sbuf
->sputc(ch
) < 0)
494 if (_IO_sputn(sbuf
, show_base
, show_base_len
) <= 0)
496 if (pad_kind
== (ios::fmtflags
)ios::internal
&& padding
> 0)
497 if (_IO_padn(sbuf
, fill_char
, padding
) < padding
)
499 if (_IO_sputn (sbuf
, buf_ptr
, buf_len
) != buf_len
)
501 if (pad_kind
== (ios::fmtflags
)ios::left
&& padding
> 0) // Left adjustment
502 if (_IO_padn(sbuf
, fill_char
, padding
) < padding
)
507 stream
.set(ios::badbit
);
511 ostream
& ostream::operator<<(int n
)
514 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
517 unsigned int abs_n
= (unsigned)n
;
518 if (n
< 0 && (flags() & (ios::oct
|ios::hex
)) == 0)
519 abs_n
= -((unsigned)n
), sign
= -1;
520 write_int(*this, abs_n
, sign
);
521 _IO_cleanup_region_end (0);
526 ostream
& ostream::operator<<(unsigned int n
)
529 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
531 write_int(*this, n
, 0);
532 _IO_cleanup_region_end (0);
538 ostream
& ostream::operator<<(long n
)
541 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
544 unsigned long abs_n
= (unsigned long)n
;
545 if (n
< 0 && (flags() & (ios::oct
|ios::hex
)) == 0)
546 abs_n
= -((unsigned long)n
), sign
= -1;
547 write_int(*this, abs_n
, sign
);
548 _IO_cleanup_region_end (0);
553 ostream
& ostream::operator<<(unsigned long n
)
556 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
558 write_int(*this, n
, 0);
559 _IO_cleanup_region_end (0);
564 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
565 ostream
& ostream::operator<<(long long n
)
568 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
571 unsigned long long abs_n
= (unsigned long long)n
;
572 if (n
< 0 && (flags() & (ios::oct
|ios::hex
)) == 0)
573 abs_n
= -((unsigned long long)n
), sign
= -1;
574 write_int(*this, abs_n
, sign
);
575 _IO_cleanup_region_end (0);
581 ostream
& ostream::operator<<(unsigned long long n
)
584 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
586 write_int(*this, n
, 0);
587 _IO_cleanup_region_end (0);
593 ostream
& ostream::operator<<(double n
)
596 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
598 // Uses __cvt_double (renamed from static cvt), in Chris Torek's
599 // stdio implementation. The setup code uses the same logic
600 // as in __vsbprintf.C (also based on Torek's code).
602 if ((flags() & ios::floatfield
) == ios::fixed
)
604 else if ((flags() & ios::floatfield
) == ios::scientific
)
605 format_char
= flags() & ios::uppercase
? 'E' : 'e';
607 format_char
= flags() & ios::uppercase
? 'G' : 'g';
609 int prec
= precision();
610 if (prec
<= 0 && !(flags() & ios::fixed
))
611 prec
= 6; /* default */
613 // Do actual conversion.
614 #ifdef _G_HAVE_PRINTF_FP
616 struct printf_info info
= { prec
: prec
,
622 alt
: flags() & ios::showpoint
,
625 showsign
: flags() & ios::showpos
,
629 const void *ptr
= &n
;
630 if (__printf_fp (rdbuf(), &info
, &ptr
) < 0)
631 set(ios::badbit
|ios::failbit
);
633 #elif defined _IO_USE_DTOA
634 if (_IO_outfloat(n
, rdbuf(), format_char
, width(0),
636 flags() & ios::showpos
? '+' : 0,
638 set(ios::badbit
|ios::failbit
); // ??
640 int fpprec
= 0; // 'Extra' (suppressed) floating precision.
641 if (prec
> MAXFRACT
) {
642 if (flags() & (ios::fixed
|ios::scientific
) & ios::showpos
)
643 fpprec
= prec
- MAXFRACT
;
651 int size
= __cvt_double(n
, prec
,
652 flags() & ios::showpoint
? 0x80 : 0,
654 format_char
, cp
, buf
+ sizeof(buf
));
655 if (negative
) sign
= '-';
656 else if (flags() & ios::showpos
) sign
= '+';
660 // Calculate padding.
661 int fieldsize
= size
+ fpprec
;
662 if (sign
) fieldsize
++;
666 padding
= w
- fieldsize
;
669 register streambuf
* sbuf
= rdbuf();
671 char fill_char
= fill();
672 ios::fmtflags pad_kind
=
673 flags() & (ios::left
|ios::right
|ios::internal
);
674 if (pad_kind
!= (ios::fmtflags
)ios::left
// Default (right) adjust.
675 && pad_kind
!= (ios::fmtflags
)ios::internal
)
676 for (i
= padding
; --i
>= 0; ) sbuf
->sputc(fill_char
);
679 if (pad_kind
== (ios::fmtflags
)ios::internal
)
680 for (i
= padding
; --i
>= 0; ) sbuf
->sputc(fill_char
);
682 // Emit the actual concented field, followed by extra zeros.
683 _IO_sputn (sbuf
, cp
, size
);
684 for (i
= fpprec
; --i
>= 0; ) sbuf
->sputc('0');
686 if (pad_kind
== (ios::fmtflags
)ios::left
) // Left adjustment
687 for (i
= padding
; --i
>= 0; ) sbuf
->sputc(fill_char
);
690 _IO_cleanup_region_end (0);
695 #if _G_HAVE_LONG_DOUBLE_IO
696 ostream
& ostream::operator<<(long double n
)
700 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
703 if ((flags() & ios::floatfield
) == ios::fixed
)
705 else if ((flags() & ios::floatfield
) == ios::scientific
)
706 format_char
= flags() & ios::uppercase
? 'E' : 'e';
708 format_char
= flags() & ios::uppercase
? 'G' : 'g';
710 int prec
= precision();
711 if (prec
<= 0 && !(flags() & ios::fixed
))
712 prec
= 6; /* default */
714 #ifdef _G_HAVE_PRINTF_FP
715 // Do actual conversion.
716 struct printf_info info
= { prec
: prec
,
722 alt
: flags() & ios::showpoint
,
725 showsign
: flags() & ios::showpos
,
730 const void *ptr
= &n
;
732 if (__printf_fp (rdbuf(), &info
, &ptr
) < 0)
733 set (ios::badbit
|ios::failbit
);
735 # error "long double I/O using dtoa or cvt_double is not implemented"
738 _IO_cleanup_region_end (0);
744 ostream
& ostream::operator<<(const char *s
)
748 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
754 // FIXME: Should we: if (w && len>w) len = w;
755 char fill_char
= fill();
756 register streambuf
*sbuf
= rdbuf();
757 register int padding
= w
> len
? w
- len
: 0;
758 if (!(flags() & ios::left
) && padding
> 0) // Default adjustment.
759 if (_IO_padn(sbuf
, fill_char
, padding
) != padding
)
764 if (_IO_sputn (sbuf
, s
, len
) != len
)
769 if (flags() & ios::left
&& padding
> 0) // Left adjustment.
770 if (_IO_padn(sbuf
, fill_char
, padding
) != padding
)
774 _IO_cleanup_region_end (0);
780 ostream
& ostream::operator<<(const void *p
)
781 { Is in osform
.cc
, to avoid pulling in all of _IO_vfprintf by
this file
. */
}
784 ostream
& ostream::operator<<(register streambuf
* sbuf
)
788 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
790 char buffer
[_IO_BUFSIZ
];
791 register streambuf
* outbuf
= _strbuf
;
794 _IO_size_t count
= _IO_sgetn(sbuf
, buffer
, _IO_BUFSIZ
);
797 if (_IO_sputn(outbuf
, buffer
, count
) != count
)
804 _IO_cleanup_region_end (0);
809 ostream::ostream(streambuf
* sb
, ostream
* tied
)
814 ostream
& ostream::seekp(streampos pos
)
816 pos
= _strbuf
->pubseekpos(pos
, ios::out
);
817 if (pos
== streampos(EOF
))
822 ostream
& ostream::seekp(streamoff off
, _seek_dir dir
)
824 streampos pos
= _IO_seekoff (_strbuf
, off
, (int) dir
, _IOS_OUTPUT
);
825 if (pos
== streampos(EOF
))
830 streampos
ostream::tellp()
833 streampos pos
= _IO_seekoff (_strbuf
, 0, _IO_seek_cur
, _IOS_OUTPUT
);
835 streampos pos
= _strbuf
->pubseekoff(0, ios::cur
, ios::out
);
837 if (pos
== streampos(EOF
))
842 ostream
& ostream::flush()
849 ostream
& flush(ostream
& outs
)
854 istream
& ws(istream
& ins
)
857 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
859 int ch
= skip_ws(ins
._strbuf
);
861 ins
.set(ios::eofbit
);
863 ins
._strbuf
->sputbackc(ch
);
865 _IO_cleanup_region_end (0);
870 // Skip white-space. Return 0 on failure (EOF), or 1 on success.
871 // Differs from ws() manipulator in that failbit is set on EOF.
872 // Called by ipfx() and ipfx0() if needed.
874 int istream::_skip_ws()
876 int ch
= skip_ws(_strbuf
);
878 set(ios::eofbit
|ios::failbit
);
882 _strbuf
->sputbackc(ch
);
887 ostream
& ends(ostream
& outs
)
893 ostream
& endl(ostream
& outs
)
895 return flush(outs
.put('\n'));
898 istream
& lock(istream
& ins
)
900 _IO_flockfile (ins
._strbuf
);
903 istream
& unlock(istream
& ins
)
905 _IO_funlockfile (ins
._strbuf
);
908 ostream
& lock(ostream
& outs
)
910 _IO_flockfile (outs
._strbuf
);
913 ostream
& unlock(ostream
& outs
)
915 _IO_funlockfile (outs
._strbuf
);
920 ostream
& ostream::write(const char *s
, streamsize n
)
923 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile
,
925 if (_IO_sputn(_strbuf
, s
, n
) != n
)
928 _IO_cleanup_region_end (0);
933 void ostream::do_osfx()
935 if (flags() & ios::unitbuf
)
937 if (flags() & ios::stdio
) {
943 iostream::iostream(streambuf
* sb
, ostream
* tied
)
948 // NOTE: extension for compatibility with old libg++.
949 // Not really compatible with fistream::close().
950 #ifdef _STREAM_COMPAT
953 if (_strbuf
->_flags
& _IO_IS_FILEBUF
)
954 ((struct filebuf
*)rdbuf())->close();
955 else if (_strbuf
!= NULL
)
961 int istream::skip(int i
)
963 int old
= (_flags
& ios::skipws
) != 0;
965 _flags
|= ios::skipws
;
967 _flags
&= ~ios::skipws
;