Util: Add integral types and capitalization specifier options
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <algorithm> // min
|
#include <algorithm> // min
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
|
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
|
||||||
#include <iomanip> // setprecision
|
#include <iomanip> // setprecision
|
||||||
#include <ios> // defaultfloat, fixed
|
#include <ios> // defaultfloat, fixed
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
@@ -28,9 +29,42 @@ void Builder::putLiteral(std::string_view literal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builder::putU64(size_t value, char fill, Align align, Sign sign, bool zeroPadding, size_t width, bool isNegative) const
|
static constexpr std::string numberToString(size_t value, uint8_t base, bool uppercase)
|
||||||
{
|
{
|
||||||
std::string string = (std::stringstream {} << value).str();
|
std::string result;
|
||||||
|
|
||||||
|
if (value > std::numeric_limits<uint32_t>::max()) {
|
||||||
|
result.reserve(64);
|
||||||
|
}
|
||||||
|
else if (value > std::numeric_limits<uint16_t>::max()) {
|
||||||
|
result.reserve(32);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const auto& lookupLowercase = "0123456789abcdef";
|
||||||
|
constexpr const auto& lookupUppercase = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
if (value == 0) {
|
||||||
|
result = '0';
|
||||||
|
}
|
||||||
|
else if (uppercase) {
|
||||||
|
while (value > 0) {
|
||||||
|
result.insert(0, 1, lookupUppercase[value % base]);
|
||||||
|
value /= base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while (value > 0) {
|
||||||
|
result.insert(0, 1, lookupLowercase[value % base]);
|
||||||
|
value /= base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Builder::putU64(size_t value, uint8_t base, bool uppercase, char fill, Align align, Sign sign, bool zeroPadding, size_t width, bool isNegative) const
|
||||||
|
{
|
||||||
|
std::string string = numberToString(value, base, uppercase);
|
||||||
|
|
||||||
// Sign
|
// Sign
|
||||||
std::string signCharacter = "";
|
std::string signCharacter = "";
|
||||||
@@ -96,11 +130,11 @@ void Builder::putU64(size_t value, char fill, Align align, Sign sign, bool zeroP
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builder::putI64(int64_t value, char fill, Align align, Sign sign, bool zeroPadding, size_t width) const
|
void Builder::putI64(int64_t value, uint8_t base, bool uppercase, char fill, Align align, Sign sign, bool zeroPadding, size_t width) const
|
||||||
{
|
{
|
||||||
bool isNegative = value < 0;
|
bool isNegative = value < 0;
|
||||||
value = isNegative ? -value : value;
|
value = isNegative ? -value : value;
|
||||||
putU64(static_cast<uint64_t>(value), fill, align, sign, zeroPadding, width, isNegative);
|
putU64(static_cast<uint64_t>(value), base, uppercase, fill, align, sign, zeroPadding, width, isNegative);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builder::putF64(double number, uint8_t precision) const
|
void Builder::putF64(double number, uint8_t precision) const
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ public:
|
|||||||
|
|
||||||
void putLiteral(std::string_view literal);
|
void putLiteral(std::string_view literal);
|
||||||
|
|
||||||
void putU64(size_t value, char fill = ' ', Align align = Align::Right, Sign sign = Sign::Negative, bool zeroPadding = false, size_t width = 0, bool isNegative = false) const;
|
void putU64(size_t value, uint8_t base = 10, bool uppercase = false, char fill = ' ', Align align = Align::Right, Sign sign = Sign::Negative, bool zeroPadding = false, size_t width = 0, bool isNegative = false) const;
|
||||||
void putI64(int64_t value, char fill = ' ', Align align = Align::Right, Sign sign = Sign::Negative, bool zeroPadding = false, size_t width = 0) const;
|
void putI64(int64_t value, uint8_t base = 10, bool uppercase = false, char fill = ' ', Align align = Align::Right, Sign sign = Sign::Negative, bool zeroPadding = false, size_t width = 0) const;
|
||||||
void putF64(double number, uint8_t precision = 6) const;
|
void putF64(double number, uint8_t precision = 6) const;
|
||||||
void putCharacter(char character) const { m_builder.write(&character, 1); }
|
void putCharacter(char character) const { m_builder.write(&character, 1); }
|
||||||
void putString(std::string_view string, char fill = ' ', Align align = Align::Left, size_t width = 0) const;
|
void putString(std::string_view string, char fill = ' ', Align align = Align::Left, size_t width = 0) const;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstdint> // int8_t, int32_t, int64_t, uint8_t, uint32_t
|
#include <cstdint> // int8_t, int32_t, int64_t, uint8_t, uint32_t
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -91,14 +92,38 @@ struct Formatter<T> {
|
|||||||
|
|
||||||
void format(Builder& builder, T value) const
|
void format(Builder& builder, T value) const
|
||||||
{
|
{
|
||||||
if (std::is_signed_v<T>) {
|
uint8_t base = 0;
|
||||||
builder.putI64(
|
bool uppercase = false;
|
||||||
value, specifier.fill, specifier.align, specifier.sign,
|
switch (specifier.type) {
|
||||||
|
case PresentationType::BinaryUppercase:
|
||||||
|
uppercase = true;
|
||||||
|
case PresentationType::Binary:
|
||||||
|
base = 2;
|
||||||
|
break;
|
||||||
|
case PresentationType::Octal:
|
||||||
|
base = 8;
|
||||||
|
break;
|
||||||
|
case PresentationType::None:
|
||||||
|
case PresentationType::Decimal:
|
||||||
|
base = 10;
|
||||||
|
break;
|
||||||
|
case PresentationType::HexUppercase:
|
||||||
|
uppercase = true;
|
||||||
|
case PresentationType::Hex:
|
||||||
|
base = 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
if constexpr (std::is_unsigned_v<T>) {
|
||||||
|
builder.putU64(
|
||||||
|
value, base, uppercase, specifier.fill, specifier.align, specifier.sign,
|
||||||
specifier.zeroPadding, specifier.width);
|
specifier.zeroPadding, specifier.width);
|
||||||
}
|
}
|
||||||
if (std::is_unsigned_v<T>) {
|
else {
|
||||||
builder.putU64(
|
builder.putI64(
|
||||||
value, specifier.fill, specifier.align, specifier.sign,
|
value, base, uppercase, specifier.fill, specifier.align, specifier.sign,
|
||||||
specifier.zeroPadding, specifier.width);
|
specifier.zeroPadding, specifier.width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user