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

  1. /***
  2. *streamb.cpp - fuctions for streambuf class.
  3. *
  4. *       Copyright (c) 1990-1997, Microsoft Corporation.  All rights reserved.
  5. *
  6. *Purpose:
  7. *       Functions for streambuf class.
  8. *
  9. *******************************************************************************/
  10.  
  11. #include <cruntime.h>
  12. #include <internal.h>
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <iostream.h>
  16. #include <dbgint.h>
  17. #pragma hdrstop
  18.  
  19.  
  20. #ifndef BUFSIZ
  21. #define BUFSIZ 512
  22. #endif  /* BUFSIZ */
  23.  
  24. /***
  25. *streambuf::streambuf() -
  26. *
  27. *Purpose:
  28. *       Default constructor.
  29. *
  30. *Entry:
  31. *
  32. *Exit:
  33. *
  34. *Exceptions:
  35. *
  36. *******************************************************************************/
  37.  
  38. streambuf::streambuf()
  39. {
  40.     _fAlloc = 0;
  41.     _fUnbuf = 0;
  42.     x_lastc = EOF;
  43.     _base = NULL;
  44.     _ebuf = NULL;
  45.     _pbase = NULL;
  46.     _pptr = NULL;
  47.     _epptr = NULL;
  48.     _eback = NULL;
  49.     _gptr = NULL;
  50.     _egptr = NULL;
  51.  
  52. #ifdef _MT
  53.     LockFlg = -1;               // default is now : locking
  54.     _mtlockinit(lockptr());
  55. #endif  /* _MT */
  56.  
  57. }
  58.  
  59. /***
  60. *streambuf::streambuf(char* pBuf, int cbBuf) -
  61. *
  62. *Purpose:
  63. *       Constructor which specifies a buffer area.
  64. *
  65. *Entry:
  66. *
  67. *Exit:
  68. *
  69. *Exceptions:
  70. *
  71. *******************************************************************************/
  72.  
  73. streambuf::streambuf( char* pBuf, int cbBuf )
  74. {
  75.     _fAlloc = 0;
  76.     _fUnbuf = 0;
  77.     x_lastc = EOF;
  78.     _base = pBuf;
  79.     _ebuf = pBuf + (unsigned)cbBuf;
  80.     _pbase = NULL;
  81.     _pptr = NULL;
  82.     _epptr = NULL;
  83.     _eback = NULL;
  84.     _gptr = NULL;
  85.     _egptr = NULL;
  86.  
  87.     if( pBuf == NULL || cbBuf == 0 ){
  88.         _fUnbuf = 1;
  89.         _base = NULL;
  90.         _ebuf = NULL;
  91.     }
  92.  
  93. #ifdef _MT
  94.     LockFlg = -1;               // default is now : locking
  95.     _mtlockinit(lockptr());
  96. #endif  /* _MT */
  97.  
  98. }
  99.  
  100.  
  101. /***
  102. *virtual streambuf::~streambuf() -
  103. *
  104. *Purpose:
  105. *       Destructor.
  106. *
  107. *Entry:
  108. *
  109. *Exit:
  110. *
  111. *Exceptions:
  112. *
  113. *******************************************************************************/
  114.  
  115. streambuf::~streambuf()
  116. {
  117. #ifdef _MT
  118.     _mtlockterm(lockptr());
  119. #endif  /* _MT */
  120.  
  121.     sync();     // make sure buffer empty before possibly destroying it
  122.     if( (_fAlloc) && (_base) )
  123.         delete _base;
  124. }
  125.  
  126.  
  127. /***
  128. * virtual streambuf * streambuf::setbuf(char * p, int len) -
  129. *
  130. *Purpose:
  131. *       Offers the array at p with len bytes to be used as a reserve area.
  132. *
  133. *Entry:
  134. *
  135. *Exit:
  136. *
  137. *Exceptions:
  138. *
  139. *******************************************************************************/
  140.  
  141. streambuf * streambuf::setbuf(char * p, int len)
  142. {
  143.     if (!_base)
  144.         {
  145.         if ((!p) || (!len))
  146.             _fUnbuf = 1;        // mark as unbuffered
  147.         else
  148.             {
  149.             _base = p;
  150.             _ebuf = p + (unsigned)len;
  151.             _fUnbuf = 0;
  152.             }
  153.         return (this);
  154.         }
  155.     return((streambuf *)NULL);
  156. }
  157.  
  158.  
  159. /***
  160. *virtual int streambuf::xsputn( char* pBuf, int cbBuf ) -
  161. *
  162. *Purpose:
  163. *       Tries to output cbBuf characters.  Returns number of characters
  164. *       that were outputted.
  165. *
  166. *Entry:
  167. *
  168. *Exit:
  169. *
  170. *Exceptions:
  171. *
  172. *******************************************************************************/
  173.  
  174. int streambuf::xsputn( const char* pBuf, int cbBuf )
  175. {
  176.     int cbOut;
  177.  
  178.     for (cbOut = 0; cbBuf--; cbOut++)
  179.         {
  180.         if ((_fUnbuf) || (_pptr >= _epptr))
  181.             {
  182.             if (overflow((unsigned char)*pBuf)==EOF)    // 0-extend 0xFF !=EOF
  183.                 break;
  184.             }
  185.         else
  186.             {
  187.             *(_pptr++) = *pBuf;
  188.             }
  189.         pBuf++;
  190.         }
  191.     return cbOut;
  192. }
  193.  
  194. /***
  195. *virtual int streambuf::xsgetn( char* pBuf, int cbBuf ) -
  196. *
  197. *Purpose:
  198. *       Tries to input cbBuf characters.  Returns number of characters
  199. *       that were read from streambuf.
  200. *
  201. *Entry:
  202. *
  203. *Exit:
  204. *
  205. *Exceptions:
  206. *
  207. *******************************************************************************/
  208.  
  209. // #pragma intrinsic(memcpy,__min)
  210.  
  211. int streambuf::xsgetn( char * pBuf, int cbBuf)
  212. {
  213.     int count;
  214.     int cbIn = 0;
  215.     if (_fUnbuf)
  216.         {
  217.         if (x_lastc==EOF)
  218.             x_lastc=underflow();
  219.  
  220.         while (cbBuf--)
  221.             {
  222.             if (x_lastc==EOF)
  223.                 break;
  224.             *(pBuf++) = (char)x_lastc;
  225.             cbIn++;
  226.             x_lastc=underflow();
  227.             }
  228.         }
  229.     else
  230.         {
  231.         while (cbBuf)
  232.             {
  233.             if (underflow()==EOF)       // make sure something to read
  234.                 break;
  235.             count = __min(egptr() - gptr(),cbBuf);
  236.             if (count>0)
  237.                 {
  238.                 memcpy(pBuf,gptr(),count);
  239.                 pBuf  += count;
  240.                 _gptr += count;
  241.                 cbIn  += count;
  242.                 cbBuf -= count;
  243.                 }
  244.             }
  245.         }
  246.     return cbIn;
  247. }
  248.  
  249. /***
  250. *virtual int streambuf::sync() -
  251. *
  252. *Purpose:
  253. *       Tries to flush all data in put area and give back any data in the
  254. *       get area (if possible), leaving both areas empty on exit.
  255. *       Default behavior is to fail unless buffers empty.
  256. *
  257. *Entry:
  258. *
  259. *Exit:
  260. *
  261. *Exceptions:
  262. *
  263. *******************************************************************************/
  264.  
  265. int streambuf::sync()
  266. {
  267.     if ((gptr() <_egptr) || (_pptr > _pbase))
  268.         {
  269.         return EOF;
  270.         }
  271.     return 0;
  272. }
  273.  
  274. /***
  275. *int streambuf::allocate() -
  276. *
  277. *Purpose:
  278. *       Tries to set up a Reserve Area.  If one already exists, or if
  279. *       unbuffered, just returns 0.
  280. *
  281. *Entry:
  282. *
  283. *Exit:
  284. *
  285. *Exceptions:
  286. *
  287. *******************************************************************************/
  288.  
  289. int streambuf::allocate()
  290. {
  291.     if ((_fUnbuf) || (_base))
  292.         return 0;
  293.     if (doallocate()==EOF) return EOF;
  294.  
  295.     return(1);
  296. }
  297.  
  298. /***
  299. *virtual int streambuf::doallocate() -
  300. *
  301. *Purpose:
  302. *       Tries to set up a Reserve Area.  Returns EOF if unsuccessful.
  303. *
  304. *Entry:
  305. *
  306. *Exit:
  307. *
  308. *Exceptions:
  309. *
  310. *******************************************************************************/
  311.  
  312. int streambuf::doallocate()
  313. {
  314.     char * tptr;
  315.     if (!( tptr = _new_crt char[BUFSIZ]))
  316.         return(EOF);
  317.     setb(tptr, tptr + BUFSIZ, 1);
  318.     return(1);
  319. }
  320.  
  321. /***
  322. *void streambuf::setb(char * b, char * eb, int a = 0) -
  323. *
  324. *Purpose:
  325. *       Sets up reserve area.
  326. *
  327. *Entry:
  328. *
  329. *Exit:
  330. *
  331. *Exceptions:
  332. *
  333. *******************************************************************************/
  334.  
  335. void streambuf::setb(char * b, char * eb, int a )
  336. {
  337.     if ((_fAlloc) && (_base))
  338.         delete _base;
  339.     _base = b;
  340.     _fAlloc = a;
  341.     _ebuf = eb;
  342. }
  343.  
  344. /***
  345. *virtual streampos streambuf::seekoff(streamoff off, ios::seekdir dir, int mode)
  346. *
  347. *Purpose:
  348. *       seekoff member function.  seek forward or backward in the stream.
  349. *       Default behavior: returns EOF.
  350. *
  351. *Entry:
  352. *       off  = offset (+ or -) to seek by
  353. *       dir  = one of ios::beg, ios::end, or ios::cur.
  354. *       mode = ios::in or ios::out.
  355. *
  356. *Exit:
  357. *       Returns new file position or EOF if error or seeking not supported.
  358. *
  359. *Exceptions:
  360. *       Returns EOF if error.
  361. *
  362. *******************************************************************************/
  363. streampos streambuf::seekoff(streamoff,ios::seek_dir,int)
  364. {
  365. return EOF;
  366. }
  367.  
  368. /***
  369. *virtual streampos streambuf::seekpos(streampos pos, int mode) -
  370. *
  371. *Purpose:
  372. *       seekoff member function.  seek to absolute file position.
  373. *       Default behavior: returns seekoff(streamoff(pos), ios::beg, mode).
  374. *
  375. *Entry:
  376. *       pos  = absolute offset to seek to
  377. *       mode = ios::in or ios::out.
  378. *
  379. *Exit:
  380. *       Returns new file position or EOF if error or seeking not supported.
  381. *
  382. *Exceptions:
  383. *       Returns EOF if error.
  384. *
  385. *******************************************************************************/
  386. streampos streambuf::seekpos(streampos pos,int mode)
  387. {
  388. return seekoff(streamoff(pos), ios::beg, mode);
  389. }
  390.  
  391. /***
  392. *virtual int streambuf::pbackfail(int c) - handle failure of putback
  393. *
  394. *Purpose:
  395. *       pbackfail member function.  Handle exception of pback function.
  396. *       Default behavior: returns EOF.  See spec. for details.
  397. *
  398. *       Note: the following implementation gives default behavior, thanks
  399. *       to the default seekoff, but also supports derived classes properly:
  400. *
  401. *Entry:
  402. *       c = character to put back
  403. *
  404. *Exit:
  405. *       Returns c if successful or EOF on error.
  406. *
  407. *Exceptions:
  408. *       Returns EOF if error.  Behavior is undefined if c was not the
  409. *       previous character in the stream.
  410. *
  411. *******************************************************************************/
  412. int streambuf::pbackfail(int c)
  413. {
  414.     if (eback()<gptr()) return sputbackc((char)c);
  415.  
  416.     if (seekoff( -1, ios::cur, ios::in)==EOF)  // always EOF for streambufs
  417.         return EOF;
  418.     if (!unbuffered() && egptr())
  419.         {
  420.         memmove((gptr()+1),gptr(),(egptr()-(gptr()+1)));
  421.         *gptr()=(char)c;
  422.         }
  423.     return(c);
  424. }
  425.