Riyyi
2 years ago
7 changed files with 0 additions and 854 deletions
@ -1,113 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include <csignal> // raise |
|
||||||
#include <cstdint> // uint32_t |
|
||||||
#include <cstdio> // fflush |
|
||||||
#include <cstring> // strlen |
|
||||||
#include <fstream> // ifstream |
|
||||||
#include <string> |
|
||||||
|
|
||||||
#include "inferno/core.h" |
|
||||||
#include "inferno/io/log.h" |
|
||||||
|
|
||||||
#ifndef NDEBUG |
|
||||||
#define NF_ENABLE_ASSERTS |
|
||||||
#endif |
|
||||||
|
|
||||||
// Asserts
|
|
||||||
#ifdef NF_ENABLE_ASSERTS |
|
||||||
// Check if SIGTRAP is available
|
|
||||||
#ifdef SIGTRAP |
|
||||||
#define ABORT_SIGNAL SIGTRAP // POSIX
|
|
||||||
#else |
|
||||||
#define ABORT_SIGNAL SIGABRT // C99
|
|
||||||
#endif |
|
||||||
|
|
||||||
// Non-standard function macro
|
|
||||||
#ifdef GCC |
|
||||||
#define FUNCTION_MACRO __PRETTY_FUNCTION__ // GCC extension
|
|
||||||
#elif MSVC |
|
||||||
#define FUNCTION_MACRO __FUNCSIG__ |
|
||||||
#else |
|
||||||
#define FUNCTION_MACRO __func__ // C99
|
|
||||||
#endif |
|
||||||
|
|
||||||
// ##__VA_ARGS__ is a non-standard GCC extension, C++20 introduces __VA_OPT__
|
|
||||||
// https://stackoverflow.com/questions/52891546/what-does-va-args-mean
|
|
||||||
#define ASSERT(expr, ...) (static_cast<bool>(expr) ? (void)0 : Inferno::__assert_fail(#expr, __FILE__, __LINE__, FUNCTION_MACRO, ##__VA_ARGS__)) |
|
||||||
#define ASSERT_NOT_REACHED() ASSERT(false) |
|
||||||
#else |
|
||||||
#define ASSERT(expr, ...) (static_cast<void>(0)) |
|
||||||
#define ASSERT_NOT_REACHED() CRASH() |
|
||||||
#endif |
|
||||||
|
|
||||||
#define CRASH() Inferno::__crash(); |
|
||||||
// https://stackoverflow.com/questions/1440570/likely-unlikely-equivalent-for-msvc
|
|
||||||
|
|
||||||
namespace Inferno { |
|
||||||
|
|
||||||
inline void __crash() |
|
||||||
{ |
|
||||||
asm volatile("int $0x03"); |
|
||||||
} |
|
||||||
|
|
||||||
// FIXME: Doesnt print to stderr
|
|
||||||
#ifdef NF_ENABLE_ASSERTS |
|
||||||
template<typename... P> |
|
||||||
inline void __assert_fail(const char* assertion, const char* file, uint32_t line, const char* function, P&&... parameters) |
|
||||||
{ |
|
||||||
(void)function; |
|
||||||
|
|
||||||
// Get the line that caused the error
|
|
||||||
std::ifstream source(file); |
|
||||||
std::string content; |
|
||||||
if (source.is_open()) { |
|
||||||
for (uint32_t i = 0; std::getline(source, content); ++i) { |
|
||||||
if (i == line - 1) { |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
// Replace tab indentation with spaces
|
|
||||||
size_t tabs = content.find_first_not_of('\t'); |
|
||||||
if (tabs > 0 && tabs < content.size()) { |
|
||||||
content = std::string(tabs * 4, ' ') + content.substr(tabs); |
|
||||||
} |
|
||||||
|
|
||||||
// Find the assertion in the line
|
|
||||||
size_t column = content.find_first_of(assertion); |
|
||||||
size_t assertionLength = strlen(assertion); |
|
||||||
if (column == std::string::npos) { |
|
||||||
column = content.find_first_not_of(' '); |
|
||||||
assertionLength = content.length() - column; |
|
||||||
} |
|
||||||
|
|
||||||
// Error message
|
|
||||||
dbgln(false, "\033[0;1m{}:{}:{}: ", file, line, column + 1); |
|
||||||
dangerln(false, "error: "); |
|
||||||
dbgln(false, "assertion failed"); |
|
||||||
if (sizeof...(P) > 0) { |
|
||||||
dbgln(false, ": "); |
|
||||||
dbgln(Log::None, false, std::forward<P>(parameters)...); |
|
||||||
} |
|
||||||
|
|
||||||
// Code line
|
|
||||||
dbgln("\n {} | {}\033[31;1m{}\033[0m{}", line, |
|
||||||
content.substr(0, column), // Whitespace at front
|
|
||||||
content.substr(column, assertionLength), // Error portion
|
|
||||||
content.substr(column + assertionLength)); // Rest of the line
|
|
||||||
|
|
||||||
// Arrow pointer
|
|
||||||
dbgln(" {} | {}\033[31;1m^{}\033[0m", |
|
||||||
std::string(std::to_string(line).length(), ' '), // Line number spacing
|
|
||||||
std::string(column, ' '), // Content spacing
|
|
||||||
std::string(assertionLength - 1, '~')); // Arrow pointer
|
|
||||||
|
|
||||||
fflush(stdout); // FIXME: stdout is buffered, strerr is not so wouldnt need this
|
|
||||||
CRASH(); |
|
||||||
} |
|
||||||
#endif |
|
||||||
|
|
||||||
} // namespace Inferno
|
|
||||||
|
|
||||||
// https://github.com/scottt/debugbreak
|
|
@ -1,48 +0,0 @@ |
|||||||
#include <ios> // std::ios |
|
||||||
#include <memory> // std::make_unique |
|
||||||
|
|
||||||
#include "ruc/meta/assert.h" |
|
||||||
|
|
||||||
#include "inferno/io/file.h" |
|
||||||
|
|
||||||
namespace Inferno { |
|
||||||
|
|
||||||
std::shared_ptr<char[]> File::raw(const std::string& path) |
|
||||||
{ |
|
||||||
// Create input stream object and open file
|
|
||||||
std::ifstream file(path); |
|
||||||
VERIFY(file.is_open(), "File could not open '{}'", path); |
|
||||||
|
|
||||||
// Get length of the file
|
|
||||||
int32_t length = File::length(path, file); |
|
||||||
|
|
||||||
// Allocate memory filled with zeros
|
|
||||||
auto buffer = std::shared_ptr<char[]>(new char[length + 1]); |
|
||||||
|
|
||||||
// Fill buffer with file contents
|
|
||||||
file.read(buffer.get(), length); |
|
||||||
file.close(); |
|
||||||
|
|
||||||
// Null termination
|
|
||||||
buffer[length] = '\0'; |
|
||||||
|
|
||||||
return buffer; |
|
||||||
} |
|
||||||
|
|
||||||
std::string File::read(const std::string& path) |
|
||||||
{ |
|
||||||
// Create string from the buffer and return
|
|
||||||
return std::string(raw(path).get()); |
|
||||||
} |
|
||||||
|
|
||||||
int32_t File::length(const std::string& path, std::ifstream& file) |
|
||||||
{ |
|
||||||
file.seekg(0, std::ios::end); |
|
||||||
int32_t length = file.tellg(); |
|
||||||
file.seekg(0, std::ios::beg); |
|
||||||
VERIFY(length != -1, "File could not determine length '{}'", path); |
|
||||||
|
|
||||||
return length; |
|
||||||
} |
|
||||||
|
|
||||||
} // namespace Inferno
|
|
@ -1,62 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include <fstream> // std::ifstream, std::ofstream |
|
||||||
#include <iomanip> // std::setfill, std::setw |
|
||||||
#include <memory> // std::shared_ptr |
|
||||||
#include <string> // std::string |
|
||||||
|
|
||||||
#include "inferno/core.h" |
|
||||||
#include "inferno/io/log.h" |
|
||||||
#include "ruc/meta/assert.h" |
|
||||||
|
|
||||||
namespace Inferno { |
|
||||||
|
|
||||||
class File { |
|
||||||
public: |
|
||||||
static std::shared_ptr<char[]> raw(const std::string& path); |
|
||||||
static std::string read(const std::string& path); |
|
||||||
static int32_t length(const std::string& path, std::ifstream& file); |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
static bool ioRead(T* t, const std::string& path) |
|
||||||
{ |
|
||||||
std::ifstream file(path); |
|
||||||
VERIFY(file.is_open(), "File could not open '{}'", path); |
|
||||||
|
|
||||||
if (!file.is_open()) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
file >> *t; |
|
||||||
} |
|
||||||
catch (...) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
static bool ioWrite(T* t, const std::string& path) |
|
||||||
{ |
|
||||||
std::ofstream file(path); |
|
||||||
VERIFY(file.is_open(), "File could not open! {}", path); |
|
||||||
|
|
||||||
if (!file.is_open()) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
// Write file with single tabs, nicely formatted
|
|
||||||
file << std::setfill('\t') << std::setw(1) << *t << std::endl; |
|
||||||
} |
|
||||||
catch (...) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
} // namespace Inferno
|
|
@ -1,321 +0,0 @@ |
|||||||
#include <cstddef> // size_t |
|
||||||
#include <cstdio> // fwrite, snprintf |
|
||||||
#include <cstdlib> // malloc, free |
|
||||||
#include <cstring> // memcpy, strlen |
|
||||||
#include <string> // std::string |
|
||||||
#include <string_view> // std::string_view |
|
||||||
|
|
||||||
#include "ruc/meta/assert.h" |
|
||||||
|
|
||||||
#include "inferno/io/log.h" |
|
||||||
|
|
||||||
namespace Inferno { |
|
||||||
|
|
||||||
BufferedLogStream::~BufferedLogStream() |
|
||||||
{ |
|
||||||
// Free buffer memory
|
|
||||||
if (m_capacity > sizeof(m_buffer.stack)) { |
|
||||||
free(m_buffer.heap); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
void BufferedLogStream::grow(size_t bytes) const |
|
||||||
{ |
|
||||||
// Bitwise & ~ example, we use 127 as binary starts at 0
|
|
||||||
// 0b001111111 127 ~
|
|
||||||
// 0b100000100 260 &
|
|
||||||
// -----------
|
|
||||||
// 0b110000000 384
|
|
||||||
// 0b100000100 260 &
|
|
||||||
// -----------
|
|
||||||
// 0b100000000 256
|
|
||||||
|
|
||||||
// Buffer is increased in chunks of 128 bytes
|
|
||||||
size_t newCapacity = (m_count + bytes + BUFFER_SIZE - 1) & ~(BUFFER_SIZE - 1); |
|
||||||
|
|
||||||
unsigned char* newBuffer = static_cast<unsigned char*>(malloc(newCapacity)); |
|
||||||
|
|
||||||
// Copy the non-heap data into the new buffer
|
|
||||||
if (m_capacity <= sizeof(m_buffer.stack)) { |
|
||||||
memcpy(newBuffer, m_buffer.stack, m_count); |
|
||||||
} |
|
||||||
// Copy old heap-buffer data into the new buffer, free old heap-buffer
|
|
||||||
else if (m_buffer.heap) { |
|
||||||
memcpy(newBuffer, m_buffer.heap, m_count); |
|
||||||
free(m_buffer.heap); |
|
||||||
} |
|
||||||
|
|
||||||
m_buffer.heap = newBuffer; |
|
||||||
m_capacity = newCapacity; |
|
||||||
} |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
DebugLogStream::~DebugLogStream() |
|
||||||
{ |
|
||||||
if (m_type != Log::None) { |
|
||||||
const char* clear = "\033[0m"; |
|
||||||
write(clear, strlen(clear)); |
|
||||||
} |
|
||||||
|
|
||||||
if (m_newline) { |
|
||||||
char newline = '\n'; |
|
||||||
write(&newline, 1); |
|
||||||
} |
|
||||||
|
|
||||||
fwrite(buffer(), 1, count(), stdout); |
|
||||||
} |
|
||||||
|
|
||||||
void DebugLogStream::color() const |
|
||||||
{ |
|
||||||
const char* color = ""; |
|
||||||
|
|
||||||
if (m_type == Log::Info) { |
|
||||||
color = "\x1B[34m"; |
|
||||||
} |
|
||||||
else if (m_type == Log::Warn) { |
|
||||||
color = "\x1B[33m"; |
|
||||||
} |
|
||||||
else if (m_type == Log::Danger) { |
|
||||||
color = "\x1B[31m"; |
|
||||||
} |
|
||||||
else if (m_type == Log::Success) { |
|
||||||
color = "\x1B[32m"; |
|
||||||
} |
|
||||||
else if (m_type == Log::Comment) { |
|
||||||
color = "\x1B[37m"; |
|
||||||
} |
|
||||||
|
|
||||||
write(color, strlen(color)); |
|
||||||
} |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
StringLogStream::~StringLogStream() |
|
||||||
{ |
|
||||||
char terminator = '\0'; |
|
||||||
write(&terminator, 1); |
|
||||||
*m_fill = std::string(reinterpret_cast<char*>(buffer())); |
|
||||||
} |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, const char* value) |
|
||||||
{ |
|
||||||
if (value == nullptr) { |
|
||||||
stream.write("(null)", 6); |
|
||||||
return stream; |
|
||||||
} |
|
||||||
|
|
||||||
stream.write(value, strlen(value)); |
|
||||||
return stream; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, const unsigned char* value) |
|
||||||
{ |
|
||||||
if (value == nullptr) { |
|
||||||
stream.write("(null)", 6); |
|
||||||
return stream; |
|
||||||
} |
|
||||||
|
|
||||||
stream.write(value, strlen((const char*)value)); |
|
||||||
return stream; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, const std::string& value) |
|
||||||
{ |
|
||||||
stream.write(value.c_str(), value.length()); |
|
||||||
return stream; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, const std::string_view& value) |
|
||||||
{ |
|
||||||
stream.write(value.data(), value.length()); |
|
||||||
return stream; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, char value) |
|
||||||
{ |
|
||||||
stream.write(&value, 1); |
|
||||||
return stream; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, unsigned char value) |
|
||||||
{ |
|
||||||
stream.write(&value, 1); |
|
||||||
return stream; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, int value) |
|
||||||
{ |
|
||||||
// return stream << std::to_string(value);
|
|
||||||
|
|
||||||
char buffer[32]; |
|
||||||
snprintf(buffer, sizeof(buffer), "%d", value); |
|
||||||
return stream << buffer; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, long int value) |
|
||||||
{ |
|
||||||
char buffer[32]; |
|
||||||
snprintf(buffer, sizeof(buffer), "%ld", value); |
|
||||||
return stream << buffer; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, long long int value) |
|
||||||
{ |
|
||||||
char buffer[32]; |
|
||||||
snprintf(buffer, sizeof(buffer), "%lld", value); |
|
||||||
return stream << buffer; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, unsigned int value) |
|
||||||
{ |
|
||||||
char buffer[32]; |
|
||||||
snprintf(buffer, sizeof(buffer), "%u", value); |
|
||||||
return stream << buffer; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, long unsigned int value) |
|
||||||
{ |
|
||||||
char buffer[32]; |
|
||||||
snprintf(buffer, sizeof(buffer), "%lu", value); |
|
||||||
return stream << buffer; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, long long unsigned int value) |
|
||||||
{ |
|
||||||
char buffer[32]; |
|
||||||
snprintf(buffer, sizeof(buffer), "%llu", value); |
|
||||||
return stream << buffer; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, double value) |
|
||||||
{ |
|
||||||
char buffer[32]; |
|
||||||
snprintf(buffer, sizeof(buffer), "%.4f", value); |
|
||||||
return stream << buffer; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, float value) |
|
||||||
{ |
|
||||||
char buffer[32]; |
|
||||||
snprintf(buffer, sizeof(buffer), "%.4f", value); |
|
||||||
return stream << buffer; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, const void* value) |
|
||||||
{ |
|
||||||
char buffer[32]; |
|
||||||
snprintf(buffer, sizeof(buffer), "%p", value); |
|
||||||
return stream << buffer; |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, bool value) |
|
||||||
{ |
|
||||||
return stream << (value ? "true" : "false"); |
|
||||||
} |
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, Log value) |
|
||||||
{ |
|
||||||
switch (value) { |
|
||||||
case Log::None: |
|
||||||
return stream << "Log"; |
|
||||||
case Log::Info: |
|
||||||
return stream << "Info"; |
|
||||||
case Log::Warn: |
|
||||||
return stream << "Warn"; |
|
||||||
case Log::Danger: |
|
||||||
return stream << "Danger"; |
|
||||||
case Log::Success: |
|
||||||
return stream << "Success"; |
|
||||||
case Log::Comment: |
|
||||||
return stream << "Comment"; |
|
||||||
default: |
|
||||||
VERIFY_NOT_REACHED(); |
|
||||||
return stream; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
DebugLogStream dbg() |
|
||||||
{ |
|
||||||
return {}; |
|
||||||
} |
|
||||||
|
|
||||||
DebugLogStream dbg(bool newline) |
|
||||||
{ |
|
||||||
return DebugLogStream(newline); |
|
||||||
} |
|
||||||
|
|
||||||
DebugLogStream info() |
|
||||||
{ |
|
||||||
return DebugLogStream(Log::Info); |
|
||||||
} |
|
||||||
|
|
||||||
DebugLogStream warn() |
|
||||||
{ |
|
||||||
return DebugLogStream(Log::Warn); |
|
||||||
} |
|
||||||
|
|
||||||
DebugLogStream danger() |
|
||||||
{ |
|
||||||
return DebugLogStream(Log::Danger); |
|
||||||
} |
|
||||||
|
|
||||||
DebugLogStream success() |
|
||||||
{ |
|
||||||
return DebugLogStream(Log::Success); |
|
||||||
} |
|
||||||
|
|
||||||
DebugLogStream comment() |
|
||||||
{ |
|
||||||
return DebugLogStream(Log::Comment); |
|
||||||
} |
|
||||||
|
|
||||||
DebugLogStream info(bool newline) |
|
||||||
{ |
|
||||||
return DebugLogStream(Log::Info, newline); |
|
||||||
} |
|
||||||
|
|
||||||
DebugLogStream warn(bool newline) |
|
||||||
{ |
|
||||||
return DebugLogStream(Log::Warn, newline); |
|
||||||
} |
|
||||||
|
|
||||||
DebugLogStream danger(bool newline) |
|
||||||
{ |
|
||||||
return DebugLogStream(Log::Danger, newline); |
|
||||||
} |
|
||||||
|
|
||||||
DebugLogStream success(bool newline) |
|
||||||
{ |
|
||||||
return DebugLogStream(Log::Success, newline); |
|
||||||
} |
|
||||||
|
|
||||||
DebugLogStream comment(bool newline) |
|
||||||
{ |
|
||||||
return DebugLogStream(Log::Comment, newline); |
|
||||||
} |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
void dbgln(Log type, bool newline) |
|
||||||
{ |
|
||||||
(void)type, DebugLogStream(newline); |
|
||||||
} |
|
||||||
|
|
||||||
void dbgln(Log type, bool newline, const char* format) |
|
||||||
{ |
|
||||||
DebugLogStream(type, newline) << format; |
|
||||||
} |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
StringLogStream str(std::string* fill) |
|
||||||
{ |
|
||||||
return StringLogStream(fill); |
|
||||||
} |
|
||||||
|
|
||||||
} // namespace Inferno
|
|
@ -1,240 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include <cstddef> // size_t |
|
||||||
#include <cstring> // memcpy |
|
||||||
#include <string> // std::string |
|
||||||
#include <string_view> // std::string_view |
|
||||||
#include <utility> // std::forward |
|
||||||
|
|
||||||
#define BUFFER_SIZE 128 |
|
||||||
|
|
||||||
namespace Inferno { |
|
||||||
|
|
||||||
enum class Log { |
|
||||||
None, |
|
||||||
Info, |
|
||||||
Warn, |
|
||||||
Danger, |
|
||||||
Success, |
|
||||||
Comment, |
|
||||||
}; |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
class LogStream { |
|
||||||
public: |
|
||||||
LogStream() {} |
|
||||||
virtual ~LogStream() {} |
|
||||||
|
|
||||||
virtual void write(const char* characters, int length) const = 0; |
|
||||||
virtual void write(const unsigned char* characters, int length) const = 0; |
|
||||||
}; |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
class BufferedLogStream : public LogStream { |
|
||||||
public: |
|
||||||
BufferedLogStream() {} |
|
||||||
virtual ~BufferedLogStream(); |
|
||||||
|
|
||||||
inline virtual void write(const char* characters, int length) const override |
|
||||||
{ |
|
||||||
write(reinterpret_cast<const unsigned char*>(characters), length); |
|
||||||
} |
|
||||||
|
|
||||||
inline virtual void write(const unsigned char* characters, int length) const override |
|
||||||
{ |
|
||||||
size_t newSize = m_count + length; |
|
||||||
|
|
||||||
if (newSize > m_capacity) { |
|
||||||
grow(length); |
|
||||||
} |
|
||||||
|
|
||||||
// Append to buffer
|
|
||||||
memcpy(buffer() + m_count, characters, length); |
|
||||||
|
|
||||||
m_count = newSize; |
|
||||||
} |
|
||||||
|
|
||||||
protected: |
|
||||||
inline unsigned char* buffer() const |
|
||||||
{ |
|
||||||
if (m_capacity <= sizeof(m_buffer.stack)) { |
|
||||||
return m_buffer.stack; |
|
||||||
} |
|
||||||
|
|
||||||
return m_buffer.heap; |
|
||||||
} |
|
||||||
|
|
||||||
inline bool empty() const { return m_count == 0; } |
|
||||||
inline size_t count() const { return m_count; } |
|
||||||
|
|
||||||
private: |
|
||||||
void grow(size_t bytes) const; |
|
||||||
|
|
||||||
mutable size_t m_count { 0 }; |
|
||||||
mutable size_t m_capacity { BUFFER_SIZE }; |
|
||||||
union { |
|
||||||
mutable unsigned char* heap { nullptr }; |
|
||||||
mutable unsigned char stack[BUFFER_SIZE]; |
|
||||||
} m_buffer; |
|
||||||
}; |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
class DebugLogStream final : public BufferedLogStream { |
|
||||||
public: |
|
||||||
DebugLogStream() |
|
||||||
: m_newline(true) |
|
||||||
, m_type(Log::None) |
|
||||||
{ |
|
||||||
} |
|
||||||
DebugLogStream(bool newline) |
|
||||||
: m_newline(newline) |
|
||||||
, m_type(Log::None) |
|
||||||
{ |
|
||||||
} |
|
||||||
DebugLogStream(Log type) |
|
||||||
: m_newline(true) |
|
||||||
, m_type(type) |
|
||||||
{ |
|
||||||
color(); |
|
||||||
} |
|
||||||
DebugLogStream(Log type, bool newline) |
|
||||||
: m_newline(newline) |
|
||||||
, m_type(type) |
|
||||||
{ |
|
||||||
color(); |
|
||||||
} |
|
||||||
virtual ~DebugLogStream() override; |
|
||||||
|
|
||||||
void color() const; |
|
||||||
|
|
||||||
private: |
|
||||||
bool m_newline; |
|
||||||
Log m_type; |
|
||||||
}; |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
class StringLogStream final : public BufferedLogStream { |
|
||||||
public: |
|
||||||
StringLogStream(std::string* fill) |
|
||||||
: m_fill(fill) |
|
||||||
{ |
|
||||||
} |
|
||||||
virtual ~StringLogStream() override; |
|
||||||
|
|
||||||
private: |
|
||||||
std::string* m_fill { nullptr }; |
|
||||||
}; |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
const LogStream& operator<<(const LogStream& stream, const char* value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, const unsigned char* value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, const std::string& value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, const std::string_view& value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, char value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, unsigned char value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, int value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, long int value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, long long int value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, unsigned int value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, long unsigned int value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, long long unsigned int value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, double value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, float value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, const void* value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, bool value); |
|
||||||
const LogStream& operator<<(const LogStream& stream, Log value); |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
DebugLogStream dbg(); |
|
||||||
DebugLogStream info(); |
|
||||||
DebugLogStream warn(); |
|
||||||
DebugLogStream danger(); |
|
||||||
DebugLogStream success(); |
|
||||||
DebugLogStream comment(); |
|
||||||
|
|
||||||
DebugLogStream dbg(bool newline); |
|
||||||
DebugLogStream info(bool newline); |
|
||||||
DebugLogStream warn(bool newline); |
|
||||||
DebugLogStream danger(bool newline); |
|
||||||
DebugLogStream success(bool newline); |
|
||||||
DebugLogStream comment(bool newline); |
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
template<typename... P> void dbgln(const char* format, P&&... parameters) { dbgln(Log::None, true, format, std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void infoln(const char* format, P&&... parameters) { dbgln(Log::Info, true, format, std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void warnln(const char* format, P&&... parameters) { dbgln(Log::Warn, true, format, std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void dangerln(const char* format, P&&... parameters) { dbgln(Log::Danger, true, format, std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void successln(const char* format, P&&... parameters) { dbgln(Log::Success, true, format, std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void commentln(const char* format, P&&... parameters) { dbgln(Log::Comment, true, format, std::forward<P>(parameters)...); } |
|
||||||
|
|
||||||
template<typename... P> void dbgln(const std::string& format, P&&... parameters) { dbgln(Log::None, true, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void infoln(const std::string& format, P&&... parameters) { dbgln(Log::Info, true, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void warnln(const std::string& format, P&&... parameters) { dbgln(Log::Warn, true, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void dangerln(const std::string& format, P&&... parameters) { dbgln(Log::Danger, true, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void successln(const std::string& format, P&&... parameters) { dbgln(Log::Success, true, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void commentln(const std::string& format, P&&... parameters) { dbgln(Log::Comment, true, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
|
|
||||||
template<typename... P> void dbgln(const std::string_view& format, P&&... parameters) { dbgln(Log::None, true, format.data(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void infoln(const std::string_view& format, P&&... parameters) { dbgln(Log::Info, true, format.data(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void warnln(const std::string_view& format, P&&... parameters) { dbgln(Log::Warn, true, format.data(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void dangerln(const std::string_view& format, P&&... parameters) { dbgln(Log::Danger, true, format.data(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void successln(const std::string_view& format, P&&... parameters) { dbgln(Log::Success, true, format.data(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void commentln(const std::string_view& format, P&&... parameters) { dbgln(Log::Comment, true, format.data(), std::forward<P>(parameters)...); } |
|
||||||
|
|
||||||
template<typename... P> void dbgln(bool newline, const char* format, P&&... parameters) { dbgln(Log::None, newline, format, std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void infoln(bool newline, const char* format, P&&... parameters) { dbgln(Log::Info, newline, format, std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void warnln(bool newline, const char* format, P&&... parameters) { dbgln(Log::Warn, newline, format, std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void dangerln(bool newline, const char* format, P&&... parameters) { dbgln(Log::Danger, newline, format, std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void successln(bool newline, const char* format, P&&... parameters) { dbgln(Log::Success, newline, format, std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void commentln(bool newline, const char* format, P&&... parameters) { dbgln(Log::Comment, newline, format, std::forward<P>(parameters)...); } |
|
||||||
|
|
||||||
template<typename... P> void dbgln(bool newline, const std::string& format, P&&... parameters) { dbgln(Log::None, newline, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void infoln(bool newline, const std::string& format, P&&... parameters) { dbgln(Log::Info, newline, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void warnln(bool newline, const std::string& format, P&&... parameters) { dbgln(Log::Warn, newline, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void dangerln(bool newline, const std::string& format, P&&... parameters) { dbgln(Log::Danger, newline, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void successln(bool newline, const std::string& format, P&&... parameters) { dbgln(Log::Success, newline, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void commentln(bool newline, const std::string& format, P&&... parameters) { dbgln(Log::Comment, newline, format.c_str(), std::forward<P>(parameters)...); } |
|
||||||
|
|
||||||
template<typename... P> void dbgln(bool newline, const std::string_view& format, P&&... parameters) { dbgln(Log::None, newline, format.data(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void infoln(bool newline, const std::string_view& format, P&&... parameters) { dbgln(Log::Info, newline, format.data(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void warnln(bool newline, const std::string_view& format, P&&... parameters) { dbgln(Log::Warn, newline, format.data(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void dangerln(bool newline, const std::string_view& format, P&&... parameters) { dbgln(Log::Danger, newline, format.data(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void successln(bool newline, const std::string_view& format, P&&... parameters) { dbgln(Log::Success, newline, format.data(), std::forward<P>(parameters)...); } |
|
||||||
template<typename... P> void commentln(bool newline, const std::string_view& format, P&&... parameters) { dbgln(Log::Comment, newline, format.data(), std::forward<P>(parameters)...); } |
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
void dbgln(Log type, bool newline); |
|
||||||
void dbgln(Log type, bool newline, const char* format); |
|
||||||
|
|
||||||
// https://en.cppreference.com/w/cpp/language/parameter_pack#Example
|
|
||||||
template<typename T, typename... P> |
|
||||||
void dbgln(Log type, bool newline, const char* format, T value, P&&... parameters) |
|
||||||
{ |
|
||||||
std::string_view view { format }; |
|
||||||
|
|
||||||
for (uint32_t i = 0; format[i] != '\0'; i++) { |
|
||||||
|
|
||||||
if (format[i] == '{' && format[i + 1] == '}') { |
|
||||||
DebugLogStream(type, false) << view.substr(0, i) << value; |
|
||||||
dbgln(type, newline, format + i + 2, parameters...); |
|
||||||
return; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
// possible c++17 improvent https://riptutorial.com/cplusplus/example/3208/iterating-over-a-parameter-pack
|
|
||||||
|
|
||||||
// -----------------------------------------
|
|
||||||
|
|
||||||
StringLogStream str(std::string* fill); |
|
||||||
|
|
||||||
} // namespace Inferno
|
|
@ -1,51 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include "ruc/meta/assert.h" |
|
||||||
|
|
||||||
namespace Inferno { |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
class Singleton { |
|
||||||
// Application is allowed to access its Singleton instance for early setting
|
|
||||||
friend class Application; |
|
||||||
|
|
||||||
public: |
|
||||||
static inline void initialize() |
|
||||||
{ |
|
||||||
VERIFY(!s_instance, "singleton already exists"); |
|
||||||
s_instance = new T { s {} }; |
|
||||||
} |
|
||||||
|
|
||||||
static inline void destroy() |
|
||||||
{ |
|
||||||
VERIFY(s_instance, "singleton does not exist"); |
|
||||||
delete s_instance; |
|
||||||
s_instance = nullptr; |
|
||||||
} |
|
||||||
|
|
||||||
static inline T& the() |
|
||||||
{ |
|
||||||
VERIFY(s_instance, "singleton does not exist"); |
|
||||||
return *s_instance; |
|
||||||
} |
|
||||||
|
|
||||||
// Remove copy constructor and copy assignment operator
|
|
||||||
Singleton(const Singleton&) = delete; |
|
||||||
Singleton& operator=(const Singleton&) = delete; |
|
||||||
Singleton(Singleton&&) = delete; |
|
||||||
Singleton& operator=(Singleton&&) = delete; |
|
||||||
|
|
||||||
protected: |
|
||||||
Singleton() {} |
|
||||||
|
|
||||||
// Constructor token
|
|
||||||
struct s {}; |
|
||||||
|
|
||||||
private: |
|
||||||
static T* s_instance; |
|
||||||
}; |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
T* Singleton<T>::s_instance = nullptr; |
|
||||||
|
|
||||||
} // namespace Inferno
|
|
@ -1,19 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include <iomanip> // std::setfill, std::setw |
|
||||||
#include <sstream> // std::stringstream |
|
||||||
|
|
||||||
namespace Inferno { |
|
||||||
|
|
||||||
template<typename T> |
|
||||||
std::string intToHex(T i) |
|
||||||
{ |
|
||||||
std::stringstream stream; |
|
||||||
stream << "0x" |
|
||||||
<< std::setfill('0') << std::setw(sizeof(T) * 2) |
|
||||||
<< std::hex << i; |
|
||||||
|
|
||||||
return stream.str(); |
|
||||||
} |
|
||||||
|
|
||||||
} // namespace Inferno
|
|
Loading…
Reference in new issue