#include "ehs/Log.h" #include "ehs/io/Console.h" #include "ehs/io/File.h" namespace ehs { void Log::DefaultRaisedCb(const Log &log) { Console::Write_8(log.ToStr()); } void Log::DefaultOutputCb(const Array &logs) { File output("Logs.txt", Mode::WRITE, Disposition::CREATE_PERSISTENT); output.SeekBeginning(); for (UInt_64 i = 0; i < logs.Size(); ++i) output.WriteStr_8(logs[i].ToStr() + "\n"); } LogRaisedCb Log::raisedCb = DefaultRaisedCb; LogOutputCb Log::outputCb = DefaultOutputCb; Array Log::logs; Log Log::lastLog; bool Log::immediate = false; void Log::SetRaisedCallback(const LogRaisedCb newCb) { raisedCb = newCb; } void Log::SetOutputCallback(const LogOutputCb newCb) { outputCb = newCb; } void Log::OnExit() { if (lastLog.GetType() != LogType::SUCCESS) logs.Push(lastLog); lastLog = {}; if (outputCb) outputCb(logs); } void Log::Raise(Log log) { if (log.GetType() == LogType::INFO || (log.GetType() != LogType::SUCCESS && immediate)) if (raisedCb) raisedCb(log); if (lastLog.GetType() != LogType::SUCCESS) logs.Push((Log&&)lastLog); lastLog = (Log&&)log; } Log Log::GetLastLog() { Log result = lastLog; lastLog = {}; return result; } void Log::EnableImmediateMode(const bool enable) { immediate = enable; } Log::Log() : type(LogType::SUCCESS), code(0) { } Log::Log(LogType type, const std::initializer_list &tags, const UInt_64 code, Str_8 msg) : type(type), tags(tags.size()), code(code), msg((Str_8&&)msg) { UInt_64 i = 0; for (auto v = tags.begin(); v != tags.end(); ++v) this->tags[i++] = *v; } Log::Log(LogType type, Array tags, const UInt_64 code, Str_8 msg) : type(type), tags((Array&&)tags), code(code), msg((Str_8&&)msg) { } Log::Log(Log &&log) noexcept : type(log.type), tags((Array&&)log.tags), code(log.code), msg((Str_8&&)log.msg) { log.type = LogType::INFO; log.code = 0; } Log::Log(const Log &log) : type(log.type), tags(log.tags), code(log.code), msg(log.msg) { } Log & Log::operator=(Log &&log) noexcept { if (this == &log) return *this; type = log.type; tags = (Array&&)log.tags; code = log.code; msg = (Str_8&&)log.msg; log.type = LogType::INFO; log.code = 0; return *this; } Log& Log::operator=(const Log &log) { if (this == &log) return *this; type = log.type; tags = log.tags; code = log.code; msg = log.msg; return *this; } /* bool Log::operator==(const Log log) { return src == log.src && type == log.type && code == log.code && msg == log.msg; } bool Log::operator!=(const Log log) { return src != log.src || type != log.type || code != log.code || msg != log.msg; } */ LogType Log::GetType() const { return type; } bool Log::HasTags(const std::initializer_list &tags) const { UInt_64 i = 0; UInt_64 c = 0; for (auto v = tags.begin(); v != tags.end(); ++v) if (this->tags[i++].GetLower() == v->GetLower()) ++c; if (c == tags.size()) return true; return false; } bool Log::HasTags(const Array &tags) const { UInt_64 c = 0; for (UInt_64 i = 0; i < tags.Size(); ++i) if (this->tags[i].GetLower() == tags[c].GetLower()) ++c; if (c == tags.Size()) return true; return false; } bool Log::HasTag(const Str_8& tag) const { for (UInt_64 i = 0; i < tags.Size(); ++i) if (tags[i].GetLower() == tag.GetLower()) return true; return false; } const Array &Log::GetTags() const { return tags; } UInt_64 Log::GetCode() const { return code; } Str_8 Log::GetMsg() const { return msg; } Str_8 Log::ToStr() const { Str_8 result = "<"; switch (type) { case LogType::SUCCESS: { result += "Success"; break; } case LogType::ERR: { result += "Error"; break; } case LogType::WARN: { result += "Warning"; break; } case LogType::INFO: { result += "Information"; } } result += ">["; for (UInt_64 i = 0; i < tags.Size(); ++i) { result += tags[i]; if (i != tags.Size() - 1) result += ", "; } result += "](" + Str_8::FromNum(code) + "): " + msg; return result; } bool Log::IsValid() const { return tags.Size() && msg.Size(); } }