summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/fud_assert.cpp8
-rw-r--r--source/fud_csv.cpp92
-rw-r--r--source/fud_file.cpp76
-rw-r--r--source/fud_print.cpp52
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