1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 12:12:50 +01:00

fmt: support numeric u128 formatting

This commit is contained in:
Nekotekina 2021-04-24 15:28:15 +03:00
parent 4d9a167f56
commit b5e9f09972
2 changed files with 99 additions and 20 deletions

View File

@ -254,6 +254,13 @@ void fmt_class_string<u128>::format(std::string& out, u64 arg)
{ {
// TODO: it should be supported as full-fledged integral type (with %u, %d, etc, fmt) // TODO: it should be supported as full-fledged integral type (with %u, %d, etc, fmt)
const u128& num = get_object(arg); const u128& num = get_object(arg);
if (!num)
{
out += '0';
return;
}
#ifdef _MSC_VER #ifdef _MSC_VER
fmt::append(out, "0x%016llx%016llx", num.hi, num.lo); fmt::append(out, "0x%016llx%016llx", num.hi, num.lo);
#else #else
@ -261,6 +268,12 @@ void fmt_class_string<u128>::format(std::string& out, u64 arg)
#endif #endif
} }
template <>
void fmt_class_string<s128>::format(std::string& out, u64 arg)
{
return fmt_class_string<u128>::format(out, arg);
}
template <> template <>
void fmt_class_string<src_loc>::format(std::string& out, u64 arg) void fmt_class_string<src_loc>::format(std::string& out, u64 arg)
{ {
@ -375,6 +388,8 @@ struct fmt::cfmt_src
TYPE(short); TYPE(short);
if (std::is_signed<char>::value) TYPE(char); if (std::is_signed<char>::value) TYPE(char);
TYPE(long); TYPE(long);
TYPE(u128);
TYPE(s128);
#undef TYPE #undef TYPE

View File

@ -5,6 +5,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include "util/asm.hpp"
static const usz size_dropped = -1; static const usz size_dropped = -1;
@ -56,36 +57,65 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
return result; return result;
}; };
const auto write_octal = [&](u64 value, u64 min_num) const auto write_octal = [&](auto value, u64 min_num)
{ {
out.resize(out.size() + std::max<u64>(min_num, 66 / 3 - (std::countl_zero<u64>(value | 1) + 2) / 3), '0'); if constexpr (sizeof(value) == 16)
{
out.resize(out.size() + std::max<u64>(min_num, 129 / 3 - (utils::clz128(value | 1) + 1) / 3), '0');
}
else
{
out.resize(out.size() + std::max<u64>(min_num, 66 / 3 - (std::countl_zero<u64>(value | 1) + 2) / 3), '0');
}
// Write in reversed order // Write in reversed order
for (auto i = out.rbegin(); value; i++, value /= 8) for (auto i = out.rbegin(); value; i++, value >>= 3)
{ {
*i = value % 8 + '0'; *i = static_cast<char>(static_cast<u64>(value) & 7) + '0';
} }
}; };
const auto write_hex = [&](u64 value, bool upper, u64 min_num) const auto write_hex = [&](auto value, bool upper, u64 min_num)
{ {
out.resize(out.size() + std::max<u64>(min_num, 64 / 4 - std::countl_zero<u64>(value | 1) / 4), '0'); if constexpr (sizeof(value) == 16)
{
out.resize(out.size() + std::max<u64>(min_num, 128 / 4 - utils::clz128(value | 1) / 4), '0');
}
else
{
out.resize(out.size() + std::max<u64>(min_num, 64 / 4 - std::countl_zero<u64>(value | 1) / 4), '0');
}
// Write in reversed order // Write in reversed order
for (auto i = out.rbegin(); value; i++, value /= 16) for (auto i = out.rbegin(); value; i++, value >>= 4)
{ {
*i = (upper ? "0123456789ABCDEF" : "0123456789abcdef")[value % 16]; *i = (upper ? "0123456789ABCDEF" : "0123456789abcdef")[static_cast<usz>(value & 0xf)];
} }
}; };
const auto write_decimal = [&](u64 value, s64 min_size) const auto write_decimal = [&](auto value, s64 min_size)
{ {
const usz start = out.size(); const usz start = out.size();
do do
{ {
out.push_back(value % 10 + '0'); if constexpr (sizeof(value) == 16)
value /= 10; {
const u128 v0 = value;
value >>= 1;
constexpr u128 by_five = 0x3333'3333'3333'3333;
const u128 v1 = (value >> 64) * by_five;
const u128 v2 = ((value >> 64) * by_five) >> 64;
const u128 v3 = (static_cast<u64>(value) * by_five) >> 64;
value = v1 + v2 + v3;
out.push_back(static_cast<char>(static_cast<u64>(v0 - (value * 10))) + '0');
}
else
{
out.push_back(value % 10 + '0');
value /= 10;
}
} }
while (0 < --min_size || value); while (0 < --min_size || value);
@ -369,7 +399,16 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
out.push_back(' '); out.push_back(' ');
} }
write_decimal(negative ? 0 - val : val, ctx.prec); if (ctx.type == 16)
{
// TODO: support negative values (s128)
u128 val2 = *reinterpret_cast<u128*>(val);
write_decimal(val2, ctx.prec);
}
else
{
write_decimal(negative ? 0 - val : val, ctx.prec);
}
} }
const usz size2 = out.size() - start; const usz size2 = out.size() - start;
@ -425,14 +464,23 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
{ {
out.push_back('0'); out.push_back('0');
if (val) if (ctx.prec)
{ {
write_octal(val, ctx.prec ? ctx.prec - 1 : 0); ctx.prec--;
} }
} }
else if (!ctx.dot || ctx.prec)
if ((ctx.alter && val) || !ctx.dot || ctx.prec)
{ {
write_octal(val, ctx.prec); if (ctx.type == 16)
{
u128 val2 = *reinterpret_cast<u128*>(val);
write_octal(val2, ctx.prec);
}
else
{
write_octal(val, ctx.prec);
}
} }
const usz size2 = out.size() - start; const usz size2 = out.size() - start;
@ -485,12 +533,20 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
if (val) if (val)
{ {
out.push_back(ch); // Prepend 0x or 0X out.push_back(ch); // Prepend 0x or 0X
write_hex(val, ch == 'X', ctx.prec);
} }
} }
else if (!ctx.dot || ctx.prec)
if ((ctx.alter && val) || !ctx.dot || ctx.prec)
{ {
write_hex(val, ch == 'X', ctx.prec); if (ctx.type == 16)
{
u128 val2 = *reinterpret_cast<u128*>(val);
write_hex(val2, ch == 'X', ctx.prec);
}
else
{
write_hex(val, ch == 'X', ctx.prec);
}
} }
const usz size2 = out.size() - start; const usz size2 = out.size() - start;
@ -544,7 +600,15 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
if (!ctx.dot || ctx.prec) if (!ctx.dot || ctx.prec)
{ {
write_decimal(val, ctx.prec); if (ctx.type == 16)
{
u128 val2 = *reinterpret_cast<u128*>(val);
write_decimal(val2, ctx.prec);
}
else
{
write_decimal(val, ctx.prec);
}
} }
const usz size2 = out.size() - start; const usz size2 = out.size() - start;