home *** CD-ROM | disk | FTP | other *** search
- /***
- *stdiostr.cpp -
- *
- * Copyright (c) 1991-1997, Microsoft Corporation. All rights reserved.
- *
- *Purpose:
- *
- *******************************************************************************/
-
- #include <cruntime.h>
- #include <internal.h>
- #include <string.h>
- #include <stdiostr.h>
- #include <dbgint.h>
- #pragma hdrstop
-
- extern "C" {
- #include <file2.h>
- #include <msdos.h>
- }
- #include <dos.h>
-
- stdiobuf::stdiobuf(FILE * f)
- : streambuf()
- {
- unbuffered(1); // initially unbuffered
- _str = f;
- }
-
- stdiobuf::~stdiobuf()
- // : ~streambuf()
- {
- stdiobuf::sync(); // make sure buffer flushed
- }
-
- int stdiobuf::setrwbuf(int readsize, int writesize)
- {
- char * tbuf;
- unbuffered(!(readsize+writesize));
- if (unbuffered())
- return(0);
-
- tbuf = _new_crt char[(readsize+writesize)];
- if (!tbuf)
- return(EOF);
-
- setb( tbuf, tbuf + (readsize+writesize), 1);
-
- if (readsize)
- {
- setg(base(),base()+readsize,base()+readsize);
- }
- else
- {
- setg(0,0,0);
- }
-
- if (writesize)
- {
- setp(base()+readsize,ebuf());
- }
- else
- {
- setp(0,0);
- }
-
- return(1);
- }
-
- int stdiobuf::overflow(int c) {
- long count, nout;
- if (allocate()==EOF) // make sure there is a reserve area
- return EOF;
- if (!unbuffered() && epptr())
- {
- if ((count = pptr() - pbase()) > 0)
- {
- nout=fwrite((void *) pbase(), 1, (int)count, _str);
- pbump(-(int)nout);
- if (nout != count)
- {
- memmove(pbase(),pbase()+nout,(int)(count-nout));
- return(EOF);
- }
- }
- }
- if ((!unbuffered()) && (!epptr()))
- setp(base()+(blen()>>1),ebuf());
- if (c!=EOF)
- {
- if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion
- sputc(c);
- else
- return fputc(c, _str);
- }
- return(1); // return something other than EOF if successful
- }
-
- int stdiobuf::underflow()
- {
- int count;
- if (allocate()==EOF) // make sure there is a reserve area
- return EOF;
- if ((!unbuffered()) && (!egptr()))
- setg(base(),(base()+(blen()>>1)),(base()+(blen()>>1)));
-
- if (unbuffered() || (!egptr()))
- return fgetc(_str);
- if (gptr() >= egptr())
- // buffer empty, try for more
- {
- if (!(count = fread((void *)eback(), 1, (size_t)(egptr()-eback()), _str)))
- return(EOF); // reach EOF, nothing read
- setg(eback(),(egptr()-count),egptr()); // _gptr = _egptr - count
- if (gptr()!=eback())
- {
- memmove(gptr(), eback(), count); // overlapping memory!
- }
- }
- return sbumpc();
- }
-
- streampos stdiobuf::seekoff(streamoff off, ios::seek_dir dir, int)
- {
-
- int fdir;
- long retpos;
- switch (dir) {
- case ios::beg :
- fdir = SEEK_SET;
- break;
- case ios::cur :
- fdir = SEEK_CUR;
- break;
- case ios::end :
- fdir = SEEK_END;
- break;
- default:
- // error
- return(EOF);
- }
-
- stdiobuf::overflow(EOF);
- if (fseek(_str, off, fdir))
- return (EOF);
- if ((retpos=ftell(_str))==-1L)
- return(EOF);
- return((streampos)retpos);
- }
-
- int stdiobuf::pbackfail(int c)
- {
- if (eback()<gptr()) return sputbackc((char)c);
-
- if (stdiobuf::seekoff( -1, ios::cur, ios::in)==EOF)
- return EOF;
- if (!unbuffered() && egptr())
- {
- memmove((gptr()+1),gptr(),(egptr()-(gptr()+1)));
- *gptr()=(char)c;
- }
- return(c);
- }
-
- int stdiobuf::sync()
- {
- long count;
- char * p;
- char flags;
- if (!unbuffered())
- {
- if (stdiobuf::overflow(EOF)==EOF)
- return(EOF);
- if ((count=in_avail())>0)
- {
- #ifdef _WIN32
- flags = _osfile_safe(_fileno(_str));
- #else /* _WIN32 */
- flags = _osfile[_fileno(_str)];
- #endif /* _WIN32 */
- if (flags & FTEXT)
- {
- // If text mode, need to account for CR/LF etc.
- for (p = gptr(); p < egptr(); p++)
- if (*p == '\n')
- count++;
-
- // account for EOF if read, not counted by _read
- if (_str->_flag & _IOCTRLZ)
- count++;
- }
- if (stdiobuf::seekoff( -count, ios::cur, ios::in)==EOF)
- return(EOF);
-
- setg(eback(),egptr(),egptr()); // empty get area (_gptr = _egptr;)
- }
- }
- return(0);
- }
-
- stdiostream::stdiostream(FILE * file)
- : iostream(_new_crt stdiobuf(file))
- {
- istream::delbuf(1);
- ostream::delbuf(1);
- }
-
- stdiostream::~stdiostream()
- {
- }
-
- // include here for better granularity
-
- int ios::sunk_with_stdio = 0;
-
- void ios::sync_with_stdio()
- {
- if (!sunk_with_stdio) // first time only
- {
- cin = _new_crt stdiobuf(stdin);
- cin.delbuf(1);
- cin.setf(ios::stdio);
-
- cout = _new_crt stdiobuf(stdout);
- cout.delbuf(1);
- cout.setf(ios::stdio|ios::unitbuf);
- ((stdiobuf*)(cout.rdbuf()))->setrwbuf(0,80);
-
- cerr = _new_crt stdiobuf(stderr);
- cerr.delbuf(1);
- cerr.setf(ios::stdio|ios::unitbuf);
- ((stdiobuf*)(cerr.rdbuf()))->setrwbuf(0,80);
-
- clog = _new_crt stdiobuf(stderr);
- clog.delbuf(1);
- clog.setf(ios::stdio);
- ((stdiobuf*)(clog.rdbuf()))->setrwbuf(0,BUFSIZ);
-
- sunk_with_stdio++;
- }
- }
-