Browse Source

Util: Add integral types and capitalization specifier options

master
Riyyi 2 years ago
parent
commit
7a98f8e79f
  1. 42
      src/util/format/builder.cpp
  2. 4
      src/util/format/builder.h
  3. 37
      src/util/format/formatter.h

42
src/util/format/builder.cpp

@ -6,6 +6,7 @@
#include <algorithm> // min
#include <cstddef> // size_t
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
#include <iomanip> // setprecision
#include <ios> // defaultfloat, fixed
#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
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;
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

4
src/util/format/builder.h

@ -36,8 +36,8 @@ public:
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 putI64(int64_t value, char fill = ' ', Align align = Align::Right, Sign sign = Sign::Negative, bool zeroPadding = false, size_t width = 0) 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, 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 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;

37
src/util/format/formatter.h

@ -6,6 +6,7 @@
#pragma once
#include <cassert>
#include <cstddef> // size_t
#include <cstdint> // int8_t, int32_t, int64_t, uint8_t, uint32_t
#include <map>
@ -91,14 +92,38 @@ struct Formatter<T> {
void format(Builder& builder, T value) const
{
if (std::is_signed_v<T>) {
builder.putI64(
value, specifier.fill, specifier.align, specifier.sign,
uint8_t base = 0;
bool uppercase = false;
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);
}
if (std::is_unsigned_v<T>) {
builder.putU64(
value, specifier.fill, specifier.align, specifier.sign,
else {
builder.putI64(
value, base, uppercase, specifier.fill, specifier.align, specifier.sign,
specifier.zeroPadding, specifier.width);
}
}

Loading…
Cancel
Save