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

  1. /***
  2. *filebuf.cpp - core filebuf member functions
  3. *
  4. *       Copyright (c) 1991-1997, Microsoft Corporation.  All rights reserved.
  5. *
  6. *Purpose:
  7. *       Contains the core member functions for filebuf class.
  8. *
  9. *******************************************************************************/
  10.  
  11. #include <cruntime.h>
  12. #include <internal.h>
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <fcntl.h>
  16. #include <crtdbg.h>
  17. #include <sys\types.h>
  18. #include <io.h>
  19. #include <fstream.h>
  20. #pragma hdrstop
  21.  
  22. #include <msdos.h>
  23. #include <sys\stat.h>
  24.  
  25. const int filebuf::openprot     = 0644;
  26.  
  27. const int filebuf::sh_none      = 04000;        // deny rw
  28. const int filebuf::sh_read      = 05000;        // deny wr
  29. const int filebuf::sh_write     = 06000;        // deny rd
  30.  
  31. const int filebuf::binary       = O_BINARY;
  32. const int filebuf::text         = O_TEXT;
  33.  
  34. /***
  35. *filebuf::filebuf() - filebuf default constructor
  36. *
  37. *Purpose:
  38. *       Default constructor.
  39. *
  40. *Entry:
  41. *
  42. *******************************************************************************/
  43.         filebuf::filebuf()
  44. : streambuf()
  45. {
  46.     x_fOpened = 0;
  47.     x_fd = -1;
  48. }
  49.  
  50.  
  51. /***
  52. *filebuf::filebuf(filedesc fd) - filebuf constructor
  53. *
  54. *Purpose:
  55. *       Constructor.  Initialize filebuf and attach to file descriptor.
  56. *
  57. *Entry:
  58. *       fd = file descriptor to attach to filebuf
  59. *
  60. *******************************************************************************/
  61.         filebuf::filebuf(filedesc fd)
  62. : streambuf()
  63. {
  64.     x_fOpened = 0;
  65.     x_fd=fd;
  66. }
  67.  
  68.  
  69. /***
  70. *filebuf::filebuf(filedesc fd, char* p, int len) - filebuf constructor
  71. *
  72. *Purpose:
  73. *       Constructor.  Initialize filebuf and attach to file descriptor.
  74. *
  75. *Entry:
  76. *       fd  = file descriptor to attach to filebuf
  77. *       p   = user-supplied buffer
  78. *       len = length of buffer
  79. *
  80. *******************************************************************************/
  81.         filebuf::filebuf(filedesc fd, char* p, int len)
  82. :    streambuf()
  83. {
  84.     filebuf::setbuf(p,len);
  85.     x_fOpened = 0;
  86.     x_fd=fd;
  87. }
  88.  
  89.  
  90. /***
  91. *filebuf::~filebuf() - filebuf destructor
  92. *
  93. *Purpose:
  94. *       Destructor.  Close attached file only if we opened it.
  95. *
  96. *Entry:
  97. *       None.
  98. *
  99. *******************************************************************************/
  100.         filebuf::~filebuf()
  101. {
  102.         lock();         // no need to unlock...
  103.         if (x_fOpened)
  104.             close();    // calls filebuf::sync()
  105.         else
  106.             filebuf::sync();
  107. }
  108.  
  109.  
  110. /***
  111. *filebuf* filebuf::close() - close an attached file
  112. *
  113. *Purpose:
  114. *       Close attached file.
  115. *
  116. *Entry:
  117. *       None.
  118. *Exit:
  119. *       Returns NULL if error, otherwise returns "this" pointer.
  120. *
  121. *******************************************************************************/
  122. filebuf* filebuf::close()
  123. {
  124.     int retval;
  125.     if (x_fd==-1)
  126.         return NULL;
  127.  
  128.     lock();
  129.     retval = sync();
  130.  
  131.     if ((_close(x_fd)==-1) || (retval==EOF))
  132.         {
  133.         unlock();
  134.         return NULL;
  135.         }
  136.     x_fd = -1;
  137.     unlock();
  138.     return this;
  139. }
  140.  
  141. /***
  142. *virtual int filebuf::overflow(int c) - overflow virtual function
  143. *
  144. *Purpose:
  145. *       flush any characters in the reserve area and handle 'c'.
  146. *
  147. *Entry:
  148. *       c = character to output (if not EOF)
  149. *
  150. *Exit:
  151. *       Returns EOF if error, otherwise returns something else.
  152. *
  153. *Exceptions:
  154. *       Returns EOF if error.
  155. *
  156. *******************************************************************************/
  157. int filebuf::overflow(int c)
  158. {
  159.     if (allocate()==EOF)        // make sure there is a reserve area
  160.         return EOF;
  161.     if (filebuf::sync()==EOF) // sync before new buffer created below
  162.         return EOF;
  163.  
  164.     if (!unbuffered())
  165.         setp(base(),ebuf());
  166.  
  167.     if (c!=EOF)
  168.         {
  169.         if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion
  170.             sputc(c);
  171.         else
  172.             {
  173.             if (_write(x_fd,&c,1)!=1)
  174.                 return(EOF);
  175.             }
  176.         }
  177.     return(1);  // return something other than EOF if successful
  178. }
  179.  
  180. /***
  181. *virtual int filebuf::underflow() - underflow virtual function
  182. *
  183. *Purpose:
  184. *       return next character in get area, or get more characters from source.
  185. *
  186. *Entry:
  187. *       None.
  188. *
  189. *Exit:
  190. *       Returns current character in file.  Does not advance get pointer.
  191. *
  192. *Exceptions:
  193. *       Returns EOF if error.
  194. *
  195. *******************************************************************************/
  196. int filebuf::underflow()
  197. {
  198.     int count;
  199.     unsigned char tbuf;
  200.  
  201.     if (in_avail())
  202.         return (int)(unsigned char) *gptr();
  203.  
  204.     if (allocate()==EOF)        // make sure there is a reserve area
  205.         return EOF;
  206.     if (filebuf::sync()==EOF)
  207.         return EOF;
  208.  
  209.     if (unbuffered())
  210.         {
  211.         if (_read(x_fd,(void *)&tbuf,1)<=0)
  212.             return EOF;
  213.         return (int)tbuf;
  214.         }
  215.  
  216.     if ((count=_read(x_fd,(void *)base(),blen())) <= 0)
  217.         return EOF;     // reached EOF
  218.     setg(base(),base(),base()+count);
  219.     return (int)(unsigned char) *gptr();
  220. }
  221.  
  222.  
  223. /***
  224. *virtual streampos filebuf::seekoff() - seekoff virtual function
  225. *
  226. *Purpose:
  227. *       Seeks to given absolute or relative file offset.
  228. *
  229. *Entry:
  230. *       off = offset to seek to relative to beginning, end or current
  231. *               position in the file.
  232. *       dir = one of ios::beg, ios::cur, or ios::end
  233. *
  234. *Exit:
  235. *       Returns current file position after seek.
  236. *
  237. *Exceptions:
  238. *       Returns EOF if error.
  239. *
  240. *******************************************************************************/
  241. streampos filebuf::seekoff(streamoff off, ios::seek_dir dir, int)
  242. {
  243.  
  244.     int fdir;
  245.     long retpos;
  246.     switch (dir) {
  247.         case ios::beg :
  248.             fdir = SEEK_SET;
  249.             break;
  250.         case ios::cur :
  251.             fdir = SEEK_CUR;
  252.             break;
  253.         case ios::end :
  254.             fdir = SEEK_END;
  255.             break;
  256.         default:
  257.         // error
  258.             return(EOF);
  259.         }
  260.  
  261.     if (filebuf::sync()==EOF)
  262.         return EOF;
  263.     if ((retpos=_lseek(x_fd, off, fdir))==-1L)
  264.         return (EOF);
  265.     return((streampos)retpos);
  266. }
  267.  
  268. /***
  269. *virtual int filebuf::sync() - synchronize buffers with external file postion.
  270. *
  271. *Purpose:
  272. *       Synchronizes buffer with external file, by flushing any output and/or
  273. *       discarding any unread input data.  Discards any get or put area(s).
  274. *
  275. *Entry:
  276. *       None.
  277. *
  278. *Exit:
  279. *       Returns EOF if error, else 0.
  280. *
  281. *Exceptions:
  282. *       Returns EOF if error.
  283. *
  284. *******************************************************************************/
  285. int filebuf::sync()
  286. {
  287.         long count, nout;
  288.         char * p;
  289.         if (x_fd==-1)
  290.             return(EOF);
  291.  
  292.         if (!unbuffered())
  293.         {
  294.             if ((count=out_waiting())!=0)
  295.             {
  296.                 if ((nout =_write(x_fd,(void *) pbase(),(unsigned int)count)) != count)
  297.                 {
  298.                     if (nout > 0) {
  299.                         // should set _pptr -= nout
  300.                         pbump(-(int)nout);
  301.                         memmove(pbase(), pbase()+nout, (int)(count-nout));
  302.                     }
  303.                     return(EOF);
  304.                 }
  305.             }
  306.             setp(0,0); // empty put area
  307.  
  308.             if ((count=in_avail()) > 0)
  309.             {
  310.                 // can't use seekoff here!!
  311. #ifdef _WIN32
  312.                 if (_osfile(x_fd) & FTEXT)
  313. #else  /* _WIN32 */
  314.                 if (_osfile[x_fd] & FTEXT)
  315. #endif  /* _WIN32 */
  316.                 {
  317.                     // If text mode, need to account for CR/LF etc.
  318.                     for (p = gptr(); p < egptr(); p++)
  319.                         if (*p == '\n')
  320.                             count++;
  321.  
  322.                     // account for EOF if read, not counted by _read
  323. #ifdef _WIN32
  324.                     if ((_osfile(x_fd) & FEOFLAG))
  325. #else  /* _WIN32 */
  326.                     if ((_osfile[x_fd] & FEOFLAG))
  327. #endif  /* _WIN32 */
  328.                         count++;
  329.  
  330.                 }
  331.                 if (_lseek(x_fd, -count, SEEK_CUR)==-1L)
  332.                 {
  333. //                  unlock();
  334.                     return (EOF);
  335.                 }
  336.             }
  337.             setg(0,0,0); // empty get area
  338.         }
  339. //      unlock();
  340.         return(0);
  341. }
  342.  
  343. /***
  344. *virtual streambuf* filebuf::setbuf(char* ptr, int len) - set reserve area.
  345. *
  346. *Purpose:
  347. *       Synchronizes buffer with external file, by flushing any output and/or
  348. *       discarding any unread input data.  Discards any get or put area(s).
  349. *
  350. *Entry:
  351. *       ptr = requested reserve area.  If NULL, request is for unbuffered.
  352. *       len = size of reserve area.  If <= 0, request is for unbuffered.
  353. *
  354. *Exit:
  355. *       Returns this pointer if request is honored, else NULL.
  356. *
  357. *Exceptions:
  358. *       Returns NULL if request is not honored.
  359. *
  360. *******************************************************************************/
  361. streambuf * filebuf::setbuf(char * ptr, int len)
  362. {
  363.     if (is_open() && (ebuf()))
  364.         return NULL;
  365.     if ((!ptr) || (len <= 0))
  366.         unbuffered(1);
  367.     else
  368.         {
  369.         lock();
  370.         setb(ptr, ptr+len, 0);
  371.         unlock();
  372.         }
  373.     return this;
  374. }
  375.