Rev 7172 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
647 | andrew_pro | 1 | #include |
7184 | siemargl | 2 | #include |
3 | #include |
||
647 | andrew_pro | 4 | #include |
5 | |||
6 | int fread(void *buffer,int size,int count,FILE* file) |
||
7 | { |
||
7184 | siemargl | 8 | dword res, readbytes; |
9 | dword fullsize, read4cache, toread, readcount; |
||
647 | andrew_pro | 10 | |
6433 | siemargl | 11 | if(!file || !buffer) |
12 | { |
||
13 | errno = E_INVALIDPTR; |
||
14 | return 0; |
||
15 | } |
||
647 | andrew_pro | 16 | |
7172 | siemargl | 17 | if ((file->mode &3)!=FILE_OPEN_READ && (file->mode & FILE_OPEN_PLUS)==0) |
6433 | siemargl | 18 | { |
19 | errno = E_ACCESS; |
||
20 | return 0; |
||
21 | } |
||
22 | |||
647 | andrew_pro | 23 | fullsize=count*size; |
7184 | siemargl | 24 | if (fullsize + file->filepos >= file->filesize) |
647 | andrew_pro | 25 | { |
7184 | siemargl | 26 | fullsize=file->filesize - file->filepos; |
27 | if (fullsize <= 0) return 0; |
||
647 | andrew_pro | 28 | } |
29 | |||
7184 | siemargl | 30 | /***** file buffering strategy, just read forward ***** |
31 | if we read small part - read full buffer, but if buffer have this data - dont read again nothing (or partial read forward 4k pages) |
||
32 | any writes drops buffers as ungetc_buf */ |
||
33 | read4cache = 0; |
||
34 | readcount = 0; |
||
35 | if (file->filepos >= file->buffer_start && file->filepos < file->buffer_end) |
||
6433 | siemargl | 36 | { |
7184 | siemargl | 37 | read4cache = min(file->buffer_end - file->filepos, fullsize); |
38 | memcpy(buffer, file->buffer + file->filepos - file->buffer_start, read4cache); |
||
39 | file->filepos += read4cache; |
||
40 | if (file->ungetc_buf != EOF) // subst ungetc byte |
||
41 | { |
||
42 | *((char*)buffer) = (char)file->ungetc_buf; |
||
43 | file->ungetc_buf = EOF; |
||
44 | } |
||
45 | buffer += read4cache; // ! advance |
||
46 | fullsize -= read4cache; |
||
47 | readcount = read4cache / size; |
||
647 | andrew_pro | 48 | } |
7184 | siemargl | 49 | |
50 | toread = max(fullsize, file->buffersize); |
||
51 | if (toread + file->filepos >= file->filesize) |
||
52 | { |
||
53 | toread = file->filesize - file->filepos; |
||
54 | } |
||
55 | |||
56 | if (fullsize <= 0 || toread <= 0) |
||
57 | res = 0; // already read or file end |
||
6433 | siemargl | 58 | else |
7184 | siemargl | 59 | { |
60 | file->buffer_start = file->filepos; |
||
61 | if (toread <= fullsize) // read to bigger buffer |
||
62 | { |
||
63 | res = _ksys_readfile(file->filename, file->filepos, toread, buffer, &readbytes); |
||
64 | read4cache = min(readbytes, file->buffersize); |
||
65 | memcpy(file->buffer, buffer, read4cache); |
||
66 | file->filepos += readbytes; |
||
67 | } else |
||
68 | { |
||
69 | res = _ksys_readfile(file->filename, file->filepos, toread, file->buffer, &readbytes); |
||
70 | read4cache = readbytes; |
||
71 | memcpy(buffer, file->buffer, min(fullsize, read4cache)); |
||
72 | file->filepos += min(fullsize, read4cache); |
||
73 | } |
||
74 | file->buffer_end = file->buffer_start + read4cache; |
||
75 | if (readbytes >= fullsize) |
||
76 | readcount += fullsize / size; |
||
77 | else |
||
78 | readcount += readbytes / size; |
||
79 | } |
||
80 | |||
81 | if (file->ungetc_buf != EOF) // subst ungetc byte |
||
82 | { |
||
83 | *((char*)buffer) = (char)file->ungetc_buf; |
||
84 | file->ungetc_buf = EOF; |
||
85 | } |
||
86 | |||
87 | if (res != 0) |
||
6433 | siemargl | 88 | { |
7184 | siemargl | 89 | file->ungetc_buf = EOF; |
6433 | siemargl | 90 | errno = -res; |
91 | } |
||
7184 | siemargl | 92 | |
93 | return readcount; // really full readed plus cached items |
||
6433 | siemargl | 94 | }=>=>=>>=> |