/*
 * fread and fwrite (optimised version)
 * Could do i/o to/from the user's buffer directly if the transfer is long
 * enough.  If there's a block-aligned block (or more) in the middle, could
 * transfer it directly.
 */

#include <stdio.h>
#include <string.h>			/* the ANSI one, for memcpy */

#ifndef PTR_TYPE
#define	PTR_TYPE char *			/* type of _ptr in stdio.h */
#endif

#ifndef voidstar
#ifdef __STDC__
#define voidstar void *
#else					/* __STDC__ */
#define voidstar char *
#endif					/* __STDC__ */
#endif					/* voidstar */

#ifndef size_type
#ifdef __STDC__
#define size_type size_t
#else					/* __STDC__ */
#define size_type int
#endif					/* __STDC__ */
#endif					/* size_type */

#ifndef THRESHOLD
#define THRESHOLD 12			/* memcpy vs in-line threshold */
#endif

typedef unsigned char putc_t;		/* cast putc args to this type */

size_type
fread(aptr, size, count, fp)
voidstar aptr;
size_type size, count;
register FILE *fp;
{
	register unsigned bytes = count * size;
	unsigned origbytes = bytes;
	char *ptr = aptr;

	while (bytes > 0) {	/* bytes still to be read */
		{
			/* all of bytes in buffer */
			register int copy = fp->_cnt;

			if (copy < 0)
				copy = 0;
			if (copy > bytes)	/* buffer longer than ptr */
				copy = bytes;	/* only fill ptr */
			bytes -= copy;	/* adjust to reflect next loop */
			fp->_cnt -= copy;
			if (copy < THRESHOLD) {
				register char *rptr = ptr,
						*bp = (char *)fp->_ptr;

				for (++copy; --copy > 0; )
					*rptr++ = *bp++;
				ptr = rptr;
				fp->_ptr = (PTR_TYPE)bp;
			} else {
				(void) memcpy(ptr, (char *)fp->_ptr, copy);
				ptr += copy;
				fp->_ptr += copy;
			}
		}
		if (bytes > 0) {	/* more to read, but buffer is empty */
			register int c = getc(fp);	/* refill buffer */

			if (c == EOF)
				break;
			else {
				*ptr++ = c;
				--bytes;
			}
		}
	}
	return size == 0? count: (origbytes - bytes) / size;
}

size_type
fwrite(aptr, size, count, fp)
voidstar aptr;
size_type size, count;
register FILE *fp;
{
	register unsigned bytes = count * size;
	unsigned origbytes = bytes;
	char *ptr = aptr;

	while (bytes > 0) {	/* bytes still to be written */
		{
			register int copy = fp->_cnt;

			if (copy < 0)
				copy = 0;
			if (copy > bytes)	/* buffer longer than ptr */
				copy = bytes;	/* only empty ptr */
			bytes -= copy;	/* adjust to reflect next loop */
			fp->_cnt -= copy;
			if (copy < THRESHOLD) {
				register char *rptr = ptr,
						*bp = (char *)fp->_ptr;

				for (++copy; --copy > 0; )
					*bp++ = *rptr++;
				ptr = rptr;
				fp->_ptr = (PTR_TYPE)bp;
			} else {
				(void) memcpy((char *)fp->_ptr, ptr, copy);
				ptr += copy;
				fp->_ptr += copy;
			}
		}
		if (bytes > 0)	/* more to write, but buffer is full */
			if (putc((putc_t)*ptr, fp) == EOF) /* flush buffer */
				break;
			else {
				ptr++;
				--bytes;
			}
	}
	return size == 0? count: (origbytes - bytes) / size;
}


syntax highlighted by Code2HTML, v. 0.9.1