.
[glibc/history.git] / stdio / fread.c
blobd2766f66166e05096cc033bea06fe2214827da31
1 /* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
19 #include <ansidecl.h>
20 #include <errno.h>
21 #include <stdio.h>
22 #include <string.h>
25 #define default_func __default_room_functions.__input
27 /* Read NMEMB chunks of SIZE bytes each from STREAM into P. */
28 size_t
29 DEFUN(fread, (p, size, nmemb, stream),
30 PTR p AND size_t size AND size_t nmemb AND register FILE *stream)
32 register char *ptr = (char *) p;
33 register size_t to_read = size * nmemb;
34 size_t bytes = to_read;
36 if (!__validfp(stream) || !stream->__mode.__read)
38 errno = EINVAL;
39 return 0;
41 if (feof(stream) || ferror(stream))
42 return 0;
43 if (p == NULL || to_read == 0)
44 return 0;
46 if (!stream->__seen || stream->__buffer == NULL || stream->__pushed_back)
48 /* This stream has never been seen before, or it has a character
49 pushed back. Call __fillbf to deal with those cases. Life will
50 be simpler after this call. */
51 int c = __fillbf(stream);
52 if (c == EOF)
53 return 0;
54 *ptr++ = c;
55 if (--to_read == 0)
56 return 1;
59 read_from_buffer:;
60 if (stream->__bufp < stream->__get_limit)
62 /* First off, empty out the buffer. */
63 register size_t copy = stream->__get_limit - stream->__bufp;
64 if (copy > to_read)
65 copy = to_read;
66 to_read -= copy;
67 if (copy > 20)
68 memcpy((PTR) ptr, (PTR) stream->__bufp, copy);
69 else
71 register size_t i;
72 for (i = 0; i < copy; ++i)
73 ptr[i] = stream->__bufp[i];
75 stream->__bufp += copy;
76 if (to_read == 0)
77 return nmemb;
78 ptr += copy;
81 /* Reading directly into the user's buffer doesn't help when
82 using a user-specified input buffer filling/expanding function,
83 so we don't do it in that case. */
84 if (to_read >= stream->__bufsize &&
85 stream->__room_funcs.__input == default_func &&
86 stream->__offset == stream->__target)
88 /* Read directly into the user's buffer. */
89 if (stream->__io_funcs.__read != NULL)
90 while (to_read > 0)
92 register int count;
93 count = (*stream->__io_funcs.__read)(stream->__cookie,
94 ptr, to_read);
95 if (count > 0)
97 to_read -= count;
98 if (stream->__offset != -1)
100 stream->__offset += count;
101 stream->__target += count;
103 ptr += count;
105 else if (count == 0)
107 stream->__eof = 1;
108 break;
110 else
112 stream->__error = 1;
113 break;
116 else
117 stream->__eof = 1;
119 else
121 int c = __fillbf(stream);
122 if (c == EOF)
123 return (bytes - to_read) / size;
124 *ptr++ = (char) c;
125 --to_read;
126 if (to_read > 0)
127 goto read_from_buffer;
130 return (bytes - to_read) / size;