summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2025-01-02 18:49:56 -0600
committerDominick Allen <djallen@librehumanitas.org>2025-01-02 18:49:56 -0600
commitd5a174a6d4f8be5e7cffe7c2adbb8db23b578f56 (patch)
tree536a10802f418e3e71f3828597439537d9e62f21
parent908fdf06b41f9084d719a4b517c868b1ad29a9ac (diff)
Fixing errors in Vector.
-rw-r--r--.clang-tidy2
-rw-r--r--include/fud_csv.hpp2
-rw-r--r--include/fud_file.hpp10
-rw-r--r--include/fud_span.hpp1
-rw-r--r--include/fud_string_view.hpp34
-rw-r--r--include/fud_vector.hpp35
-rw-r--r--source/fud_csv.cpp50
-rw-r--r--test/test_common.cpp16
-rw-r--r--test/test_common.hpp7
-rw-r--r--test/test_csv.cpp77
-rw-r--r--test/test_file.cpp11
11 files changed, 184 insertions, 61 deletions
diff --git a/.clang-tidy b/.clang-tidy
index abd3f89..d6fa925 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,5 +1,5 @@
---
-Checks: 'clang-diagnostic-*,clang-analyzer-*,readability*,-readability-use-anyofallof,bugprone*,-bugprone-easily-swappable-parameters,deadcode,cppcoreguidelines*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-avoid-do-while,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-owning-memory,-cppcoreguidelines-non-private-member-variables-in-classes,modernize-*,-modernize-pass-by-value,-modernize-use-trailing-return-type,-modernize-avoid-c-arrays,performance*,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-type-union-access,-clang-diagnostic-unknown-warning-option,-clang-analyzer-valist*,-modernize-use-designated-initializers'
+Checks: 'clang-diagnostic-*,clang-analyzer-*,readability*,-readability-use-anyofallof,bugprone*,-bugprone-easily-swappable-parameters,deadcode,cppcoreguidelines*,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-avoid-do-while,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-owning-memory,-cppcoreguidelines-non-private-member-variables-in-classes,modernize-*,-modernize-pass-by-value,-modernize-use-trailing-return-type,-modernize-avoid-c-arrays,performance*,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-type-union-access,-clang-diagnostic-unknown-warning-option,-clang-analyzer-valist*,-modernize-use-designated-initializers,-readability-redundant-member-init'
WarningsAsErrors: ''
HeaderFileExtensions:
- ''
diff --git a/include/fud_csv.hpp b/include/fud_csv.hpp
index 237c56f..2e0b6dd 100644
--- a/include/fud_csv.hpp
+++ b/include/fud_csv.hpp
@@ -88,6 +88,8 @@ struct Csv {
// assumes file is at start
static FudStatus parseFromBufferedFile(Csv& csv, BufferedRegularFile& file, size_t maxExtraAttempts);
+
+ [[nodiscard]] Result<Option<StringView>, FudStatus> entry(size_t line, size_t column) const;
};
} // namespace fud
diff --git a/include/fud_file.hpp b/include/fud_file.hpp
index 6f1acbf..66719e4 100644
--- a/include/fud_file.hpp
+++ b/include/fud_file.hpp
@@ -38,7 +38,7 @@ enum class FileAccessMode : uint8_t
ReadWrite = Read | Write
};
-enum class OpenFlagEnum : uint16_t
+enum class OpenFlagEnum : uint8_t
{
Append = 0x01,
Truncate = Append << 1,
@@ -91,7 +91,7 @@ class OpenFlags {
return mode;
}
- constexpr uint32_t flags() const noexcept
+ [[nodiscard]] constexpr uint32_t flags() const noexcept
{
uint32_t openFlags = 0;
openFlags |= static_cast<uint32_t>(hasFlag(OpenFlagEnum::Append)) * O_APPEND;
@@ -105,7 +105,7 @@ class OpenFlags {
return openFlags;
}
- constexpr bool hasFlag(OpenFlagEnum flag) const noexcept
+ [[nodiscard]] constexpr bool hasFlag(OpenFlagEnum flag) const noexcept
{
return (m_mask & static_cast<FlagType>(flag)) != 0;
}
@@ -142,7 +142,7 @@ class RegularFile {
Result<size_t, FudStatus> size() const;
- constexpr int fileDescriptor() const
+ [[nodiscard]] constexpr int fileDescriptor() const
{
return m_fd;
}
@@ -225,7 +225,7 @@ class BufferedRegularFile {
Result<size_t, FudStatus> searchSubstring(StringView subString);
- constexpr const RegularFile& file() const
+ [[nodiscard]] constexpr const RegularFile& file() const
{
return m_file;
}
diff --git a/include/fud_span.hpp b/include/fud_span.hpp
index ed4bcc7..b274d6f 100644
--- a/include/fud_span.hpp
+++ b/include/fud_span.hpp
@@ -35,6 +35,7 @@ struct Span {
using ValueType = T;
T* m_data;
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
const size_t m_size;
static Span make(Array<T, Size>& array)
diff --git a/include/fud_string_view.hpp b/include/fud_string_view.hpp
index 327bf20..c3bc0a1 100644
--- a/include/fud_string_view.hpp
+++ b/include/fud_string_view.hpp
@@ -18,10 +18,10 @@
#ifndef FUD_STRING_VIEW_HPP
#define FUD_STRING_VIEW_HPP
+#include "fud_assert.hpp"
+#include "fud_config.hpp"
#include "fud_status.hpp"
#include "fud_utf8.hpp"
-#include "fud_config.hpp"
-#include "fud_assert.hpp"
#include <string_view>
@@ -31,6 +31,7 @@ class String;
struct StringView {
template <size_t N>
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
consteval StringView(const utf8 (&input)[N]) : m_length{N - 1}, m_data{input}
{
static_assert(N > 0);
@@ -52,28 +53,42 @@ struct StringView {
}
template <size_t N>
- StringView(const char (&input)[N]) : m_length{N - 1}, m_data{reinterpret_cast<const utf8*>(input)}
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
+ StringView(const char (&input)[N]) :
+ m_length{N - 1},
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ m_data{reinterpret_cast<const utf8*>(input)}
{
static_assert(N > 0);
}
StringView(size_t strLen, const char* strData) :
- m_length(strLen), // line break
- m_data{reinterpret_cast<const utf8*>(strData)} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
+ m_length(strLen),
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ m_data{reinterpret_cast<const utf8*>(strData)}
{
}
- StringView(std::string_view rhs) noexcept : StringView(rhs.length(), rhs.data()) {}
+ StringView(std::string_view rhs) noexcept : StringView(rhs.length(), rhs.data())
+ {
+ }
explicit StringView(const String& fudString) noexcept;
template <size_t N>
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
constexpr static StringView makeFromCString(const char (&input)[N])
{
static_assert(N > 0);
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return StringView{N - 1, reinterpret_cast<const utf8*>(input)};
}
+ [[nodiscard]] constexpr Span<const utf8> asSpan() const
+ {
+ return Span<const utf8>{m_data, m_length};
+ }
+
[[nodiscard]] constexpr size_t length() const
{
return m_length;
@@ -84,8 +99,9 @@ struct StringView {
return m_data;
}
- [[nodiscard]] inline const char* c_str() const
+ [[nodiscard]] const char* c_str() const
{
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return reinterpret_cast<const char*>(m_data);
}
@@ -98,12 +114,12 @@ struct StringView {
return m_data[index];
}
- constexpr const utf8* begin() const noexcept
+ [[nodiscard]] constexpr const utf8* begin() const noexcept
{
return m_data;
}
- constexpr const utf8* end() const noexcept
+ [[nodiscard]] constexpr const utf8* end() const noexcept
{
return m_data + m_length;
}
diff --git a/include/fud_vector.hpp b/include/fud_vector.hpp
index 2942e71..760587b 100644
--- a/include/fud_vector.hpp
+++ b/include/fud_vector.hpp
@@ -116,6 +116,7 @@ class Vector {
}
output.m_allocator = allocator;
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
output.m_data = reinterpret_cast<T*>(dataPtrResult.getOkay());
output.m_length = 0;
output.m_capacity = capacity;
@@ -354,6 +355,7 @@ class Vector {
return dataPtrResult.takeError();
}
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto* dataPtr = reinterpret_cast<T*>(dataPtrResult.takeOkay());
for (size_t index = 0; index < m_length; ++index) {
const auto* ptr = new (dataPtr + index) T(std::move(m_data[index]));
@@ -363,6 +365,7 @@ class Vector {
auto status = FudStatus::Success;
if (m_capacity > 0) {
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
m_allocator->deallocate(reinterpret_cast<std::byte*>(m_data), m_capacity);
}
@@ -645,7 +648,9 @@ class Vector {
}
if (m_length + Size > m_capacity)
{
- auto status = grow();
+ size_t currentLength = m_length;
+ auto status = resize(m_length + Size);
+ m_length = currentLength;
if (status != FudStatus::Success) {
return status;
}
@@ -660,6 +665,33 @@ class Vector {
return FudStatus::Success;
}
+ FudStatus extend(Span<const T> span)
+ {
+ if (span.data() == nullptr) {
+ return FudStatus::NullPointer;
+ }
+ if (std::numeric_limits<size_t>::max() - span.size() < m_length) {
+ return FudStatus::Failure;
+ }
+ if (m_length + span.size() > m_capacity)
+ {
+ size_t currentLength = m_length;
+ auto status = resize(m_length + span.size());
+ m_length = currentLength;
+ if (status != FudStatus::Success) {
+ return status;
+ }
+ }
+
+ for (size_t spanIndex = 0; spanIndex < span.size(); ++spanIndex) {
+ const auto* ptr = new (m_data + m_length) T(span[spanIndex]);
+ fudAssert(ptr != nullptr);
+ m_length++;
+ }
+
+ return FudStatus::Success;
+ }
+
FudStatus erase(size_t index)
{
if (index >= m_length) {
@@ -709,6 +741,7 @@ class Vector {
auto status = clear();
if (m_data != nullptr && m_allocator != nullptr) {
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
m_allocator->deallocate(reinterpret_cast<std::byte*>(m_data), m_capacity);
}
diff --git a/source/fud_csv.cpp b/source/fud_csv.cpp
index e1ecf72..bcef925 100644
--- a/source/fud_csv.cpp
+++ b/source/fud_csv.cpp
@@ -17,8 +17,6 @@
#include "fud_csv.hpp"
-#include "fud_print.hpp"
-
namespace fud {
} // namespace fud
@@ -50,11 +48,9 @@ FudStatus Csv::parseFromFilenameUnbuffered(
Option<int> dirFdOption,
size_t maxExtraAttempts)
{
- debugPrint(u8"Enter parse from filename\n");
auto fileResult{RegularFile::open(filename, FileAccessMode::Read, flags, std::move(dirFdOption))};
if (fileResult.isError()) {
- debugPrint(u8"Error opening file: {}\n", FudStatusToString(fileResult.getError()));
return fileResult.takeError();
}
@@ -70,11 +66,9 @@ FudStatus Csv::parseFromFilenameBuffered(
Option<int> dirFdOption,
size_t maxExtraAttempts)
{
- debugPrint(u8"Enter parse from filename\n");
auto fileResult{RegularFile::open(filename, FileAccessMode::Read, flags, std::move(dirFdOption))};
if (fileResult.isError()) {
- debugPrint(u8"Error opening file: {}\n", FudStatusToString(fileResult.getError()));
return fileResult.takeError();
}
@@ -104,8 +98,6 @@ FudStatus Csv::parseFromBufferedFile(Csv& csv, BufferedRegularFile& file, size_t
return readResult.status;
}
- debugPrint(u8"Working with {} columns\n", csv.numColumns);
-
csv.numLines = 1;
while (readResult.status == FudStatus::Success) {
auto lineResult = scanLine(csv, file, maxExtraAttempts, rawSize);
@@ -113,7 +105,6 @@ FudStatus Csv::parseFromBufferedFile(Csv& csv, BufferedRegularFile& file, size_t
readResult.bytesDrained += lineResult.bytesDrained;
if (readResult.status == FudStatus::Success || readResult.status == FudStatus::Partial) {
csv.numLines++;
- debugPrint(u8"Read additional line - total of {}\n", csv.numLines);
}
}
@@ -126,12 +117,9 @@ FudStatus Csv::parseFromBufferedFile(Csv& csv, BufferedRegularFile& file, size_t
}
if (std::numeric_limits<size_t>::max() / csv.numLines < csv.numColumns) {
- debugPrint(u8"Fail: csv.numlines = {}, csv.numColumns = {}\n", csv.numLines, csv.numColumns);
return FudStatus::Failure;
}
- debugPrint(u8"Working with {} lines\n", csv.numLines);
-
auto reserveStatus = csv.entries.reserve(csv.numLines * csv.numColumns);
if (reserveStatus != FudStatus::Success) {
return reserveStatus;
@@ -142,8 +130,6 @@ FudStatus Csv::parseFromBufferedFile(Csv& csv, BufferedRegularFile& file, size_t
return reserveStatus;
}
- debugPrint(u8"Reserved space - {}\n", rawSize + 1);
-
auto fillStatus = fillBuffer(csv, file, maxExtraAttempts, rawSize);
if (fillStatus != FudStatus::Success) {
@@ -166,8 +152,6 @@ FudStatus Csv::parseFromUnbufferedFile(Csv& csv, RegularFile&& file, size_t maxE
template <typename File>
DrainResult readHeader(Csv& csv, File& file, size_t maxExtraAttempts, size_t& rawSize)
{
- debugPrint(u8"Entered read header\n");
-
DrainResult readResult{};
auto lineEnding{newlineText(csv.newlineDelimiter)};
@@ -183,12 +167,10 @@ DrainResult readHeader(Csv& csv, File& file, size_t maxExtraAttempts, size_t& ra
readResult.status = drainResult.status;
readResult.bytesDrained += drainResult.bytesDrained;
if (readResult.status != FudStatus::Success) {
- debugPrint(u8"Failed to read: {}", FudStatusToString(readResult.status));
return readResult;
}
if (csv.strictUtf8 && not utf8Char.valid()) {
- debugPrint(u8"UTF8 invalid\n");
readResult.status = FudStatus::Utf8Invalid;
return readResult;
}
@@ -231,7 +213,6 @@ DrainResult readHeader(Csv& csv, File& file, size_t maxExtraAttempts, size_t& ra
template <typename File>
DrainResult scanLine(const Csv& csv, File& file, size_t maxExtraAttempts, size_t& rawSize)
{
- debugPrint(u8"Entered scanLine\n");
DrainResult readResult{};
auto lineEnding{newlineText(csv.newlineDelimiter)};
@@ -257,8 +238,6 @@ DrainResult scanLine(const Csv& csv, File& file, size_t maxExtraAttempts, size_t
break;
}
- debugPrint(u8"{}", utf8Char.data());
-
if (maybeNewline and utf8Char != Utf8{Ascii{lineEnding[1]}}) {
rawSize += 2;
maybeNewline = false;
@@ -300,12 +279,7 @@ DrainResult scanLine(const Csv& csv, File& file, size_t maxExtraAttempts, size_t
}
}
- if (numColumns > 0) {
- debugPrint(u8"\n - Read line above with {} columns \n", numColumns);
- }
-
if (numColumns == 0) {
- debugPrint(u8"Read no additional columns\n");
readResult.status = FudStatus::Empty;
return readResult;
}
@@ -343,7 +317,6 @@ FudStatus fillBuffer(Csv& csv, File& file, size_t maxExtraAttempts, size_t rawSi
currentEntry.m_data = csv.buffer.data() + sizeCounter;
size_t numEntries = csv.numLines * csv.numColumns;
- debugPrint(u8"Working over {} entries\n", numEntries);
for (size_t entryIndex = 0; entryIndex < numEntries;) {
addToSize = false;
Utf8 utf8Char{};
@@ -421,7 +394,6 @@ FudStatus fillBuffer(Csv& csv, File& file, size_t maxExtraAttempts, size_t rawSi
break;
case 0:
default:
- debugPrint(u8"Char size is ??? {}\n", charSize);
charSize = 0;
break;
}
@@ -433,21 +405,13 @@ FudStatus fillBuffer(Csv& csv, File& file, size_t maxExtraAttempts, size_t rawSi
}
}
- debugPrint(
- u8"Buffer, with current size = {} and sizeCounter, = {}:\n-----\n{}\n-----\n",
- csv.buffer.size(),
- sizeCounter,
- StringView{csv.buffer.size(), csv.buffer.data()});
-
const auto* data = csv.buffer.data();
for (auto& entry : csv.entries) {
entry.m_data = data;
data += entry.m_length;
- debugPrint(u8"Entry = {}\n", entry);
}
if (rawSize != sizeCounter) {
- debugPrint(u8"Invalid: rawSize == {}, sizeCounter == {}");
return FudStatus::Failure;
}
@@ -455,4 +419,18 @@ FudStatus fillBuffer(Csv& csv, File& file, size_t maxExtraAttempts, size_t rawSi
}
// NOLINTEND(readability-function-cognitive-complexity)
+[[nodiscard]] Result<Option<StringView>, FudStatus> Csv::entry(size_t line, size_t column) const
+{
+ if (line > numLines || column > numColumns) {
+ return Error{FudStatus::IndexInvalid};
+ }
+
+ StringView entry = entries[(line * numColumns) + column];
+ if (entry.length() == 0) {
+ return Okay{Option<StringView>{NullOpt}};
+ }
+
+ return Okay{Option<StringView>{entry}};
+}
+
} // namespace fud
diff --git a/test/test_common.cpp b/test/test_common.cpp
index f272dad..03c5dff 100644
--- a/test/test_common.cpp
+++ b/test/test_common.cpp
@@ -27,28 +27,35 @@ namespace fud {
std::byte* MockFudAlloc::operator()(size_t size)
{
+ // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
return static_cast<std::byte*>(malloc(size));
}
void MockFudDealloc::operator()(std::byte* pointer)
{
+ // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
free(pointer);
}
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
MockFudAlloc globalDefaultMockAlloc{};
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
MockFudDealloc globalDefaultMockDealloc{};
+// NOLINTNEXTLINE(readability-make-member-function-const)
std::byte* MockFudAllocator::allocate(size_t size)
{
return (*m_allocator)(size);
}
+// NOLINTNEXTLINE(readability-make-member-function-const)
void MockFudAllocator::deallocate(std::byte* pointer)
{
- return (*m_deallocator)(pointer);
+ (*m_deallocator)(pointer);
}
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
MockFudAllocator globalMockFudAlloc{};
std::byte* fudAlloc(size_t size)
@@ -58,7 +65,7 @@ std::byte* fudAlloc(size_t size)
void fudFree(std::byte* ptr)
{
- return globalMockFudAlloc.deallocate(ptr);
+ globalMockFudAlloc.deallocate(ptr);
}
int unlink_cb(const char* fpath, const struct stat* sb_unused, int typeflag, struct FTW* ftwbuf)
@@ -79,7 +86,9 @@ FudStatus removeRecursive(StringView path)
if (!path.utf8Valid()) {
return FudStatus::Utf8Invalid;
}
- if (path.length() < 5) {
+
+ constexpr const size_t minPathLength = 5;
+ if (path.length() < minPathLength) {
return FudStatus::ArgumentInvalid;
}
if (not path.nullTerminated()) {
@@ -96,6 +105,7 @@ FudStatus removeRecursive(StringView path)
}
constexpr int maxOpenFd = 64;
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto status = nftw(reinterpret_cast<const char*>(path.data()), unlink_cb, maxOpenFd, FTW_DEPTH | FTW_PHYS);
if (status == 0) {
return FudStatus::Success;
diff --git a/test/test_common.hpp b/test/test_common.hpp
index 5f6828f..3be26f0 100644
--- a/test/test_common.hpp
+++ b/test/test_common.hpp
@@ -58,16 +58,22 @@ static_assert(sizeof(FOUR_BYTE) == 4 + 1);
// NOLINTEND(cppcoreguidelines-macro-usage)
+// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
struct MockFudAlloc {
+ virtual ~MockFudAlloc() = default;
virtual std::byte* operator()(size_t size);
};
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
extern MockFudAlloc globalDefaultMockAlloc;
+// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
struct MockFudDealloc {
+ virtual ~MockFudDealloc() = default;
virtual void operator()(std::byte* pointer);
};
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
extern MockFudDealloc globalDefaultMockDealloc;
struct MockFudAllocator {
@@ -78,6 +84,7 @@ struct MockFudAllocator {
MockFudDealloc* m_deallocator{&globalDefaultMockDealloc};
};
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
extern MockFudAllocator globalMockFudAlloc;
class String;
diff --git a/test/test_csv.cpp b/test/test_csv.cpp
index 90e7ef0..cb93a32 100644
--- a/test/test_csv.cpp
+++ b/test/test_csv.cpp
@@ -20,14 +20,49 @@
#include "gtest/gtest.h"
+//NOLINTBEGIN(readability-magic-numbers)
+
namespace fud {
const StringView happyCsvFilename{u8"fud-happy-test.csv"};
const StringView happyData{
u8"foo,bar,baz\n"
- u8"1,Unquoted Text,\"Quoted Text with embedded \"\" quote and embedded newline \n"
- u8"see\"\n,,\"Prior two fields are empty\"\n"};
+ u8"1,Unquoted Text,\"Quoted Text with embedded \"\" quote and embedded newline \nsee\"\n"
+ u8",,\"Prior two fields are empty\"\n"};
+
+Csv expectedHappyCsv() {
+ Csv csv{Csv::makeDefault()};
+ csv.numLines = 3;
+ csv.numColumns = 3;
+
+ auto resizeStatus = csv.entries.resize(csv.numLines * csv.numColumns);
+ fudAssert(resizeStatus == FudStatus::Success);
+ csv.entries[0] = StringView{u8"foo"};
+ csv.entries[1] = StringView{u8"bar"};
+ csv.entries[2] = StringView{u8"baz"};
+ csv.entries[3] = StringView{u8"1"};
+ csv.entries[4] = StringView{u8"Unquoted Text"};
+ csv.entries[5] = StringView{u8"Quoted Text with embedded \" quote and embedded newline \nsee"};
+ csv.entries[6] = StringView{};
+ csv.entries[7] = StringView{};
+ csv.entries[8] = StringView{u8"Prior two fields are empty"};
+
+ for (const auto& entry : csv.entries) {
+ if (entry.length() > 0) {
+ auto extendStatus = csv.buffer.extend(entry.asSpan());
+ fudAssert(extendStatus == FudStatus::Success);
+ }
+ }
+
+ size_t totalSize = 0;
+ for (auto& entry : csv.entries) {
+ entry.m_data = csv.buffer.data() + totalSize;
+ totalSize += entry.length();
+ }
+
+ return csv;
+}
auto writeHappyCsv() -> FudStatus
{
@@ -44,6 +79,7 @@ auto writeHappyCsv() -> FudStatus
}
auto file{fileResult.takeOkay()};
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto writeResult = file.write(reinterpret_cast<const std::byte*>(happyData.data()), happyData.length());
if (writeResult.status != FudStatus::Success) {
return writeResult.status;
@@ -62,13 +98,46 @@ TEST(FudCsv, ParseCsvFromFilename)
ASSERT_EQ(writeHappyCsv(), FudStatus::Success);
- debugPrint(u8"Wrote happy data:\n-----\n{}\n-----\n", happyData);
-
auto parseStatus = Csv::parseFromFilenameUnbuffered(csv, happyCsvFilename);
if (parseStatus != FudStatus::Success) {
debugPrint(u8"Error parsing file: {}\n", FudStatusToString(parseStatus));
}
ASSERT_EQ(parseStatus, FudStatus::Success);
+
+ auto expectedCsv{expectedHappyCsv()};
+ ASSERT_EQ(expectedCsv.numLines, csv.numLines);
+ ASSERT_EQ(expectedCsv.numColumns, csv.numColumns);
+ ASSERT_EQ(expectedCsv.buffer.size(), csv.buffer.size());
+ ASSERT_EQ(expectedCsv.entries.size(), csv.entries.size());
+ EXPECT_EQ(0, compareMem(expectedCsv.buffer.data(), expectedCsv.buffer.size(), csv.buffer.data(), csv.buffer.size()).takeOkayOr(-1));
+ for (size_t line = 0; line < csv.numLines; ++line)
+ {
+ for (size_t column = 0; column < csv.numColumns; ++column)
+ {
+ auto expectedEntryResult = expectedCsv.entry(line, column);
+ ASSERT_TRUE(expectedEntryResult.isOkay());
+ auto expectedEntryOpt{expectedEntryResult.takeOkay()};
+
+ auto csvEntryResult = csv.entry(line, column);
+ EXPECT_TRUE(csvEntryResult.isOkay());
+ if (csvEntryResult.isError()) {
+ continue;
+ }
+ auto csvEntryOpt{csvEntryResult.takeOkay()};
+
+ EXPECT_EQ(expectedEntryOpt.hasValue(), csvEntryOpt.hasValue());
+ if (expectedEntryOpt.isNone()) {
+ continue;
+ }
+ auto expectedEntry{expectedEntryOpt.value()};
+ auto csvEntry{csvEntryOpt.value()};
+
+ EXPECT_EQ(expectedEntry.length(), csvEntry.length());
+ EXPECT_EQ(0, compareMem(expectedEntry.data(), expectedEntry.length(), csvEntry.data(), csvEntry.length()).takeOkayOr(-1));
+ }
+ }
}
} // namespace fud
+
+//NOLINTEND(readability-magic-numbers)
diff --git a/test/test_file.cpp b/test/test_file.cpp
index 12cfb98..c1ce4f1 100644
--- a/test/test_file.cpp
+++ b/test/test_file.cpp
@@ -21,11 +21,11 @@
#include "test_common.hpp"
#include "gtest/gtest.h"
-#include <algorithm>
#include <cerrno>
#include <fcntl.h>
#include <ftw.h>
-#include <ranges>
+
+// NOLINTBEGIN(readability-magic-numbers)
namespace fud {
@@ -121,6 +121,7 @@ TEST(FudBufferedFile, OpenReadWrite)
ASSERT_EQ(bufferedFile.file().size().getOkayOr(std::numeric_limits<size_t>::max()), 0);
auto writeResult = bufferedFile.write(
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
reinterpret_cast<const std::byte*>(testName.data()),
testName.size(),
NullOpt);
@@ -132,6 +133,7 @@ TEST(FudBufferedFile, OpenReadWrite)
ASSERT_EQ(bufferedFile.seekStart(), FudStatus::Success);
Vector<utf8> output{Vector<utf8>::withSize(testName.size()).takeOkay()};
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto readResult = bufferedFile.read(reinterpret_cast<std::byte*>(output.data()), testName.size(), NullOpt);
ASSERT_EQ(readResult, expected);
@@ -142,11 +144,13 @@ TEST(FudBufferedFile, OpenReadWrite)
ASSERT_EQ(bufferedFile.seekStart(), FudStatus::Success);
expected.bytesDrained = 1;
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
readResult = bufferedFile.read(reinterpret_cast<std::byte*>(output.data()), 1, NullOpt);
ASSERT_EQ(readResult, expected);
EXPECT_EQ(output[0], testName.data()[0]);
expected.bytesDrained = testName.size() - 2;
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
readResult = bufferedFile.read(reinterpret_cast<std::byte*>(output.data()) + 1, testName.size() - 2, NullOpt);
ASSERT_EQ(readResult, expected);
EXPECT_EQ(
@@ -154,6 +158,7 @@ TEST(FudBufferedFile, OpenReadWrite)
compareMem(output.data() + 1, output.size() - 1, testName.data() + 1, testName.size() - 2).takeOkayOr(-1));
expected.bytesDrained = 1;
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
readResult = bufferedFile.read(reinterpret_cast<std::byte*>(output.data()), 1, NullOpt);
EXPECT_TRUE(readResult.status == FudStatus::Success || readResult.status == FudStatus::Partial);
@@ -164,3 +169,5 @@ TEST(FudBufferedFile, OpenReadWrite)
}
} // namespace fud
+
+// NOLINTEND(readability-magic-numbers)