Compare commits

..
5 Commits
12 changed files with 357 additions and 253 deletions
+2 -7
View File
@@ -28,7 +28,7 @@ void Builder::putLiteral(std::string_view literal)
void Builder::putF32(float number, size_t precision) const void Builder::putF32(float number, size_t precision) const
{ {
precision = (precision > std::numeric_limits<float>::digits10) ? m_precision : precision; precision = (precision > std::numeric_limits<float>::digits10) ? 6 : precision;
std::stringstream stream; std::stringstream stream;
stream stream
@@ -41,7 +41,7 @@ void Builder::putF32(float number, size_t precision) const
void Builder::putF64(double number, size_t precision) const void Builder::putF64(double number, size_t precision) const
{ {
precision = (precision > std::numeric_limits<double>::digits10) ? m_precision : precision; precision = (precision > std::numeric_limits<double>::digits10) ? 6 : precision;
std::stringstream stream; std::stringstream stream;
stream stream
@@ -52,9 +52,4 @@ void Builder::putF64(double number, size_t precision) const
m_builder << string; m_builder << string;
} }
void Builder::resetSpecifiers()
{
setPrecision();
}
} // namespace Util::Format } // namespace Util::Format
+3 -8
View File
@@ -16,8 +16,7 @@ namespace Util::Format {
class Builder { class Builder {
public: public:
explicit Builder(std::stringstream& builder) explicit Builder(std::stringstream& builder)
: m_precision(6) : m_builder(builder)
, m_builder(builder)
{ {
} }
@@ -27,20 +26,16 @@ public:
void putU32(uint32_t number) const { m_builder << number; } // unsigned int void putU32(uint32_t number) const { m_builder << number; } // unsigned int
void putI64(int64_t number) const { m_builder << number; } // long int void putI64(int64_t number) const { m_builder << number; } // long int
void putU64(size_t number) const { m_builder << number; } // long unsigned int void putU64(size_t number) const { m_builder << number; } // long unsigned int
void putF32(float number, size_t precision = -1) const; void putF32(float number, size_t precision = 6) const;
void putF64(double number, size_t precision = -1) const; void putF64(double number, size_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(const std::string_view string) const { m_builder.write(string.data(), string.length()); } void putString(const std::string_view string) const { m_builder.write(string.data(), string.length()); }
void putPointer(const void* pointer) const { m_builder << pointer; } void putPointer(const void* pointer) const { m_builder << pointer; }
void resetSpecifiers();
void setPrecision(size_t precision = 6) { m_precision = precision; };
const std::stringstream& builder() const { return m_builder; } const std::stringstream& builder() const { return m_builder; }
std::stringstream& builder() { return m_builder; } std::stringstream& builder() { return m_builder; }
private: private:
size_t m_precision { 6 };
std::stringstream& m_builder; std::stringstream& m_builder;
}; };
+18 -9
View File
@@ -11,27 +11,36 @@
#include "util/format/builder.h" #include "util/format/builder.h"
#include "util/format/format.h" #include "util/format/format.h"
#include "util/format/parser.h" #include "util/format/parser.h"
#include "util/meta/assert.h"
namespace Util::Format { namespace Util::Format {
void variadicFormatImpl(Builder& builder, Parser& parser, TypeErasedParameters& parameters) void variadicFormatImpl(Builder& builder, Parser& parser, TypeErasedParameters& parameters)
{ {
// Consume everything until '{' or EOF
const auto literal = parser.consumeLiteral(); const auto literal = parser.consumeLiteral();
builder.putLiteral(literal); builder.putLiteral(literal);
if (!parameters.isEOF()) { // Reached end of format string
std::string_view specifier; if (parser.isEOF()) {
if (parser.consumeSpecifier(specifier)) { return;
parser.applySpecifier(builder, specifier);
} }
auto& parameter = parameters.parameter(parameters.tell()); // Consume index + ':'
parameter.format(builder, parameter.value); auto indexMaybe = parser.consumeIndex();
// Get parameter at index, or next
size_t index = indexMaybe.has_value() ? indexMaybe.value() : parameters.tell();
VERIFY(index < parameters.size(), "argument not found at index '%zu':'%zu'", index, parameters.size());
auto& parameter = parameters.parameter(index);
// Format the parameter
parameter.format(builder, parser, parameter.value);
// Go to next parameter
parameters.ignore(); parameters.ignore();
builder.resetSpecifiers(); // Recurse
}
if (!parser.isEOF()) { if (!parser.isEOF()) {
variadicFormatImpl(builder, parser, parameters); variadicFormatImpl(builder, parser, parameters);
} }
+6 -4
View File
@@ -12,12 +12,13 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include "util/format/builder.h" #include "util/format/formatter.h"
#include "util/format/parser.h"
#include "util/format/toformat.h"
namespace Util::Format { namespace Util::Format {
class Builder;
class Parser;
struct Parameter { struct Parameter {
const void* value; const void* value;
void (*format)(Builder& builder, const void* value); void (*format)(Builder& builder, const void* value);
@@ -26,7 +27,8 @@ struct Parameter {
template<typename T> template<typename T>
void formatParameterValue(Builder& builder, const void* value) void formatParameterValue(Builder& builder, const void* value)
{ {
_format(builder, *static_cast<const T*>(value)); Formatter<T> formatter;
formatter.format(builder, *static_cast<const T*>(value));
} }
// Type erasure improves both compile time and binary size significantly // Type erasure improves both compile time and binary size significantly
+93
View File
@@ -0,0 +1,93 @@
/*
* Copyright (C) 2022 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#include <cstddef> // size_t
#include <cstdint> // int32_t, uint32_t, int64_t,
#include <cstring> // strlen
#include <string>
#include <string_view>
#include "util/format/builder.h"
#include "util/format/formatter.h"
#include "util/format/parser.h"
namespace Util::Format {
// Integral
template<>
void Formatter<int32_t>::format(Builder& builder, int32_t value) const
{
builder.putI32(value);
}
template<>
void Formatter<uint32_t>::format(Builder& builder, uint32_t value) const
{
builder.putU32(value);
}
template<>
void Formatter<int64_t>::format(Builder& builder, int64_t value) const
{
builder.putI64(value);
}
template<>
void Formatter<size_t>::format(Builder& builder, size_t value) const
{
builder.putU64(value);
}
// Floating point
template<>
void Formatter<float>::format(Builder& builder, float value) const
{
builder.putF32(value);
}
template<>
void Formatter<double>::format(Builder& builder, double value) const
{
builder.putF64(value);
}
// Char
template<>
void Formatter<char>::format(Builder& builder, char value) const
{
builder.putCharacter(value);
}
template<>
void Formatter<bool>::format(Builder& builder, bool value) const
{
builder.putString(value ? "true" : "false");
}
// String
void Formatter<const char*>::format(Builder& builder, const char* value) const
{
builder.putString(value != nullptr ? std::string_view { value, strlen(value) } : "(nil)");
}
template<>
void Formatter<std::string_view>::format(Builder& builder, std::string_view value) const
{
builder.putString(value);
}
// Pointer
void Formatter<std::nullptr_t>::format(Builder& builder, std::nullptr_t) const
{
Formatter<const void*>::format(builder, 0);
}
} // namespace Util::Format
+145
View File
@@ -0,0 +1,145 @@
/*
* Copyright (C) 2022 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <cstddef> // size_t
#include <cstdint> // int32_t, uint8_t, uint32_t, int64_t,
#include <string>
#include <string_view>
#include <vector>
#include "util/format/builder.h"
#include "util/format/parser.h"
namespace Util::Format {
template<typename T>
struct Formatter {
void format(Builder& builder, T value) const { (void)builder, (void)value; }
};
// Integral
template<>
void Formatter<int32_t>::format(Builder& builder, int32_t value) const;
template<>
void Formatter<uint32_t>::format(Builder& builder, uint32_t value) const;
template<>
void Formatter<int64_t>::format(Builder& builder, int64_t value) const;
template<>
void Formatter<size_t>::format(Builder& builder, size_t value) const; // uint64_t
// Floating point
template<>
void Formatter<float>::format(Builder& builder, float value) const;
template<>
void Formatter<double>::format(Builder& builder, double value) const;
// Char
template<>
void Formatter<char>::format(Builder& builder, char value) const;
template<>
void Formatter<bool>::format(Builder& builder, bool value) const;
// String
template<>
void Formatter<std::string_view>::format(Builder& builder, std::string_view value) const;
template<>
struct Formatter<std::string> : Formatter<std::string_view> {
};
template<>
struct Formatter<const char*> : Formatter<std::string_view> {
void format(Builder& builder, const char* value) const;
};
template<>
struct Formatter<char*> : Formatter<const char*> {
};
template<size_t N>
struct Formatter<char[N]> : Formatter<const char*> {
};
// Pointer
template<typename T>
struct Formatter<T*> {
void format(Builder& builder, T* value) const
{
value == nullptr
? builder.putString("0x0")
: builder.putPointer(static_cast<const void*>(value));
}
};
template<>
struct Formatter<std::nullptr_t> : Formatter<const void*> {
void format(Builder& builder, std::nullptr_t) const;
};
// Container
template<typename T>
struct Formatter<std::vector<T>> : Formatter<T> {
void format(Builder& builder, const std::vector<T>& value) const
{
builder.putString("{\n");
for (auto it = value.cbegin(); it != value.cend(); ++it) {
builder.putString(" ");
Formatter<T>::format(builder, *it);
// Add comma, except after the last element
if (it != std::prev(value.end(), 1)) {
builder.putCharacter(',');
}
builder.putCharacter('\n');
}
builder.putCharacter('}');
}
};
#define UTIL_FORMAT_FORMAT_AS_MAP(type) \
template<typename K, typename V> \
struct Formatter<type<K, V>> \
: Formatter<K> \
, Formatter<V> { \
void format(Builder& builder, const type<K, V>& value) const \
{ \
builder.putString("{\n"); \
auto last = value.end(); \
for (auto it = value.begin(); it != last; ++it) { \
builder.putString(R"( ")"); \
Formatter<K>::format(builder, it->first); \
builder.putString(R"(": )"); \
Formatter<V>::format(builder, it->second); \
\
/* Add comma, except after the last element */ \
if (std::next(it) != last) { \
builder.putCharacter(','); \
} \
\
builder.putCharacter('\n'); \
} \
builder.putCharacter('}'); \
} \
}
UTIL_FORMAT_FORMAT_AS_MAP(std::map);
UTIL_FORMAT_FORMAT_AS_MAP(std::unordered_map);
} // namespace Util::Format
+16 -16
View File
@@ -17,31 +17,31 @@ std::string formatTimeElapsed()
return format("{:.3}s ", s_timer.elapsedNanoseconds() / 1000000000.0); return format("{:.3}s ", s_timer.elapsedNanoseconds() / 1000000000.0);
} }
std::string formatType(Type type) std::string formatType(LogType type)
{ {
std::string output; std::string output;
formatTo(output, "["); formatTo(output, "[");
switch (type) { switch (type) {
case Type::Trace: case LogType::Trace:
formatTo(output, "trace"); formatTo(output, "trace");
break; break;
case Type::Debug: case LogType::Debug:
formatTo(output, fg(TerminalColor::Magenta), "debug"); formatTo(output, fg(TerminalColor::Magenta), "debug");
break; break;
case Type::Success: case LogType::Success:
formatTo(output, fg(TerminalColor::Green), "success"); formatTo(output, fg(TerminalColor::Green), "success");
break; break;
case Type::Info: case LogType::Info:
formatTo(output, fg(TerminalColor::Blue), "info"); formatTo(output, fg(TerminalColor::Blue), "info");
break; break;
case Type::Warn: case LogType::Warn:
formatTo(output, Emphasis::Bold | fg(TerminalColor::Yellow), "warn"); formatTo(output, Emphasis::Bold | fg(TerminalColor::Yellow), "warn");
break; break;
case Type::Error: case LogType::Error:
formatTo(output, Emphasis::Bold | fg(TerminalColor::Red), "error"); formatTo(output, Emphasis::Bold | fg(TerminalColor::Red), "error");
break; break;
case Type::Critical: case LogType::Critical:
formatTo(output, Emphasis::Bold | fg(TerminalColor::White) | bg(TerminalColor::Red), "critical"); formatTo(output, Emphasis::Bold | fg(TerminalColor::White) | bg(TerminalColor::Red), "critical");
break; break;
default: default:
@@ -54,7 +54,7 @@ std::string formatType(Type type)
// ----------------------------------------- // -----------------------------------------
LogOperatorStyle::LogOperatorStyle(FILE* file, Type type) LogOperatorStyle::LogOperatorStyle(FILE* file, LogType type)
: m_file(file) : m_file(file)
, m_type(type) , m_type(type)
, m_stream() , m_stream()
@@ -73,37 +73,37 @@ LogOperatorStyle::~LogOperatorStyle()
LogOperatorStyle trace() LogOperatorStyle trace()
{ {
return LogOperatorStyle(stdout, Type::Trace); return LogOperatorStyle(stdout, LogType::Trace);
} }
LogOperatorStyle debug() LogOperatorStyle debug()
{ {
return LogOperatorStyle(stdout, Type::Debug); return LogOperatorStyle(stdout, LogType::Debug);
} }
LogOperatorStyle success() LogOperatorStyle success()
{ {
return LogOperatorStyle(stdout, Type::Success); return LogOperatorStyle(stdout, LogType::Success);
} }
LogOperatorStyle info() LogOperatorStyle info()
{ {
return LogOperatorStyle(stdout, Type::Info); return LogOperatorStyle(stdout, LogType::Info);
} }
LogOperatorStyle warn() LogOperatorStyle warn()
{ {
return LogOperatorStyle(stderr, Type::Warn); return LogOperatorStyle(stderr, LogType::Warn);
} }
LogOperatorStyle error() LogOperatorStyle error()
{ {
return LogOperatorStyle(stderr, Type::Error); return LogOperatorStyle(stderr, LogType::Error);
} }
LogOperatorStyle critical() LogOperatorStyle critical()
{ {
return LogOperatorStyle(stderr, Type::Critical); return LogOperatorStyle(stderr, LogType::Critical);
} }
} // namespace Util::Format } // namespace Util::Format
+11 -11
View File
@@ -18,7 +18,7 @@ namespace Util::Format {
static Util::Timer s_timer; static Util::Timer s_timer;
enum class Type : uint8_t { enum class LogType : uint8_t {
Trace, // White Trace, // White
Debug, // Purple Debug, // Purple
Success, // Green Success, // Green
@@ -29,7 +29,7 @@ enum class Type : uint8_t {
}; };
std::string formatTimeElapsed(); std::string formatTimeElapsed();
std::string formatType(Type type); std::string formatType(LogType type);
#define LOG_FUNCTION(name, file, type) \ #define LOG_FUNCTION(name, file, type) \
template<size_t N, typename... Parameters> \ template<size_t N, typename... Parameters> \
@@ -42,26 +42,26 @@ std::string formatType(Type type);
print(file, "\n"); \ print(file, "\n"); \
} }
LOG_FUNCTION(trace, stdout, Type::Trace); LOG_FUNCTION(trace, stdout, LogType::Trace);
LOG_FUNCTION(debug, stdout, Type::Debug); LOG_FUNCTION(debug, stdout, LogType::Debug);
LOG_FUNCTION(success, stdout, Type::Success); LOG_FUNCTION(success, stdout, LogType::Success);
LOG_FUNCTION(info, stdout, Type::Info); LOG_FUNCTION(info, stdout, LogType::Info);
LOG_FUNCTION(warn, stderr, Type::Warn); LOG_FUNCTION(warn, stderr, LogType::Warn);
LOG_FUNCTION(error, stderr, Type::Error); LOG_FUNCTION(error, stderr, LogType::Error);
LOG_FUNCTION(critical, stderr, Type::Critical); LOG_FUNCTION(critical, stderr, LogType::Critical);
// ----------------------------------------- // -----------------------------------------
class LogOperatorStyle { class LogOperatorStyle {
public: public:
LogOperatorStyle(FILE* file, Type type); LogOperatorStyle(FILE* file, LogType type);
virtual ~LogOperatorStyle(); virtual ~LogOperatorStyle();
Builder& builder() { return m_builder; } Builder& builder() { return m_builder; }
private: private:
FILE* m_file; FILE* m_file;
Type m_type; LogType m_type;
std::stringstream m_stream; std::stringstream m_stream;
Builder m_builder; Builder m_builder;
+47 -25
View File
@@ -6,6 +6,7 @@
#include <algorithm> // replace #include <algorithm> // replace
#include <cstddef> // size_t #include <cstddef> // size_t
#include <limits> // numeric_limits
#include <string> #include <string>
#include <string_view> #include <string_view>
@@ -53,7 +54,9 @@ void Parser::checkFormatParameterConsistency()
if (peek0 == '{') { if (peek0 == '{') {
braceOpen++; braceOpen++;
VERIFY(peek1 == '}' || peek1 == ':', "invalid parameter reference"); if (peek1 >= '0' && peek1 <= '9') {
m_mode = ArgumentIndexingMode::Manual;
}
} }
if (peek0 == '}') { if (peek0 == '}') {
braceClose++; braceClose++;
@@ -63,13 +66,13 @@ void Parser::checkFormatParameterConsistency()
} }
m_index = 0; m_index = 0;
VERIFY(!(braceOpen < braceClose), "extra open braces in format string"); // VERIFY(!(braceOpen < braceClose), "extra open braces in format string");
VERIFY(!(braceOpen > braceClose), "extra closing braces in format string"); // VERIFY(!(braceOpen > braceClose), "extra closing braces in format string");
VERIFY(!(braceOpen < m_parameterCount), "format string does not reference all passed parameters"); // VERIFY(!(braceOpen < m_parameterCount), "format string does not reference all passed parameters");
VERIFY(!(braceOpen > m_parameterCount), "format string references nonexistent parameter"); // VERIFY(!(braceOpen > m_parameterCount), "format string references nonexistent parameter");
} }
std::string_view Parser::consumeLiteral() std::string_view Parser::consumeLiteral()
@@ -101,44 +104,63 @@ std::string_view Parser::consumeLiteral()
return m_input.substr(begin); return m_input.substr(begin);
} }
bool Parser::consumeSpecifier(std::string_view& specifier) std::optional<size_t> Parser::consumeIndex()
{ {
if (!consumeSpecific('{')) { if (!consumeSpecific('{')) {
return false; VERIFY_NOT_REACHED();
return {};
} }
if (!consumeSpecific(':')) { switch (m_mode) {
VERIFY(consumeSpecific('}'), "invalid parameter reference"); case ArgumentIndexingMode::Automatic: {
specifier = ""; VERIFY(consumeSpecific('}') || consumeSpecific(':'), "expecting '}' or ':', not '%c'", peek());
return {};
} }
else { case ArgumentIndexingMode::Manual: {
const auto begin = tell(); const auto begin = tell();
// Go until AFTER the closing brace while (!isEOF()) {
while (peek(-1) != '}') { char peek0 = peek();
consume(); if (peek0 == '}' || peek0 == ':') {
break;
} }
specifier = m_input.substr(begin, tell() - begin - 1); VERIFY(peek0 >= '0' && peek0 <= '9', "expecting number, not '%c'", peek0);
ignore();
} }
return true; size_t result = stringToNumber(m_input.substr(begin, tell() - begin));
if (peek() == ':') {
ignore();
}
return result;
}
};
VERIFY_NOT_REACHED();
} }
void Parser::applySpecifier(Builder& builder, std::string_view specifier) size_t Parser::stringToNumber(std::string_view value)
{ {
if (specifier[0] == '.') { size_t result = 0;
size_t value = 0;
for (size_t i = 1; i < value.length(); ++i) {
if (value[i] < '0' || value[i] > '9') {
VERIFY_NOT_REACHED();
}
result *= 10;
result += value[i] - '0'; // Subtract ASCII 48 to get the number
}
return result;
}
for (size_t i = 1; i < specifier.length(); ++i) {
if (specifier[i] < '0' || specifier[i] > '9') {
return;
} }
value *= 10;
value += specifier[i] - '0'; // Subtract ASCII 48 to get the number
} }
builder.setPrecision(value);
} }
} }
+10 -2
View File
@@ -7,6 +7,7 @@
#pragma once #pragma once
#include <cstddef> // size_t #include <cstddef> // size_t
#include <optional>
#include <string_view> #include <string_view>
#include "util/genericlexer.h" #include "util/genericlexer.h"
@@ -17,17 +18,24 @@ class Builder;
class Parser final : public GenericLexer { class Parser final : public GenericLexer {
public: public:
enum class ArgumentIndexingMode {
Automatic, // {} ,{}
Manual, // {0},{1}
};
Parser(std::string_view format, size_t parameterCount); Parser(std::string_view format, size_t parameterCount);
virtual ~Parser(); virtual ~Parser();
void checkFormatParameterConsistency(); void checkFormatParameterConsistency();
std::string_view consumeLiteral(); std::string_view consumeLiteral();
bool consumeSpecifier(std::string_view& specifier); std::optional<size_t> consumeIndex();
size_t stringToNumber(std::string_view value);
void applySpecifier(Builder& builder, std::string_view specifier);
private: private:
ArgumentIndexingMode m_mode { ArgumentIndexingMode::Automatic };
size_t m_parameterCount { 0 }; size_t m_parameterCount { 0 };
}; };
-165
View File
@@ -1,165 +0,0 @@
/*
* Copyright (C) 2022 Riyyi
*
* SPDX-License-Identifier: MIT
*/
#pragma once
#include <cstddef> // nullptr_t, size_t
#include <cstdint> // int32_t, uint32_t, int64_t
#include <cstring> // strlen
#include <iterator> // next
#include <map>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility> // forward
#include <vector>
#include "util/meta/odr.h"
namespace Util::Format {
namespace Detail {
template<typename FormatBuilder>
void format(FormatBuilder& builder, std::nullptr_t)
{
builder.putString("(nil)");
}
template<typename FormatBuilder, typename T>
void format(FormatBuilder& builder, T* pointer)
{
builder.putPointer(static_cast<const void*>(pointer));
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, bool boolean)
{
builder.putString(boolean ? "true" : "false");
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, int32_t number) // int
{
builder.putI32(number);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, uint32_t number) // unsigned int
{
builder.putU32(number);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, int64_t number) // long int
{
builder.putI64(number);
}
template<typename FormatBuilder> // uint64_t
void format(FormatBuilder& builder, size_t number) // long unsigned int
{
builder.putU64(number);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, float number)
{
builder.putF32(number);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, double number)
{
builder.putF64(number);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, char character)
{
builder.putCharacter(character);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, const char* string)
{
builder.putString({ string, strlen(string) });
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, const std::string& string)
{
builder.putString(string);
}
template<typename FormatBuilder>
void format(FormatBuilder& builder, std::string_view string)
{
builder.putString(string);
}
template<typename FormatBuilder, typename T>
void format(FormatBuilder& builder, const std::vector<T>& array)
{
builder.putString("{\n");
for (auto it = array.cbegin(); it != array.cend(); ++it) {
builder.putString(" ");
format(builder, *it);
// Add comma, except after the last element
if (it != std::prev(array.end(), 1)) {
builder.putCharacter(',');
}
builder.putCharacter('\n');
}
builder.putCharacter('}');
}
#define FORMAT_MAP \
builder.putString("{\n"); \
auto last = map.end(); \
for (auto it = map.begin(); it != last; ++it) { \
builder.putString(R"( ")"); \
format(builder, it->first); \
builder.putString(R"(": )"); \
format(builder, it->second); \
\
/* Add comma, except after the last element */ \
if (std::next(it) != last) { \
builder.putCharacter(','); \
} \
\
builder.putCharacter('\n'); \
} \
builder.putCharacter('}');
template<typename FormatBuilder, typename K, typename V>
void format(FormatBuilder& builder, const std::map<K, V>& map)
{
FORMAT_MAP;
}
template<typename FormatBuilder, typename K, typename V>
void format(FormatBuilder& builder, const std::unordered_map<K, V>& map)
{
FORMAT_MAP;
}
struct formatFunction {
template<typename FormatBuilder, typename T>
auto operator()(FormatBuilder& builder, T&& value) const
{
return format(builder, std::forward<T>(value));
}
};
} // namespace Detail
namespace {
constexpr const auto& _format = Util::Detail::staticConst<Detail::formatFunction>; // NOLINT(misc-definitions-in-headers,clang-diagnostic-unused-variable)
} // namespace
} // namespace Util::Format
+2 -2
View File
@@ -66,8 +66,8 @@ inline void __assertion_failed(const char* assertion, const char* file, uint32_t
fprintf(stderr, ": "); fprintf(stderr, ": ");
// Cant use the formatting library to print asserts caused by the formatting library // Cant use the formatting library to print asserts caused by the formatting library
std::string_view functionString = function; std::string_view functionString = function;
if (!functionString.starts_with("Util::Format::") if (functionString.find("Util::Format::") != std::string_view::npos
&& !functionString.starts_with("Util::GenericLexer::")) { && functionString.find("Util::GenericLexer::") != std::string_view::npos) {
std::string message; std::string message;
formatTo(message, parameters...); formatTo(message, parameters...);
fprintf(stderr, "%s", message.c_str()); fprintf(stderr, "%s", message.c_str());