Files
oldlinux-files/study/linux-travel/minix-386/estdio21.tar/estdio21/fread.c
2024-02-19 00:25:23 -05:00

121 lines
3.0 KiB
C

/* f r e a d */
#include "stdiolib.h"
/*LINTLIBRARY*/
__stdiosize_t fread F4(void *, ptr,
__stdiosize_t, size,
__stdiosize_t, nitems,
FILE *, fp)
{
__stdiosize_t red; /* bytes read in read call */
__stdiosize_t reed; /* amount to read */
__stdiobuf_t *p; /* buffer pointer */
__stdiobuf_t *q; /* pointer into getc buffer */
__stdiosize_t itemsleft; /* whole or partial items left */
__stdiosize_t nextover; /* bytes left over next iteration */
register __stdiosize_t leftover; /* bytes left over this iteration */
__stdiosize_t readitem; /* whole items to read */
register __stdiosize_t readsize; /* amount of data to read */
__stdiosize_t oversize; /* readsize less leftover */
int ch; /* single character read */
if (CHECKREAD(fp) || (itemsleft = nitems) == 0 || size == 0)
return 0;
if (GETFLAG(fp, _IOSTDX) == _IOSTDIN && __Zout != NULL &&
(ALLFLAGS(fp) & ALLFLAGS(__Zout) & _IOLBF) != 0)
(void) FFLUSH(__Zout);
/* Fix void * casting problems */
p = (__stdiobuf_t *) ptr;
/* Try to avoid specialisation for unbuffered case */
ASSERT(sizeof(fp->__buf) == 1);
/* Absorb as much data from the input buffer as possible */
readsize = BYTESINREADBUFFER(fp);
if (BUFFERSIZE(fp)/size >= itemsleft) {
reed = size * itemsleft;
readitem = itemsleft;
nextover = 0;
}
else {
reed = readsize;
readitem = readsize/size;
nextover = (leftover = readsize%size) != 0 ? size - leftover : 0;
}
while (reed != 0) {
if (readsize == 0) {
if ((ch = getc(fp)) == EOF)
return (readitem*size + nextover - reed)/size;
*p++ = ch;
reed--;
readsize = BYTESINREADBUFFER(fp);
}
else {
if (readsize > reed)
readsize = reed;
reed -= readsize;
q = GETREADPTR(fp);
if (readsize > FREADTHRESHOLD) {
MEMCPY(p, q, (size_t) readsize);
p += readsize;
q += readsize;
}
else {
do
*p++ = *q++;
while (--readsize);
}
SETREADPTR(fp, q);
}
}
/* The rest of the data comes from the file directly */
while ((itemsleft -= readitem) != 0) {
leftover = nextover;
readsize = UINT_MAX;
readitem = 0;
/* Very large objects will require several large reads */
if (readsize < leftover)
nextover = leftover - readsize;
/* Account for end of last object and start of new ones */
else {
if (leftover != 0)
readitem = 1;
oversize = readsize - leftover;
if ((readitem += oversize/size) < itemsleft)
nextover = size - oversize%size;
else {
readitem = itemsleft;
readsize = leftover + itemsleft*size;
if (leftover != 0)
readsize -= size;
}
}
for (reed = readsize;
reed != 0 && (red = __ioread(fileno(fp), (char *) p, reed)) != 0;
p += red, reed -= red)
;
if (reed != 0) {
if ((readsize -= reed) >= leftover) {
itemsleft -= (readsize-leftover)/size;
if (leftover != 0)
itemsleft--;
}
break;
}
}
return nitems-itemsleft;
}