summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/fud_allocator.hpp25
-rw-r--r--include/fud_c_file.hpp40
-rw-r--r--include/fud_drain.hpp12
-rw-r--r--include/fud_file.hpp68
-rw-r--r--include/fud_format.hpp61
-rw-r--r--include/fud_vector.hpp14
6 files changed, 126 insertions, 94 deletions
diff --git a/include/fud_allocator.hpp b/include/fud_allocator.hpp
index d4feccf..e4078ac 100644
--- a/include/fud_allocator.hpp
+++ b/include/fud_allocator.hpp
@@ -30,9 +30,9 @@ class alignas(std::max_align_t) Allocator {
public:
virtual ~Allocator() = default;
- virtual Result<void*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) = 0;
+ virtual Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) = 0;
- virtual FudStatus deallocate(void* pointer, size_t bytes) = 0;
+ virtual FudStatus deallocate(std::byte* pointer, size_t bytes) = 0;
virtual bool isEqual(const Allocator& rhs) const = 0;
};
@@ -46,20 +46,33 @@ class FudAllocator : public Allocator {
public:
virtual ~FudAllocator() override = default;
- virtual Result<void*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) override;
+ virtual Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) override;
- virtual FudStatus deallocate(void* pointer, size_t bytes) override;
+ virtual FudStatus deallocate(std::byte* pointer, size_t bytes) override;
virtual bool isEqual(const Allocator& rhs) const override;
};
extern FudAllocator globalFudAllocator;
+class NullAllocator : public Allocator {
+ public:
+ virtual ~NullAllocator() override = default;
+
+ virtual Result<std::byte*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) override;
+
+ virtual FudStatus deallocate(std::byte* pointer, size_t bytes) override;
+
+ virtual bool isEqual(const Allocator& rhs) const override;
+};
+
+extern NullAllocator globalNullAllocator;
+
/** \brief The default allocation function for globalFudAllocator. */
-extern void* fudAlloc(size_t size);
+extern std::byte* fudAlloc(size_t size);
/** \brief The default deallocation function for globalFudAllocator. */
-extern void fudFree(void* ptr);
+extern void fudFree(std::byte* ptr);
} // namespace fud
diff --git a/include/fud_c_file.hpp b/include/fud_c_file.hpp
index bf148c2..e0be680 100644
--- a/include/fud_c_file.hpp
+++ b/include/fud_c_file.hpp
@@ -18,11 +18,11 @@
#ifndef FUD_C_FILE_HPP
#define FUD_C_FILE_HPP
+#include "fud_drain.hpp"
#include "fud_permissions.hpp"
#include "fud_result.hpp"
#include "fud_status.hpp"
#include "fud_string.hpp"
-#include "fud_file.hpp"
#include <cstdint>
#include <cstdio>
@@ -184,16 +184,16 @@ class CFile {
return RetType::okay(fileSize);
}
- [[nodiscard]] ReadResult read(void* destination, size_t destinationSize, size_t length)
+ [[nodiscard]] DrainResult read(void* destination, size_t destinationSize, size_t length)
{
auto& self = static_cast<Derived&>(*this);
return self.read(destination, destinationSize, length, 0);
}
- [[nodiscard]] ReadResult read(void* destination, size_t destinationSize, size_t length, size_t offset)
+ [[nodiscard]] DrainResult read(void* destination, size_t destinationSize, size_t length, size_t offset)
{
auto& self = static_cast<Derived&>(*this);
- ReadResult result{};
+ DrainResult result{};
if (length == 0) {
return result;
}
@@ -227,9 +227,9 @@ class CFile {
}
auto* destBytes = static_cast<char*>(destination);
- result.bytesRead = fread(destBytes, 1, length, self.m_file);
+ result.bytesDrained = fread(destBytes, 1, length, self.m_file);
static_cast<void>(self.reset());
- if (result.bytesRead != length) {
+ if (result.bytesDrained != length) {
result.status = FudStatus::Partial;
} else {
result.status = FudStatus::Success;
@@ -239,7 +239,7 @@ class CFile {
}
template <typename T>
- [[nodiscard]] ReadResult read(T& destination, size_t length)
+ [[nodiscard]] DrainResult read(T& destination, size_t length)
{
static_assert(not std::is_pointer_v<decltype(destination)>);
auto& self = static_cast<Derived&>(*this);
@@ -247,39 +247,39 @@ class CFile {
}
template <typename T>
- [[nodiscard]] ReadResult read(T& destination, size_t length, size_t offset)
+ [[nodiscard]] DrainResult read(T& destination, size_t length, size_t offset)
{
static_assert(not std::is_pointer_v<decltype(destination)>);
auto& self = static_cast<Derived&>(*this);
return self.read(&destination, sizeof(destination), length, offset);
}
- [[nodiscard]] WriteResult write(const void* source, size_t sourceSize)
+ [[nodiscard]] DrainResult write(const void* source, size_t sourceSize)
{
auto& self = static_cast<Derived&>(*this);
auto offsetResult = self.size();
if (offsetResult.isError()) {
- return WriteResult{0, offsetResult.getError()};
+ return DrainResult{0, offsetResult.getError()};
}
return self.write(source, sourceSize, sourceSize, offsetResult.getOkay());
}
- [[nodiscard]] WriteResult write(const void* source, size_t sourceSize, size_t length)
+ [[nodiscard]] DrainResult write(const void* source, size_t sourceSize, size_t length)
{
auto& self = static_cast<Derived&>(*this);
auto offsetResult = self.size();
if (offsetResult.isError()) {
- return WriteResult{0, offsetResult.getError()};
+ return DrainResult{0, offsetResult.getError()};
}
return self.write(source, sourceSize, length, offsetResult.getOkay());
}
- [[nodiscard]] WriteResult write(const void* source, size_t sourceSize, size_t length, size_t offset)
+ [[nodiscard]] DrainResult write(const void* source, size_t sourceSize, size_t length, size_t offset)
{
auto& self = static_cast<Derived&>(*this);
- WriteResult result{};
+ DrainResult result{};
if (length == 0) {
return result;
}
@@ -315,9 +315,9 @@ class CFile {
}
const auto* sourceBytes = static_cast<const char*>(source);
- result.bytesWritten = fwrite(sourceBytes, 1, length, self.m_file);
+ result.bytesDrained = fwrite(sourceBytes, 1, length, self.m_file);
static_cast<void>(self.reset());
- if (result.bytesWritten != length) {
+ if (result.bytesDrained != length) {
result.status = FudStatus::Partial;
} else {
result.status = FudStatus::Success;
@@ -327,7 +327,7 @@ class CFile {
}
template <typename T>
- [[nodiscard]] WriteResult write(const T& source)
+ [[nodiscard]] DrainResult write(const T& source)
{
static_assert(not std::is_pointer_v<decltype(source)>);
auto& self = static_cast<Derived&>(*this);
@@ -335,19 +335,19 @@ class CFile {
}
template <typename T>
- [[nodiscard]] WriteResult write(const T& source, size_t sourceSize, size_t length)
+ [[nodiscard]] DrainResult write(const T& source, size_t sourceSize, size_t length)
{
static_assert(not std::is_pointer_v<decltype(source)>);
auto& self = static_cast<Derived&>(*this);
auto offsetResult = self.size();
if (offsetResult.isError()) {
- return WriteResult{0, offsetResult.getError()};
+ return DrainResult{0, offsetResult.getError()};
}
return self.write(source, sourceSize, length, offsetResult.getOkay());
}
template <typename T>
- [[nodiscard]] WriteResult write(const T& source, size_t sourceSize, size_t length, size_t offset)
+ [[nodiscard]] DrainResult write(const T& source, size_t sourceSize, size_t length, size_t offset)
{
static_assert(not std::is_pointer_v<decltype(source)>);
auto& self = static_cast<Derived&>(*this);
diff --git a/include/fud_drain.hpp b/include/fud_drain.hpp
index 5b78b10..d630bc7 100644
--- a/include/fud_drain.hpp
+++ b/include/fud_drain.hpp
@@ -26,8 +26,18 @@
namespace fud {
struct DrainResult {
- size_t bytesWritten;
+ size_t bytesDrained;
FudStatus status;
+ [[nodiscard]] constexpr bool isOkay()
+ {
+ return status == FudStatus::Success;
+ }
+};
+
+template <typename Sink, typename Source>
+concept Drainable = requires (Sink sink, Source source)
+{
+ { sink.drain(source) } -> std::same_as<DrainResult>;
};
} // namespace fud
diff --git a/include/fud_file.hpp b/include/fud_file.hpp
index 9ef2cbc..51826a6 100644
--- a/include/fud_file.hpp
+++ b/include/fud_file.hpp
@@ -18,12 +18,13 @@
#ifndef FUD_FILE_HPP
#define FUD_FILE_HPP
-#include "fud_allocator.hpp"
#include "fud_option.hpp"
#include "fud_permissions.hpp"
#include "fud_result.hpp"
#include "fud_status.hpp"
#include "fud_string_view.hpp"
+#include "fud_vector.hpp"
+#include "fud_drain.hpp"
#include <fcntl.h>
@@ -37,16 +38,17 @@ enum class FileAccessMode : uint8_t
ReadWrite = Read | Write
};
-enum class OpenFlagEnum : uint32_t
+// enum class OpenFlagEnum : uint32_t
+enum class OpenFlagEnum : uint8_t
{
- Append = O_APPEND,
- Truncate = O_TRUNC,
- CloseOnExec = O_CLOEXEC,
- DataSync = O_DSYNC,
- Direct = O_DIRECT,
- NoAtime = O_NOATIME,
- NonBlock = O_NONBLOCK,
- FileSync = O_SYNC
+ Append = 0x01,
+ Truncate = Append << 1,
+ CloseOnExec = Truncate << 1,
+ DataSync = CloseOnExec << 1,
+ Direct = DataSync << 1,
+ NoAtime = Direct << 1,
+ NonBlock = NoAtime << 1,
+ FileSync = NonBlock << 1
};
class OpenFlags {
@@ -90,12 +92,20 @@ class OpenFlags {
return mode;
}
- constexpr FlagType flags() const noexcept
- {
- return m_mask;
+ constexpr uint32_t flags() const noexcept {
+ uint32_t openFlags = 0;
+ openFlags |= static_cast<uint32_t>(hasFlag(OpenFlagEnum::Append)) * O_APPEND;
+ openFlags |= static_cast<uint32_t>(hasFlag(OpenFlagEnum::Truncate)) * O_TRUNC;
+ openFlags |= static_cast<uint32_t>(hasFlag(OpenFlagEnum::CloseOnExec)) * O_CLOEXEC;
+ openFlags |= static_cast<uint32_t>(hasFlag(OpenFlagEnum::DataSync)) * O_DSYNC;
+ openFlags |= static_cast<uint32_t>(hasFlag(OpenFlagEnum::Direct)) * O_DIRECT;
+ openFlags |= static_cast<uint32_t>(hasFlag(OpenFlagEnum::NoAtime)) * O_NOATIME;
+ openFlags |= static_cast<uint32_t>(hasFlag(OpenFlagEnum::NonBlock)) * O_NONBLOCK;
+ openFlags |= static_cast<uint32_t>(hasFlag(OpenFlagEnum::FileSync)) * O_SYNC;
+ return openFlags;
}
- constexpr bool hasFlag(OpenFlagEnum flag) noexcept
+ constexpr bool hasFlag(OpenFlagEnum flag) const noexcept
{
return (m_mask & static_cast<FlagType>(flag)) != 0;
}
@@ -110,16 +120,6 @@ constexpr OpenFlags operator|(OpenFlagEnum lhs, OpenFlagEnum rhs)
return mode | rhs;
}
-struct [[nodiscard]] ReadResult {
- size_t bytesRead{0};
- FudStatus status{FudStatus::Success};
-};
-
-struct [[nodiscard]] WriteResult {
- size_t bytesWritten{0};
- FudStatus status{FudStatus::Success};
-};
-
class RegularFile;
using FileResult = Result<RegularFile, FudStatus>;
@@ -129,8 +129,7 @@ class RegularFile {
StringView filename,
FileAccessMode mode,
OpenFlags flags,
- Option<int> dirFdoption,
- Allocator* allocator = &globalFudAllocator);
+ Option<int> dirFdoption);
static FileResult create(
StringView filename,
@@ -138,8 +137,7 @@ class RegularFile {
OpenFlags flags,
Permissions permissions,
bool exclusive,
- Option<int> dirFdOption,
- Allocator* allocator = &globalFudAllocator);
+ Option<int> dirFdOption);
FudStatus close();
@@ -163,8 +161,20 @@ class RegularFile {
private:
int m_fd{-1};
- FileAccessMode m_modeFlags{};
OpenFlags m_openFlags{};
+ FileAccessMode m_modeFlags{};
+};
+
+class BufferedRegularFile {
+public:
+ DrainResult write(const void* source, size_t sourceSize, size_t length, size_t offset);
+ // DrainResult read(void* sink, );
+private:
+ Vector<std::byte> m_readBuffer{Vector<std::byte>::NullVector()};
+ Vector<std::byte> m_writeBuffer{Vector<std::byte>::NullVector()};
+ RegularFile m_file;
+ bool m_readBuffered{false};
+ bool m_writeBuffered{false};
};
} // namespace fud
diff --git a/include/fud_format.hpp b/include/fud_format.hpp
index 4d38c26..2102dc9 100644
--- a/include/fud_format.hpp
+++ b/include/fud_format.hpp
@@ -20,6 +20,7 @@
// #include "fud_assert.hpp"
#include "dragonbox/dragonbox.h"
+#include "fud_drain.hpp"
#include "fud_array.hpp"
#include "fud_option.hpp"
#include "fud_result.hpp"
@@ -270,21 +271,14 @@ enum class FormatCharMode
ValidUtf8
};
-struct FormatResult {
- size_t bytesWritten{0};
- FudStatus status{FudStatus::Failure};
- [[nodiscard]] constexpr bool isOkay()
- {
- return status == FudStatus::Success;
- }
-};
+using FormatResult = DrainResult;
/* TODO : require concept of a sink that takes pushBack() -> FudStatus */
/* TODO : sink concept also requires drain() -> FudStatus */
-template <typename Sink>
+template <typename Sink> requires Drainable<Sink, StringView>
FormatResult format(Sink& sink, FormatCharMode formatMode, FormatString fmt);
-template <typename Sink, typename... Args>
+template <typename Sink, typename... Args> requires Drainable<Sink, StringView>
FormatResult format(Sink& sink, FormatCharMode formatMode, FormatString fmt, Args&&... args);
template <typename Sink>
@@ -341,7 +335,7 @@ size_t findSpec(StringView scanView);
} // namespace impl
-template <typename Sink, typename... Args>
+template <typename Sink, typename... Args> requires Drainable<Sink, StringView>
FormatResult format(Sink& sink, FormatCharMode formatMode, FormatString fmt, Args&&... args)
{
static_cast<void>(sink);
@@ -355,7 +349,7 @@ FormatResult format(Sink& sink, FormatCharMode formatMode, FormatString fmt, Arg
return impl::vFormat(sink, formatMode, fmt, formatArguments);
}
-template <typename Sink>
+template <typename Sink> requires Drainable<Sink, StringView>
FormatResult format(Sink& sink, FormatCharMode formatMode, FormatString fmt)
{
if (formatMode != FormatCharMode::Unchecked) {
@@ -368,8 +362,7 @@ FormatResult format(Sink& sink, FormatCharMode formatMode, FormatString fmt)
return {0, FudStatus::FormatInvalid};
}
- auto drainResult = sink.drain(fmt.view());
- return FormatResult{drainResult.bytesWritten, drainResult.status};
+ return sink.drain(fmt.view());
}
namespace impl {
@@ -419,7 +412,7 @@ FormatResult vFormat(Sink& sink, FormatCharMode formatMode, FormatString fmt, co
fudAssert(specIndex <= scanView.length());
StringView run{specIndex, scanView.data()};
auto drainResult = sink.drain(run);
- result.bytesWritten += drainResult.bytesWritten;
+ result.bytesDrained += drainResult.bytesDrained;
if (drainResult.status != FudStatus::Success) {
result.status = drainResult.status;
return result;
@@ -451,7 +444,7 @@ FormatResult vFormat(Sink& sink, FormatCharMode formatMode, FormatString fmt, co
result.status = argResult.status;
return result;
}
- result.bytesWritten += argResult.bytesWritten;
+ result.bytesDrained += argResult.bytesDrained;
if (!formatSpec.takesPosition()) {
argIndex++;
argIndex += static_cast<uint8_t>(formatSpec.takesWidth);
@@ -904,7 +897,7 @@ FormatResult drainIntegral(
if (sign.length() > 0) {
auto drainResult = sink.drain(sign);
- result.bytesWritten += drainResult.bytesWritten;
+ result.bytesDrained += drainResult.bytesDrained;
result.status = drainResult.status;
}
@@ -914,7 +907,7 @@ FormatResult drainIntegral(
if (prefix.length() > 0) {
auto drainResult = sink.drain(prefix);
- result.bytesWritten += drainResult.bytesWritten;
+ result.bytesDrained += drainResult.bytesDrained;
result.status = drainResult.status;
}
@@ -925,7 +918,7 @@ FormatResult drainIntegral(
if (padZero) {
auto zeroPadSize = width - calculatedWidth;
auto padResult = fillPad(sink, '0', zeroPadSize);
- result.bytesWritten += padResult.bytesWritten;
+ result.bytesDrained += padResult.bytesDrained;
result.status = padResult.status;
}
@@ -934,7 +927,7 @@ FormatResult drainIntegral(
}
auto drainNumberResult = sink.drain(buffer);
- result.bytesWritten += drainNumberResult.bytesWritten;
+ result.bytesDrained += drainNumberResult.bytesDrained;
result.status = drainNumberResult.status;
if (result.status != FudStatus::Success) {
@@ -942,7 +935,7 @@ FormatResult drainIntegral(
}
auto rightPadResult = rightPad(sink, align, width, fill, calculatedWidth);
- result.bytesWritten += rightPadResult.bytesWritten;
+ result.bytesDrained += rightPadResult.bytesDrained;
result.status = rightPadResult.status;
return result;
@@ -964,19 +957,19 @@ template <typename Sink>
for (auto bufferSize : bufferSizes) {
while (count > bufferSize) {
auto drainResult = sink.drain(StringView{bufferSize, backingBuffer.data()});
- result.bytesWritten += drainResult.bytesWritten;
+ result.bytesDrained += drainResult.bytesDrained;
result.status = drainResult.status;
if (result.status != FudStatus::Success) {
return result;
}
- count -= drainResult.bytesWritten;
+ count -= drainResult.bytesDrained;
}
}
if (count > 0) {
fudAssert(count < backingBuffer.size());
auto drainResult = sink.drain(StringView{count, backingBuffer.data()});
- result.bytesWritten += drainResult.bytesWritten;
+ result.bytesDrained += drainResult.bytesDrained;
result.status = drainResult.status;
}
@@ -1201,45 +1194,45 @@ template <typename Sink, typename DecimalRepr>
if (width > calculatedWidth && not padZero) {
auto padResult = leftPad(sink, align, width, fill, calculatedWidth);
- result.bytesWritten += padResult.bytesWritten;
+ result.bytesDrained += padResult.bytesDrained;
result.status = padResult.status;
}
if (result.status == FudStatus::Success && sign.length() > 0) {
auto drainResult = sink.drain(sign);
- result.bytesWritten += drainResult.bytesWritten;
+ result.bytesDrained += drainResult.bytesDrained;
result.status = drainResult.status;
}
if (result.status == FudStatus::Success && padZero && width > calculatedWidth) {
auto zeroPadSize = width - calculatedWidth;
auto padResult = fillPad(sink, '0', zeroPadSize);
- result.bytesWritten += padResult.bytesWritten;
+ result.bytesDrained += padResult.bytesDrained;
result.status = padResult.status;
}
if (result.status == FudStatus::Success) {
auto drainNumberResult = sink.drain(numberView);
- result.bytesWritten += drainNumberResult.bytesWritten;
+ result.bytesDrained += drainNumberResult.bytesDrained;
result.status = drainNumberResult.status;
}
if (result.status == FudStatus::Success && precision > precisionPlaces) {
auto remainingPlaces = precision - precisionPlaces;
auto precisionResult = fillPad(sink, '0', remainingPlaces);
- result.bytesWritten += precisionResult.bytesWritten;
+ result.bytesDrained += precisionResult.bytesDrained;
result.status = precisionResult.status;
}
if (result.status == FudStatus::Success) {
auto exponentDrainResult = sink.drain(exponentView);
- result.bytesWritten += exponentDrainResult.bytesWritten;
+ result.bytesDrained += exponentDrainResult.bytesDrained;
result.status = exponentDrainResult.status;
}
if (result.status == FudStatus::Success) {
auto padResult = rightPad(sink, align, width, fill, calculatedWidth);
- result.bytesWritten += padResult.bytesWritten;
+ result.bytesDrained += padResult.bytesDrained;
result.status = padResult.status;
}
@@ -1441,7 +1434,7 @@ FormatResult format(Sink& sink, FormatCharMode formatMode, const FormatSpec& for
}
auto padResult = impl::leftPad(sink, align, width, fill, calculatedWidth);
- result.bytesWritten += padResult.bytesWritten;
+ result.bytesDrained += padResult.bytesDrained;
result.status = padResult.status;
if (result.status != FudStatus::Success) {
@@ -1449,7 +1442,7 @@ FormatResult format(Sink& sink, FormatCharMode formatMode, const FormatSpec& for
}
auto drainViewResult = sink.drain(arg);
- result.bytesWritten += drainViewResult.bytesWritten;
+ result.bytesDrained += drainViewResult.bytesDrained;
result.status = drainViewResult.status;
if (result.status != FudStatus::Success) {
@@ -1457,7 +1450,7 @@ FormatResult format(Sink& sink, FormatCharMode formatMode, const FormatSpec& for
}
padResult = impl::rightPad(sink, align, width, fill, calculatedWidth);
- result.bytesWritten += padResult.bytesWritten;
+ result.bytesDrained += padResult.bytesDrained;
result.status = padResult.status;
return result;
diff --git a/include/fud_vector.hpp b/include/fud_vector.hpp
index 2b5de9a..52876fd 100644
--- a/include/fud_vector.hpp
+++ b/include/fud_vector.hpp
@@ -70,6 +70,12 @@ class Vector {
rhs.m_capacity = 0;
}
+ static constexpr Vector<T> NullVector() noexcept {
+ Vector<T> output{};
+ output.m_allocator = &globalNullAllocator;
+ return output;
+ }
+
static Result<Vector<T>, FudStatus> withCapacity(size_t capacity, Allocator* allocator = &globalFudAllocator)
{
Vector<T> output{};
@@ -104,7 +110,7 @@ class Vector {
}
output.m_allocator = allocator;
- output.m_data = static_cast<T*>(dataPtrResult.getOkay());
+ output.m_data = reinterpret_cast<T*>(dataPtrResult.getOkay());
output.m_length = 0;
output.m_capacity = capacity;
return FudStatus::Success;
@@ -341,7 +347,7 @@ class Vector {
return dataPtrResult.takeError();
}
- auto* dataPtr = static_cast<T*>(dataPtrResult.takeOkay());
+ 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]));
fudAssert(ptr != nullptr);
@@ -350,7 +356,7 @@ class Vector {
auto status = FudStatus::Success;
if (m_capacity > 0) {
- status = m_allocator->deallocate(m_data, m_capacity);
+ status = m_allocator->deallocate(reinterpret_cast<std::byte*>(m_data), m_capacity);
}
m_data = dataPtr;
@@ -666,7 +672,7 @@ class Vector {
auto status = clear();
if (m_data != nullptr && m_allocator != nullptr) {
- auto deallocStatus = m_allocator->deallocate(m_data, m_capacity);
+ auto deallocStatus = m_allocator->deallocate(reinterpret_cast<std::byte*>(m_data), m_capacity);
if (status == FudStatus::Success) {
status = deallocStatus;
}