/* * 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_FORMAT_HPP #define FUD_FORMAT_HPP // #include "fud_assert.hpp" #include "fud_result.hpp" #include "fud_status.hpp" #include "fud_string_view.hpp" #include "fud_utf8.hpp" #include #include #include namespace fud { 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; } return formatAlign; } Value value; }; struct FormatFill { FormatAlign align; 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 { Plus, Minus, Space }; enum class FormatStringType : uint8_t { String, Escaped, }; enum class FormatIntegerType : uint8_t { BinaryLower, BinaryUpper, Character, Decimal, Octal, HexLower, HexUpper, }; enum class FormatCharacterType : uint8_t { BinaryLower, BinaryUpper, Character, Decimal, Octal, HexLower, HexUpper, }; enum class FormatBoolType : uint8_t { BinaryLower, BinaryUpper, Character, Decimal, Octal, HexLower, HexUpper, }; enum class FormatFloatingType : uint8_t { FloatHexLower, FloatHexUpper, ScientificLower, ScientificUpper, Fixed, GeneralLower, GeneralUpper }; enum class FormatPointerType : uint8_t { HexLower, HexUpper }; using FormatType = std::variant< // break std::monostate, FormatStringType, FormatIntegerType, FormatCharacterType, FormatBoolType, FormatFloatingType, FormatPointerType>; struct FormatSpec; using FormatSpecResult = Result; struct FormatSpec { size_t width; size_t precision; FormatFill fill; FormatSign formatSign; FormatType formatType; bool hasWidth; bool takesWidth; bool hasPrecision; bool takesPrecision; bool hasFill; bool hasFormatSign; bool alternateForm; bool leadingZero; static Result make(StringView& formatView, size_t specIndex); }; } // namespace fud #endif