summaryrefslogtreecommitdiff
path: root/source/fud_file.cpp
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2025-01-02 15:11:51 -0600
committerDominick Allen <djallen@librehumanitas.org>2025-01-02 15:11:51 -0600
commit87071200872c2450c947047350132aee493033c1 (patch)
tree49109532d9bbd148b4e59043120037684093be33 /source/fud_file.cpp
parent16379362c02a2472f00fac49cad62788547c9519 (diff)
Get basic CSV parser operating.
Diffstat (limited to 'source/fud_file.cpp')
-rw-r--r--source/fud_file.cpp118
1 files changed, 82 insertions, 36 deletions
diff --git a/source/fud_file.cpp b/source/fud_file.cpp
index caf0f5a..ca6404d 100644
--- a/source/fud_file.cpp
+++ b/source/fud_file.cpp
@@ -552,11 +552,11 @@ FudStatus BufferedRegularFile::resizeBuffer(size_t size)
return m_buffer.resize(size);
}
-DrainResult BufferedRegularFile::write(const std::byte* source, size_t length, Option<size_t> maxExtraAttempts)
+DrainResult BufferedRegularFile::validateBufferedIO(const std::byte* pointer, Operation requestedOperation)
{
DrainResult result{0, FudStatus::Success};
- if (source == nullptr) {
+ if (pointer == nullptr) {
result.status = FudStatus::NullPointer;
return result;
}
@@ -566,9 +566,25 @@ DrainResult BufferedRegularFile::write(const std::byte* source, size_t length, O
return result;
}
- if (m_lastOperation != Operation::Write) {
+ if (requestedOperation == Operation::Read && m_lastOperation == Operation::Write && m_bufferLength > 0) {
+ result.status = FudStatus::OperationInvalid;
+ return result;
+ }
+
+ if (m_lastOperation != requestedOperation) {
m_bufferLength = 0;
- m_lastOperation = Operation::Write;
+ m_bufferPosition = 0;
+ m_lastOperation = requestedOperation;
+ }
+
+ return result;
+}
+
+DrainResult BufferedRegularFile::write(const std::byte* source, size_t length, Option<size_t> maxExtraAttempts)
+{
+ DrainResult result{validateBufferedIO(source, Operation::Write)};
+ if (result.status != FudStatus::Success) {
+ return result;
}
if (length == 0) {
@@ -628,46 +644,17 @@ 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};
+ DrainResult result{validateBufferedIO(sink, Operation::Read)};
- if (sink == nullptr) {
- result.status = FudStatus::NullPointer;
- return result;
- }
-
- if (not m_file.isOpen()) {
- result.status = FudStatus::HandleInvalid;
- return result;
- }
-
- if (m_lastOperation == Operation::Write && m_bufferLength > 0) {
- result.status = FudStatus::OperationInvalid;
+ if (result.status != FudStatus::Success) {
return result;
}
- 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 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);
-
- sink += count;
- length -= count;
-
- m_bufferPosition += count;
- result.bytesDrained += count;
- }
+ drainReadBuffer(sink, length, result);
fudAssert(length == 0 || m_bufferPosition == m_bufferLength);
@@ -727,6 +714,65 @@ DrainResult BufferedRegularFile::read(std::byte* sink, size_t length, Option<siz
return result;
}
+/** \brief Attempt to read one UTF8 sequence. */
+DrainResult BufferedRegularFile::readUtf8(Utf8& sink, Option<size_t> maxExtraAttempts)
+{
+ size_t extraAttempts{maxExtraAttempts.valueOr(0)};
+ Array<utf8, 4> utf8Data{};
+ auto drainResult = read(reinterpret_cast<std::byte*>(utf8Data.data()), 1, maxExtraAttempts);
+ if (drainResult.status != FudStatus::Success) {
+ return drainResult;
+ }
+
+ auto utf8Type = utf8TypeFromByte(utf8Data[0]);
+ uint8_t bytesToRead{0};
+ switch (utf8Type) {
+ case Utf8Type::Ascii:
+ break;
+ case Utf8Type::Utf82Byte:
+ bytesToRead = 1;
+ break;
+ case Utf8Type::Utf83Byte:
+ bytesToRead = 2;
+ break;
+ case Utf8Type::Utf84Byte:
+ bytesToRead = 3;
+ break;
+ case Utf8Type::Invalid:
+ default:
+ sink = Utf8{Ascii{utf8Data[0]}};
+ drainResult.status = FudStatus::Utf8Invalid;
+ return drainResult;
+ }
+
+ if (bytesToRead > 0) {
+ auto utf8ReadResult = read(reinterpret_cast<std::byte*>(utf8Data.data() + 1), bytesToRead, extraAttempts);
+ drainResult.status = utf8ReadResult.status;
+ drainResult.bytesDrained += utf8ReadResult.bytesDrained;
+ }
+
+ sink = Utf8::make(utf8Data);
+
+ return drainResult;
+}
+
+void BufferedRegularFile::drainReadBuffer(std::byte*& sink, size_t& length, DrainResult& result)
+{
+ if (m_bufferLength > 0 && m_bufferPosition < m_bufferLength) {
+ 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);
+
+ sink += count;
+ length -= count;
+
+ m_bufferPosition += count;
+ result.bytesDrained += count;
+ }
+}
+
FudStatus BufferedRegularFile::setBuffer(Vector<std::byte>&& buffer, bool discardOldBuffer)
{
static_cast<void>(buffer);