Commit 92847a0d authored by Victor Zverovich's avatar Victor Zverovich

Add integral type handler

parent a03842b0
...@@ -1707,6 +1707,29 @@ typedef basic_format_specs<char> format_specs; ...@@ -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,10 +2508,16 @@ typename basic_writer<Char>::pointer_type ...@@ -2485,10 +2508,16 @@ 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) {
struct spec_handler {
basic_writer<Char> &writer;
const Spec& spec;
unsigned prefix_size = 0; unsigned prefix_size = 0;
typedef typename internal::int_traits<T>::main_type UnsignedType; typedef typename internal::int_traits<T>::main_type UnsignedType;
UnsignedType abs_value = static_cast<UnsignedType>(value); UnsignedType abs_value;
char prefix[4] = ""; char prefix[4] = "";
spec_handler(basic_writer<Char> &w, T value, const Spec& s)
: writer(w), abs_value(static_cast<UnsignedType>(value)), spec(s) {
if (internal::is_negative(value)) { if (internal::is_negative(value)) {
prefix[0] = '-'; prefix[0] = '-';
++prefix_size; ++prefix_size;
...@@ -2497,15 +2526,16 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) { ...@@ -2497,15 +2526,16 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) {
prefix[0] = spec.flag(PLUS_FLAG) ? '+' : ' '; prefix[0] = spec.flag(PLUS_FLAG) ? '+' : ' ';
++prefix_size; ++prefix_size;
} }
switch (spec.type()) { }
case 0: case 'd': {
void on_dec() {
unsigned num_digits = internal::count_digits(abs_value); unsigned num_digits = internal::count_digits(abs_value);
pointer_type p = pointer_type p =
prepare_int_buffer(num_digits, spec, prefix, prefix_size) + 1; writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size) + 1;
internal::format_decimal(get(p), abs_value, 0); internal::format_decimal(get(p), abs_value, 0);
break;
} }
case 'x': case 'X': {
void on_hex() {
UnsignedType n = abs_value; UnsignedType n = abs_value;
if (spec.flag(HASH_FLAG)) { if (spec.flag(HASH_FLAG)) {
prefix[prefix_size++] = '0'; prefix[prefix_size++] = '0';
...@@ -2515,17 +2545,17 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) { ...@@ -2515,17 +2545,17 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) {
do { do {
++num_digits; ++num_digits;
} while ((n >>= 4) != 0); } while ((n >>= 4) != 0);
Char *p = get(prepare_int_buffer( Char *p =
num_digits, spec, prefix, prefix_size)); get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
n = abs_value; n = abs_value;
const char *digits = spec.type() == 'x' ? const char *digits = spec.type() == 'x' ?
"0123456789abcdef" : "0123456789ABCDEF"; "0123456789abcdef" : "0123456789ABCDEF";
do { do {
*p-- = digits[n & 0xf]; *p-- = digits[n & 0xf];
} while ((n >>= 4) != 0); } while ((n >>= 4) != 0);
break;
} }
case 'b': case 'B': {
void on_bin() {
UnsignedType n = abs_value; UnsignedType n = abs_value;
if (spec.flag(HASH_FLAG)) { if (spec.flag(HASH_FLAG)) {
prefix[prefix_size++] = '0'; prefix[prefix_size++] = '0';
...@@ -2535,14 +2565,15 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) { ...@@ -2535,14 +2565,15 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) {
do { do {
++num_digits; ++num_digits;
} while ((n >>= 1) != 0); } while ((n >>= 1) != 0);
Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size)); Char *p =
get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
n = abs_value; n = abs_value;
do { do {
*p-- = static_cast<Char>('0' + (n & 1)); *p-- = static_cast<Char>('0' + (n & 1));
} while ((n >>= 1) != 0); } while ((n >>= 1) != 0);
break;
} }
case 'o': {
void on_oct() {
UnsignedType n = abs_value; UnsignedType n = abs_value;
if (spec.flag(HASH_FLAG)) if (spec.flag(HASH_FLAG))
prefix[prefix_size++] = '0'; prefix[prefix_size++] = '0';
...@@ -2550,31 +2581,35 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) { ...@@ -2550,31 +2581,35 @@ void basic_writer<Char>::write_int(T value, const Spec& spec) {
do { do {
++num_digits; ++num_digits;
} while ((n >>= 3) != 0); } while ((n >>= 3) != 0);
Char *p = get(prepare_int_buffer(num_digits, spec, prefix, prefix_size)); Char *p =
get(writer.prepare_int_buffer(num_digits, spec, prefix, prefix_size));
n = abs_value; n = abs_value;
do { do {
*p-- = static_cast<Char>('0' + (n & 7)); *p-- = static_cast<Char>('0' + (n & 7));
} while ((n >>= 3) != 0); } while ((n >>= 3) != 0);
break;
} }
case 'n': {
void on_num() {
unsigned num_digits = internal::count_digits(abs_value); unsigned num_digits = internal::count_digits(abs_value);
std::locale loc = buffer_.locale(); std::locale loc = writer.buffer_.locale();
Char thousands_sep = Char thousands_sep =
std::use_facet<std::numpunct<Char>>(loc).thousands_sep(); std::use_facet<std::numpunct<Char>>(loc).thousands_sep();
fmt::basic_string_view<Char> sep(&thousands_sep, 1); fmt::basic_string_view<Char> sep(&thousands_sep, 1);
unsigned size = static_cast<unsigned>( unsigned size = static_cast<unsigned>(
num_digits + sep.size() * ((num_digits - 1) / 3)); num_digits + sep.size() * ((num_digits - 1) / 3));
pointer_type p = prepare_int_buffer(size, spec, prefix, prefix_size) + 1; pointer_type p =
writer.prepare_int_buffer(size, spec, prefix, prefix_size) + 1;
internal::format_decimal(get(p), abs_value, 0, internal::format_decimal(get(p), abs_value, 0,
internal::add_thousands_sep<Char>(sep)); internal::add_thousands_sep<Char>(sep));
break;
} }
default:
void on_error() {
internal::report_unknown_type( internal::report_unknown_type(
spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer"); spec.type(), spec.flag(CHAR_FLAG) ? "char" : "integer");
break;
} }
};
internal::handle_integral_type_spec(
spec.type(), spec_handler(*this, value, spec));
} }
template <typename Char> template <typename Char>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment