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 *,
46 int __cvt_double(double number, register int prec, int flags, int *signp,
47 int fmtch, char *startp, char *endp);
51 #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
53 //#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n')
55 istream::istream(streambuf *sb, ostream* tied)
61 int skip_ws(streambuf* sb)
66 if (ch == EOF || !isspace(ch))
71 istream& istream::get(char& c)
74 int ch = _strbuf->sbumpc();
76 set(ios::eofbit|ios::failbit);
93 if (_tie && rdbuf()->in_avail() == 0)
95 int ch = _strbuf->sgetc();
101 istream& istream::ignore(int n /* = 1 */, int delim /* = EOF */)
105 register streambuf* sb = _strbuf;
107 _gcount = sb->ignore(n);
112 if (n != MAXINT) // FIXME
116 int ch = sb->sbumpc();
118 set(ios::eofbit|ios::failbit);
129 istream& istream::read(char *s, streamsize n)
132 _gcount = _strbuf->sgetn(s, n);
134 set(ios::failbit|ios::eofbit);
144 streambuf *sb = rdbuf ();
147 if (sb->sync ()) // Later: pubsync
149 setstate (ios::badbit);
156 istream& istream::seekg(streampos pos)
158 pos = _strbuf->pubseekpos(pos, ios::in);
159 if (pos == streampos(EOF))
164 istream& istream::seekg(streamoff off, _seek_dir dir)
166 streampos pos = _IO_seekoff (_strbuf, off, (int) dir, _IOS_INPUT);
167 if (pos == streampos(EOF))
172 streampos istream::tellg()
175 streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::in);
177 streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_INPUT);
179 if (pos == streampos(EOF))
184 istream& istream::operator>>(char& c)
187 int ch = _strbuf->sbumpc();
189 set(ios::eofbit|ios::failbit);
197 istream::operator>> (char* ptr)
199 register char *p = ptr;
203 register streambuf* sb = _strbuf;
206 int ch = sb->sbumpc();
212 else if (isspace(ch) || w == 1)
227 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
228 #define LONGEST long long
233 static int read_int(istream& stream, unsigned LONGEST& val, int& neg)
237 register streambuf* sb = stream.rdbuf();
240 register int ch = skip_ws(sb);
247 else if (ch == '-') {
251 if (ch == EOF) goto eof_fail;
252 if (!(stream.flags() & ios::basefield)) {
259 if (ch == 'x' || ch == 'X') {
262 if (ch == EOF) goto eof_fail;
271 else if ((stream.flags() & ios::basefield) == ios::hex)
273 else if ((stream.flags() & ios::basefield) == ios::oct)
280 if (ch >= '0' && ch <= '9')
282 else if (ch >= 'A' && ch <= 'F')
283 digit = ch - 'A' + 10;
284 else if (ch >= 'a' && ch <= 'f')
285 digit = ch - 'a' + 10;
296 val = base * val + digit;
301 stream.set(ios::failbit);
304 stream.set(ios::failbit|ios::eofbit);
308 #define READ_INT(TYPE) \
309 istream& istream::operator>>(TYPE& i)\
311 unsigned LONGEST val; int neg;\
312 if (read_int(*this, val, neg)) {\
313 if (neg) val = -val;\
320 READ_INT(unsigned short)
322 READ_INT(unsigned int)
324 READ_INT(unsigned long)
325 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
327 READ_INT(unsigned long long)
333 istream& istream::operator>>(long double& x)
337 #if _G_HAVE_LONG_DOUBLE_IO
348 istream& istream::operator>>(double& x)
355 istream& istream::operator>>(float& x)
362 istream& istream::operator>>(register streambuf* sbuf)
365 register streambuf* inbuf = rdbuf();
366 // FIXME: Should optimize!
368 register int ch = inbuf->sbumpc();
373 if (sbuf->sputc(ch) == EOF) {
382 ostream& ostream::operator<<(char c)
385 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
388 // This is what the cfront implementation does.
389 if (_strbuf->sputc(c) == EOF) {
394 // This is what cfront documentation and current ANSI drafts say.
396 char fill_char = fill();
397 register int padding = w > 0 ? w - 1 : 0;
398 register streambuf *sb = _strbuf;
399 if (!(flags() & ios::left) && padding) // Default adjustment.
400 if (_IO_padn(sb, fill_char, padding) < padding) {
404 if (sb->sputc(c) == EOF) {
408 if (flags() & ios::left && padding) // Left adjustment.
409 if (_IO_padn(sb, fill_char, padding) < padding)
414 _IO_cleanup_region_end (0);
419 /* Write VAL on STREAM.
420 If SIGN<0, val is the absolute value of a negative number.
421 If SIGN>0, val is a signed non-negative number.
422 If SIGN==0, val is unsigned. */
424 static void write_int(ostream& stream, unsigned LONGEST val, int sign)
426 #define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3)
427 char buf[WRITE_BUF_SIZE];
428 register char *buf_ptr = buf+WRITE_BUF_SIZE; // End of buf.
429 const char *show_base = "";
430 int show_base_len = 0;
431 int show_pos = 0; // If 1, print a '+'.
433 // Now do the actual conversion, placing the result at the *end* of buf.
434 // Note that we use separate code for decimal, octal, and hex,
435 // so we can divide by optimizable constants.
436 if ((stream.flags() & ios::basefield) == ios::oct) { // Octal
438 *--buf_ptr = (val & 7) + '0';
441 if ((stream.flags() & ios::showbase) && (*buf_ptr != '0'))
444 else if ((stream.flags() & ios::basefield) == ios::hex) { // Hex
445 const char *xdigs = (stream.flags() & ios::uppercase) ? "0123456789ABCDEF0X"
446 : "0123456789abcdef0x";
448 *--buf_ptr = xdigs[val & 15];
451 if ((stream.flags() & ios::showbase)) {
452 show_base = xdigs + 16; // Either "0X" or "0x".
457 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
458 // Optimization: Only use long long when we need to.
459 while (val > UINT_MAX) {
460 *--buf_ptr = (val % 10) + '0';
463 // Use more efficient (int) arithmetic for the rest.
464 register unsigned int ival = (unsigned int)val;
466 register unsigned LONGEST ival = val;
469 *--buf_ptr = (ival % 10) + '0';
472 if (sign > 0 && (stream.flags() & ios::showpos))
476 int buf_len = buf+WRITE_BUF_SIZE - buf_ptr;
477 int w = stream.width(0);
479 // Calculate padding.
480 int len = buf_len+show_pos;
482 len += show_base_len;
483 int padding = len > w ? 0 : w - len;
486 register streambuf* sbuf = stream.rdbuf();
487 ios::fmtflags pad_kind =
488 stream.flags() & (ios::left|ios::right|ios::internal);
489 char fill_char = stream.fill();
491 && pad_kind != (ios::fmtflags)ios::left
492 && pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust.
493 if (_IO_padn(sbuf, fill_char, padding) < padding)
495 if (sign < 0 || show_pos)
497 char ch = sign < 0 ? '-' : '+';
498 if (sbuf->sputc(ch) < 0)
502 if (_IO_sputn(sbuf, show_base, show_base_len) <= 0)
504 if (pad_kind == (ios::fmtflags)ios::internal && padding > 0)
505 if (_IO_padn(sbuf, fill_char, padding) < padding)
507 if (_IO_sputn (sbuf, buf_ptr, buf_len) != buf_len)
509 if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment
510 if (_IO_padn(sbuf, fill_char, padding) < padding)
515 stream.set(ios::badbit);
519 ostream& ostream::operator<<(int n)
522 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
525 unsigned int abs_n = (unsigned)n;
526 if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
527 abs_n = -((unsigned)n), sign = -1;
528 write_int(*this, abs_n, sign);
529 _IO_cleanup_region_end (0);
534 ostream& ostream::operator<<(unsigned int n)
537 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
539 write_int(*this, n, 0);
540 _IO_cleanup_region_end (0);
546 ostream& ostream::operator<<(long n)
549 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
552 unsigned long abs_n = (unsigned long)n;
553 if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
554 abs_n = -((unsigned long)n), sign = -1;
555 write_int(*this, abs_n, sign);
556 _IO_cleanup_region_end (0);
561 ostream& ostream::operator<<(unsigned long n)
564 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
566 write_int(*this, n, 0);
567 _IO_cleanup_region_end (0);
572 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
573 ostream& ostream::operator<<(long long n)
576 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
579 unsigned long long abs_n = (unsigned long long)n;
580 if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
581 abs_n = -((unsigned long long)n), sign = -1;
582 write_int(*this, abs_n, sign);
583 _IO_cleanup_region_end (0);
589 ostream& ostream::operator<<(unsigned long long n)
592 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
594 write_int(*this, n, 0);
595 _IO_cleanup_region_end (0);
601 ostream& ostream::operator<<(double n)
604 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
606 // Uses __cvt_double (renamed from static cvt), in Chris Torek's
607 // stdio implementation. The setup code uses the same logic
608 // as in __vsbprintf.C (also based on Torek's code).
610 if ((flags() & ios::floatfield) == ios::fixed)
612 else if ((flags() & ios::floatfield) == ios::scientific)
613 format_char = flags() & ios::uppercase ? 'E' : 'e';
615 format_char = flags() & ios::uppercase ? 'G' : 'g';
617 int prec = precision();
618 if (prec <= 0 && !(flags() & ios::fixed))
619 prec = 6; /* default */
621 // Do actual conversion.
622 #if _G_HAVE_PRINTF_FP
624 struct printf_info info = { /* prec: */ prec,
625 /* width: */ width(0),
626 /* spec: */ format_char,
627 /* is_long_double: */ 0,
630 /* alt: */ (flags() & ios::showpoint) != 0,
632 /* left: */ (flags() & ios::left) != 0,
633 /* showsign: */ (flags() & ios::showpos) != 0,
635 #if defined __GLIBC__ && __GLIBC__ >= 2
640 const void *ptr = (const void *) &n;
641 if (__printf_fp (rdbuf(), &info, &ptr) < 0)
642 set(ios::badbit|ios::failbit);
644 #elif defined _IO_USE_DTOA
645 if (_IO_outfloat(n, rdbuf(), format_char, width(0),
647 flags() & ios::showpos ? '+' : 0,
649 set(ios::badbit|ios::failbit); // ??
651 int fpprec = 0; // 'Extra' (suppressed) floating precision.
652 if (prec > MAXFRACT) {
653 if (flags() & (ios::fixed|ios::scientific) & ios::showpos)
654 fpprec = prec - MAXFRACT;
662 int size = __cvt_double(n, prec,
663 flags() & ios::showpoint ? 0x80 : 0,
665 format_char, cp, buf + sizeof(buf));
666 if (negative) sign = '-';
667 else if (flags() & ios::showpos) sign = '+';
671 // Calculate padding.
672 int fieldsize = size + fpprec;
673 if (sign) fieldsize++;
677 padding = w - fieldsize;
680 register streambuf* sbuf = rdbuf();
682 char fill_char = fill();
683 ios::fmtflags pad_kind =
684 flags() & (ios::left|ios::right|ios::internal);
685 if (pad_kind != (ios::fmtflags)ios::left // Default (right) adjust.
686 && pad_kind != (ios::fmtflags)ios::internal)
687 for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
690 if (pad_kind == (ios::fmtflags)ios::internal)
691 for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
693 // Emit the actual concented field, followed by extra zeros.
694 _IO_sputn (sbuf, cp, size);
695 for (i = fpprec; --i >= 0; ) sbuf->sputc('0');
697 if (pad_kind == (ios::fmtflags)ios::left) // Left adjustment
698 for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
701 _IO_cleanup_region_end (0);
706 #if _G_HAVE_LONG_DOUBLE_IO
707 ostream& ostream::operator<<(long double n)
711 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
714 if ((flags() & ios::floatfield) == ios::fixed)
716 else if ((flags() & ios::floatfield) == ios::scientific)
717 format_char = flags() & ios::uppercase ? 'E' : 'e';
719 format_char = flags() & ios::uppercase ? 'G' : 'g';
721 int prec = precision();
722 if (prec <= 0 && !(flags() & ios::fixed))
723 prec = 6; /* default */
725 #if _G_HAVE_PRINTF_FP
726 // Do actual conversion.
727 struct printf_info info = { /* prec: */ prec,
728 /* width: */ width(0),
729 /* spec: */ format_char,
730 /* is_long_double: */ 1,
733 /* alt: */ (flags() & ios::showpoint) != 0,
735 /* left: */ (flags() & ios::left) != 0,
736 /* showsign: */ (flags() & ios::showpos) != 0,
738 #if defined __GLIBC__ && __GLIBC__ >= 2
744 const void *ptr = (const void *) &n;
746 if (__printf_fp (rdbuf(), &info, &ptr) < 0)
747 set (ios::badbit|ios::failbit);
749 # error "long double I/O using dtoa or cvt_double is not implemented"
752 _IO_cleanup_region_end (0);
758 ostream& ostream::operator<<(const char *s)
762 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
768 // FIXME: Should we: if (w && len>w) len = w;
769 char fill_char = fill();
770 register streambuf *sbuf = rdbuf();
771 register int padding = w > len ? w - len : 0;
772 if (!(flags() & ios::left) && padding > 0) // Default adjustment.
773 if (_IO_padn(sbuf, fill_char, padding) != padding)
778 if (_IO_sputn (sbuf, s, len) != len)
783 if (flags() & ios::left && padding > 0) // Left adjustment.
784 if (_IO_padn(sbuf, fill_char, padding) != padding)
788 _IO_cleanup_region_end (0);
794 ostream& ostream::operator<<(const void *p)
795 { Is in osform.cc, to avoid pulling in all of _IO_vfprintf by this file. */ }
798 ostream& ostream::operator<<(register streambuf* sbuf)
802 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
804 char buffer[_IO_BUFSIZ];
805 register streambuf* outbuf = _strbuf;
808 _IO_size_t count = _IO_sgetn(sbuf, buffer, _IO_BUFSIZ);
811 if (_IO_sputn(outbuf, buffer, count) != count)
818 _IO_cleanup_region_end (0);
823 ostream::ostream(streambuf* sb, ostream* tied)
828 ostream& ostream::seekp(streampos pos)
830 pos = _strbuf->pubseekpos(pos, ios::out);
831 if (pos == streampos(EOF))
836 ostream& ostream::seekp(streamoff off, _seek_dir dir)
838 streampos pos = _IO_seekoff (_strbuf, off, (int) dir, _IOS_OUTPUT);
839 if (pos == streampos(EOF))
844 streampos ostream::tellp()
847 streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_OUTPUT);
849 streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::out);
851 if (pos == streampos(EOF))
856 ostream& ostream::flush()
863 ostream& flush(ostream& outs)
868 istream& ws(istream& ins)
871 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
873 int ch = skip_ws(ins._strbuf);
875 ins.set(ios::eofbit);
877 ins._strbuf->sputbackc(ch);
879 _IO_cleanup_region_end (0);
884 // Skip white-space. Return 0 on failure (EOF), or 1 on success.
885 // Differs from ws() manipulator in that failbit is set on EOF.
886 // Called by ipfx() and ipfx0() if needed.
888 int istream::_skip_ws()
890 int ch = skip_ws(_strbuf);
892 set(ios::eofbit|ios::failbit);
896 _strbuf->sputbackc(ch);
901 ostream& ends(ostream& outs)
907 ostream& endl(ostream& outs)
909 return flush(outs.put('\n'));
912 istream& lock(istream& ins)
914 _IO_flockfile (ins._strbuf);
917 istream& unlock(istream& ins)
919 _IO_funlockfile (ins._strbuf);
922 ostream& lock(ostream& outs)
924 _IO_flockfile (outs._strbuf);
927 ostream& unlock(ostream& outs)
929 _IO_funlockfile (outs._strbuf);
934 ostream& ostream::write(const char *s, streamsize n)
937 _IO_cleanup_region_start ((void (*) __P ((void *))) _IO_funlockfile,
939 if (_IO_sputn(_strbuf, s, n) != n)
942 _IO_cleanup_region_end (0);
947 void ostream::do_osfx()
949 if (flags() & ios::unitbuf)
951 if (flags() & ios::stdio) {
957 iostream::iostream(streambuf* sb, ostream* tied)
962 // NOTE: extension for compatibility with old libg++.
963 // Not really compatible with fistream::close().
964 #ifdef _STREAM_COMPAT
967 if (_strbuf->_flags & _IO_IS_FILEBUF)
968 ((struct filebuf*)rdbuf())->close();
969 else if (_strbuf != NULL)
975 int istream::skip(int i)
977 int old = (_flags & ios::skipws) != 0;
979 _flags |= ios::skipws;
981 _flags &= ~ios::skipws;