| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- //
- // Logger.cpp
- // DanmakuRPG
- //
- // Created by Sam Jaffe on 7/18/15.
- // Copyright (c) 2015 Sam Jaffe. All rights reserved.
- //
- #ifdef _WIN32
- #include <Windows.h>
- #endif
- #include <cassert>
- #include <cmath>
- #include <ctime>
- #include <map>
- #include <stdexcept>
- #include "logger.hpp"
- #include "properties.hpp"
- namespace logging {
- #define X(l) \
- case logging::L##l: \
- return #l;
-
- const char* level_header(log_level l) {
- assert(l != logging::LNONE);
- switch (l) {
- X(FATAL)
- X(CRITICAL)
- X(ERROR)
- X(WARNING)
- X(INFO)
- X(DEBUG)
- X(TRACE)
- X(NONE)
- }
- }
-
- #undef X
-
- std::string timestamp() {
- time_t round = std::time(NULL);
- struct tm time = *std::localtime(&round);
- char buf[32];
- snprintf(buf, sizeof(buf), "%0.4d-%0.2d-%0.2d %0.2d:%0.2d:%0.2d.%0.3d ",
- 1900 + time.tm_year, time.tm_mon + 1, time.tm_mday,
- time.tm_hour, time.tm_min, time.tm_sec,
- static_cast<int>(round % 1000));
- return buf;
- }
- }
- namespace logging {
- class multiple_bindings : public std::logic_error {
- using std::logic_error::logic_error;
- };
-
- // extern logger_impl& _logger_impl_shared_instance();
- extern _binding _default_logger_impl;
- static _binding _impl_binding = nullptr;
-
- bool bind_logger_impl(_binding impl) {
- assert(_impl_binding == nullptr);
- if (_impl_binding != nullptr) {
- throw multiple_bindings{"Only one logger implementation may be bound"};
- }
- _impl_binding = impl;
- return true;
- }
-
- logger_impl& _get_shared_instance() {
- if (_impl_binding == nullptr) {
- return _default_logger_impl();
- } else {
- return _impl_binding();
- }
- }
- }
- namespace logging {
- logger& logger::instance() {
- static logger instance;
- return instance;
- }
-
- logger& logger::instance(const char* name) {
- static std::map<const char*, std::unique_ptr<logger>> instances;
- std::map<const char*, std::unique_ptr<logger>>::iterator it;
- if ((it = instances.find(name)) != instances.end()) {
- return *(it->second);
- }
- return *(instances.emplace(std::make_pair(name, std::unique_ptr<logger>(new logger(name)))).first->second);
- }
-
- logger::logger(const char* name)
- : min_level_(LDEBUG)
- , logger_name_(name)
- , impl_(_get_shared_instance())
- {
- }
-
- logger::~logger() {
- flush();
- }
-
- std::string logger::get_header(log_level level) {
- std::string ts = timestamp();
- char data[64];
- snprintf(data, sizeof(data), "[%-5s] %s %s - ", level_header(level), logger_name_, ts.c_str());
- return data;
- }
-
- void logger::vlognf(log_level level, size_t num_bytes, char const* fmt, va_list args) {
- if (level < min_level_) return;
- const std::unique_ptr<char[]> data(new char[num_bytes]);
- int n = vsnprintf(data.get(), num_bytes, fmt, args);
- if (n >= 0) {
- data[num_bytes-1] = '\0';
- log(level, get_header(level) + data.get());
- }
- }
-
- void logger::log(log_level level, std::string const& msg) {
- impl_.write(level, msg);
- }
-
- void logger::flush() {
- impl_.flush();
- }
- }
|