diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/fud_algorithm.hpp | 162 | ||||
-rw-r--r-- | include/fud_array.hpp | 4 | ||||
-rw-r--r-- | include/fud_c_string.hpp | 55 | ||||
-rw-r--r-- | include/fud_format.hpp | 362 | ||||
-rw-r--r-- | include/fud_result.hpp | 35 | ||||
-rw-r--r-- | include/fud_span.hpp | 75 | ||||
-rw-r--r-- | include/fud_status.hpp | 3 | ||||
-rw-r--r-- | include/fud_string.hpp | 1 | ||||
-rw-r--r-- | include/fud_string_view.hpp | 14 | ||||
-rw-r--r-- | include/fud_utf8.hpp | 130 | ||||
-rw-r--r-- | include/fud_vector.hpp | 64 |
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 |