15#include <AUI/IO/APath.h>
16#include <AUI/IO/IOutputStream.h>
17#include <AUI/Reflect/AReflect.h>
18#include <AUI/Util/ARaiiHelper.h>
19#include "AUI/Thread/AMutex.h"
20#include "AUI/IO/AFileOutputStream.h"
21#include <fmt/format.h>
22#include <fmt/chrono.h>
23#include <AUI/Thread/AMutexWrapper.h>
80 char* currentIterator;
83 std::variant<StackBuffer, HeapBuffer> mBuffer;
88 auto& stack = std::get<StackBuffer>(mBuffer);
89 h.insert(h.end(), stack.buffer, stack.currentIterator);
90 mBuffer = std::move(h);
93 using value_type = char;
95 Buffer()
noexcept: mBuffer({}) {
96 auto& sb = std::get<StackBuffer>(mBuffer);
97 sb.currentIterator = sb.buffer;
99 size_t write(
const char* t,
size_t s) {
100 if (std::holds_alternative<StackBuffer>(mBuffer)) {
101 auto& stack = std::get<StackBuffer>(mBuffer);
102 if (stack.currentIterator + s <= stack.buffer +
sizeof(stack.buffer)) {
103 std::memcpy(stack.currentIterator, t, s);
104 stack.currentIterator += s;
109 auto& h = std::get<HeapBuffer>(mBuffer);
110 h.insert(h.end(), t, t + s);
114 if (std::holds_alternative<StackBuffer>(mBuffer)) {
115 auto& stack = std::get<StackBuffer>(mBuffer);
116 if (stack.currentIterator +
sizeof(c) <= stack.buffer +
sizeof(stack.buffer)) {
117 *stack.currentIterator = c;
118 stack.currentIterator += 1;
123 std::get<HeapBuffer>(mBuffer).push_back(c);
126 void push_back(
char c) {
131 std::string_view str()
const {
133 if (std::holds_alternative<StackBuffer>(mBuffer)) {
134 auto& stack = std::get<StackBuffer>(mBuffer);
135 return {stack.buffer,
static_cast<std::string_view::size_type
>(stack.currentIterator - stack.buffer) - 1};
137 auto& h = std::get<HeapBuffer>(mBuffer);
138 return {h.data(), h.size()};
142 struct LazyStreamBuf final: std::streambuf {
147 LazyStreamBuf(Buffer& stackBuffer) : stackBuffer(stackBuffer), stream(
this) {}
150 std::streamsize xsputn(
const char_type* s, std::streamsize n)
override {
151 return stackBuffer.write(s, n);
154 int overflow(int_type __c)
override {
155 stackBuffer.write(__c);
163 void writeTimestamp(
const char* fmt, std::chrono::system_clock::time_point t)
noexcept {
164 fmt::format_to(std::back_inserter(mBuffer),
"{}", t);
171 mPrefix(std::move(prefix)) {
177 auto s = mBuffer.str();
182 LogWriter& operator<<(
const T& t)
noexcept {
184 if constexpr(std::is_constructible_v<std::string_view, T>) {
185 std::string_view stringView(t);
186 mBuffer.write(stringView.data(), stringView.size());
187 }
else if constexpr(std::is_base_of_v<AString, T>) {
188 *
this << t.toStdString();
189 }
else if constexpr(std::is_base_of_v<std::exception, T> && !std::is_base_of_v<AException, T>) {
190 *
this <<
"(" << AReflect::name(&t) <<
") " << t.what();
191 }
else if constexpr(std::is_same_v<std::chrono::seconds, T>) {
192 writeTimestamp(
"%D %T", std::chrono::system_clock::time_point(t));
193 }
else if constexpr(std::is_same_v<std::chrono::minutes, T> || std::is_same_v<std::chrono::hours, T>) {
194 writeTimestamp(
"%D %R", std::chrono::system_clock::time_point(t));
197 mStreamBuf.emplace(mBuffer);
199 mStreamBuf->stream << t;
213 setLogFileImpl(std::move(filename));
220 void setDebugMode(
bool debug) {
221 global().mDebug = debug;
224 return global().mDebug;
238 setLogFileImpl(std::move(path));
246 static void setLogFileForGlobal(
APath path);
250 return mLogFile.valueOrException().path();
253 void onLogged(std::function<
void(
const AString& prefix,
const AString& message, Level level)> callback) {
254 std::unique_lock lock(mOnLogged);
255 mOnLogged = std::move(callback);
263 template <aui::invocable Callable>
265 std::unique_lock lock(mLogSync);
267 if (!mLogFile)
return;
269 mLogFile->open(
true);
271 auto path = mLogFile->path();
274 log(WARN,
"Logger", fmt::format(
"Unable to reopen file {}: {}", path, e.getMessage()));
277 if (!mLogFile || !mLogFile->nativeHandle()) {
286 static LogWriter info(
const AString& str)
288 return {global(), INFO, str};
290 static LogWriter warn(
const AString& str)
292 return {global(), WARN, str};
294 static LogWriter err(
const AString& str)
296 return {global(), ERR, str};
298 static LogWriter debug(
const AString& str)
300 return {global(), DEBUG, str};
310 return {*
this, level, prefix};
320 bool mDebug = AUI_DEBUG;
322 void setLogFileImpl(
AString path);
331 void log(Level level, std::string_view prefix, std::string_view message);
335 template<glm::length_t L,
typename T, glm::qualifier Q>
336 inline std::ostream& operator<<(std::ostream& o, vec<L, T, Q> vec) {
338 for (std::size_t i = 0; i < L; ++i) {
339 if (i != 0) o <<
", ";
349template<glm::length_t L,
typename T, glm::qualifier Q>
350struct fmt::formatter<glm::vec<L, T, Q>> {
351 constexpr auto parse (format_parse_context& ctx) {
return ctx.begin(); }
353 template <
typename Context>
354 constexpr auto format(glm::vec<L, T, Q> vec, Context& ctx)
const {
355 auto out = ctx.out();
356 out = format_to(out, FMT_STRING(
"{{ "));
357 for (glm::length_t i = 0; i < L; ++i) {
359 out = format_to(out, FMT_STRING(
"{}"), vec[i]);
361 out = format_to(out, FMT_STRING(
", {}"), vec[i]);
364 out = format_to(out, FMT_STRING(
" }}"));
371#define ALOG_DEBUG(str) if (ALogger::global().isDebug()) ALogger::debug(str)
373#include <AUI/Traits/strings.h>
Abstract AUI exception.
Definition: AException.h:29
A logger class.
Definition: ALogger.h:61
LogWriter log(Level level, const AString &prefix)
Writer a log entry with LogWriter helper.
Definition: ALogger.h:308
void doLogFileAccessSafe(Callable action)
Allows to perform some action (access safely) on log file (which is opened all over the execution pro...
Definition: ALogger.h:264
void setLogFile(APath path)
Sets log file.
Definition: ALogger.h:237
ALogger(AString filename)
Constructor for an extra log file.
Definition: ALogger.h:212
Wraps the object with mutex, providing thread-safety layer and a runtime check.
Definition: AMutexWrapper.h:22
Utility wrapper implementing the stack-allocated (fast) optional idiom.
Definition: AOptional.h:32
An add-on to AString with functions for working with the path.
Definition: APath.h:106
Definition: ARaiiHelper.h:17
Represents a Unicode character string.
Definition: AString.h:37
std::string toStdString() const noexcept
Definition: AString.cpp:338
A std::vector with AUI extensions.
Definition: AVector.h:38
Basic syscall-based synchronization primitive.
Definition: AMutex.h:33