Add integral type handler

This commit is contained in:
Victor Zverovich 2017-11-08 05:56:52 -08:00
parent a03842b0d5
commit 92847a0d11

View File

@ -1707,6 +1707,29 @@ typedef basic_format_specs<char> format_specs;
namespace internal { namespace internal {
template <typename Handler>
void handle_integral_type_spec(char c, Handler &&handler) {
switch (c) {
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;
case 'n':
handler.on_num();
break;
default:
handler.on_error();
}
}
template <typename Context> template <typename Context>
class arg_map { class arg_map {
private: private:
@ -2485,96 +2508,108 @@ typename basic_writer<Char>::pointer_type
template <typename Char> template <typename Char>
template <typename T, typename Spec> template <typename T, typename Spec>
void basic_writer<Char>::write_int(T value, const Spec& spec) { void basic_writer<Char>::write_int(T value, const Spec& spec) {
unsigned prefix_size = 0; struct spec_handler {
typedef typename internal::int_traits<T>::main_type UnsignedType; basic_writer<Char> &writer;
UnsignedType abs_value = static_cast<UnsignedType>(value); const Spec& spec;
char prefix[4] = ""; unsigned prefix_size = 0;
if (internal::is_negative(value)) { typedef typename internal::int_traits<T>::main_type UnsignedType;
prefix[0] = '-'; UnsignedType abs_value;
++prefix_size; char prefix[4] = "";
abs_value = 0 - abs_value;
} else if (spec.flag(SIGN_FLAG)) { spec_handler(basic_writer<Char> &w, T value, const Spec& s)
prefix[0] = spec.flag(PLUS_FLAG) ? '+' : ' '; : writer(w), abs_value(static_cast<UnsignedType>(value)), spec(s) {
++prefix_size; if (internal::is_negative(value)) {
} prefix[0] = '-';
switch (spec.type()) { ++prefix_size;
case 0: case 'd': { abs_value = 0 - abs_value;
unsigned num_digits = internal::count_digits(abs_value); } else if (spec.flag(SIGN_FLAG)) {
pointer_type p = prefix[0] = spec.flag(PLUS_FLAG) ? '+' : ' ';
prepare_int_buffer(num_digits, spec, prefix, prefix_size) + 1; ++prefix_size;
internal::format_decimal(get(p), abs_value, 0); }
break;
}
case 'x': case 'X': {
UnsignedType n = abs_value;
if (spec.flag(HASH_FLAG)) {
prefix[prefix_size++] = '0';
prefix[prefix_size++] = spec.type();
} }
unsigned num_digits = 0;
do { void on_dec() {
++num_digits; unsigned num_digits = internal::count_digits(abs_value);
} while ((n >>= 4) != 0); pointer_type p =
Char *p = get(prepare_int_buffer( writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size) + 1;
num_digits, spec, prefix, prefix_size)); internal::format_decimal(get(p), abs_value, 0);
n = abs_value;
const char *digits = spec.type() == 'x' ?
"0123456789abcdef" : "0123456789ABCDEF";
do {
*p-- = digits[n & 0xf];
} while ((n >>= 4) != 0);
break;
}
case 'b': case 'B': {
UnsignedType n = abs_value;
if (spec.flag(HASH_FLAG)) {
prefix[prefix_size++] = '0';
prefix[prefix_size++] = spec.type();
} }
unsigned num_digits = 0;
do { void on_hex() {
++num_digits; UnsignedType n = abs_value;
} while ((n >>= 1) != 0); if (spec.flag(HASH_FLAG)) {
Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size)); prefix[prefix_size++] = '0';
n = abs_value; prefix[prefix_size++] = spec.type();
do { }
*p-- = static_cast<Char>('0' + (n & 1)); unsigned num_digits = 0;
} while ((n >>= 1) != 0); do {
break; ++num_digits;
} } while ((n >>= 4) != 0);
case 'o': { Char *p =
UnsignedType n = abs_value; get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
if (spec.flag(HASH_FLAG)) n = abs_value;
prefix[prefix_size++] = '0'; const char *digits = spec.type() == 'x' ?
unsigned num_digits = 0; "0123456789abcdef" : "0123456789ABCDEF";
do { do {
++num_digits; *p-- = digits[n & 0xf];
} while ((n >>= 3) != 0); } while ((n >>= 4) != 0);
Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size)); }
n = abs_value;
do { void on_bin() {
*p-- = static_cast<Char>('0' + (n & 7)); UnsignedType n = abs_value;
} while ((n >>= 3) != 0); if (spec.flag(HASH_FLAG)) {
break; prefix[prefix_size++] = '0';
} prefix[prefix_size++] = spec.type();
case 'n': { }
unsigned num_digits = internal::count_digits(abs_value); unsigned num_digits = 0;
std::locale loc = buffer_.locale(); do {
Char thousands_sep = ++num_digits;
std::use_facet<std::numpunct<Char>>(loc).thousands_sep(); } while ((n >>= 1) != 0);
fmt::basic_string_view<Char> sep(&thousands_sep, 1); Char *p =
unsigned size = static_cast<unsigned>( get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
num_digits + sep.size() * ((num_digits - 1) / 3)); n = abs_value;
pointer_type p = prepare_int_buffer(size, spec, prefix, prefix_size) + 1; do {
internal::format_decimal(get(p), abs_value, 0, *p-- = static_cast<Char>('0' + (n & 1));
internal::add_thousands_sep<Char>(sep)); } while ((n >>= 1) != 0);
break; }
}
default: void on_oct() {
internal::report_unknown_type( UnsignedType n = abs_value;
spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer"); if (spec.flag(HASH_FLAG))
break; prefix[prefix_size++] = '0';
} unsigned num_digits = 0;
do {
++num_digits;
} while ((n >>= 3) != 0);
Char *p =
get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
n = abs_value;
do {
*p-- = static_cast<Char>('0' + (n & 7));
} while ((n >>= 3) != 0);
}
void on_num() {
unsigned num_digits = internal::count_digits(abs_value);
std::locale loc = writer.buffer_.locale();
Char thousands_sep =
std::use_facet<std::numpunct<Char>>(loc).thousands_sep();
fmt::basic_string_view<Char> sep(&thousands_sep, 1);
unsigned size = static_cast<unsigned>(
num_digits + sep.size() * ((num_digits - 1) / 3));
pointer_type p =
writer.prepare_int_buffer(size, spec, prefix, prefix_size) + 1;
internal::format_decimal(get(p), abs_value, 0,
internal::add_thousands_sep<Char>(sep));
}
void on_error() {
internal::report_unknown_type(
spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer");
}
};
internal::handle_integral_type_spec(
spec.type(), spec_handler(*this, value, spec));
} }
template <typename Char> template <typename Char>