diff --git a/src/util/format/formatter.cpp b/src/util/format/formatter.cpp index 166c74e..268e5b9 100644 --- a/src/util/format/formatter.cpp +++ b/src/util/format/formatter.cpp @@ -88,11 +88,20 @@ void Formatter::format(Builder& builder, std::string_view valu builder.putString(value, specifier.width, specifier.align, specifier.fill); } +void Formatter::parse(Parser& parser) +{ + parser.parseSpecifier(specifier, Parser::ParameterType::CString); +} + void Formatter::format(Builder& builder, const char* value) const { - Formatter::format( - builder, - value != nullptr ? std::string_view { value, strlen(value) } : "nullptr"); + if (specifier.type == PresentationType::Pointer) { + Formatter formatter { specifier }; + formatter.format(builder, static_cast(value)); + return; + } + + builder.putString(value != nullptr ? std::string_view { value, strlen(value) } : "nullptr"); } // Pointer diff --git a/src/util/format/formatter.h b/src/util/format/formatter.h index b6a84db..e7ca0f9 100644 --- a/src/util/format/formatter.h +++ b/src/util/format/formatter.h @@ -124,6 +124,7 @@ struct Formatter : Formatter { template<> struct Formatter : Formatter { + void parse(Parser& parser); void format(Builder& builder, const char* value) const; }; diff --git a/src/util/format/parser.cpp b/src/util/format/parser.cpp index 6f69482..1e1c83e 100644 --- a/src/util/format/parser.cpp +++ b/src/util/format/parser.cpp @@ -284,6 +284,73 @@ void Parser::parseSpecifier(Specifier& specifier, ParameterType type) } specifier.precision = static_cast(stringToNumber(m_input.substr(precisionBegin, precisionEnd - precisionBegin))); } + + checkSpecifierType(specifier, type); +} + +constexpr void Parser::checkSpecifierIntegralType(const Specifier& specifier) +{ + switch (specifier.type) { + case PresentationType::None: + case PresentationType::Binary: + case PresentationType::BinaryUppercase: + case PresentationType::Decimal: + case PresentationType::Octal: + case PresentationType::Hex: + case PresentationType::HexUppercase: + case PresentationType::Character: + break; + default: + VERIFY("invalid type spcifier"); + }; +} + +constexpr void Parser::checkSpecifierType(const Specifier& specifier, ParameterType type) +{ + switch (type) { + case ParameterType::Integral: + checkSpecifierIntegralType(specifier); + break; + case ParameterType::FloatingPoint: + switch (specifier.type) { + case PresentationType::Hexfloat: + case PresentationType::HexfloatUppercase: + case PresentationType::Exponent: + case PresentationType::ExponentUppercase: + case PresentationType::FixedPoint: + case PresentationType::FixedPointUppercase: + case PresentationType::General: + case PresentationType::GeneralUppercase: + break; + default: + VERIFY("invalid type spcifier"); + } + break; + case ParameterType::Char: + if (specifier.type != PresentationType::None + && specifier.type != PresentationType::Character) { + checkSpecifierIntegralType(specifier); + } + break; + case ParameterType::CString: + VERIFY(specifier.type == PresentationType::None + || specifier.type == PresentationType::String + || specifier.type == PresentationType::Pointer, + "invalid type specifier"); + break; + case ParameterType::String: + VERIFY(specifier.type == PresentationType::None + || specifier.type == PresentationType::String, + "invalid type specifier"); + break; + case ParameterType::Pointer: + VERIFY(specifier.type == PresentationType::None + || specifier.type == PresentationType::Pointer, + "invalid type specifier"); + break; + default: + VERIFY_NOT_REACHED(); + } } } // namespace Util::Format diff --git a/src/util/format/parser.h b/src/util/format/parser.h index 36bc237..8817cde 100644 --- a/src/util/format/parser.h +++ b/src/util/format/parser.h @@ -28,6 +28,7 @@ public: Integral, FloatingPoint, Char, + CString, String, Pointer, }; @@ -42,6 +43,8 @@ public: std::optional consumeIndex(); void parseSpecifier(Specifier& specifier, ParameterType type); + constexpr void checkSpecifierIntegralType(const Specifier& specifier); + constexpr void checkSpecifierType(const Specifier& specifier, ParameterType type); private: ArgumentIndexingMode m_mode { ArgumentIndexingMode::Automatic };