Rewrote fread/fwrite for a better/faster handling of reads/writes requests.

svn path=/trunk/; revision=3039
This commit is contained in:
Hartmut Birr 2002-06-10 21:26:36 +00:00
parent 9ac5422074
commit 495dfc660f
2 changed files with 128 additions and 34 deletions

View file

@ -7,8 +7,9 @@
size_t fread(void *vptr, size_t size, size_t count, FILE *iop) size_t fread(void *vptr, size_t size, size_t count, FILE *iop)
{ {
char *ptr = (char *)vptr; unsigned char *ptr = (unsigned char *)vptr;
size_t to_read ,n_read; size_t to_read ,n_read;
int c, copy;
to_read = size * count; to_read = size * count;
@ -29,25 +30,58 @@ size_t fread(void *vptr, size_t size, size_t count, FILE *iop)
if (vptr == NULL || to_read == 0) if (vptr == NULL || to_read == 0)
return 0; return 0;
while(iop->_cnt > 0 && to_read > 0 ) if (iop->_base == NULL)
{ {
to_read--; int c = _filbuf(iop);
*ptr++ = getc(iop); if (c == EOF)
return 0;
*ptr++ = c;
if (--to_read == 0)
return 1;
} }
// if the buffer is dirty it will have to be written now if (iop->_cnt > 0 && to_read > 0)
// otherwise the file pointer won't match anymore. {
copy = min(iop->_cnt, to_read);
memcpy(ptr, iop->_ptr, copy);
ptr += copy;
iop->_ptr += copy;
iop->_cnt -= copy;
to_read -= copy;
if (to_read == 0)
return count;
}
fflush(iop); if (to_read > 0)
{
// check to see if this will work with in combination with ungetc
if (to_read >= iop->_bufsiz)
{
n_read = _read(fileno(iop), ptr, to_read); n_read = _read(fileno(iop), ptr, to_read);
if ( n_read != -1 ) if (n_read < 0)
iop->_flag |= _IOERR;
else if (n_read == 0)
iop->_flag |= _IOEOF;
else
to_read -= n_read; to_read -= n_read;
// the file buffer is empty and there is no read ahead information anymore. // the file buffer is empty and there is no read ahead information anymore.
iop->_flag &= ~_IOAHEAD; iop->_flag &= ~_IOAHEAD;
}
else
{
c = _filbuf(iop);
if (c != EOF)
{
*ptr++ = c;
to_read--;
copy = min(iop->_cnt, to_read);
memcpy(ptr, iop->_ptr, copy);
iop->_ptr += copy;
iop->_cnt -= copy;
to_read -= copy;
}
}
}
return count - (to_read/size); return count - (to_read/size);
} }

View file

@ -3,12 +3,17 @@
#include <msvcrt/string.h> #include <msvcrt/string.h>
#include <msvcrt/errno.h> #include <msvcrt/errno.h>
#include <msvcrt/internal/file.h> #include <msvcrt/internal/file.h>
#define NDEBUG
#include <msvcrt/msvcrtdbg.h>
size_t fwrite(const void *vptr, size_t size, size_t count, FILE *iop) size_t fwrite(const void *vptr, size_t size, size_t count, FILE *iop)
{ {
size_t to_write, n_written; size_t to_write, n_written;
char *ptr = (char *)vptr; unsigned char *ptr = (unsigned char *)vptr;
int copy;
DPRINT("fwrite(%x, %d, %d, %x)\n", vptr, size, count, iop);
to_write = size*count; to_write = size*count;
if (!OPEN4WRITING(iop)) if (!OPEN4WRITING(iop))
@ -28,24 +33,79 @@ size_t fwrite(const void *vptr, size_t size, size_t count, FILE *iop)
if (vptr == NULL || to_write == 0) if (vptr == NULL || to_write == 0)
return 0; return 0;
while(iop->_cnt > 0 && to_write > 0) if (iop->_base == NULL && !(iop->_flag&_IONBF))
{ {
to_write--; if (EOF == _flsbuf(*ptr++, iop))
putc(*ptr++,iop); return 0;
if (--to_write == 0)
return 1;
} }
if (iop->_flag & _IOLBF)
{
while (to_write > 0)
{
if (EOF == putc(*ptr++, iop))
{
iop->_flag |= _IOERR;
break;
}
to_write--;
}
}
else
{
if (iop->_cnt > 0 && to_write > 0)
{
copy = min(iop->_cnt, to_write);
memcpy(iop->_ptr, ptr, copy);
ptr += copy;
iop->_ptr += copy;
iop->_cnt -= copy;
to_write -= copy;
iop->_flag |= _IODIRTY;
}
if (to_write > 0)
{
// if the buffer is dirty it will have to be written now // if the buffer is dirty it will have to be written now
// otherwise the file pointer won't match anymore. // otherwise the file pointer won't match anymore.
fflush(iop); fflush(iop);
if (to_write >= iop->_bufsiz)
n_written = _write(fileno(iop), ptr,to_write); {
if (n_written != -1) while (to_write > 0)
{
n_written = _write(fileno(iop), ptr, to_write);
if (n_written <= 0)
{
iop->_flag |= _IOERR;
break;
}
to_write -= n_written; to_write -= n_written;
ptr += n_written;
}
// check to see if this will work with in combination with ungetc // check to see if this will work with in combination with ungetc
// the file buffer is empty and there is no read ahead information anymore. // the file buffer is empty and there is no read ahead information anymore.
iop->_flag &= ~_IOAHEAD; iop->_flag &= ~_IOAHEAD;
}
else
{
if (EOF != _flsbuf(*ptr++, iop))
{
if (--to_write > 0)
{
memcpy(iop->_ptr, ptr, to_write);
iop->_ptr += to_write;
iop->_cnt -= to_write;
iop->_flag |= _IODIRTY;
return count;
}
}
}
}
}
return count - (to_write/size); return count - (to_write/size);
} }