Add support for platforms without uintptr_t
This commit is contained in:
parent
0302927f56
commit
bd8177177a
@ -244,6 +244,15 @@ FMT_FUNC void system_error::init(int err_code, string_view format_str,
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <> FMT_FUNC int count_digits<4>(internal::uintptr_t n) {
|
||||
// Assume little endian; pointer formatting is implementation-defined anyway.
|
||||
int i = static_cast<int>(sizeof(void*)) - 1;
|
||||
while (i > 0 && n.value[i] == 0) --i;
|
||||
auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
|
||||
return i >= 0 ? i * char_digits + count_digits<4, unsigned>(n.value[i]) : 1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int char_traits<char>::format_float(char* buf, std::size_t size,
|
||||
const char* format, int precision,
|
||||
@ -268,6 +277,9 @@ const char basic_data<T>::DIGITS[] =
|
||||
"6061626364656667686970717273747576777879"
|
||||
"8081828384858687888990919293949596979899";
|
||||
|
||||
template <typename T>
|
||||
const char basic_data<T>::HEX_DIGITS[] = "0123456789abcdef";
|
||||
|
||||
#define FMT_POWERS_OF_10(factor) \
|
||||
factor * 10, factor * 100, factor * 1000, factor * 10000, factor * 100000, \
|
||||
factor * 1000000, factor * 10000000, factor * 100000000, \
|
||||
|
@ -311,11 +311,11 @@ template <>
|
||||
class numeric_limits<fmt::internal::uintptr_t>
|
||||
: public std::numeric_limits<int> {
|
||||
public:
|
||||
static uintptr_t to_uint(const void* p) {
|
||||
return fmt::internal::bit_cast<uintptr_t>(p);
|
||||
}
|
||||
|
||||
typedef uintptr_t uintptr_type;
|
||||
|
||||
static uintptr_type to_uint(const void* p) {
|
||||
return fmt::internal::bit_cast<uintptr_type>(p);
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
@ -743,6 +743,7 @@ template <typename T = void> struct FMT_API basic_data {
|
||||
static const uint64_t POW10_SIGNIFICANDS[];
|
||||
static const int16_t POW10_EXPONENTS[];
|
||||
static const char DIGITS[];
|
||||
static const char HEX_DIGITS[];
|
||||
static const char FOREGROUND_COLOR[];
|
||||
static const char BACKGROUND_COLOR[];
|
||||
static const char RESET_COLOR[5];
|
||||
@ -791,6 +792,8 @@ template <unsigned BITS, typename UInt> inline int count_digits(UInt n) {
|
||||
return num_digits;
|
||||
}
|
||||
|
||||
template <> int count_digits<4>(internal::uintptr_t n);
|
||||
|
||||
template <typename Char>
|
||||
inline size_t count_code_points(basic_string_view<Char> s) {
|
||||
return s.size();
|
||||
@ -1002,7 +1005,7 @@ inline Char* format_uint(Char* buffer, UInt value, int num_digits,
|
||||
buffer += num_digits;
|
||||
Char* end = buffer;
|
||||
do {
|
||||
const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||
const char* digits = upper ? "0123456789ABCDEF" : data::HEX_DIGITS;
|
||||
unsigned digit = (value & ((1 << BASE_BITS) - 1));
|
||||
*--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit)
|
||||
: digits[digit]);
|
||||
@ -1010,6 +1013,26 @@ inline Char* format_uint(Char* buffer, UInt value, int num_digits,
|
||||
return end;
|
||||
}
|
||||
|
||||
template <unsigned BASE_BITS, typename Char>
|
||||
Char* format_uint(Char* buffer, internal::uintptr_t n, int num_digits,
|
||||
bool = false) {
|
||||
auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
|
||||
int start = (num_digits + char_digits - 1) / char_digits - 1;
|
||||
if (int start_digits = num_digits % char_digits)
|
||||
buffer = format_uint<BASE_BITS>(buffer, n.value[start--], start_digits);
|
||||
for (; start >= 0; --start) {
|
||||
auto value = n.value[start];
|
||||
buffer += char_digits;
|
||||
auto p = buffer;
|
||||
for (int i = 0; i < char_digits; ++i) {
|
||||
unsigned digit = (value & ((1 << BASE_BITS) - 1));
|
||||
*--p = static_cast<Char>(data::HEX_DIGITS[digit]);
|
||||
value >>= BASE_BITS;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
|
||||
inline It format_uint(It out, UInt value, int num_digits, bool upper = false) {
|
||||
// Buffer should be large enough to hold all digits (digits / BASE_BITS + 1)
|
||||
@ -1420,7 +1443,7 @@ template <typename Range> class arg_formatter_base {
|
||||
}
|
||||
|
||||
void write_pointer(const void* p) {
|
||||
writer_.write(p, specs_);
|
||||
writer_.write_pointer(internal::numutil::to_uint(p), specs_);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -2690,8 +2713,9 @@ template <typename Range> class basic_writer {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename UIntPtr>
|
||||
struct pointer_writer {
|
||||
internal::numutil::uintptr_type value;
|
||||
UIntPtr value;
|
||||
int num_digits;
|
||||
|
||||
size_t size() const { return num_digits + 2; }
|
||||
@ -2700,7 +2724,7 @@ template <typename Range> class basic_writer {
|
||||
template <typename It> void operator()(It&& it) const {
|
||||
*it++ = static_cast<char_type>('0');
|
||||
*it++ = static_cast<char_type>('x');
|
||||
it = internal::format_uint<4, char_type>(it, value, num_digits, false);
|
||||
it = internal::format_uint<4, char_type>(it, value, num_digits);
|
||||
}
|
||||
};
|
||||
|
||||
@ -2791,11 +2815,10 @@ template <typename Range> class basic_writer {
|
||||
write(data, size, spec);
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_same<T, void>::value)>
|
||||
void write(const T* p, const align_spec* spec) {
|
||||
auto value = internal::numutil::to_uint(p);
|
||||
template <typename UIntPtr>
|
||||
void write_pointer(UIntPtr value, const align_spec* spec) {
|
||||
int num_digits = internal::count_digits<4>(value);
|
||||
auto pw = pointer_writer{value, num_digits};
|
||||
auto pw = pointer_writer<UIntPtr>{value, num_digits};
|
||||
if (!spec) return pw(reserve(num_digits + 2));
|
||||
align_spec as = *spec;
|
||||
if (as.align() == ALIGN_DEFAULT) as.align_ = ALIGN_RIGHT;
|
||||
|
@ -701,6 +701,13 @@ TEST(WriterTest, WriteWideString) {
|
||||
// std::declval<fmt::basic_writer<fmt::wbuffer>>().write("abc");
|
||||
}
|
||||
|
||||
TEST(WriterTest, WriteUIntPtr) {
|
||||
memory_buffer buf;
|
||||
fmt::writer writer(buf);
|
||||
writer.write_pointer(fmt::internal::bit_cast<fmt::internal::uintptr_t>(
|
||||
reinterpret_cast<void*>(0xface)), FMT_NULL);
|
||||
}
|
||||
|
||||
TEST(FormatToTest, FormatWithoutArgs) {
|
||||
std::string s;
|
||||
fmt::format_to(std::back_inserter(s), "test");
|
||||
|
Loading…
Reference in New Issue
Block a user