Subversion Repositories Kolibri OS

Rev

Rev 4921 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 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
/*
19
FUNCTION
6099 serge 20
<>, <>---read array elements from a file
4349 Serge 21
 
22
INDEX
23
	fread
24
INDEX
6099 serge 25
	fread_unlocked
26
INDEX
4349 Serge 27
	_fread_r
6099 serge 28
INDEX
29
	_fread_unlocked_r
4349 Serge 30
 
31
ANSI_SYNOPSIS
32
	#include 
4921 Serge 33
	size_t fread(void *restrict <[buf]>, size_t <[size]>, size_t <[count]>,
34
		     FILE *restrict <[fp]>);
4349 Serge 35
 
6099 serge 36
	#define _BSD_SOURCE
4349 Serge 37
	#include 
6099 serge 38
	size_t fread_unlocked(void *restrict <[buf]>, size_t <[size]>, size_t <[count]>,
39
		     FILE *restrict <[fp]>);
40
 
41
	#include 
4921 Serge 42
	size_t _fread_r(struct _reent *<[ptr]>, void *restrict <[buf]>,
43
	                size_t <[size]>, size_t <[count]>, FILE *restrict <[fp]>);
4349 Serge 44
 
6099 serge 45
	#include 
46
	size_t _fread_unlocked_r(struct _reent *<[ptr]>, void *restrict <[buf]>,
47
	                size_t <[size]>, size_t <[count]>, FILE *restrict <[fp]>);
48
 
4349 Serge 49
TRAD_SYNOPSIS
50
	#include 
51
	size_t fread(<[buf]>, <[size]>, <[count]>, <[fp]>)
52
	char *<[buf]>;
53
	size_t <[size]>;
54
	size_t <[count]>;
55
	FILE *<[fp]>;
56
 
6099 serge 57
	#define _BSD_SOURCE
4349 Serge 58
	#include 
6099 serge 59
	size_t fread_unlocked(<[buf]>, <[size]>, <[count]>, <[fp]>)
60
	char *<[buf]>;
61
	size_t <[size]>;
62
	size_t <[count]>;
63
	FILE *<[fp]>;
64
 
65
	#include 
4349 Serge 66
	size_t _fread_r(<[ptr]>, <[buf]>, <[size]>, <[count]>, <[fp]>)
67
	struct _reent *<[ptr]>;
68
	char *<[buf]>;
69
	size_t <[size]>;
70
	size_t <[count]>;
71
	FILE *<[fp]>;
72
 
6099 serge 73
	#include 
74
	size_t _fread_unlocked_r(<[ptr]>, <[buf]>, <[size]>, <[count]>, <[fp]>)
75
	struct _reent *<[ptr]>;
76
	char *<[buf]>;
77
	size_t <[size]>;
78
	size_t <[count]>;
79
	FILE *<[fp]>;
80
 
4349 Serge 81
DESCRIPTION
82
<> attempts to copy, from the file or stream identified by
83
<[fp]>, <[count]> elements (each of size <[size]>) into memory,
84
starting at <[buf]>.   <> may copy fewer elements than
85
<[count]> if an error, or end of file, intervenes.
86
 
87
<> also advances the file position indicator (if any) for
88
<[fp]> by the number of @emph{characters} actually read.
89
 
6099 serge 90
<> is a non-thread-safe version of <>.
91
<> may only safely be used within a scope
92
protected by flockfile() (or ftrylockfile()) and funlockfile().  This
93
function may safely be used in a multi-threaded program if and only
94
if they are called while the invoking thread owns the (FILE *)
95
object, as is the case after a successful call to the flockfile() or
96
ftrylockfile() functions.  If threads are disabled, then
97
<> is equivalent to <>.
4349 Serge 98
 
6099 serge 99
<<_fread_r>> and <<_fread_unlocked_r>> are simply reentrant versions of the
100
above that take an additional reentrant structure pointer argument: <[ptr]>.
101
 
4349 Serge 102
RETURNS
103
The result of <> is the number of elements it succeeded in
104
reading.
105
 
106
PORTABILITY
107
ANSI C requires <>.
108
 
6099 serge 109
<> is a BSD extension also provided by GNU libc.
110
 
4349 Serge 111
Supporting OS subroutines required: <>, <>, <>,
112
<>, <>, <>, <>.
113
*/
114
 
115
#include <_ansi.h>
116
#include 
117
#include 
118
#include 
119
#include "local.h"
120
 
6099 serge 121
#ifdef __IMPL_UNLOCKED__
122
#define _fread_r _fread_unlocked_r
123
#define fread fread_unlocked
124
#endif
125
 
4349 Serge 126
#ifdef __SCLE
127
static size_t
128
_DEFUN(crlf_r, (ptr, fp, buf, count, eof),
129
       struct _reent * ptr _AND
130
       FILE * fp _AND
131
       char * buf _AND
132
       size_t count _AND
133
       int eof)
134
{
135
  int r;
136
  char *s, *d, *e;
137
 
138
  if (count == 0)
139
    return 0;
140
 
141
  e = buf + count;
142
  for (s=d=buf; s
143
    {
144
      if (*s == '\r' && s[1] == '\n')
145
        s++;
146
      *d++ = *s;
147
    }
148
  if (s < e)
149
    {
150
      if (*s == '\r')
151
        {
152
          int c = __sgetc_raw_r (ptr, fp);
153
          if (c == '\n')
154
            *s = '\n';
155
          else
156
            ungetc (c, fp);
157
        }
158
      *d++ = *s++;
159
    }
160
 
161
 
162
  while (d < e)
163
    {
164
      r = _getc_r (ptr, fp);
165
      if (r == EOF)
166
        return count - (e-d);
167
      *d++ = r;
168
    }
169
 
170
  return count;
171
 
172
}
173
 
174
#endif
175
 
176
size_t
177
_DEFUN(_fread_r, (ptr, buf, size, count, fp),
178
       struct _reent * ptr _AND
4921 Serge 179
       _PTR __restrict buf _AND
4349 Serge 180
       size_t size _AND
181
       size_t count _AND
4921 Serge 182
       FILE * __restrict fp)
4349 Serge 183
{
184
  register size_t resid;
185
  register char *p;
186
  register int r;
187
  size_t total;
188
 
189
  if ((resid = count * size) == 0)
190
    return 0;
191
 
192
  CHECK_INIT(ptr, fp);
193
 
4921 Serge 194
  _newlib_flockfile_start (fp);
4349 Serge 195
  ORIENT (fp, -1);
196
  if (fp->_r < 0)
197
    fp->_r = 0;
198
  total = resid;
199
  p = buf;
200
 
201
#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
202
 
203
  /* Optimize unbuffered I/O.  */
204
  if (fp->_flags & __SNBF)
205
    {
206
      /* First copy any available characters from ungetc buffer.  */
207
      int copy_size = resid > fp->_r ? fp->_r : resid;
208
      _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, (size_t) copy_size);
209
      fp->_p += copy_size;
210
      fp->_r -= copy_size;
211
      p += copy_size;
212
      resid -= copy_size;
213
 
214
      /* If still more data needed, free any allocated ungetc buffer.  */
215
      if (HASUB (fp) && resid > 0)
216
	FREEUB (ptr, fp);
217
 
218
      /* Finally read directly into user's buffer if needed.  */
219
      while (resid > 0)
220
	{
221
	  int rc = 0;
222
	  /* save fp buffering state */
223
	  void *old_base = fp->_bf._base;
224
	  void * old_p = fp->_p;
225
	  int old_size = fp->_bf._size;
226
	  /* allow __refill to use user's buffer */
227
	  fp->_bf._base = (unsigned char *) p;
228
	  fp->_bf._size = resid;
229
	  fp->_p = (unsigned char *) p;
230
	  rc = __srefill_r (ptr, fp);
231
	  /* restore fp buffering back to original state */
232
	  fp->_bf._base = old_base;
233
	  fp->_bf._size = old_size;
234
	  fp->_p = old_p;
235
	  resid -= fp->_r;
236
	  p += fp->_r;
237
	  fp->_r = 0;
238
	  if (rc)
239
	    {
240
#ifdef __SCLE
241
              if (fp->_flags & __SCLE)
242
	        {
4921 Serge 243
	          _newlib_flockfile_exit (fp);
4349 Serge 244
	          return crlf_r (ptr, fp, buf, total-resid, 1) / size;
245
	        }
246
#endif
4921 Serge 247
	      _newlib_flockfile_exit (fp);
4349 Serge 248
	      return (total - resid) / size;
249
	    }
250
	}
251
    }
252
  else
253
#endif /* !PREFER_SIZE_OVER_SPEED && !__OPTIMIZE_SIZE__ */
254
    {
255
      while (resid > (r = fp->_r))
256
	{
257
	  _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, (size_t) r);
258
	  fp->_p += r;
259
	  /* fp->_r = 0 ... done in __srefill */
260
	  p += r;
261
	  resid -= r;
262
	  if (__srefill_r (ptr, fp))
263
	    {
264
	      /* no more input: return partial result */
265
#ifdef __SCLE
266
	      if (fp->_flags & __SCLE)
267
		{
4921 Serge 268
		  _newlib_flockfile_exit (fp);
4349 Serge 269
		  return crlf_r (ptr, fp, buf, total-resid, 1) / size;
270
		}
271
#endif
4921 Serge 272
	      _newlib_flockfile_exit (fp);
4349 Serge 273
	      return (total - resid) / size;
274
	    }
275
	}
276
      _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, resid);
277
      fp->_r -= resid;
278
      fp->_p += resid;
279
    }
280
 
281
  /* Perform any CR/LF clean-up if necessary.  */
282
#ifdef __SCLE
283
  if (fp->_flags & __SCLE)
284
    {
4921 Serge 285
      _newlib_flockfile_exit (fp);
4349 Serge 286
      return crlf_r(ptr, fp, buf, total, 0) / size;
287
    }
288
#endif
4921 Serge 289
  _newlib_flockfile_end (fp);
4349 Serge 290
  return count;
291
}
292
 
293
#ifndef _REENT_ONLY
294
size_t
295
_DEFUN(fread, (buf, size, count, fp),
4921 Serge 296
       _PTR __restrict  buf _AND
4349 Serge 297
       size_t size _AND
298
       size_t count _AND
4921 Serge 299
       FILE *__restrict fp)
4349 Serge 300
{
301
   return _fread_r (_REENT, buf, size, count, fp);
302
}
303
#endif