diff options
Diffstat (limited to 'include/fud_format.hpp')
-rw-r--r-- | include/fud_format.hpp | 131 |
1 files changed, 93 insertions, 38 deletions
diff --git a/include/fud_format.hpp b/include/fud_format.hpp index ea32bd8..2576eca 100644 --- a/include/fud_format.hpp +++ b/include/fud_format.hpp @@ -22,24 +22,30 @@ #include "fud_result.hpp" #include "fud_status.hpp" #include "fud_string_view.hpp" +#include "fud_option.hpp" #include "fud_utf8.hpp" #include <cstdint> -#include <optional> #include <variant> +#include <limits> namespace fud { struct FormatAlign { - enum class Value : uint8_t + enum class Value : utf8 { - Left, - Right, - Center + Left = '<', + Right = '>', + Center = '^', + Default = std::numeric_limits<utf8>::max() }; - constexpr static std::optional<FormatAlign> from(utf8 letter) + constexpr static FormatAlign makeDefault() noexcept { + return {Value::Default}; + } + + constexpr static Option<FormatAlign> from(utf8 letter) { FormatAlign formatAlign; switch (letter) { @@ -53,12 +59,16 @@ struct FormatAlign formatAlign.value = Value::Center; break; default: - return std::nullopt; + return NullOpt; } return formatAlign; } + Value operator()() const { + return value; + } + Value value; }; @@ -66,37 +76,50 @@ struct FormatFill { FormatAlign align; 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); + constexpr static FormatFill make() noexcept { + return FormatFill {FormatAlign::makeDefault(), ' '}; + } + + constexpr static Result<Option<FormatFill>, FudStatus> make(StringView formatView, size_t& length) noexcept { + using RetType = Result<Option<FormatFill>, FudStatus>; + if (formatView.length() < 1) { + return RetType::okay(NullOpt); } const auto* data = formatView.data(); - if (data[0] != 'A') { - return RetType::okay(std::nullopt); + auto align1 = FormatAlign::from(data[0]); + decltype(align1) align2 = NullOpt; + if (formatView.length() > 1) { + align2 = FormatAlign::from(data[1]); } - auto align = FormatAlign::from(data[1]); - if (!align.has_value()) { - return FudStatus::FormatInvalid; + if (align2.hasValue()) { + length = 2; + auto fill = data[0]; + if (not Ascii::valid(fill)) { + return FudStatus::Utf8Invalid; + } + if (fill == '{' || fill == '}') { + return FudStatus::FormatInvalid; + } + return RetType::okay(FormatFill{std::move(align2).value(), data[0]}); } - auto fill = data[2]; - if (!Ascii::valid(fill)) { - return FudStatus::Utf8Invalid; + if (align1.hasValue()) { + length = 1; + return RetType::okay(FormatFill{std::move(align1).value(), ' '}); } - return RetType::okay(FormatFill{*align, fill}); + return RetType::okay(NullOpt); } }; enum class FormatSign : uint8_t { - Plus, - Minus, - Space + Plus = '+', + Minus = '-', + Space = ' ', + Default = std::numeric_limits<utf8>::max() }; enum class FormatStringType : uint8_t @@ -155,6 +178,7 @@ enum class FormatPointerType : uint8_t HexUpper }; +/* using FormatType = std::variant< // break std::monostate, FormatStringType, @@ -163,33 +187,64 @@ using FormatType = std::variant< // break FormatBoolType, FormatFloatingType, FormatPointerType>; +*/ + +enum class FormatType : utf8 { + Unspecified = '\0', + String = 's', + Escaped = '?', + BinaryLower = 'b', + BinaryUpper = 'B', + Character = 'c', + Decimal = 'd', + Octal = 'o', + HexLower = 'x', + HexUpper = 'X', + FloatHexLower = 'a', + FloatHexUpper = 'A', + ScientificLower = 'e', + ScientificUpper = 'E', + FixedLower = 'f', + FixedUpper = 'F', + GeneralLower = 'g', + GeneralUpper = 'G', +}; struct FormatSpec; using FormatSpecResult = Result<FormatSpec, FudStatus>; struct FormatSpec { - size_t width; - size_t precision; - FormatFill fill; - FormatSign formatSign; + static constexpr uint32_t widthUnspecified = std::numeric_limits<uint32_t>::max(); + static constexpr uint32_t precisionUnspecified = std::numeric_limits<uint32_t>::max(); + static constexpr uint16_t positionUnspecified = std::numeric_limits<uint16_t>::max(); + static constexpr utf8 openBracket = '{'; + static constexpr utf8 closeBracket = '}'; + static constexpr utf8 formatTypeUnspecified = std::numeric_limits<utf8>::max(); + static constexpr utf8 localeChar = 'L'; + + uint32_t width{widthUnspecified}; + + uint32_t precision{precisionUnspecified}; + + uint16_t position{positionUnspecified}; + + FormatFill fill{FormatFill::make()}; - FormatType formatType; + FormatSign formatSign{FormatSign::Default}; - bool hasWidth; - bool takesWidth; + FormatType formatType{}; - bool hasPrecision; - bool takesPrecision; + bool takesWidth{false}; - bool hasFill; + bool takesPrecision{false}; - bool hasFormatSign; + bool alternateForm{false}; - bool alternateForm; + bool leadingZero{false}; - bool leadingZero; + bool hasLocale{false}; - static Result<FormatSpec, FudStatus> make(StringView& formatView, size_t specIndex); + static Result<FormatSpec, FudStatus> make(StringView formatView, size_t& specLength); }; } // namespace fud |