@@ -42,7 +42,7 @@ FileIOResult File::write_unlocked_nbf(const uint8_t *data, size_t len) {
4242 if (pos > 0 ) { // If the buffer is not empty
4343 // Flush the buffer
4444 const size_t write_size = pos;
45- auto write_result = platform_write (this , buf, write_size);
45+ FileIOResult write_result = platform_write (this , buf, write_size);
4646 pos = 0 ; // Buffer is now empty so reset pos to the beginning.
4747 // If less bytes were written than expected, then an error occurred.
4848 if (write_result < write_size) {
@@ -52,7 +52,7 @@ FileIOResult File::write_unlocked_nbf(const uint8_t *data, size_t len) {
5252 }
5353 }
5454
55- auto write_result = platform_write (this , data, len);
55+ FileIOResult write_result = platform_write (this , data, len);
5656 if (write_result < len)
5757 err = true ;
5858 return write_result;
@@ -99,7 +99,7 @@ FileIOResult File::write_unlocked_fbf(const uint8_t *data, size_t len) {
9999 // is full.
100100 const size_t write_size = pos;
101101
102- auto buf_result = platform_write (this , buf, write_size);
102+ FileIOResult buf_result = platform_write (this , buf, write_size);
103103 size_t bytes_written = buf_result.value ;
104104
105105 pos = 0 ; // Buffer is now empty so reset pos to the beginning.
@@ -121,7 +121,8 @@ FileIOResult File::write_unlocked_fbf(const uint8_t *data, size_t len) {
121121 pos = remainder.size ();
122122 } else {
123123
124- auto result = platform_write (this , remainder.data (), remainder.size ());
124+ FileIOResult result =
125+ platform_write (this , remainder.data (), remainder.size ());
125126 size_t bytes_written = buf_result.value ;
126127
127128 // If less bytes were written than expected, then an error occurred. Return
@@ -190,6 +191,17 @@ FileIOResult File::read_unlocked(void *data, size_t len) {
190191
191192 prev_op = FileOp::READ;
192193
194+ if (bufmode == _IONBF) { // unbuffered.
195+ return read_unlocked_nbf (static_cast <uint8_t *>(data), len);
196+ } else if (bufmode == _IOFBF) { // fully buffered
197+ return read_unlocked_fbf (static_cast <uint8_t *>(data), len);
198+ } else /* if (bufmode == _IOLBF) */ { // line buffered
199+ // There is no line buffered mode for read. Use fully buffered instead.
200+ return read_unlocked_fbf (static_cast <uint8_t *>(data), len);
201+ }
202+ }
203+
204+ size_t File::copy_data_from_buf (uint8_t *data, size_t len) {
193205 cpp::span<uint8_t > bufref (static_cast <uint8_t *>(buf), bufsize);
194206 cpp::span<uint8_t > dataref (static_cast <uint8_t *>(data), len);
195207
@@ -209,32 +221,42 @@ FileIOResult File::read_unlocked(void *data, size_t len) {
209221 for (size_t i = 0 ; i < available_data; ++i)
210222 dataref[i] = bufref[i + pos];
211223 read_limit = pos = 0 ; // Reset the pointers.
224+
225+ return available_data;
226+ }
227+
228+ FileIOResult File::read_unlocked_fbf (uint8_t *data, size_t len) {
229+ // Read data from the buffer first.
230+ size_t available_data = copy_data_from_buf (data, len);
231+ if (available_data == len)
232+ return available_data;
233+
212234 // Update the dataref to reflect that fact that we have already
213235 // copied |available_data| into |data|.
214- dataref = cpp::span<uint8_t >(dataref.data () + available_data,
215- dataref.size () - available_data);
216-
217236 size_t to_fetch = len - available_data;
237+ cpp::span<uint8_t > dataref (static_cast <uint8_t *>(data) + available_data,
238+ to_fetch);
239+
218240 if (to_fetch > bufsize) {
219- auto result = platform_read (this , dataref.data (), to_fetch);
241+ FileIOResult result = platform_read (this , dataref.data (), to_fetch);
220242 size_t fetched_size = result.value ;
221243 if (result.has_error () || fetched_size < to_fetch) {
222244 if (!result.has_error ())
223245 eof = true ;
224246 else
225247 err = true ;
226- return {available_data + fetched_size, result.has_error () };
248+ return {available_data + fetched_size, result.error };
227249 }
228250 return len;
229251 }
230252
231253 // Fetch and buffer another buffer worth of data.
232- auto result = platform_read (this , buf, bufsize);
254+ FileIOResult result = platform_read (this , buf, bufsize);
233255 size_t fetched_size = result.value ;
234256 read_limit += fetched_size;
235257 size_t transfer_size = fetched_size >= to_fetch ? to_fetch : fetched_size;
236258 for (size_t i = 0 ; i < transfer_size; ++i)
237- dataref[i] = bufref [i];
259+ dataref[i] = buf [i];
238260 pos += transfer_size;
239261 if (result.has_error () || fetched_size < to_fetch) {
240262 if (!result.has_error ())
@@ -245,6 +267,26 @@ FileIOResult File::read_unlocked(void *data, size_t len) {
245267 return {transfer_size + available_data, result.error };
246268}
247269
270+ FileIOResult File::read_unlocked_nbf (uint8_t *data, size_t len) {
271+ // Check whether there is a character in the ungetc buffer.
272+ size_t available_data = copy_data_from_buf (data, len);
273+ if (available_data == len)
274+ return available_data;
275+
276+ // Directly copy the data into |data|.
277+ cpp::span<uint8_t > dataref (static_cast <uint8_t *>(data) + available_data,
278+ len - available_data);
279+ FileIOResult result = platform_read (this , dataref.data (), dataref.size ());
280+
281+ if (result.has_error () || result < dataref.size ()) {
282+ if (!result.has_error ())
283+ eof = true ;
284+ else
285+ err = true ;
286+ }
287+ return {result + available_data, result.error };
288+ }
289+
248290int File::ungetc_unlocked (int c) {
249291 // There is no meaning to unget if:
250292 // 1. You are trying to push back EOF.
@@ -287,7 +329,7 @@ ErrorOr<int> File::seek(off_t offset, int whence) {
287329 FileLock lock (this );
288330 if (prev_op == FileOp::WRITE && pos > 0 ) {
289331
290- auto buf_result = platform_write (this , buf, pos);
332+ FileIOResult buf_result = platform_write (this , buf, pos);
291333 if (buf_result.has_error () || buf_result.value < pos) {
292334 err = true ;
293335 return Error (buf_result.error );
@@ -325,7 +367,7 @@ ErrorOr<off_t> File::tell() {
325367
326368int File::flush_unlocked () {
327369 if (prev_op == FileOp::WRITE && pos > 0 ) {
328- auto buf_result = platform_write (this , buf, pos);
370+ FileIOResult buf_result = platform_write (this , buf, pos);
329371 if (buf_result.has_error () || buf_result.value < pos) {
330372 err = true ;
331373 return buf_result.error ;
0 commit comments