Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions libc/src/__support/File/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,17 @@ FileIOResult File::read_unlocked(void *data, size_t len) {

prev_op = FileOp::READ;

if (bufmode == _IONBF) { // unbuffered.
return read_unlocked_nbf(static_cast<uint8_t *>(data), len);
} else if (bufmode == _IOFBF) { // fully buffered
return read_unlocked_fbf(static_cast<uint8_t *>(data), len);
} else /*if (bufmode == _IOLBF) */ { // line buffered
// There is no line buffered mode for read. Use fully buffered instead.
return read_unlocked_fbf(static_cast<uint8_t *>(data), len);
}
}

size_t File::copy_data_from_buf(uint8_t *data, size_t len) {
cpp::span<uint8_t> bufref(static_cast<uint8_t *>(buf), bufsize);
cpp::span<uint8_t> dataref(static_cast<uint8_t *>(data), len);

Expand All @@ -209,12 +220,22 @@ FileIOResult File::read_unlocked(void *data, size_t len) {
for (size_t i = 0; i < available_data; ++i)
dataref[i] = bufref[i + pos];
read_limit = pos = 0; // Reset the pointers.

return available_data;
}

FileIOResult File::read_unlocked_fbf(uint8_t *data, size_t len) {
// Read data from the buffer first.
size_t available_data = copy_data_from_buf(data, len);
if (available_data == len)
return available_data;

// Update the dataref to reflect that fact that we have already
// copied |available_data| into |data|.
dataref = cpp::span<uint8_t>(dataref.data() + available_data,
dataref.size() - available_data);

size_t to_fetch = len - available_data;
cpp::span<uint8_t> dataref(static_cast<uint8_t *>(data) + available_data,
to_fetch);

if (to_fetch > bufsize) {
auto result = platform_read(this, dataref.data(), to_fetch);
size_t fetched_size = result.value;
Expand All @@ -223,7 +244,7 @@ FileIOResult File::read_unlocked(void *data, size_t len) {
eof = true;
else
err = true;
return {available_data + fetched_size, result.has_error()};
return {available_data + fetched_size, result.error};
}
return len;
}
Expand All @@ -234,7 +255,7 @@ FileIOResult File::read_unlocked(void *data, size_t len) {
read_limit += fetched_size;
size_t transfer_size = fetched_size >= to_fetch ? to_fetch : fetched_size;
for (size_t i = 0; i < transfer_size; ++i)
dataref[i] = bufref[i];
dataref[i] = buf[i];
pos += transfer_size;
if (result.has_error() || fetched_size < to_fetch) {
if (!result.has_error())
Expand All @@ -245,6 +266,26 @@ FileIOResult File::read_unlocked(void *data, size_t len) {
return {transfer_size + available_data, result.error};
}

FileIOResult File::read_unlocked_nbf(uint8_t *data, size_t len) {
// Check whether there is a character in the ungetc buffer.
size_t available_data = copy_data_from_buf(data, len);
if (available_data == len)
return available_data;

// Directly copy the data into |data|.
cpp::span<uint8_t> dataref(static_cast<uint8_t *>(data) + available_data,
len - available_data);
auto result = platform_read(this, dataref.data(), dataref.size());

if (result.has_error() || result < dataref.size()) {
if (!result.has_error())
eof = true;
else
err = true;
}
return {result + available_data, result.error};
}

int File::ungetc_unlocked(int c) {
// There is no meaning to unget if:
// 1. You are trying to push back EOF.
Expand Down
4 changes: 4 additions & 0 deletions libc/src/__support/File/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ class File {
FileIOResult write_unlocked_fbf(const uint8_t *data, size_t len);
FileIOResult write_unlocked_nbf(const uint8_t *data, size_t len);

FileIOResult read_unlocked_fbf(uint8_t *data, size_t len);
FileIOResult read_unlocked_nbf(uint8_t *data, size_t len);
size_t copy_data_from_buf(uint8_t *data, size_t len);

constexpr void adjust_buf() {
if (read_allowed() && (buf == nullptr || bufsize == 0)) {
// We should allow atleast one ungetc operation.
Expand Down
Loading