New logger
This commit is contained in:
@@ -83,7 +83,7 @@ class EventSystem {
|
||||
this->eventDelegates[eventType] =
|
||||
std::make_unique<std::any>(EventDelegate<E>());
|
||||
|
||||
log::trace("EventSystem creating new event type: ", eventType);
|
||||
log::trace("EventSystem creating new event type: {}", eventType);
|
||||
}
|
||||
|
||||
EventDelegate<E>& delegate =
|
||||
@@ -102,7 +102,7 @@ class EventSystem {
|
||||
this->eventDelegates[eventType] =
|
||||
std::make_unique<std::any>(EventDelegate<E>());
|
||||
|
||||
log::trace("EventSystem creating new event type: ", eventType);
|
||||
log::trace("EventSystem creating new event type: {}", eventType);
|
||||
}
|
||||
|
||||
EventDelegate<E>& delegate =
|
||||
@@ -124,12 +124,14 @@ class EventSystem {
|
||||
std::any_cast<EventDelegate<E>&>(*this->eventDelegates.at(eventType));
|
||||
delegate.invoke(event);
|
||||
} catch (const std::out_of_range& error) {
|
||||
log::error("event dispatch failed: ", event.toString());
|
||||
log::error("event dispatch failed: {}", event.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
EventSystem() { log::info("EventSystem Initialized: ", this); }
|
||||
EventSystem() {
|
||||
log::info("EventSystem Initialized: {}", static_cast<const void*>(this));
|
||||
}
|
||||
~EventSystem() { log::info("EventSystem Destroyed"); }
|
||||
|
||||
std::unordered_map<EventType, std::unique_ptr<std::any>> eventDelegates;
|
||||
|
||||
@@ -38,7 +38,7 @@ class PanelRegistry {
|
||||
const T& get(PanelHandle handle) const {
|
||||
const Panel& panel = get(handle);
|
||||
SOPHIA_ASSERT(dynamic_cast<const T*>(&panel) != nullptr,
|
||||
"PanelHandle does not refer to a", typeid(T).name());
|
||||
"PanelHandle does not refer to a {}", typeid(T).name());
|
||||
return static_cast<const T&>(panel);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
/**
|
||||
* Usage:
|
||||
* SOPHIA_ASSERT(pipelineLayout != nullptr);
|
||||
* SOPHIA_ASSERT(index < count, "index", index, "out of bounds:", count);
|
||||
* SOPHIA_ASSERT(index < count, "index {} out of bounds: {}", index, count);
|
||||
*
|
||||
* The optional message is a std::format string, checked at compile time.
|
||||
*
|
||||
* Compiled out entirely in release (NDEBUG) builds, matching <cassert>'s
|
||||
* assert() semantics: don't rely on side effects inside the condition.
|
||||
@@ -10,16 +12,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <format>
|
||||
#include <sophia/util/logger.hpp>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define SOPHIA_ASSERT(condition, ...) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
::sophia::log::fatal("Assertion failed:", #condition, "at", __FILE__, \
|
||||
":", __LINE__ __VA_OPT__(, ) __VA_ARGS__); \
|
||||
std::abort(); \
|
||||
} \
|
||||
#define SOPHIA_ASSERT(condition, ...) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
::sophia::log::fatal( \
|
||||
"Assertion failed: {} at {}:{}" __VA_OPT__(" - {}"), #condition, \
|
||||
__FILE__, __LINE__ __VA_OPT__(, ::std::format(__VA_ARGS__))); \
|
||||
std::abort(); \
|
||||
} \
|
||||
} while (false)
|
||||
#else
|
||||
#define SOPHIA_ASSERT(condition, ...) ((void)0)
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sophia/util/logger.hpp>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
|
||||
#include <sophia/util/logger.hpp>
|
||||
|
||||
#define DEFAULT_DELEGATE_FUNCTOR_ALLOC 5
|
||||
|
||||
namespace sophia {
|
||||
@@ -39,7 +38,9 @@ class expired_weak_object : public std::runtime_error {
|
||||
template <class O, typename... A>
|
||||
std::function<void(A...)> createWeakFunction(void (O::*method)(A...),
|
||||
std::shared_ptr<O> obj) {
|
||||
if (!obj) { throw std::invalid_argument("method and obj must not be null"); }
|
||||
if (!obj) {
|
||||
throw std::invalid_argument("method and obj must not be null");
|
||||
}
|
||||
|
||||
std::weak_ptr<O> weakObj = obj;
|
||||
|
||||
@@ -82,7 +83,7 @@ class Delegate {
|
||||
try {
|
||||
this->functors[i](std::forward<A>(args)...);
|
||||
} catch (const expired_weak_object& e) {
|
||||
log::error("delegate invoke error: ", e.what());
|
||||
log::error("delegate invoke error: {}", e.what());
|
||||
deadFunctorIndexs.push_back(i);
|
||||
}
|
||||
}
|
||||
@@ -97,7 +98,9 @@ class Delegate {
|
||||
void operator=(Functor c) {
|
||||
clear();
|
||||
|
||||
if (c != nullptr) { add(c); }
|
||||
if (c != nullptr) {
|
||||
add(c);
|
||||
}
|
||||
}
|
||||
|
||||
void operator+=(Functor c) { add(c); }
|
||||
|
||||
@@ -1,23 +1,36 @@
|
||||
/**
|
||||
* Lots of work still needs to be done in here.
|
||||
* std::format-style logging. Format strings are checked at compile time.
|
||||
*
|
||||
* Usage:
|
||||
* using namespace sophia;
|
||||
* log::fatal("fatal message")
|
||||
* log::info("Infomation message")
|
||||
* log::fatal("failed to load {}", path)
|
||||
* log::info("loaded {} meshes in {:.2f}ms", count, ms)
|
||||
* log::debug("value: {}", x) // prefixed with file:line
|
||||
* log::print("no prefix, just the message")
|
||||
*
|
||||
* Everything is compiled out in release (NDEBUG) builds.
|
||||
*
|
||||
* TODO Impl some form of log error handling
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <sophia/types.hpp>
|
||||
#include <cstdio>
|
||||
#include <format>
|
||||
#include <print>
|
||||
#include <source_location>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace sophia::log {
|
||||
|
||||
#ifndef NDEBUG
|
||||
inline constexpr bool enabled = true;
|
||||
#else
|
||||
inline constexpr bool enabled = false;
|
||||
#endif // !NDEBUG
|
||||
|
||||
enum class LEVEL {
|
||||
NONE,
|
||||
FATAL,
|
||||
@@ -29,118 +42,113 @@ enum class LEVEL {
|
||||
TRACE,
|
||||
};
|
||||
|
||||
// Helper print functions
|
||||
#define LOG_PRINT_HELPER(MSG) std::cout << MSG
|
||||
#define LOG_PREFIX_FATAL LOG_PRINT_HELPER("\033[1;91m[FATAL]\033[0m ")
|
||||
#define LOG_PREFIX_ERROR LOG_PRINT_HELPER("\033[1;31m[ERROR]\033[0m ")
|
||||
#define LOG_PREFIX_WARNING LOG_PRINT_HELPER("\033[1;33m[WARNING]\033[0m ")
|
||||
#define LOG_PREFIX_INFO LOG_PRINT_HELPER("\033[32m[INFO]\033[0m ")
|
||||
#define LOG_PREFIX_VERBOSE LOG_PRINT_HELPER("\033[36m[VERBOSE]\033[0m ")
|
||||
#define LOG_PREFIX_DEBUG LOG_PRINT_HELPER("\033[1;34m[DEBUG]\033[0m ")
|
||||
#define LOG_PREFIX_TRACE LOG_PRINT_HELPER("\033[1;90m[TRACE]\033[0m ")
|
||||
namespace detail {
|
||||
|
||||
template <typename... Args>
|
||||
void log(LEVEL level = LEVEL::NONE, Args... args) {
|
||||
#ifndef NDEBUG
|
||||
constexpr std::string_view prefix(LEVEL level) {
|
||||
switch (level) {
|
||||
case LEVEL::FATAL:
|
||||
LOG_PREFIX_FATAL;
|
||||
break;
|
||||
return "\033[1;91m[FATAL]\033[0m ";
|
||||
case LEVEL::ERROR:
|
||||
LOG_PREFIX_ERROR;
|
||||
break;
|
||||
return "\033[1;31m[ERROR]\033[0m ";
|
||||
case LEVEL::WARNING:
|
||||
LOG_PREFIX_WARNING;
|
||||
break;
|
||||
return "\033[1;33m[WARNING]\033[0m ";
|
||||
case LEVEL::INFO:
|
||||
LOG_PREFIX_INFO;
|
||||
break;
|
||||
return "\033[32m[INFO]\033[0m ";
|
||||
case LEVEL::VERBOSE:
|
||||
LOG_PREFIX_VERBOSE;
|
||||
break;
|
||||
// case LEVEL::DEBUGGING:
|
||||
// LOG_PREFIX_DEBUG;
|
||||
// break;
|
||||
return "\033[36m[VERBOSE]\033[0m ";
|
||||
case LEVEL::DEBUGGING:
|
||||
return "\033[1;34m[DEBUG]\033[0m ";
|
||||
case LEVEL::TRACE:
|
||||
LOG_PREFIX_TRACE;
|
||||
break;
|
||||
return "\033[1;90m[TRACE]\033[0m ";
|
||||
default:
|
||||
std::cout << "\033[1;90m[LOG]\033[0m ";
|
||||
break;
|
||||
return "\033[1;90m[LOG]\033[0m ";
|
||||
}
|
||||
}
|
||||
|
||||
((std::cout << ' ' << std::forward<Args>(args)), ...);
|
||||
std::cout << std::endl;
|
||||
#else
|
||||
(void)level;
|
||||
(void)std::initializer_list<int>{((void)args, 0)...};
|
||||
#endif // !NDEBUG
|
||||
inline void write(std::string_view prefix, std::string_view message) {
|
||||
std::println(stdout, "{}{}", prefix, message);
|
||||
std::fflush(stdout);
|
||||
}
|
||||
|
||||
// Captures the caller's location alongside the format string, since a
|
||||
// defaulted std::source_location parameter can't follow a parameter pack.
|
||||
template <typename... Args>
|
||||
struct FormatWithLocation {
|
||||
std::format_string<Args...> fmt;
|
||||
std::source_location location;
|
||||
|
||||
template <typename S>
|
||||
requires std::is_convertible_v<const S&, std::string_view>
|
||||
consteval FormatWithLocation(
|
||||
const S& fmt,
|
||||
std::source_location location = std::source_location::current())
|
||||
: fmt(fmt), location(location) {}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename... Args>
|
||||
void log(LEVEL level, std::format_string<Args...> fmt, Args&&... args) {
|
||||
if constexpr (enabled) {
|
||||
detail::write(detail::prefix(level),
|
||||
std::format(fmt, std::forward<Args>(args)...));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void fatal(Args... args) {
|
||||
log(LEVEL::FATAL, args...);
|
||||
void fatal(std::format_string<Args...> fmt, Args&&... args) {
|
||||
log(LEVEL::FATAL, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void error(Args... args) {
|
||||
log(LEVEL::ERROR, args...);
|
||||
void error(std::format_string<Args...> fmt, Args&&... args) {
|
||||
log(LEVEL::ERROR, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void warning(Args... args) {
|
||||
log(LEVEL::WARNING, args...);
|
||||
void warning(std::format_string<Args...> fmt, Args&&... args) {
|
||||
log(LEVEL::WARNING, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void info(Args... args) {
|
||||
log(LEVEL::INFO, args...);
|
||||
void info(std::format_string<Args...> fmt, Args&&... args) {
|
||||
log(LEVEL::INFO, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void verbose(Args... args) {
|
||||
log(LEVEL::VERBOSE, args...);
|
||||
void verbose(std::format_string<Args...> fmt, Args&&... args) {
|
||||
log(LEVEL::VERBOSE, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void debug(const char* file, u16 line, Args... args) {
|
||||
#ifndef NDEBUG
|
||||
LOG_PREFIX_DEBUG;
|
||||
std::cout << file << "::" << line;
|
||||
((std::cout << ' ' << std::forward<Args>(args)), ...);
|
||||
std::cout << std::endl;
|
||||
#else
|
||||
(void)file;
|
||||
(void)line;
|
||||
(void)std::initializer_list<int>{((void)args, 0)...};
|
||||
#endif // !NDEBUG
|
||||
void debug(detail::FormatWithLocation<std::type_identity_t<Args>...> fmt,
|
||||
Args&&... args) {
|
||||
if constexpr (enabled) {
|
||||
detail::write(
|
||||
detail::prefix(LEVEL::DEBUGGING),
|
||||
std::format("{}:{} {}", fmt.location.file_name(), fmt.location.line(),
|
||||
std::format(fmt.fmt, std::forward<Args>(args)...)));
|
||||
}
|
||||
}
|
||||
// trick
|
||||
#define debug(...) debug(__FILE__, __LINE__, __VA_ARGS__)
|
||||
|
||||
template <typename... Args>
|
||||
void trace(Args... args) {
|
||||
log(LEVEL::TRACE, args...);
|
||||
void trace(std::format_string<Args...> fmt, Args&&... args) {
|
||||
log(LEVEL::TRACE, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Like the functions above, but with no "[LEVEL]" prefix: just the arguments,
|
||||
// separated by spaces, then a newline. With none, an empty line.
|
||||
// Like the functions above, but with no "[LEVEL]" prefix. With no arguments,
|
||||
// an empty line.
|
||||
inline void print() {
|
||||
#ifndef NDEBUG
|
||||
std::cout << std::endl;
|
||||
#endif // !NDEBUG
|
||||
if constexpr (enabled) {
|
||||
detail::write("", "");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename First, typename... Rest>
|
||||
void print(First first, Rest... rest) {
|
||||
#ifndef NDEBUG
|
||||
std::cout << first;
|
||||
((std::cout << ' ' << rest), ...);
|
||||
std::cout << std::endl;
|
||||
#else
|
||||
(void)first;
|
||||
(void)std::initializer_list<int>{((void)rest, 0)...};
|
||||
#endif // !NDEBUG
|
||||
template <typename... Args>
|
||||
void print(std::format_string<Args...> fmt, Args&&... args) {
|
||||
if constexpr (enabled) {
|
||||
detail::write("", std::format(fmt, std::forward<Args>(args)...));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sophia::log
|
||||
|
||||
@@ -111,15 +111,12 @@ class Pool {
|
||||
};
|
||||
|
||||
const Slot& validate(Handle<T> handle) const {
|
||||
SOPHIA_ASSERT(handle.isValid(), "invalid handle:", name);
|
||||
SOPHIA_ASSERT(handle.index < slots.size(), name,
|
||||
"handle index out of range:", handle.index);
|
||||
SOPHIA_ASSERT(handle.isValid(), "invalid handle: {}", name);
|
||||
SOPHIA_ASSERT(handle.index < slots.size(), "{} handle index out of range: {}", name, static_cast<u32>(handle.index));
|
||||
|
||||
const Slot& slot = slots[handle.index];
|
||||
SOPHIA_ASSERT(slot.generation == handle.generation, "stale", name,
|
||||
"handle (generation mismatch):", handle.index);
|
||||
SOPHIA_ASSERT(slot.item != nullptr, name,
|
||||
"handle refers to a released item:", handle.index);
|
||||
SOPHIA_ASSERT(slot.generation == handle.generation, "stale {} handle (generation mismatch): {}", name, static_cast<u32>(handle.index));
|
||||
SOPHIA_ASSERT(slot.item != nullptr, "{} handle refers to a released item: {}", name, static_cast<u32>(handle.index));
|
||||
return slot;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user