Refactor format string checks

This commit is contained in:
Victor Zverovich
2022-12-30 16:03:41 -08:00
parent 72785a3aba
commit a73a9b6a84
5 changed files with 125 additions and 221 deletions
+63 -5
View File
@@ -2249,14 +2249,13 @@ FMT_CONSTEXPR auto write(OutputIt out,
basic_string_view<type_identity_t<Char>> s,
const format_specs<Char>& specs, locale_ref)
-> OutputIt {
check_string_type_spec(specs.type);
return write(out, s, specs);
}
template <typename Char, typename OutputIt>
FMT_CONSTEXPR auto write(OutputIt out, const Char* s,
const format_specs<Char>& specs, locale_ref)
-> OutputIt {
return check_cstring_type_spec(specs.type)
return specs.type != presentation_type::pointer
? write(out, basic_string_view<Char>(s), specs, {})
: write_ptr<Char>(out, bit_cast<uintptr_t>(s), &specs);
}
@@ -2283,6 +2282,68 @@ FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
return base_iterator(out, it);
}
// A floating-point presentation format.
enum class float_format : unsigned char {
general, // General: exponent notation or fixed point based on magnitude.
exp, // Exponent notation with the default precision of 6, e.g. 1.2e-3.
fixed, // Fixed point with the default precision of 6, e.g. 0.0012.
hex
};
struct float_specs {
int precision;
float_format format : 8;
sign_t sign : 8;
bool upper : 1;
bool locale : 1;
bool binary32 : 1;
bool showpoint : 1;
};
template <typename ErrorHandler = error_handler, typename Char>
FMT_CONSTEXPR auto parse_float_type_spec(const format_specs<Char>& specs,
ErrorHandler&& eh = {})
-> float_specs {
auto result = float_specs();
result.showpoint = specs.alt;
result.locale = specs.localized;
switch (specs.type) {
case presentation_type::none:
result.format = float_format::general;
break;
case presentation_type::general_upper:
result.upper = true;
FMT_FALLTHROUGH;
case presentation_type::general_lower:
result.format = float_format::general;
break;
case presentation_type::exp_upper:
result.upper = true;
FMT_FALLTHROUGH;
case presentation_type::exp_lower:
result.format = float_format::exp;
result.showpoint |= specs.precision != 0;
break;
case presentation_type::fixed_upper:
result.upper = true;
FMT_FALLTHROUGH;
case presentation_type::fixed_lower:
result.format = float_format::fixed;
result.showpoint |= specs.precision != 0;
break;
case presentation_type::hexfloat_upper:
result.upper = true;
FMT_FALLTHROUGH;
case presentation_type::hexfloat_lower:
result.format = float_format::hex;
break;
default:
eh.on_error("invalid format specifier");
break;
}
return result;
}
template <typename Char, typename OutputIt>
FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan,
format_specs<Char> specs,
@@ -3465,7 +3526,6 @@ template <typename Char, typename OutputIt, typename T,
FMT_ENABLE_IF(std::is_same<T, void>::value)>
auto write(OutputIt out, const T* value, const format_specs<Char>& specs = {},
locale_ref = {}) -> OutputIt {
check_pointer_type_spec(specs.type, error_handler());
return write_ptr<Char>(out, bit_cast<uintptr_t>(value), &specs);
}
@@ -3891,7 +3951,6 @@ template <> struct formatter<bytes> {
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
auto end = parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
detail::type::string_type);
detail::check_string_type_spec(specs_.type, detail::error_handler());
return end;
}
@@ -3932,7 +3991,6 @@ template <typename T> struct formatter<group_digits_view<T>> : formatter<T> {
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
auto end = parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
detail::type::int_type);
detail::check_string_type_spec(specs_.type, detail::error_handler());
return end;
}