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

  1. /***
  2. *setvbuf.c - set buffer size for a stream
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines setvbuf() - set the buffering mode and size for a stream.
  8. *
  9. *******************************************************************************/
  10.  
  11. #include <cruntime.h>
  12. #include <stdio.h>
  13. #include <file2.h>
  14. #include <malloc.h>
  15. #include <internal.h>
  16. #include <mtdll.h>
  17. #include <limits.h>
  18. #include <dbgint.h>
  19.  
  20. /***
  21. *int setvbuf(stream, buffer, type, size) - set buffering for a file
  22. *
  23. *Purpose:
  24. *       Controls buffering and buffer size for the specified stream.  The
  25. *       array pointed to by buf is used as a buffer, unless NULL, in which
  26. *       case we'll allocate a buffer automatically. type specifies the type
  27. *       of buffering: _IONBF = no buffer, _IOFBF = buffered, _IOLBF = same
  28. *       as _IOFBF.
  29. *
  30. *Entry:
  31. *       FILE *stream - stream to control buffer on
  32. *       char *buffer - pointer to buffer to use (NULL means auto allocate)
  33. *       int type     - type of buffering (_IONBF, _IOFBF or _IOLBF)
  34. *       size_t size  - size of buffer
  35. *
  36. *Exit:
  37. *       return 0 if successful
  38. *       returns non-zero if fails
  39. *
  40. *Exceptions:
  41. *
  42. *******************************************************************************/
  43.  
  44. int __cdecl setvbuf (
  45.         FILE *str,
  46.         char *buffer,
  47.         int type,
  48.         size_t size
  49.         )
  50. {
  51.         REG1 FILE *stream;
  52.         int retval=0;   /* assume good return */
  53.  
  54.         _ASSERTE(str != NULL);
  55.  
  56.         /*
  57.          * (1) Make sure type is one of the three legal values.
  58.          * (2) If we are buffering, make sure size is greater than 0.
  59.          */
  60. #ifdef _WIN32
  61.         if ( (type != _IONBF) && ((size < 2) || (size > INT_MAX) ||
  62. #else  /* _WIN32 */
  63. #if defined (_M_MPPC) || defined (_M_M68K)
  64.         if ( (type != _IONBF) && ((size == 0) || (size > INT_MAX) ||
  65. #endif  /* defined (_M_MPPC) || defined (_M_M68K) */
  66. #endif  /* _WIN32 */
  67.              ((type != _IOFBF) && (type != _IOLBF))) )
  68.                 return(-1);
  69.  
  70. #ifdef _WIN32
  71.         /*
  72.          * force size to be even by masking down to the nearest multiple
  73.          * of 2
  74.          */
  75.         size &= (size_t)~1;
  76. #endif  /* _WIN32 */
  77.  
  78.         /*
  79.          * Init stream pointers
  80.          */
  81.         stream = str;
  82.  
  83.         /*
  84.          * Lock the file
  85.          */
  86.         _lock_str(stream);
  87.  
  88.         /*
  89.          * Flush the current buffer and free it, if it is ours.
  90.          */
  91.         _flush(stream);
  92.         _freebuf(stream);
  93.  
  94.         /*
  95.          * Clear a bunch of bits in stream->_flag (all bits related to
  96.          * buffering and those which used to be in stream2->_flag2). Most
  97.          * of these should never be set when setvbuf() is called, but it
  98.          * doesn't cost anything to be safe.
  99.          */
  100.         stream->_flag &= ~(_IOMYBUF | _IOYOURBUF | _IONBF |
  101. #ifdef _WIN32
  102.                            _IOSETVBUF |
  103. #endif  /* _WIN32 */
  104.                            _IOFEOF | _IOFLRTN | _IOCTRLZ);
  105.  
  106.         /*
  107.          * CASE 1: No Buffering.
  108.          */
  109.         if (type & _IONBF) {
  110.                 stream->_flag |= _IONBF;
  111.                 buffer = (char *)&(stream->_charbuf);
  112. #ifdef _WIN32
  113.                 size = 2;
  114. #else  /* _WIN32 */
  115. #if defined (_M_MPPC) || defined (_M_M68K)
  116.                 size = 1;
  117. #endif  /* defined (_M_MPPC) || defined (_M_M68K) */
  118. #endif  /* _WIN32 */
  119.         }
  120.  
  121.         /*
  122.          * NOTE: Cases 2 and 3 (below) cover type == _IOFBF or type == _IOLBF
  123.          * Line buffering is treated as the same as full buffering, so the
  124.          * _IOLBF bit in stream->_flag is never set. Finally, since _IOFBF is
  125.          * defined to be 0, full buffering is simply assumed whenever _IONBF
  126.          * is not set.
  127.          */
  128.  
  129.         /*
  130.          * CASE 2: Default Buffering -- Allocate a buffer for the user.
  131.          */
  132.         else if ( buffer == NULL ) {
  133.                 if ( (buffer = _malloc_crt(size)) == NULL ) {
  134. #ifndef CRTDLL
  135.                         /*
  136.                          * force library pre-termination procedure (placed here
  137.                          * because the code path should almost never be hit)
  138.                          */
  139.                         _cflush++;
  140. #endif  /* CRTDLL */
  141.                         retval = -1;
  142.                         goto done;
  143.                 }
  144. #ifdef _WIN32
  145.                 stream->_flag |= _IOMYBUF | _IOSETVBUF;
  146. #else  /* _WIN32 */
  147. #if defined (_M_MPPC) || defined (_M_M68K)
  148.                 stream->_flag |= _IOMYBUF;
  149. #endif  /* defined (_M_MPPC) || defined (_M_M68K) */
  150. #endif  /* _WIN32 */
  151.         }
  152.  
  153.         /*
  154.          * CASE 3: User Buffering -- Use the buffer supplied by the user.
  155.          */
  156.         else {
  157. #ifdef _WIN32
  158.                 stream->_flag |= _IOYOURBUF | _IOSETVBUF;
  159. #else  /* _WIN32 */
  160. #if defined (_M_MPPC) || defined (_M_M68K)
  161.                 stream->_flag |= _IOYOURBUF;
  162. #endif  /* defined (_M_MPPC) || defined (_M_M68K) */
  163. #endif  /* _WIN32 */
  164.         }
  165.  
  166.         /*
  167.          * Common return for all cases.
  168.          */
  169.         stream->_bufsiz = size;
  170.         stream->_ptr = stream->_base = buffer;
  171.         stream->_cnt = 0;
  172. done:
  173.         _unlock_str(stream);
  174.         return(retval);
  175. }
  176.