source: trunk/libs/newlib/src/newlib/libc/stdio/fread.c @ 567

Last change on this file since 567 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 6.7 KB
Line 
1/*
2 * Copyright (c) 1990, 2007 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley.  The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18/*
19FUNCTION
20<<fread>>, <<fread_unlocked>>---read array elements from a file
21
22INDEX
23        fread
24INDEX
25        fread_unlocked
26INDEX
27        _fread_r
28INDEX
29        _fread_unlocked_r
30
31SYNOPSIS
32        #include <stdio.h>
33        size_t fread(void *restrict <[buf]>, size_t <[size]>, size_t <[count]>,
34                     FILE *restrict <[fp]>);
35
36        #define _BSD_SOURCE
37        #include <stdio.h>
38        size_t fread_unlocked(void *restrict <[buf]>, size_t <[size]>, size_t <[count]>,
39                     FILE *restrict <[fp]>);
40
41        #include <stdio.h>
42        size_t _fread_r(struct _reent *<[ptr]>, void *restrict <[buf]>,
43                        size_t <[size]>, size_t <[count]>, FILE *restrict <[fp]>);
44
45        #include <stdio.h>
46        size_t _fread_unlocked_r(struct _reent *<[ptr]>, void *restrict <[buf]>,
47                        size_t <[size]>, size_t <[count]>, FILE *restrict <[fp]>);
48
49DESCRIPTION
50<<fread>> attempts to copy, from the file or stream identified by
51<[fp]>, <[count]> elements (each of size <[size]>) into memory,
52starting at <[buf]>.   <<fread>> may copy fewer elements than
53<[count]> if an error, or end of file, intervenes.
54
55<<fread>> also advances the file position indicator (if any) for
56<[fp]> by the number of @emph{characters} actually read.
57
58<<fread_unlocked>> is a non-thread-safe version of <<fread>>.
59<<fread_unlocked>> may only safely be used within a scope
60protected by flockfile() (or ftrylockfile()) and funlockfile().  This
61function may safely be used in a multi-threaded program if and only
62if they are called while the invoking thread owns the (FILE *)
63object, as is the case after a successful call to the flockfile() or
64ftrylockfile() functions.  If threads are disabled, then
65<<fread_unlocked>> is equivalent to <<fread>>.
66
67<<_fread_r>> and <<_fread_unlocked_r>> are simply reentrant versions of the
68above that take an additional reentrant structure pointer argument: <[ptr]>.
69
70RETURNS
71The result of <<fread>> is the number of elements it succeeded in
72reading.
73
74PORTABILITY
75ANSI C requires <<fread>>.
76
77<<fread_unlocked>> is a BSD extension also provided by GNU libc.
78
79Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
80<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
81*/
82
83#include <_ansi.h>
84#include <stdio.h>
85#include <string.h>
86#include <malloc.h>
87#include "local.h"
88
89#ifdef __IMPL_UNLOCKED__
90#define _fread_r _fread_unlocked_r
91#define fread fread_unlocked
92#endif
93
94#ifdef __SCLE
95static size_t
96crlf_r (struct _reent * ptr,
97       FILE * fp,
98       char * buf,
99       size_t count,
100       int eof)
101{
102  int r;
103  char *s, *d, *e;
104
105  if (count == 0)
106    return 0;
107
108  e = buf + count;
109  for (s=d=buf; s<e-1; s++)
110    {
111      if (*s == '\r' && s[1] == '\n')
112        s++;
113      *d++ = *s;
114    }
115  if (s < e)
116    {
117      if (*s == '\r')
118        {
119          int c = __sgetc_raw_r (ptr, fp);
120          if (c == '\n')
121            *s = '\n';
122          else
123            ungetc (c, fp);
124        }
125      *d++ = *s++;
126    }
127
128
129  while (d < e)
130    {
131      r = _getc_r (ptr, fp);
132      if (r == EOF)
133        return count - (e-d);
134      *d++ = r;
135    }
136
137  return count;
138 
139}
140
141#endif
142
143size_t
144_fread_r (struct _reent * ptr,
145       void *__restrict buf,
146       size_t size,
147       size_t count,
148       FILE * __restrict fp)
149{
150  register size_t resid;
151  register char *p;
152  register int r;
153  size_t total;
154
155  if ((resid = count * size) == 0)
156    return 0;
157
158  CHECK_INIT(ptr, fp);
159
160  _newlib_flockfile_start (fp);
161  ORIENT (fp, -1);
162  if (fp->_r < 0)
163    fp->_r = 0;
164  total = resid;
165  p = buf;
166
167#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
168
169  /* Optimize unbuffered I/O.  */
170  if (fp->_flags & __SNBF)
171    {
172      /* First copy any available characters from ungetc buffer.  */
173      int copy_size = resid > fp->_r ? fp->_r : resid;
174      (void) memcpy ((void *) p, (void *) fp->_p, (size_t) copy_size);
175      fp->_p += copy_size;
176      fp->_r -= copy_size;
177      p += copy_size;
178      resid -= copy_size;
179
180      /* If still more data needed, free any allocated ungetc buffer.  */
181      if (HASUB (fp) && resid > 0)
182        FREEUB (ptr, fp);
183
184      /* Finally read directly into user's buffer if needed.  */
185      while (resid > 0)
186        {
187          int rc = 0;
188          /* save fp buffering state */
189          void *old_base = fp->_bf._base;
190          void * old_p = fp->_p;
191          int old_size = fp->_bf._size;
192          /* allow __refill to use user's buffer */
193          fp->_bf._base = (unsigned char *) p;
194          fp->_bf._size = resid;
195          fp->_p = (unsigned char *) p;
196          rc = __srefill_r (ptr, fp);
197          /* restore fp buffering back to original state */
198          fp->_bf._base = old_base;
199          fp->_bf._size = old_size;
200          fp->_p = old_p;
201          resid -= fp->_r;
202          p += fp->_r;
203          fp->_r = 0;
204          if (rc)
205            {
206#ifdef __SCLE
207              if (fp->_flags & __SCLE)
208                {
209                  _newlib_flockfile_exit (fp);
210                  return crlf_r (ptr, fp, buf, total-resid, 1) / size;
211                }
212#endif
213              _newlib_flockfile_exit (fp);
214              return (total - resid) / size;
215            }
216        }
217    }
218  else
219#endif /* !PREFER_SIZE_OVER_SPEED && !__OPTIMIZE_SIZE__ */
220    {
221      while (resid > (r = fp->_r))
222        {
223          (void) memcpy ((void *) p, (void *) fp->_p, (size_t) r);
224          fp->_p += r;
225          /* fp->_r = 0 ... done in __srefill */
226          p += r;
227          resid -= r;
228          if (__srefill_r (ptr, fp))
229            {
230              /* no more input: return partial result */
231#ifdef __SCLE
232              if (fp->_flags & __SCLE)
233                {
234                  _newlib_flockfile_exit (fp);
235                  return crlf_r (ptr, fp, buf, total-resid, 1) / size;
236                }
237#endif
238              _newlib_flockfile_exit (fp);
239              return (total - resid) / size;
240            }
241        }
242      (void) memcpy ((void *) p, (void *) fp->_p, resid);
243      fp->_r -= resid;
244      fp->_p += resid;
245    }
246
247  /* Perform any CR/LF clean-up if necessary.  */
248#ifdef __SCLE
249  if (fp->_flags & __SCLE)
250    {
251      _newlib_flockfile_exit (fp);
252      return crlf_r(ptr, fp, buf, total, 0) / size;
253    }
254#endif
255  _newlib_flockfile_end (fp);
256  return count;
257}
258
259#ifndef _REENT_ONLY
260size_t
261fread (void *__restrict  buf,
262       size_t size,
263       size_t count,
264       FILE *__restrict fp)
265{
266   return _fread_r (_REENT, buf, size, count, fp);
267}
268#endif
Note: See TracBrowser for help on using the repository browser.