ReactOS 0.4.16-dev-1063-gd722e70
fread.cpp File Reference
Include dependency graph for fread.cpp:

Go to the source code of this file.

Macros

#define _BUFFER_FILL_PATTERN   0
 

Functions

size_t __cdecl fread_s (void *const buffer, size_t const buffer_size, size_t const element_size, size_t const element_count, FILE *const stream)
 
size_t __cdecl _fread_nolock_s (void *const buffer, size_t const buffer_size, size_t const element_size, size_t const element_count, FILE *const public_stream)
 
size_t __cdecl fread (void *const buffer, size_t const element_size, size_t const element_count, FILE *const stream)
 
size_t __cdecl _fread_nolock (void *const buffer, size_t const element_size, size_t const element_count, FILE *const stream)
 

Macro Definition Documentation

◆ _BUFFER_FILL_PATTERN

#define _BUFFER_FILL_PATTERN   0

Definition at line 14 of file fread.cpp.

Function Documentation

◆ _fread_nolock()

size_t __cdecl _fread_nolock ( void *const  buffer,
size_t const  element_size,
size_t const  element_count,
FILE *const  stream 
)

Definition at line 245 of file fread.cpp.

251{
252 // Assume there is enough space in the destination buffer
253#pragma warning(suppress:__WARNING_POTENTIAL_BUFFER_OVERFLOW_HIGH_PRIORITY) // 26015 - _fread_nolock is unsafe
255}
#define _CRT_UNBOUNDED_BUFFER_SIZE
size_t const element_size
Definition: debug_heap.cpp:510
size_t __cdecl _fread_nolock_s(void *const buffer, size_t const buffer_size, size_t const element_size, size_t const element_count, FILE *const public_stream)
Definition: fread.cpp:69
GLuint buffer
Definition: glext.h:5915
Definition: parse.h:23

◆ _fread_nolock_s()

size_t __cdecl _fread_nolock_s ( void *const  buffer,
size_t const  buffer_size,
size_t const  element_size,
size_t const  element_count,
FILE *const  public_stream 
)

Definition at line 69 of file fread.cpp.

76{
77 __crt_stdio_stream const stream(public_stream);
78
79 if (element_size == 0 || element_count == 0)
80 return 0;
81
82 _VALIDATE_RETURN(buffer != nullptr, EINVAL, 0);
83 if (!stream.valid() || element_count > (SIZE_MAX / element_size))
84 {
87
88 _VALIDATE_RETURN(stream.valid(), EINVAL, 0);
89 _VALIDATE_RETURN(element_count <= (SIZE_MAX / element_size), EINVAL, 0);
90 }
91
92 // Figure out how big the buffer is; if the stream doesn't currently have a
93 // buffer, we assume that we'll get one with the usual internal buffer size:
94 unsigned stream_buffer_size = stream.has_any_buffer()
95 ? stream->_bufsiz
97
98 // The total number of bytes to be read into the buffer:
99 size_t const total_bytes = element_size * element_count;
100
101 char* data = static_cast<char*>(buffer);
102
103 // Read blocks of data from the stream until we have read the requested
104 // number of elements or we fill the buffer.
105 size_t remaining_bytes = total_bytes;
106 size_t remaining_buffer = buffer_size;
107 while (remaining_bytes != 0)
108 {
109 // If the stream is buffered and has characters, copy them into the
110 // result buffer:
111 if (stream.has_any_buffer() && stream->_cnt != 0)
112 {
113 if(stream->_cnt < 0)
114 {
115 _ASSERTE(("Inconsistent Stream Count. Flush between consecutive read and write", stream->_cnt >= 0));
116 stream.set_flags(_IOERROR);
117 return (total_bytes - remaining_bytes) / element_size;
118 }
119
120 unsigned const bytes_to_read = remaining_bytes < static_cast<size_t>(stream->_cnt)
121 ? static_cast<unsigned>(remaining_bytes)
122 : static_cast<unsigned>(stream->_cnt);
123
124 if (bytes_to_read > remaining_buffer)
125 {
128
129 _VALIDATE_RETURN(("buffer too small", 0), ERANGE, 0)
130 }
131
132 memcpy_s(data, remaining_buffer, stream->_ptr, bytes_to_read);
133
134 // Update the stream and local tracking variables to account for the
135 // read. Note that the number of bytes actually read is always equal
136 // to the number of bytes that we expected to read, because the data
137 // was already buffered in the stream.
138 remaining_bytes -= bytes_to_read;
139 stream->_cnt -= bytes_to_read;
140 stream->_ptr += bytes_to_read;
141 data += bytes_to_read;
142 remaining_buffer -= bytes_to_read;
143 }
144 // There is no data remaining in the stream buffer to be read, and we
145 // need to read more data than will fit in the buffer (or we need to read
146 // at least enough data to fill the buffer completely):
147 else if (remaining_bytes >= stream_buffer_size)
148 {
149 // We can read at most INT_MAX bytes at a time. This is a hard limit
150 // of the lowio _read() function.
151 unsigned const maximum_bytes_to_read = remaining_bytes > INT_MAX
152 ? static_cast<unsigned>(INT_MAX)
153 : static_cast<unsigned>(remaining_bytes);
154
155 // If the stream has a buffer, we want to read the largest chunk that
156 // is a multiple of the buffer size, to keep the stream buffer state
157 // consistent. If the stream is not buffered, we can read the maximum
158 // number of bytes that we can:
159 unsigned const bytes_to_read = stream_buffer_size != 0
160 ? static_cast<unsigned>(maximum_bytes_to_read - maximum_bytes_to_read % stream_buffer_size)
161 : maximum_bytes_to_read;
162
163 if (bytes_to_read > remaining_buffer)
164 {
167
168 _VALIDATE_RETURN(("buffer too small", 0), ERANGE, 0)
169 }
170
171 // We are about to read data directly from the underlying file
172 // descriptor, bypassing the stream buffer. We reset the stream
173 // buffer state to ensure that future seeks do not incorrectly
174 // assume that the buffer contents are valid.
176
177 // Do the read. Note that if the stream is open in text mode, the
178 // bytes_read may not be the same as the bytes_to_read, due to
179 // newline translation.
180 int const bytes_read = _read_nolock(_fileno(stream.public_stream()), data, bytes_to_read);
181 if (bytes_read == 0)
182 {
183 // We encountered EOF:
184 stream.set_flags(_IOEOF);
185 return (total_bytes - remaining_bytes) / element_size;
186 }
187 else if (bytes_read < 0)
188 {
189 // The _read failed:
190 stream.set_flags(_IOERROR);
191 return (total_bytes - remaining_bytes) / element_size;
192 }
193
194 // Update the iteration state to reflect the read:
195 remaining_bytes -= bytes_read;
196 data += bytes_read;
197 remaining_buffer -= bytes_read;
198 }
199 // Otherwise, the stream does not have a buffer, or the stream buffer
200 // is full and there is insufficient space to do a direct read, so use
201 // __acrt_stdio_refill_and_read_narrow_nolock:
202 else
203 {
204 int const c = __acrt_stdio_refill_and_read_narrow_nolock(stream.public_stream());
205 if (c == EOF)
206 return (total_bytes - remaining_bytes) / element_size;
207
208 // If we have filled the result buffer before we have read the
209 // requested number of elements or reached EOF, it is an error:
210 if (remaining_buffer == 0)
211 {
214
215 _VALIDATE_RETURN(("buffer too small", 0), ERANGE, 0)
216 }
217
218 *data++ = static_cast<char>(c);
219 --remaining_bytes;
220 --remaining_buffer;
221
222 stream_buffer_size = stream->_bufsiz;
223 }
224 }
225
226 return element_count; // Success!
227}
int __cdecl __acrt_stdio_refill_and_read_narrow_nolock(FILE *const stream)
Definition: _filbuf.cpp:178
#define EINVAL
Definition: acclib.h:90
#define ERANGE
Definition: acclib.h:92
#define _INTERNAL_BUFSIZ
void __cdecl __acrt_stdio_reset_buffer(__crt_stdio_stream const stream)
#define _VALIDATE_RETURN(expr, errorcode, retexpr)
#define _ASSERTE(expr)
Definition: crtdbg.h:114
#define _BUFFER_FILL_PATTERN
Definition: fread.cpp:14
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
const GLubyte * c
Definition: glext.h:8905
_Check_return_ _CRTIMP int __cdecl _fileno(_In_ FILE *_File)
#define EOF
Definition: stdio.h:24
#define _IOEOF
Definition: stdio.h:132
#define INT_MAX
Definition: intsafe.h:150
#define c
Definition: ke_i.h:80
#define SIZE_MAX
Definition: compat.h:66
int CDECL memcpy_s(void *dest, size_t numberOfElements, const void *src, size_t count)
Definition: heap.c:800
#define memset(x, y, z)
Definition: compat.h:39
int __cdecl _read_nolock(int const fh, void *const result_buffer, unsigned const result_buffer_size)
Definition: read.cpp:408
wchar_t const *const size_t const buffer_size
Definition: stat.cpp:95

Referenced by _fread_nolock(), and fread_s().

◆ fread()

size_t __cdecl fread ( void *const  buffer,
size_t const  element_size,
size_t const  element_count,
FILE *const  stream 
)

Definition at line 231 of file fread.cpp.

237{
238 // Assume there is enough space in the destination buffer
239#pragma warning(suppress:__WARNING_POTENTIAL_BUFFER_OVERFLOW_HIGH_PRIORITY) // 26015 - fread is unsafe
241}
size_t __cdecl fread_s(void *const buffer, size_t const buffer_size, size_t const element_size, size_t const element_count, FILE *const stream)
Definition: fread.cpp:30

◆ fread_s()

size_t __cdecl fread_s ( void *const  buffer,
size_t const  buffer_size,
size_t const  element_size,
size_t const  element_count,
FILE *const  stream 
)

Definition at line 30 of file fread.cpp.

37{
38 if (element_size == 0 || element_count == 0)
39 return 0;
40
41 // The rest of the argument validation is done in the _nolock function. Here
42 // we only need to validate that the stream is non-null before we lock it.
43 if (stream == nullptr)
44 {
47
48 _VALIDATE_RETURN(stream != nullptr, EINVAL, 0);
49 }
50
51 size_t return_value = 0;
52
54 __try
55 {
56 return_value = _fread_nolock_s(buffer, buffer_size, element_size, element_count, stream);
57 }
59 {
61 }
63
64 return return_value;
65}
_CRTIMP void __cdecl _unlock_file(_Inout_ FILE *_File)
_CRTIMP void __cdecl _lock_file(_Inout_ FILE *_File)
#define __try
Definition: pseh2_64.h:188
#define __endtry
Definition: pseh2_64.h:191
#define __finally
Definition: pseh2_64.h:190

Referenced by fread().