summaryrefslogtreecommitdiffstats
path: root/private/crt32/stdio/fread.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/crt32/stdio/fread.c
downloadNT4.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.c197
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;
+}