Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e6ec1eff3 | ||
|
|
14e57acfd8 | ||
|
|
5cf8d18742 | ||
|
|
086da50a57 | ||
|
|
36a18f65c1 | ||
|
|
ea853c1ace |
+26
-24
@@ -73,85 +73,87 @@ void Builder::putU64(size_t value,
|
|||||||
size_t width,
|
size_t width,
|
||||||
bool isNegative) const
|
bool isNegative) const
|
||||||
{
|
{
|
||||||
std::string string = numberToString(value, base, uppercase);
|
std::string number = numberToString(value, base, uppercase);
|
||||||
|
|
||||||
// Sign
|
// Sign
|
||||||
std::string signCharacter = "";
|
std::string prefix = "";
|
||||||
switch (sign) {
|
switch (sign) {
|
||||||
case Sign::None:
|
case Sign::None:
|
||||||
case Sign::Negative:
|
case Sign::Negative:
|
||||||
if (isNegative) {
|
if (isNegative) {
|
||||||
signCharacter = '-';
|
prefix = '-';
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Sign::Both:
|
case Sign::Both:
|
||||||
signCharacter = (isNegative) ? '-' : '+';
|
prefix = (isNegative) ? '-' : '+';
|
||||||
break;
|
break;
|
||||||
case Sign::Space:
|
case Sign::Space:
|
||||||
signCharacter = (isNegative) ? '-' : ' ';
|
prefix = (isNegative) ? '-' : ' ';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
};
|
};
|
||||||
if (align != Align::None || !zeroPadding) {
|
|
||||||
string.insert(0, signCharacter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alternative form
|
// Alternative form
|
||||||
if (alternativeForm) {
|
if (alternativeForm) {
|
||||||
switch (base) {
|
switch (base) {
|
||||||
case 2:
|
case 2:
|
||||||
string.insert(0, (uppercase) ? "0B" : "0b");
|
prefix += (uppercase) ? "0B" : "0b";
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
|
prefix += '0';
|
||||||
break;
|
break;
|
||||||
string.insert(0, 1, '0');
|
|
||||||
case 10:
|
case 10:
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
string.insert(0, (uppercase) ? "0X" : "0x");
|
prefix += (uppercase) ? "0X" : "0x";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zero padding
|
if (!zeroPadding) {
|
||||||
if (zeroPadding) {
|
number.insert(0, prefix);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (align != Builder::Align::None) {
|
||||||
|
number.insert(0, prefix);
|
||||||
|
}
|
||||||
fill = '0';
|
fill = '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t length = string.length();
|
size_t length = number.length();
|
||||||
if (width < length) {
|
if (width < length) {
|
||||||
m_builder.write(string.data(), length);
|
m_builder.write(number.data(), length);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (align) {
|
switch (align) {
|
||||||
case Align::Left:
|
case Align::Left:
|
||||||
m_builder.write(string.data(), length);
|
m_builder.write(number.data(), length);
|
||||||
m_builder << std::string(width - length, fill);
|
m_builder << std::string(width - length, fill);
|
||||||
break;
|
break;
|
||||||
case Align::Center: {
|
case Align::Center: {
|
||||||
size_t half = (width - length) / 2;
|
size_t half = (width - length) / 2;
|
||||||
m_builder << std::string(half, fill);
|
m_builder << std::string(half, fill);
|
||||||
m_builder.write(string.data(), length);
|
m_builder.write(number.data(), length);
|
||||||
m_builder << std::string(width - half - length, fill);
|
m_builder << std::string(width - half - length, fill);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Align::Right:
|
case Align::Right:
|
||||||
m_builder << std::string(width - length, fill);
|
m_builder << std::string(width - length, fill);
|
||||||
m_builder.write(string.data(), length);
|
m_builder.write(number.data(), length);
|
||||||
break;
|
break;
|
||||||
case Align::None:
|
case Align::None:
|
||||||
if (zeroPadding) {
|
if (zeroPadding) {
|
||||||
m_builder << signCharacter;
|
m_builder << prefix;
|
||||||
if (signCharacter.empty()) {
|
m_builder << std::string(width - length - prefix.length(), fill);
|
||||||
m_builder << '0';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_builder << std::string(width - length - zeroPadding, fill);
|
else {
|
||||||
m_builder.write(string.data(), length);
|
m_builder << std::string(width - length, fill);
|
||||||
|
}
|
||||||
|
m_builder.write(number.data(), length);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
|||||||
+68
-30
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstdint> // int8_t, int32_t, int64_t, uint8_t, uint32_t, uintptr_t
|
#include <cstdint> // int8_t, uint8_t, uintptr_t
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
@@ -66,7 +66,7 @@ template<typename T>
|
|||||||
struct Formatter {
|
struct Formatter {
|
||||||
Specifier specifier;
|
Specifier specifier;
|
||||||
|
|
||||||
constexpr void parse(Parser& parser)
|
void parse(Parser& parser)
|
||||||
{
|
{
|
||||||
if constexpr (std::is_same_v<T, char>) {
|
if constexpr (std::is_same_v<T, char>) {
|
||||||
parser.parseSpecifier(specifier, Parser::ParameterType::Char);
|
parser.parseSpecifier(specifier, Parser::ParameterType::Char);
|
||||||
@@ -197,7 +197,7 @@ struct Formatter<char[N]> : Formatter<const char*> {
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Formatter<T*> : Formatter<uintptr_t> {
|
struct Formatter<T*> : Formatter<uintptr_t> {
|
||||||
constexpr void parse(Parser& parser)
|
void parse(Parser& parser)
|
||||||
{
|
{
|
||||||
parser.parseSpecifier(specifier, Parser::ParameterType::Pointer);
|
parser.parseSpecifier(specifier, Parser::ParameterType::Pointer);
|
||||||
specifier.alternativeForm = true;
|
specifier.alternativeForm = true;
|
||||||
@@ -219,47 +219,85 @@ struct Formatter<std::nullptr_t> : Formatter<const void*> {
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Formatter<std::vector<T>> : Formatter<T> {
|
struct Formatter<std::vector<T>> : Formatter<T> {
|
||||||
|
Specifier specifier;
|
||||||
|
|
||||||
|
void parse(Parser& parser)
|
||||||
|
{
|
||||||
|
parser.parseSpecifier(specifier, Parser::ParameterType::Container);
|
||||||
|
}
|
||||||
|
|
||||||
void format(Builder& builder, const std::vector<T>& value) const
|
void format(Builder& builder, const std::vector<T>& value) const
|
||||||
{
|
{
|
||||||
builder.putString("{\n");
|
std::string indent = std::string(specifier.width, specifier.fill);
|
||||||
|
|
||||||
|
builder.putCharacter('{');
|
||||||
|
if (specifier.alternativeForm) {
|
||||||
|
builder.putCharacter('\n');
|
||||||
|
}
|
||||||
for (auto it = value.cbegin(); it != value.cend(); ++it) {
|
for (auto it = value.cbegin(); it != value.cend(); ++it) {
|
||||||
builder.putString(" ");
|
builder.putString(indent);
|
||||||
|
|
||||||
Formatter<T>::format(builder, *it);
|
Formatter<T>::format(builder, *it);
|
||||||
|
|
||||||
// Add comma, except after the last element
|
// Add comma, except after the last element
|
||||||
if (it != std::prev(value.end(), 1)) {
|
if (it != std::prev(value.end(), 1)) {
|
||||||
builder.putCharacter(',');
|
builder.putCharacter(',');
|
||||||
}
|
}
|
||||||
builder.putCharacter('\n');
|
else if (!specifier.alternativeForm) {
|
||||||
|
builder.putString(indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (specifier.alternativeForm) {
|
||||||
|
builder.putCharacter('\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
builder.putCharacter('}');
|
builder.putCharacter('}');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define UTIL_FORMAT_FORMAT_AS_MAP(type) \
|
#define UTIL_FORMAT_FORMAT_AS_MAP(type) \
|
||||||
template<typename K, typename V> \
|
template<typename K, typename V> \
|
||||||
struct Formatter<type<K, V>> \
|
struct Formatter<type<K, V>> \
|
||||||
: Formatter<K> \
|
: Formatter<K> \
|
||||||
, Formatter<V> { \
|
, Formatter<V> { \
|
||||||
void format(Builder& builder, const type<K, V>& value) const \
|
Specifier specifier; \
|
||||||
{ \
|
\
|
||||||
builder.putString("{\n"); \
|
void parse(Parser& parser) \
|
||||||
auto last = value.end(); \
|
{ \
|
||||||
for (auto it = value.begin(); it != last; ++it) { \
|
parser.parseSpecifier(specifier, Parser::ParameterType::Container); \
|
||||||
builder.putString(R"( ")"); \
|
} \
|
||||||
Formatter<K>::format(builder, it->first); \
|
\
|
||||||
builder.putString(R"(": )"); \
|
void format(Builder& builder, const type<K, V>& value) const \
|
||||||
Formatter<V>::format(builder, it->second); \
|
{ \
|
||||||
\
|
std::string indent = std::string(specifier.width, specifier.fill); \
|
||||||
/* Add comma, except after the last element */ \
|
\
|
||||||
if (std::next(it) != last) { \
|
builder.putCharacter('{'); \
|
||||||
builder.putCharacter(','); \
|
if (specifier.alternativeForm) { \
|
||||||
} \
|
builder.putCharacter('\n'); \
|
||||||
\
|
} \
|
||||||
builder.putCharacter('\n'); \
|
auto last = value.end(); \
|
||||||
} \
|
for (auto it = value.begin(); it != last; ++it) { \
|
||||||
builder.putCharacter('}'); \
|
builder.putString(indent); \
|
||||||
} \
|
builder.putCharacter('"'); \
|
||||||
|
Formatter<K>::format(builder, it->first); \
|
||||||
|
builder.putCharacter('"'); \
|
||||||
|
builder.putString((specifier.width > 0) ? ": " : ":"); \
|
||||||
|
Formatter<V>::format(builder, it->second); \
|
||||||
|
\
|
||||||
|
/* Add comma, except after the last element */ \
|
||||||
|
if (std::next(it) != last) { \
|
||||||
|
builder.putCharacter(','); \
|
||||||
|
} \
|
||||||
|
else if (!specifier.alternativeForm) { \
|
||||||
|
builder.putString(indent); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (specifier.alternativeForm) { \
|
||||||
|
builder.putCharacter('\n'); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
builder.putCharacter('}'); \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
UTIL_FORMAT_FORMAT_AS_MAP(std::map);
|
UTIL_FORMAT_FORMAT_AS_MAP(std::map);
|
||||||
|
|||||||
@@ -301,6 +301,7 @@ constexpr void Parser::checkSpecifierIntegralType(const Specifier& specifier)
|
|||||||
constexpr void Parser::checkSpecifierFloatingPointType(const Specifier& specifier)
|
constexpr void Parser::checkSpecifierFloatingPointType(const Specifier& specifier)
|
||||||
{
|
{
|
||||||
switch (specifier.type) {
|
switch (specifier.type) {
|
||||||
|
case PresentationType::None:
|
||||||
case PresentationType::Hexfloat:
|
case PresentationType::Hexfloat:
|
||||||
case PresentationType::HexfloatUppercase:
|
case PresentationType::HexfloatUppercase:
|
||||||
case PresentationType::Exponent:
|
case PresentationType::Exponent:
|
||||||
@@ -382,6 +383,8 @@ constexpr void Parser::checkSpecifierType(const Specifier& specifier, ParameterT
|
|||||||
case ParameterType::Pointer:
|
case ParameterType::Pointer:
|
||||||
checkSpecifierPointerType(specifier);
|
checkSpecifierPointerType(specifier);
|
||||||
break;
|
break;
|
||||||
|
case ParameterType::Container:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public:
|
|||||||
CString,
|
CString,
|
||||||
String,
|
String,
|
||||||
Pointer,
|
Pointer,
|
||||||
|
Container,
|
||||||
};
|
};
|
||||||
|
|
||||||
Parser(std::string_view format, size_t parameterCount);
|
Parser(std::string_view format, size_t parameterCount);
|
||||||
|
|||||||
+413
-54
@@ -5,8 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstdint> // int32_t, uint32_t, int64_t
|
#include <cstdint> // int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <sstream> // stringstream
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -18,29 +19,92 @@
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
TEST_CASE(FormatBasicTypes)
|
TEST_CASE(FormatIntegral)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
// Signed
|
||||||
|
|
||||||
|
int8_t i8 = 127; // char
|
||||||
|
result = Util::format("{}", i8);
|
||||||
|
EXPECT_EQ(result, "127");
|
||||||
|
|
||||||
|
int16_t i16 = 32767;
|
||||||
|
result = Util::format("{}", i16);
|
||||||
|
EXPECT_EQ(result, "32767");
|
||||||
|
|
||||||
|
int32_t i32 = 68766; // int
|
||||||
|
result = Util::format("{}", i32);
|
||||||
|
EXPECT_EQ(result, "68766");
|
||||||
|
|
||||||
|
int64_t i64 = 237942768427; // long int
|
||||||
|
result = Util::format("{}", i64);
|
||||||
|
EXPECT_EQ(result, "237942768427");
|
||||||
|
|
||||||
|
// Unsigned
|
||||||
|
|
||||||
|
uint8_t u8 = 255; // unsigned char
|
||||||
|
result = Util::format("{}", u8);
|
||||||
|
EXPECT_EQ(result, "255");
|
||||||
|
|
||||||
|
uint16_t u16 = 65535;
|
||||||
|
result = Util::format("{}", u16);
|
||||||
|
EXPECT_EQ(result, "65535");
|
||||||
|
|
||||||
|
uint32_t u32 = 4294967295; // unsigned int
|
||||||
|
result = Util::format("{}", u32);
|
||||||
|
EXPECT_EQ(result, "4294967295");
|
||||||
|
|
||||||
|
size_t u64 = 18446744073709551615; // long unsigned int
|
||||||
|
result = Util::format("{}", u64);
|
||||||
|
EXPECT_EQ(result, "18446744073709551615");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(FormatFloatingPoint)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
float f32R = 245789.70000;
|
||||||
|
result = Util::format("{}", f32R);
|
||||||
|
EXPECT_EQ(result, "245789.703125");
|
||||||
|
|
||||||
|
float f32 = 45645.3233;
|
||||||
|
result = Util::format("{}", f32);
|
||||||
|
EXPECT_EQ(result, "45645.324219");
|
||||||
|
|
||||||
|
double f64 = 87522.300000000;
|
||||||
|
result = Util::format("{}", f64);
|
||||||
|
EXPECT_EQ(result, "87522.300000");
|
||||||
|
|
||||||
|
double pi = 3.14159265359;
|
||||||
|
result = Util::format("{}", pi);
|
||||||
|
EXPECT_EQ(result, "3.141593");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(FormatChar)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
char character = 'A';
|
||||||
|
result = Util::format("{}", character);
|
||||||
|
EXPECT_EQ(result, "A");
|
||||||
|
|
||||||
|
bool boolean = true;
|
||||||
|
result = Util::format("{}", boolean);
|
||||||
|
EXPECT_EQ(result, "true");
|
||||||
|
|
||||||
|
boolean = false;
|
||||||
|
result = Util::format("{}", boolean);
|
||||||
|
EXPECT_EQ(result, "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(FormatString)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
result = Util::format("");
|
result = Util::format("");
|
||||||
EXPECT_EQ(result, "");
|
EXPECT_EQ(result, "");
|
||||||
|
|
||||||
result = Util::format("{}", nullptr);
|
|
||||||
EXPECT_EQ(result, "nullptr");
|
|
||||||
|
|
||||||
int* number = new int(3);
|
|
||||||
result = Util::format("{}", number);
|
|
||||||
EXPECT_EQ(result.substr(0, 2), "0x");
|
|
||||||
|
|
||||||
result = Util::format("{}", true);
|
|
||||||
EXPECT_EQ(result, "true");
|
|
||||||
|
|
||||||
result = Util::format("{}", false);
|
|
||||||
EXPECT_EQ(result, "false");
|
|
||||||
|
|
||||||
result = Util::format("{}", 'c');
|
|
||||||
EXPECT_EQ(result, "c");
|
|
||||||
|
|
||||||
const char* cString = "C string";
|
const char* cString = "C string";
|
||||||
result = Util::format("{}", cString);
|
result = Util::format("{}", cString);
|
||||||
EXPECT_EQ(result, "C string");
|
EXPECT_EQ(result, "C string");
|
||||||
@@ -63,41 +127,324 @@ TEST_CASE(FormatBasicTypes)
|
|||||||
EXPECT_EQ(result, "{bracesSomething}");
|
EXPECT_EQ(result, "{bracesSomething}");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(FormatNumbers)
|
TEST_CASE(FormatPointer)
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
int32_t i32 = 68766;
|
result = Util::format("{}", nullptr);
|
||||||
result = Util::format("{}", i32); // int
|
EXPECT_EQ(result, "0x0");
|
||||||
EXPECT_EQ(result, "68766");
|
|
||||||
|
|
||||||
uint32_t u32 = 123841; // unsigned int
|
int integer = 42;
|
||||||
result = Util::format("{}", u32);
|
std::stringstream stream;
|
||||||
EXPECT_EQ(result, "123841");
|
stream << &integer;
|
||||||
|
std::string pointer = stream.str();
|
||||||
|
|
||||||
int64_t i64 = 237942768427; // long int
|
result = Util::format("{}", &integer);
|
||||||
result = Util::format("{}", i64);
|
EXPECT_EQ(result, pointer);
|
||||||
EXPECT_EQ(result, "237942768427");
|
}
|
||||||
|
|
||||||
size_t u64 = 1337; // long unsigned int
|
TEST_CASE(FormatSpecifierIntegral)
|
||||||
result = Util::format("{}", u64);
|
{
|
||||||
EXPECT_EQ(result, "1337");
|
std::string result;
|
||||||
|
|
||||||
float f32R = 245789.70000;
|
// Fill and Align
|
||||||
result = Util::format("{}", f32R);
|
result = Util::format("{:+<}", 12345);
|
||||||
EXPECT_EQ(result, "245789.703125");
|
EXPECT_EQ(result, "12345");
|
||||||
|
result = Util::format("{:+^}", 12345);
|
||||||
|
EXPECT_EQ(result, "12345");
|
||||||
|
result = Util::format("{:+>}", 12345);
|
||||||
|
EXPECT_EQ(result, "12345");
|
||||||
|
|
||||||
float f32 = 45645.3233;
|
// Sign
|
||||||
result = Util::format("{}", f32);
|
result = Util::format("{:+}", 12345);
|
||||||
EXPECT_EQ(result, "45645.324219");
|
EXPECT_EQ(result, "+12345");
|
||||||
|
result = Util::format("{:+}", -12345);
|
||||||
|
EXPECT_EQ(result, "-12345");
|
||||||
|
result = Util::format("{:-}", 12345);
|
||||||
|
EXPECT_EQ(result, "12345");
|
||||||
|
result = Util::format("{:-}", -12345);
|
||||||
|
EXPECT_EQ(result, "-12345");
|
||||||
|
result = Util::format("{: }", 12345);
|
||||||
|
EXPECT_EQ(result, " 12345");
|
||||||
|
result = Util::format("{: }", -12345);
|
||||||
|
EXPECT_EQ(result, "-12345");
|
||||||
|
|
||||||
double f64 = 87522.300000000;
|
// AlternativeForm
|
||||||
result = Util::format("{}", f64);
|
result = Util::format("{:#}", 12345);
|
||||||
EXPECT_EQ(result, "87522.300000");
|
EXPECT_EQ(result, "12345");
|
||||||
|
|
||||||
double pi = 3.14159265359;
|
// ZeroPadding
|
||||||
result = Util::format("{:.15}", pi);
|
result = Util::format("{:0}", 12345);
|
||||||
EXPECT_EQ(result, "3.141592653590000");
|
EXPECT_EQ(result, "12345");
|
||||||
|
|
||||||
|
// Width
|
||||||
|
result = Util::format("{:10}", 12345);
|
||||||
|
EXPECT_EQ(result, " 12345");
|
||||||
|
|
||||||
|
// Width + Fill and Align
|
||||||
|
result = Util::format("{:+<10}", 12345);
|
||||||
|
EXPECT_EQ(result, "12345+++++");
|
||||||
|
result = Util::format("{:+^10}", 12345);
|
||||||
|
EXPECT_EQ(result, "++12345+++");
|
||||||
|
result = Util::format("{:+>10}", 12345);
|
||||||
|
EXPECT_EQ(result, "+++++12345");
|
||||||
|
|
||||||
|
// Width + ZeroPadding
|
||||||
|
result = Util::format("{:010}", 12345);
|
||||||
|
EXPECT_EQ(result, "0000012345");
|
||||||
|
|
||||||
|
// Precision
|
||||||
|
// Not possible on integral types
|
||||||
|
|
||||||
|
// Type
|
||||||
|
result = Util::format("{:b}", 12345);
|
||||||
|
EXPECT_EQ(result, "11000000111001");
|
||||||
|
result = Util::format("{:B}", 12345);
|
||||||
|
EXPECT_EQ(result, "11000000111001");
|
||||||
|
result = Util::format("{:c}", 65);
|
||||||
|
EXPECT_EQ(result, "A");
|
||||||
|
result = Util::format("{:o}", 12345);
|
||||||
|
EXPECT_EQ(result, "30071");
|
||||||
|
result = Util::format("{:x}", 62432);
|
||||||
|
EXPECT_EQ(result, "f3e0");
|
||||||
|
result = Util::format("{:X}", 62432);
|
||||||
|
EXPECT_EQ(result, "F3E0");
|
||||||
|
|
||||||
|
// Type + AlternativeForm
|
||||||
|
result = Util::format("{:#b}", 12345);
|
||||||
|
EXPECT_EQ(result, "0b11000000111001");
|
||||||
|
result = Util::format("{:#B}", 12345);
|
||||||
|
EXPECT_EQ(result, "0B11000000111001");
|
||||||
|
result = Util::format("{:#c}", 65);
|
||||||
|
EXPECT_EQ(result, "A");
|
||||||
|
result = Util::format("{:#o}", 12345);
|
||||||
|
EXPECT_EQ(result, "030071");
|
||||||
|
result = Util::format("{:#x}", 62432);
|
||||||
|
EXPECT_EQ(result, "0xf3e0");
|
||||||
|
result = Util::format("{:#X}", 62432);
|
||||||
|
EXPECT_EQ(result, "0XF3E0");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(FormatSpecifierIntegralCombination)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
// AlternativeForm + ZeroPadding + Width + Type
|
||||||
|
// ------------------------------
|
||||||
|
|
||||||
|
result = Util::format("{:-#010d}", 402);
|
||||||
|
EXPECT_EQ(result, "0000000402");
|
||||||
|
|
||||||
|
// AlternativeForm + Width + Type
|
||||||
|
// ------------------------------
|
||||||
|
|
||||||
|
result = Util::format("{:#10x}", 402);
|
||||||
|
EXPECT_EQ(result, " 0x192");
|
||||||
|
|
||||||
|
// + Fill and Align
|
||||||
|
|
||||||
|
result = Util::format("{:^<#10x}", 402);
|
||||||
|
EXPECT_EQ(result, "0x192^^^^^");
|
||||||
|
|
||||||
|
result = Util::format("{:^^#10x}", 402);
|
||||||
|
EXPECT_EQ(result, "^^0x192^^^");
|
||||||
|
|
||||||
|
result = Util::format("{:^>#10x}", 402);
|
||||||
|
EXPECT_EQ(result, "^^^^^0x192");
|
||||||
|
|
||||||
|
// ------------------------------
|
||||||
|
|
||||||
|
// + Sign
|
||||||
|
|
||||||
|
result = Util::format("{:+#10x}", 402);
|
||||||
|
EXPECT_EQ(result, " +0x192");
|
||||||
|
|
||||||
|
// + Fill and Align + Sign
|
||||||
|
|
||||||
|
result = Util::format("{:^<+#10x}", 402);
|
||||||
|
EXPECT_EQ(result, "+0x192^^^^");
|
||||||
|
|
||||||
|
result = Util::format("{:^^+#10x}", 402);
|
||||||
|
EXPECT_EQ(result, "^^+0x192^^");
|
||||||
|
|
||||||
|
result = Util::format("{:^>+#10x}", 402);
|
||||||
|
EXPECT_EQ(result, "^^^^+0x192");
|
||||||
|
|
||||||
|
// ------------------------------
|
||||||
|
|
||||||
|
// + ZeroPadding
|
||||||
|
|
||||||
|
result = Util::format("{:#010x}", 402);
|
||||||
|
EXPECT_EQ(result, "0x00000192");
|
||||||
|
|
||||||
|
// Fill and Align + ZeroPadding
|
||||||
|
|
||||||
|
result = Util::format("{:^<#010x}", 402);
|
||||||
|
EXPECT_EQ(result, "0x19200000");
|
||||||
|
|
||||||
|
result = Util::format("{:^^#010x}", 402);
|
||||||
|
EXPECT_EQ(result, "000x192000");
|
||||||
|
|
||||||
|
result = Util::format("{:^>#010x}", 402);
|
||||||
|
EXPECT_EQ(result, "000000x192");
|
||||||
|
|
||||||
|
// ------------------------------
|
||||||
|
|
||||||
|
// + Sign + ZeroPadding
|
||||||
|
|
||||||
|
result = Util::format("{:+#010x}", 402);
|
||||||
|
EXPECT_EQ(result, "+0x0000192");
|
||||||
|
|
||||||
|
// + Fill and Align + Sign + ZeroPadding
|
||||||
|
|
||||||
|
result = Util::format("{:^<+#010x}", 402);
|
||||||
|
EXPECT_EQ(result, "+0x1920000");
|
||||||
|
|
||||||
|
result = Util::format("{:^^+#010x}", 402);
|
||||||
|
EXPECT_EQ(result, "00+0x19200");
|
||||||
|
|
||||||
|
result = Util::format("{:^>+#010x}", 402);
|
||||||
|
EXPECT_EQ(result, "0000+0x192");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(FormatSpecifierFloatingPoint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(FormatSpecifierChar)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
char character = 65;
|
||||||
|
result = Util::format("{:b}", character);
|
||||||
|
EXPECT_EQ(result, "1000001");
|
||||||
|
result = Util::format("{:B}", character);
|
||||||
|
EXPECT_EQ(result, "1000001");
|
||||||
|
result = Util::format("{:d}", character);
|
||||||
|
EXPECT_EQ(result, "65");
|
||||||
|
result = Util::format("{:o}", character);
|
||||||
|
EXPECT_EQ(result, "101");
|
||||||
|
result = Util::format("{:x}", character);
|
||||||
|
EXPECT_EQ(result, "41");
|
||||||
|
result = Util::format("{:X}", character);
|
||||||
|
EXPECT_EQ(result, "41");
|
||||||
|
|
||||||
|
bool boolean = true;
|
||||||
|
result = Util::format("{:b}", boolean);
|
||||||
|
EXPECT_EQ(result, "1");
|
||||||
|
result = Util::format("{:B}", boolean);
|
||||||
|
EXPECT_EQ(result, "1");
|
||||||
|
result = Util::format("{:d}", boolean);
|
||||||
|
EXPECT_EQ(result, "1");
|
||||||
|
result = Util::format("{:o}", boolean);
|
||||||
|
EXPECT_EQ(result, "1");
|
||||||
|
result = Util::format("{:x}", boolean);
|
||||||
|
EXPECT_EQ(result, "1");
|
||||||
|
result = Util::format("{:X}", boolean);
|
||||||
|
EXPECT_EQ(result, "1");
|
||||||
|
|
||||||
|
boolean = false;
|
||||||
|
result = Util::format("{:b}", boolean);
|
||||||
|
EXPECT_EQ(result, "0");
|
||||||
|
result = Util::format("{:B}", boolean);
|
||||||
|
EXPECT_EQ(result, "0");
|
||||||
|
result = Util::format("{:d}", boolean);
|
||||||
|
EXPECT_EQ(result, "0");
|
||||||
|
result = Util::format("{:o}", boolean);
|
||||||
|
EXPECT_EQ(result, "0");
|
||||||
|
result = Util::format("{:x}", boolean);
|
||||||
|
EXPECT_EQ(result, "0");
|
||||||
|
result = Util::format("{:X}", boolean);
|
||||||
|
EXPECT_EQ(result, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(FormatSpecifierString)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
std::string string = "my string";
|
||||||
|
|
||||||
|
// Fill and Align
|
||||||
|
result = Util::format("{:+<}", string);
|
||||||
|
EXPECT_EQ(result, "my string");
|
||||||
|
result = Util::format("{:+^}", string);
|
||||||
|
EXPECT_EQ(result, "my string");
|
||||||
|
result = Util::format("{:+>}", string);
|
||||||
|
EXPECT_EQ(result, "my string");
|
||||||
|
|
||||||
|
// Sign
|
||||||
|
// Not possible on string types
|
||||||
|
|
||||||
|
// AlternativeForm
|
||||||
|
// Not possible on string types
|
||||||
|
|
||||||
|
// ZeroPadding
|
||||||
|
// Not possible on string types
|
||||||
|
|
||||||
|
// Width
|
||||||
|
result = Util::format("{:15}", string);
|
||||||
|
EXPECT_EQ(result, "my string ");
|
||||||
|
|
||||||
|
// Width + Fill and Align
|
||||||
|
result = Util::format("{:+<15}", string);
|
||||||
|
EXPECT_EQ(result, "my string++++++");
|
||||||
|
result = Util::format("{:+^15}", string);
|
||||||
|
EXPECT_EQ(result, "+++my string+++");
|
||||||
|
result = Util::format("{:+>15}", string);
|
||||||
|
EXPECT_EQ(result, "++++++my string");
|
||||||
|
|
||||||
|
// Precision
|
||||||
|
// Not possible on string types
|
||||||
|
|
||||||
|
// Type
|
||||||
|
result = Util::format("{:s}", string);
|
||||||
|
EXPECT_EQ(result, "my string");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE(FormatSpecifierPointer)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
int integer = 42;
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << &integer;
|
||||||
|
std::string pointer = stream.str();
|
||||||
|
|
||||||
|
// Fill and Align
|
||||||
|
result = Util::format("{:+<}", &integer);
|
||||||
|
EXPECT_EQ(result, pointer);
|
||||||
|
result = Util::format("{:+^}", &integer);
|
||||||
|
EXPECT_EQ(result, pointer);
|
||||||
|
result = Util::format("{:+>}", &integer);
|
||||||
|
EXPECT_EQ(result, pointer);
|
||||||
|
|
||||||
|
// Sign
|
||||||
|
// Not possible on string types
|
||||||
|
|
||||||
|
// AlternativeForm
|
||||||
|
// Not possible on string types
|
||||||
|
|
||||||
|
// ZeroPadding
|
||||||
|
// Not possible on string types
|
||||||
|
|
||||||
|
// Width
|
||||||
|
result = Util::format("{:24}", &integer);
|
||||||
|
EXPECT_EQ(result, std::string(24 - pointer.length(), ' ') + pointer);
|
||||||
|
|
||||||
|
// Width + Fill and Align
|
||||||
|
result = Util::format("{:+<24}", &integer);
|
||||||
|
EXPECT_EQ(result, pointer + std::string(24 - pointer.length(), '+'));
|
||||||
|
result = Util::format("{:+^24}", &integer);
|
||||||
|
EXPECT_EQ(result, std::string((24 - pointer.length()) / 2, '+') + pointer + std::string((24 - pointer.length()) / 2, '+'));
|
||||||
|
result = Util::format("{:+>24}", &integer);
|
||||||
|
EXPECT_EQ(result, std::string(24 - pointer.length(), '+') + pointer);
|
||||||
|
|
||||||
|
// Precision
|
||||||
|
// Not possible on string types
|
||||||
|
|
||||||
|
// Type
|
||||||
|
result = Util::format("{:p}", &integer);
|
||||||
|
EXPECT_EQ(result, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(FormatContainers)
|
TEST_CASE(FormatContainers)
|
||||||
@@ -106,19 +453,39 @@ TEST_CASE(FormatContainers)
|
|||||||
|
|
||||||
std::vector<std::string> vector { "thing1", "thing2", "thing3" };
|
std::vector<std::string> vector { "thing1", "thing2", "thing3" };
|
||||||
result = Util::format("{}", vector);
|
result = Util::format("{}", vector);
|
||||||
|
EXPECT_EQ(result, "{thing1,thing2,thing3}");
|
||||||
|
result = Util::format("{:1}", vector);
|
||||||
|
EXPECT_EQ(result, "{ thing1, thing2, thing3 }");
|
||||||
|
result = Util::format("{:#4}", vector);
|
||||||
EXPECT_EQ(result, R"({
|
EXPECT_EQ(result, R"({
|
||||||
thing1,
|
thing1,
|
||||||
thing2,
|
thing2,
|
||||||
thing3
|
thing3
|
||||||
})");
|
})");
|
||||||
|
result = Util::format("{:\t<#1}", vector);
|
||||||
|
EXPECT_EQ(result, R"({
|
||||||
|
thing1,
|
||||||
|
thing2,
|
||||||
|
thing3
|
||||||
|
})");
|
||||||
|
|
||||||
std::map<std::string, int> map { { "thing3", 3 }, { "thing2", 2 }, { "thing1", 1 } };
|
std::map<std::string, int> map { { "thing3", 3 }, { "thing2", 2 }, { "thing1", 1 } };
|
||||||
result = Util::format("{}", map);
|
result = Util::format("{}", map);
|
||||||
|
EXPECT_EQ(result, R"({"thing1":1,"thing2":2,"thing3":3})");
|
||||||
|
result = Util::format("{:1}", map);
|
||||||
|
EXPECT_EQ(result, R"({ "thing1": 1, "thing2": 2, "thing3": 3 })");
|
||||||
|
result = Util::format("{:#4}", map);
|
||||||
EXPECT_EQ(result, R"({
|
EXPECT_EQ(result, R"({
|
||||||
"thing1": 1,
|
"thing1": 1,
|
||||||
"thing2": 2,
|
"thing2": 2,
|
||||||
"thing3": 3
|
"thing3": 3
|
||||||
})");
|
})");
|
||||||
|
result = Util::format("{:\t<#1}", map);
|
||||||
|
EXPECT_EQ(result, R"({
|
||||||
|
"thing1": 1,
|
||||||
|
"thing2": 2,
|
||||||
|
"thing3": 3
|
||||||
|
})");
|
||||||
|
|
||||||
// Multidimensional containers arent supported,
|
// Multidimensional containers arent supported,
|
||||||
// the user should write a customization point
|
// the user should write a customization point
|
||||||
@@ -126,17 +493,9 @@ TEST_CASE(FormatContainers)
|
|||||||
{ "thing1", "thing2", "thing3" },
|
{ "thing1", "thing2", "thing3" },
|
||||||
{ "thing1", "thing2", "thing3" }
|
{ "thing1", "thing2", "thing3" }
|
||||||
};
|
};
|
||||||
result = Util::format("{}", twoDimensionalVector);
|
result = Util::format("{:#4}", twoDimensionalVector);
|
||||||
EXPECT_EQ(result, R"({
|
EXPECT_EQ(result, R"({
|
||||||
{
|
{thing1,thing2,thing3},
|
||||||
thing1,
|
{thing1,thing2,thing3}
|
||||||
thing2,
|
|
||||||
thing3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
thing1,
|
|
||||||
thing2,
|
|
||||||
thing3
|
|
||||||
}
|
|
||||||
})");
|
})");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user