mirror of
https://github.com/fmtlib/fmt.git
synced 2024-10-02 04:52:03 +00:00
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 {
|
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>
|
template <typename T>
|
||||||
int char_traits<char>::format_float(char* buf, std::size_t size,
|
int char_traits<char>::format_float(char* buf, std::size_t size,
|
||||||
const char* format, int precision,
|
const char* format, int precision,
|
||||||
@ -268,6 +277,9 @@ const char basic_data<T>::DIGITS[] =
|
|||||||
"6061626364656667686970717273747576777879"
|
"6061626364656667686970717273747576777879"
|
||||||
"8081828384858687888990919293949596979899";
|
"8081828384858687888990919293949596979899";
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
const char basic_data<T>::HEX_DIGITS[] = "0123456789abcdef";
|
||||||
|
|
||||||
#define FMT_POWERS_OF_10(factor) \
|
#define FMT_POWERS_OF_10(factor) \
|
||||||
factor * 10, factor * 100, factor * 1000, factor * 10000, factor * 100000, \
|
factor * 10, factor * 100, factor * 1000, factor * 10000, factor * 100000, \
|
||||||
factor * 1000000, factor * 10000000, factor * 100000000, \
|
factor * 1000000, factor * 10000000, factor * 100000000, \
|
||||||
|
@ -311,11 +311,11 @@ template <>
|
|||||||
class numeric_limits<fmt::internal::uintptr_t>
|
class numeric_limits<fmt::internal::uintptr_t>
|
||||||
: public std::numeric_limits<int> {
|
: public std::numeric_limits<int> {
|
||||||
public:
|
public:
|
||||||
static uintptr_t to_uint(const void* p) {
|
|
||||||
return fmt::internal::bit_cast<uintptr_t>(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef uintptr_t uintptr_type;
|
typedef uintptr_t uintptr_type;
|
||||||
|
|
||||||
|
static uintptr_type to_uint(const void* p) {
|
||||||
|
return fmt::internal::bit_cast<uintptr_type>(p);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
@ -743,6 +743,7 @@ template <typename T = void> struct FMT_API basic_data {
|
|||||||
static const uint64_t POW10_SIGNIFICANDS[];
|
static const uint64_t POW10_SIGNIFICANDS[];
|
||||||
static const int16_t POW10_EXPONENTS[];
|
static const int16_t POW10_EXPONENTS[];
|
||||||
static const char DIGITS[];
|
static const char DIGITS[];
|
||||||
|
static const char HEX_DIGITS[];
|
||||||
static const char FOREGROUND_COLOR[];
|
static const char FOREGROUND_COLOR[];
|
||||||
static const char BACKGROUND_COLOR[];
|
static const char BACKGROUND_COLOR[];
|
||||||
static const char RESET_COLOR[5];
|
static const char RESET_COLOR[5];
|
||||||
@ -791,6 +792,8 @@ template <unsigned BITS, typename UInt> inline int count_digits(UInt n) {
|
|||||||
return num_digits;
|
return num_digits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> int count_digits<4>(internal::uintptr_t n);
|
||||||
|
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
inline size_t count_code_points(basic_string_view<Char> s) {
|
inline size_t count_code_points(basic_string_view<Char> s) {
|
||||||
return s.size();
|
return s.size();
|
||||||
@ -1002,7 +1005,7 @@ inline Char* format_uint(Char* buffer, UInt value, int num_digits,
|
|||||||
buffer += num_digits;
|
buffer += num_digits;
|
||||||
Char* end = buffer;
|
Char* end = buffer;
|
||||||
do {
|
do {
|
||||||
const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef";
|
const char* digits = upper ? "0123456789ABCDEF" : data::HEX_DIGITS;
|
||||||
unsigned digit = (value & ((1 << BASE_BITS) - 1));
|
unsigned digit = (value & ((1 << BASE_BITS) - 1));
|
||||||
*--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit)
|
*--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit)
|
||||||
: digits[digit]);
|
: digits[digit]);
|
||||||
@ -1010,6 +1013,26 @@ inline Char* format_uint(Char* buffer, UInt value, int num_digits,
|
|||||||
return end;
|
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>
|
template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
|
||||||
inline It format_uint(It out, UInt value, int num_digits, bool upper = false) {
|
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)
|
// 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) {
|
void write_pointer(const void* p) {
|
||||||
writer_.write(p, specs_);
|
writer_.write_pointer(internal::numutil::to_uint(p), specs_);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -2690,8 +2713,9 @@ template <typename Range> class basic_writer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename UIntPtr>
|
||||||
struct pointer_writer {
|
struct pointer_writer {
|
||||||
internal::numutil::uintptr_type value;
|
UIntPtr value;
|
||||||
int num_digits;
|
int num_digits;
|
||||||
|
|
||||||
size_t size() const { return num_digits + 2; }
|
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 {
|
template <typename It> void operator()(It&& it) const {
|
||||||
*it++ = static_cast<char_type>('0');
|
*it++ = static_cast<char_type>('0');
|
||||||
*it++ = static_cast<char_type>('x');
|
*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);
|
write(data, size, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(std::is_same<T, void>::value)>
|
template <typename UIntPtr>
|
||||||
void write(const T* p, const align_spec* spec) {
|
void write_pointer(UIntPtr value, const align_spec* spec) {
|
||||||
auto value = internal::numutil::to_uint(p);
|
|
||||||
int num_digits = internal::count_digits<4>(value);
|
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));
|
if (!spec) return pw(reserve(num_digits + 2));
|
||||||
align_spec as = *spec;
|
align_spec as = *spec;
|
||||||
if (as.align() == ALIGN_DEFAULT) as.align_ = ALIGN_RIGHT;
|
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");
|
// 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) {
|
TEST(FormatToTest, FormatWithoutArgs) {
|
||||||
std::string s;
|
std::string s;
|
||||||
fmt::format_to(std::back_inserter(s), "test");
|
fmt::format_to(std::back_inserter(s), "test");
|
||||||
|
Loading…
Reference in New Issue
Block a user