summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorDominick Allen <djallen@librehumanitas.org>2024-10-20 10:48:19 -0500
committerDominick Allen <djallen@librehumanitas.org>2024-10-20 10:48:19 -0500
commit6a27a2a4032e88fa9154ef0f0741edc584f7a701 (patch)
tree92ca58cbcdd2c1d11b7d69deb0d4925d0f979a3f /include
parente94db4695e236b42ae1be44b2605075161d5144f (diff)
Lots of work.
Diffstat (limited to 'include')
-rw-r--r--include/fud_algorithm.hpp162
-rw-r--r--include/fud_array.hpp4
-rw-r--r--include/fud_c_string.hpp55
-rw-r--r--include/fud_format.hpp362
-rw-r--r--include/fud_result.hpp35
-rw-r--r--include/fud_span.hpp75
-rw-r--r--include/fud_status.hpp3
-rw-r--r--include/fud_string.hpp1
-rw-r--r--include/fud_string_view.hpp14
-rw-r--r--include/fud_utf8.hpp130
-rw-r--r--include/fud_vector.hpp64
11 files changed, 595 insertions, 310 deletions
diff --git a/include/fud_algorithm.hpp b/include/fud_algorithm.hpp
new file mode 100644
index 0000000..e3d5d3b
--- /dev/null
+++ b/include/fud_algorithm.hpp
@@ -0,0 +1,162 @@
+/*
+ * 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_ALGORITHM_HPP
+#define FUD_ALGORITHM_HPP
+
+#include "fud_span.hpp"
+
+#include <concepts>
+#include <limits>
+#include <optional>
+#include <type_traits>
+
+namespace fud {
+
+template <std::integral T>
+class Iota {
+ public:
+ constexpr Iota() noexcept : m_value{}, m_increment{static_cast<T>(1)}, m_limit{std::numeric_limits<T>::max()}
+ {
+ }
+
+ constexpr Iota(T value) noexcept :
+ m_value{value}, m_increment{static_cast<T>(1)}, m_limit{std::numeric_limits<T>::max()}
+ {
+ }
+
+ constexpr Iota(T value, T increment) noexcept :
+ m_value{value}, m_increment{increment}, m_limit{std::numeric_limits<T>::max()}
+ {
+ }
+
+ constexpr Iota(T value, T increment, T limit) noexcept : m_value{value}, m_increment{increment}, m_limit{limit}
+ {
+ }
+
+ constexpr std::optional<T> operator()() noexcept
+ {
+ auto value = m_value;
+ if (m_increment > 0) {
+ if (m_limit - m_increment < m_value) {
+ return std::nullopt;
+ }
+ } else {
+ if (m_limit + m_increment + 1 >= m_value) {
+ return std::nullopt;
+ }
+ }
+ m_value += m_increment;
+ return value;
+ }
+
+ void set(T value) {
+ m_value = value;
+ }
+
+ private:
+ T m_value;
+ const T m_increment;
+ const T m_limit;
+};
+
+template <typename T, size_t Size, typename Func>
+Span<T, Size> forEach(Span<T, Size> input, Func&& mapFunc)
+{
+ for (auto& element : input) {
+ element = std::forward<Func>(mapFunc)(element);
+ }
+
+ return input;
+}
+
+template <typename T, typename U, size_t Size, typename Func>
+Span<T, Size> mapTo(Span<T, Size> input, Span<U, Size> output, Func&& mapFunc)
+{
+ for (auto idx = 0; idx < input.size(); ++idx) {
+ output[idx] = std::forward<Func>(mapFunc)(input[idx]);
+ }
+
+ return input;
+}
+
+template <typename T, size_t Size, typename Func, typename Builder, typename Output>
+auto map(Span<T, Size> input, Func&& mapFunc, Builder&& builder) -> decltype(std::forward<Builder>(builder)())
+{
+ Output output{std::forward<Builder>(builder)()};
+ for (auto idx = 0; idx < input.size() && idx < output.size(); ++idx) {
+ output[idx] = std::forward<Func>(mapFunc)(input[idx]);
+ }
+
+ return input;
+}
+
+template <typename Generator, typename Builder>
+auto generate(Builder&& builder, Generator&& generator) -> decltype(std::forward<Builder>(builder)())
+{
+ using Output = decltype(std::forward<Builder>(builder)());
+ Output output{std::forward<Builder>(builder)()};
+ for (auto idx = 0; idx < output.size(); ++idx) {
+ output[idx] = std::forward<Generator>(generator)();
+ }
+
+ return output;
+}
+
+template <typename T, size_t Size, typename Func>
+bool allOf(Span<T, Size> input, Func&& predicate)
+{
+ bool result = input.size() > 0;
+ for (size_t idx = 0; result && idx < input.size(); ++idx) {
+ result = result && std::forward<Func>(predicate)(input[idx]);
+ }
+ return result;
+}
+
+template <typename Generator, typename Func>
+bool allOf(Generator&& generator, Func&& predicate)
+{
+ bool result = true;
+ while (auto val = std::forward<Generator>(generator)()) {
+ result = result && std::forward<Func>(predicate)(*val);
+ }
+ return result;
+}
+
+template <typename T, size_t Size, typename Func>
+bool anyOf(Span<T, Size> input, Func&& predicate)
+{
+ bool result = !(input.size() > 0);
+ for (size_t idx = 0; result && idx < input.size(); ++idx) {
+ result = result || std::forward<Func>(predicate)(input[idx]);
+ }
+ return result;
+}
+
+template <typename Generator, typename Func>
+bool anyOf(Generator&& generator, Func&& predicate)
+{
+ bool result = false;
+ while (auto val = std::forward<Generator>(generator)()) {
+ result = result || std::forward<Func>(predicate)(*val);
+ }
+ return result;
+}
+
+} // namespace fud
+
+#endif
diff --git a/include/fud_array.hpp b/include/fud_array.hpp
index 4e2c702..807621a 100644
--- a/include/fud_array.hpp
+++ b/include/fud_array.hpp
@@ -18,9 +18,9 @@
#ifndef FUD_ARRAY_HPP
#define FUD_ARRAY_HPP
-#include "fud_memory.hpp"
+#include <cstddef>
-#include <cstdlib>
+#include "fud_memory.hpp"
namespace fud {
diff --git a/include/fud_c_string.hpp b/include/fud_c_string.hpp
new file mode 100644
index 0000000..44e0dc8
--- /dev/null
+++ b/include/fud_c_string.hpp
@@ -0,0 +1,55 @@
+/*
+ * 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_C_STRING_HPP
+#define FUD_C_STRING_HPP
+
+#include <climits>
+#include <cstddef>
+#include <sys/types.h>
+
+
+namespace fud {
+
+constexpr ssize_t cStringLength(const char* str, size_t maxLength)
+{
+ if (str == nullptr || maxLength > (SSIZE_MAX - 1)) {
+ return -1;
+ }
+
+ ssize_t size = 0;
+
+ while (str[size] != 0 && static_cast<size_t>(size) < maxLength) {
+ size++;
+ }
+
+ if (str[size] != 0 && static_cast<size_t>(size) == maxLength) {
+ return static_cast<ssize_t>(maxLength) + 1;
+ }
+
+ return size;
+}
+
+constexpr ssize_t cStringLength(const char* str)
+{
+ constexpr auto maxLength = SSIZE_MAX - 1;
+ return cStringLength(str, maxLength);
+}
+
+} // namespace fud
+
+#endif
diff --git a/include/fud_format.hpp b/include/fud_format.hpp
index 8985faf..ea32bd8 100644
--- a/include/fud_format.hpp
+++ b/include/fud_format.hpp
@@ -18,275 +18,179 @@
#ifndef FUD_FORMAT_HPP
#define FUD_FORMAT_HPP
-#include "fud_assert.hpp"
+// #include "fud_assert.hpp"
#include "fud_result.hpp"
-#include "fud_span.hpp"
#include "fud_status.hpp"
#include "fud_string_view.hpp"
+#include "fud_utf8.hpp"
-#include <format> // for std::format_string
#include <cstdint>
#include <optional>
+#include <variant>
namespace fud {
-template <size_t Size>
-using CharSpan = Span<char, Size>;
-
-template <typename... Args>
-using FormatLiteral = std::format_string<Args...>;
+struct FormatAlign
+{
+ enum class Value : uint8_t
+ {
+ Left,
+ Right,
+ Center
+ };
+
+ constexpr static std::optional<FormatAlign> from(utf8 letter)
+ {
+ FormatAlign formatAlign;
+ switch (letter) {
+ case '<':
+ formatAlign.value = Value::Left;
+ break;
+ case '>':
+ formatAlign.value = Value::Right;
+ break;
+ case '^':
+ formatAlign.value = Value::Center;
+ break;
+ default:
+ return std::nullopt;
+ }
-template <typename... Args, size_t Size>
-Result<size_t, FudStatus> format(CharSpan<Size> buffer, FormatLiteral<Args...> formatLiteral, Args&&... args);
+ return formatAlign;
+ }
-enum class FormatAlign : uint8_t {
- Left,
- Right,
- Center
+ Value value;
};
struct FormatFill {
FormatAlign align;
- char fill;
+ utf8 fill;
+
+ constexpr static Result<std::optional<FormatFill>, FudStatus> parse(StringView formatView) {
+ // "{:A<X}"
+ using RetType = Result<std::optional<FormatFill>, FudStatus>;
+ if (formatView.length() < 3) {
+ return RetType::okay(std::nullopt);
+ }
+
+ const auto* data = formatView.data();
+ if (data[0] != 'A') {
+ return RetType::okay(std::nullopt);
+ }
+
+ auto align = FormatAlign::from(data[1]);
+ if (!align.has_value()) {
+ return FudStatus::FormatInvalid;
+ }
+
+ auto fill = data[2];
+ if (!Ascii::valid(fill)) {
+ return FudStatus::Utf8Invalid;
+ }
+
+ return RetType::okay(FormatFill{*align, fill});
+ }
};
-enum class FormatSign : uint8_t {
+enum class FormatSign : uint8_t
+{
Plus,
Minus,
Space
};
-struct FormatSpec {
- std::optional<FormatFill> fill;
- std::optional<FormatSign> formatSign;
- uint32_t minWidth;
+enum class FormatStringType : uint8_t
+{
+ String,
+ Escaped,
};
-namespace detail {
-
-template <typename Arg, typename... Args, size_t Size>
-Result<size_t, FudStatus> formatHelper(
- CharSpan<Size> buffer,
- size_t formattedSize,
- StringView formatView,
- Arg&& arg,
- Args&&... args);
-
-template <typename Arg, typename... Args, size_t Size>
-Result<size_t, FudStatus> formatHelper(
- CharSpan<Size> buffer,
- size_t formattedSize,
- StringView formatView,
- Arg&& arg);
-
-template <size_t Size>
-Result<size_t, FudStatus> formatHelper(
- CharSpan<Size> buffer,
- size_t formattedSize,
- StringView formatView);
-
-} // namespace detail
-
-template <typename... Args, size_t Size>
-Result<size_t, FudStatus> format(CharSpan<Size> buffer, FormatLiteral<Args...> formatLiteral, Args&&... args)
+enum class FormatIntegerType : uint8_t
{
- static_assert(Size > 0);
-
- if (buffer.data() == nullptr) {
- return FudStatus::NullPointer;
- }
-
- StringView formatView{formatLiteral.get()};
-
- if (formatView.length() == 0 || formatView.data()[0] == '\0') {
- return 0U;
- }
-
- size_t argCount = sizeof...(args);
- static_cast<void>(argCount);
-
- size_t formattedSize = 0;
+ BinaryLower,
+ BinaryUpper,
+ Character,
+ Decimal,
+ Octal,
+ HexLower,
+ HexUpper,
+};
- return detail::formatHelper(buffer, formattedSize, formatView, std::forward<Args>(args)...);
-}
+enum class FormatCharacterType : uint8_t
+{
+ BinaryLower,
+ BinaryUpper,
+ Character,
+ Decimal,
+ Octal,
+ HexLower,
+ HexUpper,
+};
-namespace detail {
+enum class FormatBoolType : uint8_t
+{
+ BinaryLower,
+ BinaryUpper,
+ Character,
+ Decimal,
+ Octal,
+ HexLower,
+ HexUpper,
+};
-#define FUDETAIL_ADVANCE_FORMAT(FORMAT_VIEW, ADVANCE_BY) \
- fudAssert(ADVANCE_BY <= FORMAT_VIEW.m_length); \
- FORMAT_VIEW.m_length -= ADVANCE_BY; \
- FORMAT_VIEW.m_data += ADVANCE_BY; \
+enum class FormatFloatingType : uint8_t
+{
+ FloatHexLower,
+ FloatHexUpper,
+ ScientificLower,
+ ScientificUpper,
+ Fixed,
+ GeneralLower,
+ GeneralUpper
+};
-constexpr bool findBracket(size_t& copyLength, StringView formatView)
+enum class FormatPointerType : uint8_t
{
- while (copyLength < formatView.m_length) {
- if (formatView.m_data[copyLength] == '{') {
- return true;
- }
- copyLength++;
- }
+ HexLower,
+ HexUpper
+};
- return false;
-}
+using FormatType = std::variant< // break
+ std::monostate,
+ FormatStringType,
+ FormatIntegerType,
+ FormatCharacterType,
+ FormatBoolType,
+ FormatFloatingType,
+ FormatPointerType>;
-template <size_t Size>
-size_t copyRemaining(
- CharSpan<Size> buffer,
- size_t formattedSize,
- StringView& formatView,
- size_t copyLength)
-{
- fudAssert(copyLength <= formatView.length());
- if (copyLength + formattedSize > Size) {
- copyLength = Size - formattedSize;
- }
- auto copyResult = copyMem(
- buffer.data() + formattedSize,
- Size - formattedSize,
- formatView.m_data,
- copyLength);
- fudAssert(copyResult == FudStatus::Success);
- FUDETAIL_ADVANCE_FORMAT(formatView, copyLength);
- return formattedSize + copyLength;
-}
-
-template <typename Arg, size_t Size>
-Result<size_t, FudStatus> handleSpec(
- CharSpan<Size> buffer,
- size_t formattedSize,
- StringView& formatView,
- Arg&& arg,
- bool& consumed)
-{
- fudAssert(formattedSize < Size);
- fudAssert(formatView.length() > 1);
-
- if (formatView.m_data[1] == '{') {
- consumed = false;
- buffer[formattedSize] = '{';
- FUDETAIL_ADVANCE_FORMAT(formatView, 2);
- return formattedSize + 1;
- }
+struct FormatSpec;
+using FormatSpecResult = Result<FormatSpec, FudStatus>;
- static_cast<void>(arg);
- buffer[formattedSize] = 'X';
- formattedSize += 1;
- size_t index = 0;
- for (; index < formatView.m_length; ++index) {
- if (formatView.m_data[index] == '}') {
- break;
- }
- }
- FUDETAIL_ADVANCE_FORMAT(formatView, index + 1);
- return formattedSize;
-}
-
-template <typename Arg, typename... Args, size_t Size>
-Result<size_t, FudStatus> formatHelper(
- CharSpan<Size> buffer,
- size_t formattedSize,
- StringView formatView,
- Arg&& arg,
- Args&&... args)
-{
- while (formattedSize < Size) {
- size_t copyLength = 0;
- auto found = findBracket(copyLength, formatView);
- formattedSize = copyRemaining(buffer, formattedSize, formatView, copyLength);
- fudAssert(formattedSize <= Size);
- if (!found || formattedSize == Size) {
- return formattedSize;
- }
+struct FormatSpec {
+ size_t width;
+ size_t precision;
+ FormatFill fill;
+ FormatSign formatSign;
- bool consumed = false;
- auto specResult = handleSpec(buffer, formattedSize, formatView, std::forward<Arg>(arg), consumed);
- formattedSize = M_TakeOrReturn(specResult);
- fudAssert(formattedSize <= Size);
- if (formattedSize == Size) {
- return formattedSize;
- }
+ FormatType formatType;
- if (consumed) {
- return formatHelper(buffer, formattedSize, formatView, std::forward<Args>(args)...);
- }
- }
+ bool hasWidth;
+ bool takesWidth;
- return formattedSize;
-}
+ bool hasPrecision;
+ bool takesPrecision;
-template <typename Arg, typename... Args, size_t Size>
-Result<size_t, FudStatus> formatHelper(
- CharSpan<Size> buffer,
- size_t formattedSize,
- StringView formatView,
- Arg&& arg)
-{
- while (formattedSize < Size) {
- size_t copyLength = 0;
- auto found = findBracket(copyLength, formatView);
- formattedSize = copyRemaining(buffer, formattedSize, formatView, copyLength);
- fudAssert(formattedSize <= Size);
- if (!found || formattedSize == Size) {
- return formattedSize;
- }
+ bool hasFill;
- bool consumed = false;
- auto specResult = handleSpec(buffer, formattedSize, formatView, std::forward<Arg>(arg), consumed);
- formattedSize = M_TakeOrReturn(specResult);
- if (consumed) {
- return formatHelper(buffer, formattedSize, formatView);
- }
- }
- return formattedSize;
-}
-
-template <size_t Size>
-Result<size_t, FudStatus> formatHelper(
- CharSpan<Size> buffer,
- size_t formattedSize,
- StringView formatView)
-{
- size_t index = 0;
- while (formattedSize < Size && formatView.m_length > 0) {
- while (index < formatView.m_length && formattedSize + index < Size) {
- if (formatView.m_data[index] == '{') {
- break;
- }
- index++;
- }
- bool isBracket{false};
- if (index + 1 < formatView.m_length && formattedSize + index + 1 < Size) {
- if (formatView.m_data[index] == '{') {
- isBracket = true;
- index++;
- }
- }
- auto copyResult = copyMem(
- buffer.data() + formattedSize,
- Size - formattedSize,
- formatView.m_data,
- index);
- formattedSize += index;
- formatView.m_length -= index;
- formatView.m_data += index;
- if (isBracket) {
- index = 0;
- if (formatView.m_length > 0) {
- formatView.m_length--;
- formatView.m_data++;
- }
- if (formattedSize < Size) {
- buffer.data()[formattedSize] = 'X';
- formattedSize++;
- }
- }
- }
- return formattedSize;
-}
+ bool hasFormatSign;
+
+ bool alternateForm;
-#undef FUDETAIL_ADVANCE_FORMAT
+ bool leadingZero;
-} // namespace detail
+ static Result<FormatSpec, FudStatus> make(StringView& formatView, size_t specIndex);
+};
} // namespace fud
diff --git a/include/fud_result.hpp b/include/fud_result.hpp
index 4bfb819..877c49c 100644
--- a/include/fud_result.hpp
+++ b/include/fud_result.hpp
@@ -19,6 +19,7 @@
#define FUD_RESULT_HPP
#include <variant>
+#include <utility>
namespace fud {
@@ -28,62 +29,62 @@ class [[nodiscard]] Result {
public:
using ResultType = Result<T, E>;
- Result(const T& value) : m_value{value}
+ constexpr Result(const T& value) : m_value{value}
{
}
- Result(const E& value) : m_value{value}
+ constexpr Result(const E& value) : m_value{value}
{
}
- Result(T&& value) : m_value{std::move(value)}
+ constexpr Result(T&& value) : m_value{std::move(value)}
{
}
- Result(E&& value) : m_value{std::move(value)}
+ constexpr Result(E&& value) : m_value{std::move(value)}
{
}
- static ResultType okay(const T& okay)
+ static constexpr ResultType okay(const T& okay)
{
return ResultType{okay};
}
- static ResultType okay(T&& okay)
+ static constexpr ResultType okay(T&& okay)
{
return ResultType{std::move(okay)};
}
- static ResultType error(const E& error)
+ static constexpr ResultType error(const E& error)
{
return ResultType{error};
}
- static ResultType error(E&& error)
+ static constexpr ResultType error(E&& error)
{
return ResultType{std::move(error)};
}
template <typename F>
- static ResultType okay(const Result<T, F>& okayRes)
+ static constexpr ResultType okay(const Result<T, F>& okayRes)
{
return ResultType{okayRes.getOkay()};
}
template <typename F>
- static ResultType okay(Result<T, F>&& okayRes)
+ static constexpr ResultType okay(Result<T, F>&& okayRes)
{
return ResultType{okayRes.takeOkay()};
}
template <typename U>
- static ResultType error(const Result<U, E>& errorRes)
+ static constexpr ResultType error(const Result<U, E>& errorRes)
{
return ResultType{errorRes.getError()};
}
template <typename U>
- static ResultType error(Result<U, E>&& errorRes)
+ static constexpr ResultType error(Result<U, E>&& errorRes)
{
return ResultType{errorRes.takeError()};
}
@@ -98,28 +99,28 @@ class [[nodiscard]] Result {
return (m_value.index() == 1);
}
- [[nodiscard]] const T& getOkay() const&
+ [[nodiscard]] constexpr const T& getOkay() const&
{
return std::get<T>(m_value);
}
- [[nodiscard]] const E& getError() const&
+ [[nodiscard]] constexpr const E& getError() const&
{
return std::get<E>(m_value);
}
- [[nodiscard]] T&& takeOkay()
+ [[nodiscard]] constexpr T&& takeOkay()
{
return std::move(std::get<T>(m_value));
}
- [[nodiscard]] E&& takeError()
+ [[nodiscard]] constexpr E&& takeError()
{
return std::move(std::get<E>(m_value));
}
private:
- Result() : m_value()
+ constexpr Result() : m_value()
{
}
diff --git a/include/fud_span.hpp b/include/fud_span.hpp
index cc693f8..5b8497e 100644
--- a/include/fud_span.hpp
+++ b/include/fud_span.hpp
@@ -18,41 +18,71 @@
#ifndef FUD_SPAN_HPP
#define FUD_SPAN_HPP
-#include <cstdlib>
-
#include "fud_array.hpp"
+#include "fud_result.hpp"
+#include "fud_status.hpp"
+
+#include <cstddef>
+#include <cstdint>
namespace fud {
-template <typename T, size_t Size>
+template <typename T, size_t Size = SIZE_MAX>
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();
+ static Span make(Array<T, Size>& array)
+ {
+ Span<T, Size> output{array.data(), Size};
return output;
}
+ static Result<Span, FudStatus> make(Array<T, Size>& array, size_t size)
+ {
+ if (size > Size) {
+ return FudStatus::ArgumentInvalid;
+ }
+ return Span<T, Size>{array.data(), Size};
+ }
+
template <typename U>
- static Span make(const Array<U, Size>& array) {
+ 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;
+ return Span<T, Size>{array.data(), Size};
}
template <typename U>
- static Span make(Array<U, Size>& array) {
+ static Result<Span, FudStatus> make(const Array<U, Size>& array, size_t size)
+ {
static_assert(std::convertible_to<U, T>);
- Span<T, Size> output{};
- output.m_data = array.data();
- return output;
+ if (size > Size) {
+ return FudStatus::ArgumentInvalid;
+ }
+ return Span<T, Size>{array.data(), Size};
+ }
+
+ template <typename U>
+ static Span make(Array<U, Size>& array)
+ {
+ static_assert(std::convertible_to<U, T>);
+ return Span<T, Size>{array.data(), array.size()};
+ }
+
+ template <typename U>
+ static Result<Span, FudStatus> make(Array<U, Size>& array, size_t size)
+ {
+ static_assert(std::convertible_to<U, T>);
+ if (size > Size) {
+ return FudStatus::ArgumentInvalid;
+ }
+ return Span<T, Size>{array.data(), array.size()};
}
template <size_t ArraySize>
- static Span makeCStringBuffer(Array<T, ArraySize>& array) {
+ static Span makeCStringBuffer(Array<T, ArraySize>& array)
+ {
static_assert(ArraySize > Size);
Span<T, Size> output{};
output.m_data = array.data();
@@ -60,10 +90,15 @@ struct Span {
}
T* m_data;
+ const size_t m_size;
[[nodiscard]] constexpr size_t size() const
{
- return Size;
+ if constexpr (Size < SIZE_MAX) {
+ return Size;
+ } else {
+ return m_size;
+ }
}
constexpr T& front()
@@ -78,12 +113,12 @@ struct Span {
constexpr T& back()
{
- return m_data[Size - 1];
+ return m_data[size() - 1];
}
constexpr const T& back() const
{
- return m_data[Size - 1];
+ return m_data[size() - 1];
}
constexpr T* data() noexcept
@@ -108,12 +143,12 @@ struct Span {
constexpr T* end() noexcept
{
- return m_data + Size;
+ return m_data + size();
}
constexpr const T* end() const noexcept
{
- return m_data + Size;
+ return m_data + size();
}
constexpr T& operator[](size_t index)
diff --git a/include/fud_status.hpp b/include/fud_status.hpp
index bda646b..91048ac 100644
--- a/include/fud_status.hpp
+++ b/include/fud_status.hpp
@@ -40,6 +40,7 @@ enum class [[nodiscard]] FudStatus
RangeError,
VariantInvalid,
BadArrayLength,
+ FormatInvalid,
NotImplemented,
NotSupported
};
@@ -83,6 +84,8 @@ constexpr const char* FudStatusToString(FudStatus status)
return "VariantInvalid";
case FudStatus::BadArrayLength:
return "BadArrayLength";
+ case FudStatus::FormatInvalid:
+ return "FormatInvalid";
case FudStatus::NotImplemented:
return "NotImplemented";
case FudStatus::NotSupported:
diff --git a/include/fud_string.hpp b/include/fud_string.hpp
index ba05450..60a328f 100644
--- a/include/fud_string.hpp
+++ b/include/fud_string.hpp
@@ -23,6 +23,7 @@
#include "fud_result.hpp"
#include "fud_status.hpp"
#include "fud_string_view.hpp"
+#include "fud_c_string.hpp"
#include "fud_utf8.hpp"
#include <climits>
diff --git a/include/fud_string_view.hpp b/include/fud_string_view.hpp
index 7b4925e..8a47ae5 100644
--- a/include/fud_string_view.hpp
+++ b/include/fud_string_view.hpp
@@ -71,6 +71,14 @@ struct StringView {
Result<size_t, FudStatus> trimWhitespace();
+ [[nodiscard]] bool advance();
+
+ void advanceUnsafe();
+
+ [[nodiscard]] bool advance(size_t size);
+
+ void advanceUnsafe(size_t size);
+
FudStatus toUint8(uint8_t& number, uint8_t specifiedRadix, size_t& strLen) const;
FudStatus toUint16(uint16_t& number, uint8_t specifiedRadix, size_t& strLen) const;
@@ -96,12 +104,6 @@ struct StringView {
const utf8* m_data{nullptr};
};
-FudStatus skipWhitespace(StringView& view, size_t& skipIndex);
-
-ssize_t cStringLength(const char* str);
-
-ssize_t cStringLength(const char* str, size_t maxLength);
-
} // namespace fud
#endif
diff --git a/include/fud_utf8.hpp b/include/fud_utf8.hpp
index 539e0f4..3b1a6b7 100644
--- a/include/fud_utf8.hpp
+++ b/include/fud_utf8.hpp
@@ -19,8 +19,8 @@
#define FUD_UTF8_HPP
#include "fud_array.hpp"
-#include "fud_status.hpp"
#include "fud_unique_array.hpp"
+#include "fud_c_string.hpp"
#include <cstdint>
#include <optional>
@@ -28,6 +28,8 @@
namespace fud {
+
+
using utf8 = unsigned char;
class String;
@@ -110,6 +112,18 @@ struct Utf82Byte {
constexpr Utf82Byte(utf8 first, utf8 second) noexcept : characters{{first, second}}
{
}
+
+ __attribute__((nonnull))
+ constexpr Utf82Byte(const char* letterStr) noexcept : characters{}
+ {
+ auto length = cStringLength(letterStr, 2);
+ if (length < 2) {
+ return;
+ }
+ characters[0] = static_cast<utf8>(letterStr[0]);
+ characters[1] = static_cast<utf8>(letterStr[1]);
+ }
+
Array<utf8, 2> characters;
static constexpr size_t size() noexcept
{
@@ -145,6 +159,18 @@ struct Utf83Byte {
{
}
+ __attribute__((nonnull))
+ constexpr Utf83Byte(const char* letterStr) noexcept : characters{}
+ {
+ auto length = cStringLength(letterStr, 3);
+ if (length < 3) {
+ return;
+ }
+ characters[0] = static_cast<utf8>(letterStr[0]);
+ characters[1] = static_cast<utf8>(letterStr[1]);
+ characters[2] = static_cast<utf8>(letterStr[2]);
+ }
+
Array<utf8, 3> characters;
static constexpr size_t size() noexcept
@@ -187,6 +213,19 @@ struct Utf84Byte {
{
}
+ __attribute__((nonnull))
+ constexpr Utf84Byte(const char* letterStr) noexcept : characters{}
+ {
+ auto length = cStringLength(letterStr, 4);
+ if (length < 4) {
+ return;
+ }
+ characters[0] = static_cast<utf8>(letterStr[0]);
+ characters[1] = static_cast<utf8>(letterStr[1]);
+ characters[2] = static_cast<utf8>(letterStr[2]);
+ characters[3] = static_cast<utf8>(letterStr[3]);
+ }
+
Array<utf8, 4> characters;
static constexpr size_t size() noexcept
@@ -250,11 +289,12 @@ struct FudUtf8 {
Utf8Variant m_variant{Utf8Variant{Ascii{}}};
static constexpr Ascii invalidAsciiCode{Ascii{0xFF}};
- static FudUtf8 fromString(const String& fudString, size_t index) noexcept;
- static FudUtf8 fromStringView(StringView view, size_t index) noexcept;
- // static FudUtf8 fromStringView(const StringView& view, size_t index) noexcept;
- static constexpr FudUtf8 makeUtf8(const Array<utf8, 4>& data)
+ static FudUtf8 from(const String& fudString, size_t index) noexcept;
+
+ static FudUtf8 from(StringView view, size_t index) noexcept;
+
+ static constexpr FudUtf8 make(const Array<utf8, 4>& data)
{
FudUtf8 unicode{};
if (Ascii::valid(data[0])) {
@@ -271,7 +311,12 @@ struct FudUtf8 {
return unicode;
}
- static constexpr FudUtf8 makeUtf8(const Ascii& utf8Char)
+ static constexpr FudUtf8 make(utf8 utf8Char)
+ {
+ return make(Ascii{utf8Char});
+ }
+
+ static constexpr FudUtf8 make(Ascii utf8Char)
{
FudUtf8 unicode{{Utf8Variant{Ascii{}}}};
if (utf8Char.valid()) {
@@ -282,6 +327,15 @@ struct FudUtf8 {
return unicode;
}
+ static constexpr FudUtf8 make(Utf8Variant utf8Variant) {
+ FudUtf8 unicode{};
+ unicode.m_variant = utf8Variant;
+ if (!std::visit([](auto arg) { return arg.valid(); }, utf8Variant)) {
+ unicode.m_variant = invalidAsciiCode;
+ }
+ return unicode;
+ }
+
static constexpr FudUtf8 invalidAscii()
{
FudUtf8 character{};
@@ -460,89 +514,93 @@ struct FudUtf8 {
};
/** \brief Checks if a character is ascii. */
-bool char_is_ascii(char character);
+[[nodiscard]] bool charIsAscii(char character);
-FudStatus utf8_is_ascii(FudUtf8& character, bool& isAscii);
+[[nodiscard]] bool utf8IsAscii(FudUtf8 character);
/** \brief Checks if a character is alphanumeric. */
-bool char_is_alphanumeric(char character);
+[[nodiscard]] bool charIsAlphanumeric(char character);
/** \brief Checks if a character is alphanumeric. */
-FudStatus utf8_is_alphanumeric(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsAlphanumeric(FudUtf8 character);
/** \brief Checks if a character is alphabetic. */
-bool char_is_alpha(char character);
+[[nodiscard]] bool charIsAlpha(char character);
/** \brief Checks if a character is alphabetic. */
-FudStatus utf8_is_alpha(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsAlpha(FudUtf8 character);
/** \brief Checks if a character is lowercase. */
-bool char_is_lowercase(char character);
+[[nodiscard]] bool charIsLowercase(char character);
/** \brief Checks if a character is lowercase. */
-FudStatus utf8_is_lowercase(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsLowercase(FudUtf8 character);
/** \brief Checks if a character is an uppercase character. */
-bool char_is_uppercase(char character);
+[[nodiscard]] bool charIsUppercase(char character);
/** \brief Checks if a character is uppercase. */
-FudStatus utf8_is_uppercase(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsUppercase(FudUtf8 character);
/** \brief Checks if a character is a digit. */
-bool char_is_digit(char character);
+[[nodiscard]] bool charIsDigit(char character);
/** \brief Checks if a character is a digit. */
-FudStatus utf8_is_digit(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsDigit(FudUtf8 character);
/** \brief Checks if a character is a hexadecimal character. */
-bool char_is_hex_digit(char character);
+[[nodiscard]] bool charIsHexDigit(char character);
/** \brief Checks if a character is a hexadecimal digit. */
-FudStatus utf8_is_hex_digit(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsHexDigit(FudUtf8 character);
/** \brief Checks if a character is a control character. */
-bool char_is_control(char character);
+[[nodiscard]] bool charIsControl(char character);
/** \brief Checks if a character is a control character. */
-FudStatus utf8_is_control(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsControl(FudUtf8 character);
/** \brief Checks if a character is a graphical character. */
-bool char_is_graphical(char character);
+[[nodiscard]] bool charIsGraphical(char character);
/** \brief Checks if a character is a graphical character. */
-FudStatus utf8_is_graphical(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsGraphical(FudUtf8 character);
/** \brief Checks if a character is a space character. */
-bool char_is_space(char character);
+[[nodiscard]] bool charIsSpace(char character);
/** \brief Checks if a character is a space character. */
-FudStatus utf8_is_space(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsSpace(FudUtf8 character);
/** \brief Checks if a character is a blank character. */
-bool char_is_blank(char character);
+[[nodiscard]] bool charIsBlank(char character);
/** \brief Checks if a character is a blank character. */
-FudStatus utf8_is_blank(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsBlank(FudUtf8 character);
/** \brief Checks if a character is a printable character. */
-bool char_is_printable(char character);
+[[nodiscard]] bool charIsPrintable(char character);
/** \brief Checks if a character is a printable character. */
-FudStatus utf8_is_printable(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsPrintable(FudUtf8 character);
/** \brief Checks if a character is a punctuation character. */
-bool char_is_punctuation(char character);
+[[nodiscard]] bool charIsPunctuation(char character);
/** \brief Checks if a character is a punctuation character. */
-FudStatus utf8_is_punctuation(FudUtf8* character, bool* pred);
+[[nodiscard]] bool utf8IsPunctuation(FudUtf8 character);
-uint8_t char_to_lower(uint8_t character);
+/** \brief Converts character to lowercase if valid. */
+uint8_t charToLower(uint8_t character);
-FudUtf8* utf8_to_lower(FudUtf8* character);
+/** \brief Converts character to lowercase if valid. */
+FudUtf8 utf8ToLower(FudUtf8 character);
-uint8_t char_to_upper(uint8_t character);
+/** \brief Converts character to uppercase if valid. */
+uint8_t charToUpper(uint8_t character);
-FudUtf8* utf8_to_upper(FudUtf8* character);
+/** \brief Converts character to uppercase if valid. */
+FudUtf8 utf8ToUpper(FudUtf8 character);
} // namespace fud
diff --git a/include/fud_vector.hpp b/include/fud_vector.hpp
new file mode 100644
index 0000000..56e1659
--- /dev/null
+++ b/include/fud_vector.hpp
@@ -0,0 +1,64 @@
+/*
+ * 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_VECTOR_HPP
+#define FUD_VECTOR_HPP
+
+#include "fud_allocator.hpp"
+#include "fud_result.hpp"
+#include "fud_status.hpp"
+
+#include <cstddef>
+
+namespace fud {
+
+template <typename T>
+class Vector {
+ public:
+ static Result<Vector<T>, FudStatus> from(const Vector<T>& rhs);
+
+ static Vector<T> move(Vector<T>&& rhs);
+
+ FudStatus copy(const Vector<T>& rhs);
+
+ FudStatus take(Vector<T>&& rhs);
+
+ [[nodiscard]] size_t size() const {
+ return m_length;
+ }
+
+ [[nodiscard]] size_t capacity() const {
+ return m_capacity;
+ }
+
+ FudStatus reserve();
+
+ FudStatus resize();
+
+ FudStatus clear();
+
+ // FudResult at();
+
+ private:
+ Allocator* m_allocator{&globalFudAllocator};
+ size_t m_length{0};
+ size_t m_capacity{0};
+};
+
+} // namespace fud
+
+#endif