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

  1. /***
  2. *fseek.c - reposition file pointer on a stream
  3. *
  4. *       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines fseek() - move the file pointer to new place in file
  8. *
  9. *******************************************************************************/
  10.  
  11. #include <cruntime.h>
  12. #include <stdio.h>
  13. #include <file2.h>
  14. #include <dbgint.h>
  15. #include <msdos.h>
  16. #include <errno.h>
  17. #include <malloc.h>
  18. #include <io.h>
  19. #include <stddef.h>
  20. #include <internal.h>
  21. #include <mtdll.h>
  22.  
  23. /***
  24. *int fseek(stream, offset, whence) - reposition file pointer
  25. *
  26. *Purpose:
  27. *
  28. *       Reposition file pointer to the desired location.  The new location
  29. *       is calculated as follows:
  30. *                                { whence=0, beginning of file }
  31. *               <offset> bytes + { whence=1, current position  }
  32. *                                { whence=2, end of file       }
  33. *
  34. *       Be careful to coordinate with buffering.
  35. *
  36. *                       - - - - - - - - - - - - -
  37. *
  38. *       [NOTE: We used to bend over backwards to try and preserve the current
  39. *       buffer and maintain disk block alignment.  This ended up making our
  40. *       code big and slow and complicated, and slowed us down quite a bit.
  41. *       Some of the things pertinent to the old implimentation:
  42. *
  43. *       (1) Read-only: We only did the special code path if the file was
  44. *       opened read-only (_IOREAD).  If the file was writable, we didn't
  45. *       try to optimize.
  46. *
  47. *       (2) Buffering:  We'd assign a buffer, if necessary, since the
  48. *       later code might need it (i.e., call _getbuf).
  49. *
  50. *       (3) Ungetc: Fseek had to be careful NOT to save the buffer if
  51. *       an ungetc had ever been done on the buffer (flag _IOUNGETC).
  52. *
  53. *       (4) Control ^Z: Fseek had to deal with ^Z after reading a
  54. *       new buffer's worth of data (flag _IOCTRLZ).
  55. *
  56. *       (5) Seek-to-end-and-back: To determine if the new seek was within
  57. *       the current buffer, we had to 'normalize' the desired location.
  58. *       This means that we sometimes had to seek to the end of the file
  59. *       and back to determine what the 0-relative offset was.  Two extra
  60. *       lseek() calls hurt performance.
  61. *
  62. *       (6) CR/LF accounting - When trying to seek within a buffer that
  63. *       is in text mode, we had to go account for CR/LF expansion.  This
  64. *       required us to look at every character up to the new offset and
  65. *       see if it was '\n' or not.  In addition, we had to check the
  66. *       FCRLF flag to see if the new buffer started with '\n'.
  67. *
  68. *       Again, all of these notes are for the OLD implimentation just to
  69. *       remind folks of some of the issues involving seeking within a buffer
  70. *       and maintaining buffer alignment.  As an aside, I think this may have
  71. *       been a big win in the 'old days' on floppy-based systems but on newer
  72. *       fast hard disks, the extra code/complexity overwhelmed any gain.
  73. *
  74. *                       - - - - - - - - - - - - -
  75. *
  76. *Entry:
  77. *       FILE *stream - file to reposition file pointer on
  78. *       long offset - offset to seek to
  79. *       int whence - origin offset is measured from (0=beg, 1=current pos,
  80. *                    2=end)
  81. *
  82. *Exit:
  83. *       returns 0 if succeeds
  84. *       returns -1 and sets errno if fails
  85. *       fields of FILE struct will be changed
  86. *
  87. *Exceptions:
  88. *
  89. *******************************************************************************/
  90.  
  91. #ifdef _MT
  92.  
  93. int __cdecl fseek (
  94.         FILE *stream,
  95.         long offset,
  96.         int whence
  97.         )
  98. {
  99.         int retval;
  100.  
  101.         _ASSERTE(stream != NULL);
  102.  
  103.         _lock_str(stream);
  104.  
  105.         retval = _fseek_lk (stream, offset, whence);
  106.  
  107.         _unlock_str(stream);
  108.  
  109.         return(retval);
  110. }
  111.  
  112.  
  113. /***
  114. *_fseek_lk() - Core fseek() routine (stream is locked)
  115. *
  116. *Purpose:
  117. *       Core fseek() routine; assumes that caller has the stream locked.
  118. *
  119. *       [See fseek() for more info.]
  120. *
  121. *Entry: [See fseek()]
  122. *
  123. *Exit:  [See fseek()]
  124. *
  125. *Exceptions:
  126. *
  127. *******************************************************************************/
  128.  
  129. int __cdecl _fseek_lk (
  130.  
  131. #else  /* _MT */
  132.  
  133. int __cdecl fseek (
  134.  
  135. #endif  /* _MT */
  136.  
  137.         FILE *str,
  138.         long offset,
  139.         int whence
  140.         )
  141. {
  142.  
  143.  
  144.         REG1 FILE *stream;
  145.  
  146.         _ASSERTE(str != NULL);
  147.  
  148.         /* Init stream pointer */
  149.         stream = str;
  150.  
  151.         if ( !inuse(stream) || ((whence != SEEK_SET) && (whence != SEEK_CUR) &&
  152.             (whence != SEEK_END)) ) {
  153.                 errno=EINVAL;
  154.                 return(-1);
  155.         }
  156.  
  157.         /* Clear EOF flag */
  158.  
  159.         stream->_flag &= ~_IOEOF;
  160.  
  161.         /* If seeking relative to current location, then convert to
  162.            a seek relative to beginning of file.  This accounts for
  163.            buffering, etc. by letting fseek() tell us where we are. */
  164.  
  165.         if (whence == SEEK_CUR) {
  166.                 offset += _ftell_lk(stream);
  167.                 whence = SEEK_SET;
  168.         }
  169.  
  170.         /* Flush buffer as necessary */
  171.  
  172.         _flush(stream);
  173.  
  174.         /* If file opened for read/write, clear flags since we don't know
  175.            what the user is going to do next. If the file was opened for
  176.            read access only, decrease _bufsiz so that the next _filbuf
  177.            won't cost quite so much */
  178.  
  179.         if (stream->_flag & _IORW)
  180.                 stream->_flag &= ~(_IOWRT|_IOREAD);
  181. #if !defined (_M_MPPC) && !defined (_M_M68K)
  182.         else if ( (stream->_flag & _IOREAD) && (stream->_flag & _IOMYBUF) &&
  183.                   !(stream->_flag & _IOSETVBUF) )
  184.                 stream->_bufsiz = _SMALL_BUFSIZ;
  185. #endif  /* !defined (_M_MPPC) && !defined (_M_M68K) */
  186.  
  187.         /* Seek to the desired locale and return. */
  188.  
  189.         return(_lseek(_fileno(stream), offset, whence) == -1L ? -1 : 0);
  190. }
  191.