From 6a27a2a4032e88fa9154ef0f0741edc584f7a701 Mon Sep 17 00:00:00 2001 From: Dominick Allen Date: Sun, 20 Oct 2024 10:48:19 -0500 Subject: Lots of work. --- include/fud_format.hpp | 362 ++++++++++++++++++------------------------------- 1 file changed, 133 insertions(+), 229 deletions(-) (limited to 'include/fud_format.hpp') 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 // for std::format_string #include #include +#include namespace fud { -template -using CharSpan = Span; - -template -using FormatLiteral = std::format_string; +struct FormatAlign +{ + enum class Value : uint8_t + { + Left, + Right, + Center + }; + + constexpr static std::optional 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 -Result format(CharSpan buffer, FormatLiteral 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, FudStatus> parse(StringView formatView) { + // "{:A, 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 fill; - std::optional formatSign; - uint32_t minWidth; +enum class FormatStringType : uint8_t +{ + String, + Escaped, }; -namespace detail { - -template -Result formatHelper( - CharSpan buffer, - size_t formattedSize, - StringView formatView, - Arg&& arg, - Args&&... args); - -template -Result formatHelper( - CharSpan buffer, - size_t formattedSize, - StringView formatView, - Arg&& arg); - -template -Result formatHelper( - CharSpan buffer, - size_t formattedSize, - StringView formatView); - -} // namespace detail - -template -Result format(CharSpan buffer, FormatLiteral 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(argCount); - - size_t formattedSize = 0; + BinaryLower, + BinaryUpper, + Character, + Decimal, + Octal, + HexLower, + HexUpper, +}; - return detail::formatHelper(buffer, formattedSize, formatView, std::forward(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 copyRemaining( - CharSpan 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 -Result handleSpec( - CharSpan 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; - static_cast(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 -Result formatHelper( - CharSpan 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), 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)...); - } - } + bool hasWidth; + bool takesWidth; - return formattedSize; -} + bool hasPrecision; + bool takesPrecision; -template -Result formatHelper( - CharSpan 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), consumed); - formattedSize = M_TakeOrReturn(specResult); - if (consumed) { - return formatHelper(buffer, formattedSize, formatView); - } - } - return formattedSize; -} - -template -Result formatHelper( - CharSpan 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 make(StringView& formatView, size_t specIndex); +}; } // namespace fud -- cgit v1.2.3