Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33df4bef39 | ||
|
|
e8c4b6eb11 | ||
|
|
15a524adbb | ||
|
|
c3776fb967 |
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <iomanip> // setprecision
|
#include <iomanip> // setprecision
|
||||||
#include <ios> // fixed
|
#include <ios> // defaultfloat, fixed
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
#include <sstream> // stringstream
|
#include <sstream> // stringstream
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -32,9 +32,9 @@ void Builder::putF32(float number, size_t precision) const
|
|||||||
|
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
stream
|
stream
|
||||||
<< std::fixed
|
<< std::fixed << std::setprecision(precision)
|
||||||
<< std::setprecision(precision)
|
<< number
|
||||||
<< number;
|
<< std::defaultfloat << std::setprecision(6);
|
||||||
std::string string = stream.str();
|
std::string string = stream.str();
|
||||||
string = string.substr(0, string.find_first_of('0', string.find('.')));
|
string = string.substr(0, string.find_first_of('0', string.find('.')));
|
||||||
m_builder << string;
|
m_builder << string;
|
||||||
@@ -46,9 +46,9 @@ void Builder::putF64(double number, size_t precision) const
|
|||||||
|
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
stream
|
stream
|
||||||
<< std::fixed
|
<< std::fixed << std::setprecision(precision)
|
||||||
<< std::setprecision(precision)
|
<< number
|
||||||
<< number;
|
<< std::defaultfloat << std::setprecision(6);
|
||||||
std::string string = stream.str();
|
std::string string = stream.str();
|
||||||
string = string.substr(0, string.find_first_of('0', string.find('.')));
|
string = string.substr(0, string.find_first_of('0', string.find('.')));
|
||||||
m_builder << string;
|
m_builder << string;
|
||||||
|
|||||||
+6
-155
@@ -47,170 +47,21 @@ void variadicFormat(std::stringstream& stream, std::string_view format, TypeEras
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
void prettyVariadicFormat(Type type, bool bold, std::string_view format, TypeErasedParameters& parameters)
|
FormatAngleBracket::FormatAngleBracket(std::string& output)
|
||||||
{
|
: m_output(output)
|
||||||
std::stringstream stream;
|
|
||||||
|
|
||||||
if (type != Type::None || bold) {
|
|
||||||
stream << "\033[";
|
|
||||||
switch (type) {
|
|
||||||
case Type::Info:
|
|
||||||
stream << "34";
|
|
||||||
break;
|
|
||||||
case Type::Warn:
|
|
||||||
stream << "33";
|
|
||||||
break;
|
|
||||||
case Type::Danger:
|
|
||||||
stream << "31";
|
|
||||||
break;
|
|
||||||
case Type::Success:
|
|
||||||
stream << "32";
|
|
||||||
break;
|
|
||||||
case Type::Comment:
|
|
||||||
stream << "37";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (bold) {
|
|
||||||
stream << ";1";
|
|
||||||
}
|
|
||||||
stream << "m";
|
|
||||||
}
|
|
||||||
|
|
||||||
variadicFormat(stream, format, parameters);
|
|
||||||
|
|
||||||
if (type != Type::None || bold) {
|
|
||||||
stream << "\033[0m";
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s\n", stream.str().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
Dbg::Dbg(Type type, bool bold)
|
|
||||||
: m_type(type)
|
|
||||||
, m_bold(bold)
|
|
||||||
, m_stream()
|
|
||||||
, m_builder(m_stream)
|
|
||||||
{
|
|
||||||
if (type != Type::None || m_bold) {
|
|
||||||
m_stream << "\033[";
|
|
||||||
switch (type) {
|
|
||||||
case Type::Info:
|
|
||||||
m_stream << "34";
|
|
||||||
break;
|
|
||||||
case Type::Warn:
|
|
||||||
m_stream << "33";
|
|
||||||
break;
|
|
||||||
case Type::Danger:
|
|
||||||
m_stream << "31";
|
|
||||||
break;
|
|
||||||
case Type::Success:
|
|
||||||
m_stream << "32";
|
|
||||||
break;
|
|
||||||
case Type::Comment:
|
|
||||||
m_stream << "37";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (m_bold) {
|
|
||||||
m_stream << ";1";
|
|
||||||
}
|
|
||||||
m_stream << "m";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg::~Dbg()
|
|
||||||
{
|
|
||||||
if (m_type != Type::None || m_bold) {
|
|
||||||
m_stream << "\033[0m";
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s", m_stream.str().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg dbg()
|
|
||||||
{
|
|
||||||
return Dbg(Type::None, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg dbgb()
|
|
||||||
{
|
|
||||||
return Dbg(Type::None, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg info()
|
|
||||||
{
|
|
||||||
return Dbg(Type::Info, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg infob()
|
|
||||||
{
|
|
||||||
return Dbg(Type::Info, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg warn()
|
|
||||||
{
|
|
||||||
return Dbg(Type::Warn, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg warnb()
|
|
||||||
{
|
|
||||||
return Dbg(Type::Warn, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg danger()
|
|
||||||
{
|
|
||||||
return Dbg(Type::Danger, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg dangerb()
|
|
||||||
{
|
|
||||||
return Dbg(Type::Danger, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg success()
|
|
||||||
{
|
|
||||||
return Dbg(Type::Success, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg successb()
|
|
||||||
{
|
|
||||||
return Dbg(Type::Success, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg comment()
|
|
||||||
{
|
|
||||||
return Dbg(Type::Comment, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg commentb()
|
|
||||||
{
|
|
||||||
return Dbg(Type::Comment, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
Str::Str(std::string& fill)
|
|
||||||
: m_fill(fill)
|
|
||||||
, m_stream()
|
, m_stream()
|
||||||
, m_builder(m_stream)
|
, m_builder(m_stream)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Str::~Str()
|
FormatAngleBracket::~FormatAngleBracket()
|
||||||
{
|
{
|
||||||
m_fill = m_stream.str();
|
m_output = m_stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
Str str(std::string& fill)
|
FormatAngleBracket formatTo(std::string& output)
|
||||||
{
|
{
|
||||||
return Str(fill);
|
return FormatAngleBracket(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Util::Format
|
} // namespace Util::Format
|
||||||
|
|||||||
+34
-114
@@ -7,10 +7,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
|
#include <span>
|
||||||
#include <sstream> // stringstream
|
#include <sstream> // stringstream
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "util/format/builder.h"
|
#include "util/format/builder.h"
|
||||||
#include "util/format/parser.h"
|
#include "util/format/parser.h"
|
||||||
@@ -26,9 +26,10 @@ 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));
|
_format(builder, *static_cast<const T*>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Type erasure improves both compile time and binary size significantly
|
||||||
class TypeErasedParameters {
|
class TypeErasedParameters {
|
||||||
public:
|
public:
|
||||||
const Parameter parameter(size_t index) { return m_parameters[index]; }
|
const Parameter parameter(size_t index) { return m_parameters[index]; }
|
||||||
@@ -40,16 +41,20 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t m_index { 0 };
|
size_t m_index { 0 };
|
||||||
std::vector<Parameter> m_parameters;
|
std::span<const Parameter> m_parameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Parameters>
|
template<typename... Parameters>
|
||||||
class VariadicParameters final : public TypeErasedParameters {
|
class VariadicParameters final : public TypeErasedParameters {
|
||||||
public:
|
public:
|
||||||
VariadicParameters(const Parameters&... parameters)
|
VariadicParameters(const Parameters&... parameters)
|
||||||
|
: m_templatedParameters({ { ¶meters, formatParameterValue<Parameters> }... })
|
||||||
{
|
{
|
||||||
m_parameters = { { ¶meters, formatParameterValue<Parameters> }... };
|
m_parameters = m_templatedParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<Parameter, sizeof...(Parameters)> m_templatedParameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
@@ -59,138 +64,53 @@ void variadicFormat(std::stringstream& stream, std::string_view format, TypeEras
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
enum class Type {
|
|
||||||
None, // Foreground
|
|
||||||
Info, // Blue
|
|
||||||
Warn, // Yellow
|
|
||||||
Danger, // Red
|
|
||||||
Success, // Green
|
|
||||||
Comment, // White
|
|
||||||
};
|
|
||||||
|
|
||||||
void prettyVariadicFormat(Type type, bool bold, std::string_view format, TypeErasedParameters& parameters);
|
|
||||||
|
|
||||||
#define FORMAT_FUNCTION(name, type, bold) \
|
|
||||||
template<size_t N, typename... Parameters> \
|
|
||||||
void name(const char(&format)[N] = "", const Parameters&... parameters) \
|
|
||||||
{ \
|
|
||||||
VariadicParameters variadicParameters { parameters... }; \
|
|
||||||
prettyVariadicFormat(Type::type, bold, { format, N - 1 }, variadicParameters); \
|
|
||||||
}
|
|
||||||
|
|
||||||
FORMAT_FUNCTION(dbgln, None, false);
|
|
||||||
FORMAT_FUNCTION(dbgbln, None, true);
|
|
||||||
FORMAT_FUNCTION(infoln, Info, false);
|
|
||||||
FORMAT_FUNCTION(infobln, Info, true);
|
|
||||||
FORMAT_FUNCTION(warnln, Warn, false);
|
|
||||||
FORMAT_FUNCTION(warnbln, Warn, true);
|
|
||||||
FORMAT_FUNCTION(dangerln, Danger, false);
|
|
||||||
FORMAT_FUNCTION(dangerbln, Danger, true);
|
|
||||||
FORMAT_FUNCTION(successln, Success, false);
|
|
||||||
FORMAT_FUNCTION(successbln, Success, true);
|
|
||||||
FORMAT_FUNCTION(commentln, Comment, false);
|
|
||||||
FORMAT_FUNCTION(commentbln, Comment, true);
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
class Dbg {
|
|
||||||
public:
|
|
||||||
Dbg(Type type, bool bold);
|
|
||||||
virtual ~Dbg();
|
|
||||||
|
|
||||||
Builder& builder() { return m_builder; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Type m_type;
|
|
||||||
bool m_bold;
|
|
||||||
|
|
||||||
std::stringstream m_stream;
|
|
||||||
Builder m_builder;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
const Dbg& operator<<(const Dbg& debug, const T& value)
|
|
||||||
{
|
|
||||||
format(const_cast<Dbg&>(debug).builder(), value);
|
|
||||||
return debug;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dbg dbg();
|
|
||||||
Dbg dbgb();
|
|
||||||
Dbg info();
|
|
||||||
Dbg infob();
|
|
||||||
Dbg warn();
|
|
||||||
Dbg warnb();
|
|
||||||
Dbg danger();
|
|
||||||
Dbg dangerb();
|
|
||||||
Dbg success();
|
|
||||||
Dbg successb();
|
|
||||||
Dbg comment();
|
|
||||||
Dbg commentb();
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
template<typename... Parameters>
|
template<typename... Parameters>
|
||||||
void strln(std::string& fill, std::string_view format, const Parameters&... parameters)
|
std::string format(std::string_view format, const Parameters&... parameters)
|
||||||
{
|
{
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
VariadicParameters variadicParameters { parameters... };
|
VariadicParameters variadicParameters { parameters... };
|
||||||
variadicFormat(stream, format, variadicParameters);
|
variadicFormat(stream, format, variadicParameters);
|
||||||
stream << '\n';
|
return stream.str();
|
||||||
fill = stream.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Str {
|
template<typename... Parameters>
|
||||||
|
void formatTo(std::string& output, std::string_view format, const Parameters&... parameters)
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
VariadicParameters variadicParameters { parameters... };
|
||||||
|
variadicFormat(stream, format, variadicParameters);
|
||||||
|
output += stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
class FormatAngleBracket {
|
||||||
public:
|
public:
|
||||||
Str(std::string& fill);
|
FormatAngleBracket(std::string& output);
|
||||||
virtual ~Str();
|
virtual ~FormatAngleBracket();
|
||||||
|
|
||||||
Builder& builder() { return m_builder; }
|
Builder& builder() { return m_builder; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string& m_fill;
|
std::string& m_output;
|
||||||
std::stringstream m_stream;
|
std::stringstream m_stream;
|
||||||
Builder m_builder;
|
Builder m_builder;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const Str& operator<<(const Str& string, const T& value)
|
const FormatAngleBracket& operator<<(const FormatAngleBracket& formatAngleBracket, const T& value)
|
||||||
{
|
{
|
||||||
format(const_cast<Str&>(string).builder(), value);
|
_format(const_cast<FormatAngleBracket&>(formatAngleBracket).builder(), value);
|
||||||
return string;
|
return formatAngleBracket;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str str(std::string& fill);
|
FormatAngleBracket formatTo(std::string& output);
|
||||||
|
|
||||||
} // namespace Util::Format
|
} // namespace Util::Format
|
||||||
|
|
||||||
using Util::Format::commentbln;
|
namespace Util {
|
||||||
using Util::Format::commentln;
|
|
||||||
using Util::Format::dangerbln;
|
|
||||||
using Util::Format::dangerln;
|
|
||||||
using Util::Format::dbgbln;
|
|
||||||
using Util::Format::dbgln;
|
|
||||||
using Util::Format::infobln;
|
|
||||||
using Util::Format::infoln;
|
|
||||||
using Util::Format::successbln;
|
|
||||||
using Util::Format::successln;
|
|
||||||
using Util::Format::warnbln;
|
|
||||||
using Util::Format::warnln;
|
|
||||||
|
|
||||||
using Util::Format::comment;
|
using Util::Format::format;
|
||||||
using Util::Format::commentb;
|
using Util::Format::formatTo;
|
||||||
using Util::Format::danger;
|
|
||||||
using Util::Format::dangerb;
|
|
||||||
using Util::Format::dbg;
|
|
||||||
using Util::Format::dbgb;
|
|
||||||
using Util::Format::info;
|
|
||||||
using Util::Format::infob;
|
|
||||||
using Util::Format::success;
|
|
||||||
using Util::Format::successb;
|
|
||||||
using Util::Format::warn;
|
|
||||||
using Util::Format::warnb;
|
|
||||||
|
|
||||||
using Util::Format::str;
|
} // namespace Util
|
||||||
using Util::Format::strln;
|
|
||||||
|
|
||||||
using FormatBuilder = Util::Format::Builder;
|
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdio> // FILE, fputs
|
||||||
|
#include <iomanip> // setprecision
|
||||||
|
#include <ios> // defaultfloat, fixed
|
||||||
|
#include <sstream> // stringstream
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "util/format/print.h"
|
||||||
|
|
||||||
|
namespace Util::Format {
|
||||||
|
|
||||||
|
void printTimeElapsedAndTypePrefix(std::stringstream& stream, Type type, bool bold)
|
||||||
|
{
|
||||||
|
stream << std::fixed << std::setprecision(3)
|
||||||
|
<< s_timer.elapsedNanoseconds() / 1000000000.0 << "s "
|
||||||
|
<< std::defaultfloat << std::setprecision(6);
|
||||||
|
|
||||||
|
stream << "[\033[";
|
||||||
|
if (bold) {
|
||||||
|
stream << "1";
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case Type::None:
|
||||||
|
stream << ";35mdebug";
|
||||||
|
break;
|
||||||
|
case Type::Info:
|
||||||
|
stream << ";34minfo";
|
||||||
|
break;
|
||||||
|
case Type::Warn:
|
||||||
|
stream << ";33mwarn";
|
||||||
|
break;
|
||||||
|
case Type::Critical:
|
||||||
|
stream << ";31mcritical";
|
||||||
|
break;
|
||||||
|
case Type::Success:
|
||||||
|
stream << ";32msuccess";
|
||||||
|
break;
|
||||||
|
case Type::Comment:
|
||||||
|
stream << "mcomment";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
stream << "\033[0m] ";
|
||||||
|
}
|
||||||
|
|
||||||
|
void prettyVariadicFormat(FILE* file, Type type, bool bold, std::string_view format, TypeErasedParameters& parameters)
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
|
||||||
|
printTimeElapsedAndTypePrefix(stream, type, bold);
|
||||||
|
|
||||||
|
variadicFormat(stream, format, parameters);
|
||||||
|
|
||||||
|
std::string string = stream.str();
|
||||||
|
fputs(string.c_str(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
FormatPrint::FormatPrint(FILE* file, Type type, bool bold)
|
||||||
|
: m_file(file)
|
||||||
|
, m_type(type)
|
||||||
|
, m_bold(bold)
|
||||||
|
, m_stream()
|
||||||
|
, m_builder(m_stream)
|
||||||
|
{
|
||||||
|
printTimeElapsedAndTypePrefix(m_stream, type, bold);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint::~FormatPrint()
|
||||||
|
{
|
||||||
|
std::string string = m_stream.str();
|
||||||
|
fputs(string.c_str(), stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint dbg()
|
||||||
|
{
|
||||||
|
return FormatPrint(stdout, Type::None, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint dbgb()
|
||||||
|
{
|
||||||
|
return FormatPrint(stdout, Type::None, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint info()
|
||||||
|
{
|
||||||
|
return FormatPrint(stdout, Type::Info, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint infob()
|
||||||
|
{
|
||||||
|
return FormatPrint(stdout, Type::Info, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint warn()
|
||||||
|
{
|
||||||
|
return FormatPrint(stdout, Type::Warn, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint warnb()
|
||||||
|
{
|
||||||
|
return FormatPrint(stdout, Type::Warn, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint critical()
|
||||||
|
{
|
||||||
|
return FormatPrint(stderr, Type::Critical, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint criticalb()
|
||||||
|
{
|
||||||
|
return FormatPrint(stderr, Type::Critical, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint success()
|
||||||
|
{
|
||||||
|
return FormatPrint(stdout, Type::Success, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint successb()
|
||||||
|
{
|
||||||
|
return FormatPrint(stdout, Type::Success, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint comment()
|
||||||
|
{
|
||||||
|
return FormatPrint(stdout, Type::Comment, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint commentb()
|
||||||
|
{
|
||||||
|
return FormatPrint(stdout, Type::Comment, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Util::Format
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdio> // FILE
|
||||||
|
|
||||||
|
#include "util/format/format.h"
|
||||||
|
#include "util/timer.h"
|
||||||
|
|
||||||
|
namespace Util::Format {
|
||||||
|
|
||||||
|
static Util::Timer s_timer;
|
||||||
|
|
||||||
|
enum class Type {
|
||||||
|
None, // Foreground
|
||||||
|
Info, // Blue
|
||||||
|
Warn, // Yellow
|
||||||
|
Critical, // Red
|
||||||
|
Success, // Green
|
||||||
|
Comment, // White
|
||||||
|
};
|
||||||
|
|
||||||
|
void prettyVariadicFormat(FILE* file, Type type, bool bold, std::string_view format, TypeErasedParameters& parameters);
|
||||||
|
|
||||||
|
#define FORMAT_FUNCTION(name, type, bold) \
|
||||||
|
template<size_t N, typename... Parameters> \
|
||||||
|
void name(const char(&format)[N] = "", const Parameters&... parameters) \
|
||||||
|
{ \
|
||||||
|
VariadicParameters variadicParameters { parameters... }; \
|
||||||
|
prettyVariadicFormat(stdout, Type::type, bold, { format, N - 1 }, variadicParameters); \
|
||||||
|
} \
|
||||||
|
template<size_t N, typename... Parameters> \
|
||||||
|
void name(FILE* file, const char(&format)[N] = "", const Parameters&... parameters) \
|
||||||
|
{ \
|
||||||
|
VariadicParameters variadicParameters { parameters... }; \
|
||||||
|
prettyVariadicFormat(file, Type::type, bold, { format, N - 1 }, variadicParameters); \
|
||||||
|
}
|
||||||
|
|
||||||
|
FORMAT_FUNCTION(dbgln, None, false);
|
||||||
|
FORMAT_FUNCTION(dbgbln, None, true);
|
||||||
|
FORMAT_FUNCTION(infoln, Info, false);
|
||||||
|
FORMAT_FUNCTION(infobln, Info, true);
|
||||||
|
FORMAT_FUNCTION(warnln, Warn, false);
|
||||||
|
FORMAT_FUNCTION(warnbln, Warn, true);
|
||||||
|
FORMAT_FUNCTION(criticalln, Critical, false);
|
||||||
|
FORMAT_FUNCTION(criticalbln, Critical, true);
|
||||||
|
FORMAT_FUNCTION(successln, Success, false);
|
||||||
|
FORMAT_FUNCTION(successbln, Success, true);
|
||||||
|
FORMAT_FUNCTION(commentln, Comment, false);
|
||||||
|
FORMAT_FUNCTION(commentbln, Comment, true);
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
class FormatPrint {
|
||||||
|
public:
|
||||||
|
FormatPrint(FILE* file, Type type, bool bold);
|
||||||
|
virtual ~FormatPrint();
|
||||||
|
|
||||||
|
Builder& builder() { return m_builder; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
FILE* m_file;
|
||||||
|
Type m_type;
|
||||||
|
bool m_bold;
|
||||||
|
|
||||||
|
std::stringstream m_stream;
|
||||||
|
Builder m_builder;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const FormatPrint& operator<<(const FormatPrint& formatPrint, const T& value)
|
||||||
|
{
|
||||||
|
_format(const_cast<FormatPrint&>(formatPrint).builder(), value);
|
||||||
|
return formatPrint;
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatPrint dbg();
|
||||||
|
FormatPrint dbgb();
|
||||||
|
FormatPrint info();
|
||||||
|
FormatPrint infob();
|
||||||
|
FormatPrint warn();
|
||||||
|
FormatPrint warnb();
|
||||||
|
FormatPrint critical();
|
||||||
|
FormatPrint criticalb();
|
||||||
|
FormatPrint success();
|
||||||
|
FormatPrint successb();
|
||||||
|
FormatPrint comment();
|
||||||
|
FormatPrint commentb();
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
} // namespace Util::Format
|
||||||
|
|
||||||
|
namespace Util {
|
||||||
|
|
||||||
|
using Util::Format::commentbln;
|
||||||
|
using Util::Format::commentln;
|
||||||
|
using Util::Format::criticalbln;
|
||||||
|
using Util::Format::criticalln;
|
||||||
|
using Util::Format::dbgbln;
|
||||||
|
using Util::Format::dbgln;
|
||||||
|
using Util::Format::infobln;
|
||||||
|
using Util::Format::infoln;
|
||||||
|
using Util::Format::successbln;
|
||||||
|
using Util::Format::successln;
|
||||||
|
using Util::Format::warnbln;
|
||||||
|
using Util::Format::warnln;
|
||||||
|
|
||||||
|
using Util::Format::comment;
|
||||||
|
using Util::Format::commentb;
|
||||||
|
using Util::Format::critical;
|
||||||
|
using Util::Format::criticalb;
|
||||||
|
using Util::Format::dbg;
|
||||||
|
using Util::Format::dbgb;
|
||||||
|
using Util::Format::info;
|
||||||
|
using Util::Format::infob;
|
||||||
|
using Util::Format::success;
|
||||||
|
using Util::Format::successb;
|
||||||
|
using Util::Format::warn;
|
||||||
|
using Util::Format::warnb;
|
||||||
|
|
||||||
|
} // namespace Util
|
||||||
@@ -159,7 +159,7 @@ struct formatFunction {
|
|||||||
} // namespace Detail
|
} // namespace Detail
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr const auto& format = Util::Detail::staticConst<Detail::formatFunction>; // NOLINT(misc-definitions-in-headers,clang-diagnostic-unused-variable)
|
constexpr const auto& _format = Util::Detail::staticConst<Detail::formatFunction>; // NOLINT(misc-definitions-in-headers,clang-diagnostic-unused-variable)
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
} // namespace Util::Format
|
} // namespace Util::Format
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <utility> // move, swap
|
#include <utility> // move, swap
|
||||||
|
|
||||||
#include "util/format/format.h"
|
#include "util/format/builder.h"
|
||||||
#include "util/json/array.h"
|
#include "util/json/array.h"
|
||||||
#include "util/json/job.h"
|
#include "util/json/job.h"
|
||||||
#include "util/json/object.h"
|
#include "util/json/object.h"
|
||||||
@@ -332,7 +332,7 @@ std::ostream& operator<<(std::ostream& output, const Value& value)
|
|||||||
return output << value.dump(4);
|
return output << value.dump(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void format(FormatBuilder& builder, const Value& value)
|
void format(Util::Format::Builder& builder, const Value& value)
|
||||||
{
|
{
|
||||||
builder.putString(value.dump(4));
|
builder.putString(value.dump(4));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <utility> // forward
|
#include <utility> // forward
|
||||||
|
|
||||||
#include "util/format/format.h"
|
#include "util/format/builder.h"
|
||||||
#include "util/json/fromjson.h"
|
#include "util/json/fromjson.h"
|
||||||
#include "util/json/tojson.h"
|
#include "util/json/tojson.h"
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ private:
|
|||||||
std::istream& operator>>(std::istream& input, Value& value);
|
std::istream& operator>>(std::istream& input, Value& value);
|
||||||
std::ostream& operator<<(std::ostream& output, const Value& value);
|
std::ostream& operator<<(std::ostream& output, const Value& value);
|
||||||
|
|
||||||
void format(FormatBuilder& builder, const Value& value);
|
void format(Util::Format::Builder& builder, const Value& value);
|
||||||
|
|
||||||
} // namespace Util::JSON
|
} // namespace Util::JSON
|
||||||
|
|
||||||
|
|||||||
@@ -67,20 +67,16 @@ inline void __assertion_failed(const char* assertion, const char* file, uint32_t
|
|||||||
// 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
|
||||||
if (!std::string_view(function).starts_with("Util::Format::")) {
|
if (!std::string_view(function).starts_with("Util::Format::")) {
|
||||||
std::string message;
|
std::string message;
|
||||||
strln(message, parameters...);
|
formatTo(message, parameters...);
|
||||||
fprintf(stderr, "%s", message.c_str());
|
fprintf(stderr, "%s", message.c_str());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, parameters...);
|
fprintf(stderr, parameters...);
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Code line
|
// Code line
|
||||||
fprintf(stderr, " %u | %s\033[31;1m%s\033[0m%s\n", line,
|
fprintf(stderr, "\n %u | %s\033[31;1m%s\033[0m%s\n", line,
|
||||||
content.substr(0, column).c_str(), // Whitespace at front
|
content.substr(0, column).c_str(), // Whitespace at front
|
||||||
content.substr(column, assertionLength).c_str(), // Error portion
|
content.substr(column, assertionLength).c_str(), // Error portion
|
||||||
content.substr(column + assertionLength).c_str()); // Rest of the line
|
content.substr(column + assertionLength).c_str()); // Rest of the line
|
||||||
|
|||||||
@@ -22,44 +22,44 @@ TEST_CASE(FormatBasicTypes)
|
|||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
strln(result, "");
|
result = Util::format("");
|
||||||
EXPECT_EQ(result, "");
|
EXPECT_EQ(result, "");
|
||||||
|
|
||||||
strln(result, "{}", nullptr);
|
result = Util::format("{}", nullptr);
|
||||||
EXPECT_EQ(result, "(nil)");
|
EXPECT_EQ(result, "(nil)");
|
||||||
|
|
||||||
int* number = new int(3);
|
int* number = new int(3);
|
||||||
strln(result, "{}", number);
|
result = Util::format("{}", number);
|
||||||
EXPECT_EQ(result.substr(0, 2), "0x");
|
EXPECT_EQ(result.substr(0, 2), "0x");
|
||||||
|
|
||||||
strln(result, "{}", true);
|
result = Util::format("{}", true);
|
||||||
EXPECT_EQ(result, "true");
|
EXPECT_EQ(result, "true");
|
||||||
|
|
||||||
strln(result, "{}", false);
|
result = Util::format("{}", false);
|
||||||
EXPECT_EQ(result, "false");
|
EXPECT_EQ(result, "false");
|
||||||
|
|
||||||
strln(result, "{}", 'c');
|
result = Util::format("{}", 'c');
|
||||||
EXPECT_EQ(result, "c");
|
EXPECT_EQ(result, "c");
|
||||||
|
|
||||||
const char* cString = "C string";
|
const char* cString = "C string";
|
||||||
strln(result, "{}", cString);
|
result = Util::format("{}", cString);
|
||||||
EXPECT_EQ(result, "C string");
|
EXPECT_EQ(result, "C string");
|
||||||
|
|
||||||
std::string string = "string";
|
std::string string = "string";
|
||||||
strln(result, "{}", string);
|
result = Util::format("{}", string);
|
||||||
EXPECT_EQ(result, "string");
|
EXPECT_EQ(result, "string");
|
||||||
|
|
||||||
std::string_view stringView = "string_view";
|
std::string_view stringView = "string_view";
|
||||||
strln(result, "{}", stringView);
|
result = Util::format("{}", stringView);
|
||||||
EXPECT_EQ(result, "string_view");
|
EXPECT_EQ(result, "string_view");
|
||||||
|
|
||||||
strln(result, "{} {}", "Hello", "World");
|
result = Util::format("{} {}", "Hello", "World");
|
||||||
EXPECT_EQ(result, "Hello World");
|
EXPECT_EQ(result, "Hello World");
|
||||||
|
|
||||||
strln(result, "{{escaped braces}}");
|
result = Util::format("{{escaped braces}}");
|
||||||
EXPECT_EQ(result, "{escaped braces}");
|
EXPECT_EQ(result, "{escaped braces}");
|
||||||
|
|
||||||
strln(result, "{{braces{}}}", "Something");
|
result = Util::format("{{braces{}}}", "Something");
|
||||||
EXPECT_EQ(result, "{bracesSomething}");
|
EXPECT_EQ(result, "{bracesSomething}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,35 +68,35 @@ TEST_CASE(FormatNumbers)
|
|||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
int32_t i32 = 68766;
|
int32_t i32 = 68766;
|
||||||
strln(result, "{}", i32); // int
|
result = Util::format("{}", i32); // int
|
||||||
EXPECT_EQ(result, "68766");
|
EXPECT_EQ(result, "68766");
|
||||||
|
|
||||||
uint32_t u32 = 123841; // unsigned int
|
uint32_t u32 = 123841; // unsigned int
|
||||||
strln(result, "{}", u32);
|
result = Util::format("{}", u32);
|
||||||
EXPECT_EQ(result, "123841");
|
EXPECT_EQ(result, "123841");
|
||||||
|
|
||||||
int64_t i64 = 237942768427; // long int
|
int64_t i64 = 237942768427; // long int
|
||||||
strln(result, "{}", i64);
|
result = Util::format("{}", i64);
|
||||||
EXPECT_EQ(result, "237942768427");
|
EXPECT_EQ(result, "237942768427");
|
||||||
|
|
||||||
size_t u64 = 1337; // long unsigned int
|
size_t u64 = 1337; // long unsigned int
|
||||||
strln(result, "{}", u64);
|
result = Util::format("{}", u64);
|
||||||
EXPECT_EQ(result, "1337");
|
EXPECT_EQ(result, "1337");
|
||||||
|
|
||||||
float f32R = 245789.70000;
|
float f32R = 245789.70000;
|
||||||
strln(result, "{}", f32R);
|
result = Util::format("{}", f32R);
|
||||||
EXPECT_EQ(result, "245789.7");
|
EXPECT_EQ(result, "245789.7");
|
||||||
|
|
||||||
float f32 = 45645.3233;
|
float f32 = 45645.3233;
|
||||||
strln(result, "{}", f32);
|
result = Util::format("{}", f32);
|
||||||
EXPECT_EQ(result, "45645.324219");
|
EXPECT_EQ(result, "45645.324219");
|
||||||
|
|
||||||
double f64 = 87522.300000000;
|
double f64 = 87522.300000000;
|
||||||
strln(result, "{}", f64);
|
result = Util::format("{}", f64);
|
||||||
EXPECT_EQ(result, "87522.3");
|
EXPECT_EQ(result, "87522.3");
|
||||||
|
|
||||||
double pi = 3.14159265359;
|
double pi = 3.14159265359;
|
||||||
strln(result, "{:.15}", pi);
|
result = Util::format("{:.15}", pi);
|
||||||
EXPECT_EQ(result, "3.14159265359");
|
EXPECT_EQ(result, "3.14159265359");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ TEST_CASE(FormatContainers)
|
|||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
std::vector<std::string> vector { "thing1", "thing2", "thing3" };
|
std::vector<std::string> vector { "thing1", "thing2", "thing3" };
|
||||||
strln(result, "{}", vector);
|
result = Util::format("{}", vector);
|
||||||
EXPECT_EQ(result, R"({
|
EXPECT_EQ(result, R"({
|
||||||
thing1,
|
thing1,
|
||||||
thing2,
|
thing2,
|
||||||
@@ -113,7 +113,7 @@ TEST_CASE(FormatContainers)
|
|||||||
})");
|
})");
|
||||||
|
|
||||||
std::map<std::string, int> map { { "thing3", 3 }, { "thing2", 2 }, { "thing1", 1 } };
|
std::map<std::string, int> map { { "thing3", 3 }, { "thing2", 2 }, { "thing1", 1 } };
|
||||||
strln(result, "{}", map);
|
result = Util::format("{}", map);
|
||||||
EXPECT_EQ(result, R"({
|
EXPECT_EQ(result, R"({
|
||||||
"thing1": 1,
|
"thing1": 1,
|
||||||
"thing2": 2,
|
"thing2": 2,
|
||||||
@@ -126,7 +126,7 @@ TEST_CASE(FormatContainers)
|
|||||||
{ "thing1", "thing2", "thing3" },
|
{ "thing1", "thing2", "thing3" },
|
||||||
{ "thing1", "thing2", "thing3" }
|
{ "thing1", "thing2", "thing3" }
|
||||||
};
|
};
|
||||||
strln(result, "{}", twoDimensionalVector);
|
result = Util::format("{}", twoDimensionalVector);
|
||||||
EXPECT_EQ(result, R"({
|
EXPECT_EQ(result, R"({
|
||||||
{
|
{
|
||||||
thing1,
|
thing1,
|
||||||
|
|||||||
Reference in New Issue
Block a user