1570af302Sopenharmony_ci#include "stdio_impl.h"
2570af302Sopenharmony_ci#include <string.h>
3570af302Sopenharmony_ci#ifndef __LITEOS__
4570af302Sopenharmony_ci#include "param_check.h"
5570af302Sopenharmony_ci#endif
6570af302Sopenharmony_ci
7570af302Sopenharmony_ci#define MIN(a,b) ((a)<(b) ? (a) : (b))
8570af302Sopenharmony_ci
9570af302Sopenharmony_ciint __fill_buffer(FILE *f)
10570af302Sopenharmony_ci{
11570af302Sopenharmony_ci	int r = __toread(f);
12570af302Sopenharmony_ci	if (r != 0) {
13570af302Sopenharmony_ci		return r;
14570af302Sopenharmony_ci	}
15570af302Sopenharmony_ci
16570af302Sopenharmony_ci	int k = f->readx(f, f->buf, f->buf_size);
17570af302Sopenharmony_ci	if (k <= 0) {
18570af302Sopenharmony_ci		f->flags |= (k == 0) ? F_EOF : F_ERR;
19570af302Sopenharmony_ci		f->rpos = f->rend;
20570af302Sopenharmony_ci		return k;
21570af302Sopenharmony_ci	}
22570af302Sopenharmony_ci
23570af302Sopenharmony_ci	f->rpos = f->buf;
24570af302Sopenharmony_ci	f->rend = f->rpos + k;
25570af302Sopenharmony_ci
26570af302Sopenharmony_ci	return 0;
27570af302Sopenharmony_ci}
28570af302Sopenharmony_ci
29570af302Sopenharmony_cisize_t fread(void *restrict destv, size_t size, size_t nmemb, FILE *restrict f)
30570af302Sopenharmony_ci{
31570af302Sopenharmony_ci#ifndef __LITEOS__
32570af302Sopenharmony_ci	PARAM_CHECK(f);
33570af302Sopenharmony_ci#endif
34570af302Sopenharmony_ci	unsigned char *dest = destv;
35570af302Sopenharmony_ci	size_t len = size * nmemb, l = len, k;
36570af302Sopenharmony_ci	if (!size) {
37570af302Sopenharmony_ci		nmemb = 0;
38570af302Sopenharmony_ci	}
39570af302Sopenharmony_ci
40570af302Sopenharmony_ci	FLOCK(f);
41570af302Sopenharmony_ci
42570af302Sopenharmony_ci	/* allocate file buffer if needed */
43570af302Sopenharmony_ci	if (__falloc_buf(f) < 0) {
44570af302Sopenharmony_ci		f->flags |= F_ERR;
45570af302Sopenharmony_ci		goto exit;
46570af302Sopenharmony_ci	}
47570af302Sopenharmony_ci
48570af302Sopenharmony_ci	f->mode |= f->mode-1;
49570af302Sopenharmony_ci
50570af302Sopenharmony_ci	while (l > 0) {
51570af302Sopenharmony_ci		if (f->rpos != f->rend) {
52570af302Sopenharmony_ci			/* First exhaust the buffer. */
53570af302Sopenharmony_ci			k = MIN(f->rend - f->rpos, l);
54570af302Sopenharmony_ci			memcpy(dest, f->rpos, k);
55570af302Sopenharmony_ci			f->rpos += k;
56570af302Sopenharmony_ci			dest += k;
57570af302Sopenharmony_ci			l -= k;
58570af302Sopenharmony_ci		}
59570af302Sopenharmony_ci		/* done */
60570af302Sopenharmony_ci		if (l == 0) {
61570af302Sopenharmony_ci			goto exit;
62570af302Sopenharmony_ci		}
63570af302Sopenharmony_ci		/* if user buffer is longer than file buffer,
64570af302Sopenharmony_ci		 * maybe buffer size is 0, non-buffer mode,
65570af302Sopenharmony_ci		 * read directly */
66570af302Sopenharmony_ci		if (l > f->buf_size) {
67570af302Sopenharmony_ci			break;
68570af302Sopenharmony_ci		}
69570af302Sopenharmony_ci
70570af302Sopenharmony_ci		if (__fill_buffer(f)) {
71570af302Sopenharmony_ci			goto exit;
72570af302Sopenharmony_ci		}
73570af302Sopenharmony_ci	}
74570af302Sopenharmony_ci
75570af302Sopenharmony_ci	/* Read the remainder directly */
76570af302Sopenharmony_ci	for (; l; l-=k, dest+=k) {
77570af302Sopenharmony_ci		k = f->readx(f, dest, l);
78570af302Sopenharmony_ci		if (!k) {
79570af302Sopenharmony_ci			break;
80570af302Sopenharmony_ci		}
81570af302Sopenharmony_ci	}
82570af302Sopenharmony_ci
83570af302Sopenharmony_ciexit:
84570af302Sopenharmony_ci	FUNLOCK(f);
85570af302Sopenharmony_ci	return (len - l) / size;
86570af302Sopenharmony_ci}
87570af302Sopenharmony_ci
88570af302Sopenharmony_ciweak_alias(fread, fread_unlocked);
89