summaryrefslogtreecommitdiff
path: root/source/fud_file.cpp
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2025-01-01 17:41:17 -0600
committerDominick Allen <djallen@librehumanitas.org>2025-01-01 17:41:17 -0600
commit16379362c02a2472f00fac49cad62788547c9519 (patch)
tree9b7f42acbba8dd259a536287a2b130e92ad2e2c7 /source/fud_file.cpp
parent012df4bc38777c9053353ec2c4213bba67d63ab4 (diff)
Add CSV parsing, printing, fix buffered file reading.
Diffstat (limited to 'source/fud_file.cpp')
-rw-r--r--source/fud_file.cpp76
1 files changed, 55 insertions, 21 deletions
diff --git a/source/fud_file.cpp b/source/fud_file.cpp
index 55f8dbc..caf0f5a 100644
--- a/source/fud_file.cpp
+++ b/source/fud_file.cpp
@@ -17,6 +17,8 @@
#include "fud_file.hpp"
+#include "fud_algorithm.hpp"
+
#include <cerrno>
#include <fcntl.h>
#include <linux/openat2.h>
@@ -625,6 +627,7 @@ DrainResult BufferedRegularFile::write(const std::byte* source, size_t length, O
DrainResult BufferedRegularFile::read(std::byte* sink, size_t length, Option<size_t> maxExtraAttempts)
{
+ auto extraAttempts = maxExtraAttempts.valueOr(0);
DrainResult result{0, FudStatus::Success};
if (sink == nullptr) {
@@ -637,15 +640,6 @@ DrainResult BufferedRegularFile::read(std::byte* sink, size_t length, Option<siz
return result;
}
- if (m_lastOperation != Operation::Write) {
- m_bufferLength = 0;
- m_lastOperation = Operation::Write;
- }
-
- if (length == 0) {
- return result;
- }
-
if (m_lastOperation == Operation::Write && m_bufferLength > 0) {
result.status = FudStatus::OperationInvalid;
return result;
@@ -653,13 +647,18 @@ DrainResult BufferedRegularFile::read(std::byte* sink, size_t length, Option<siz
if (m_lastOperation != Operation::Read) {
m_lastOperation = Operation::Read;
+ m_bufferPosition = 0;
+ m_bufferLength = 0;
+ }
+
+ if (length == 0) {
+ return result;
}
if (m_bufferLength > 0 && m_bufferPosition < m_bufferLength) {
- auto count = m_bufferLength - m_bufferPosition;
- if (count > length) {
- count = length;
- }
+ auto remainingLength = m_bufferLength - m_bufferPosition;
+ auto count = min(length, remainingLength);
+
auto copyStatus = copyMem(sink, length, m_buffer.data() + m_bufferPosition, count);
fudAssert(copyStatus == FudStatus::Success);
@@ -677,23 +676,52 @@ DrainResult BufferedRegularFile::read(std::byte* sink, size_t length, Option<siz
m_bufferLength = 0;
}
+ if (length == 0) {
+ return result;
+ }
+
+ fudAssert(m_bufferLength == 0);
+ fudAssert(m_bufferPosition == 0);
+
if (length > m_buffer.size()) {
- auto drainResult = m_file.read(sink, length, maxExtraAttempts.valueOr(0));
+ auto drainResult = m_file.read(sink, length, extraAttempts);
+
+ sink += drainResult.bytesDrained;
+ length -= drainResult.bytesDrained;
+
result.status = drainResult.status;
result.bytesDrained += drainResult.bytesDrained;
+ return result;
}
- if (length == 0 || result.status != FudStatus::Success) {
+ fudAssert(length > 0);
+
+ if (result.status != FudStatus::Success) {
return result;
}
- fudAssert(m_bufferLength == 0 && m_bufferPosition == 0);
- auto drainResult = m_file.read(m_buffer.data(), m_buffer.size(), maxExtraAttempts.valueOr(0));
- if (drainResult.status != FudStatus::Success && drainResult.status != FudStatus::Partial) {
- result.status = drainResult.status;
- } else {
- result.status = FudStatus::Success;
+ fudAssert(m_bufferLength == 0);
+ fudAssert(m_bufferPosition == 0);
+
+ auto drainResult = m_file.read(m_buffer.data(), m_buffer.size(), extraAttempts);
+ result.status = drainResult.status;
+ if (drainResult.status == FudStatus::Success || drainResult.status == FudStatus::Partial) {
m_bufferLength = drainResult.bytesDrained;
+
+ auto count = min(length, m_bufferLength);
+
+ auto copyStatus = copyMem(sink, count, m_buffer.data(), count);
+ fudAssert(copyStatus == FudStatus::Success);
+
+ sink += count;
+ length -= count;
+
+ if (drainResult.status == FudStatus::Partial && length == 0) {
+ drainResult.status = FudStatus::Success;
+ }
+
+ m_bufferPosition = count;
+ result.bytesDrained += count;
}
return result;
@@ -713,6 +741,12 @@ DrainResult BufferedRegularFile::flush(size_t maxExtraAttempts)
return {0, FudStatus::Success};
}
+ if (m_lastOperation != Operation::Write) {
+ m_bufferLength = 0;
+ m_bufferPosition = 0;
+ return {0, FudStatus::Success};
+ }
+
auto drainResult = m_file.write(m_buffer.data(), m_bufferLength, maxExtraAttempts);
if (drainResult.status == FudStatus::Success) {
m_bufferLength = 0;