Skip to content

Commit 26e848f

Browse files
committed
[libc] Copy the data from the buffer first.
For read_unlocked() with the _IONBUF mode, there is still an one-character buffer which is used to store the data inserted by ungetc(), so we always need to check the buffer first.
1 parent 2bea940 commit 26e848f

File tree

2 files changed

+27
-8
lines changed

2 files changed

+27
-8
lines changed

libc/src/__support/File/file.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ FileIOResult File::read_unlocked(void *data, size_t len) {
200200
}
201201
}
202202

203-
FileIOResult File::read_unlocked_fbf(uint8_t *data, size_t len) {
203+
FileIOResult File::copy_data_from_buf(uint8_t *data, size_t len) {
204204
cpp::span<uint8_t> bufref(static_cast<uint8_t *>(buf), bufsize);
205205
cpp::span<uint8_t> dataref(static_cast<uint8_t *>(data), len);
206206

@@ -220,12 +220,22 @@ FileIOResult File::read_unlocked_fbf(uint8_t *data, size_t len) {
220220
for (size_t i = 0; i < available_data; ++i)
221221
dataref[i] = bufref[i + pos];
222222
read_limit = pos = 0; // Reset the pointers.
223+
224+
return available_data;
225+
}
226+
227+
FileIOResult File::read_unlocked_fbf(uint8_t *data, size_t len) {
228+
// Read data from the buffer first.
229+
size_t available_data = copy_data_from_buf(data, len);
230+
if (available_data == len)
231+
return available_data;
232+
223233
// Update the dataref to reflect that fact that we have already
224234
// copied |available_data| into |data|.
225-
dataref = cpp::span<uint8_t>(dataref.data() + available_data,
226-
dataref.size() - available_data);
227-
228235
size_t to_fetch = len - available_data;
236+
cpp::span<uint8_t> dataref(static_cast<uint8_t *>(data) + available_data,
237+
to_fetch);
238+
229239
if (to_fetch > bufsize) {
230240
auto result = platform_read(this, dataref.data(), to_fetch);
231241
size_t fetched_size = result.value;
@@ -245,7 +255,7 @@ FileIOResult File::read_unlocked_fbf(uint8_t *data, size_t len) {
245255
read_limit += fetched_size;
246256
size_t transfer_size = fetched_size >= to_fetch ? to_fetch : fetched_size;
247257
for (size_t i = 0; i < transfer_size; ++i)
248-
dataref[i] = bufref[i];
258+
dataref[i] = buf[i];
249259
pos += transfer_size;
250260
if (result.has_error() || fetched_size < to_fetch) {
251261
if (!result.has_error())
@@ -257,15 +267,23 @@ FileIOResult File::read_unlocked_fbf(uint8_t *data, size_t len) {
257267
}
258268

259269
FileIOResult File::read_unlocked_nbf(uint8_t *data, size_t len) {
260-
auto result = platform_read(this, data, len);
270+
// Check whether there is a character in the ungetc buffer.
271+
size_t available_data = copy_data_from_buf(data, len);
272+
if (available_data == len)
273+
return available_data;
274+
275+
// Directly copy the data into |data|.
276+
cpp::span<uint8_t> dataref(static_cast<uint8_t *>(data) + available_data,
277+
len - available_data);
278+
auto result = platform_read(this, dataref.data(), dataref.size());
261279

262-
if (result.has_error() || result < len) {
280+
if (result.has_error() || result < dataref.size()) {
263281
if (!result.has_error())
264282
eof = true;
265283
else
266284
err = true;
267285
}
268-
return result;
286+
return {result + available_data, result.has_error()};
269287
}
270288

271289
int File::ungetc_unlocked(int c) {

libc/src/__support/File/file.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ class File {
282282

283283
FileIOResult read_unlocked_fbf(uint8_t *data, size_t len);
284284
FileIOResult read_unlocked_nbf(uint8_t *data, size_t len);
285+
FileIOResult copy_data_from_buf(uint8_t *data, size_t len);
285286

286287
constexpr void adjust_buf() {
287288
if (read_allowed() && (buf == nullptr || bufsize == 0)) {

0 commit comments

Comments
 (0)