diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/crt32/stdio/fread.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/crt32/stdio/fread.c')
-rw-r--r-- | private/crt32/stdio/fread.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/private/crt32/stdio/fread.c b/private/crt32/stdio/fread.c new file mode 100644 index 000000000..c925264f5 --- /dev/null +++ b/private/crt32/stdio/fread.c @@ -0,0 +1,197 @@ +/*** +*fread.c - read from a stream +* +* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Read from the specified stream into the user's buffer. +* +*Revision History: +* 06-23-89 PHG Module created, based on asm version +* 02-15-90 GJF _iob[], _iob2[] merge. Also, fixed copyright and +* indents. +* 03-19-90 GJF Made calling type _CALLTYPE1 and added #include +* <cruntime.h>. +* 08-14-90 SBM Compiles cleanly with -W3 +* 10-02-90 GJF New-style function declarators. +* 01-22-91 GJF ANSI naming. +* 03-27-92 DJM POSIX support. +* 06-22-92 GJF Must return 0 if EITHER size-of-item or number-of- +* item arguments is 0 (TNT Bug #523) +* 08-26-92 GJF Include unistd.h for POSIX build. +* +*******************************************************************************/ + +#include <cruntime.h> +#ifdef _POSIX_ +#include <unistd.h> +#endif +#include <stdio.h> +#include <os2dll.h> +#include <io.h> +#include <string.h> +#include <file2.h> + +/*** +*size_t fread(void *buffer, size_t size, size_t count, FILE *stream) - +* read from specified stream into the specified buffer. +* +*Purpose: +* Read 'count' items of size 'size' from the specified stream into +* the specified buffer. Return when 'count' items have been read in +* or no more items can be read from the stream. +* +*Entry: +* buffer - pointer to user's buffer +* size - size of the item to read in +* count - number of items to read +* stream - stream to read from +* +*Exit: +* Returns the number of (whole) items that were read into the buffer. +* This may be less than 'count' if an error or eof occurred. In this +* case, ferror() or feof() should be used to distinguish between the +* two conditions. +* +*Notes: +* fread will attempt to buffer the stream (side effect of the _filbuf +* call) if necessary. +* +* No more than 0xFFFE bytes may be read in at a time by a call to +* read(). Further, read() does not handle huge buffers. Therefore, +* in large data models, the read request is broken down into chunks +* that do not violate these considerations. Each of these chunks is +* processed much like an fread() call in a small data model (by a +* call to _nfread()). +* +* MTHREAD/DLL - Handled in three layers. fread() handles the locking +* and DS saving/loading/restoring (if required) and calls _fread_lk() +* to do the work. _fread_lk() is the same as the single-thread, +* large data model version of fread(). It breaks up the read request +* into digestible chunks and calls _nfread() to do the actual work. +* +* 386/MTHREAD/DLL - Handled in just the two layers since it is small +* data model. The outer layer, fread(), takes care of the stream locking +* and calls _fread_lk() to do the actual work. _fread_lk() is the same +* as the single-thread version of fread(). +* +*******************************************************************************/ + + +#ifdef MTHREAD +/* define locking/unlocking version */ +size_t _CALLTYPE1 fread ( + void *buffer, + size_t size, + size_t count, + FILE *stream + ) +{ + int index; + size_t retval; + + index = _iob_index(stream); + _lock_str(index); /* lock stream */ + retval = _fread_lk(buffer, size, count, stream); /* do the read */ + _unlock_str(index); /* unlock stream */ + return retval; +} +#endif + +/* define the normal version */ +#ifdef MTHREAD +size_t _CALLTYPE1 _fread_lk ( +#else +size_t _CALLTYPE1 fread ( +#endif + void *buffer, + size_t size, + size_t num, + FILE *stream + ) +{ + char *data; /* point to where should be read next */ + unsigned total; /* total bytes to read */ + unsigned count; /* num bytes left to read */ + unsigned bufsize; /* size of stream buffer */ + unsigned nbytes; /* how much to read now */ + unsigned nread; /* how much we did read */ + int c; /* a temp char */ + + /* initialize local vars */ + data = buffer; + + if ( (count = total = size * num) == 0 ) + return 0; + + if (anybuf(stream)) + /* already has buffer, use its size */ + bufsize = stream->_bufsiz; + else + /* assume will get BUFSIZ buffer */ + bufsize = BUFSIZ; + + /* here is the main loop -- we go through here until we're done */ + while (count != 0) { + /* if the buffer exists and has characters, copy them to user + buffer */ + if (anybuf(stream) && stream->_cnt != 0) { + /* how much do we want? */ + nbytes = (count < (unsigned)stream->_cnt) ? count : stream->_cnt; + memcpy(data, stream->_ptr, nbytes); + + /* update stream and amt of data read */ + count -= nbytes; + stream->_cnt -= nbytes; + stream->_ptr += nbytes; + data += nbytes; + } + else if (count >= bufsize) { + /* If we have more than bufsize chars to read, get data + by calling read with an integral number of bufsiz + blocks. Note that if the stream is text mode, read + will return less chars than we ordered. */ + + /* calc chars to read -- (count/bufsize) * bufsize */ + nbytes = count - count % bufsize; + +#ifdef _POSIX_ + nread = read(fileno(stream), data, nbytes); +#else + nread = _read(_fileno(stream), data, nbytes); +#endif + if (nread == 0) { + /* end of file -- out of here */ + stream->_flag |= _IOEOF; + return (total - count) / size; + } + else if (nread == (unsigned)-1) { + /* error -- out of here */ + stream->_flag |= _IOERR; + return (total - count) / size; + } + + /* update count and data to reflect read */ + count -= nread; + data += nread; + } + else { + /* less than bufsize chars to read, so call _filbuf to + fill buffer */ + if ((c = _filbuf(stream)) == EOF) { + /* error or eof, stream flags set by _filbuf */ + return (total - count) / size; + } + + /* _filbuf returned a char -- store it */ + *data++ = (char) c; + --count; + + /* update buffer size */ + bufsize = stream->_bufsiz; + } + } + + /* we finished successfully, so just return num */ + return num; +} |