diff options
author | Dominick Allen <djallen@librehumanitas.org> | 2025-01-02 15:11:51 -0600 |
---|---|---|
committer | Dominick Allen <djallen@librehumanitas.org> | 2025-01-02 15:11:51 -0600 |
commit | 87071200872c2450c947047350132aee493033c1 (patch) | |
tree | 49109532d9bbd148b4e59043120037684093be33 /source/fud_file.cpp | |
parent | 16379362c02a2472f00fac49cad62788547c9519 (diff) |
Get basic CSV parser operating.
Diffstat (limited to 'source/fud_file.cpp')
-rw-r--r-- | source/fud_file.cpp | 118 |
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); |