summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/fud_allocator.hpp11
-rw-r--r--include/fud_assert.hpp13
-rw-r--r--include/fud_c_file.hpp6
-rw-r--r--include/fud_result.hpp55
-rw-r--r--include/fud_span.hpp120
-rw-r--r--include/fud_status.hpp9
-rw-r--r--include/fud_string.hpp3
-rw-r--r--include/libfud.hpp8
8 files changed, 186 insertions, 39 deletions
diff --git a/include/fud_allocator.hpp b/include/fud_allocator.hpp
index 8955fae..a9fbd67 100644
--- a/include/fud_allocator.hpp
+++ b/include/fud_allocator.hpp
@@ -32,8 +32,7 @@ class Allocator {
virtual Result<void*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) = 0;
- /* ...should this be void? */
- virtual void deallocate(void* pointer, size_t bytes, size_t alignment = alignof(std::max_align_t)) = 0;
+ virtual FudStatus deallocate(void* pointer, size_t bytes) = 0;
virtual bool isEqual(const Allocator& rhs) const = 0;
};
@@ -48,8 +47,7 @@ class FudAllocator : public Allocator {
virtual Result<void*, FudStatus> allocate(size_t bytes, size_t alignment = alignof(std::max_align_t)) override;
- /* ...should this be void? */
- virtual void deallocate(void* pointer, size_t bytes, size_t alignment = alignof(std::max_align_t)) override;
+ virtual FudStatus deallocate(void* pointer, size_t bytes) override;
virtual bool isEqual(const Allocator& rhs) const override;
};
@@ -59,12 +57,9 @@ extern FudAllocator globalFudAllocator;
/** \brief The default allocation function for globalFudAllocator. */
extern void* fudAlloc(size_t size);
-/** \brief The default allocation function for globalFudAllocator. */
-extern void* fudRealloc(void* ptr, size_t size);
-
+/** \brief The default deallocation function for globalFudAllocator. */
extern void fudFree(void* ptr);
-
} // namespace fud
#endif
diff --git a/include/fud_assert.hpp b/include/fud_assert.hpp
index 6b21fdc..ecfaa2f 100644
--- a/include/fud_assert.hpp
+++ b/include/fud_assert.hpp
@@ -22,9 +22,22 @@
// #include <stacktrace>
#include <source_location>
+#include "fud_span.hpp"
namespace fud {
+constexpr std::size_t MAX_FILE_CHARS = 256;
+constexpr std::size_t MAX_FUNCTION_CHARS = 256;
+constexpr std::size_t BITS_PER_OCTAL = 3;
+constexpr auto MAX_LINE_CHARS = BITS_PER_OCTAL * sizeof(decltype(std::source_location{}.line())) + 3;
+constexpr std::size_t MAX_ASSERT_CHARS = 512 - MAX_LINE_CHARS;
+constexpr std::size_t ASSERT_MSG_SIZE = MAX_FILE_CHARS + MAX_LINE_CHARS + MAX_FUNCTION_CHARS + MAX_ASSERT_CHARS;
+
+void assertFormat(
+ const char* assertion,
+ std::source_location sourceLocation,
+ Span<char, ASSERT_MSG_SIZE> buffer);
+
[[noreturn]] void assertFail(
const char* assertion,
std::source_location sourceLocation = std::source_location::current());
diff --git a/include/fud_c_file.hpp b/include/fud_c_file.hpp
index 4905643..b54b044 100644
--- a/include/fud_c_file.hpp
+++ b/include/fud_c_file.hpp
@@ -220,7 +220,7 @@ class CFile {
}
if (offset > LONG_MAX || SIZE_MAX - offset < length || destinationSize < length) {
- result.status = FudStatus::InvalidInput;
+ result.status = FudStatus::ArgumentInvalid;
return result;
}
@@ -232,7 +232,7 @@ class CFile {
auto fileSize = fileSizeResult.getOkay();
if (offset + length > fileSize) {
- result.status = FudStatus::InvalidInput;
+ result.status = FudStatus::ArgumentInvalid;
return result;
}
@@ -306,7 +306,7 @@ class CFile {
}
if (offset > LONG_MAX || SIZE_MAX - offset < length || sourceSize < length) {
- result.status = FudStatus::InvalidInput;
+ result.status = FudStatus::ArgumentInvalid;
return result;
}
diff --git a/include/fud_result.hpp b/include/fud_result.hpp
index 5dabaf5..4bfb819 100644
--- a/include/fud_result.hpp
+++ b/include/fud_result.hpp
@@ -28,6 +28,22 @@ class [[nodiscard]] Result {
public:
using ResultType = Result<T, E>;
+ Result(const T& value) : m_value{value}
+ {
+ }
+
+ Result(const E& value) : m_value{value}
+ {
+ }
+
+ Result(T&& value) : m_value{std::move(value)}
+ {
+ }
+
+ Result(E&& value) : m_value{std::move(value)}
+ {
+ }
+
static ResultType okay(const T& okay)
{
return ResultType{okay};
@@ -49,22 +65,26 @@ class [[nodiscard]] Result {
}
template <typename F>
- static ResultType okay(const Result<T, F>& okayRes) {
+ static ResultType okay(const Result<T, F>& okayRes)
+ {
return ResultType{okayRes.getOkay()};
}
template <typename F>
- static ResultType okay(Result<T, F>&& okayRes) {
+ static ResultType okay(Result<T, F>&& okayRes)
+ {
return ResultType{okayRes.takeOkay()};
}
template <typename U>
- static ResultType error(const Result<U, E>& errorRes) {
+ static ResultType error(const Result<U, E>& errorRes)
+ {
return ResultType{errorRes.getError()};
}
template <typename U>
- static ResultType error(Result<U, E>&& errorRes) {
+ static ResultType error(Result<U, E>&& errorRes)
+ {
return ResultType{errorRes.takeError()};
}
@@ -99,29 +119,22 @@ class [[nodiscard]] Result {
}
private:
- explicit Result() : m_value()
- {
- }
-
- explicit Result(const T& value) : m_value{value}
- {
- }
-
- explicit Result(const E& value) : m_value{value}
- {
- }
-
- explicit Result(T&& value): m_value{std::move(value)}
- {
- }
-
- explicit Result(E&& value) : m_value{std::move(value)}
+ Result() : m_value()
{
}
std::variant<T, E> m_value;
};
+#define M_TakeOrReturn(HYGIENE_EXPRESSION) \
+ ({ \
+ auto HYGIENE_RESULT{(HYGIENE_EXPRESSION)}; \
+ if (HYGIENE_RESULT.isError()) { \
+ return HYGIENE_RESULT.takeError(); \
+ } \
+ HYGIENE_RESULT.takeOkay(); \
+ })
+
} // namespace fud
#endif
diff --git a/include/fud_span.hpp b/include/fud_span.hpp
new file mode 100644
index 0000000..e8c5704
--- /dev/null
+++ b/include/fud_span.hpp
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+#ifndef FUD_SPAN_HPP
+#define FUD_SPAN_HPP
+
+#include <cstdlib>
+
+#include "fud_array.hpp"
+
+namespace fud {
+
+template <typename T, size_t Size>
+struct Span {
+ static_assert(Size > 0);
+ using ValueType = T;
+
+ static Span make(Array<T, Size>& array) {
+ Span<T, Size> output{};
+ output.m_data = array.data();
+ return output;
+ }
+
+ template <typename U>
+ static Span make(const Array<U, Size>& array) {
+ static_assert(std::convertible_to<U, T>);
+ Span<T, Size> output{};
+ output.m_data = array.data();
+ return output;
+ }
+
+ T* m_data;
+
+ [[nodiscard]] constexpr size_t size() const
+ {
+ return Size;
+ }
+
+ constexpr T& front()
+ {
+ return m_data[0];
+ }
+
+ constexpr const T& front() const
+ {
+ return m_data[0];
+ }
+
+ constexpr T& back()
+ {
+ return m_data[Size - 1];
+ }
+
+ constexpr const T& back() const
+ {
+ return m_data[Size - 1];
+ }
+
+ constexpr T* data() noexcept
+ {
+ return m_data;
+ }
+
+ constexpr const T* data() const noexcept
+ {
+ return m_data;
+ }
+
+ constexpr T* begin() noexcept
+ {
+ return m_data;
+ }
+
+ constexpr const T* begin() const noexcept
+ {
+ return m_data;
+ }
+
+ constexpr T* end() noexcept
+ {
+ return m_data + Size;
+ }
+
+ constexpr const T* end() const noexcept
+ {
+ return m_data + Size;
+ }
+
+ constexpr T& operator[](size_t index)
+ {
+ return m_data[index];
+ }
+
+ constexpr const T& operator[](size_t index) const
+ {
+ return m_data[index];
+ }
+
+ constexpr bool operator==(const Span<T, Size>&) const noexcept = default;
+
+ constexpr auto operator<=>(const Span<T, Size>& other) const noexcept = default;
+};
+
+} // namespace fud
+
+#endif
diff --git a/include/fud_status.hpp b/include/fud_status.hpp
index 5ebf229..bda646b 100644
--- a/include/fud_status.hpp
+++ b/include/fud_status.hpp
@@ -28,7 +28,8 @@ enum class [[nodiscard]] FudStatus
ObjectInvalid,
OperationInvalid,
AllocFailure,
- InvalidInput,
+ DeallocFailure,
+ ArgumentInvalid,
Utf8Invalid,
Failure,
NotFound,
@@ -58,8 +59,10 @@ constexpr const char* FudStatusToString(FudStatus status)
return "OperationInvalid";
case FudStatus::AllocFailure:
return "AllocFailure";
- case FudStatus::InvalidInput:
- return "InvalidInput";
+ case FudStatus::DeallocFailure:
+ return "DeallocFailure";
+ case FudStatus::ArgumentInvalid:
+ return "ArgumentInvalid";
case FudStatus::Utf8Invalid:
return "Utf8Invalid";
case FudStatus::Failure:
diff --git a/include/fud_string.hpp b/include/fud_string.hpp
index 4367aae..ba05450 100644
--- a/include/fud_string.hpp
+++ b/include/fud_string.hpp
@@ -72,7 +72,7 @@ class String {
auto lengthResult = cStringLength(cString);
if (lengthResult < 0 || lengthResult >= SSIZE_MAX) {
- return StringResult::error(FudStatus::InvalidInput);
+ return StringResult::error(FudStatus::ArgumentInvalid);
}
auto stringLength = static_cast<size_t>(lengthResult);
if (SIZE_MAX - totalLength < stringLength) {
@@ -89,6 +89,7 @@ class String {
output.m_allocator = allocator;
if (output.m_length >= output.m_capacity) {
output.m_capacity = output.m_length + 1;
+ /* Avoid using compiler expansions in headers */
auto dataResult = output.m_allocator->allocate(output.m_capacity);
if (dataResult.isError()) {
return StringResult::error(dataResult.getError());
diff --git a/include/libfud.hpp b/include/libfud.hpp
index 5bc1630..bff791d 100644
--- a/include/libfud.hpp
+++ b/include/libfud.hpp
@@ -19,6 +19,7 @@
#define LIBFUD_HPP
#include "fud_array.hpp"
+#include "fud_allocator.hpp"
#include "fud_result.hpp"
#include "fud_status.hpp"
#include "fud_string.hpp"
@@ -43,12 +44,13 @@ FUD fud();
* \brief Get an environmental variable if it exists.
*
* \param[in] name The name of the variable to look up.
+ * \param[in] allocator The allocator used by the string returned.
*
* \retstmt The value of the string bound to the variable if it exists.
* \retcode FudStatus::NullPointer if name is a null pointer.
* \retcode FudStatus::NotFound if no binding for the variable exists.
*/
-Result<String, FudStatus> getEnv(const char* name);
+Result<String, FudStatus> getEnv(const char* name, Allocator* allocator= &globalFudAllocator);
template <typename T>
concept CStringRepr = requires(T strObj) {
@@ -56,9 +58,9 @@ concept CStringRepr = requires(T strObj) {
};
template <CStringRepr T>
-Result<String, FudStatus> getEnv(const T& name)
+Result<String, FudStatus> getEnv(const T& name, Allocator* allocator = &globalFudAllocator)
{
- return getEnv(name.c_str());
+ return getEnv(name.c_str(), allocator);
}
} // namespace fud