diff --git a/include/fmt/format.h b/include/fmt/format.h index 1e8cae5c..8f606e6a 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -314,6 +314,8 @@ class numeric_limits static uintptr_t to_uint(const void* p) { return fmt::internal::bit_cast(p); } + + typedef uintptr_t uintptr_type; }; } // namespace std @@ -780,6 +782,15 @@ inline int count_digits(uint64_t n) { } #endif +// Counts the number of digits in n. BITS = log2(radix). +template inline int count_digits(UInt n) { + int num_digits = 0; + do { + ++num_digits; + } while ((n >>= BITS) != 0); + return num_digits; +} + template inline size_t count_code_points(basic_string_view s) { return s.size(); @@ -1409,10 +1420,7 @@ template class arg_formatter_base { } void write_pointer(const void* p) { - format_specs specs = specs_ ? *specs_ : format_specs(); - specs.flags = HASH_FLAG; - specs.type = 'x'; - writer_.write_int(internal::numutil::to_uint(p), specs); + writer_.write(p, specs_); } protected: @@ -2486,16 +2494,6 @@ template class basic_writer { string_view get_prefix() const { return string_view(prefix, prefix_size); } - // Counts the number of digits in abs_value. BITS = log2(radix). - template int count_digits() const { - unsigned_type n = abs_value; - int num_digits = 0; - do { - ++num_digits; - } while ((n >>= BITS) != 0); - return num_digits; - } - int_writer(basic_writer& w, Int value, const Spec& s) : writer(w), spec(s), @@ -2541,7 +2539,7 @@ template class basic_writer { prefix[prefix_size++] = '0'; prefix[prefix_size++] = static_cast(spec.type); } - int num_digits = count_digits<4>(); + int num_digits = internal::count_digits<4>(abs_value); writer.write_int(num_digits, get_prefix(), spec, hex_writer{*this, num_digits}); } @@ -2560,13 +2558,13 @@ template class basic_writer { prefix[prefix_size++] = '0'; prefix[prefix_size++] = static_cast(spec.type); } - int num_digits = count_digits<1>(); + int num_digits = internal::count_digits<1>(abs_value); writer.write_int(num_digits, get_prefix(), spec, bin_writer<1>{abs_value, num_digits}); } void on_oct() { - int num_digits = count_digits<3>(); + int num_digits = internal::count_digits<3>(abs_value); if (spec.has(HASH_FLAG) && spec.precision <= num_digits) { // Octal prefix '0' is counted as a digit, so only add it if precision // is not greater than the number of digits. @@ -2692,6 +2690,20 @@ template class basic_writer { } }; + struct pointer_writer { + internal::numutil::uintptr_type value; + int num_digits; + + size_t size() const { return num_digits + 2; } + size_t width() const { return size(); } + + template void operator()(It&& it) const { + *it++ = static_cast('0'); + *it++ = static_cast('x'); + it = internal::format_uint<4, char_type>(it, value, num_digits, false); + } + }; + template friend class internal::arg_formatter_base; public: @@ -2780,11 +2792,14 @@ template class basic_writer { } template ::value)> - void write(const T* p) { - format_specs specs; - specs.flags = HASH_FLAG; - specs.type = 'x'; - write_int(internal::numutil::to_uint(p), specs); + void write(const T* p, const align_spec* spec) { + auto value = internal::numutil::to_uint(p); + int num_digits = internal::count_digits<4>(value); + auto pw = pointer_writer{value, num_digits}; + if (!spec) return pw(reserve(num_digits + 2)); + align_spec as = *spec; + if (as.align() == ALIGN_DEFAULT) as.align_ = ALIGN_RIGHT; + write_padded(as, pw); } };