Simplify integer spec checking
This commit is contained in:
parent
8f9db3fcb8
commit
bac14ef985
@ -1425,45 +1425,6 @@ int snprintf_float(T value, int precision, float_specs specs,
|
|||||||
template <typename T> T promote_float(T value) { return value; }
|
template <typename T> T promote_float(T value) { return value; }
|
||||||
inline double promote_float(float value) { return static_cast<double>(value); }
|
inline double promote_float(float value) { return static_cast<double>(value); }
|
||||||
|
|
||||||
template <typename Handler>
|
|
||||||
FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) {
|
|
||||||
switch (spec) {
|
|
||||||
case 0:
|
|
||||||
case 'd':
|
|
||||||
handler.on_dec();
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
case 'X':
|
|
||||||
handler.on_hex();
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
case 'B':
|
|
||||||
handler.on_bin();
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
handler.on_oct();
|
|
||||||
break;
|
|
||||||
#ifdef FMT_DEPRECATED_N_SPECIFIER
|
|
||||||
case 'n':
|
|
||||||
handler.on_num();
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case 'c':
|
|
||||||
handler.on_chr();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
handler.on_error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Char, typename Handler>
|
|
||||||
FMT_CONSTEXPR void handle_bool_type_spec(const basic_format_specs<Char>* specs,
|
|
||||||
Handler&& handler) {
|
|
||||||
if (!specs) return handler.on_str();
|
|
||||||
if (specs->type && specs->type != 's') return handler.on_int();
|
|
||||||
handler.on_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ErrorHandler = error_handler, typename Char>
|
template <typename ErrorHandler = error_handler, typename Char>
|
||||||
FMT_CONSTEXPR float_specs parse_float_type_spec(
|
FMT_CONSTEXPR float_specs parse_float_type_spec(
|
||||||
const basic_format_specs<Char>& specs, ErrorHandler&& eh = {}) {
|
const basic_format_specs<Char>& specs, ErrorHandler&& eh = {}) {
|
||||||
@ -1512,6 +1473,27 @@ FMT_CONSTEXPR float_specs parse_float_type_spec(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ErrorHandler>
|
||||||
|
FMT_CONSTEXPR void check_int_type_spec(char spec, ErrorHandler&& eh) {
|
||||||
|
switch (spec) {
|
||||||
|
case 0:
|
||||||
|
case 'd':
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
case 'b':
|
||||||
|
case 'B':
|
||||||
|
case 'o':
|
||||||
|
#ifdef FMT_DEPRECATED_N_SPECIFIER
|
||||||
|
case 'n':
|
||||||
|
#endif
|
||||||
|
case 'c':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
eh.on_error("invalid type specifier");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Char, typename Handler>
|
template <typename Char, typename Handler>
|
||||||
FMT_CONSTEXPR void handle_char_specs(const basic_format_specs<Char>* specs,
|
FMT_CONSTEXPR void handle_char_specs(const basic_format_specs<Char>* specs,
|
||||||
Handler&& handler) {
|
Handler&& handler) {
|
||||||
@ -1542,22 +1524,6 @@ FMT_CONSTEXPR void check_pointer_type_spec(Char spec, ErrorHandler&& eh) {
|
|||||||
if (spec != 0 && spec != 'p') eh.on_error("invalid type specifier");
|
if (spec != 0 && spec != 'p') eh.on_error("invalid type specifier");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ErrorHandler> class int_type_checker : private ErrorHandler {
|
|
||||||
public:
|
|
||||||
FMT_CONSTEXPR explicit int_type_checker(ErrorHandler eh) : ErrorHandler(eh) {}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_dec() {}
|
|
||||||
FMT_CONSTEXPR void on_hex() {}
|
|
||||||
FMT_CONSTEXPR void on_bin() {}
|
|
||||||
FMT_CONSTEXPR void on_oct() {}
|
|
||||||
FMT_CONSTEXPR void on_num() {}
|
|
||||||
FMT_CONSTEXPR void on_chr() {}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_error() {
|
|
||||||
ErrorHandler::on_error("invalid type specifier");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ErrorHandler>
|
template <typename ErrorHandler>
|
||||||
class char_specs_checker : public ErrorHandler {
|
class char_specs_checker : public ErrorHandler {
|
||||||
private:
|
private:
|
||||||
@ -1567,9 +1533,7 @@ class char_specs_checker : public ErrorHandler {
|
|||||||
FMT_CONSTEXPR char_specs_checker(char type, ErrorHandler eh)
|
FMT_CONSTEXPR char_specs_checker(char type, ErrorHandler eh)
|
||||||
: ErrorHandler(eh), type_(type) {}
|
: ErrorHandler(eh), type_(type) {}
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_int() {
|
FMT_CONSTEXPR void on_int() { check_int_type_spec(type_, *this); }
|
||||||
handle_int_type_spec(type_, int_type_checker<ErrorHandler>(*this));
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR void on_char() {}
|
FMT_CONSTEXPR void on_char() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1583,21 +1547,6 @@ class cstring_type_checker : public ErrorHandler {
|
|||||||
FMT_CONSTEXPR void on_pointer() {}
|
FMT_CONSTEXPR void on_pointer() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ErrorHandler>
|
|
||||||
class bool_type_checker : private ErrorHandler {
|
|
||||||
private:
|
|
||||||
char type_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
FMT_CONSTEXPR explicit bool_type_checker(char type, ErrorHandler eh)
|
|
||||||
: ErrorHandler(eh), type_(type) {}
|
|
||||||
|
|
||||||
FMT_CONSTEXPR void on_int() {
|
|
||||||
handle_int_type_spec(type_, int_type_checker<ErrorHandler>(*this));
|
|
||||||
}
|
|
||||||
FMT_CONSTEXPR void on_str() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename OutputIt, typename Char>
|
template <typename OutputIt, typename Char>
|
||||||
FMT_NOINLINE FMT_CONSTEXPR OutputIt fill(OutputIt it, size_t n,
|
FMT_NOINLINE FMT_CONSTEXPR OutputIt fill(OutputIt it, size_t n,
|
||||||
const fill_t<Char>& fill) {
|
const fill_t<Char>& fill) {
|
||||||
@ -1708,25 +1657,15 @@ write_int(OutputIt out, int num_digits, unsigned prefix,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutputIt, typename UInt, typename Char>
|
template <typename OutputIt, typename UInt, typename Char>
|
||||||
FMT_CONSTEXPR OutputIt write_dec(OutputIt out, UInt value, unsigned prefix,
|
bool write_int_localized(OutputIt& out, UInt value, unsigned prefix,
|
||||||
const basic_format_specs<Char>& specs) {
|
|
||||||
auto num_digits = count_digits(value);
|
|
||||||
return write_int(out, num_digits, prefix, specs,
|
|
||||||
[=](reserve_iterator<OutputIt> it) {
|
|
||||||
return format_decimal<Char>(it, value, num_digits).end;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename OutputIt, typename UInt, typename Char>
|
|
||||||
OutputIt write_int_localized(OutputIt out, UInt value, unsigned prefix,
|
|
||||||
const basic_format_specs<Char>& specs,
|
const basic_format_specs<Char>& specs,
|
||||||
locale_ref loc) {
|
locale_ref loc) {
|
||||||
static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, "");
|
static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, "");
|
||||||
const auto sep_size = 1;
|
const auto sep_size = 1;
|
||||||
std::string groups = grouping<Char>(loc);
|
std::string groups = grouping<Char>(loc);
|
||||||
if (groups.empty()) return write_dec(out, value, prefix, specs);
|
if (groups.empty()) return false;
|
||||||
auto sep = thousands_sep<Char>(loc);
|
auto sep = thousands_sep<Char>(loc);
|
||||||
if (!sep) return write_dec(out, value, prefix, specs);
|
if (!sep) return false;
|
||||||
int num_digits = count_digits(value);
|
int num_digits = count_digits(value);
|
||||||
int size = num_digits, n = num_digits;
|
int size = num_digits, n = num_digits;
|
||||||
std::string::const_iterator group = groups.cbegin();
|
std::string::const_iterator group = groups.cbegin();
|
||||||
@ -1764,10 +1703,11 @@ OutputIt write_int_localized(OutputIt out, UInt value, unsigned prefix,
|
|||||||
*p-- = static_cast<Char>(*digits);
|
*p-- = static_cast<Char>(*digits);
|
||||||
if (prefix != 0) *p = static_cast<Char>(prefix);
|
if (prefix != 0) *p = static_cast<Char>(prefix);
|
||||||
auto data = buffer.data();
|
auto data = buffer.data();
|
||||||
return write_padded<align::right>(
|
out = write_padded<align::right>(
|
||||||
out, specs, usize, usize, [=](reserve_iterator<OutputIt> it) {
|
out, specs, usize, usize, [=](reserve_iterator<OutputIt> it) {
|
||||||
return copy_str<Char>(data, data + size, it);
|
return copy_str<Char>(data, data + size, it);
|
||||||
});
|
});
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) {
|
FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) {
|
||||||
@ -1790,12 +1730,18 @@ FMT_CONSTEXPR OutputIt write_int(OutputIt out, T value,
|
|||||||
auto utype = static_cast<unsigned>(specs.type);
|
auto utype = static_cast<unsigned>(specs.type);
|
||||||
switch (specs.type) {
|
switch (specs.type) {
|
||||||
case 0:
|
case 0:
|
||||||
case 'd':
|
case 'd': {
|
||||||
return specs.localized
|
if (specs.localized &&
|
||||||
? write_int_localized(out,
|
write_int_localized(out, static_cast<uint64_or_128_t<T>>(abs_value),
|
||||||
static_cast<uint64_or_128_t<T>>(abs_value),
|
prefix, specs, loc)) {
|
||||||
prefix, specs, loc)
|
return out;
|
||||||
: write_dec(out, abs_value, prefix, specs);
|
}
|
||||||
|
auto num_digits = count_digits(abs_value);
|
||||||
|
return write_int(
|
||||||
|
out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
|
||||||
|
return format_decimal<Char>(it, abs_value, num_digits).end;
|
||||||
|
});
|
||||||
|
}
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X': {
|
case 'X': {
|
||||||
if (specs.alt) prefix_append(prefix, (utype << 8) | '0');
|
if (specs.alt) prefix_append(prefix, (utype << 8) | '0');
|
||||||
@ -3537,18 +3483,16 @@ struct formatter<T, Char,
|
|||||||
case detail::type::none_type:
|
case detail::type::none_type:
|
||||||
FMT_ASSERT(false, "invalid argument type");
|
FMT_ASSERT(false, "invalid argument type");
|
||||||
break;
|
break;
|
||||||
|
case detail::type::bool_type:
|
||||||
|
if (!specs_.type || specs_.type == 's') break;
|
||||||
|
FMT_FALLTHROUGH;
|
||||||
case detail::type::int_type:
|
case detail::type::int_type:
|
||||||
case detail::type::uint_type:
|
case detail::type::uint_type:
|
||||||
case detail::type::long_long_type:
|
case detail::type::long_long_type:
|
||||||
case detail::type::ulong_long_type:
|
case detail::type::ulong_long_type:
|
||||||
case detail::type::int128_type:
|
case detail::type::int128_type:
|
||||||
case detail::type::uint128_type:
|
case detail::type::uint128_type:
|
||||||
handle_int_type_spec(specs_.type,
|
detail::check_int_type_spec(specs_.type, eh);
|
||||||
detail::int_type_checker<decltype(eh)>(eh));
|
|
||||||
break;
|
|
||||||
case detail::type::bool_type:
|
|
||||||
handle_bool_type_spec(
|
|
||||||
&specs_, detail::bool_type_checker<decltype(eh)>(specs_.type, eh));
|
|
||||||
break;
|
break;
|
||||||
case detail::type::char_type:
|
case detail::type::char_type:
|
||||||
handle_char_specs(
|
handle_char_specs(
|
||||||
|
Loading…
Reference in New Issue
Block a user