mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
fmt: support numeric u128 formatting
This commit is contained in:
parent
4d9a167f56
commit
b5e9f09972
@ -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
|
||||||
|
|
||||||
|
@ -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,37 +57,66 @@ 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)
|
||||||
|
{
|
||||||
|
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');
|
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)
|
||||||
|
{
|
||||||
|
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');
|
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
|
||||||
|
{
|
||||||
|
if constexpr (sizeof(value) == 16)
|
||||||
|
{
|
||||||
|
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');
|
out.push_back(value % 10 + '0');
|
||||||
value /= 10;
|
value /= 10;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
while (0 < --min_size || value);
|
while (0 < --min_size || value);
|
||||||
|
|
||||||
// Revert written characters
|
// Revert written characters
|
||||||
@ -369,8 +399,17 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
|||||||
out.push_back(' ');
|
out.push_back(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
write_decimal(negative ? 0 - val : val, ctx.prec);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const usz size2 = out.size() - start;
|
const usz size2 = out.size() - start;
|
||||||
|
|
||||||
@ -425,15 +464,24 @@ 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)
|
||||||
|
{
|
||||||
|
if (ctx.type == 16)
|
||||||
|
{
|
||||||
|
u128 val2 = *reinterpret_cast<u128*>(val);
|
||||||
|
write_octal(val2, ctx.prec);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
write_octal(val, ctx.prec);
|
write_octal(val, ctx.prec);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const usz size2 = out.size() - start;
|
const usz size2 = out.size() - start;
|
||||||
|
|
||||||
@ -485,13 +533,21 @@ 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)
|
||||||
|
{
|
||||||
|
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);
|
write_hex(val, ch == 'X', ctx.prec);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const usz size2 = out.size() - start;
|
const usz size2 = out.size() - start;
|
||||||
|
|
||||||
@ -543,9 +599,17 @@ usz cfmt_append(Dst& out, const Char* fmt, Src&& src)
|
|||||||
const usz start = out.size();
|
const usz start = out.size();
|
||||||
|
|
||||||
if (!ctx.dot || ctx.prec)
|
if (!ctx.dot || ctx.prec)
|
||||||
|
{
|
||||||
|
if (ctx.type == 16)
|
||||||
|
{
|
||||||
|
u128 val2 = *reinterpret_cast<u128*>(val);
|
||||||
|
write_decimal(val2, ctx.prec);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
write_decimal(val, ctx.prec);
|
write_decimal(val, ctx.prec);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const usz size2 = out.size() - start;
|
const usz size2 = out.size() - start;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user