Compare commits
7
Commits
33df4bef39
...
f58113e257
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f58113e257 | ||
|
|
c90369181f | ||
|
|
187e082018 | ||
|
|
3837ebef06 | ||
|
|
94906028fc | ||
|
|
c59bfc20f7 | ||
|
|
04f5f42bb5 |
+2
-2
@@ -4,7 +4,6 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cassert> // assert
|
|
||||||
#include <csignal> // raise
|
#include <csignal> // raise
|
||||||
#include <cstdio> // fprintf
|
#include <cstdio> // fprintf
|
||||||
#include <filesystem> // current_path, recursive_directory
|
#include <filesystem> // current_path, recursive_directory
|
||||||
@@ -14,6 +13,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "util/json/json.h"
|
#include "util/json/json.h"
|
||||||
|
#include "util/meta/assert.h"
|
||||||
|
|
||||||
Config::Config(s)
|
Config::Config(s)
|
||||||
: m_workingDirectory(std::filesystem::current_path())
|
: m_workingDirectory(std::filesystem::current_path())
|
||||||
@@ -82,7 +82,7 @@ void toJson(Util::Json& json, const Settings& settings)
|
|||||||
|
|
||||||
void fromJson(const Util::Json& json, Settings& settings)
|
void fromJson(const Util::Json& json, Settings& settings)
|
||||||
{
|
{
|
||||||
assert(json.type() == Util::Json::Type::Object);
|
VERIFY(json.type() == Util::Json::Type::Object);
|
||||||
|
|
||||||
if (json.exists("ignorePatterns")) {
|
if (json.exists("ignorePatterns")) {
|
||||||
json.at("ignorePatterns").getTo(settings.ignorePatterns);
|
json.at("ignorePatterns").getTo(settings.ignorePatterns);
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,6 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cassert> // assert
|
|
||||||
#include <cctype> // tolower
|
#include <cctype> // tolower
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstdio> // fprintf, printf, stderr
|
#include <cstdio> // fprintf, printf, stderr
|
||||||
@@ -20,6 +19,7 @@
|
|||||||
#include "dotfile.h"
|
#include "dotfile.h"
|
||||||
#include "machine.h"
|
#include "machine.h"
|
||||||
#include "util/file.h"
|
#include "util/file.h"
|
||||||
|
#include "util/meta/assert.h"
|
||||||
|
|
||||||
Dotfile::Dotfile(s)
|
Dotfile::Dotfile(s)
|
||||||
{
|
{
|
||||||
@@ -107,7 +107,7 @@ void Dotfile::push(const std::vector<std::string>& targets)
|
|||||||
|
|
||||||
bool Dotfile::match(const std::string& path, const std::vector<std::string>& patterns)
|
bool Dotfile::match(const std::string& path, const std::vector<std::string>& patterns)
|
||||||
{
|
{
|
||||||
assert(path.front() == '/');
|
VERIFY(path.front() == '/', "path is not absolute: '{}'", path);
|
||||||
|
|
||||||
// Cut off working directory
|
// Cut off working directory
|
||||||
size_t cutFrom = path.find(Config::the().workingDirectory()) == 0 ? Config::the().workingDirectorySize() : 0;
|
size_t cutFrom = path.find(Config::the().workingDirectory()) == 0 ? Config::the().workingDirectorySize() : 0;
|
||||||
|
|||||||
+4
-4
@@ -4,7 +4,6 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cassert> // assert
|
|
||||||
#include <cstdint> // int32_t
|
#include <cstdint> // int32_t
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream> // ifstream, ios, ofstream
|
#include <fstream> // ifstream, ios, ofstream
|
||||||
@@ -12,6 +11,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "util/file.h"
|
#include "util/file.h"
|
||||||
|
#include "util/meta/assert.h"
|
||||||
|
|
||||||
namespace Util {
|
namespace Util {
|
||||||
|
|
||||||
@@ -20,13 +20,13 @@ File::File(const std::string& path)
|
|||||||
{
|
{
|
||||||
// Create input stream object and open file
|
// Create input stream object and open file
|
||||||
std::ifstream file(path, std::ios::in);
|
std::ifstream file(path, std::ios::in);
|
||||||
assert(file.is_open());
|
VERIFY(file.is_open(), "failed to open file: '{}'", path);
|
||||||
|
|
||||||
// Get length of the file
|
// Get length of the file
|
||||||
file.seekg(0, std::ios::end);
|
file.seekg(0, std::ios::end);
|
||||||
int32_t size = file.tellg();
|
int32_t size = file.tellg();
|
||||||
file.seekg(0, std::ios::beg);
|
file.seekg(0, std::ios::beg);
|
||||||
assert(size != -1);
|
VERIFY(size != -1, "failed to read file length: '{}', path");
|
||||||
|
|
||||||
// Allocate memory filled with zeros
|
// Allocate memory filled with zeros
|
||||||
auto buffer = std::make_unique<char[]>(size);
|
auto buffer = std::make_unique<char[]>(size);
|
||||||
@@ -78,7 +78,7 @@ File& File::flush()
|
|||||||
{
|
{
|
||||||
// Create output stream object and open file
|
// Create output stream object and open file
|
||||||
std::ofstream file(m_path, std::ios::out | std::ios::trunc);
|
std::ofstream file(m_path, std::ios::out | std::ios::trunc);
|
||||||
assert(file.is_open());
|
VERIFY(file.is_open(), "failed to open file: '{}'", m_path);
|
||||||
|
|
||||||
// Write data to disk
|
// Write data to disk
|
||||||
file.write(m_data.c_str(), m_data.size());
|
file.write(m_data.c_str(), m_data.size());
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ void Builder::putF32(float number, size_t precision) const
|
|||||||
<< number
|
<< number
|
||||||
<< std::defaultfloat << std::setprecision(6);
|
<< 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('.')));
|
|
||||||
m_builder << string;
|
m_builder << string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +49,6 @@ void Builder::putF64(double number, size_t precision) const
|
|||||||
<< number
|
<< number
|
||||||
<< std::defaultfloat << std::setprecision(6);
|
<< 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('.')));
|
|
||||||
m_builder << string;
|
m_builder << string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdint> // uint8_t
|
||||||
|
#include <cstdio> // FILE, fputs, stdout
|
||||||
|
#include <sstream> // stringstream
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "util/format/color.h"
|
||||||
|
#include "util/format/format.h"
|
||||||
|
#include "util/meta/assert.h"
|
||||||
|
|
||||||
|
namespace Util::Format {
|
||||||
|
|
||||||
|
TextStyle::TextStyle(Emphasis emphasis)
|
||||||
|
: m_emphasis(emphasis)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TextStyle::TextStyle(bool isForeground, TerminalColor color)
|
||||||
|
{
|
||||||
|
if (isForeground) {
|
||||||
|
m_foregroundColor = color;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_backgroundColor = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
TextStyle& TextStyle::operator|=(const TextStyle& rhs)
|
||||||
|
{
|
||||||
|
if (m_foregroundColor == TerminalColor::None) {
|
||||||
|
m_foregroundColor = rhs.m_foregroundColor;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VERIFY(rhs.m_foregroundColor == TerminalColor::None, "can't OR a terminal color");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_backgroundColor == TerminalColor::None) {
|
||||||
|
m_backgroundColor = rhs.m_backgroundColor;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
VERIFY(rhs.m_backgroundColor == TerminalColor::None, "can't OR a terminal color");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_emphasis = static_cast<Emphasis>(static_cast<uint8_t>(m_emphasis) | static_cast<uint8_t>(rhs.m_emphasis));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextStyle fg(TerminalColor foreground)
|
||||||
|
{
|
||||||
|
return TextStyle(true, foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextStyle bg(TerminalColor background)
|
||||||
|
{
|
||||||
|
return TextStyle(false, background);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextStyle operator|(TextStyle lhs, const TextStyle& rhs)
|
||||||
|
{
|
||||||
|
return lhs |= rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextStyle operator|(Emphasis lhs, Emphasis rhs)
|
||||||
|
{
|
||||||
|
return TextStyle { lhs } | rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator&(Emphasis lhs, Emphasis rhs)
|
||||||
|
{
|
||||||
|
return static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void setDisplayAttributes(std::stringstream& stream, const TextStyle& style)
|
||||||
|
{
|
||||||
|
bool hasForeground = style.foregroundColor() != TerminalColor::None;
|
||||||
|
bool hasBackground = style.backgroundColor() != TerminalColor::None;
|
||||||
|
bool hasEmphasis = style.emphasis() != Emphasis::None;
|
||||||
|
if (!hasForeground && !hasBackground && !hasEmphasis) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.write("\033[", 2);
|
||||||
|
|
||||||
|
if (hasForeground) {
|
||||||
|
stream << format("{}", static_cast<uint8_t>(style.foregroundColor()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasBackground) {
|
||||||
|
if (hasForeground) {
|
||||||
|
stream.write(";", 1);
|
||||||
|
}
|
||||||
|
stream << format("{}", static_cast<uint8_t>(style.backgroundColor()) + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.write("m", 1);
|
||||||
|
|
||||||
|
if (hasEmphasis) {
|
||||||
|
|
||||||
|
#define ESCAPE_ATTRIBUTE(escape, attribute) \
|
||||||
|
if (style.emphasis() & escape) { \
|
||||||
|
stream.write("\033[", 2); \
|
||||||
|
stream.write(attribute, 1); \
|
||||||
|
stream.write("m", 1); \
|
||||||
|
}
|
||||||
|
|
||||||
|
ESCAPE_ATTRIBUTE(Emphasis::Bold, "1");
|
||||||
|
ESCAPE_ATTRIBUTE(Emphasis::Faint, "2");
|
||||||
|
ESCAPE_ATTRIBUTE(Emphasis::Italic, "3");
|
||||||
|
ESCAPE_ATTRIBUTE(Emphasis::Underline, "4");
|
||||||
|
ESCAPE_ATTRIBUTE(Emphasis::Blink, "5");
|
||||||
|
ESCAPE_ATTRIBUTE(Emphasis::Reverse, "7");
|
||||||
|
ESCAPE_ATTRIBUTE(Emphasis::Conceal, "8");
|
||||||
|
ESCAPE_ATTRIBUTE(Emphasis::Strikethrough, "9");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void coloredVariadicFormat(std::stringstream& stream, const TextStyle& style, std::string_view format, TypeErasedParameters& parameters)
|
||||||
|
{
|
||||||
|
setDisplayAttributes(stream, style);
|
||||||
|
variadicFormat(stream, format, parameters);
|
||||||
|
stream.write("\033[0m", 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void coloredVariadicPrint(FILE* file, const TextStyle& style, std::string_view format, TypeErasedParameters& parameters)
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
setDisplayAttributes(stream, style);
|
||||||
|
variadicFormat(stream, format, parameters);
|
||||||
|
stream.write("\033[0m", 4);
|
||||||
|
|
||||||
|
std::string string = stream.str();
|
||||||
|
fputs(string.c_str(), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
ColorPrintOperatorStyle::ColorPrintOperatorStyle(FILE* file, const TextStyle& style)
|
||||||
|
: m_file(file)
|
||||||
|
, m_style(style)
|
||||||
|
, m_stream()
|
||||||
|
, m_builder(m_stream)
|
||||||
|
{
|
||||||
|
setDisplayAttributes(m_stream, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorPrintOperatorStyle::~ColorPrintOperatorStyle()
|
||||||
|
{
|
||||||
|
m_stream.write("\033[0m", 4);
|
||||||
|
std::string string = m_stream.str();
|
||||||
|
fputs(string.c_str(), m_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorPrintOperatorStyle print(const TextStyle& style)
|
||||||
|
{
|
||||||
|
return ColorPrintOperatorStyle(stdout, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorPrintOperatorStyle print(FILE* file, const TextStyle& style)
|
||||||
|
{
|
||||||
|
return ColorPrintOperatorStyle(file, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Util::Format
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef> // size_t
|
||||||
|
#include <cstdint> // uint8_t
|
||||||
|
#include <cstdio> // FILE, stdout
|
||||||
|
#include <sstream> // stringstream
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "util/format/format.h"
|
||||||
|
|
||||||
|
namespace Util::Format {
|
||||||
|
|
||||||
|
enum class TerminalColor : uint8_t {
|
||||||
|
None = 0,
|
||||||
|
Black = 30,
|
||||||
|
Red,
|
||||||
|
Green,
|
||||||
|
Yellow,
|
||||||
|
Blue,
|
||||||
|
Magenta,
|
||||||
|
Cyan,
|
||||||
|
White,
|
||||||
|
BrightBlack = 90,
|
||||||
|
BrightRed,
|
||||||
|
BrightGreen,
|
||||||
|
BrightYellow,
|
||||||
|
BrightBlue,
|
||||||
|
BrightMagenta,
|
||||||
|
BrightCyan,
|
||||||
|
BrightWhite
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bit field
|
||||||
|
enum class Emphasis : uint8_t {
|
||||||
|
None = 0, // Attribute 0
|
||||||
|
Bold = 1, // Attribute 1
|
||||||
|
Faint = 1 << 1, // Attribute 2
|
||||||
|
Italic = 1 << 2, // Attribute 3
|
||||||
|
Underline = 1 << 3, // Attribute 4
|
||||||
|
Blink = 1 << 4, // Attribute 5
|
||||||
|
Reverse = 1 << 5, // Attribute 7
|
||||||
|
Conceal = 1 << 6, // Attribute 8
|
||||||
|
Strikethrough = 1 << 7, // Attribute 9
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextStyle {
|
||||||
|
private:
|
||||||
|
friend TextStyle fg(TerminalColor foreground);
|
||||||
|
friend TextStyle bg(TerminalColor background);
|
||||||
|
|
||||||
|
public:
|
||||||
|
TextStyle(Emphasis emphasis);
|
||||||
|
|
||||||
|
// Operator pipe equal, reads the same way as +=
|
||||||
|
TextStyle& operator|=(const TextStyle& rhs);
|
||||||
|
|
||||||
|
TerminalColor foregroundColor() const { return m_foregroundColor; }
|
||||||
|
TerminalColor backgroundColor() const { return m_backgroundColor; }
|
||||||
|
Emphasis emphasis() const { return m_emphasis; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
TextStyle(bool isForeground, TerminalColor color);
|
||||||
|
|
||||||
|
TerminalColor m_foregroundColor { TerminalColor::None };
|
||||||
|
TerminalColor m_backgroundColor { TerminalColor::None };
|
||||||
|
Emphasis m_emphasis { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
TextStyle fg(TerminalColor foreground);
|
||||||
|
TextStyle bg(TerminalColor background);
|
||||||
|
TextStyle operator|(TextStyle lhs, const TextStyle& rhs);
|
||||||
|
TextStyle operator|(Emphasis lhs, Emphasis rhs);
|
||||||
|
bool operator&(Emphasis lhs, Emphasis rhs);
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void coloredVariadicFormat(std::stringstream& stream, const TextStyle& style, std::string_view format, TypeErasedParameters& parameters);
|
||||||
|
|
||||||
|
template<typename... Parameters>
|
||||||
|
std::string format(const TextStyle& style, std::string_view format, const Parameters&... parameters)
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
VariadicParameters variadicParameters { parameters... };
|
||||||
|
coloredVariadicFormat(stream, style, format, variadicParameters);
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Parameters>
|
||||||
|
void formatTo(std::string& output, const TextStyle& style, std::string_view format, const Parameters&... parameters)
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
VariadicParameters variadicParameters { parameters... };
|
||||||
|
coloredVariadicFormat(stream, style, format, variadicParameters);
|
||||||
|
output += stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
void coloredVariadicPrint(FILE* file, const TextStyle& style, std::string_view format, TypeErasedParameters& parameters);
|
||||||
|
|
||||||
|
template<size_t N, typename... Parameters>
|
||||||
|
void print(const TextStyle& style, const char (&format)[N], const Parameters&... parameters)
|
||||||
|
{
|
||||||
|
VariadicParameters variadicParameters { parameters... };
|
||||||
|
coloredVariadicPrint(stdout, style, { format, N - 1 }, variadicParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<size_t N, typename... Parameters>
|
||||||
|
void print(FILE* file, const TextStyle& style, const char (&format)[N], const Parameters&... parameters)
|
||||||
|
{
|
||||||
|
VariadicParameters variadicParameters { parameters... };
|
||||||
|
coloredVariadicPrint(file, style, { format, N - 1 }, variadicParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
class ColorPrintOperatorStyle {
|
||||||
|
public:
|
||||||
|
ColorPrintOperatorStyle(FILE* file, const TextStyle& style);
|
||||||
|
virtual ~ColorPrintOperatorStyle();
|
||||||
|
|
||||||
|
Builder& builder() { return m_builder; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
FILE* m_file;
|
||||||
|
TextStyle m_style;
|
||||||
|
|
||||||
|
std::stringstream m_stream;
|
||||||
|
Builder m_builder;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const ColorPrintOperatorStyle& operator<<(const ColorPrintOperatorStyle& colorPrintOperatorStyle, const T& value)
|
||||||
|
{
|
||||||
|
_format(const_cast<ColorPrintOperatorStyle&>(colorPrintOperatorStyle).builder(), value);
|
||||||
|
return colorPrintOperatorStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorPrintOperatorStyle print(const TextStyle& style);
|
||||||
|
ColorPrintOperatorStyle print(FILE* file, const TextStyle& style);
|
||||||
|
|
||||||
|
} // namespace Util::Format
|
||||||
|
|
||||||
|
namespace Util {
|
||||||
|
|
||||||
|
using Util::Format::format;
|
||||||
|
using Util::Format::formatTo;
|
||||||
|
using Util::Format::print;
|
||||||
|
|
||||||
|
} // namespace Util
|
||||||
@@ -47,21 +47,21 @@ void variadicFormat(std::stringstream& stream, std::string_view format, TypeEras
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
FormatAngleBracket::FormatAngleBracket(std::string& output)
|
FormatOperatorStyle::FormatOperatorStyle(std::string& output)
|
||||||
: m_output(output)
|
: m_output(output)
|
||||||
, m_stream()
|
, m_stream()
|
||||||
, m_builder(m_stream)
|
, m_builder(m_stream)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatAngleBracket::~FormatAngleBracket()
|
FormatOperatorStyle::~FormatOperatorStyle()
|
||||||
{
|
{
|
||||||
m_output = m_stream.str();
|
m_output = m_stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatAngleBracket formatTo(std::string& output)
|
FormatOperatorStyle formatTo(std::string& output)
|
||||||
{
|
{
|
||||||
return FormatAngleBracket(output);
|
return FormatOperatorStyle(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Util::Format
|
} // namespace Util::Format
|
||||||
|
|||||||
@@ -84,10 +84,10 @@ void formatTo(std::string& output, std::string_view format, const Parameters&...
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
class FormatAngleBracket {
|
class FormatOperatorStyle {
|
||||||
public:
|
public:
|
||||||
FormatAngleBracket(std::string& output);
|
FormatOperatorStyle(std::string& output);
|
||||||
virtual ~FormatAngleBracket();
|
virtual ~FormatOperatorStyle();
|
||||||
|
|
||||||
Builder& builder() { return m_builder; }
|
Builder& builder() { return m_builder; }
|
||||||
|
|
||||||
@@ -98,13 +98,13 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const FormatAngleBracket& operator<<(const FormatAngleBracket& formatAngleBracket, const T& value)
|
const FormatOperatorStyle& operator<<(const FormatOperatorStyle& formatOperatorStyle, const T& value)
|
||||||
{
|
{
|
||||||
_format(const_cast<FormatAngleBracket&>(formatAngleBracket).builder(), value);
|
_format(const_cast<FormatOperatorStyle&>(formatOperatorStyle).builder(), value);
|
||||||
return formatAngleBracket;
|
return formatOperatorStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatAngleBracket formatTo(std::string& output);
|
FormatOperatorStyle formatTo(std::string& output);
|
||||||
|
|
||||||
} // namespace Util::Format
|
} // namespace Util::Format
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdio> // FILE
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "util/format/color.h"
|
||||||
|
#include "util/format/log.h"
|
||||||
|
|
||||||
|
namespace Util::Format {
|
||||||
|
|
||||||
|
std::string formatTimeElapsed()
|
||||||
|
{
|
||||||
|
return format("{:.3}s ", s_timer.elapsedNanoseconds() / 1000000000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string formatType(Type type)
|
||||||
|
{
|
||||||
|
std::string output;
|
||||||
|
|
||||||
|
formatTo(output, "[");
|
||||||
|
switch (type) {
|
||||||
|
case Type::Trace:
|
||||||
|
formatTo(output, "trace");
|
||||||
|
break;
|
||||||
|
case Type::Debug:
|
||||||
|
formatTo(output, fg(TerminalColor::Magenta), "debug");
|
||||||
|
break;
|
||||||
|
case Type::Success:
|
||||||
|
formatTo(output, fg(TerminalColor::Green), "success");
|
||||||
|
break;
|
||||||
|
case Type::Info:
|
||||||
|
formatTo(output, fg(TerminalColor::Blue), "info");
|
||||||
|
break;
|
||||||
|
case Type::Warn:
|
||||||
|
formatTo(output, Emphasis::Bold | fg(TerminalColor::Yellow), "warn");
|
||||||
|
break;
|
||||||
|
case Type::Error:
|
||||||
|
formatTo(output, Emphasis::Bold | fg(TerminalColor::Red), "error");
|
||||||
|
break;
|
||||||
|
case Type::Critical:
|
||||||
|
formatTo(output, Emphasis::Bold | fg(TerminalColor::White) | bg(TerminalColor::Red), "critical");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
formatTo(output, "] ");
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
LogOperatorStyle::LogOperatorStyle(FILE* file, Type type)
|
||||||
|
: m_file(file)
|
||||||
|
, m_type(type)
|
||||||
|
, m_stream()
|
||||||
|
, m_builder(m_stream)
|
||||||
|
{
|
||||||
|
m_stream << formatTimeElapsed();
|
||||||
|
m_stream << formatType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogOperatorStyle::~LogOperatorStyle()
|
||||||
|
{
|
||||||
|
m_stream.write("\n", 1);
|
||||||
|
std::string string = m_stream.str();
|
||||||
|
fputs(string.c_str(), m_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogOperatorStyle trace()
|
||||||
|
{
|
||||||
|
return LogOperatorStyle(stdout, Type::Trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogOperatorStyle debug()
|
||||||
|
{
|
||||||
|
return LogOperatorStyle(stdout, Type::Debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogOperatorStyle success()
|
||||||
|
{
|
||||||
|
return LogOperatorStyle(stdout, Type::Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogOperatorStyle info()
|
||||||
|
{
|
||||||
|
return LogOperatorStyle(stdout, Type::Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogOperatorStyle warn()
|
||||||
|
{
|
||||||
|
return LogOperatorStyle(stderr, Type::Warn);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogOperatorStyle error()
|
||||||
|
{
|
||||||
|
return LogOperatorStyle(stderr, Type::Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogOperatorStyle critical()
|
||||||
|
{
|
||||||
|
return LogOperatorStyle(stderr, Type::Critical);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Util::Format
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Riyyi
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdio> // FILE, stderr, stdout
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "util/format/format.h"
|
||||||
|
#include "util/format/print.h"
|
||||||
|
#include "util/timer.h"
|
||||||
|
|
||||||
|
namespace Util::Format {
|
||||||
|
|
||||||
|
static Util::Timer s_timer;
|
||||||
|
|
||||||
|
enum class Type : uint8_t {
|
||||||
|
Trace, // White
|
||||||
|
Debug, // Purple
|
||||||
|
Success, // Green
|
||||||
|
Info, // Blue
|
||||||
|
Warn, // Bold yellow
|
||||||
|
Error, // Bold red
|
||||||
|
Critical, // Bold on red
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string formatTimeElapsed();
|
||||||
|
std::string formatType(Type type);
|
||||||
|
|
||||||
|
#define LOG_FUNCTION(name, file, type) \
|
||||||
|
template<size_t N, typename... Parameters> \
|
||||||
|
void name(const char(&format)[N], const Parameters&... parameters) \
|
||||||
|
{ \
|
||||||
|
print(file, "{}", formatTimeElapsed()); \
|
||||||
|
print(file, "{}", formatType(type)); \
|
||||||
|
VariadicParameters variadicParameters { parameters... }; \
|
||||||
|
print(file, format, variadicParameters); \
|
||||||
|
print(file, "\n"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_FUNCTION(trace, stdout, Type::Trace);
|
||||||
|
LOG_FUNCTION(debug, stdout, Type::Debug);
|
||||||
|
LOG_FUNCTION(success, stdout, Type::Success);
|
||||||
|
LOG_FUNCTION(info, stdout, Type::Info);
|
||||||
|
LOG_FUNCTION(warn, stderr, Type::Warn);
|
||||||
|
LOG_FUNCTION(error, stderr, Type::Error);
|
||||||
|
LOG_FUNCTION(critical, stderr, Type::Critical);
|
||||||
|
|
||||||
|
// -----------------------------------------
|
||||||
|
|
||||||
|
class LogOperatorStyle {
|
||||||
|
public:
|
||||||
|
LogOperatorStyle(FILE* file, Type type);
|
||||||
|
virtual ~LogOperatorStyle();
|
||||||
|
|
||||||
|
Builder& builder() { return m_builder; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
FILE* m_file;
|
||||||
|
Type m_type;
|
||||||
|
|
||||||
|
std::stringstream m_stream;
|
||||||
|
Builder m_builder;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const LogOperatorStyle& operator<<(const LogOperatorStyle& logOperatorStyle, const T& value)
|
||||||
|
{
|
||||||
|
_format(const_cast<LogOperatorStyle&>(logOperatorStyle).builder(), value);
|
||||||
|
return logOperatorStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogOperatorStyle trace();
|
||||||
|
LogOperatorStyle debug();
|
||||||
|
LogOperatorStyle success();
|
||||||
|
LogOperatorStyle info();
|
||||||
|
LogOperatorStyle warn();
|
||||||
|
LogOperatorStyle error();
|
||||||
|
LogOperatorStyle critical();
|
||||||
|
|
||||||
|
} // namespace Util::Format
|
||||||
|
|
||||||
|
namespace Util {
|
||||||
|
|
||||||
|
using Util::Format::critical;
|
||||||
|
using Util::Format::debug;
|
||||||
|
using Util::Format::error;
|
||||||
|
using Util::Format::info;
|
||||||
|
using Util::Format::success;
|
||||||
|
using Util::Format::trace;
|
||||||
|
using Util::Format::warn;
|
||||||
|
|
||||||
|
} // namespace Util
|
||||||
@@ -5,13 +5,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm> // replace
|
#include <algorithm> // replace
|
||||||
#include <cassert> // assert
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "util/format/builder.h"
|
#include "util/format/builder.h"
|
||||||
#include "util/format/parser.h"
|
#include "util/format/parser.h"
|
||||||
|
#include "util/meta/assert.h"
|
||||||
|
|
||||||
namespace Util::Format {
|
namespace Util::Format {
|
||||||
|
|
||||||
@@ -32,8 +32,7 @@ void Parser::checkFormatParameterConsistency()
|
|||||||
{
|
{
|
||||||
size_t length = m_input.length();
|
size_t length = m_input.length();
|
||||||
|
|
||||||
// Format string does not reference all passed parameters
|
VERIFY(length >= m_parameterCount * 2, "format string does not reference all parameters");
|
||||||
assert(length >= m_parameterCount * 2);
|
|
||||||
|
|
||||||
size_t braceOpen = 0;
|
size_t braceOpen = 0;
|
||||||
size_t braceClose = 0;
|
size_t braceClose = 0;
|
||||||
@@ -54,8 +53,7 @@ void Parser::checkFormatParameterConsistency()
|
|||||||
if (peek0 == '{') {
|
if (peek0 == '{') {
|
||||||
braceOpen++;
|
braceOpen++;
|
||||||
|
|
||||||
// Only empty references {} or specified references {:} are valid
|
VERIFY(peek1 == '}' || peek1 == ':', "invalid parameter reference");
|
||||||
assert(peek1 == '}' || peek1 == ':');
|
|
||||||
}
|
}
|
||||||
if (peek0 == '}') {
|
if (peek0 == '}') {
|
||||||
braceClose++;
|
braceClose++;
|
||||||
@@ -65,17 +63,13 @@ void Parser::checkFormatParameterConsistency()
|
|||||||
}
|
}
|
||||||
m_index = 0;
|
m_index = 0;
|
||||||
|
|
||||||
// Extra open braces in format string
|
VERIFY(!(braceOpen < braceClose), "extra open braces in format string");
|
||||||
assert(!(braceOpen < braceClose));
|
|
||||||
|
|
||||||
// Extra closing braces in format string
|
VERIFY(!(braceOpen > braceClose), "extra closing braces in format string");
|
||||||
assert(!(braceOpen > braceClose));
|
|
||||||
|
|
||||||
// Format string does not reference all passed parameters
|
VERIFY(!(braceOpen < m_parameterCount), "format string does not reference all passed parameters");
|
||||||
assert(!(braceOpen < m_parameterCount));
|
|
||||||
|
|
||||||
// Format string references nonexistent parameter
|
VERIFY(!(braceOpen > m_parameterCount), "format string references nonexistent parameter");
|
||||||
assert(!(braceOpen > m_parameterCount));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view Parser::consumeLiteral()
|
std::string_view Parser::consumeLiteral()
|
||||||
@@ -114,7 +108,7 @@ bool Parser::consumeSpecifier(std::string_view& specifier)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!consumeSpecific(':')) {
|
if (!consumeSpecific(':')) {
|
||||||
assert(consumeSpecific('}'));
|
VERIFY(consumeSpecific('}'), "invalid parameter reference");
|
||||||
specifier = "";
|
specifier = "";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+9
-100
@@ -4,7 +4,7 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdio> // FILE, fputs
|
#include <cstdio> // FILE, fputs, stdout, stderr
|
||||||
#include <iomanip> // setprecision
|
#include <iomanip> // setprecision
|
||||||
#include <ios> // defaultfloat, fixed
|
#include <ios> // defaultfloat, fixed
|
||||||
#include <sstream> // stringstream
|
#include <sstream> // stringstream
|
||||||
@@ -15,47 +15,9 @@
|
|||||||
|
|
||||||
namespace Util::Format {
|
namespace Util::Format {
|
||||||
|
|
||||||
void printTimeElapsedAndTypePrefix(std::stringstream& stream, Type type, bool bold)
|
void variadicPrint(FILE* file, std::string_view format, TypeErasedParameters& parameters)
|
||||||
{
|
|
||||||
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;
|
std::stringstream stream;
|
||||||
|
|
||||||
printTimeElapsedAndTypePrefix(stream, type, bold);
|
|
||||||
|
|
||||||
variadicFormat(stream, format, parameters);
|
variadicFormat(stream, format, parameters);
|
||||||
|
|
||||||
std::string string = stream.str();
|
std::string string = stream.str();
|
||||||
@@ -64,80 +26,27 @@ void prettyVariadicFormat(FILE* file, Type type, bool bold, std::string_view for
|
|||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
FormatPrint::FormatPrint(FILE* file, Type type, bool bold)
|
PrintOperatorStyle::PrintOperatorStyle(FILE* file)
|
||||||
: m_file(file)
|
: m_file(file)
|
||||||
, m_type(type)
|
|
||||||
, m_bold(bold)
|
|
||||||
, m_stream()
|
, m_stream()
|
||||||
, m_builder(m_stream)
|
, m_builder(m_stream)
|
||||||
{
|
{
|
||||||
printTimeElapsedAndTypePrefix(m_stream, type, bold);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatPrint::~FormatPrint()
|
PrintOperatorStyle::~PrintOperatorStyle()
|
||||||
{
|
{
|
||||||
std::string string = m_stream.str();
|
std::string string = m_stream.str();
|
||||||
fputs(string.c_str(), stdout);
|
fputs(string.c_str(), m_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatPrint dbg()
|
PrintOperatorStyle print()
|
||||||
{
|
{
|
||||||
return FormatPrint(stdout, Type::None, false);
|
return PrintOperatorStyle(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatPrint dbgb()
|
PrintOperatorStyle print(FILE* file)
|
||||||
{
|
{
|
||||||
return FormatPrint(stdout, Type::None, true);
|
return PrintOperatorStyle(file);
|
||||||
}
|
|
||||||
|
|
||||||
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
|
} // namespace Util::Format
|
||||||
|
|||||||
+27
-82
@@ -4,90 +4,59 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdio> // FILE
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint> // uint8_t
|
||||||
|
#include <cstdio> // FILE, stdout
|
||||||
|
#include <sstream> // stringstream
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include "util/format/format.h"
|
#include "util/format/format.h"
|
||||||
#include "util/timer.h"
|
#include "util/timer.h"
|
||||||
|
|
||||||
namespace Util::Format {
|
namespace Util::Format {
|
||||||
|
|
||||||
static Util::Timer s_timer;
|
void variadicPrint(FILE* file, std::string_view format, TypeErasedParameters& parameters);
|
||||||
|
|
||||||
enum class Type {
|
template<size_t N, typename... Parameters>
|
||||||
None, // Foreground
|
void print(const char (&format)[N], const Parameters&... parameters)
|
||||||
Info, // Blue
|
{
|
||||||
Warn, // Yellow
|
VariadicParameters variadicParameters { parameters... };
|
||||||
Critical, // Red
|
variadicPrint(stdout, { format, N - 1 }, variadicParameters);
|
||||||
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);
|
template<size_t N, typename... Parameters>
|
||||||
FORMAT_FUNCTION(dbgbln, None, true);
|
void print(FILE* file, const char (&format)[N], const Parameters&... parameters)
|
||||||
FORMAT_FUNCTION(infoln, Info, false);
|
{
|
||||||
FORMAT_FUNCTION(infobln, Info, true);
|
VariadicParameters variadicParameters { parameters... };
|
||||||
FORMAT_FUNCTION(warnln, Warn, false);
|
variadicPrint(file, { format, N - 1 }, variadicParameters);
|
||||||
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 {
|
class PrintOperatorStyle {
|
||||||
public:
|
public:
|
||||||
FormatPrint(FILE* file, Type type, bool bold);
|
PrintOperatorStyle(FILE* file);
|
||||||
virtual ~FormatPrint();
|
virtual ~PrintOperatorStyle();
|
||||||
|
|
||||||
Builder& builder() { return m_builder; }
|
Builder& builder() { return m_builder; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FILE* m_file;
|
FILE* m_file;
|
||||||
Type m_type;
|
|
||||||
bool m_bold;
|
|
||||||
|
|
||||||
std::stringstream m_stream;
|
std::stringstream m_stream;
|
||||||
Builder m_builder;
|
Builder m_builder;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const FormatPrint& operator<<(const FormatPrint& formatPrint, const T& value)
|
const PrintOperatorStyle& operator<<(const PrintOperatorStyle& printOperatorStyle, const T& value)
|
||||||
{
|
{
|
||||||
_format(const_cast<FormatPrint&>(formatPrint).builder(), value);
|
_format(const_cast<PrintOperatorStyle&>(printOperatorStyle).builder(), value);
|
||||||
return formatPrint;
|
return printOperatorStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatPrint dbg();
|
PrintOperatorStyle print();
|
||||||
FormatPrint dbgb();
|
PrintOperatorStyle print(FILE* file);
|
||||||
FormatPrint info();
|
|
||||||
FormatPrint infob();
|
|
||||||
FormatPrint warn();
|
|
||||||
FormatPrint warnb();
|
|
||||||
FormatPrint critical();
|
|
||||||
FormatPrint criticalb();
|
|
||||||
FormatPrint success();
|
|
||||||
FormatPrint successb();
|
|
||||||
FormatPrint comment();
|
|
||||||
FormatPrint commentb();
|
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|
||||||
@@ -95,30 +64,6 @@ FormatPrint commentb();
|
|||||||
|
|
||||||
namespace Util {
|
namespace Util {
|
||||||
|
|
||||||
using Util::Format::commentbln;
|
using Util::Format::print;
|
||||||
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
|
} // namespace Util
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <algorithm> // max, min
|
#include <algorithm> // max, min
|
||||||
|
|
||||||
#include "util/genericlexer.h"
|
#include "util/genericlexer.h"
|
||||||
|
#include "util/meta/assert.h"
|
||||||
|
|
||||||
namespace Util {
|
namespace Util {
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ void GenericLexer::retreat(size_t count)
|
|||||||
|
|
||||||
char GenericLexer::consume()
|
char GenericLexer::consume()
|
||||||
{
|
{
|
||||||
assert(!isEOF());
|
VERIFY(!isEOF());
|
||||||
return m_input[m_index++];
|
return m_input[m_index++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cassert> // assert
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // transform
|
#include <algorithm> // transform
|
||||||
#include <cassert> // assert
|
|
||||||
#include <cstddef> // nullptr_t
|
#include <cstddef> // nullptr_t
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -17,6 +16,7 @@
|
|||||||
|
|
||||||
#include "util/json/array.h"
|
#include "util/json/array.h"
|
||||||
#include "util/json/object.h"
|
#include "util/json/object.h"
|
||||||
|
#include "util/meta/assert.h"
|
||||||
#include "util/meta/odr.h"
|
#include "util/meta/odr.h"
|
||||||
|
|
||||||
namespace Util::JSON {
|
namespace Util::JSON {
|
||||||
@@ -33,42 +33,42 @@ void fromJson(const Json& json, Json& value)
|
|||||||
template<typename Json>
|
template<typename Json>
|
||||||
void fromJson(const Json& json, std::nullptr_t& null)
|
void fromJson(const Json& json, std::nullptr_t& null)
|
||||||
{
|
{
|
||||||
assert(json.type() == Json::Type::Null);
|
VERIFY(json.type() == Json::Type::Null);
|
||||||
null = nullptr;
|
null = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Json>
|
template<typename Json>
|
||||||
void fromJson(const Json& json, bool& boolean)
|
void fromJson(const Json& json, bool& boolean)
|
||||||
{
|
{
|
||||||
assert(json.type() == Json::Type::Bool);
|
VERIFY(json.type() == Json::Type::Bool);
|
||||||
boolean = json.asBool();
|
boolean = json.asBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Json>
|
template<typename Json>
|
||||||
void fromJson(const Json& json, int& number)
|
void fromJson(const Json& json, int& number)
|
||||||
{
|
{
|
||||||
assert(json.type() == Json::Type::Number);
|
VERIFY(json.type() == Json::Type::Number);
|
||||||
number = (int)json.asDouble();
|
number = (int)json.asDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Json>
|
template<typename Json>
|
||||||
void fromJson(const Json& json, double& number)
|
void fromJson(const Json& json, double& number)
|
||||||
{
|
{
|
||||||
assert(json.type() == Json::Type::Number);
|
VERIFY(json.type() == Json::Type::Number);
|
||||||
number = json.asDouble();
|
number = json.asDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Json>
|
template<typename Json>
|
||||||
void fromJson(const Json& json, std::string& string)
|
void fromJson(const Json& json, std::string& string)
|
||||||
{
|
{
|
||||||
assert(json.type() == Json::Type::String);
|
VERIFY(json.type() == Json::Type::String);
|
||||||
string = json.asString();
|
string = json.asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Json, typename T>
|
template<typename Json, typename T>
|
||||||
void fromJson(const Json& json, std::vector<T>& array)
|
void fromJson(const Json& json, std::vector<T>& array)
|
||||||
{
|
{
|
||||||
assert(json.type() == Json::Type::Array);
|
VERIFY(json.type() == Json::Type::Array);
|
||||||
array.resize(json.size());
|
array.resize(json.size());
|
||||||
std::transform(
|
std::transform(
|
||||||
json.asArray().elements().begin(),
|
json.asArray().elements().begin(),
|
||||||
@@ -82,7 +82,7 @@ void fromJson(const Json& json, std::vector<T>& array)
|
|||||||
template<typename Json, typename T>
|
template<typename Json, typename T>
|
||||||
void fromJson(const Json& json, std::map<std::string, T>& object)
|
void fromJson(const Json& json, std::map<std::string, T>& object)
|
||||||
{
|
{
|
||||||
assert(json.type() == Json::Type::Object);
|
VERIFY(json.type() == Json::Type::Object);
|
||||||
object.clear();
|
object.clear();
|
||||||
for (const auto& [name, value] : json.asObject().members()) {
|
for (const auto& [name, value] : json.asObject().members()) {
|
||||||
object.emplace(name, value.template get<T>());
|
object.emplace(name, value.template get<T>());
|
||||||
@@ -92,7 +92,7 @@ void fromJson(const Json& json, std::map<std::string, T>& object)
|
|||||||
template<typename Json, typename T>
|
template<typename Json, typename T>
|
||||||
void fromJson(const Json& json, std::unordered_map<std::string, T>& object)
|
void fromJson(const Json& json, std::unordered_map<std::string, T>& object)
|
||||||
{
|
{
|
||||||
assert(json.type() == Json::Type::Object);
|
VERIFY(json.type() == Json::Type::Object);
|
||||||
object.clear();
|
object.clear();
|
||||||
for (const auto& [name, value] : json.asObject().members()) {
|
for (const auto& [name, value] : json.asObject().members()) {
|
||||||
object.emplace(name, value.template get<T>());
|
object.emplace(name, value.template get<T>());
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "util/json/object.h"
|
#include "util/json/object.h"
|
||||||
#include "util/json/parser.h"
|
#include "util/json/parser.h"
|
||||||
#include "util/json/value.h"
|
#include "util/json/value.h"
|
||||||
|
#include "util/meta/assert.h"
|
||||||
|
|
||||||
namespace Util::JSON {
|
namespace Util::JSON {
|
||||||
|
|
||||||
@@ -88,13 +89,13 @@ bool Parser::isEOF()
|
|||||||
|
|
||||||
Token Parser::peek()
|
Token Parser::peek()
|
||||||
{
|
{
|
||||||
assert(!isEOF());
|
VERIFY(!isEOF());
|
||||||
return (*m_tokens)[m_index];
|
return (*m_tokens)[m_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
Token Parser::consume()
|
Token Parser::consume()
|
||||||
{
|
{
|
||||||
assert(!isEOF());
|
VERIFY(!isEOF());
|
||||||
return (*m_tokens)[m_index++];
|
return (*m_tokens)[m_index++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-12
@@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm> // all_of
|
#include <algorithm> // all_of
|
||||||
#include <cassert> // assert
|
|
||||||
#include <cstdint> // uint32_t
|
#include <cstdint> // uint32_t
|
||||||
#include <fstream> // >>
|
#include <fstream> // >>
|
||||||
#include <iostream> // istream, ostream
|
#include <iostream> // istream, ostream
|
||||||
@@ -18,6 +17,7 @@
|
|||||||
#include "util/json/object.h"
|
#include "util/json/object.h"
|
||||||
#include "util/json/serializer.h"
|
#include "util/json/serializer.h"
|
||||||
#include "util/json/value.h"
|
#include "util/json/value.h"
|
||||||
|
#include "util/meta/assert.h"
|
||||||
|
|
||||||
namespace Util::JSON {
|
namespace Util::JSON {
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ void Value::emplace_back(Value value)
|
|||||||
m_value.array = new Array;
|
m_value.array = new Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_type == Type::Array);
|
VERIFY(m_type == Type::Array);
|
||||||
m_value.array->emplace_back(value);
|
m_value.array->emplace_back(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ void Value::emplace(const std::string& key, Value value)
|
|||||||
m_value.object = new Object;
|
m_value.object = new Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_type == Type::Object);
|
VERIFY(m_type == Type::Object);
|
||||||
m_value.object->emplace(key, value);
|
m_value.object->emplace(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +203,7 @@ bool Value::exists(size_t index) const
|
|||||||
|
|
||||||
bool Value::exists(const std::string& key) const
|
bool Value::exists(const std::string& key) const
|
||||||
{
|
{
|
||||||
assert(m_type == Type::Object);
|
VERIFY(m_type == Type::Object);
|
||||||
return m_value.object->members().find(key) != m_value.object->members().end();
|
return m_value.object->members().find(key) != m_value.object->members().end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +217,7 @@ Value& Value::operator[](size_t index)
|
|||||||
m_value.array = new Array;
|
m_value.array = new Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_type == Type::Array);
|
VERIFY(m_type == Type::Array);
|
||||||
return (*m_value.array)[index];
|
return (*m_value.array)[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,43 +229,43 @@ Value& Value::operator[](const std::string& key)
|
|||||||
m_value.object = new Object;
|
m_value.object = new Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(m_type == Type::Object);
|
VERIFY(m_type == Type::Object);
|
||||||
return (*m_value.object)[key];
|
return (*m_value.object)[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value& Value::operator[](size_t index) const
|
const Value& Value::operator[](size_t index) const
|
||||||
{
|
{
|
||||||
assert(m_type == Type::Array);
|
VERIFY(m_type == Type::Array);
|
||||||
return (*m_value.array)[index];
|
return (*m_value.array)[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value& Value::operator[](const std::string& key) const
|
const Value& Value::operator[](const std::string& key) const
|
||||||
{
|
{
|
||||||
assert(m_type == Type::Object);
|
VERIFY(m_type == Type::Object);
|
||||||
return (*m_value.object)[key];
|
return (*m_value.object)[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
Value& Value::at(size_t index)
|
Value& Value::at(size_t index)
|
||||||
{
|
{
|
||||||
assert(m_type == Type::Array);
|
VERIFY(m_type == Type::Array);
|
||||||
return m_value.array->at(index);
|
return m_value.array->at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value& Value::at(const std::string& key)
|
Value& Value::at(const std::string& key)
|
||||||
{
|
{
|
||||||
assert(m_type == Type::Object);
|
VERIFY(m_type == Type::Object);
|
||||||
return m_value.object->at(key);
|
return m_value.object->at(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value& Value::at(size_t index) const
|
const Value& Value::at(size_t index) const
|
||||||
{
|
{
|
||||||
assert(m_type == Type::Array);
|
VERIFY(m_type == Type::Array);
|
||||||
return m_value.array->at(index);
|
return m_value.array->at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value& Value::at(const std::string& key) const
|
const Value& Value::at(const std::string& key) const
|
||||||
{
|
{
|
||||||
assert(m_type == Type::Object);
|
VERIFY(m_type == Type::Object);
|
||||||
return m_value.object->at(key);
|
return m_value.object->at(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,9 @@ inline void __assertion_failed(const char* assertion, const char* file, uint32_t
|
|||||||
if constexpr (sizeof...(Parameters) > 0) {
|
if constexpr (sizeof...(Parameters) > 0) {
|
||||||
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
|
||||||
if (!std::string_view(function).starts_with("Util::Format::")) {
|
std::string_view functionString = function;
|
||||||
|
if (!functionString.starts_with("Util::Format::")
|
||||||
|
&& !functionString.starts_with("Util::GenericLexer::")) {
|
||||||
std::string message;
|
std::string message;
|
||||||
formatTo(message, parameters...);
|
formatTo(message, parameters...);
|
||||||
fprintf(stderr, "%s", message.c_str());
|
fprintf(stderr, "%s", message.c_str());
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ TEST_CASE(FormatNumbers)
|
|||||||
|
|
||||||
float f32R = 245789.70000;
|
float f32R = 245789.70000;
|
||||||
result = Util::format("{}", f32R);
|
result = Util::format("{}", f32R);
|
||||||
EXPECT_EQ(result, "245789.7");
|
EXPECT_EQ(result, "245789.703125");
|
||||||
|
|
||||||
float f32 = 45645.3233;
|
float f32 = 45645.3233;
|
||||||
result = Util::format("{}", f32);
|
result = Util::format("{}", f32);
|
||||||
@@ -93,11 +93,11 @@ TEST_CASE(FormatNumbers)
|
|||||||
|
|
||||||
double f64 = 87522.300000000;
|
double f64 = 87522.300000000;
|
||||||
result = Util::format("{}", f64);
|
result = Util::format("{}", f64);
|
||||||
EXPECT_EQ(result, "87522.3");
|
EXPECT_EQ(result, "87522.300000");
|
||||||
|
|
||||||
double pi = 3.14159265359;
|
double pi = 3.14159265359;
|
||||||
result = Util::format("{:.15}", pi);
|
result = Util::format("{:.15}", pi);
|
||||||
EXPECT_EQ(result, "3.14159265359");
|
EXPECT_EQ(result, "3.141592653590000");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE(FormatContainers)
|
TEST_CASE(FormatContainers)
|
||||||
|
|||||||
Reference in New Issue
Block a user