diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/fud_assert.cpp | 8 | ||||
-rw-r--r-- | source/fud_csv.cpp | 92 | ||||
-rw-r--r-- | source/fud_file.cpp | 76 | ||||
-rw-r--r-- | source/fud_print.cpp | 52 |
4 files changed, 203 insertions, 25 deletions
diff --git a/source/fud_assert.cpp b/source/fud_assert.cpp index 966f44c..425826d 100644 --- a/source/fud_assert.cpp +++ b/source/fud_assert.cpp @@ -17,8 +17,8 @@ #include "fud_assert.hpp" -#include "fud_format.hpp" #include "fud_drain.hpp" +#include "fud_format.hpp" #include "fud_string_view.hpp" #include <cstdio> @@ -26,11 +26,11 @@ namespace fud { -struct BufferSink { +struct StdErrSink { DrainResult drain(StringView source); }; -DrainResult BufferSink::drain(StringView source) +DrainResult StdErrSink::drain(StringView source) { DrainResult result{0, FudStatus::Success}; if (source.m_data == nullptr) { @@ -52,7 +52,7 @@ DrainResult BufferSink::drain(StringView source) namespace impl { void assertFailMessage(const char* assertion, const std::source_location sourceLocation) { - BufferSink sink; + StdErrSink sink; const char* fileName = sourceLocation.file_name(); if (fileName == nullptr) { fileName = "Unknown file"; diff --git a/source/fud_csv.cpp b/source/fud_csv.cpp new file mode 100644 index 0000000..031fcbc --- /dev/null +++ b/source/fud_csv.cpp @@ -0,0 +1,92 @@ +/* + * libfud + * Copyright 2025 Dominick Allen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fud_csv.hpp" + +namespace fud { + +FudStatus Csv::parseCsvFromFilename( + Csv& csv, + Option<TextBuffer&&> bufferOption, + StringView filename, + OpenFlags flags, + Option<int> dirFdOption) +{ + auto fileResult{RegularFile::open(filename, FileAccessMode::Read, flags, dirFdOption)}; + + if (fileResult.isError()) { + return fileResult.takeError(); + } + + if (bufferOption.hasValue()) { + auto bufferedFile{BufferedRegularFile::make(fileResult.takeOkay(), std::move(bufferOption.value()))}; + return parseCsvFromBufferedFile(csv, bufferedFile); + } + + auto unbufferedFile{fileResult.takeOkay()}; + return parseCsvFromUnbufferedFile(csv, std::move(unbufferedFile)); +} + +enum class CsvTextState : uint8_t +{ + UnquotedField, + QuotedField, + Separator, + Newline, +}; + +FudStatus Csv::parseCsvFromBufferedFile(Csv& csv, BufferedRegularFile& file) +{ + auto lineEnding{newlineText(csv.newlineDelimiter)}; + static_cast<void>(lineEnding); + DrainResult readResult{}; + while (true) { + utf8 letter{}; + auto drainResult = file.read(reinterpret_cast<std::byte*>(&letter), sizeof(letter), NullOpt); + readResult.status = drainResult.status; + readResult.bytesDrained += drainResult.bytesDrained; + // if (status + // REMOVE + break; + } + + size_t rawSize = 0; + + while (true) { + rawSize++; + // REMOVE + break; + } + + auto reserveStatus = csv.buffer.reserve(rawSize); + if (reserveStatus != FudStatus::Success) { + return reserveStatus; + } + + return FudStatus::NotImplemented; +} + +FudStatus Csv::parseCsvFromUnbufferedFile(Csv& csv, RegularFile&& file) +{ + static_cast<void>(csv); + constexpr size_t BufferSize = 256; + SimpleStackAllocator<BufferSize> stackAllocator{}; + auto bufferedFile{BufferedRegularFile::make(std::move(file), TextBuffer{stackAllocator})}; + return parseCsvFromBufferedFile(csv, bufferedFile); +} + +} // namespace fud 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; diff --git a/source/fud_print.cpp b/source/fud_print.cpp new file mode 100644 index 0000000..85a3d76 --- /dev/null +++ b/source/fud_print.cpp @@ -0,0 +1,52 @@ +/* + * libfud + * Copyright 2024 Dominick Allen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fud_print.hpp" +#include "fud_drain.hpp" +#include "fud_string_view.hpp" + +#include <cstdio> +#include <exception> + +namespace fud { + +DrainResult StdOutSink::drain(StringView source) +{ + DrainResult result{0, FudStatus::Success}; + if (source.m_data == nullptr) { + result.status = FudStatus::NullPointer; + return result; + } + if (source.m_length == 0) { + result.status = FudStatus::Success; + return result; + } + /* TODO: give users control over this functionality */ + result.bytesDrained = fwrite(reinterpret_cast<const char*>(source.m_data), 1, source.m_length, stdout); + if (result.bytesDrained != source.m_length) { + result.status = FudStatus::Full; + } + return result; +} + +FormatResult print(FormatString fmt) +{ + StdOutSink outSink{}; + return format(outSink, FormatCharMode::Unchecked, fmt); +} + +} // namespace fud |