1 /* This is part of libio/iostream, providing -*- C++ -*- input/output.
2 Copyright (C) 1993 Free Software Foundation
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, USA.
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does not cause
21 the resulting executable to be covered by the GNU General Public License.
22 This exception does not however invalidate any other reasons why
23 the executable file might be covered by the GNU General Public License. */
25 /* Written by Per Bothner (bothner@cygnus.com). */
28 #pragma implementation
30 #define _STREAM_COMPAT
33 #include <stdio.h> /* Needed for sprintf */
39 #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
41 //#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n')
43 istream::istream(streambuf
*sb
, ostream
* tied
)
49 int skip_ws(streambuf
* sb
)
54 if (ch
== EOF
|| !isspace(ch
))
59 istream
& istream::get(char& c
)
62 int ch
= _strbuf
->sbumpc();
64 set(ios::eofbit
|ios::failbit
);
81 if (_tie
&& rdbuf()->in_avail() == 0)
83 int ch
= _strbuf
->sgetc();
89 istream
& istream::ignore(int n
/* = 1 */, int delim
/* = EOF */)
93 register streambuf
* sb
= _strbuf
;
95 _gcount
= sb
->ignore(n
);
100 if (n
!= MAXINT
) // FIXME
104 int ch
= sb
->sbumpc();
106 set(ios::eofbit
|ios::failbit
);
117 istream
& istream::read(char *s
, streamsize n
)
120 _gcount
= _strbuf
->sgetn(s
, n
);
122 set(ios::failbit
|ios::eofbit
);
132 streambuf
*sb
= rdbuf ();
135 if (sb
->sync ()) // Later: pubsync
137 setstate (ios::badbit
);
144 istream
& istream::seekg(streampos pos
)
146 pos
= _strbuf
->pubseekpos(pos
, ios::in
);
147 if (pos
== streampos(EOF
))
152 istream
& istream::seekg(streamoff off
, _seek_dir dir
)
154 streampos pos
= _IO_seekoff (_strbuf
, off
, (int) dir
, _IOS_INPUT
);
155 if (pos
== streampos(EOF
))
160 streampos
istream::tellg()
163 streampos pos
= _strbuf
->pubseekoff(0, ios::cur
, ios::in
);
165 streampos pos
= _IO_seekoff (_strbuf
, 0, _IO_seek_cur
, _IOS_INPUT
);
167 if (pos
== streampos(EOF
))
172 istream
& istream::operator>>(char& c
)
175 int ch
= _strbuf
->sbumpc();
177 set(ios::eofbit
|ios::failbit
);
185 istream::operator>> (char* ptr
)
187 register char *p
= ptr
;
191 register streambuf
* sb
= _strbuf
;
194 int ch
= sb
->sbumpc();
200 else if (isspace(ch
) || w
== 1)
215 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
216 #define LONGEST long long
221 static int read_int(istream
& stream
, unsigned LONGEST
& val
, int& neg
)
225 register streambuf
* sb
= stream
.rdbuf();
228 register int ch
= skip_ws(sb
);
235 else if (ch
== '-') {
239 if (ch
== EOF
) goto eof_fail
;
240 if (!(stream
.flags() & ios::basefield
)) {
247 if (ch
== 'x' || ch
== 'X') {
250 if (ch
== EOF
) goto eof_fail
;
259 else if ((stream
.flags() & ios::basefield
) == ios::hex
)
261 else if ((stream
.flags() & ios::basefield
) == ios::oct
)
268 if (ch
>= '0' && ch
<= '9')
270 else if (ch
>= 'A' && ch
<= 'F')
271 digit
= ch
- 'A' + 10;
272 else if (ch
>= 'a' && ch
<= 'f')
273 digit
= ch
- 'a' + 10;
284 val
= base
* val
+ digit
;
289 stream
.set(ios::failbit
);
292 stream
.set(ios::failbit
|ios::eofbit
);
296 #define READ_INT(TYPE) \
297 istream& istream::operator>>(TYPE& i)\
299 unsigned LONGEST val; int neg;\
300 if (read_int(*this, val, neg)) {\
301 if (neg) val = -val;\
308 READ_INT(unsigned short)
310 READ_INT(unsigned int)
312 READ_INT(unsigned long)
313 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
315 READ_INT(unsigned long long)
321 istream
& istream::operator>>(long double& x
)
328 istream
& istream::operator>>(double& x
)
335 istream
& istream::operator>>(float& x
)
342 istream
& istream::operator>>(register streambuf
* sbuf
)
345 register streambuf
* inbuf
= rdbuf();
346 // FIXME: Should optimize!
348 register int ch
= inbuf
->sbumpc();
353 if (sbuf
->sputc(ch
) == EOF
) {
362 ostream
& ostream::operator<<(char c
)
366 // This is what the cfront implementation does.
367 if (_strbuf
->sputc(c
) == EOF
)
370 // This is what cfront documentation and current ANSI drafts say.
372 char fill_char
= fill();
373 register int padding
= w
> 0 ? w
- 1 : 0;
374 register streambuf
*sb
= _strbuf
;
375 if (!(flags() & ios::left
) && padding
) // Default adjustment.
376 if (_IO_padn(sb
, fill_char
, padding
) < padding
)
378 if (sb
->sputc(c
) == EOF
)
380 if (flags() & ios::left
&& padding
) // Left adjustment.
381 if (_IO_padn(sb
, fill_char
, padding
) < padding
)
393 /* Write VAL on STREAM.
394 If SIGN<0, val is the absolute value of a negative number.
395 If SIGN>0, val is a signed non-negative number.
396 If SIGN==0, val is unsigned. */
398 static void write_int(ostream
& stream
, unsigned LONGEST val
, int sign
)
400 #define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3)
401 char buf
[WRITE_BUF_SIZE
];
402 register char *buf_ptr
= buf
+WRITE_BUF_SIZE
; // End of buf.
403 const char *show_base
= "";
404 int show_base_len
= 0;
405 int show_pos
= 0; // If 1, print a '+'.
407 // Now do the actual conversion, placing the result at the *end* of buf.
408 // Note that we use separate code for decimal, octal, and hex,
409 // so we can divide by optimizable constants.
410 if ((stream
.flags() & ios::basefield
) == ios::oct
) { // Octal
412 *--buf_ptr
= (val
& 7) + '0';
415 if ((stream
.flags() & ios::showbase
) && (*buf_ptr
!= '0'))
418 else if ((stream
.flags() & ios::basefield
) == ios::hex
) { // Hex
419 const char *xdigs
= (stream
.flags() & ios::uppercase
) ? "0123456789ABCDEF0X"
420 : "0123456789abcdef0x";
422 *--buf_ptr
= xdigs
[val
& 15];
425 if ((stream
.flags() & ios::showbase
)) {
426 show_base
= xdigs
+ 16; // Either "0X" or "0x".
431 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
432 // Optimization: Only use long long when we need to.
433 while (val
> UINT_MAX
) {
434 *--buf_ptr
= (val
% 10) + '0';
437 // Use more efficient (int) arithmetic for the rest.
438 register unsigned int ival
= (unsigned int)val
;
440 register unsigned LONGEST ival
= val
;
443 *--buf_ptr
= (ival
% 10) + '0';
446 if (sign
> 0 && (stream
.flags() & ios::showpos
))
450 int buf_len
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
451 int w
= stream
.width(0);
453 // Calculate padding.
454 int len
= buf_len
+show_pos
;
456 len
+= show_base_len
;
457 int padding
= len
> w
? 0 : w
- len
;
460 register streambuf
* sbuf
= stream
.rdbuf();
461 ios::fmtflags pad_kind
=
462 stream
.flags() & (ios::left
|ios::right
|ios::internal
);
463 char fill_char
= stream
.fill();
465 && pad_kind
!= (ios::fmtflags
)ios::left
466 && pad_kind
!= (ios::fmtflags
)ios::internal
) // Default (right) adjust.
467 if (_IO_padn(sbuf
, fill_char
, padding
) < padding
)
469 if (sign
< 0 || show_pos
)
471 char ch
= sign
< 0 ? '-' : '+';
472 if (sbuf
->sputc(ch
) < 0)
476 if (_IO_sputn(sbuf
, show_base
, show_base_len
) <= 0)
478 if (pad_kind
== (ios::fmtflags
)ios::internal
&& padding
> 0)
479 if (_IO_padn(sbuf
, fill_char
, padding
) < padding
)
481 if (_IO_sputn (sbuf
, buf_ptr
, buf_len
) != buf_len
)
483 if (pad_kind
== (ios::fmtflags
)ios::left
&& padding
> 0) // Left adjustment
484 if (_IO_padn(sbuf
, fill_char
, padding
) < padding
)
489 stream
.set(ios::badbit
);
493 ostream
& ostream::operator<<(int n
)
497 unsigned int abs_n
= (unsigned)n
;
498 if (n
< 0 && (flags() & (ios::oct
|ios::hex
)) == 0)
499 abs_n
= -((unsigned)n
), sign
= -1;
500 write_int(*this, abs_n
, sign
);
505 ostream
& ostream::operator<<(unsigned int n
)
508 write_int(*this, n
, 0);
513 ostream
& ostream::operator<<(long n
)
517 unsigned long abs_n
= (unsigned long)n
;
518 if (n
< 0 && (flags() & (ios::oct
|ios::hex
)) == 0)
519 abs_n
= -((unsigned long)n
), sign
= -1;
520 write_int(*this, abs_n
, sign
);
525 ostream
& ostream::operator<<(unsigned long n
)
528 write_int(*this, n
, 0);
532 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
533 ostream
& ostream::operator<<(long long n
)
537 unsigned long long abs_n
= (unsigned long long)n
;
538 if (n
< 0 && (flags() & (ios::oct
|ios::hex
)) == 0)
539 abs_n
= -((unsigned long long)n
), sign
= -1;
540 write_int(*this, abs_n
, sign
);
546 ostream
& ostream::operator<<(unsigned long long n
)
549 write_int(*this, n
, 0);
554 ostream
& ostream::operator<<(double n
)
557 // Uses __cvt_double (renamed from static cvt), in Chris Torek's
558 // stdio implementation. The setup code uses the same logic
559 // as in __vsbprintf.C (also based on Torek's code).
561 if ((flags() & ios::floatfield
) == ios::fixed
)
563 else if ((flags() & ios::floatfield
) == ios::scientific
)
564 format_char
= flags() & ios::uppercase
? 'E' : 'e';
566 format_char
= flags() & ios::uppercase
? 'G' : 'g';
568 int prec
= precision();
569 if (prec
<= 0 && !(flags() & ios::fixed
))
570 prec
= 6; /* default */
572 // Do actual conversion.
574 if (_IO_outfloat(n
, rdbuf(), format_char
, width(0),
576 flags() & ios::showpos
? '+' : 0,
578 set(ios::badbit
|ios::failbit
); // ??
580 int fpprec
= 0; // 'Extra' (suppressed) floating precision.
581 if (prec
> MAXFRACT
) {
582 if (flags() & (ios::fixed
|ios::scientific
) & ios::showpos
)
583 fpprec
= prec
- MAXFRACT
;
591 int size
= __cvt_double(n
, prec
,
592 flags() & ios::showpoint
? 0x80 : 0,
594 format_char
, cp
, buf
+ sizeof(buf
));
595 if (negative
) sign
= '-';
596 else if (flags() & ios::showpos
) sign
= '+';
600 // Calculate padding.
601 int fieldsize
= size
+ fpprec
;
602 if (sign
) fieldsize
++;
606 padding
= w
- fieldsize
;
609 register streambuf
* sbuf
= rdbuf();
611 char fill_char
= fill();
612 ios::fmtflags pad_kind
=
613 flags() & (ios::left
|ios::right
|ios::internal
);
614 if (pad_kind
!= (ios::fmtflags
)ios::left
// Default (right) adjust.
615 && pad_kind
!= (ios::fmtflags
)ios::internal
)
616 for (i
= padding
; --i
>= 0; ) sbuf
->sputc(fill_char
);
619 if (pad_kind
== (ios::fmtflags
)ios::internal
)
620 for (i
= padding
; --i
>= 0; ) sbuf
->sputc(fill_char
);
622 // Emit the actual concented field, followed by extra zeros.
623 _IO_sputn (sbuf
, cp
, size
);
624 for (i
= fpprec
; --i
>= 0; ) sbuf
->sputc('0');
626 if (pad_kind
== (ios::fmtflags
)ios::left
) // Left adjustment
627 for (i
= padding
; --i
>= 0; ) sbuf
->sputc(fill_char
);
634 ostream
& ostream::operator<<(const char *s
)
642 // FIXME: Should we: if (w && len>w) len = w;
643 char fill_char
= fill();
644 register streambuf
*sbuf
= rdbuf();
645 register int padding
= w
> len
? w
- len
: 0;
646 if (!(flags() & ios::left
) && padding
> 0) // Default adjustment.
647 if (_IO_padn(sbuf
, fill_char
, padding
) != padding
)
649 if (_IO_sputn (sbuf
, s
, len
) != len
)
651 if (flags() & ios::left
&& padding
> 0) // Left adjustment.
652 if (_IO_padn(sbuf
, fill_char
, padding
) != padding
)
664 ostream
& ostream::operator<<(const void *p
)
665 { Is in osform
.cc
, to avoid pulling in all of _IO_vfprintf by
this file
. */
}
668 ostream
& ostream::operator<<(register streambuf
* sbuf
)
672 char buffer
[_IO_BUFSIZ
];
673 register streambuf
* outbuf
= _strbuf
;
676 _IO_size_t count
= _IO_sgetn(sbuf
, buffer
, _IO_BUFSIZ
);
679 if (_IO_sputn(outbuf
, buffer
, count
) != count
)
690 ostream::ostream(streambuf
* sb
, ostream
* tied
)
695 ostream
& ostream::seekp(streampos pos
)
697 pos
= _strbuf
->pubseekpos(pos
, ios::out
);
698 if (pos
== streampos(EOF
))
703 ostream
& ostream::seekp(streamoff off
, _seek_dir dir
)
705 streampos pos
= _IO_seekoff (_strbuf
, off
, (int) dir
, _IOS_OUTPUT
);
706 if (pos
== streampos(EOF
))
711 streampos
ostream::tellp()
714 streampos pos
= _IO_seekoff (_strbuf
, 0, _IO_seek_cur
, _IOS_OUTPUT
);
716 streampos pos
= _strbuf
->pubseekoff(0, ios::cur
, ios::out
);
718 if (pos
== streampos(EOF
))
723 ostream
& ostream::flush()
730 ostream
& flush(ostream
& outs
)
735 istream
& ws(istream
& ins
)
738 int ch
= skip_ws(ins
._strbuf
);
740 ins
.set(ios::eofbit
);
742 ins
._strbuf
->sputbackc(ch
);
747 // Skip white-space. Return 0 on failure (EOF), or 1 on success.
748 // Differs from ws() manipulator in that failbit is set on EOF.
749 // Called by ipfx() and ipfx0() if needed.
751 int istream::_skip_ws()
753 int ch
= skip_ws(_strbuf
);
755 set(ios::eofbit
|ios::failbit
);
759 _strbuf
->sputbackc(ch
);
764 ostream
& ends(ostream
& outs
)
770 ostream
& endl(ostream
& outs
)
772 return flush(outs
.put('\n'));
775 ostream
& ostream::write(const char *s
, streamsize n
)
778 if (_IO_sputn(_strbuf
, s
, n
) != n
)
784 void ostream::do_osfx()
786 if (flags() & ios::unitbuf
)
788 if (flags() & ios::stdio
) {
794 iostream::iostream(streambuf
* sb
, ostream
* tied
)
799 // NOTE: extension for compatibility with old libg++.
800 // Not really compatible with fistream::close().
801 #ifdef _STREAM_COMPAT
804 if (_strbuf
->_flags
& _IO_IS_FILEBUF
)
805 ((struct filebuf
*)rdbuf())->close();
806 else if (_strbuf
!= NULL
)
812 int istream::skip(int i
)
814 int old
= (_flags
& ios::skipws
) != 0;
816 _flags
|= ios::skipws
;
818 _flags
&= ~ios::skipws
;