@@ -42,7 +42,7 @@ FileIOResult File::write_unlocked_nbf(const uint8_t *data, size_t len) {
42
42
if (pos > 0 ) { // If the buffer is not empty
43
43
// Flush the buffer
44
44
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);
46
46
pos = 0 ; // Buffer is now empty so reset pos to the beginning.
47
47
// If less bytes were written than expected, then an error occurred.
48
48
if (write_result < write_size) {
@@ -52,7 +52,7 @@ FileIOResult File::write_unlocked_nbf(const uint8_t *data, size_t len) {
52
52
}
53
53
}
54
54
55
- auto write_result = platform_write (this , data, len);
55
+ FileIOResult write_result = platform_write (this , data, len);
56
56
if (write_result < len)
57
57
err = true ;
58
58
return write_result;
@@ -99,7 +99,7 @@ FileIOResult File::write_unlocked_fbf(const uint8_t *data, size_t len) {
99
99
// is full.
100
100
const size_t write_size = pos;
101
101
102
- auto buf_result = platform_write (this , buf, write_size);
102
+ FileIOResult buf_result = platform_write (this , buf, write_size);
103
103
size_t bytes_written = buf_result.value ;
104
104
105
105
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) {
121
121
pos = remainder.size ();
122
122
} else {
123
123
124
- auto result = platform_write (this , remainder.data (), remainder.size ());
124
+ FileIOResult result =
125
+ platform_write (this , remainder.data (), remainder.size ());
125
126
size_t bytes_written = buf_result.value ;
126
127
127
128
// 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) {
190
191
191
192
prev_op = FileOp::READ;
192
193
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) {
193
205
cpp::span<uint8_t > bufref (static_cast <uint8_t *>(buf), bufsize);
194
206
cpp::span<uint8_t > dataref (static_cast <uint8_t *>(data), len);
195
207
@@ -209,32 +221,42 @@ FileIOResult File::read_unlocked(void *data, size_t len) {
209
221
for (size_t i = 0 ; i < available_data; ++i)
210
222
dataref[i] = bufref[i + pos];
211
223
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
+
212
234
// Update the dataref to reflect that fact that we have already
213
235
// copied |available_data| into |data|.
214
- dataref = cpp::span<uint8_t >(dataref.data () + available_data,
215
- dataref.size () - available_data);
216
-
217
236
size_t to_fetch = len - available_data;
237
+ cpp::span<uint8_t > dataref (static_cast <uint8_t *>(data) + available_data,
238
+ to_fetch);
239
+
218
240
if (to_fetch > bufsize) {
219
- auto result = platform_read (this , dataref.data (), to_fetch);
241
+ FileIOResult result = platform_read (this , dataref.data (), to_fetch);
220
242
size_t fetched_size = result.value ;
221
243
if (result.has_error () || fetched_size < to_fetch) {
222
244
if (!result.has_error ())
223
245
eof = true ;
224
246
else
225
247
err = true ;
226
- return {available_data + fetched_size, result.has_error () };
248
+ return {available_data + fetched_size, result.error };
227
249
}
228
250
return len;
229
251
}
230
252
231
253
// Fetch and buffer another buffer worth of data.
232
- auto result = platform_read (this , buf, bufsize);
254
+ FileIOResult result = platform_read (this , buf, bufsize);
233
255
size_t fetched_size = result.value ;
234
256
read_limit += fetched_size;
235
257
size_t transfer_size = fetched_size >= to_fetch ? to_fetch : fetched_size;
236
258
for (size_t i = 0 ; i < transfer_size; ++i)
237
- dataref[i] = bufref [i];
259
+ dataref[i] = buf [i];
238
260
pos += transfer_size;
239
261
if (result.has_error () || fetched_size < to_fetch) {
240
262
if (!result.has_error ())
@@ -245,6 +267,26 @@ FileIOResult File::read_unlocked(void *data, size_t len) {
245
267
return {transfer_size + available_data, result.error };
246
268
}
247
269
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
+
248
290
int File::ungetc_unlocked (int c) {
249
291
// There is no meaning to unget if:
250
292
// 1. You are trying to push back EOF.
@@ -287,7 +329,7 @@ ErrorOr<int> File::seek(off_t offset, int whence) {
287
329
FileLock lock (this );
288
330
if (prev_op == FileOp::WRITE && pos > 0 ) {
289
331
290
- auto buf_result = platform_write (this , buf, pos);
332
+ FileIOResult buf_result = platform_write (this , buf, pos);
291
333
if (buf_result.has_error () || buf_result.value < pos) {
292
334
err = true ;
293
335
return Error (buf_result.error );
@@ -325,7 +367,7 @@ ErrorOr<off_t> File::tell() {
325
367
326
368
int File::flush_unlocked () {
327
369
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);
329
371
if (buf_result.has_error () || buf_result.value < pos) {
330
372
err = true ;
331
373
return buf_result.error ;
0 commit comments