Util: Implement specifier option checks

This commit is contained in:
Riyyi
2022-08-05 23:38:08 +02:00
parent a75bb863ff
commit 80c37496e8
2 changed files with 67 additions and 36 deletions
+64 -37
View File
@@ -200,8 +200,6 @@ void Parser::parseSpecifier(Specifier& specifier, ParameterType type)
// Sign is only valid for numeric types // Sign is only valid for numeric types
if (peek0 == '+' || peek0 == '-' || peek0 == ' ') { if (peek0 == '+' || peek0 == '-' || peek0 == ' ') {
VERIFY(state < State::AfterSign, "unexpected '%c' at this position", peek0); VERIFY(state < State::AfterSign, "unexpected '%c' at this position", peek0);
VERIFY(type == ParameterType::Integral || type == ParameterType::FloatingPoint,
"sign option is only valid for numeric types");
state = State::AfterSign; state = State::AfterSign;
specifier.sign = static_cast<Builder::Sign>(peek0); specifier.sign = static_cast<Builder::Sign>(peek0);
} }
@@ -209,8 +207,6 @@ void Parser::parseSpecifier(Specifier& specifier, ParameterType type)
// Alternative form is only valid for numeric types // Alternative form is only valid for numeric types
if (peek0 == '#') { if (peek0 == '#') {
VERIFY(state < State::AfterAlternativeForm, "unexpected '#' at this position"); VERIFY(state < State::AfterAlternativeForm, "unexpected '#' at this position");
VERIFY(type == ParameterType::Integral || type == ParameterType::FloatingPoint,
"'#' option is only valid for numeric types");
state = State::AfterAlternativeForm; state = State::AfterAlternativeForm;
specifier.alternativeForm = true; specifier.alternativeForm = true;
} }
@@ -219,8 +215,6 @@ void Parser::parseSpecifier(Specifier& specifier, ParameterType type)
if (peek0 == '0') { if (peek0 == '0') {
if (state < State::AfterWidth) { if (state < State::AfterWidth) {
VERIFY(state < State::AfterZeroPadding, "unexpected '0' at this position"); VERIFY(state < State::AfterZeroPadding, "unexpected '0' at this position");
VERIFY(type == ParameterType::Integral || type == ParameterType::FloatingPoint,
"zero padding option is only valid for numeric types");
state = State::AfterZeroPadding; state = State::AfterZeroPadding;
specifier.zeroPadding = true; specifier.zeroPadding = true;
} }
@@ -290,37 +284,22 @@ constexpr void Parser::checkSpecifierIntegralType(const Specifier& specifier)
case PresentationType::None: case PresentationType::None:
case PresentationType::Binary: case PresentationType::Binary:
case PresentationType::BinaryUppercase: case PresentationType::BinaryUppercase:
case PresentationType::Character:
case PresentationType::Decimal: case PresentationType::Decimal:
case PresentationType::Octal: case PresentationType::Octal:
case PresentationType::Hex: case PresentationType::Hex:
case PresentationType::HexUppercase: case PresentationType::HexUppercase:
case PresentationType::Character:
break; break;
default: default:
VERIFY("invalid type spcifier"); VERIFY(false, "invalid type specifier");
}; };
}
constexpr void Parser::checkSpecifierPointerType(const Specifier& specifier) // Invalid: precision
{
VERIFY(specifier.type == PresentationType::None || specifier.type == PresentationType::Pointer,
"invalid type specifier");
// Valid: fill, align, width
// Invalid: sign, alternativeForm, zeroPadding, precision
VERIFY(specifier.sign == Builder::Sign::None, "invalid specifier option");
VERIFY(specifier.alternativeForm == false, "invalid specifier option");
VERIFY(specifier.zeroPadding == false, "invalid specifier option");
VERIFY(specifier.precision == -1, "invalid specifier option"); VERIFY(specifier.precision == -1, "invalid specifier option");
} }
constexpr void Parser::checkSpecifierType(const Specifier& specifier, ParameterType type) constexpr void Parser::checkSpecifierFloatingPointType(const Specifier& specifier)
{ {
switch (type) {
case ParameterType::Integral:
checkSpecifierIntegralType(specifier);
break;
case ParameterType::FloatingPoint:
switch (specifier.type) { switch (specifier.type) {
case PresentationType::Hexfloat: case PresentationType::Hexfloat:
case PresentationType::HexfloatUppercase: case PresentationType::HexfloatUppercase:
@@ -332,25 +311,73 @@ constexpr void Parser::checkSpecifierType(const Specifier& specifier, ParameterT
case PresentationType::GeneralUppercase: case PresentationType::GeneralUppercase:
break; break;
default: default:
VERIFY("invalid type spcifier"); VERIFY(false, "invalid type specifier");
} }
}
constexpr void Parser::checkSpecifierCharType(const Specifier& specifier)
{
checkSpecifierIntegralType(specifier);
// Valid: fill, align, width
// Invalid: sign, alternativeForm, zeroPadding, precision
if (specifier.type == PresentationType::None
|| specifier.type == PresentationType::Character) {
VERIFY(specifier.sign == Builder::Sign::None, "invalid specifier option");
VERIFY(specifier.alternativeForm == false, "invalid specifier option");
VERIFY(specifier.zeroPadding == false, "invalid specifier option");
}
// Precision checked in Integral
}
constexpr void Parser::checkSpecifierCStringType(const Specifier& specifier)
{
switch (specifier.type) {
case PresentationType::None:
case PresentationType::String:
case PresentationType::Pointer:
break;
default:
VERIFY(false, "invalid type specifier");
}
// Valid: fill, align, width
// Invalid: sign, alternativeForm, zeroPadding, precision
VERIFY(specifier.sign == Builder::Sign::None, "invalid specifier option");
VERIFY(specifier.alternativeForm == false, "invalid specifier option");
VERIFY(specifier.zeroPadding == false, "invalid specifier option");
VERIFY(specifier.precision == -1, "invalid specifier option");
}
constexpr void Parser::checkSpecifierStringType(const Specifier& specifier)
{
checkSpecifierCStringType(specifier);
VERIFY(specifier.type != PresentationType::Pointer, "invalid type specifier");
}
constexpr void Parser::checkSpecifierPointerType(const Specifier& specifier)
{
checkSpecifierCStringType(specifier);
VERIFY(specifier.type != PresentationType::String, "invalid type specifier");
}
constexpr void Parser::checkSpecifierType(const Specifier& specifier, ParameterType type)
{
switch (type) {
case ParameterType::Integral:
checkSpecifierIntegralType(specifier);
break;
case ParameterType::FloatingPoint:
checkSpecifierFloatingPointType(specifier);
break; break;
case ParameterType::Char: case ParameterType::Char:
if (specifier.type != PresentationType::None checkSpecifierCharType(specifier);
&& specifier.type != PresentationType::Character) {
checkSpecifierIntegralType(specifier);
}
break; break;
case ParameterType::CString: case ParameterType::CString:
VERIFY(specifier.type == PresentationType::None checkSpecifierCStringType(specifier);
|| specifier.type == PresentationType::String
|| specifier.type == PresentationType::Pointer,
"invalid type specifier");
break; break;
case ParameterType::String: case ParameterType::String:
VERIFY(specifier.type == PresentationType::None checkSpecifierStringType(specifier);
|| specifier.type == PresentationType::String,
"invalid type specifier");
break; break;
case ParameterType::Pointer: case ParameterType::Pointer:
checkSpecifierPointerType(specifier); checkSpecifierPointerType(specifier);
+4
View File
@@ -44,6 +44,10 @@ public:
void parseSpecifier(Specifier& specifier, ParameterType type); void parseSpecifier(Specifier& specifier, ParameterType type);
constexpr void checkSpecifierIntegralType(const Specifier& specifier); constexpr void checkSpecifierIntegralType(const Specifier& specifier);
constexpr void checkSpecifierFloatingPointType(const Specifier& specifier);
constexpr void checkSpecifierCharType(const Specifier& specifier);
constexpr void checkSpecifierCStringType(const Specifier& specifier);
constexpr void checkSpecifierStringType(const Specifier& specifier);
constexpr void checkSpecifierPointerType(const Specifier& specifier); constexpr void checkSpecifierPointerType(const Specifier& specifier);
constexpr void checkSpecifierType(const Specifier& specifier, ParameterType type); constexpr void checkSpecifierType(const Specifier& specifier, ParameterType type);