ReactOS 0.4.16-dev-981-g80eb313
fwrite.cpp
Go to the documentation of this file.
1//
2// fwrite.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines fwrite() and related functions, which write unformatted data to a
7// stdio stream.
8//
11
12// Writes data from the provided buffer to the specified stream. The function
13// writes 'count' elements of 'size' size to the stream, and returns when
14// either all of the elements have been written or no more data can be written
15// (e.g. if EOF is encountered or an error occurs).
16//
17// Returns the number of "whole" elements that were written to the stream. This
18// may be fewer than the requested number of an error occurs or EOF is encountered.
19// In this case, ferror() or feof() should be used to distinguish between the two
20// conditions.
21extern "C" size_t __cdecl _fwrite_internal(
22 void const* const buffer,
23 size_t const size,
24 size_t const count,
25 FILE* const stream,
26 __crt_cached_ptd_host& ptd
27 )
28{
29 if (size == 0 || count == 0)
30 {
31 return 0;
32 }
33
34 // The _nolock version will do the rest of the validation.
35 _UCRT_VALIDATE_RETURN(ptd, stream != nullptr, EINVAL, 0);
36
37 return __acrt_lock_stream_and_call(stream, [&]() -> size_t
38 {
39 __acrt_stdio_temporary_buffering_guard const buffering(stream, ptd);
40
42 });
43}
44
45extern "C" size_t __cdecl fwrite(
46 void const* const buffer,
47 size_t const size,
48 size_t const count,
49 FILE* const stream
50 )
51{
52 __crt_cached_ptd_host ptd;
54}
55
57 void const* const buffer,
58 size_t const element_size,
59 size_t const element_count,
60 FILE* const public_stream,
61 __crt_cached_ptd_host& ptd
62 )
63{
64 if (element_size == 0 || element_count == 0)
65 {
66 return 0;
67 }
68
69 __crt_stdio_stream const stream(public_stream);
70
72 _UCRT_VALIDATE_RETURN(ptd, buffer != nullptr, EINVAL, 0);
73 _UCRT_VALIDATE_RETURN(ptd, element_count <= (SIZE_MAX / element_size), EINVAL, 0);
74
75 // Figure out how big the buffer is; if the stream doesn't currently have a
76 // buffer, we assume that we'll get one with the usual internal buffer size:
77 unsigned stream_buffer_size = stream.has_any_buffer()
78 ? stream->_bufsiz
80
81 // The total number of bytes to be written to the stream:
82 size_t const total_bytes = element_size * element_count;
83
84 char const* data = static_cast<char const*>(buffer);
85
86 // Write blocks of data from the buffer until there is no more data left:
87 size_t remaining_bytes = total_bytes;
88 while (remaining_bytes != 0)
89 {
90 // If the buffer is big and is not full, copy data into the buffer:
91 if (stream.has_big_buffer() && stream->_cnt != 0)
92 {
93 if (stream->_cnt < 0)
94 {
95 _ASSERTE(("Inconsistent Stream Count. Flush between consecutive read and write", stream->_cnt >= 0));
96 stream.set_flags(_IOERROR);
97 return (total_bytes - remaining_bytes) / element_size;
98 }
99
100 if (stream.has_any_of(_IOREAD))
101 {
102 _ASSERTE(("Flush between consecutive read and write.", !stream.has_any_of(_IOREAD)));
103 return (total_bytes - remaining_bytes) / element_size;
104 }
105
106 size_t const bytes_to_write = __min(remaining_bytes, static_cast<size_t>(stream->_cnt));
107
108 memcpy(stream->_ptr, data, bytes_to_write);
109
110 remaining_bytes -= bytes_to_write;
111 stream->_cnt -= static_cast<int>(bytes_to_write);
112 stream->_ptr += bytes_to_write;
113 data += bytes_to_write;
114 }
115 // If we have more than stream_buffer_size bytes to write, write data by
116 // calling _write() with an integral number of stream_buffer_size blocks.
117 else if (remaining_bytes >= stream_buffer_size)
118 {
119 // If we reach here and we have a big buffer, it must be full, so
120 // flush it. If the flush fails, there's nothing we can do to
121 // recover:
122 if (stream.has_big_buffer() && __acrt_stdio_flush_nolock(stream.public_stream(), ptd))
123 {
124 return (total_bytes - remaining_bytes) / element_size;
125 }
126
127 // Calculate the number of bytes to write. The _write API takes a
128 // 32-bit unsigned byte count and returns -1 (UINT_MAX) on failure,
129 // so clamp the value to UINT_MAX - 1:
130 size_t const max_bytes_to_write = stream_buffer_size > 0
131 ? remaining_bytes - remaining_bytes % stream_buffer_size
132 : remaining_bytes;
133
134 unsigned const bytes_to_write = static_cast<unsigned>(__min(max_bytes_to_write, UINT_MAX - 1));
135
136 unsigned const bytes_actually_written = _write_internal(_fileno(stream.public_stream()), data, bytes_to_write, ptd);
137 if (bytes_actually_written == UINT_MAX) // UINT_MAX == -1
138 {
139 stream.set_flags(_IOERROR);
140 return (total_bytes - remaining_bytes) / element_size;
141 }
142
143 // VSWhidbey #326224: _write can return more bytes than we requested
144 // due to Unicode conversions in text files. We do not care how many
145 // bytes were written as long as the number is as least as large as we
146 // requested:
147 unsigned const bytes_written = bytes_actually_written > bytes_to_write
148 ? bytes_to_write
149 : bytes_actually_written;
150
151 // Update the remaining bytes and data to reflect the write:
152 remaining_bytes -= bytes_written;
153 data += bytes_written;
154
155 if (bytes_actually_written < bytes_to_write)
156 {
157 stream.set_flags(_IOERROR);
158 return (total_bytes - remaining_bytes) / element_size;
159 }
160 }
161 // Otherwise, the stream does not have a buffer, or the buffer is full
162 // and there are not enough characters to do a direct write, so use
163 // __acrt_stdio_flush_and_write_narrow_nolock:
164 else
165 {
166 // Write the first character. If this fails, there is nothing we can
167 // do. (Note that if this fails, it will update the stream error state.)
169 {
170 return (total_bytes - remaining_bytes) / element_size;
171 }
172
173 // Update the remaining bytes to account for the byte we just wrote:
174 ++data;
175 --remaining_bytes;
176
177 stream_buffer_size = stream->_bufsiz > 0
178 ? stream->_bufsiz
179 : 1;
180 }
181 }
182
183 return element_count; // Success!
184}
185
186extern "C" size_t __cdecl _fwrite_nolock(
187 void const* const buffer,
188 size_t const element_size,
189 size_t const element_count,
190 FILE* const public_stream
191 )
192{
193 __crt_cached_ptd_host ptd;
194 return _fwrite_nolock_internal(buffer, element_size, element_count, public_stream, ptd);
195}
196
int __cdecl __acrt_stdio_flush_and_write_narrow_nolock(int const c, FILE *const stream, __crt_cached_ptd_host &ptd)
Definition: _flsbuf.cpp:195
#define EINVAL
Definition: acclib.h:90
#define __cdecl
Definition: accygwin.h:79
int __cdecl _write_internal(_In_ int _FileHandle, _In_reads_bytes_(_MaxCharCount) void const *_Buf, _In_ unsigned int _MaxCharCount, _Inout_ __crt_cached_ptd_host &_Ptd)
#define _INTERNAL_BUFSIZ
#define _UCRT_VALIDATE_RETURN(ptd, expr, errorcode, retexpr)
auto __acrt_lock_stream_and_call(FILE *const stream, Action &&action) -> decltype(action())
#define _ASSERTE(expr)
Definition: crtdbg.h:114
_In_ size_t const _In_ int _In_ bool const _In_ unsigned const _In_ __acrt_rounding_mode const _Inout_ __crt_cached_ptd_host & ptd
Definition: cvt.cpp:355
size_t const element_size
Definition: debug_heap.cpp:510
int __cdecl __acrt_stdio_flush_nolock(FILE *const public_stream, __crt_cached_ptd_host &ptd)
Definition: fflush.cpp:222
size_t __cdecl _fwrite_nolock(void const *const buffer, size_t const element_size, size_t const element_count, FILE *const public_stream)
Definition: fwrite.cpp:186
size_t __cdecl _fwrite_internal(void const *const buffer, size_t const size, size_t const count, FILE *const stream, __crt_cached_ptd_host &ptd)
Definition: fwrite.cpp:21
size_t __cdecl _fwrite_nolock_internal(void const *const buffer, size_t const element_size, size_t const element_count, FILE *const public_stream, __crt_cached_ptd_host &ptd)
Definition: fwrite.cpp:56
size_t __cdecl fwrite(void const *const buffer, size_t const size, size_t const count, FILE *const stream)
Definition: fwrite.cpp:45
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
_Check_return_ _CRTIMP int __cdecl _fileno(_In_ FILE *_File)
#define EOF
Definition: stdio.h:24
#define _IOREAD
Definition: stdio.h:124
#define __min(a, b)
Definition: stdlib.h:102
#define UINT_MAX
Definition: intsafe.h:152
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define SIZE_MAX
Definition: compat.h:66
Definition: parse.h:23
#define const
Definition: zconf.h:233