home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / g__~1 / gplibs17.zoo / iostream.cc < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-02  |  16.2 KB  |  762 lines

  1. //    This is part of the iostream library, providing input/output for C++.
  2. //    Copyright (C) 1991, 1992 Per Bothner.
  3. //
  4. //    This library is free software; you can redistribute it and/or
  5. //    modify it under the terms of the GNU Library General Public
  6. //    License as published by the Free Software Foundation; either
  7. //    version 2 of the License, or (at your option) any later version.
  8. //
  9. //    This library is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. //    Library General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU Library General Public
  15. //    License along with this library; if not, write to the Free
  16. //    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #ifdef __GNUG__
  19. #pragma implementation
  20. #endif
  21. #define _STREAM_COMPAT
  22. #include <ioprivat.h>
  23. #include <iostream.h>
  24. #include <stdio.h>  /* Needed for sprintf */
  25. #include <ctype.h>
  26. #include <limits.h>
  27. #include <floatio.h>
  28.  
  29. #define    BUF        (MAXEXP+MAXFRACT+1)    /* + decimal point */
  30.  
  31. //#define isspace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n')
  32.  
  33. istream::istream(streambuf *sb, ostream* tied) : ios(sb, tied)
  34. {
  35.     _flags |= ios::dont_close;
  36.     _gcount = 0;
  37. }
  38.  
  39. int skip_ws(streambuf* sb)
  40. {
  41.     int ch;
  42.     for (;;) {
  43.     ch = sb->sbumpc();
  44.     if (ch == EOF || !isspace(ch))
  45.         return ch;
  46.     }
  47. }
  48.  
  49. istream& istream::get(char& c)
  50. {
  51.     if (ipfx1()) {
  52.     int ch = _strbuf->sbumpc();
  53.     if (ch == EOF) set(ios::eofbit|ios::failbit);
  54.     else c = (char)ch;
  55.     }
  56.     return *this;
  57. }
  58.  
  59. istream& istream::ignore(_G_size_t n1 /* = 1 */, int delim /* = EOF */)
  60. {
  61.     long n = n1;
  62.     if (ipfx1()) {
  63.     register streambuf* sb = _strbuf;
  64.     if (delim == EOF) {
  65.         _gcount = sb->ignore(n);
  66.         return *this;
  67.     }
  68.     _gcount = 0;
  69.     for (;;) {
  70. #if 0
  71.         if (n != MAXINT) // FIXME
  72. #endif
  73.         if (--n < 0)
  74.         break;
  75.         int ch = sb->sbumpc();
  76.         if (ch == EOF) {
  77.         set(ios::eofbit|ios::failbit);
  78.         break;
  79.         }
  80.         _gcount++;
  81.         if (ch == delim)
  82.         break;
  83.     }
  84.     }
  85.     return *this;
  86. }
  87.  
  88. istream& istream::read(char *s, _G_size_t n)
  89. {
  90.     if (ipfx1()) {
  91.     _gcount = _strbuf->sgetn(s, n);
  92.     if (_gcount != n)
  93.         set(ios::failbit);
  94.     }
  95.     return *this;
  96. }
  97.  
  98. istream& istream::seekg(streampos pos)
  99. {
  100.     pos = _strbuf->seekpos(pos, ios::in);
  101.     if (pos == streampos(EOF))
  102.     set(ios::badbit);
  103.     return *this;
  104. }
  105.  
  106. istream& istream::seekg(streamoff off, _seek_dir dir)
  107. {
  108.     streampos pos = _strbuf->seekoff(off, dir, ios::in);
  109.     if (pos == streampos(EOF))
  110.     set(ios::badbit);
  111.     return *this;
  112. }
  113.  
  114. streampos istream::tellg()
  115. {
  116.     streampos pos = _strbuf->seekoff(0, ios::cur, ios::in);
  117.     if (pos == streampos(EOF))
  118.     set(ios::badbit);
  119.     return pos;
  120. }
  121.  
  122. istream& istream::scan(const char *format ...)
  123. {
  124.     if (ipfx0()) {
  125.     va_list ap;
  126.     va_start(ap, format);
  127.     _strbuf->vscan(format, ap, this);
  128.     va_end(ap);
  129.     }
  130.     return *this;
  131. }
  132.  
  133. istream& istream::vscan(const char *format, _G_va_list args)
  134. {
  135.     if (ipfx0())
  136.     _strbuf->vscan(format, args, this);
  137.     return *this;
  138. }
  139.  
  140. istream& istream::operator>>(char& c)
  141. {
  142.     if (ipfx0()) {
  143.     int ch = _strbuf->sbumpc();
  144.     if (ch == EOF)
  145.         set(ios::eofbit|ios::failbit);
  146.     else
  147.         c = (char)ch;
  148.     }
  149.     return *this;
  150. }
  151.  
  152. istream& istream::operator>>(char* ptr)
  153. {
  154.     if (ipfx0()) {
  155.     register streambuf* sb = _strbuf;
  156.     int ch = sb->sbumpc();
  157.     if (ch == EOF)
  158.         set(ios::eofbit|ios::failbit);
  159.     else {
  160.         int w = width(0);
  161.         sb->sputbackc(ch);
  162.         for (;;) {
  163.         ch = sb->sbumpc();
  164.         if (ch == EOF) {
  165.             set(ios::eofbit);
  166.             break;
  167.         }
  168.         else if (isspace(ch)) {
  169.             sb->sputbackc(ch);
  170.             break;
  171.         }
  172.         else if (w == 1) {
  173.             set(ios::failbit);
  174.             sb->sputbackc(ch);
  175.             break;
  176.         }
  177.         else *ptr++ = ch;
  178.         w--;
  179.         }
  180.     }
  181.     }
  182.     *ptr = '\0';
  183.     return *this;
  184. }
  185.  
  186. #if defined(__GNUC__) && (!defined(atarist))
  187. #define LONGEST long long
  188. #else
  189. #define LONGEST long
  190. #endif
  191.  
  192. static int read_int(istream& stream, unsigned LONGEST& val, int& neg)
  193. {
  194.     if (!stream.ipfx0())
  195.     return 0;
  196.     register streambuf* sb = stream.rdbuf();
  197.     int base = 10;
  198.     int ndigits = 0;
  199.     register int ch = skip_ws(sb);
  200.     if (ch == EOF)
  201.     goto eof_fail;
  202.     neg = 0;
  203.     if (ch == '+') {
  204.     ch = skip_ws(sb);
  205.     }
  206.     else if (ch == '-') {
  207.     neg = 1;
  208.     ch = skip_ws(sb);
  209.     }
  210.     if (ch == EOF) goto eof_fail;
  211.     if (!(stream.flags() & ios::basefield)) {
  212.     if (ch == '0') {
  213.         ch = sb->sbumpc();
  214.         if (ch == EOF) {
  215.         val = 0;
  216.         return 1;
  217.         }
  218.         if (ch == 'x' || ch == 'X') {
  219.         base = 16;
  220.         ch = sb->sbumpc();
  221.         if (ch == EOF) goto eof_fail;
  222.         }
  223.         else {
  224.         sb->sputbackc(ch);
  225.         base = 8;
  226.         ch = '0';
  227.         }
  228.     }
  229.     }
  230.     else if ((stream.flags() & ios::basefield) == ios::hex)
  231.     base = 16;
  232.     else if ((stream.flags() & ios::basefield) == ios::oct)
  233.     base = 8;
  234.     val = 0;
  235.     for (;;) {
  236.     if (ch == EOF)
  237.         break;
  238.     int digit;
  239.     if (ch >= '0' && ch <= '9')
  240.         digit = ch - '0';
  241.     else if (ch >= 'A' && ch <= 'F')
  242.         digit = ch - 'A' + 10;
  243.     else if (ch >= 'a' && ch <= 'f')
  244.         digit = ch - 'a' + 10;
  245.     else
  246.         digit = 999;
  247.     if (digit >= base) {
  248.         sb->sputbackc(ch);
  249.         if (ndigits == 0)
  250.         goto fail;
  251.         else
  252.         return 1;
  253.     }
  254.     ndigits++;
  255.     val = base * val + digit;
  256.     ch = sb->sbumpc();
  257.     }
  258.     return 1;
  259.   fail:
  260.     stream.set(ios::failbit);
  261.     return 0;
  262.   eof_fail:
  263.     stream.set(ios::failbit|ios::eofbit);
  264.     return 0;
  265. }
  266.  
  267. #define READ_INT(TYPE) \
  268. istream& istream::operator>>(TYPE& i)\
  269. {\
  270.     unsigned LONGEST val; int neg;\
  271.     if (read_int(*this, val, neg)) {\
  272.     if (neg) val = -val;\
  273.     i = (TYPE)val;\
  274.     }\
  275.     return *this;\
  276. }
  277.  
  278. READ_INT(short)
  279. READ_INT(unsigned short)
  280. READ_INT(int)
  281. READ_INT(unsigned int)
  282. READ_INT(long)
  283. READ_INT(unsigned long)
  284. #ifdef __GNUG__
  285. READ_INT(long long)
  286. READ_INT(unsigned long long)
  287. #endif
  288.  
  289. istream& istream::operator>>(double& x)
  290. {
  291.     if (ipfx0())
  292.     scan("%lg", &x);
  293.     return *this;
  294. }
  295.  
  296. istream& istream::operator>>(float& x)
  297. {
  298.     if (ipfx0())
  299.     scan("%g", &x);
  300.     return *this;
  301. }
  302.  
  303. istream& istream::operator>>(register streambuf* sbuf)
  304. {
  305.     if (ipfx0()) {
  306.     register streambuf* inbuf = rdbuf();
  307.     // FIXME: Should optimize!
  308.     for (;;) {
  309.         register int ch = inbuf->sbumpc();
  310.         if (ch == EOF) {
  311.         set(ios::eofbit);
  312.         break;
  313.         }
  314.         if (sbuf->sputc(ch) == EOF) {
  315.         set(ios::failbit);
  316.         break;
  317.         }
  318.     }
  319.     }
  320.     return *this;
  321. }
  322.  
  323. ostream& ostream::operator<<(char c)
  324. {
  325.     if (opfx()) {
  326.     int w = width(0);
  327.     char fill_char = fill();
  328.     register int padding = w > 0 ? w - 1 : 0;
  329.     register streambuf *sb = _strbuf;
  330.     if (!(flags() & ios::left)) // Default adjustment.
  331.         while (--padding >= 0) sb->sputc(fill_char);
  332.     sb->sputc(c);
  333.     if (flags() & ios::left) // Left adjustment.
  334.         while (--padding >= 0) sb->sputc(fill_char);
  335.     osfx();
  336.     }
  337.     return *this;
  338. }
  339.  
  340. /* Write VAL on STREAM.
  341.    If SIGN<0, val is the absolute value of a negative number.
  342.    If SIGN>0, val is a signed non-negative number.
  343.    If SIGN==0, val is unsigned. */
  344.  
  345. static void write_int(ostream& stream, unsigned LONGEST val, int sign)
  346. {
  347. #define WRITE_BUF_SIZE (10 + sizeof(unsigned LONGEST) * 3)
  348.     char buf[WRITE_BUF_SIZE];
  349.     register char *buf_ptr = buf+WRITE_BUF_SIZE; // End of buf.
  350.     char *show_base = "";
  351.     int show_base_len = 0;
  352.     int show_pos = 0; // If 1, print a '+'.
  353.  
  354.     // Now do the actual conversion, placing the result at the *end* of buf.
  355.     // Note that we use separate code for decimal, octal, and hex,
  356.     // so we can divide by optimizable constants.
  357.     if ((stream.flags() & ios::basefield) == ios::oct) { // Octal
  358.     if ((stream.flags() & ios::showbase) && (val != 0))
  359.         show_base = "0", show_base_len = 1;
  360.     do {
  361.         *--buf_ptr = (val & 7) + '0';
  362.         val = val >> 3;
  363.     } while (val != 0);
  364.     }
  365.     else if ((stream.flags() & ios::basefield) == ios::hex) { // Hex
  366.     char *xdigs = (stream.flags() & ios::uppercase) ? "0123456789ABCDEF0X"
  367.         : "0123456789abcdef0x";
  368.     do {
  369.         *--buf_ptr = xdigs[val & 15];
  370.         val = val >> 4;
  371.     } while (val != 0);
  372.     if (stream.flags() & ios::showbase) {
  373.         show_base = xdigs + 16; // Either "0X" or "0x".
  374.         show_base_len = 2;
  375.     }
  376.     }
  377.     else { // Decimal
  378.     if (val != 0 && sign > 0 && (stream.flags() & ios::showpos))
  379.         show_pos=1;
  380. #ifdef __GNUC__
  381.     // Optimization:  Only use long long when we need to.
  382.     while (val > UINT_MAX) {
  383.         *--buf_ptr = (val % 10) + '0';
  384.         val /= 10;
  385.     }
  386.     // Use more efficient (int) arithmetic for the rest.
  387.     register unsigned int ival = (unsigned int)val;
  388. #else
  389.     register unsigned LONGEST ival = val;
  390. #endif
  391.     do {
  392.         *--buf_ptr = (ival % 10) + '0';
  393.         ival /= 10;
  394.     } while (ival != 0);
  395.     }
  396.  
  397.     _G_size_t buf_len = buf+WRITE_BUF_SIZE - buf_ptr;
  398.     int w = stream.width(0);
  399.  
  400.     // Calculate padding.
  401.     _G_size_t len = buf_len+show_pos;
  402.     if (sign < 0) len++;
  403.     len += show_base_len;
  404.     _G_size_t padding = len > w ? 0 : w - len;
  405.  
  406.     // Do actual output.
  407.     register streambuf* sbuf = stream.rdbuf();
  408.     ios::fmtflags pad_kind =
  409.     stream.flags() & (ios::left|ios::right|ios::internal);
  410.     char fill_char = stream.fill();
  411.     if (padding > 0
  412.     && pad_kind != (ios::fmtflags)ios::left
  413.     && pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust.
  414.     sbuf->padn(fill_char, padding);
  415.     if (sign < 0) sbuf->sputc('-');
  416.     else if (show_pos) sbuf->sputc('+');
  417.     if (show_base_len)
  418.     sbuf->sputn(show_base, show_base_len);
  419.     if (pad_kind == (ios::fmtflags)ios::internal && padding > 0)
  420.     sbuf->padn(fill_char, padding);
  421.     sbuf->sputn(buf_ptr, buf_len);
  422.     if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment
  423.     sbuf->padn(fill_char, padding);
  424.     stream.osfx();
  425. }
  426.  
  427. ostream& ostream::operator<<(int n)
  428. {
  429.     if (opfx()) {
  430.     int sign = 1;
  431.     if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
  432.         n = -n, sign = -1;
  433.     write_int(*this, n, sign);
  434.     }
  435.     return *this;
  436. }
  437.  
  438. ostream& ostream::operator<<(unsigned int n)
  439. {
  440.     if (opfx())
  441.     write_int(*this, n, 0);
  442.     return *this;
  443. }
  444.  
  445.  
  446. ostream& ostream::operator<<(long n)
  447. {
  448.     if (opfx()) {
  449.     int sign = 1;
  450.     if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
  451.         n = -n, sign = -1;
  452.     write_int(*this, n, sign);
  453.     }
  454.     return *this;
  455. }
  456.  
  457. ostream& ostream::operator<<(unsigned long n)
  458. {
  459.     if (opfx())
  460.     write_int(*this, n, 0);
  461.     return *this;
  462. }
  463.  
  464. #ifdef __GNUG__
  465. ostream& ostream::operator<<(long long n)
  466. {
  467.     if (opfx()) {
  468.     int sign = 1;
  469.     if (n < 0 && (flags() & (ios::oct|ios::hex)) == 0)
  470.         n = -n, sign = -1;
  471.     write_int(*this, n, sign);
  472.     }
  473.     return *this;
  474. }
  475.  
  476.  
  477. ostream& ostream::operator<<(unsigned long long n)
  478. {
  479.     if (opfx())
  480.     write_int(*this, n, 0);
  481.     return *this;
  482. }
  483. #endif /*__GNUG__*/
  484.  
  485. ostream& ostream::operator<<(double n)
  486. {
  487.     if (opfx()) {
  488.     // Uses __cvt_double (renamed from static cvt), in Chris Torek's
  489.     // stdio implementation.  The setup code uses the same logic
  490.     // as in __vsbprintf.C (also based on Torek's code).
  491.     int format_char;
  492. #if 0
  493.     if (flags() ios::showpos) sign = '+';
  494. #endif
  495.     if ((flags() & ios::floatfield) == ios::fixed)
  496.         format_char = 'f';
  497.     else if ((flags() & ios::floatfield) == ios::scientific)
  498.         format_char = flags() & ios::uppercase ? 'E' : 'e';
  499.     else
  500.         format_char = flags() & ios::uppercase ? 'G' : 'g';
  501.  
  502.     int fpprec = 0; // 'Extra' (suppressed) floating precision.
  503.     int prec = precision();
  504.     if (prec < 0) prec = 6; // default.
  505.     else if (prec > MAXFRACT) {
  506.         if (flags() & (ios::fixed|ios::scientific) & ios::showpos)
  507.         fpprec = prec - MAXFRACT;
  508.         prec = MAXFRACT;
  509.     }
  510.  
  511.     // Do actual conversion.
  512. #ifdef USE_DTOA
  513.     if (__outfloat(n, rdbuf(), format_char, width(0),
  514.                precision(), flags(), 0, fill()) < 0)
  515.         set(ios::badbit|ios::failbit); // ??
  516. #else
  517.     int negative;
  518.     char buf[BUF];
  519.     int sign = '\0';
  520.     char *cp = buf;
  521.     *cp = 0;
  522.     int size = __cvt_double(n, precision(),
  523.                 flags() & ios::showpoint ? 0x80 : 0,
  524.                 &negative,
  525.                 format_char, cp, buf + sizeof(buf));
  526.     if (negative) sign = '-';
  527.     if (*cp == 0)
  528.         cp++;
  529.  
  530.     // Calculate padding.
  531.     int fieldsize = size + fpprec;
  532.     if (sign) fieldsize++;
  533.     int padding = 0;
  534.     int w = width(0);
  535.     if (fieldsize < w)
  536.         padding = w - fieldsize;
  537.  
  538.     // Do actual output.
  539.     register streambuf* sbuf = rdbuf();
  540.     register i;
  541.     char fill_char = fill();
  542.     ios::fmtflags pad_kind =
  543.         flags() & (ios::left|ios::right|ios::internal);
  544.     if (pad_kind != (ios::fmtflags)ios::left // Default (right) adjust.
  545.         && pad_kind != (ios::fmtflags)ios::internal)
  546.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  547.     if (sign)
  548.         sbuf->sputc(sign);
  549.     if (pad_kind == (ios::fmtflags)ios::internal)
  550.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  551.     
  552.     // Emit the actual concented field, followed by extra zeros.
  553.     sbuf->sputn(cp, size);
  554.     for (i = fpprec; --i >= 0; ) sbuf->sputc('0');
  555.  
  556.     if (pad_kind == (ios::fmtflags)ios::left) // Left adjustment
  557.         for (i = padding; --i >= 0; ) sbuf->sputc(fill_char);
  558. #endif
  559.     osfx();
  560.     }
  561.     return *this;
  562. }
  563.  
  564. ostream& ostream::operator<<(const char *s)
  565. {
  566.     if (opfx()) {
  567.     if (s == NULL)
  568.         s = "(null)";
  569.     _G_size_t len = strlen(s);
  570.     int w = width(0);
  571.     char fill_char = fill();
  572.     register streambuf *sbuf = rdbuf();
  573.     register int padding = w > len ? w - len : 0;
  574.     if (!(flags() & ios::left)) // Default adjustment.
  575.         while (--padding >= 0) sbuf->sputc(fill_char);
  576.     sbuf->sputn(s, len);
  577.     if (flags() & ios::left) // Left adjustment.
  578.         while (--padding >= 0) sbuf->sputc(fill_char);
  579.     osfx();
  580.     }
  581.     return *this;
  582. }
  583.  
  584. ostream& ostream::operator<<(void *p)
  585. {
  586.     if (opfx()) {
  587.     form("%p", p);
  588.     osfx();
  589.     }
  590.     return *this;
  591. }
  592.  
  593. ostream& ostream::operator<<(register streambuf* sbuf)
  594. {
  595.     if (opfx()) {
  596.     register streambuf* outbuf = rdbuf();
  597.     // FIXME: Should optimize!
  598.     for (;;) {
  599.         register int ch = sbuf->sbumpc();
  600.         if (ch == EOF) break;
  601.         if (outbuf->sputc(ch) == EOF) {
  602.         set(ios::badbit);
  603.         break;
  604.         }
  605.     }
  606.     osfx();
  607.     }
  608.     return *this;
  609. }
  610.  
  611. ostream::ostream(streambuf* sb, ostream* tied) : ios(sb, tied)
  612. {
  613.     _flags |= ios::dont_close;
  614. }
  615.  
  616. ostream& ostream::seekp(streampos pos)
  617. {
  618.     pos = _strbuf->seekpos(pos, ios::out);
  619.     if (pos == streampos(EOF))
  620.     set(ios::badbit);
  621.     return *this;
  622. }
  623.  
  624. ostream& ostream::seekp(streamoff off, _seek_dir dir)
  625. {
  626.     streampos pos = _strbuf->seekoff(off, dir, ios::out);
  627.     if (pos == streampos(EOF))
  628.     set(ios::badbit);
  629.     return *this;
  630. }
  631.  
  632. streampos ostream::tellp()
  633. {
  634.     streampos pos = _strbuf->seekoff(0, ios::cur, ios::out);
  635.     if (pos == streampos(EOF))
  636.     set(ios::badbit);
  637.     return pos;
  638. }
  639.  
  640. ostream& ostream::form(const char *format ...)
  641. {
  642.     if (opfx()) {
  643.     va_list ap;
  644.     va_start(ap, format);
  645.     _strbuf->vform(format, ap);
  646.     va_end(ap);
  647.     }
  648.     return *this;
  649. }
  650.  
  651. ostream& ostream::vform(const char *format, _G_va_list args)
  652. {
  653.     if (opfx())
  654.     _strbuf->vform(format, args);
  655.     return *this;
  656. }
  657.  
  658. ostream& ostream::flush()
  659. {
  660.     if (_strbuf->sync())
  661.     set(ios::badbit);
  662.     return *this;
  663. }
  664.  
  665. ostream& flush(ostream& outs)
  666. {
  667.     outs.rdbuf()->overflow(EOF);
  668.     return outs;
  669. }
  670.  
  671. istream& ws(istream& ins)
  672. {
  673.     if (ins.ipfx1()) {
  674.     int ch = skip_ws(ins._strbuf);
  675.     if (ch == EOF)
  676.         ins.set(ios::eofbit);
  677.     else
  678.         ins._strbuf->sputbackc(ch);
  679.     }
  680.     return ins;
  681. }
  682.  
  683. // Skip white-space.  Return 0 on failure (EOF), or 1 on success.
  684. // Differs from ws() manipulator in that failbit is set on EOF.
  685. // Called by ipfx() and ipfx0() if needed.
  686.  
  687. int istream::_skip_ws()
  688. {
  689.     int ch = skip_ws(_strbuf);
  690.     if (ch == EOF) {
  691.     set(ios::eofbit|ios::failbit);
  692.     return 0;
  693.     }
  694.     else {
  695.     _strbuf->sputbackc(ch);
  696.     return 1;
  697.     }
  698. }
  699.  
  700. ostream& ends(ostream& outs)
  701. {
  702.     outs.put(0);
  703.     return outs;
  704. }
  705.  
  706. ostream& endl(ostream& outs)
  707. {
  708.     return flush(outs.put('\n'));
  709. }
  710.  
  711. ostream& ostream::write(const char *s, _G_size_t n)
  712. {
  713.     if (opfx()) {
  714.     if (_strbuf->sputn(s, n) != n)
  715.         set(ios::failbit);
  716.     }
  717.     return *this;
  718. }
  719.  
  720. void ostream::do_osfx()
  721. {
  722.     if (flags() & ios::unitbuf)
  723.     flush();
  724.     if (flags() & ios::stdio) {
  725.     fflush(stdout);
  726.     fflush(stderr);
  727.     }
  728. }
  729.  
  730. iostream::iostream(streambuf* sb, ostream* tied) : ios(sb, tied)
  731. {
  732.     _flags |= ios::dont_close;
  733.     _gcount = 0;
  734. }
  735.  
  736. // NOTE: extension for compatibility with old libg++.
  737. // Not really compatible with fistream::close().
  738. #ifdef _STREAM_COMPAT
  739. void ios::close()
  740. {
  741.     if (!(_flags & (unsigned int)ios::dont_close))
  742.     delete _strbuf;
  743.     else if (_strbuf->_flags & _S_IS_FILEBUF)
  744.     ((struct filebuf*)_strbuf)->close();
  745.     else if (_strbuf != NULL)
  746.     _strbuf->sync();
  747.     _flags |= ios::dont_close;
  748.     _strbuf = NULL;
  749.     _state = badbit;
  750. }
  751.  
  752. int istream::skip(_G_size_t i)
  753. {
  754.     int old = (_flags & ios::skipws) != 0;
  755.     if (i)
  756.     _flags |= ios::skipws;
  757.     else
  758.     _flags &= ~ios::skipws;
  759.     return old;
  760. }
  761. #endif
  762.