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

  1. /***
  2. *ftelli64.c - get current file position
  3. *
  4. *       Copyright (c) 1994-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines _ftelli64() - find current current position of file pointer
  8. *
  9. *******************************************************************************/
  10.  
  11. #include <cruntime.h>
  12. #include <stdio.h>
  13. #include <file2.h>
  14. #include <dbgint.h>
  15. #include <errno.h>
  16. #include <msdos.h>
  17. #include <stddef.h>
  18. #include <io.h>
  19. #include <internal.h>
  20. #include <mtdll.h>
  21.  
  22. /***
  23. *__int64 _ftelli64(stream) - query stream file pointer
  24. *
  25. *Purpose:
  26. *       Find out what stream's position is. coordinate with buffering; adjust
  27. *       backward for read-ahead and forward for write-behind. This is NOT
  28. *       equivalent to fseek(stream,0L,1), because fseek will remove an ungetc,
  29. *       may flush buffers, etc.
  30. *
  31. *Entry:
  32. *       FILE *stream - stream to query for position
  33. *
  34. *Exit:
  35. *       return present file position if succeeds
  36. *       returns -1i64 and sets errno if fails
  37. *
  38. *Exceptions:
  39. *
  40. *******************************************************************************/
  41.  
  42. #ifdef _MT
  43.  
  44. __int64 __cdecl _ftelli64 (
  45.         FILE *stream
  46.         )
  47. {
  48.         __int64 retval;
  49.  
  50.         _ASSERTE(stream != NULL);
  51.  
  52.         _lock_str(stream);
  53.  
  54.         retval = _ftelli64_lk (stream);
  55.  
  56.         _unlock_str(stream);
  57.  
  58.         return(retval);
  59. }
  60.  
  61.  
  62. /***
  63. *_ftelli64_lk() - _ftelli64() core routine (assumes stream is locked).
  64. *
  65. *Purpose:
  66. *       Core _ftelli64() routine (assumes caller has aquired stream lock).
  67. *
  68. *Entry:
  69. *
  70. *Exit:
  71. *
  72. *Exceptions:
  73. *
  74. *******************************************************************************/
  75.  
  76. __int64 __cdecl _ftelli64_lk (
  77.  
  78. #else  /* _MT */
  79.  
  80. __int64 __cdecl _ftelli64 (
  81.  
  82. #endif  /* _MT */
  83.  
  84.         FILE *str
  85.         )
  86. {
  87.         REG1 FILE *stream;
  88.         unsigned int offset;
  89.         __int64 filepos;
  90.         REG2 char *p;
  91.         char *max;
  92.         int fd;
  93.         unsigned int rdcnt;
  94.  
  95.         _ASSERTE(str != NULL);
  96.  
  97.         /* Init stream pointer and file descriptor */
  98.         stream = str;
  99.         fd = _fileno(stream);
  100.  
  101.         if (stream->_cnt < 0)
  102.                 stream->_cnt = 0;
  103.  
  104.         if ((filepos = _lseeki64(fd, 0i64, SEEK_CUR)) < 0L)
  105.                 return(-1i64);
  106.  
  107.         if (!bigbuf(stream))            /* _IONBF or no buffering designated */
  108.                 return(filepos - stream->_cnt);
  109.  
  110.         offset = stream->_ptr - stream->_base;
  111.  
  112.         if (stream->_flag & (_IOWRT|_IOREAD)) {
  113.                 if (_osfile(fd) & FTEXT)
  114.                         for (p = stream->_base; p < stream->_ptr; p++)
  115.                                 if (*p == '\n')  /* adjust for '\r' */
  116.                                         offset++;
  117.         }
  118.         else if (!(stream->_flag & _IORW)) {
  119.                 errno=EINVAL;
  120.                 return(-1i64);
  121.         }
  122.  
  123.         if (filepos == 0i64)
  124.                 return((__int64)offset);
  125.  
  126.         if (stream->_flag & _IOREAD)    /* go to preceding sector */
  127.  
  128.                 if (stream->_cnt == 0)  /* filepos holds correct location */
  129.                         offset = 0;
  130.  
  131.                 else {
  132.  
  133.                         /* Subtract out the number of unread bytes left in the
  134.                            buffer. [We can't simply use _iob[]._bufsiz because
  135.                            the last read may have hit EOF and, thus, the buffer
  136.                            was not completely filled.] */
  137.  
  138.                         rdcnt = stream->_cnt + (stream->_ptr - stream->_base);
  139.  
  140.                         /* If text mode, adjust for the cr/lf substitution. If
  141.                            binary mode, we're outta here. */
  142.                         if (_osfile(fd) & FTEXT) {
  143.                                 /* (1) If we're not at eof, simply copy _bufsiz
  144.                                    onto rdcnt to get the # of untranslated
  145.                                    chars read. (2) If we're at eof, we must
  146.                                    look through the buffer expanding the '\n'
  147.                                    chars one at a time. */
  148.  
  149.                                 /* [NOTE: Performance issue -- it is faster to
  150.                                    do the two _lseek() calls than to blindly go
  151.                                    through and expand the '\n' chars regardless
  152.                                    of whether we're at eof or not.] */
  153.  
  154.                                 if (_lseeki64(fd, 0i64, SEEK_END) == filepos) {
  155.  
  156.                                         max = stream->_base + rdcnt;
  157.                                         for (p = stream->_base; p < max; p++)
  158.                                                 if (*p == '\n')
  159.                                                         /* adjust for '\r' */
  160.                                                         rdcnt++;
  161.  
  162.                                         /* If last byte was ^Z, the lowio read
  163.                                            didn't tell us about it.  Check flag
  164.                                            and bump count, if necessary. */
  165.  
  166.                                         if (stream->_flag & _IOCTRLZ)
  167.                                                 ++rdcnt;
  168.                                 }
  169.  
  170.                                 else {
  171.  
  172.                                         _lseeki64(fd, filepos, SEEK_SET);
  173.  
  174.                                         /* We want to set rdcnt to the number
  175.                                            of bytes originally read into the
  176.                                            stream buffer (before crlf->lf
  177.                                            translation). In most cases, this
  178.                                            will just be _bufsiz. However, the
  179.                                            buffer size may have been changed,
  180.                                            due to fseek optimization, at the
  181.                                            END of the last _filbuf call. */
  182.  
  183.                                         if ( (rdcnt <= _SMALL_BUFSIZ) &&
  184.                                              (stream->_flag & _IOMYBUF) &&
  185.                                              !(stream->_flag & _IOSETVBUF) )
  186.                                         {
  187.                                                 /* The translated contents of
  188.                                                    the buffer is small and we
  189.                                                    are not at eof. The buffer
  190.                                                    size must have been set to
  191.                                                    _SMALL_BUFSIZ during the
  192.                                                    last _filbuf call. */
  193.  
  194.                                                 rdcnt = _SMALL_BUFSIZ;
  195.                                         }
  196.                                         else
  197.                                                 rdcnt = stream->_bufsiz;
  198.  
  199.  
  200.                                         /* If first byte in untranslated buffer
  201.                                            was a '\n', assume it was preceeded
  202.                                            by a '\r' which was discarded by the
  203.                                            previous read operation and count
  204.                                            the '\n'. */
  205.                                         if  (_osfile(fd) & FCRLF)
  206.                                                 ++rdcnt;
  207.                                 }
  208.  
  209.                         } /* end if FTEXT */
  210.  
  211.                         filepos -= (__int64)rdcnt;
  212.  
  213.                 } /* end else stream->_cnt != 0 */
  214.  
  215.         return(filepos + (__int64)offset);
  216. }
  217.