home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / stdiostr.cpp < prev    next >
C/C++ Source or Header  |  1998-06-17  |  6KB  |  242 lines

  1. /***
  2. *stdiostr.cpp -
  3. *
  4. *       Copyright (c) 1991-1997, Microsoft Corporation.  All rights reserved.
  5. *
  6. *Purpose:
  7. *
  8. *******************************************************************************/
  9.  
  10. #include <cruntime.h>
  11. #include <internal.h>
  12. #include <string.h>
  13. #include <stdiostr.h>
  14. #include <dbgint.h>
  15. #pragma hdrstop
  16.  
  17. extern "C" {
  18. #include <file2.h>
  19. #include <msdos.h>
  20. }
  21. #include <dos.h>
  22.  
  23.         stdiobuf::stdiobuf(FILE * f)
  24. : streambuf()
  25. {
  26.         unbuffered(1);                  // initially unbuffered
  27.         _str = f;
  28. }
  29.  
  30.         stdiobuf::~stdiobuf()
  31. // : ~streambuf()
  32. {
  33.         stdiobuf::sync();               // make sure buffer flushed
  34. }
  35.  
  36.         int stdiobuf::setrwbuf(int readsize, int writesize)
  37. {
  38.     char * tbuf;
  39.     unbuffered(!(readsize+writesize));
  40.     if (unbuffered())
  41.         return(0);
  42.  
  43.     tbuf = _new_crt char[(readsize+writesize)];
  44.     if (!tbuf)
  45.         return(EOF);
  46.  
  47.     setb( tbuf, tbuf + (readsize+writesize), 1);
  48.  
  49.     if (readsize)
  50.         {
  51.         setg(base(),base()+readsize,base()+readsize);
  52.         }
  53.     else
  54.         {
  55.         setg(0,0,0);
  56.         }
  57.  
  58.     if (writesize)
  59.         {
  60.         setp(base()+readsize,ebuf());
  61.         }
  62.     else
  63.         {
  64.         setp(0,0);
  65.         }
  66.  
  67.     return(1);
  68. }
  69.  
  70. int stdiobuf::overflow(int c) {
  71.     long count, nout;
  72.     if (allocate()==EOF)        // make sure there is a reserve area
  73.         return EOF;
  74.     if (!unbuffered() && epptr())
  75.         {
  76.         if ((count = pptr() - pbase()) > 0)
  77.             {
  78.             nout=fwrite((void *) pbase(), 1, (int)count, _str);
  79.             pbump(-(int)nout);
  80.             if (nout != count)
  81.                 {
  82.                 memmove(pbase(),pbase()+nout,(int)(count-nout));
  83.                 return(EOF);
  84.                 }
  85.             }
  86.         }
  87.     if ((!unbuffered()) && (!epptr()))
  88.         setp(base()+(blen()>>1),ebuf());
  89.     if (c!=EOF)
  90.         {
  91.         if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion
  92.             sputc(c);
  93.         else
  94.             return fputc(c, _str);
  95.         }
  96.     return(1);  // return something other than EOF if successful
  97. }
  98.  
  99. int stdiobuf::underflow()
  100. {
  101.     int count;
  102.     if (allocate()==EOF)        // make sure there is a reserve area
  103.         return EOF;
  104.     if ((!unbuffered()) && (!egptr()))
  105.         setg(base(),(base()+(blen()>>1)),(base()+(blen()>>1)));
  106.  
  107.     if (unbuffered() || (!egptr()))
  108.         return fgetc(_str);
  109.     if (gptr() >= egptr())
  110. // buffer empty, try for more
  111.     {
  112.     if (!(count = fread((void *)eback(), 1, (size_t)(egptr()-eback()), _str)))
  113.         return(EOF); // reach EOF, nothing read
  114.     setg(eback(),(egptr()-count),egptr());   // _gptr = _egptr - count
  115.     if (gptr()!=eback())
  116.         {
  117.         memmove(gptr(), eback(), count);        // overlapping memory!
  118.         }
  119.     }
  120.     return sbumpc();
  121. }
  122.  
  123. streampos stdiobuf::seekoff(streamoff off, ios::seek_dir dir, int)
  124. {
  125.  
  126.     int fdir;
  127.     long retpos;
  128.     switch (dir) {
  129.         case ios::beg :
  130.             fdir = SEEK_SET;
  131.             break;
  132.         case ios::cur :
  133.             fdir = SEEK_CUR;
  134.             break;
  135.         case ios::end :
  136.             fdir = SEEK_END;
  137.             break;
  138.         default:
  139.         // error
  140.             return(EOF);
  141.         }
  142.  
  143.     stdiobuf::overflow(EOF);
  144.     if (fseek(_str, off, fdir))
  145.         return (EOF);
  146.     if ((retpos=ftell(_str))==-1L)
  147.         return(EOF);
  148.     return((streampos)retpos);
  149. }
  150.  
  151. int stdiobuf::pbackfail(int c)
  152. {
  153.     if (eback()<gptr()) return sputbackc((char)c);
  154.  
  155.     if (stdiobuf::seekoff( -1, ios::cur, ios::in)==EOF)
  156.         return EOF;
  157.     if (!unbuffered() && egptr())
  158.         {
  159.         memmove((gptr()+1),gptr(),(egptr()-(gptr()+1)));
  160.         *gptr()=(char)c;
  161.         }
  162.     return(c);
  163. }
  164.  
  165. int stdiobuf::sync()
  166. {
  167.     long count;
  168.     char * p;
  169.     char flags;
  170.     if (!unbuffered())
  171.         {
  172.         if (stdiobuf::overflow(EOF)==EOF)
  173.             return(EOF);
  174.         if ((count=in_avail())>0)
  175.             {
  176. #ifdef _WIN32
  177.             flags = _osfile_safe(_fileno(_str));
  178. #else  /* _WIN32 */
  179.             flags = _osfile[_fileno(_str)];
  180. #endif  /* _WIN32 */
  181.             if (flags & FTEXT)
  182.                 {
  183.                 // If text mode, need to account for CR/LF etc.
  184.                 for (p = gptr(); p < egptr(); p++)
  185.                     if (*p == '\n')
  186.                         count++;
  187.  
  188.                 // account for EOF if read, not counted by _read
  189.                 if (_str->_flag & _IOCTRLZ)
  190.                     count++;
  191.                 }
  192.             if (stdiobuf::seekoff( -count, ios::cur, ios::in)==EOF)
  193.                 return(EOF);
  194.  
  195.             setg(eback(),egptr(),egptr()); // empty get area (_gptr = _egptr;)
  196.             }
  197.         }
  198.     return(0);
  199. }
  200.  
  201.         stdiostream::stdiostream(FILE * file)
  202. : iostream(_new_crt stdiobuf(file))
  203. {
  204. istream::delbuf(1);
  205. ostream::delbuf(1);
  206. }
  207.  
  208.         stdiostream::~stdiostream()
  209. {
  210. }
  211.  
  212. // include here for better granularity
  213.  
  214. int ios::sunk_with_stdio = 0;
  215.  
  216. void ios::sync_with_stdio()
  217. {
  218.     if (!sunk_with_stdio)       // first time only
  219.         {
  220.         cin = _new_crt stdiobuf(stdin);
  221.         cin.delbuf(1);
  222.         cin.setf(ios::stdio);
  223.  
  224.         cout = _new_crt stdiobuf(stdout);
  225.         cout.delbuf(1);
  226.         cout.setf(ios::stdio|ios::unitbuf);
  227.         ((stdiobuf*)(cout.rdbuf()))->setrwbuf(0,80);
  228.  
  229.         cerr = _new_crt stdiobuf(stderr);
  230.         cerr.delbuf(1);
  231.         cerr.setf(ios::stdio|ios::unitbuf);
  232.         ((stdiobuf*)(cerr.rdbuf()))->setrwbuf(0,80);
  233.  
  234.         clog = _new_crt stdiobuf(stderr);
  235.         clog.delbuf(1);
  236.         clog.setf(ios::stdio);
  237.         ((stdiobuf*)(clog.rdbuf()))->setrwbuf(0,BUFSIZ);
  238.  
  239.         sunk_with_stdio++;
  240.         }
  241. }
  242.