Merge commit 'a4163d8b1b2f6c012c0e1d26f90815879a743aa8' as 'vendor/spdlog'
This commit is contained in:
		
							
								
								
									
										82
									
								
								vendor/spdlog/include/spdlog/async_logger.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								vendor/spdlog/include/spdlog/async_logger.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// Very fast asynchronous logger (millions of logs per second on an average desktop)
 | 
			
		||||
// Uses pre allocated lockfree queue for maximum throughput even under large number of threads.
 | 
			
		||||
// Creates a single back thread to pop messages from the queue and log them.
 | 
			
		||||
//
 | 
			
		||||
// Upon each log write the logger:
 | 
			
		||||
//    1. Checks if its log level is enough to log the message
 | 
			
		||||
//    2. Push a new copy of the message to a queue (or block the caller until space is available in the queue)
 | 
			
		||||
//    3. will throw spdlog_ex upon log exceptions
 | 
			
		||||
// Upon destruction, logs all remaining messages in the queue before destructing..
 | 
			
		||||
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
#include "spdlog/logger.h"
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
class async_log_helper;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class async_logger SPDLOG_FINAL :public logger
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    template<class It>
 | 
			
		||||
    async_logger(const std::string& name,
 | 
			
		||||
                 const It& begin,
 | 
			
		||||
                 const It& end,
 | 
			
		||||
                 size_t queue_size,
 | 
			
		||||
                 const async_overflow_policy overflow_policy =  async_overflow_policy::block_retry,
 | 
			
		||||
                 const std::function<void()>& worker_warmup_cb = nullptr,
 | 
			
		||||
                 const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
 | 
			
		||||
                 const std::function<void()>& worker_teardown_cb = nullptr);
 | 
			
		||||
 | 
			
		||||
    async_logger(const std::string& logger_name,
 | 
			
		||||
                 sinks_init_list sinks,
 | 
			
		||||
                 size_t queue_size,
 | 
			
		||||
                 const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
 | 
			
		||||
                 const std::function<void()>& worker_warmup_cb = nullptr,
 | 
			
		||||
                 const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
 | 
			
		||||
                 const std::function<void()>& worker_teardown_cb = nullptr);
 | 
			
		||||
 | 
			
		||||
    async_logger(const std::string& logger_name,
 | 
			
		||||
                 sink_ptr single_sink,
 | 
			
		||||
                 size_t queue_size,
 | 
			
		||||
                 const async_overflow_policy overflow_policy =  async_overflow_policy::block_retry,
 | 
			
		||||
                 const std::function<void()>& worker_warmup_cb = nullptr,
 | 
			
		||||
                 const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
 | 
			
		||||
                 const std::function<void()>& worker_teardown_cb = nullptr);
 | 
			
		||||
 | 
			
		||||
    //Wait for the queue to be empty, and flush synchronously
 | 
			
		||||
    //Warning: this can potentially last forever as we wait it to complete
 | 
			
		||||
    void flush() override;
 | 
			
		||||
 | 
			
		||||
    // Error handler
 | 
			
		||||
    virtual void set_error_handler(log_err_handler) override;
 | 
			
		||||
    virtual log_err_handler error_handler() override;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void _sink_it(details::log_msg& msg) override;
 | 
			
		||||
    void _set_formatter(spdlog::formatter_ptr msg_formatter) override;
 | 
			
		||||
    void _set_pattern(const std::string& pattern, pattern_time_type pattern_time) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::unique_ptr<details::async_log_helper> _async_log_helper;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/async_logger_impl.h"
 | 
			
		||||
							
								
								
									
										166
									
								
								vendor/spdlog/include/spdlog/common.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								vendor/spdlog/include/spdlog/common.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,166 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <initializer_list>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <exception>
 | 
			
		||||
#include<functional>
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
 | 
			
		||||
#include <codecvt>
 | 
			
		||||
#include <locale>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/null_mutex.h"
 | 
			
		||||
 | 
			
		||||
//visual studio upto 2013 does not support noexcept nor constexpr
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
 | 
			
		||||
#define SPDLOG_NOEXCEPT throw()
 | 
			
		||||
#define SPDLOG_CONSTEXPR
 | 
			
		||||
#else
 | 
			
		||||
#define SPDLOG_NOEXCEPT noexcept
 | 
			
		||||
#define SPDLOG_CONSTEXPR constexpr
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// See tweakme.h
 | 
			
		||||
#if !defined(SPDLOG_FINAL)
 | 
			
		||||
#define SPDLOG_FINAL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__)  || defined(__clang__)
 | 
			
		||||
#define SPDLOG_DEPRECATED __attribute__((deprecated))
 | 
			
		||||
#elif defined(_MSC_VER)
 | 
			
		||||
#define SPDLOG_DEPRECATED __declspec(deprecated)
 | 
			
		||||
#else
 | 
			
		||||
#define SPDLOG_DEPRECATED
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
#include <cxxabi.h>
 | 
			
		||||
#define SPDLOG_CATCH_ALL catch (abi::__forced_unwind&) { _err_handler("Unknown exception"); throw; } catch (...)
 | 
			
		||||
#else // __linux__
 | 
			
		||||
#define SPDLOG_CATCH_ALL catch (...)
 | 
			
		||||
#endif // __linux__
 | 
			
		||||
 | 
			
		||||
#include "spdlog/fmt/fmt.h"
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
class formatter;
 | 
			
		||||
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
class sink;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
using log_clock = std::chrono::system_clock;
 | 
			
		||||
using sink_ptr = std::shared_ptr < sinks::sink >;
 | 
			
		||||
using sinks_init_list = std::initializer_list < sink_ptr >;
 | 
			
		||||
using formatter_ptr = std::shared_ptr<spdlog::formatter>;
 | 
			
		||||
#if defined(SPDLOG_NO_ATOMIC_LEVELS)
 | 
			
		||||
using level_t = details::null_atomic_int;
 | 
			
		||||
#else
 | 
			
		||||
using level_t = std::atomic<int>;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using log_err_handler = std::function<void(const std::string &err_msg)>;
 | 
			
		||||
 | 
			
		||||
//Log level enum
 | 
			
		||||
namespace level
 | 
			
		||||
{
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    trace = 0,
 | 
			
		||||
    debug = 1,
 | 
			
		||||
    info = 2,
 | 
			
		||||
    warn = 3,
 | 
			
		||||
    err = 4,
 | 
			
		||||
    critical = 5,
 | 
			
		||||
    off = 6
 | 
			
		||||
} level_enum;
 | 
			
		||||
 | 
			
		||||
#if !defined(SPDLOG_LEVEL_NAMES)
 | 
			
		||||
#define SPDLOG_LEVEL_NAMES { "trace", "debug", "info",  "warning", "error", "critical", "off" };
 | 
			
		||||
#endif
 | 
			
		||||
static const char* level_names[] SPDLOG_LEVEL_NAMES
 | 
			
		||||
 | 
			
		||||
static const char* short_level_names[] { "T", "D", "I", "W", "E", "C", "O" };
 | 
			
		||||
 | 
			
		||||
inline const char* to_str(spdlog::level::level_enum l)
 | 
			
		||||
{
 | 
			
		||||
    return level_names[l];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline const char* to_short_str(spdlog::level::level_enum l)
 | 
			
		||||
{
 | 
			
		||||
    return short_level_names[l];
 | 
			
		||||
}
 | 
			
		||||
} //level
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Async overflow policy - block by default.
 | 
			
		||||
//
 | 
			
		||||
enum class async_overflow_policy
 | 
			
		||||
{
 | 
			
		||||
    block_retry, // Block / yield / sleep until message can be enqueued
 | 
			
		||||
    discard_log_msg // Discard the message it enqueue fails
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Pattern time - specific time getting to use for pattern_formatter.
 | 
			
		||||
// local time by default
 | 
			
		||||
//
 | 
			
		||||
enum class pattern_time_type
 | 
			
		||||
{
 | 
			
		||||
    local, // log localtime
 | 
			
		||||
    utc    // log utc
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Log exception
 | 
			
		||||
//
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
namespace os
 | 
			
		||||
{
 | 
			
		||||
std::string errno_str(int err_num);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
class spdlog_ex: public std::exception
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    spdlog_ex(const std::string& msg):_msg(msg)
 | 
			
		||||
    {}
 | 
			
		||||
    spdlog_ex(const std::string& msg, int last_errno)
 | 
			
		||||
    {
 | 
			
		||||
        _msg = msg + ": " + details::os::errno_str(last_errno);
 | 
			
		||||
    }
 | 
			
		||||
    const char* what() const SPDLOG_NOEXCEPT override
 | 
			
		||||
    {
 | 
			
		||||
        return _msg.c_str();
 | 
			
		||||
    }
 | 
			
		||||
private:
 | 
			
		||||
    std::string _msg;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
 | 
			
		||||
//
 | 
			
		||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
 | 
			
		||||
using filename_t = std::wstring;
 | 
			
		||||
#else
 | 
			
		||||
using filename_t = std::string;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
} //spdlog
 | 
			
		||||
							
								
								
									
										399
									
								
								vendor/spdlog/include/spdlog/details/async_log_helper.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										399
									
								
								vendor/spdlog/include/spdlog/details/async_log_helper.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,399 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// async log helper :
 | 
			
		||||
// Process logs asynchronously using a back thread.
 | 
			
		||||
//
 | 
			
		||||
// If the internal queue of log messages reaches its max size,
 | 
			
		||||
// then the client call will block until there is more room.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
#include "spdlog/sinks/sink.h"
 | 
			
		||||
#include "spdlog/details/mpmc_bounded_q.h"
 | 
			
		||||
#include "spdlog/details/log_msg.h"
 | 
			
		||||
#include "spdlog/details/os.h"
 | 
			
		||||
#include "spdlog/formatter.h"
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <exception>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
class async_log_helper
 | 
			
		||||
{
 | 
			
		||||
    // Async msg to move to/from the queue
 | 
			
		||||
    // Movable only. should never be copied
 | 
			
		||||
    enum class async_msg_type
 | 
			
		||||
    {
 | 
			
		||||
        log,
 | 
			
		||||
        flush,
 | 
			
		||||
        terminate
 | 
			
		||||
    };
 | 
			
		||||
    struct async_msg
 | 
			
		||||
    {
 | 
			
		||||
        std::string logger_name;
 | 
			
		||||
        level::level_enum level;
 | 
			
		||||
        log_clock::time_point time;
 | 
			
		||||
        size_t thread_id;
 | 
			
		||||
        std::string txt;
 | 
			
		||||
        async_msg_type msg_type;
 | 
			
		||||
        size_t msg_id;
 | 
			
		||||
 | 
			
		||||
        async_msg() = default;
 | 
			
		||||
        ~async_msg() = default;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
 | 
			
		||||
        logger_name(std::move(other.logger_name)),
 | 
			
		||||
                    level(std::move(other.level)),
 | 
			
		||||
                    time(std::move(other.time)),
 | 
			
		||||
                    thread_id(other.thread_id),
 | 
			
		||||
                    txt(std::move(other.txt)),
 | 
			
		||||
                    msg_type(std::move(other.msg_type)),
 | 
			
		||||
                    msg_id(other.msg_id)
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
        async_msg(async_msg_type m_type):
 | 
			
		||||
            level(level::info),
 | 
			
		||||
            thread_id(0),
 | 
			
		||||
            msg_type(m_type),
 | 
			
		||||
            msg_id(0)
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
        async_msg& operator=(async_msg&& other) SPDLOG_NOEXCEPT
 | 
			
		||||
        {
 | 
			
		||||
            logger_name = std::move(other.logger_name);
 | 
			
		||||
            level = other.level;
 | 
			
		||||
            time = std::move(other.time);
 | 
			
		||||
            thread_id = other.thread_id;
 | 
			
		||||
            txt = std::move(other.txt);
 | 
			
		||||
            msg_type = other.msg_type;
 | 
			
		||||
            msg_id = other.msg_id;
 | 
			
		||||
            return *this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // never copy or assign. should only be moved..
 | 
			
		||||
        async_msg(const async_msg&) = delete;
 | 
			
		||||
        async_msg& operator=(const async_msg& other) = delete;
 | 
			
		||||
 | 
			
		||||
        // construct from log_msg
 | 
			
		||||
        async_msg(const details::log_msg& m):
 | 
			
		||||
            level(m.level),
 | 
			
		||||
            time(m.time),
 | 
			
		||||
            thread_id(m.thread_id),
 | 
			
		||||
            txt(m.raw.data(), m.raw.size()),
 | 
			
		||||
            msg_type(async_msg_type::log),
 | 
			
		||||
            msg_id(m.msg_id)
 | 
			
		||||
        {
 | 
			
		||||
#ifndef SPDLOG_NO_NAME
 | 
			
		||||
            logger_name = *m.logger_name;
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // copy into log_msg
 | 
			
		||||
        void fill_log_msg(log_msg &msg)
 | 
			
		||||
        {
 | 
			
		||||
            msg.logger_name = &logger_name;
 | 
			
		||||
            msg.level = level;
 | 
			
		||||
            msg.time = time;
 | 
			
		||||
            msg.thread_id = thread_id;
 | 
			
		||||
            msg.raw << txt;
 | 
			
		||||
            msg.msg_id = msg_id;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    using item_type = async_msg;
 | 
			
		||||
    using q_type = details::mpmc_bounded_queue<item_type>;
 | 
			
		||||
 | 
			
		||||
    using clock = std::chrono::steady_clock;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    async_log_helper(formatter_ptr formatter,
 | 
			
		||||
                     const std::vector<sink_ptr>& sinks,
 | 
			
		||||
                     size_t queue_size,
 | 
			
		||||
                     const log_err_handler err_handler,
 | 
			
		||||
                     const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
 | 
			
		||||
                     const std::function<void()>& worker_warmup_cb = nullptr,
 | 
			
		||||
                     const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
 | 
			
		||||
                     const std::function<void()>& worker_teardown_cb = nullptr);
 | 
			
		||||
 | 
			
		||||
    void log(const details::log_msg& msg);
 | 
			
		||||
 | 
			
		||||
    // stop logging and join the back thread
 | 
			
		||||
    ~async_log_helper();
 | 
			
		||||
 | 
			
		||||
    void set_formatter(formatter_ptr);
 | 
			
		||||
 | 
			
		||||
    void flush(bool wait_for_q);
 | 
			
		||||
 | 
			
		||||
    void set_error_handler(spdlog::log_err_handler err_handler);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    formatter_ptr _formatter;
 | 
			
		||||
    std::vector<std::shared_ptr<sinks::sink>> _sinks;
 | 
			
		||||
 | 
			
		||||
    // queue of messages to log
 | 
			
		||||
    q_type _q;
 | 
			
		||||
 | 
			
		||||
    log_err_handler _err_handler;
 | 
			
		||||
 | 
			
		||||
    bool _flush_requested;
 | 
			
		||||
 | 
			
		||||
    bool _terminate_requested;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // overflow policy
 | 
			
		||||
    const async_overflow_policy _overflow_policy;
 | 
			
		||||
 | 
			
		||||
    // worker thread warmup callback - one can set thread priority, affinity, etc
 | 
			
		||||
    const std::function<void()> _worker_warmup_cb;
 | 
			
		||||
 | 
			
		||||
    // auto periodic sink flush parameter
 | 
			
		||||
    const std::chrono::milliseconds _flush_interval_ms;
 | 
			
		||||
 | 
			
		||||
    // worker thread teardown callback
 | 
			
		||||
    const std::function<void()> _worker_teardown_cb;
 | 
			
		||||
 | 
			
		||||
    // worker thread
 | 
			
		||||
    std::thread _worker_thread;
 | 
			
		||||
 | 
			
		||||
    void push_msg(async_msg&& new_msg);
 | 
			
		||||
 | 
			
		||||
    // worker thread main loop
 | 
			
		||||
    void worker_loop();
 | 
			
		||||
 | 
			
		||||
    // pop next message from the queue and process it. will set the last_pop to the pop time
 | 
			
		||||
    // return false if termination of the queue is required
 | 
			
		||||
    bool process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush);
 | 
			
		||||
 | 
			
		||||
    void handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush);
 | 
			
		||||
 | 
			
		||||
    // sleep,yield or return immediately using the time passed since last message as a hint
 | 
			
		||||
    static void sleep_or_yield(const spdlog::log_clock::time_point& now, const log_clock::time_point& last_op_time);
 | 
			
		||||
 | 
			
		||||
    // wait until the queue is empty
 | 
			
		||||
    void wait_empty_q();
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// async_sink class implementation
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
inline spdlog::details::async_log_helper::async_log_helper(
 | 
			
		||||
    formatter_ptr formatter,
 | 
			
		||||
    const std::vector<sink_ptr>& sinks,
 | 
			
		||||
    size_t queue_size,
 | 
			
		||||
    log_err_handler err_handler,
 | 
			
		||||
    const async_overflow_policy overflow_policy,
 | 
			
		||||
    const std::function<void()>& worker_warmup_cb,
 | 
			
		||||
    const std::chrono::milliseconds& flush_interval_ms,
 | 
			
		||||
    const std::function<void()>& worker_teardown_cb):
 | 
			
		||||
    _formatter(formatter),
 | 
			
		||||
    _sinks(sinks),
 | 
			
		||||
    _q(queue_size),
 | 
			
		||||
    _err_handler(err_handler),
 | 
			
		||||
    _flush_requested(false),
 | 
			
		||||
    _terminate_requested(false),
 | 
			
		||||
    _overflow_policy(overflow_policy),
 | 
			
		||||
    _worker_warmup_cb(worker_warmup_cb),
 | 
			
		||||
    _flush_interval_ms(flush_interval_ms),
 | 
			
		||||
    _worker_teardown_cb(worker_teardown_cb),
 | 
			
		||||
    _worker_thread(&async_log_helper::worker_loop, this)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
// Send to the worker thread termination message(level=off)
 | 
			
		||||
// and wait for it to finish gracefully
 | 
			
		||||
inline spdlog::details::async_log_helper::~async_log_helper()
 | 
			
		||||
{
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        push_msg(async_msg(async_msg_type::terminate));
 | 
			
		||||
        _worker_thread.join();
 | 
			
		||||
    }
 | 
			
		||||
    catch (...) // don't crash in destructor
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Try to push and block until succeeded (if the policy is not to discard when the queue is full)
 | 
			
		||||
inline void spdlog::details::async_log_helper::log(const details::log_msg& msg)
 | 
			
		||||
{
 | 
			
		||||
    push_msg(async_msg(msg));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::details::async_log_helper::push_msg(details::async_log_helper::async_msg&& new_msg)
 | 
			
		||||
{
 | 
			
		||||
    if (!_q.enqueue(std::move(new_msg)) && _overflow_policy != async_overflow_policy::discard_log_msg)
 | 
			
		||||
    {
 | 
			
		||||
        auto last_op_time = details::os::now();
 | 
			
		||||
        auto now = last_op_time;
 | 
			
		||||
        do
 | 
			
		||||
        {
 | 
			
		||||
            now = details::os::now();
 | 
			
		||||
            sleep_or_yield(now, last_op_time);
 | 
			
		||||
        }
 | 
			
		||||
        while (!_q.enqueue(std::move(new_msg)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// optionally wait for the queue be empty and request flush from the sinks
 | 
			
		||||
inline void spdlog::details::async_log_helper::flush(bool wait_for_q)
 | 
			
		||||
{
 | 
			
		||||
    push_msg(async_msg(async_msg_type::flush));
 | 
			
		||||
    if (wait_for_q)
 | 
			
		||||
        wait_empty_q(); //return only make after the above flush message was processed
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::details::async_log_helper::worker_loop()
 | 
			
		||||
{
 | 
			
		||||
    if (_worker_warmup_cb) _worker_warmup_cb();
 | 
			
		||||
    auto last_pop = details::os::now();
 | 
			
		||||
    auto last_flush = last_pop;
 | 
			
		||||
    auto active = true;
 | 
			
		||||
    while (active)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            active = process_next_msg(last_pop, last_flush);
 | 
			
		||||
        }
 | 
			
		||||
        catch (const std::exception &ex)
 | 
			
		||||
        {
 | 
			
		||||
            _err_handler(ex.what());
 | 
			
		||||
        }
 | 
			
		||||
        catch (...)
 | 
			
		||||
        {
 | 
			
		||||
            _err_handler("Unknown exception");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (_worker_teardown_cb) _worker_teardown_cb();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// process next message in the queue
 | 
			
		||||
// return true if this thread should still be active (while no terminate msg was received)
 | 
			
		||||
inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush)
 | 
			
		||||
{
 | 
			
		||||
    async_msg incoming_async_msg;
 | 
			
		||||
 | 
			
		||||
    if (_q.dequeue(incoming_async_msg))
 | 
			
		||||
    {
 | 
			
		||||
        last_pop = details::os::now();
 | 
			
		||||
        switch (incoming_async_msg.msg_type)
 | 
			
		||||
        {
 | 
			
		||||
        case async_msg_type::flush:
 | 
			
		||||
            _flush_requested = true;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        case async_msg_type::terminate:
 | 
			
		||||
            _flush_requested = true;
 | 
			
		||||
            _terminate_requested = true;
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        default:
 | 
			
		||||
            log_msg incoming_log_msg;
 | 
			
		||||
            incoming_async_msg.fill_log_msg(incoming_log_msg);
 | 
			
		||||
            _formatter->format(incoming_log_msg);
 | 
			
		||||
            for (auto &s : _sinks)
 | 
			
		||||
            {
 | 
			
		||||
                if (s->should_log(incoming_log_msg.level))
 | 
			
		||||
                {
 | 
			
		||||
                    s->log(incoming_log_msg);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Handle empty queue..
 | 
			
		||||
    // This is the only place where the queue can terminate or flush to avoid losing messages already in the queue
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        auto now = details::os::now();
 | 
			
		||||
        handle_flush_interval(now, last_flush);
 | 
			
		||||
        sleep_or_yield(now, last_pop);
 | 
			
		||||
        return !_terminate_requested;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// flush all sinks if _flush_interval_ms has expired
 | 
			
		||||
inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush)
 | 
			
		||||
{
 | 
			
		||||
    auto should_flush = _flush_requested || (_flush_interval_ms != std::chrono::milliseconds::zero() && now - last_flush >= _flush_interval_ms);
 | 
			
		||||
    if (should_flush)
 | 
			
		||||
    {
 | 
			
		||||
        for (auto &s : _sinks)
 | 
			
		||||
            s->flush();
 | 
			
		||||
        now = last_flush = details::os::now();
 | 
			
		||||
        _flush_requested = false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter)
 | 
			
		||||
{
 | 
			
		||||
    _formatter = msg_formatter;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// spin, yield or sleep. use the time passed since last message as a hint
 | 
			
		||||
inline void spdlog::details::async_log_helper::sleep_or_yield(const spdlog::log_clock::time_point& now, const spdlog::log_clock::time_point& last_op_time)
 | 
			
		||||
{
 | 
			
		||||
    using namespace std::this_thread;
 | 
			
		||||
    using std::chrono::milliseconds;
 | 
			
		||||
    using std::chrono::microseconds;
 | 
			
		||||
 | 
			
		||||
    auto time_since_op = now - last_op_time;
 | 
			
		||||
 | 
			
		||||
    // spin upto 50 micros
 | 
			
		||||
    if (time_since_op <= microseconds(50))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    // yield upto 150 micros
 | 
			
		||||
    if (time_since_op <= microseconds(100))
 | 
			
		||||
        return std::this_thread::yield();
 | 
			
		||||
 | 
			
		||||
    // sleep for 20 ms upto 200 ms
 | 
			
		||||
    if (time_since_op <= milliseconds(200))
 | 
			
		||||
        return sleep_for(milliseconds(20));
 | 
			
		||||
 | 
			
		||||
    // sleep for 200 ms
 | 
			
		||||
    return sleep_for(milliseconds(200));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// wait for the queue to be empty
 | 
			
		||||
inline void spdlog::details::async_log_helper::wait_empty_q()
 | 
			
		||||
{
 | 
			
		||||
    auto last_op = details::os::now();
 | 
			
		||||
    while (_q.approx_size() > 0)
 | 
			
		||||
    {
 | 
			
		||||
        sleep_or_yield(details::os::now(), last_op);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::details::async_log_helper::set_error_handler(spdlog::log_err_handler err_handler)
 | 
			
		||||
{
 | 
			
		||||
    _err_handler = err_handler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										105
									
								
								vendor/spdlog/include/spdlog/details/async_logger_impl.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								vendor/spdlog/include/spdlog/details/async_logger_impl.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// Async Logger implementation
 | 
			
		||||
// Use an async_sink (queue per logger) to perform the logging in a worker thread
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/async_log_helper.h"
 | 
			
		||||
#include "spdlog/async_logger.h"
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
template<class It>
 | 
			
		||||
inline spdlog::async_logger::async_logger(const std::string& logger_name,
 | 
			
		||||
        const It& begin,
 | 
			
		||||
        const It& end,
 | 
			
		||||
        size_t queue_size,
 | 
			
		||||
        const  async_overflow_policy overflow_policy,
 | 
			
		||||
        const std::function<void()>& worker_warmup_cb,
 | 
			
		||||
        const std::chrono::milliseconds& flush_interval_ms,
 | 
			
		||||
        const std::function<void()>& worker_teardown_cb) :
 | 
			
		||||
    logger(logger_name, begin, end),
 | 
			
		||||
    _async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb))
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline spdlog::async_logger::async_logger(const std::string& logger_name,
 | 
			
		||||
        sinks_init_list sinks_list,
 | 
			
		||||
        size_t queue_size,
 | 
			
		||||
        const  async_overflow_policy overflow_policy,
 | 
			
		||||
        const std::function<void()>& worker_warmup_cb,
 | 
			
		||||
        const std::chrono::milliseconds& flush_interval_ms,
 | 
			
		||||
        const std::function<void()>& worker_teardown_cb) :
 | 
			
		||||
    async_logger(logger_name, sinks_list.begin(), sinks_list.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
 | 
			
		||||
 | 
			
		||||
inline spdlog::async_logger::async_logger(const std::string& logger_name,
 | 
			
		||||
        sink_ptr single_sink,
 | 
			
		||||
        size_t queue_size,
 | 
			
		||||
        const  async_overflow_policy overflow_policy,
 | 
			
		||||
        const std::function<void()>& worker_warmup_cb,
 | 
			
		||||
        const std::chrono::milliseconds& flush_interval_ms,
 | 
			
		||||
        const std::function<void()>& worker_teardown_cb) :
 | 
			
		||||
    async_logger(logger_name,
 | 
			
		||||
{
 | 
			
		||||
    single_sink
 | 
			
		||||
}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline void spdlog::async_logger::flush()
 | 
			
		||||
{
 | 
			
		||||
    _async_log_helper->flush(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error handler
 | 
			
		||||
inline void spdlog::async_logger::set_error_handler(spdlog::log_err_handler err_handler)
 | 
			
		||||
{
 | 
			
		||||
    _err_handler = err_handler;
 | 
			
		||||
    _async_log_helper->set_error_handler(err_handler);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
inline spdlog::log_err_handler spdlog::async_logger::error_handler()
 | 
			
		||||
{
 | 
			
		||||
    return _err_handler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter)
 | 
			
		||||
{
 | 
			
		||||
    _formatter = msg_formatter;
 | 
			
		||||
    _async_log_helper->set_formatter(_formatter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::async_logger::_set_pattern(const std::string& pattern, pattern_time_type pattern_time)
 | 
			
		||||
{
 | 
			
		||||
    _formatter = std::make_shared<pattern_formatter>(pattern, pattern_time);
 | 
			
		||||
    _async_log_helper->set_formatter(_formatter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline void spdlog::async_logger::_sink_it(details::log_msg& msg)
 | 
			
		||||
{
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
 | 
			
		||||
        _incr_msg_counter(msg);
 | 
			
		||||
#endif
 | 
			
		||||
        _async_log_helper->log(msg);
 | 
			
		||||
        if (_should_flush_on(msg))
 | 
			
		||||
            _async_log_helper->flush(false); // do async flush
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception &ex)
 | 
			
		||||
    {
 | 
			
		||||
        _err_handler(ex.what());
 | 
			
		||||
    }
 | 
			
		||||
    catch (...)
 | 
			
		||||
    {
 | 
			
		||||
        _err_handler("Unknown exception");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										117
									
								
								vendor/spdlog/include/spdlog/details/file_helper.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								vendor/spdlog/include/spdlog/details/file_helper.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// Helper class for file sink
 | 
			
		||||
// When failing to open a file, retry several times(5) with small delay between the tries(10 ms)
 | 
			
		||||
// Throw spdlog_ex exception on errors
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/os.h"
 | 
			
		||||
#include "spdlog/details/log_msg.h"
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <cerrno>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
class file_helper
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    const int open_tries = 5;
 | 
			
		||||
    const int open_interval = 10;
 | 
			
		||||
 | 
			
		||||
    explicit file_helper() :
 | 
			
		||||
        _fd(nullptr)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    file_helper(const file_helper&) = delete;
 | 
			
		||||
    file_helper& operator=(const file_helper&) = delete;
 | 
			
		||||
 | 
			
		||||
    ~file_helper()
 | 
			
		||||
    {
 | 
			
		||||
        close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    void open(const filename_t& fname, bool truncate = false)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        close();
 | 
			
		||||
        auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
 | 
			
		||||
        _filename = fname;
 | 
			
		||||
        for (int tries = 0; tries < open_tries; ++tries)
 | 
			
		||||
        {
 | 
			
		||||
            if (!os::fopen_s(&_fd, fname, mode))
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            std::this_thread::sleep_for(std::chrono::milliseconds(open_interval));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reopen(bool truncate)
 | 
			
		||||
    {
 | 
			
		||||
        if (_filename.empty())
 | 
			
		||||
            throw spdlog_ex("Failed re opening file - was not opened before");
 | 
			
		||||
        open(_filename, truncate);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void flush()
 | 
			
		||||
    {
 | 
			
		||||
        std::fflush(_fd);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void close()
 | 
			
		||||
    {
 | 
			
		||||
        if (_fd)
 | 
			
		||||
        {
 | 
			
		||||
            std::fclose(_fd);
 | 
			
		||||
            _fd = nullptr;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void write(const log_msg& msg)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        size_t msg_size = msg.formatted.size();
 | 
			
		||||
        auto data = msg.formatted.data();
 | 
			
		||||
        if (std::fwrite(data, 1, msg_size, _fd) != msg_size)
 | 
			
		||||
            throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t size()
 | 
			
		||||
    {
 | 
			
		||||
        if (!_fd)
 | 
			
		||||
            throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename));
 | 
			
		||||
        return os::filesize(_fd);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const filename_t& filename() const
 | 
			
		||||
    {
 | 
			
		||||
        return _filename;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static bool file_exists(const filename_t& name)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        return os::file_exists(name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    FILE* _fd;
 | 
			
		||||
    filename_t _filename;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								vendor/spdlog/include/spdlog/details/log_msg.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								vendor/spdlog/include/spdlog/details/log_msg.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
#include "spdlog/details/os.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
struct log_msg
 | 
			
		||||
{
 | 
			
		||||
    log_msg() = default;
 | 
			
		||||
    log_msg(const std::string *loggers_name, level::level_enum lvl) :
 | 
			
		||||
        logger_name(loggers_name),
 | 
			
		||||
        level(lvl),
 | 
			
		||||
        msg_id(0)
 | 
			
		||||
    {
 | 
			
		||||
#ifndef SPDLOG_NO_DATETIME
 | 
			
		||||
        time = os::now();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef SPDLOG_NO_THREAD_ID
 | 
			
		||||
        thread_id = os::thread_id();
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    log_msg(const log_msg& other)  = delete;
 | 
			
		||||
    log_msg& operator=(log_msg&& other) = delete;
 | 
			
		||||
    log_msg(log_msg&& other) = delete;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    const std::string *logger_name;
 | 
			
		||||
    level::level_enum level;
 | 
			
		||||
    log_clock::time_point time;
 | 
			
		||||
    size_t thread_id;
 | 
			
		||||
    fmt::MemoryWriter raw;
 | 
			
		||||
    fmt::MemoryWriter formatted;
 | 
			
		||||
    size_t msg_id;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										574
									
								
								vendor/spdlog/include/spdlog/details/logger_impl.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										574
									
								
								vendor/spdlog/include/spdlog/details/logger_impl.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,574 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/logger.h"
 | 
			
		||||
#include "spdlog/sinks/stdout_sinks.h"
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
// create logger with given name, sinks and the default pattern formatter
 | 
			
		||||
// all other ctors will call this one
 | 
			
		||||
template<class It>
 | 
			
		||||
inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end):
 | 
			
		||||
    _name(logger_name),
 | 
			
		||||
    _sinks(begin, end),
 | 
			
		||||
    _formatter(std::make_shared<pattern_formatter>("%+")),
 | 
			
		||||
    _level(level::info),
 | 
			
		||||
    _flush_level(level::off),
 | 
			
		||||
    _last_err_time(0),
 | 
			
		||||
    _msg_counter(1)  // message counter will start from 1. 0-message id will be reserved for controll messages
 | 
			
		||||
{
 | 
			
		||||
    _err_handler = [this](const std::string &msg)
 | 
			
		||||
    {
 | 
			
		||||
        this->_default_err_handler(msg);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ctor with sinks as init list
 | 
			
		||||
inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list):
 | 
			
		||||
    logger(logger_name, sinks_list.begin(), sinks_list.end())
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// ctor with single sink
 | 
			
		||||
inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink):
 | 
			
		||||
    logger(logger_name,
 | 
			
		||||
{
 | 
			
		||||
    single_sink
 | 
			
		||||
})
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline spdlog::logger::~logger() = default;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter)
 | 
			
		||||
{
 | 
			
		||||
    _set_formatter(msg_formatter);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::logger::set_pattern(const std::string& pattern, pattern_time_type pattern_time)
 | 
			
		||||
{
 | 
			
		||||
    _set_pattern(pattern, pattern_time);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (!should_log(lvl)) return;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        details::log_msg log_msg(&_name, lvl);
 | 
			
		||||
 | 
			
		||||
#if defined(SPDLOG_FMT_PRINTF)
 | 
			
		||||
        fmt::printf(log_msg.raw, fmt, args...);
 | 
			
		||||
#else
 | 
			
		||||
        log_msg.raw.write(fmt, args...);
 | 
			
		||||
#endif
 | 
			
		||||
        _sink_it(log_msg);
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception &ex)
 | 
			
		||||
    {
 | 
			
		||||
        _err_handler(ex.what());
 | 
			
		||||
    }
 | 
			
		||||
    SPDLOG_CATCH_ALL
 | 
			
		||||
    {
 | 
			
		||||
        _err_handler("Unknown exception");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::log(level::level_enum lvl, const char* msg)
 | 
			
		||||
{
 | 
			
		||||
    if (!should_log(lvl)) return;
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        details::log_msg log_msg(&_name, lvl);
 | 
			
		||||
        log_msg.raw << msg;
 | 
			
		||||
        _sink_it(log_msg);
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception &ex)
 | 
			
		||||
    {
 | 
			
		||||
        _err_handler(ex.what());
 | 
			
		||||
    }
 | 
			
		||||
    SPDLOG_CATCH_ALL
 | 
			
		||||
    {
 | 
			
		||||
        _err_handler("Unknown exception");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::log(level::level_enum lvl, const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    if (!should_log(lvl)) return;
 | 
			
		||||
    try
 | 
			
		||||
    {
 | 
			
		||||
        details::log_msg log_msg(&_name, lvl);
 | 
			
		||||
        log_msg.raw << msg;
 | 
			
		||||
        _sink_it(log_msg);
 | 
			
		||||
    }
 | 
			
		||||
    catch (const std::exception &ex)
 | 
			
		||||
    {
 | 
			
		||||
        _err_handler(ex.what());
 | 
			
		||||
    }
 | 
			
		||||
    SPDLOG_CATCH_ALL
 | 
			
		||||
    {
 | 
			
		||||
        _err_handler("Unknown exception");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::trace(const char* fmt, const Arg1 &arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::trace, fmt, arg1, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::debug(const char* fmt, const Arg1 &arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::debug, fmt, arg1, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::info(const char* fmt, const Arg1 &arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::info, fmt, arg1, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::warn(const char* fmt, const Arg1 &arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::warn, fmt, arg1, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::error(const char* fmt, const Arg1 &arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::err, fmt, arg1, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::critical(const char* fmt, const Arg1 &arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::critical, fmt, arg1, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::log_if(const bool flag, level::level_enum lvl, const char* msg)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(lvl, msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::log_if(const bool flag, level::level_enum lvl, const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(lvl, msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::trace_if(const bool flag, const char* fmt, const Arg1 &arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::trace, fmt, arg1, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::debug_if(const bool flag, const char* fmt, const Arg1 &arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::debug, fmt, arg1, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::info_if(const bool flag, const char* fmt, const Arg1 &arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::info, fmt, arg1, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::warn_if(const bool flag, const char* fmt, const Arg1& arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::warn, fmt, arg1, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::error_if(const bool flag, const char* fmt, const Arg1 &arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::err, fmt, arg1, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Arg1, typename... Args>
 | 
			
		||||
inline void spdlog::logger::critical_if(const bool flag, const char* fmt, const Arg1 &arg1, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::critical, fmt, arg1, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::trace(const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    log(level::trace, msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::debug(const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    log(level::debug, msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::info(const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    log(level::info, msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::warn(const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    log(level::warn, msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::error(const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    log(level::err, msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::critical(const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    log(level::critical, msg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::trace_if(const bool flag, const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::trace, msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::debug_if(const bool flag, const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::debug, msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::info_if(const bool flag, const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::info, msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::warn_if(const bool flag, const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::warn, msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::error_if(const bool flag, const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::err, msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
inline void spdlog::logger::critical_if(const bool flag, const T& msg)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::critical, msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
 | 
			
		||||
#include <codecvt>
 | 
			
		||||
#include <locale>
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::log(level::level_enum lvl, const wchar_t* msg)
 | 
			
		||||
{
 | 
			
		||||
    std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
 | 
			
		||||
 | 
			
		||||
    log(lvl, conv.to_bytes(msg));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::log(level::level_enum lvl, const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    fmt::WMemoryWriter wWriter;
 | 
			
		||||
 | 
			
		||||
    wWriter.write(fmt, args...);
 | 
			
		||||
    log(lvl, wWriter.c_str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::trace(const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::trace, fmt, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::debug(const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::debug, fmt, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::info(const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::info, fmt, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::warn(const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::warn, fmt, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::error(const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::err, fmt, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::critical(const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    log(level::critical, fmt, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// conditional logging
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::log_if(const bool flag, level::level_enum lvl, const wchar_t* msg)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(lvl, msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::log_if(const bool flag, level::level_enum lvl, const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(lvl, fmt, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::trace_if(const bool flag, const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::trace, fmt, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::debug_if(const bool flag, const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::debug, fmt, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::info_if(const bool flag, const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::info, fmt, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::warn_if(const bool flag, const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::warn, fmt, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::error_if(const bool flag, const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::err, fmt, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
inline void spdlog::logger::critical_if(const bool flag, const wchar_t* fmt, const Args&... args)
 | 
			
		||||
{
 | 
			
		||||
    if (flag)
 | 
			
		||||
    {
 | 
			
		||||
        log(level::critical, fmt, args...);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// name and level
 | 
			
		||||
//
 | 
			
		||||
inline const std::string& spdlog::logger::name() const
 | 
			
		||||
{
 | 
			
		||||
    return _name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
 | 
			
		||||
{
 | 
			
		||||
    _level.store(log_level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler)
 | 
			
		||||
{
 | 
			
		||||
    _err_handler = err_handler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline spdlog::log_err_handler spdlog::logger::error_handler()
 | 
			
		||||
{
 | 
			
		||||
    return _err_handler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline void spdlog::logger::flush_on(level::level_enum log_level)
 | 
			
		||||
{
 | 
			
		||||
    _flush_level.store(log_level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline spdlog::level::level_enum spdlog::logger::level() const
 | 
			
		||||
{
 | 
			
		||||
    return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) const
 | 
			
		||||
{
 | 
			
		||||
    return msg_level >= _level.load(std::memory_order_relaxed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// protected virtual called at end of each user log call (if enabled) by the line_logger
 | 
			
		||||
//
 | 
			
		||||
inline void spdlog::logger::_sink_it(details::log_msg& msg)
 | 
			
		||||
{
 | 
			
		||||
#if defined(SPDLOG_ENABLE_MESSAGE_COUNTER)
 | 
			
		||||
    _incr_msg_counter(msg);
 | 
			
		||||
#endif
 | 
			
		||||
    _formatter->format(msg);
 | 
			
		||||
    for (auto &sink : _sinks)
 | 
			
		||||
    {
 | 
			
		||||
        if( sink->should_log( msg.level))
 | 
			
		||||
        {
 | 
			
		||||
            sink->log(msg);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(_should_flush_on(msg))
 | 
			
		||||
        flush();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::logger::_set_pattern(const std::string& pattern, pattern_time_type pattern_time)
 | 
			
		||||
{
 | 
			
		||||
    _formatter = std::make_shared<pattern_formatter>(pattern, pattern_time);
 | 
			
		||||
}
 | 
			
		||||
inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter)
 | 
			
		||||
{
 | 
			
		||||
    _formatter = msg_formatter;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::logger::flush()
 | 
			
		||||
{
 | 
			
		||||
    for (auto& sink : _sinks)
 | 
			
		||||
        sink->flush();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::logger::_default_err_handler(const std::string &msg)
 | 
			
		||||
{
 | 
			
		||||
    auto now = time(nullptr);
 | 
			
		||||
    if (now - _last_err_time < 60)
 | 
			
		||||
        return;
 | 
			
		||||
    auto tm_time = details::os::localtime(now);
 | 
			
		||||
    char date_buf[100];
 | 
			
		||||
    std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
 | 
			
		||||
    details::log_msg  err_msg;
 | 
			
		||||
    err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::eol);
 | 
			
		||||
    sinks::stderr_sink_mt::instance()->log(err_msg);
 | 
			
		||||
    _last_err_time = now;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool spdlog::logger::_should_flush_on(const details::log_msg &msg)
 | 
			
		||||
{
 | 
			
		||||
    const auto flush_level = _flush_level.load(std::memory_order_relaxed);
 | 
			
		||||
    return (msg.level >= flush_level) && (msg.level != level::off);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::logger::_incr_msg_counter(details::log_msg &msg)
 | 
			
		||||
{
 | 
			
		||||
    msg.msg_id = _msg_counter.fetch_add(1, std::memory_order_relaxed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline const std::vector<spdlog::sink_ptr>& spdlog::logger::sinks() const
 | 
			
		||||
{
 | 
			
		||||
    return _sinks;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#undef SPDLOG_CATCH_ALL
 | 
			
		||||
							
								
								
									
										172
									
								
								vendor/spdlog/include/spdlog/details/mpmc_bounded_q.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								vendor/spdlog/include/spdlog/details/mpmc_bounded_q.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,172 @@
 | 
			
		||||
/*
 | 
			
		||||
A modified version of Bounded MPMC queue by Dmitry Vyukov.
 | 
			
		||||
 | 
			
		||||
Original code from:
 | 
			
		||||
http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
 | 
			
		||||
 | 
			
		||||
licensed by Dmitry Vyukov under the terms below:
 | 
			
		||||
 | 
			
		||||
Simplified BSD license
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
 | 
			
		||||
Redistribution and use in source and binary forms, with or without modification,
 | 
			
		||||
are permitted provided that the following conditions are met:
 | 
			
		||||
1. Redistributions of source code must retain the above copyright notice, this list of
 | 
			
		||||
conditions and the following disclaimer.
 | 
			
		||||
 | 
			
		||||
2. Redistributions in binary form must reproduce the above copyright notice, this list
 | 
			
		||||
of conditions and the following disclaimer in the documentation and/or other materials
 | 
			
		||||
provided with the distribution.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 | 
			
		||||
SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 | 
			
		||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 | 
			
		||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 | 
			
		||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
The views and conclusions contained in the software and documentation are those of the authors and
 | 
			
		||||
should not be interpreted as representing official policies, either expressed or implied, of Dmitry Vyukov.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
The code in its current form adds the license below:
 | 
			
		||||
 | 
			
		||||
Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
class mpmc_bounded_queue
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    using item_type = T;
 | 
			
		||||
    mpmc_bounded_queue(size_t buffer_size)
 | 
			
		||||
        :max_size_(buffer_size),
 | 
			
		||||
         buffer_(new cell_t [buffer_size]),
 | 
			
		||||
         buffer_mask_(buffer_size - 1)
 | 
			
		||||
    {
 | 
			
		||||
        //queue size must be power of two
 | 
			
		||||
        if(!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0)))
 | 
			
		||||
            throw spdlog_ex("async logger queue size must be power of two");
 | 
			
		||||
 | 
			
		||||
        for (size_t i = 0; i != buffer_size; i += 1)
 | 
			
		||||
            buffer_[i].sequence_.store(i, std::memory_order_relaxed);
 | 
			
		||||
        enqueue_pos_.store(0, std::memory_order_relaxed);
 | 
			
		||||
        dequeue_pos_.store(0, std::memory_order_relaxed);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~mpmc_bounded_queue()
 | 
			
		||||
    {
 | 
			
		||||
        delete [] buffer_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    bool enqueue(T&& data)
 | 
			
		||||
    {
 | 
			
		||||
        cell_t* cell;
 | 
			
		||||
        size_t pos = enqueue_pos_.load(std::memory_order_relaxed);
 | 
			
		||||
        for (;;)
 | 
			
		||||
        {
 | 
			
		||||
            cell = &buffer_[pos & buffer_mask_];
 | 
			
		||||
            size_t seq = cell->sequence_.load(std::memory_order_acquire);
 | 
			
		||||
            intptr_t dif = static_cast<intptr_t>(seq) - static_cast<intptr_t>(pos);
 | 
			
		||||
            if (dif == 0)
 | 
			
		||||
            {
 | 
			
		||||
                if (enqueue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            else if (dif < 0)
 | 
			
		||||
            {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                pos = enqueue_pos_.load(std::memory_order_relaxed);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        cell->data_ = std::move(data);
 | 
			
		||||
        cell->sequence_.store(pos + 1, std::memory_order_release);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool dequeue(T& data)
 | 
			
		||||
    {
 | 
			
		||||
        cell_t* cell;
 | 
			
		||||
        size_t pos = dequeue_pos_.load(std::memory_order_relaxed);
 | 
			
		||||
        for (;;)
 | 
			
		||||
        {
 | 
			
		||||
            cell = &buffer_[pos & buffer_mask_];
 | 
			
		||||
            size_t seq =
 | 
			
		||||
                cell->sequence_.load(std::memory_order_acquire);
 | 
			
		||||
            intptr_t dif = static_cast<intptr_t>(seq) - static_cast<intptr_t>(pos + 1);
 | 
			
		||||
            if (dif == 0)
 | 
			
		||||
            {
 | 
			
		||||
                if (dequeue_pos_.compare_exchange_weak(pos, pos + 1, std::memory_order_relaxed))
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            else if (dif < 0)
 | 
			
		||||
                return false;
 | 
			
		||||
            else
 | 
			
		||||
                pos = dequeue_pos_.load(std::memory_order_relaxed);
 | 
			
		||||
        }
 | 
			
		||||
        data = std::move(cell->data_);
 | 
			
		||||
        cell->sequence_.store(pos + buffer_mask_ + 1, std::memory_order_release);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t approx_size()
 | 
			
		||||
    {
 | 
			
		||||
        size_t first_pos = dequeue_pos_.load(std::memory_order_relaxed);
 | 
			
		||||
        size_t last_pos = enqueue_pos_.load(std::memory_order_relaxed);
 | 
			
		||||
        if (last_pos <= first_pos)
 | 
			
		||||
            return 0;
 | 
			
		||||
        auto size = last_pos - first_pos;
 | 
			
		||||
        return size < max_size_ ? size : max_size_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    struct cell_t
 | 
			
		||||
    {
 | 
			
		||||
        std::atomic<size_t>   sequence_;
 | 
			
		||||
        T                     data_;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    size_t const max_size_;
 | 
			
		||||
 | 
			
		||||
    static size_t const     cacheline_size = 64;
 | 
			
		||||
    typedef char            cacheline_pad_t [cacheline_size];
 | 
			
		||||
 | 
			
		||||
    cacheline_pad_t         pad0_;
 | 
			
		||||
    cell_t* const           buffer_;
 | 
			
		||||
    size_t const            buffer_mask_;
 | 
			
		||||
    cacheline_pad_t         pad1_;
 | 
			
		||||
    std::atomic<size_t>     enqueue_pos_;
 | 
			
		||||
    cacheline_pad_t         pad2_;
 | 
			
		||||
    std::atomic<size_t>     dequeue_pos_;
 | 
			
		||||
    cacheline_pad_t         pad3_;
 | 
			
		||||
 | 
			
		||||
    mpmc_bounded_queue(mpmc_bounded_queue const&) = delete;
 | 
			
		||||
    void operator= (mpmc_bounded_queue const&) = delete;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // ns details
 | 
			
		||||
} // ns spdlog
 | 
			
		||||
							
								
								
									
										45
									
								
								vendor/spdlog/include/spdlog/details/null_mutex.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								vendor/spdlog/include/spdlog/details/null_mutex.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
// null, no cost dummy "mutex" and dummy "atomic" int
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
struct null_mutex
 | 
			
		||||
{
 | 
			
		||||
    void lock() {}
 | 
			
		||||
    void unlock() {}
 | 
			
		||||
    bool try_lock()
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct null_atomic_int
 | 
			
		||||
{
 | 
			
		||||
    int value;
 | 
			
		||||
    null_atomic_int() = default;
 | 
			
		||||
 | 
			
		||||
    null_atomic_int(int val):value(val)
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    int load(std::memory_order) const
 | 
			
		||||
    {
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void store(int val)
 | 
			
		||||
    {
 | 
			
		||||
        value = val;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										469
									
								
								vendor/spdlog/include/spdlog/details/os.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										469
									
								
								vendor/spdlog/include/spdlog/details/os.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,469 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <ctime>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
 | 
			
		||||
#ifndef NOMINMAX
 | 
			
		||||
#define NOMINMAX //prevent windows redefining min/max
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef WIN32_LEAN_AND_MEAN
 | 
			
		||||
#define WIN32_LEAN_AND_MEAN
 | 
			
		||||
#endif
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
#include <process.h> //  _get_pid support
 | 
			
		||||
#include <io.h> // _get_osfhandle and _isatty support
 | 
			
		||||
 | 
			
		||||
#ifdef __MINGW32__
 | 
			
		||||
#include <share.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#else // unix
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __linux__
 | 
			
		||||
#include <sys/syscall.h> //Use gettid() syscall under linux to get thread id
 | 
			
		||||
 | 
			
		||||
#elif __FreeBSD__
 | 
			
		||||
#include <sys/thr.h> //Use thr_self() syscall under FreeBSD to get thread id
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif //unix
 | 
			
		||||
 | 
			
		||||
#ifndef __has_feature       // Clang - feature checking macros.
 | 
			
		||||
#define __has_feature(x) 0  // Compatibility with non-clang compilers.
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
namespace os
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
inline spdlog::log_clock::time_point now()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#if defined __linux__ && defined SPDLOG_CLOCK_COARSE
 | 
			
		||||
    timespec ts;
 | 
			
		||||
    ::clock_gettime(CLOCK_REALTIME_COARSE, &ts);
 | 
			
		||||
    return std::chrono::time_point<log_clock, typename log_clock::duration>(
 | 
			
		||||
               std::chrono::duration_cast<typename log_clock::duration>(
 | 
			
		||||
                   std::chrono::seconds(ts.tv_sec) + std::chrono::nanoseconds(ts.tv_nsec)));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
    return log_clock::now();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
inline std::tm localtime(const std::time_t &time_tt)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    std::tm tm;
 | 
			
		||||
    localtime_s(&tm, &time_tt);
 | 
			
		||||
#else
 | 
			
		||||
    std::tm tm;
 | 
			
		||||
    localtime_r(&time_tt, &tm);
 | 
			
		||||
#endif
 | 
			
		||||
    return tm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::tm localtime()
 | 
			
		||||
{
 | 
			
		||||
    std::time_t now_t = time(nullptr);
 | 
			
		||||
    return localtime(now_t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline std::tm gmtime(const std::time_t &time_tt)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    std::tm tm;
 | 
			
		||||
    gmtime_s(&tm, &time_tt);
 | 
			
		||||
#else
 | 
			
		||||
    std::tm tm;
 | 
			
		||||
    gmtime_r(&time_tt, &tm);
 | 
			
		||||
#endif
 | 
			
		||||
    return tm;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::tm gmtime()
 | 
			
		||||
{
 | 
			
		||||
    std::time_t now_t = time(nullptr);
 | 
			
		||||
    return gmtime(now_t);
 | 
			
		||||
}
 | 
			
		||||
inline bool operator==(const std::tm& tm1, const std::tm& tm2)
 | 
			
		||||
{
 | 
			
		||||
    return (tm1.tm_sec == tm2.tm_sec &&
 | 
			
		||||
            tm1.tm_min == tm2.tm_min &&
 | 
			
		||||
            tm1.tm_hour == tm2.tm_hour &&
 | 
			
		||||
            tm1.tm_mday == tm2.tm_mday &&
 | 
			
		||||
            tm1.tm_mon == tm2.tm_mon &&
 | 
			
		||||
            tm1.tm_year == tm2.tm_year &&
 | 
			
		||||
            tm1.tm_isdst == tm2.tm_isdst);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
 | 
			
		||||
{
 | 
			
		||||
    return !(tm1 == tm2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// eol definition
 | 
			
		||||
#if !defined (SPDLOG_EOL)
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#define SPDLOG_EOL "\r\n"
 | 
			
		||||
#else
 | 
			
		||||
#define SPDLOG_EOL "\n"
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
SPDLOG_CONSTEXPR static const char* eol = SPDLOG_EOL;
 | 
			
		||||
SPDLOG_CONSTEXPR static int eol_size = sizeof(SPDLOG_EOL) - 1;
 | 
			
		||||
 | 
			
		||||
inline void prevent_child_fd(FILE *f)
 | 
			
		||||
{
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    auto file_handle = (HANDLE)_get_osfhandle(_fileno(f));
 | 
			
		||||
    if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0))
 | 
			
		||||
        throw spdlog_ex("SetHandleInformation failed", errno);
 | 
			
		||||
#else
 | 
			
		||||
    auto fd = fileno(f);
 | 
			
		||||
    if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
 | 
			
		||||
        throw spdlog_ex("fcntl with FD_CLOEXEC failed", errno);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//fopen_s on non windows for writing
 | 
			
		||||
inline int fopen_s(FILE** fp, const filename_t& filename, const filename_t& mode)
 | 
			
		||||
{
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#ifdef SPDLOG_WCHAR_FILENAMES
 | 
			
		||||
    *fp = _wfsopen((filename.c_str()), mode.c_str(), _SH_DENYWR);
 | 
			
		||||
#else
 | 
			
		||||
    *fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYWR);
 | 
			
		||||
#endif
 | 
			
		||||
#else //unix
 | 
			
		||||
    *fp = fopen((filename.c_str()), mode.c_str());
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SPDLOG_PREVENT_CHILD_FD
 | 
			
		||||
    if (*fp != nullptr)
 | 
			
		||||
        prevent_child_fd(*fp);
 | 
			
		||||
#endif
 | 
			
		||||
    return *fp == nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline int remove(const filename_t &filename)
 | 
			
		||||
{
 | 
			
		||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
 | 
			
		||||
    return _wremove(filename.c_str());
 | 
			
		||||
#else
 | 
			
		||||
    return std::remove(filename.c_str());
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline int rename(const filename_t& filename1, const filename_t& filename2)
 | 
			
		||||
{
 | 
			
		||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
 | 
			
		||||
    return _wrename(filename1.c_str(), filename2.c_str());
 | 
			
		||||
#else
 | 
			
		||||
    return std::rename(filename1.c_str(), filename2.c_str());
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Return if file exists
 | 
			
		||||
inline bool file_exists(const filename_t& filename)
 | 
			
		||||
{
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#ifdef SPDLOG_WCHAR_FILENAMES
 | 
			
		||||
    auto attribs = GetFileAttributesW(filename.c_str());
 | 
			
		||||
#else
 | 
			
		||||
    auto attribs = GetFileAttributesA(filename.c_str());
 | 
			
		||||
#endif
 | 
			
		||||
    return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY));
 | 
			
		||||
#else //common linux/unix all have the stat system call
 | 
			
		||||
    struct stat buffer;
 | 
			
		||||
    return (stat(filename.c_str(), &buffer) == 0);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Return file size according to open FILE* object
 | 
			
		||||
inline size_t filesize(FILE *f)
 | 
			
		||||
{
 | 
			
		||||
    if (f == nullptr)
 | 
			
		||||
        throw spdlog_ex("Failed getting file size. fd is null");
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    int fd = _fileno(f);
 | 
			
		||||
#if _WIN64 //64 bits
 | 
			
		||||
    struct _stat64 st;
 | 
			
		||||
    if (_fstat64(fd, &st) == 0)
 | 
			
		||||
        return st.st_size;
 | 
			
		||||
 | 
			
		||||
#else //windows 32 bits
 | 
			
		||||
    long ret = _filelength(fd);
 | 
			
		||||
    if (ret >= 0)
 | 
			
		||||
        return static_cast<size_t>(ret);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#else // unix
 | 
			
		||||
    int fd = fileno(f);
 | 
			
		||||
    //64 bits(but not in osx, where fstat64 is deprecated)
 | 
			
		||||
#if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__))
 | 
			
		||||
    struct stat64 st;
 | 
			
		||||
    if (fstat64(fd, &st) == 0)
 | 
			
		||||
        return static_cast<size_t>(st.st_size);
 | 
			
		||||
#else // unix 32 bits or osx
 | 
			
		||||
    struct stat st;
 | 
			
		||||
    if (fstat(fd, &st) == 0)
 | 
			
		||||
        return static_cast<size_t>(st.st_size);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
    throw spdlog_ex("Failed getting file size from fd", errno);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Return utc offset in minutes or throw spdlog_ex on failure
 | 
			
		||||
inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#if _WIN32_WINNT < _WIN32_WINNT_WS08
 | 
			
		||||
    TIME_ZONE_INFORMATION tzinfo;
 | 
			
		||||
    auto rv = GetTimeZoneInformation(&tzinfo);
 | 
			
		||||
#else
 | 
			
		||||
    DYNAMIC_TIME_ZONE_INFORMATION tzinfo;
 | 
			
		||||
    auto rv = GetDynamicTimeZoneInformation(&tzinfo);
 | 
			
		||||
#endif
 | 
			
		||||
    if (rv == TIME_ZONE_ID_INVALID)
 | 
			
		||||
        throw spdlog::spdlog_ex("Failed getting timezone info. ", errno);
 | 
			
		||||
 | 
			
		||||
    int offset = -tzinfo.Bias;
 | 
			
		||||
    if (tm.tm_isdst)
 | 
			
		||||
        offset -= tzinfo.DaylightBias;
 | 
			
		||||
    else
 | 
			
		||||
        offset -= tzinfo.StandardBias;
 | 
			
		||||
    return offset;
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#if defined(sun) || defined(__sun)
 | 
			
		||||
    // 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
 | 
			
		||||
    struct helper
 | 
			
		||||
    {
 | 
			
		||||
        static long int calculate_gmt_offset(const std::tm & localtm = details::os::localtime(), const std::tm & gmtm = details::os::gmtime())
 | 
			
		||||
        {
 | 
			
		||||
            int local_year = localtm.tm_year + (1900 - 1);
 | 
			
		||||
            int gmt_year = gmtm.tm_year + (1900 - 1);
 | 
			
		||||
 | 
			
		||||
            long int days = (
 | 
			
		||||
                                // difference in day of year
 | 
			
		||||
                                localtm.tm_yday - gmtm.tm_yday
 | 
			
		||||
 | 
			
		||||
                                // + intervening leap days
 | 
			
		||||
                                + ((local_year >> 2) - (gmt_year >> 2))
 | 
			
		||||
                                - (local_year / 100 - gmt_year / 100)
 | 
			
		||||
                                + ((local_year / 100 >> 2) - (gmt_year / 100 >> 2))
 | 
			
		||||
 | 
			
		||||
                                // + difference in years * 365 */
 | 
			
		||||
                                + (long int)(local_year - gmt_year) * 365
 | 
			
		||||
                            );
 | 
			
		||||
 | 
			
		||||
            long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour);
 | 
			
		||||
            long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min);
 | 
			
		||||
            long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec);
 | 
			
		||||
 | 
			
		||||
            return secs;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    long int offset_seconds = helper::calculate_gmt_offset(tm);
 | 
			
		||||
#else
 | 
			
		||||
    long int offset_seconds = tm.tm_gmtoff;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return static_cast<int>(offset_seconds / 60);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Return current thread id as size_t
 | 
			
		||||
//It exists because the std::this_thread::get_id() is much slower(espcially under VS 2013)
 | 
			
		||||
inline size_t _thread_id()
 | 
			
		||||
{
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    return  static_cast<size_t>(::GetCurrentThreadId());
 | 
			
		||||
#elif __linux__
 | 
			
		||||
# if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21)
 | 
			
		||||
#  define SYS_gettid __NR_gettid
 | 
			
		||||
# endif
 | 
			
		||||
    return  static_cast<size_t>(syscall(SYS_gettid));
 | 
			
		||||
#elif __FreeBSD__
 | 
			
		||||
    long tid;
 | 
			
		||||
    thr_self(&tid);
 | 
			
		||||
    return static_cast<size_t>(tid);
 | 
			
		||||
#elif __APPLE__
 | 
			
		||||
    uint64_t tid;
 | 
			
		||||
    pthread_threadid_np(nullptr, &tid);
 | 
			
		||||
    return static_cast<size_t>(tid);
 | 
			
		||||
#else //Default to standard C++11 (other Unix)
 | 
			
		||||
    return static_cast<size_t>(std::hash<std::thread::id>()(std::this_thread::get_id()));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Return current thread id as size_t (from thread local storage)
 | 
			
		||||
inline size_t thread_id()
 | 
			
		||||
{
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER < 1900) || defined(__clang__) && !__has_feature(cxx_thread_local)
 | 
			
		||||
    return _thread_id();
 | 
			
		||||
#else
 | 
			
		||||
    static thread_local const size_t tid = _thread_id();
 | 
			
		||||
    return tid;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
 | 
			
		||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
 | 
			
		||||
#define SPDLOG_FILENAME_T(s) L ## s
 | 
			
		||||
inline std::string filename_to_str(const filename_t& filename)
 | 
			
		||||
{
 | 
			
		||||
    std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> c;
 | 
			
		||||
    return c.to_bytes(filename);
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
#define SPDLOG_FILENAME_T(s) s
 | 
			
		||||
inline std::string filename_to_str(const filename_t& filename)
 | 
			
		||||
{
 | 
			
		||||
    return filename;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
inline std::string errno_to_string(char[256], char* res)
 | 
			
		||||
{
 | 
			
		||||
    return std::string(res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::string errno_to_string(char buf[256], int res)
 | 
			
		||||
{
 | 
			
		||||
    if (res == 0)
 | 
			
		||||
    {
 | 
			
		||||
        return std::string(buf);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        return "Unknown error";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Return errno string (thread safe)
 | 
			
		||||
inline std::string errno_str(int err_num)
 | 
			
		||||
{
 | 
			
		||||
    char buf[256];
 | 
			
		||||
    SPDLOG_CONSTEXPR auto buf_size = sizeof(buf);
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    if (strerror_s(buf, buf_size, err_num) == 0)
 | 
			
		||||
        return std::string(buf);
 | 
			
		||||
    else
 | 
			
		||||
        return "Unknown error";
 | 
			
		||||
 | 
			
		||||
#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || defined(__SUNPRO_CC) || \
 | 
			
		||||
      ((_POSIX_C_SOURCE >= 200112L) && ! defined(_GNU_SOURCE)) // posix version
 | 
			
		||||
 | 
			
		||||
    if (strerror_r(err_num, buf, buf_size) == 0)
 | 
			
		||||
        return std::string(buf);
 | 
			
		||||
    else
 | 
			
		||||
        return "Unknown error";
 | 
			
		||||
 | 
			
		||||
#else  // gnu version (might not use the given buf, so its retval pointer must be used)
 | 
			
		||||
    auto err = strerror_r(err_num, buf, buf_size); // let compiler choose type
 | 
			
		||||
    return errno_to_string(buf, err); // use overloading to select correct stringify function
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline int pid()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    return ::_getpid();
 | 
			
		||||
#else
 | 
			
		||||
    return static_cast<int>(::getpid());
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Detrmine if the terminal supports colors
 | 
			
		||||
// Source: https://github.com/agauniyal/rang/
 | 
			
		||||
inline bool is_color_terminal()
 | 
			
		||||
{
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    return true;
 | 
			
		||||
#else
 | 
			
		||||
    static constexpr const char* Terms[] =
 | 
			
		||||
    {
 | 
			
		||||
        "ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm",
 | 
			
		||||
        "linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm"
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const char *env_p = std::getenv("TERM");
 | 
			
		||||
    if (env_p == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static const bool result = std::any_of(
 | 
			
		||||
                                   std::begin(Terms), std::end(Terms), [&](const char* term)
 | 
			
		||||
    {
 | 
			
		||||
        return std::strstr(env_p, term) != nullptr;
 | 
			
		||||
    });
 | 
			
		||||
    return result;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Detrmine if the terminal attached
 | 
			
		||||
// Source: https://github.com/agauniyal/rang/
 | 
			
		||||
inline bool in_terminal(FILE* file)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    return _isatty(_fileno(file)) ? true : false;
 | 
			
		||||
#else
 | 
			
		||||
    return isatty(fileno(file)) ? true : false;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
} //os
 | 
			
		||||
} //details
 | 
			
		||||
} //spdlog
 | 
			
		||||
							
								
								
									
										686
									
								
								vendor/spdlog/include/spdlog/details/pattern_formatter_impl.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										686
									
								
								vendor/spdlog/include/spdlog/details/pattern_formatter_impl.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,686 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/formatter.h"
 | 
			
		||||
#include "spdlog/details/log_msg.h"
 | 
			
		||||
#include "spdlog/details/os.h"
 | 
			
		||||
#include "spdlog/fmt/fmt.h"
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <ctime>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <array>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
class flag_formatter
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~flag_formatter()
 | 
			
		||||
    {}
 | 
			
		||||
    virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////
 | 
			
		||||
// name & level pattern appenders
 | 
			
		||||
///////////////////////////////////////////////////////////////////////
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
class name_formatter:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << *msg.logger_name;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// log level appender
 | 
			
		||||
class level_formatter:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << level::to_str(msg.level);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// short log level appender
 | 
			
		||||
class short_level_formatter:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << level::to_short_str(msg.level);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Date time pattern appenders
 | 
			
		||||
///////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
static const char* ampm(const tm& t)
 | 
			
		||||
{
 | 
			
		||||
    return t.tm_hour >= 12 ? "PM" : "AM";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int to12h(const tm& t)
 | 
			
		||||
{
 | 
			
		||||
    return t.tm_hour > 12 ? t.tm_hour - 12 : t.tm_hour;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Abbreviated weekday name
 | 
			
		||||
static const std::string days[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
 | 
			
		||||
class a_formatter:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << days[tm_time.tm_wday];
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//Full weekday name
 | 
			
		||||
static const std::string full_days[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
 | 
			
		||||
class A_formatter:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << full_days[tm_time.tm_wday];
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//Abbreviated month
 | 
			
		||||
static const std::string  months[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec" };
 | 
			
		||||
class b_formatter:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << months[tm_time.tm_mon];
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//Full month name
 | 
			
		||||
static const std::string full_months[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
 | 
			
		||||
class B_formatter:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << full_months[tm_time.tm_mon];
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//write 2 ints separated by sep with padding of 2
 | 
			
		||||
static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, char sep)
 | 
			
		||||
{
 | 
			
		||||
    w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0');
 | 
			
		||||
    return w;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//write 3 ints separated by sep with padding of 2
 | 
			
		||||
static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v3, char sep)
 | 
			
		||||
{
 | 
			
		||||
    w << fmt::pad(v1, 2, '0') << sep << fmt::pad(v2, 2, '0') << sep << fmt::pad(v3, 2, '0');
 | 
			
		||||
    return w;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//Date and time representation (Thu Aug 23 15:35:46 2014)
 | 
			
		||||
class c_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << days[tm_time.tm_wday] << ' ' << months[tm_time.tm_mon] << ' ' << tm_time.tm_mday << ' ';
 | 
			
		||||
        pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << tm_time.tm_year + 1900;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// year - 2 digit
 | 
			
		||||
class C_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << fmt::pad(tm_time.tm_year % 100, 2, '0');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01
 | 
			
		||||
class D_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        pad_n_join(msg.formatted, tm_time.tm_mon + 1, tm_time.tm_mday, tm_time.tm_year % 100, '/');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// year - 4 digit
 | 
			
		||||
class Y_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << tm_time.tm_year + 1900;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// month 1-12
 | 
			
		||||
class m_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << fmt::pad(tm_time.tm_mon + 1, 2, '0');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// day of month 1-31
 | 
			
		||||
class d_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << fmt::pad(tm_time.tm_mday, 2, '0');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// hours in 24 format  0-23
 | 
			
		||||
class H_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << fmt::pad(tm_time.tm_hour, 2, '0');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// hours in 12 format  1-12
 | 
			
		||||
class I_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << fmt::pad(to12h(tm_time), 2, '0');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// minutes 0-59
 | 
			
		||||
class M_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << fmt::pad(tm_time.tm_min, 2, '0');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// seconds 0-59
 | 
			
		||||
class S_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << fmt::pad(tm_time.tm_sec, 2, '0');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// milliseconds
 | 
			
		||||
class e_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        auto duration = msg.time.time_since_epoch();
 | 
			
		||||
        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
 | 
			
		||||
        msg.formatted << fmt::pad(static_cast<int>(millis), 3, '0');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// microseconds
 | 
			
		||||
class f_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        auto duration = msg.time.time_since_epoch();
 | 
			
		||||
        auto micros = std::chrono::duration_cast<std::chrono::microseconds>(duration).count() % 1000000;
 | 
			
		||||
        msg.formatted << fmt::pad(static_cast<int>(micros), 6, '0');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// nanoseconds
 | 
			
		||||
class F_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        auto duration = msg.time.time_since_epoch();
 | 
			
		||||
        auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count() % 1000000000;
 | 
			
		||||
        msg.formatted << fmt::pad(static_cast<int>(ns), 9, '0');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class E_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        auto duration = msg.time.time_since_epoch();
 | 
			
		||||
        auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
 | 
			
		||||
        msg.formatted << seconds;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// AM/PM
 | 
			
		||||
class p_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << ampm(tm_time);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// 12 hour clock 02:55:02 pm
 | 
			
		||||
class r_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        pad_n_join(msg.formatted, to12h(tm_time), tm_time.tm_min, tm_time.tm_sec, ':') << ' ' << ampm(tm_time);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 24-hour HH:MM time, equivalent to %H:%M
 | 
			
		||||
class R_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, ':');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
 | 
			
		||||
class T_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
        pad_n_join(msg.formatted, tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec, ':');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ISO 8601 offset from UTC in timezone (+-HH:MM)
 | 
			
		||||
class z_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    const std::chrono::seconds cache_refresh = std::chrono::seconds(5);
 | 
			
		||||
 | 
			
		||||
    z_formatter():_last_update(std::chrono::seconds(0)), _offset_minutes(0)
 | 
			
		||||
    {}
 | 
			
		||||
    z_formatter(const z_formatter&) = delete;
 | 
			
		||||
    z_formatter& operator=(const z_formatter&) = delete;
 | 
			
		||||
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
        int total_minutes = get_cached_offset(msg, tm_time);
 | 
			
		||||
#else
 | 
			
		||||
        // No need to chache under gcc,
 | 
			
		||||
        // it is very fast (already stored in tm.tm_gmtoff)
 | 
			
		||||
        int total_minutes = os::utc_minutes_offset(tm_time);
 | 
			
		||||
#endif
 | 
			
		||||
        bool is_negative = total_minutes < 0;
 | 
			
		||||
        char sign;
 | 
			
		||||
        if (is_negative)
 | 
			
		||||
        {
 | 
			
		||||
            total_minutes = -total_minutes;
 | 
			
		||||
            sign = '-';
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            sign = '+';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int h = total_minutes / 60;
 | 
			
		||||
        int m = total_minutes % 60;
 | 
			
		||||
        msg.formatted << sign;
 | 
			
		||||
        pad_n_join(msg.formatted, h, m, ':');
 | 
			
		||||
    }
 | 
			
		||||
private:
 | 
			
		||||
    log_clock::time_point _last_update;
 | 
			
		||||
    int _offset_minutes;
 | 
			
		||||
    std::mutex _mutex;
 | 
			
		||||
 | 
			
		||||
    int get_cached_offset(const log_msg& msg, const std::tm& tm_time)
 | 
			
		||||
    {
 | 
			
		||||
        using namespace std::chrono;
 | 
			
		||||
        std::lock_guard<std::mutex> l(_mutex);
 | 
			
		||||
        if (msg.time - _last_update >= cache_refresh)
 | 
			
		||||
        {
 | 
			
		||||
            _offset_minutes = os::utc_minutes_offset(tm_time);
 | 
			
		||||
            _last_update = msg.time;
 | 
			
		||||
        }
 | 
			
		||||
        return _offset_minutes;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Thread id
 | 
			
		||||
class t_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << msg.thread_id;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Current pid
 | 
			
		||||
class pid_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << details::os::pid();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// message counter formatter
 | 
			
		||||
class i_formatter SPDLOG_FINAL :public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << fmt::pad(msg.msg_id, 6, '0');
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class v_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ch_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    explicit ch_formatter(char ch): _ch(ch)
 | 
			
		||||
    {}
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << _ch;
 | 
			
		||||
    }
 | 
			
		||||
private:
 | 
			
		||||
    char _ch;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//aggregate user chars to display as is
 | 
			
		||||
class aggregate_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    aggregate_formatter()
 | 
			
		||||
    {}
 | 
			
		||||
    void add_ch(char ch)
 | 
			
		||||
    {
 | 
			
		||||
        _str += ch;
 | 
			
		||||
    }
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm&) override
 | 
			
		||||
    {
 | 
			
		||||
        msg.formatted << _str;
 | 
			
		||||
    }
 | 
			
		||||
private:
 | 
			
		||||
    std::string _str;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Full info formatter
 | 
			
		||||
// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v
 | 
			
		||||
class full_formatter SPDLOG_FINAL:public flag_formatter
 | 
			
		||||
{
 | 
			
		||||
    void format(details::log_msg& msg, const std::tm& tm_time) override
 | 
			
		||||
    {
 | 
			
		||||
#ifndef SPDLOG_NO_DATETIME
 | 
			
		||||
        auto duration = msg.time.time_since_epoch();
 | 
			
		||||
        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 1000;
 | 
			
		||||
 | 
			
		||||
        /* Slower version(while still very fast - about 3.2 million lines/sec under 10 threads),
 | 
			
		||||
        msg.formatted.write("[{:d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}.{:03d}] [{}] [{}] {} ",
 | 
			
		||||
        tm_time.tm_year + 1900,
 | 
			
		||||
        tm_time.tm_mon + 1,
 | 
			
		||||
        tm_time.tm_mday,
 | 
			
		||||
        tm_time.tm_hour,
 | 
			
		||||
        tm_time.tm_min,
 | 
			
		||||
        tm_time.tm_sec,
 | 
			
		||||
        static_cast<int>(millis),
 | 
			
		||||
        msg.logger_name,
 | 
			
		||||
        level::to_str(msg.level),
 | 
			
		||||
        msg.raw.str());*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Faster (albeit uglier) way to format the line (5.6 million lines/sec under 10 threads)
 | 
			
		||||
        msg.formatted << '[' << static_cast<unsigned int>(tm_time.tm_year + 1900) << '-'
 | 
			
		||||
                      << fmt::pad(static_cast<unsigned int>(tm_time.tm_mon + 1), 2, '0') << '-'
 | 
			
		||||
                      << fmt::pad(static_cast<unsigned int>(tm_time.tm_mday), 2, '0') << ' '
 | 
			
		||||
                      << fmt::pad(static_cast<unsigned int>(tm_time.tm_hour), 2, '0') << ':'
 | 
			
		||||
                      << fmt::pad(static_cast<unsigned int>(tm_time.tm_min), 2, '0') << ':'
 | 
			
		||||
                      << fmt::pad(static_cast<unsigned int>(tm_time.tm_sec), 2, '0') << '.'
 | 
			
		||||
                      << fmt::pad(static_cast<unsigned int>(millis), 3, '0') << "] ";
 | 
			
		||||
 | 
			
		||||
        //no datetime needed
 | 
			
		||||
#else
 | 
			
		||||
        (void)tm_time;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef SPDLOG_NO_NAME
 | 
			
		||||
        msg.formatted << '[' << *msg.logger_name << "] ";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        msg.formatted << '[' << level::to_str(msg.level) << "] ";
 | 
			
		||||
        msg.formatted << fmt::StringRef(msg.raw.data(), msg.raw.size());
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// pattern_formatter inline impl
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern, pattern_time_type pattern_time)
 | 
			
		||||
    : _pattern_time(pattern_time)
 | 
			
		||||
{
 | 
			
		||||
    compile_pattern(pattern);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::pattern_formatter::compile_pattern(const std::string& pattern)
 | 
			
		||||
{
 | 
			
		||||
    auto end = pattern.end();
 | 
			
		||||
    std::unique_ptr<details::aggregate_formatter> user_chars;
 | 
			
		||||
    for (auto it = pattern.begin(); it != end; ++it)
 | 
			
		||||
    {
 | 
			
		||||
        if (*it == '%')
 | 
			
		||||
        {
 | 
			
		||||
            if (user_chars) //append user chars found so far
 | 
			
		||||
                _formatters.push_back(std::move(user_chars));
 | 
			
		||||
 | 
			
		||||
            if (++it != end)
 | 
			
		||||
                handle_flag(*it);
 | 
			
		||||
            else
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        else // chars not following the % sign should be displayed as is
 | 
			
		||||
        {
 | 
			
		||||
            if (!user_chars)
 | 
			
		||||
                user_chars = std::unique_ptr<details::aggregate_formatter>(new details::aggregate_formatter());
 | 
			
		||||
            user_chars->add_ch(*it);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (user_chars) //append raw chars found so far
 | 
			
		||||
    {
 | 
			
		||||
        _formatters.push_back(std::move(user_chars));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
inline void spdlog::pattern_formatter::handle_flag(char flag)
 | 
			
		||||
{
 | 
			
		||||
    switch (flag)
 | 
			
		||||
    {
 | 
			
		||||
    // logger name
 | 
			
		||||
    case 'n':
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::name_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 'l':
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::level_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case 'L':
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::short_level_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('t'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::t_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('v'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::v_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('a'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::a_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('A'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::A_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('b'):
 | 
			
		||||
    case('h'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::b_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('B'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::B_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
    case('c'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::c_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('C'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::C_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('Y'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::Y_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('D'):
 | 
			
		||||
    case('x'):
 | 
			
		||||
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::D_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('m'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::m_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('d'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::d_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('H'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::H_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('I'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::I_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('M'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::M_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('S'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::S_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('e'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::e_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('f'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::f_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
    case('F'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::F_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('E'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::E_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('p'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::p_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('r'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::r_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('R'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::R_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('T'):
 | 
			
		||||
    case('X'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::T_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case('z'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::z_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case ('+'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::full_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    case ('P'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::pid_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    case ('i'):
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::i_formatter()));
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    default: //Unknown flag appears as is
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter('%')));
 | 
			
		||||
        _formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::ch_formatter(flag)));
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::tm spdlog::pattern_formatter::get_time(details::log_msg& msg)
 | 
			
		||||
{
 | 
			
		||||
    if (_pattern_time == pattern_time_type::local)
 | 
			
		||||
        return details::os::localtime(log_clock::to_time_t(msg.time));
 | 
			
		||||
    else
 | 
			
		||||
        return details::os::gmtime(log_clock::to_time_t(msg.time));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::pattern_formatter::format(details::log_msg& msg)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#ifndef SPDLOG_NO_DATETIME
 | 
			
		||||
    auto tm_time = get_time(msg);
 | 
			
		||||
#else
 | 
			
		||||
    std::tm tm_time;
 | 
			
		||||
#endif
 | 
			
		||||
    for (auto &f : _formatters)
 | 
			
		||||
    {
 | 
			
		||||
        f->format(msg, tm_time);
 | 
			
		||||
    }
 | 
			
		||||
    //write eol
 | 
			
		||||
    msg.formatted.write(details::os::eol, details::os::eol_size);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										214
									
								
								vendor/spdlog/include/spdlog/details/registry.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										214
									
								
								vendor/spdlog/include/spdlog/details/registry.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,214 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// Loggers registy of unique name->logger pointer
 | 
			
		||||
// An attempt to create a logger with an already existing name will be ignored
 | 
			
		||||
// If user requests a non existing logger, nullptr will be returned
 | 
			
		||||
// This class is thread safe
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/null_mutex.h"
 | 
			
		||||
#include "spdlog/logger.h"
 | 
			
		||||
#include "spdlog/async_logger.h"
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
template <class Mutex> class registry_t
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    void register_logger(std::shared_ptr<logger> logger)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        auto logger_name = logger->name();
 | 
			
		||||
        throw_if_exists(logger_name);
 | 
			
		||||
        _loggers[logger_name] = logger;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<logger> get(const std::string& logger_name)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        auto found = _loggers.find(logger_name);
 | 
			
		||||
        return found == _loggers.end() ? nullptr : found->second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class It>
 | 
			
		||||
    std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        throw_if_exists(logger_name);
 | 
			
		||||
        std::shared_ptr<logger> new_logger;
 | 
			
		||||
        if (_async_mode)
 | 
			
		||||
            new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb);
 | 
			
		||||
        else
 | 
			
		||||
            new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
 | 
			
		||||
 | 
			
		||||
        if (_formatter)
 | 
			
		||||
            new_logger->set_formatter(_formatter);
 | 
			
		||||
 | 
			
		||||
        if (_err_handler)
 | 
			
		||||
            new_logger->set_error_handler(_err_handler);
 | 
			
		||||
 | 
			
		||||
        new_logger->set_level(_level);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //Add to registry
 | 
			
		||||
        _loggers[logger_name] = new_logger;
 | 
			
		||||
        return new_logger;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class It>
 | 
			
		||||
    std::shared_ptr<async_logger> create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb, const It& sinks_begin, const It& sinks_end)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        throw_if_exists(logger_name);
 | 
			
		||||
        auto new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb);
 | 
			
		||||
 | 
			
		||||
        if (_formatter)
 | 
			
		||||
            new_logger->set_formatter(_formatter);
 | 
			
		||||
 | 
			
		||||
        if (_err_handler)
 | 
			
		||||
            new_logger->set_error_handler(_err_handler);
 | 
			
		||||
 | 
			
		||||
        new_logger->set_level(_level);
 | 
			
		||||
 | 
			
		||||
        //Add to registry
 | 
			
		||||
        _loggers[logger_name] = new_logger;
 | 
			
		||||
        return new_logger;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void apply_all(std::function<void(std::shared_ptr<logger>)> fun)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        for (auto &l : _loggers)
 | 
			
		||||
            fun(l.second);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void drop(const std::string& logger_name)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        _loggers.erase(logger_name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void drop_all()
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        _loggers.clear();
 | 
			
		||||
    }
 | 
			
		||||
    std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks)
 | 
			
		||||
    {
 | 
			
		||||
        return create(logger_name, sinks.begin(), sinks.end());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<logger> create(const std::string& logger_name, sink_ptr sink)
 | 
			
		||||
    {
 | 
			
		||||
        return create(logger_name, { sink });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<async_logger> create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb, sinks_init_list sinks)
 | 
			
		||||
    {
 | 
			
		||||
        return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks.begin(), sinks.end());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::shared_ptr<async_logger> create_async(const std::string& logger_name, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb, sink_ptr sink)
 | 
			
		||||
    {
 | 
			
		||||
        return create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, { sink });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void formatter(formatter_ptr f)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        _formatter = f;
 | 
			
		||||
        for (auto& l : _loggers)
 | 
			
		||||
            l.second->set_formatter(_formatter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set_pattern(const std::string& pattern)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        _formatter = std::make_shared<pattern_formatter>(pattern);
 | 
			
		||||
        for (auto& l : _loggers)
 | 
			
		||||
            l.second->set_formatter(_formatter);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set_level(level::level_enum log_level)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        for (auto& l : _loggers)
 | 
			
		||||
            l.second->set_level(log_level);
 | 
			
		||||
        _level = log_level;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set_error_handler(log_err_handler handler)
 | 
			
		||||
    {
 | 
			
		||||
        for (auto& l : _loggers)
 | 
			
		||||
            l.second->set_error_handler(handler);
 | 
			
		||||
        _err_handler = handler;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        _async_mode = true;
 | 
			
		||||
        _async_q_size = q_size;
 | 
			
		||||
        _overflow_policy = overflow_policy;
 | 
			
		||||
        _worker_warmup_cb = worker_warmup_cb;
 | 
			
		||||
        _flush_interval_ms = flush_interval_ms;
 | 
			
		||||
        _worker_teardown_cb = worker_teardown_cb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set_sync_mode()
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        _async_mode = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static registry_t<Mutex>& instance()
 | 
			
		||||
    {
 | 
			
		||||
        static registry_t<Mutex> s_instance;
 | 
			
		||||
        return s_instance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    registry_t<Mutex>() {}
 | 
			
		||||
    registry_t<Mutex>(const registry_t<Mutex>&) = delete;
 | 
			
		||||
    registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete;
 | 
			
		||||
 | 
			
		||||
    void throw_if_exists(const std::string &logger_name)
 | 
			
		||||
    {
 | 
			
		||||
        if (_loggers.find(logger_name) != _loggers.end())
 | 
			
		||||
            throw spdlog_ex("logger with name '" + logger_name + "' already exists");
 | 
			
		||||
    }
 | 
			
		||||
    Mutex _mutex;
 | 
			
		||||
    std::unordered_map <std::string, std::shared_ptr<logger>> _loggers;
 | 
			
		||||
    formatter_ptr _formatter;
 | 
			
		||||
    level::level_enum _level = level::info;
 | 
			
		||||
    log_err_handler _err_handler;
 | 
			
		||||
    bool _async_mode = false;
 | 
			
		||||
    size_t _async_q_size = 0;
 | 
			
		||||
    async_overflow_policy _overflow_policy = async_overflow_policy::block_retry;
 | 
			
		||||
    std::function<void()> _worker_warmup_cb = nullptr;
 | 
			
		||||
    std::chrono::milliseconds _flush_interval_ms;
 | 
			
		||||
    std::function<void()> _worker_teardown_cb = nullptr;
 | 
			
		||||
};
 | 
			
		||||
#ifdef SPDLOG_NO_REGISTRY_MUTEX
 | 
			
		||||
typedef registry_t<spdlog::details::null_mutex> registry;
 | 
			
		||||
#else
 | 
			
		||||
typedef registry_t<std::mutex> registry;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										263
									
								
								vendor/spdlog/include/spdlog/details/spdlog_impl.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								vendor/spdlog/include/spdlog/details/spdlog_impl.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,263 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Global registry functions
 | 
			
		||||
//
 | 
			
		||||
#include "spdlog/spdlog.h"
 | 
			
		||||
#include "spdlog/details/registry.h"
 | 
			
		||||
#include "spdlog/sinks/file_sinks.h"
 | 
			
		||||
#include "spdlog/sinks/stdout_sinks.h"
 | 
			
		||||
#ifdef SPDLOG_ENABLE_SYSLOG
 | 
			
		||||
#include "spdlog/sinks/syslog_sink.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#include "spdlog/sinks/wincolor_sink.h"
 | 
			
		||||
#else
 | 
			
		||||
#include "spdlog/sinks/ansicolor_sink.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
#include "spdlog/sinks/android_sink.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
inline void spdlog::register_logger(std::shared_ptr<logger> logger)
 | 
			
		||||
{
 | 
			
		||||
    return details::registry::instance().register_logger(logger);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::get(const std::string& name)
 | 
			
		||||
{
 | 
			
		||||
    return details::registry::instance().get(name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::drop(const std::string &name)
 | 
			
		||||
{
 | 
			
		||||
    details::registry::instance().drop(name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create multi/single threaded simple file logger
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate)
 | 
			
		||||
{
 | 
			
		||||
    return create<spdlog::sinks::simple_file_sink_mt>(logger_name, filename, truncate);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate)
 | 
			
		||||
{
 | 
			
		||||
    return create<spdlog::sinks::simple_file_sink_st>(logger_name, filename, truncate);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create multi/single threaded rotating file logger
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
 | 
			
		||||
{
 | 
			
		||||
    return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, max_file_size, max_files);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
 | 
			
		||||
{
 | 
			
		||||
    return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, max_file_size, max_files);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create file logger which creates new file at midnight):
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour, int minute)
 | 
			
		||||
{
 | 
			
		||||
    return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, hour, minute);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute)
 | 
			
		||||
{
 | 
			
		||||
    return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, hour, minute);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// stdout/stderr loggers
 | 
			
		||||
//
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_st::instance());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_mt::instance());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_st::instance());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// stdout/stderr color loggers
 | 
			
		||||
//
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>();
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, sink);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    auto sink = std::make_shared<spdlog::sinks::wincolor_stdout_sink_st>();
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, sink);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    auto sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_mt>();
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, sink);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    auto sink = std::make_shared<spdlog::sinks::wincolor_stderr_sink_st>();
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, sink);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else //ansi terminal colors
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_mt(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    auto sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, sink);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_color_st(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    auto sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_st>();
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, sink);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_mt(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    auto sink = std::make_shared<spdlog::sinks::ansicolor_stderr_sink_mt>();
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, sink);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_color_st(const std::string& logger_name)
 | 
			
		||||
{
 | 
			
		||||
    auto sink = std::make_shared<spdlog::sinks::ansicolor_stderr_sink_st>();
 | 
			
		||||
    return spdlog::details::registry::instance().create(logger_name, sink);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SPDLOG_ENABLE_SYSLOG
 | 
			
		||||
// Create syslog logger
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option)
 | 
			
		||||
{
 | 
			
		||||
    return create<spdlog::sinks::syslog_sink>(logger_name, syslog_ident, syslog_option);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string& logger_name, const std::string& tag)
 | 
			
		||||
{
 | 
			
		||||
    return create<spdlog::sinks::android_sink>(logger_name, tag);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Create and register a logger a single sink
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const spdlog::sink_ptr& sink)
 | 
			
		||||
{
 | 
			
		||||
    return details::registry::instance().create(logger_name, sink);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//Create logger with multiple sinks
 | 
			
		||||
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, spdlog::sinks_init_list sinks)
 | 
			
		||||
{
 | 
			
		||||
    return details::registry::instance().create(logger_name, sinks);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <typename Sink, typename... Args>
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, Args... args)
 | 
			
		||||
{
 | 
			
		||||
    sink_ptr sink = std::make_shared<Sink>(args...);
 | 
			
		||||
    return details::registry::instance().create(logger_name, { sink });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<class It>
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
 | 
			
		||||
{
 | 
			
		||||
    return details::registry::instance().create(logger_name, sinks_begin, sinks_end);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create and register an async logger with a single sink
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::create_async(const std::string& logger_name, const sink_ptr& sink, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
 | 
			
		||||
{
 | 
			
		||||
    return details::registry::instance().create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sink);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create and register an async logger with multiple sinks
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::create_async(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb )
 | 
			
		||||
{
 | 
			
		||||
    return details::registry::instance().create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class It>
 | 
			
		||||
inline std::shared_ptr<spdlog::logger> spdlog::create_async(const std::string& logger_name, const It& sinks_begin, const It& sinks_end, size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
 | 
			
		||||
{
 | 
			
		||||
    return details::registry::instance().create_async(logger_name, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb, sinks_begin, sinks_end);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::set_formatter(spdlog::formatter_ptr f)
 | 
			
		||||
{
 | 
			
		||||
    details::registry::instance().formatter(f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::set_pattern(const std::string& format_string)
 | 
			
		||||
{
 | 
			
		||||
    return details::registry::instance().set_pattern(format_string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::set_level(level::level_enum log_level)
 | 
			
		||||
{
 | 
			
		||||
    return details::registry::instance().set_level(log_level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::set_error_handler(log_err_handler handler)
 | 
			
		||||
{
 | 
			
		||||
    return details::registry::instance().set_error_handler(handler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
 | 
			
		||||
{
 | 
			
		||||
    details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::set_sync_mode()
 | 
			
		||||
{
 | 
			
		||||
    details::registry::instance().set_sync_mode();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::apply_all(std::function<void(std::shared_ptr<logger>)> fun)
 | 
			
		||||
{
 | 
			
		||||
    details::registry::instance().apply_all(fun);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void spdlog::drop_all()
 | 
			
		||||
{
 | 
			
		||||
    details::registry::instance().drop_all();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										535
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/format.cc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										535
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/format.cc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,535 @@
 | 
			
		||||
/*
 | 
			
		||||
 Formatting library for C++
 | 
			
		||||
 | 
			
		||||
 Copyright (c) 2012 - 2016, Victor Zverovich
 | 
			
		||||
 All rights reserved.
 | 
			
		||||
 | 
			
		||||
 Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 modification, are permitted provided that the following conditions are met:
 | 
			
		||||
 | 
			
		||||
 1. Redistributions of source code must retain the above copyright notice, this
 | 
			
		||||
    list of conditions and the following disclaimer.
 | 
			
		||||
 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
			
		||||
    this list of conditions and the following disclaimer in the documentation
 | 
			
		||||
    and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 | 
			
		||||
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 | 
			
		||||
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 | 
			
		||||
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 | 
			
		||||
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 | 
			
		||||
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
			
		||||
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include <cctype>
 | 
			
		||||
#include <cerrno>
 | 
			
		||||
#include <climits>
 | 
			
		||||
#include <cmath>
 | 
			
		||||
#include <cstdarg>
 | 
			
		||||
#include <cstddef>  // for std::ptrdiff_t
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32) && defined(__MINGW32__)
 | 
			
		||||
# include <cstring>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if FMT_USE_WINDOWS_H
 | 
			
		||||
# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
 | 
			
		||||
#  define WIN32_LEAN_AND_MEAN
 | 
			
		||||
# endif
 | 
			
		||||
# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
 | 
			
		||||
#  include <windows.h>
 | 
			
		||||
# else
 | 
			
		||||
#  define NOMINMAX
 | 
			
		||||
#  include <windows.h>
 | 
			
		||||
#  undef NOMINMAX
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if FMT_EXCEPTIONS
 | 
			
		||||
# define FMT_TRY try
 | 
			
		||||
# define FMT_CATCH(x) catch (x)
 | 
			
		||||
#else
 | 
			
		||||
# define FMT_TRY if (true)
 | 
			
		||||
# define FMT_CATCH(x) if (false)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
# pragma warning(push)
 | 
			
		||||
# pragma warning(disable: 4127)  // conditional expression is constant
 | 
			
		||||
# pragma warning(disable: 4702)  // unreachable code
 | 
			
		||||
// Disable deprecation warning for strerror. The latter is not called but
 | 
			
		||||
// MSVC fails to detect it.
 | 
			
		||||
# pragma warning(disable: 4996)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Dummy implementations of strerror_r and strerror_s called if corresponding
 | 
			
		||||
// system functions are not available.
 | 
			
		||||
static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
 | 
			
		||||
  return fmt::internal::Null<>();
 | 
			
		||||
}
 | 
			
		||||
static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
 | 
			
		||||
  return fmt::internal::Null<>();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace fmt {
 | 
			
		||||
 | 
			
		||||
FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {}
 | 
			
		||||
FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT {}
 | 
			
		||||
FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT {}
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
#ifndef _MSC_VER
 | 
			
		||||
# define FMT_SNPRINTF snprintf
 | 
			
		||||
#else  // _MSC_VER
 | 
			
		||||
inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
 | 
			
		||||
  va_list args;
 | 
			
		||||
  va_start(args, format);
 | 
			
		||||
  int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
 | 
			
		||||
  va_end(args);
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
# define FMT_SNPRINTF fmt_snprintf
 | 
			
		||||
#endif  // _MSC_VER
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
 | 
			
		||||
# define FMT_SWPRINTF snwprintf
 | 
			
		||||
#else
 | 
			
		||||
# define FMT_SWPRINTF swprintf
 | 
			
		||||
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
 | 
			
		||||
 | 
			
		||||
const char RESET_COLOR[] = "\x1b[0m";
 | 
			
		||||
 | 
			
		||||
typedef void (*FormatFunc)(Writer &, int, StringRef);
 | 
			
		||||
 | 
			
		||||
// Portable thread-safe version of strerror.
 | 
			
		||||
// Sets buffer to point to a string describing the error code.
 | 
			
		||||
// This can be either a pointer to a string stored in buffer,
 | 
			
		||||
// or a pointer to some static immutable string.
 | 
			
		||||
// Returns one of the following values:
 | 
			
		||||
//   0      - success
 | 
			
		||||
//   ERANGE - buffer is not large enough to store the error message
 | 
			
		||||
//   other  - failure
 | 
			
		||||
// Buffer should be at least of size 1.
 | 
			
		||||
int safe_strerror(
 | 
			
		||||
    int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
 | 
			
		||||
  FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
 | 
			
		||||
 | 
			
		||||
  class StrError {
 | 
			
		||||
   private:
 | 
			
		||||
    int error_code_;
 | 
			
		||||
    char *&buffer_;
 | 
			
		||||
    std::size_t buffer_size_;
 | 
			
		||||
 | 
			
		||||
    // A noop assignment operator to avoid bogus warnings.
 | 
			
		||||
    void operator=(const StrError &) {}
 | 
			
		||||
 | 
			
		||||
    // Handle the result of XSI-compliant version of strerror_r.
 | 
			
		||||
    int handle(int result) {
 | 
			
		||||
      // glibc versions before 2.13 return result in errno.
 | 
			
		||||
      return result == -1 ? errno : result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Handle the result of GNU-specific version of strerror_r.
 | 
			
		||||
    int handle(char *message) {
 | 
			
		||||
      // If the buffer is full then the message is probably truncated.
 | 
			
		||||
      if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
 | 
			
		||||
        return ERANGE;
 | 
			
		||||
      buffer_ = message;
 | 
			
		||||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Handle the case when strerror_r is not available.
 | 
			
		||||
    int handle(internal::Null<>) {
 | 
			
		||||
      return fallback(strerror_s(buffer_, buffer_size_, error_code_));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Fallback to strerror_s when strerror_r is not available.
 | 
			
		||||
    int fallback(int result) {
 | 
			
		||||
      // If the buffer is full then the message is probably truncated.
 | 
			
		||||
      return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
 | 
			
		||||
            ERANGE : result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Fallback to strerror if strerror_r and strerror_s are not available.
 | 
			
		||||
    int fallback(internal::Null<>) {
 | 
			
		||||
      errno = 0;
 | 
			
		||||
      buffer_ = strerror(error_code_);
 | 
			
		||||
      return errno;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
   public:
 | 
			
		||||
    StrError(int err_code, char *&buf, std::size_t buf_size)
 | 
			
		||||
      : error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
 | 
			
		||||
 | 
			
		||||
    int run() {
 | 
			
		||||
      // Suppress a warning about unused strerror_r.
 | 
			
		||||
      strerror_r(0, FMT_NULL, "");
 | 
			
		||||
      return handle(strerror_r(error_code_, buffer_, buffer_size_));
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  return StrError(error_code, buffer, buffer_size).run();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void format_error_code(Writer &out, int error_code,
 | 
			
		||||
                       StringRef message) FMT_NOEXCEPT {
 | 
			
		||||
  // Report error code making sure that the output fits into
 | 
			
		||||
  // INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
 | 
			
		||||
  // bad_alloc.
 | 
			
		||||
  out.clear();
 | 
			
		||||
  static const char SEP[] = ": ";
 | 
			
		||||
  static const char ERROR_STR[] = "error ";
 | 
			
		||||
  // Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
 | 
			
		||||
  std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
 | 
			
		||||
  typedef internal::IntTraits<int>::MainType MainType;
 | 
			
		||||
  MainType abs_value = static_cast<MainType>(error_code);
 | 
			
		||||
  if (internal::is_negative(error_code)) {
 | 
			
		||||
    abs_value = 0 - abs_value;
 | 
			
		||||
    ++error_code_size;
 | 
			
		||||
  }
 | 
			
		||||
  error_code_size += internal::count_digits(abs_value);
 | 
			
		||||
  if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size)
 | 
			
		||||
    out << message << SEP;
 | 
			
		||||
  out << ERROR_STR << error_code;
 | 
			
		||||
  assert(out.size() <= internal::INLINE_BUFFER_SIZE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void report_error(FormatFunc func, int error_code,
 | 
			
		||||
                  StringRef message) FMT_NOEXCEPT {
 | 
			
		||||
  MemoryWriter full_message;
 | 
			
		||||
  func(full_message, error_code, message);
 | 
			
		||||
  // Use Writer::data instead of Writer::c_str to avoid potential memory
 | 
			
		||||
  // allocation.
 | 
			
		||||
  std::fwrite(full_message.data(), full_message.size(), 1, stderr);
 | 
			
		||||
  std::fputc('\n', stderr);
 | 
			
		||||
}
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
FMT_FUNC void SystemError::init(
 | 
			
		||||
    int err_code, CStringRef format_str, ArgList args) {
 | 
			
		||||
  error_code_ = err_code;
 | 
			
		||||
  MemoryWriter w;
 | 
			
		||||
  format_system_error(w, err_code, format(format_str, args));
 | 
			
		||||
  std::runtime_error &base = *this;
 | 
			
		||||
  base = std::runtime_error(w.str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
int internal::CharTraits<char>::format_float(
 | 
			
		||||
    char *buffer, std::size_t size, const char *format,
 | 
			
		||||
    unsigned width, int precision, T value) {
 | 
			
		||||
  if (width == 0) {
 | 
			
		||||
    return precision < 0 ?
 | 
			
		||||
        FMT_SNPRINTF(buffer, size, format, value) :
 | 
			
		||||
        FMT_SNPRINTF(buffer, size, format, precision, value);
 | 
			
		||||
  }
 | 
			
		||||
  return precision < 0 ?
 | 
			
		||||
      FMT_SNPRINTF(buffer, size, format, width, value) :
 | 
			
		||||
      FMT_SNPRINTF(buffer, size, format, width, precision, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
int internal::CharTraits<wchar_t>::format_float(
 | 
			
		||||
    wchar_t *buffer, std::size_t size, const wchar_t *format,
 | 
			
		||||
    unsigned width, int precision, T value) {
 | 
			
		||||
  if (width == 0) {
 | 
			
		||||
    return precision < 0 ?
 | 
			
		||||
        FMT_SWPRINTF(buffer, size, format, value) :
 | 
			
		||||
        FMT_SWPRINTF(buffer, size, format, precision, value);
 | 
			
		||||
  }
 | 
			
		||||
  return precision < 0 ?
 | 
			
		||||
      FMT_SWPRINTF(buffer, size, format, width, value) :
 | 
			
		||||
      FMT_SWPRINTF(buffer, size, format, width, precision, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
const char internal::BasicData<T>::DIGITS[] =
 | 
			
		||||
    "0001020304050607080910111213141516171819"
 | 
			
		||||
    "2021222324252627282930313233343536373839"
 | 
			
		||||
    "4041424344454647484950515253545556575859"
 | 
			
		||||
    "6061626364656667686970717273747576777879"
 | 
			
		||||
    "8081828384858687888990919293949596979899";
 | 
			
		||||
 | 
			
		||||
#define FMT_POWERS_OF_10(factor) \
 | 
			
		||||
  factor * 10, \
 | 
			
		||||
  factor * 100, \
 | 
			
		||||
  factor * 1000, \
 | 
			
		||||
  factor * 10000, \
 | 
			
		||||
  factor * 100000, \
 | 
			
		||||
  factor * 1000000, \
 | 
			
		||||
  factor * 10000000, \
 | 
			
		||||
  factor * 100000000, \
 | 
			
		||||
  factor * 1000000000
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
const uint32_t internal::BasicData<T>::POWERS_OF_10_32[] = {
 | 
			
		||||
  0, FMT_POWERS_OF_10(1)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
const uint64_t internal::BasicData<T>::POWERS_OF_10_64[] = {
 | 
			
		||||
  0,
 | 
			
		||||
  FMT_POWERS_OF_10(1),
 | 
			
		||||
  FMT_POWERS_OF_10(ULongLong(1000000000)),
 | 
			
		||||
  // Multiply several constants instead of using a single long long constant
 | 
			
		||||
  // to avoid warnings about C++98 not supporting long long.
 | 
			
		||||
  ULongLong(1000000000) * ULongLong(1000000000) * 10
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
FMT_FUNC void internal::report_unknown_type(char code, const char *type) {
 | 
			
		||||
  (void)type;
 | 
			
		||||
  if (std::isprint(static_cast<unsigned char>(code))) {
 | 
			
		||||
    FMT_THROW(FormatError(
 | 
			
		||||
        format("unknown format code '{}' for {}", code, type)));
 | 
			
		||||
  }
 | 
			
		||||
  FMT_THROW(FormatError(
 | 
			
		||||
      format("unknown format code '\\x{:02x}' for {}",
 | 
			
		||||
        static_cast<unsigned>(code), type)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if FMT_USE_WINDOWS_H
 | 
			
		||||
 | 
			
		||||
FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) {
 | 
			
		||||
  static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
 | 
			
		||||
  if (s.size() > INT_MAX)
 | 
			
		||||
    FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
 | 
			
		||||
  int s_size = static_cast<int>(s.size());
 | 
			
		||||
  int length = MultiByteToWideChar(
 | 
			
		||||
      CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
 | 
			
		||||
  if (length == 0)
 | 
			
		||||
    FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
 | 
			
		||||
  buffer_.resize(length + 1);
 | 
			
		||||
  length = MultiByteToWideChar(
 | 
			
		||||
    CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
 | 
			
		||||
  if (length == 0)
 | 
			
		||||
    FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
 | 
			
		||||
  buffer_[length] = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_FUNC internal::UTF16ToUTF8::UTF16ToUTF8(WStringRef s) {
 | 
			
		||||
  if (int error_code = convert(s)) {
 | 
			
		||||
    FMT_THROW(WindowsError(error_code,
 | 
			
		||||
        "cannot convert string from UTF-16 to UTF-8"));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) {
 | 
			
		||||
  if (s.size() > INT_MAX)
 | 
			
		||||
    return ERROR_INVALID_PARAMETER;
 | 
			
		||||
  int s_size = static_cast<int>(s.size());
 | 
			
		||||
  int length = WideCharToMultiByte(
 | 
			
		||||
    CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
 | 
			
		||||
  if (length == 0)
 | 
			
		||||
    return GetLastError();
 | 
			
		||||
  buffer_.resize(length + 1);
 | 
			
		||||
  length = WideCharToMultiByte(
 | 
			
		||||
    CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
 | 
			
		||||
  if (length == 0)
 | 
			
		||||
    return GetLastError();
 | 
			
		||||
  buffer_[length] = 0;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_FUNC void WindowsError::init(
 | 
			
		||||
    int err_code, CStringRef format_str, ArgList args) {
 | 
			
		||||
  error_code_ = err_code;
 | 
			
		||||
  MemoryWriter w;
 | 
			
		||||
  internal::format_windows_error(w, err_code, format(format_str, args));
 | 
			
		||||
  std::runtime_error &base = *this;
 | 
			
		||||
  base = std::runtime_error(w.str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_FUNC void internal::format_windows_error(
 | 
			
		||||
    Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
 | 
			
		||||
  FMT_TRY {
 | 
			
		||||
    MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
 | 
			
		||||
    buffer.resize(INLINE_BUFFER_SIZE);
 | 
			
		||||
    for (;;) {
 | 
			
		||||
      wchar_t *system_message = &buffer[0];
 | 
			
		||||
      int result = FormatMessageW(
 | 
			
		||||
        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
 | 
			
		||||
        FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 | 
			
		||||
        system_message, static_cast<uint32_t>(buffer.size()), FMT_NULL);
 | 
			
		||||
      if (result != 0) {
 | 
			
		||||
        UTF16ToUTF8 utf8_message;
 | 
			
		||||
        if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
 | 
			
		||||
          out << message << ": " << utf8_message;
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
 | 
			
		||||
        break;  // Can't get error message, report error code instead.
 | 
			
		||||
      buffer.resize(buffer.size() * 2);
 | 
			
		||||
    }
 | 
			
		||||
  } FMT_CATCH(...) {}
 | 
			
		||||
  fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_USE_WINDOWS_H
 | 
			
		||||
 | 
			
		||||
FMT_FUNC void format_system_error(
 | 
			
		||||
    Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
 | 
			
		||||
  FMT_TRY {
 | 
			
		||||
    internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> buffer;
 | 
			
		||||
    buffer.resize(internal::INLINE_BUFFER_SIZE);
 | 
			
		||||
    for (;;) {
 | 
			
		||||
      char *system_message = &buffer[0];
 | 
			
		||||
      int result = safe_strerror(error_code, system_message, buffer.size());
 | 
			
		||||
      if (result == 0) {
 | 
			
		||||
        out << message << ": " << system_message;
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (result != ERANGE)
 | 
			
		||||
        break;  // Can't get error message, report error code instead.
 | 
			
		||||
      buffer.resize(buffer.size() * 2);
 | 
			
		||||
    }
 | 
			
		||||
  } FMT_CATCH(...) {}
 | 
			
		||||
  fmt::format_error_code(out, error_code, message);  // 'fmt::' is for bcc32.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
void internal::ArgMap<Char>::init(const ArgList &args) {
 | 
			
		||||
  if (!map_.empty())
 | 
			
		||||
    return;
 | 
			
		||||
  typedef internal::NamedArg<Char> NamedArg;
 | 
			
		||||
  const NamedArg *named_arg = FMT_NULL;
 | 
			
		||||
  bool use_values =
 | 
			
		||||
      args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
 | 
			
		||||
  if (use_values) {
 | 
			
		||||
    for (unsigned i = 0;/*nothing*/; ++i) {
 | 
			
		||||
      internal::Arg::Type arg_type = args.type(i);
 | 
			
		||||
      switch (arg_type) {
 | 
			
		||||
      case internal::Arg::NONE:
 | 
			
		||||
        return;
 | 
			
		||||
      case internal::Arg::NAMED_ARG:
 | 
			
		||||
        named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
 | 
			
		||||
        map_.push_back(Pair(named_arg->name, *named_arg));
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        /*nothing*/;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
 | 
			
		||||
    internal::Arg::Type arg_type = args.type(i);
 | 
			
		||||
    if (arg_type == internal::Arg::NAMED_ARG) {
 | 
			
		||||
      named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
 | 
			
		||||
      map_.push_back(Pair(named_arg->name, *named_arg));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
 | 
			
		||||
    switch (args.args_[i].type) {
 | 
			
		||||
    case internal::Arg::NONE:
 | 
			
		||||
      return;
 | 
			
		||||
    case internal::Arg::NAMED_ARG:
 | 
			
		||||
      named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
 | 
			
		||||
      map_.push_back(Pair(named_arg->name, *named_arg));
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      /*nothing*/;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
void internal::FixedBuffer<Char>::grow(std::size_t) {
 | 
			
		||||
  FMT_THROW(std::runtime_error("buffer overflow"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_FUNC internal::Arg internal::FormatterBase::do_get_arg(
 | 
			
		||||
    unsigned arg_index, const char *&error) {
 | 
			
		||||
  internal::Arg arg = args_[arg_index];
 | 
			
		||||
  switch (arg.type) {
 | 
			
		||||
  case internal::Arg::NONE:
 | 
			
		||||
    error = "argument index out of range";
 | 
			
		||||
    break;
 | 
			
		||||
  case internal::Arg::NAMED_ARG:
 | 
			
		||||
    arg = *static_cast<const internal::Arg*>(arg.pointer);
 | 
			
		||||
    break;
 | 
			
		||||
  default:
 | 
			
		||||
    /*nothing*/;
 | 
			
		||||
  }
 | 
			
		||||
  return arg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_FUNC void report_system_error(
 | 
			
		||||
    int error_code, fmt::StringRef message) FMT_NOEXCEPT {
 | 
			
		||||
  // 'fmt::' is for bcc32.
 | 
			
		||||
  report_error(format_system_error, error_code, message);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if FMT_USE_WINDOWS_H
 | 
			
		||||
FMT_FUNC void report_windows_error(
 | 
			
		||||
    int error_code, fmt::StringRef message) FMT_NOEXCEPT {
 | 
			
		||||
  // 'fmt::' is for bcc32.
 | 
			
		||||
  report_error(internal::format_windows_error, error_code, message);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
FMT_FUNC void print(std::FILE *f, CStringRef format_str, ArgList args) {
 | 
			
		||||
  MemoryWriter w;
 | 
			
		||||
  w.write(format_str, args);
 | 
			
		||||
  std::fwrite(w.data(), 1, w.size(), f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_FUNC void print(CStringRef format_str, ArgList args) {
 | 
			
		||||
  print(stdout, format_str, args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) {
 | 
			
		||||
  char escape[] = "\x1b[30m";
 | 
			
		||||
  escape[3] = static_cast<char>('0' + c);
 | 
			
		||||
  std::fputs(escape, stdout);
 | 
			
		||||
  print(format, args);
 | 
			
		||||
  std::fputs(RESET_COLOR, stdout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_HEADER_ONLY
 | 
			
		||||
 | 
			
		||||
template struct internal::BasicData<void>;
 | 
			
		||||
 | 
			
		||||
// Explicit instantiations for char.
 | 
			
		||||
 | 
			
		||||
template void internal::FixedBuffer<char>::grow(std::size_t);
 | 
			
		||||
 | 
			
		||||
template void internal::ArgMap<char>::init(const ArgList &args);
 | 
			
		||||
 | 
			
		||||
template FMT_API int internal::CharTraits<char>::format_float(
 | 
			
		||||
    char *buffer, std::size_t size, const char *format,
 | 
			
		||||
    unsigned width, int precision, double value);
 | 
			
		||||
 | 
			
		||||
template FMT_API int internal::CharTraits<char>::format_float(
 | 
			
		||||
    char *buffer, std::size_t size, const char *format,
 | 
			
		||||
    unsigned width, int precision, long double value);
 | 
			
		||||
 | 
			
		||||
// Explicit instantiations for wchar_t.
 | 
			
		||||
 | 
			
		||||
template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
 | 
			
		||||
 | 
			
		||||
template void internal::ArgMap<wchar_t>::init(const ArgList &args);
 | 
			
		||||
 | 
			
		||||
template FMT_API int internal::CharTraits<wchar_t>::format_float(
 | 
			
		||||
    wchar_t *buffer, std::size_t size, const wchar_t *format,
 | 
			
		||||
    unsigned width, int precision, double value);
 | 
			
		||||
 | 
			
		||||
template FMT_API int internal::CharTraits<wchar_t>::format_float(
 | 
			
		||||
    wchar_t *buffer, std::size_t size, const wchar_t *format,
 | 
			
		||||
    unsigned width, int precision, long double value);
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_HEADER_ONLY
 | 
			
		||||
 | 
			
		||||
}  // namespace fmt
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
# pragma warning(pop)
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										4012
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/format.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4012
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/format.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										35
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/ostream.cc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/ostream.cc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
/*
 | 
			
		||||
 Formatting library for C++ - std::ostream support
 | 
			
		||||
 | 
			
		||||
 Copyright (c) 2012 - 2016, Victor Zverovich
 | 
			
		||||
 All rights reserved.
 | 
			
		||||
 | 
			
		||||
 For the license information refer to format.h.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "ostream.h"
 | 
			
		||||
 | 
			
		||||
namespace fmt {
 | 
			
		||||
 | 
			
		||||
namespace internal {
 | 
			
		||||
FMT_FUNC void write(std::ostream &os, Writer &w) {
 | 
			
		||||
  const char *data = w.data();
 | 
			
		||||
  typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
 | 
			
		||||
  UnsignedStreamSize size = w.size();
 | 
			
		||||
  UnsignedStreamSize max_size =
 | 
			
		||||
      internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
 | 
			
		||||
  do {
 | 
			
		||||
    UnsignedStreamSize n = size <= max_size ? size : max_size;
 | 
			
		||||
    os.write(data, static_cast<std::streamsize>(n));
 | 
			
		||||
    data += n;
 | 
			
		||||
    size -= n;
 | 
			
		||||
  } while (size != 0);
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) {
 | 
			
		||||
  MemoryWriter w;
 | 
			
		||||
  w.write(format_str, args);
 | 
			
		||||
  internal::write(os, w);
 | 
			
		||||
}
 | 
			
		||||
}  // namespace fmt
 | 
			
		||||
							
								
								
									
										105
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/ostream.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/ostream.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
/*
 | 
			
		||||
 Formatting library for C++ - std::ostream support
 | 
			
		||||
 | 
			
		||||
 Copyright (c) 2012 - 2016, Victor Zverovich
 | 
			
		||||
 All rights reserved.
 | 
			
		||||
 | 
			
		||||
 For the license information refer to format.h.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_OSTREAM_H_
 | 
			
		||||
#define FMT_OSTREAM_H_
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
#include <ostream>
 | 
			
		||||
 | 
			
		||||
namespace fmt {
 | 
			
		||||
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
template <class Char>
 | 
			
		||||
class FormatBuf : public std::basic_streambuf<Char> {
 | 
			
		||||
 private:
 | 
			
		||||
  typedef typename std::basic_streambuf<Char>::int_type int_type;
 | 
			
		||||
  typedef typename std::basic_streambuf<Char>::traits_type traits_type;
 | 
			
		||||
 | 
			
		||||
  Buffer<Char> &buffer_;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  FormatBuf(Buffer<Char> &buffer) : buffer_(buffer) {}
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  // The put-area is actually always empty. This makes the implementation
 | 
			
		||||
  // simpler and has the advantage that the streambuf and the buffer are always
 | 
			
		||||
  // in sync and sputc never writes into uninitialized memory. The obvious
 | 
			
		||||
  // disadvantage is that each call to sputc always results in a (virtual) call
 | 
			
		||||
  // to overflow. There is no disadvantage here for sputn since this always
 | 
			
		||||
  // results in a call to xsputn.
 | 
			
		||||
 | 
			
		||||
  int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
 | 
			
		||||
    if (!traits_type::eq_int_type(ch, traits_type::eof()))
 | 
			
		||||
      buffer_.push_back(static_cast<Char>(ch));
 | 
			
		||||
    return ch;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE {
 | 
			
		||||
    buffer_.append(s, s + count);
 | 
			
		||||
    return count;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Yes &convert(std::ostream &);
 | 
			
		||||
 | 
			
		||||
struct DummyStream : std::ostream {
 | 
			
		||||
  DummyStream();  // Suppress a bogus warning in MSVC.
 | 
			
		||||
  // Hide all operator<< overloads from std::ostream.
 | 
			
		||||
  void operator<<(Null<>);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
No &operator<<(std::ostream &, int);
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
struct ConvertToIntImpl<T, true> {
 | 
			
		||||
  // Convert to int only if T doesn't have an overloaded operator<<.
 | 
			
		||||
  enum {
 | 
			
		||||
    value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Write the content of w to os.
 | 
			
		||||
FMT_API void write(std::ostream &os, Writer &w);
 | 
			
		||||
}  // namespace internal
 | 
			
		||||
 | 
			
		||||
// Formats a value.
 | 
			
		||||
template <typename Char, typename ArgFormatter_, typename T>
 | 
			
		||||
void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
 | 
			
		||||
                const Char *&format_str, const T &value) {
 | 
			
		||||
  internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
 | 
			
		||||
 | 
			
		||||
  internal::FormatBuf<Char> format_buf(buffer);
 | 
			
		||||
  std::basic_ostream<Char> output(&format_buf);
 | 
			
		||||
  output << value;
 | 
			
		||||
 | 
			
		||||
  BasicStringRef<Char> str(&buffer[0], buffer.size());
 | 
			
		||||
  typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
 | 
			
		||||
  format_str = f.format(format_str, MakeArg(str));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Prints formatted data to the stream *os*.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    print(cerr, "Don't {}!", "panic");
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
 | 
			
		||||
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
 | 
			
		||||
}  // namespace fmt
 | 
			
		||||
 | 
			
		||||
#ifdef FMT_HEADER_ONLY
 | 
			
		||||
# include "ostream.cc"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_OSTREAM_H_
 | 
			
		||||
							
								
								
									
										241
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/posix.cc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/posix.cc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,241 @@
 | 
			
		||||
/*
 | 
			
		||||
 A C++ interface to POSIX functions.
 | 
			
		||||
 | 
			
		||||
 Copyright (c) 2012 - 2016, Victor Zverovich
 | 
			
		||||
 All rights reserved.
 | 
			
		||||
 | 
			
		||||
 For the license information refer to format.h.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Disable bogus MSVC warnings.
 | 
			
		||||
#ifndef _CRT_SECURE_NO_WARNINGS
 | 
			
		||||
# define _CRT_SECURE_NO_WARNINGS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "posix.h"
 | 
			
		||||
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
 | 
			
		||||
#ifndef _WIN32
 | 
			
		||||
# include <unistd.h>
 | 
			
		||||
#else
 | 
			
		||||
# ifndef WIN32_LEAN_AND_MEAN
 | 
			
		||||
#  define WIN32_LEAN_AND_MEAN
 | 
			
		||||
# endif
 | 
			
		||||
# include <windows.h>
 | 
			
		||||
# include <io.h>
 | 
			
		||||
 | 
			
		||||
# define O_CREAT _O_CREAT
 | 
			
		||||
# define O_TRUNC _O_TRUNC
 | 
			
		||||
 | 
			
		||||
# ifndef S_IRUSR
 | 
			
		||||
#  define S_IRUSR _S_IREAD
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# ifndef S_IWUSR
 | 
			
		||||
#  define S_IWUSR _S_IWRITE
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# ifdef __MINGW32__
 | 
			
		||||
#  define _SH_DENYNO 0x40
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
#endif  // _WIN32
 | 
			
		||||
 | 
			
		||||
#ifdef fileno
 | 
			
		||||
# undef fileno
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
// Return type of read and write functions.
 | 
			
		||||
typedef int RWResult;
 | 
			
		||||
 | 
			
		||||
// On Windows the count argument to read and write is unsigned, so convert
 | 
			
		||||
// it from size_t preventing integer overflow.
 | 
			
		||||
inline unsigned convert_rwcount(std::size_t count) {
 | 
			
		||||
  return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
// Return type of read and write functions.
 | 
			
		||||
typedef ssize_t RWResult;
 | 
			
		||||
 | 
			
		||||
inline std::size_t convert_rwcount(std::size_t count) { return count; }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fmt::BufferedFile::~BufferedFile() FMT_NOEXCEPT {
 | 
			
		||||
  if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
 | 
			
		||||
    fmt::report_system_error(errno, "cannot close file");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fmt::BufferedFile::BufferedFile(
 | 
			
		||||
    fmt::CStringRef filename, fmt::CStringRef mode) {
 | 
			
		||||
  FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())), 0);
 | 
			
		||||
  if (!file_)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot open file {}", filename));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fmt::BufferedFile::close() {
 | 
			
		||||
  if (!file_)
 | 
			
		||||
    return;
 | 
			
		||||
  int result = FMT_SYSTEM(fclose(file_));
 | 
			
		||||
  file_ = FMT_NULL;
 | 
			
		||||
  if (result != 0)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot close file"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A macro used to prevent expansion of fileno on broken versions of MinGW.
 | 
			
		||||
#define FMT_ARGS
 | 
			
		||||
 | 
			
		||||
int fmt::BufferedFile::fileno() const {
 | 
			
		||||
  int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
 | 
			
		||||
  if (fd == -1)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot get file descriptor"));
 | 
			
		||||
  return fd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fmt::File::File(fmt::CStringRef path, int oflag) {
 | 
			
		||||
  int mode = S_IRUSR | S_IWUSR;
 | 
			
		||||
#if defined(_WIN32) && !defined(__MINGW32__)
 | 
			
		||||
  fd_ = -1;
 | 
			
		||||
  FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
 | 
			
		||||
#else
 | 
			
		||||
  FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
 | 
			
		||||
#endif
 | 
			
		||||
  if (fd_ == -1)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot open file {}", path));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fmt::File::~File() FMT_NOEXCEPT {
 | 
			
		||||
  // Don't retry close in case of EINTR!
 | 
			
		||||
  // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
 | 
			
		||||
  if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
 | 
			
		||||
    fmt::report_system_error(errno, "cannot close file");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fmt::File::close() {
 | 
			
		||||
  if (fd_ == -1)
 | 
			
		||||
    return;
 | 
			
		||||
  // Don't retry close in case of EINTR!
 | 
			
		||||
  // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
 | 
			
		||||
  int result = FMT_POSIX_CALL(close(fd_));
 | 
			
		||||
  fd_ = -1;
 | 
			
		||||
  if (result != 0)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot close file"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fmt::LongLong fmt::File::size() const {
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
  // Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT
 | 
			
		||||
  // is less than 0x0500 as is the case with some default MinGW builds.
 | 
			
		||||
  // Both functions support large file sizes.
 | 
			
		||||
  DWORD size_upper = 0;
 | 
			
		||||
  HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd_));
 | 
			
		||||
  DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper));
 | 
			
		||||
  if (size_lower == INVALID_FILE_SIZE) {
 | 
			
		||||
    DWORD error = GetLastError();
 | 
			
		||||
    if (error != NO_ERROR)
 | 
			
		||||
      FMT_THROW(WindowsError(GetLastError(), "cannot get file size"));
 | 
			
		||||
  }
 | 
			
		||||
  fmt::ULongLong long_size = size_upper;
 | 
			
		||||
  return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
 | 
			
		||||
#else
 | 
			
		||||
  typedef struct stat Stat;
 | 
			
		||||
  Stat file_stat = Stat();
 | 
			
		||||
  if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot get file attributes"));
 | 
			
		||||
  FMT_STATIC_ASSERT(sizeof(fmt::LongLong) >= sizeof(file_stat.st_size),
 | 
			
		||||
      "return type of File::size is not large enough");
 | 
			
		||||
  return file_stat.st_size;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::size_t fmt::File::read(void *buffer, std::size_t count) {
 | 
			
		||||
  RWResult result = 0;
 | 
			
		||||
  FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
 | 
			
		||||
  if (result < 0)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot read from file"));
 | 
			
		||||
  return internal::to_unsigned(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::size_t fmt::File::write(const void *buffer, std::size_t count) {
 | 
			
		||||
  RWResult result = 0;
 | 
			
		||||
  FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
 | 
			
		||||
  if (result < 0)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot write to file"));
 | 
			
		||||
  return internal::to_unsigned(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fmt::File fmt::File::dup(int fd) {
 | 
			
		||||
  // Don't retry as dup doesn't return EINTR.
 | 
			
		||||
  // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
 | 
			
		||||
  int new_fd = FMT_POSIX_CALL(dup(fd));
 | 
			
		||||
  if (new_fd == -1)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot duplicate file descriptor {}", fd));
 | 
			
		||||
  return File(new_fd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fmt::File::dup2(int fd) {
 | 
			
		||||
  int result = 0;
 | 
			
		||||
  FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
 | 
			
		||||
  if (result == -1) {
 | 
			
		||||
    FMT_THROW(SystemError(errno,
 | 
			
		||||
      "cannot duplicate file descriptor {} to {}", fd_, fd));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fmt::File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT {
 | 
			
		||||
  int result = 0;
 | 
			
		||||
  FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
 | 
			
		||||
  if (result == -1)
 | 
			
		||||
    ec = ErrorCode(errno);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void fmt::File::pipe(File &read_end, File &write_end) {
 | 
			
		||||
  // Close the descriptors first to make sure that assignments don't throw
 | 
			
		||||
  // and there are no leaks.
 | 
			
		||||
  read_end.close();
 | 
			
		||||
  write_end.close();
 | 
			
		||||
  int fds[2] = {};
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
  // Make the default pipe capacity same as on Linux 2.6.11+.
 | 
			
		||||
  enum { DEFAULT_CAPACITY = 65536 };
 | 
			
		||||
  int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
 | 
			
		||||
#else
 | 
			
		||||
  // Don't retry as the pipe function doesn't return EINTR.
 | 
			
		||||
  // http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
 | 
			
		||||
  int result = FMT_POSIX_CALL(pipe(fds));
 | 
			
		||||
#endif
 | 
			
		||||
  if (result != 0)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot create pipe"));
 | 
			
		||||
  // The following assignments don't throw because read_fd and write_fd
 | 
			
		||||
  // are closed.
 | 
			
		||||
  read_end = File(fds[0]);
 | 
			
		||||
  write_end = File(fds[1]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fmt::BufferedFile fmt::File::fdopen(const char *mode) {
 | 
			
		||||
  // Don't retry as fdopen doesn't return EINTR.
 | 
			
		||||
  FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
 | 
			
		||||
  if (!f)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot associate stream with file descriptor"));
 | 
			
		||||
  BufferedFile file(f);
 | 
			
		||||
  fd_ = -1;
 | 
			
		||||
  return file;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
long fmt::getpagesize() {
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
  SYSTEM_INFO si;
 | 
			
		||||
  GetSystemInfo(&si);
 | 
			
		||||
  return si.dwPageSize;
 | 
			
		||||
#else
 | 
			
		||||
  long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
 | 
			
		||||
  if (size < 0)
 | 
			
		||||
    FMT_THROW(SystemError(errno, "cannot get memory page size"));
 | 
			
		||||
  return size;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										367
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/posix.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										367
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/posix.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,367 @@
 | 
			
		||||
/*
 | 
			
		||||
 A C++ interface to POSIX functions.
 | 
			
		||||
 | 
			
		||||
 Copyright (c) 2012 - 2016, Victor Zverovich
 | 
			
		||||
 All rights reserved.
 | 
			
		||||
 | 
			
		||||
 For the license information refer to format.h.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_POSIX_H_
 | 
			
		||||
#define FMT_POSIX_H_
 | 
			
		||||
 | 
			
		||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
 | 
			
		||||
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
 | 
			
		||||
# undef __STRICT_ANSI__
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>   // for O_RDONLY
 | 
			
		||||
#include <locale.h>  // for locale_t
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>  // for strtod_l
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
 | 
			
		||||
#if defined __APPLE__ || defined(__FreeBSD__)
 | 
			
		||||
# include <xlocale.h>  // for LC_NUMERIC_MASK on OS X
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_POSIX
 | 
			
		||||
# if defined(_WIN32) && !defined(__MINGW32__)
 | 
			
		||||
// Fix warnings about deprecated symbols.
 | 
			
		||||
#  define FMT_POSIX(call) _##call
 | 
			
		||||
# else
 | 
			
		||||
#  define FMT_POSIX(call) call
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
 | 
			
		||||
#ifdef FMT_SYSTEM
 | 
			
		||||
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
 | 
			
		||||
#else
 | 
			
		||||
# define FMT_SYSTEM(call) call
 | 
			
		||||
# ifdef _WIN32
 | 
			
		||||
// Fix warnings about deprecated symbols.
 | 
			
		||||
#  define FMT_POSIX_CALL(call) ::_##call
 | 
			
		||||
# else
 | 
			
		||||
#  define FMT_POSIX_CALL(call) ::call
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Retries the expression while it evaluates to error_result and errno
 | 
			
		||||
// equals to EINTR.
 | 
			
		||||
#ifndef _WIN32
 | 
			
		||||
# define FMT_RETRY_VAL(result, expression, error_result) \
 | 
			
		||||
  do { \
 | 
			
		||||
    result = (expression); \
 | 
			
		||||
  } while (result == error_result && errno == EINTR)
 | 
			
		||||
#else
 | 
			
		||||
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
 | 
			
		||||
 | 
			
		||||
namespace fmt {
 | 
			
		||||
 | 
			
		||||
// An error code.
 | 
			
		||||
class ErrorCode {
 | 
			
		||||
 private:
 | 
			
		||||
  int value_;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  explicit ErrorCode(int value = 0) FMT_NOEXCEPT : value_(value) {}
 | 
			
		||||
 | 
			
		||||
  int get() const FMT_NOEXCEPT { return value_; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// A buffered file.
 | 
			
		||||
class BufferedFile {
 | 
			
		||||
 private:
 | 
			
		||||
  FILE *file_;
 | 
			
		||||
 | 
			
		||||
  friend class File;
 | 
			
		||||
 | 
			
		||||
  explicit BufferedFile(FILE *f) : file_(f) {}
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  // Constructs a BufferedFile object which doesn't represent any file.
 | 
			
		||||
  BufferedFile() FMT_NOEXCEPT : file_(FMT_NULL) {}
 | 
			
		||||
 | 
			
		||||
  // Destroys the object closing the file it represents if any.
 | 
			
		||||
  FMT_API ~BufferedFile() FMT_NOEXCEPT;
 | 
			
		||||
 | 
			
		||||
#if !FMT_USE_RVALUE_REFERENCES
 | 
			
		||||
  // Emulate a move constructor and a move assignment operator if rvalue
 | 
			
		||||
  // references are not supported.
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  // A proxy object to emulate a move constructor.
 | 
			
		||||
  // It is private to make it impossible call operator Proxy directly.
 | 
			
		||||
  struct Proxy {
 | 
			
		||||
    FILE *file;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  // A "move constructor" for moving from a temporary.
 | 
			
		||||
  BufferedFile(Proxy p) FMT_NOEXCEPT : file_(p.file) {}
 | 
			
		||||
 | 
			
		||||
  // A "move constructor" for moving from an lvalue.
 | 
			
		||||
  BufferedFile(BufferedFile &f) FMT_NOEXCEPT : file_(f.file_) {
 | 
			
		||||
    f.file_ = FMT_NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // A "move assignment operator" for moving from a temporary.
 | 
			
		||||
  BufferedFile &operator=(Proxy p) {
 | 
			
		||||
    close();
 | 
			
		||||
    file_ = p.file;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // A "move assignment operator" for moving from an lvalue.
 | 
			
		||||
  BufferedFile &operator=(BufferedFile &other) {
 | 
			
		||||
    close();
 | 
			
		||||
    file_ = other.file_;
 | 
			
		||||
    other.file_ = FMT_NULL;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Returns a proxy object for moving from a temporary:
 | 
			
		||||
  //   BufferedFile file = BufferedFile(...);
 | 
			
		||||
  operator Proxy() FMT_NOEXCEPT {
 | 
			
		||||
    Proxy p = {file_};
 | 
			
		||||
    file_ = FMT_NULL;
 | 
			
		||||
    return p;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 private:
 | 
			
		||||
  FMT_DISALLOW_COPY_AND_ASSIGN(BufferedFile);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  BufferedFile(BufferedFile &&other) FMT_NOEXCEPT : file_(other.file_) {
 | 
			
		||||
    other.file_ = FMT_NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  BufferedFile& operator=(BufferedFile &&other) {
 | 
			
		||||
    close();
 | 
			
		||||
    file_ = other.file_;
 | 
			
		||||
    other.file_ = FMT_NULL;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // Opens a file.
 | 
			
		||||
  FMT_API BufferedFile(CStringRef filename, CStringRef mode);
 | 
			
		||||
 | 
			
		||||
  // Closes the file.
 | 
			
		||||
  FMT_API void close();
 | 
			
		||||
 | 
			
		||||
  // Returns the pointer to a FILE object representing this file.
 | 
			
		||||
  FILE *get() const FMT_NOEXCEPT { return file_; }
 | 
			
		||||
 | 
			
		||||
  // We place parentheses around fileno to workaround a bug in some versions
 | 
			
		||||
  // of MinGW that define fileno as a macro.
 | 
			
		||||
  FMT_API int (fileno)() const;
 | 
			
		||||
 | 
			
		||||
  void print(CStringRef format_str, const ArgList &args) {
 | 
			
		||||
    fmt::print(file_, format_str, args);
 | 
			
		||||
  }
 | 
			
		||||
  FMT_VARIADIC(void, print, CStringRef)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// A file. Closed file is represented by a File object with descriptor -1.
 | 
			
		||||
// Methods that are not declared with FMT_NOEXCEPT may throw
 | 
			
		||||
// fmt::SystemError in case of failure. Note that some errors such as
 | 
			
		||||
// closing the file multiple times will cause a crash on Windows rather
 | 
			
		||||
// than an exception. You can get standard behavior by overriding the
 | 
			
		||||
// invalid parameter handler with _set_invalid_parameter_handler.
 | 
			
		||||
class File {
 | 
			
		||||
 private:
 | 
			
		||||
  int fd_;  // File descriptor.
 | 
			
		||||
 | 
			
		||||
  // Constructs a File object with a given descriptor.
 | 
			
		||||
  explicit File(int fd) : fd_(fd) {}
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  // Possible values for the oflag argument to the constructor.
 | 
			
		||||
  enum {
 | 
			
		||||
    RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
 | 
			
		||||
    WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
 | 
			
		||||
    RDWR   = FMT_POSIX(O_RDWR)    // Open for reading and writing.
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Constructs a File object which doesn't represent any file.
 | 
			
		||||
  File() FMT_NOEXCEPT : fd_(-1) {}
 | 
			
		||||
 | 
			
		||||
  // Opens a file and constructs a File object representing this file.
 | 
			
		||||
  FMT_API File(CStringRef path, int oflag);
 | 
			
		||||
 | 
			
		||||
#if !FMT_USE_RVALUE_REFERENCES
 | 
			
		||||
  // Emulate a move constructor and a move assignment operator if rvalue
 | 
			
		||||
  // references are not supported.
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  // A proxy object to emulate a move constructor.
 | 
			
		||||
  // It is private to make it impossible call operator Proxy directly.
 | 
			
		||||
  struct Proxy {
 | 
			
		||||
    int fd;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  // A "move constructor" for moving from a temporary.
 | 
			
		||||
  File(Proxy p) FMT_NOEXCEPT : fd_(p.fd) {}
 | 
			
		||||
 | 
			
		||||
  // A "move constructor" for moving from an lvalue.
 | 
			
		||||
  File(File &other) FMT_NOEXCEPT : fd_(other.fd_) {
 | 
			
		||||
    other.fd_ = -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // A "move assignment operator" for moving from a temporary.
 | 
			
		||||
  File &operator=(Proxy p) {
 | 
			
		||||
    close();
 | 
			
		||||
    fd_ = p.fd;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // A "move assignment operator" for moving from an lvalue.
 | 
			
		||||
  File &operator=(File &other) {
 | 
			
		||||
    close();
 | 
			
		||||
    fd_ = other.fd_;
 | 
			
		||||
    other.fd_ = -1;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Returns a proxy object for moving from a temporary:
 | 
			
		||||
  //   File file = File(...);
 | 
			
		||||
  operator Proxy() FMT_NOEXCEPT {
 | 
			
		||||
    Proxy p = {fd_};
 | 
			
		||||
    fd_ = -1;
 | 
			
		||||
    return p;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 private:
 | 
			
		||||
  FMT_DISALLOW_COPY_AND_ASSIGN(File);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  File(File &&other) FMT_NOEXCEPT : fd_(other.fd_) {
 | 
			
		||||
    other.fd_ = -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  File& operator=(File &&other) {
 | 
			
		||||
    close();
 | 
			
		||||
    fd_ = other.fd_;
 | 
			
		||||
    other.fd_ = -1;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // Destroys the object closing the file it represents if any.
 | 
			
		||||
  FMT_API ~File() FMT_NOEXCEPT;
 | 
			
		||||
 | 
			
		||||
  // Returns the file descriptor.
 | 
			
		||||
  int descriptor() const FMT_NOEXCEPT { return fd_; }
 | 
			
		||||
 | 
			
		||||
  // Closes the file.
 | 
			
		||||
  FMT_API void close();
 | 
			
		||||
 | 
			
		||||
  // Returns the file size. The size has signed type for consistency with
 | 
			
		||||
  // stat::st_size.
 | 
			
		||||
  FMT_API LongLong size() const;
 | 
			
		||||
 | 
			
		||||
  // Attempts to read count bytes from the file into the specified buffer.
 | 
			
		||||
  FMT_API std::size_t read(void *buffer, std::size_t count);
 | 
			
		||||
 | 
			
		||||
  // Attempts to write count bytes from the specified buffer to the file.
 | 
			
		||||
  FMT_API std::size_t write(const void *buffer, std::size_t count);
 | 
			
		||||
 | 
			
		||||
  // Duplicates a file descriptor with the dup function and returns
 | 
			
		||||
  // the duplicate as a file object.
 | 
			
		||||
  FMT_API static File dup(int fd);
 | 
			
		||||
 | 
			
		||||
  // Makes fd be the copy of this file descriptor, closing fd first if
 | 
			
		||||
  // necessary.
 | 
			
		||||
  FMT_API void dup2(int fd);
 | 
			
		||||
 | 
			
		||||
  // Makes fd be the copy of this file descriptor, closing fd first if
 | 
			
		||||
  // necessary.
 | 
			
		||||
  FMT_API void dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT;
 | 
			
		||||
 | 
			
		||||
  // Creates a pipe setting up read_end and write_end file objects for reading
 | 
			
		||||
  // and writing respectively.
 | 
			
		||||
  FMT_API static void pipe(File &read_end, File &write_end);
 | 
			
		||||
 | 
			
		||||
  // Creates a BufferedFile object associated with this file and detaches
 | 
			
		||||
  // this File object from the file.
 | 
			
		||||
  FMT_API BufferedFile fdopen(const char *mode);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Returns the memory page size.
 | 
			
		||||
long getpagesize();
 | 
			
		||||
 | 
			
		||||
#if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \
 | 
			
		||||
    !defined(__ANDROID__) && !defined(__CYGWIN__)
 | 
			
		||||
# define FMT_LOCALE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef FMT_LOCALE
 | 
			
		||||
// A "C" numeric locale.
 | 
			
		||||
class Locale {
 | 
			
		||||
 private:
 | 
			
		||||
# ifdef _MSC_VER
 | 
			
		||||
  typedef _locale_t locale_t;
 | 
			
		||||
 | 
			
		||||
  enum { LC_NUMERIC_MASK = LC_NUMERIC };
 | 
			
		||||
 | 
			
		||||
  static locale_t newlocale(int category_mask, const char *locale, locale_t) {
 | 
			
		||||
    return _create_locale(category_mask, locale);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static void freelocale(locale_t locale) {
 | 
			
		||||
    _free_locale(locale);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static double strtod_l(const char *nptr, char **endptr, _locale_t locale) {
 | 
			
		||||
    return _strtod_l(nptr, endptr, locale);
 | 
			
		||||
  }
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
  locale_t locale_;
 | 
			
		||||
 | 
			
		||||
  FMT_DISALLOW_COPY_AND_ASSIGN(Locale);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  typedef locale_t Type;
 | 
			
		||||
 | 
			
		||||
  Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL)) {
 | 
			
		||||
    if (!locale_)
 | 
			
		||||
      FMT_THROW(fmt::SystemError(errno, "cannot create locale"));
 | 
			
		||||
  }
 | 
			
		||||
  ~Locale() { freelocale(locale_); }
 | 
			
		||||
 | 
			
		||||
  Type get() const { return locale_; }
 | 
			
		||||
 | 
			
		||||
  // Converts string to floating-point number and advances str past the end
 | 
			
		||||
  // of the parsed input.
 | 
			
		||||
  double strtod(const char *&str) const {
 | 
			
		||||
    char *end = FMT_NULL;
 | 
			
		||||
    double result = strtod_l(str, &end, locale_);
 | 
			
		||||
    str = end;
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
#endif  // FMT_LOCALE
 | 
			
		||||
}  // namespace fmt
 | 
			
		||||
 | 
			
		||||
#if !FMT_USE_RVALUE_REFERENCES
 | 
			
		||||
namespace std {
 | 
			
		||||
// For compatibility with C++98.
 | 
			
		||||
inline fmt::BufferedFile &move(fmt::BufferedFile &f) { return f; }
 | 
			
		||||
inline fmt::File &move(fmt::File &f) { return f; }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_POSIX_H_
 | 
			
		||||
							
								
								
									
										32
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/printf.cc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/printf.cc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
/*
 | 
			
		||||
 Formatting library for C++
 | 
			
		||||
 | 
			
		||||
 Copyright (c) 2012 - 2016, Victor Zverovich
 | 
			
		||||
 All rights reserved.
 | 
			
		||||
 | 
			
		||||
 For the license information refer to format.h.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
#include "printf.h"
 | 
			
		||||
 | 
			
		||||
namespace fmt {
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args);
 | 
			
		||||
 | 
			
		||||
FMT_FUNC int fprintf(std::FILE *f, CStringRef format, ArgList args) {
 | 
			
		||||
  MemoryWriter w;
 | 
			
		||||
  printf(w, format, args);
 | 
			
		||||
  std::size_t size = w.size();
 | 
			
		||||
  return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_HEADER_ONLY
 | 
			
		||||
 | 
			
		||||
template void PrintfFormatter<char>::format(CStringRef format);
 | 
			
		||||
template void PrintfFormatter<wchar_t>::format(WCStringRef format);
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_HEADER_ONLY
 | 
			
		||||
 | 
			
		||||
}  // namespace fmt
 | 
			
		||||
							
								
								
									
										603
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/printf.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										603
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/printf.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,603 @@
 | 
			
		||||
/*
 | 
			
		||||
 Formatting library for C++
 | 
			
		||||
 | 
			
		||||
 Copyright (c) 2012 - 2016, Victor Zverovich
 | 
			
		||||
 All rights reserved.
 | 
			
		||||
 | 
			
		||||
 For the license information refer to format.h.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_PRINTF_H_
 | 
			
		||||
#define FMT_PRINTF_H_
 | 
			
		||||
 | 
			
		||||
#include <algorithm>  // std::fill_n
 | 
			
		||||
#include <limits>     // std::numeric_limits
 | 
			
		||||
 | 
			
		||||
#include "ostream.h"
 | 
			
		||||
 | 
			
		||||
namespace fmt {
 | 
			
		||||
namespace internal {
 | 
			
		||||
 | 
			
		||||
// Checks if a value fits in int - used to avoid warnings about comparing
 | 
			
		||||
// signed and unsigned integers.
 | 
			
		||||
template <bool IsSigned>
 | 
			
		||||
struct IntChecker {
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  static bool fits_in_int(T value) {
 | 
			
		||||
    unsigned max = std::numeric_limits<int>::max();
 | 
			
		||||
    return value <= max;
 | 
			
		||||
  }
 | 
			
		||||
  static bool fits_in_int(bool) { return true; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct IntChecker<true> {
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  static bool fits_in_int(T value) {
 | 
			
		||||
    return value >= std::numeric_limits<int>::min() &&
 | 
			
		||||
           value <= std::numeric_limits<int>::max();
 | 
			
		||||
  }
 | 
			
		||||
  static bool fits_in_int(int) { return true; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class PrecisionHandler : public ArgVisitor<PrecisionHandler, int> {
 | 
			
		||||
 public:
 | 
			
		||||
  void report_unhandled_arg() {
 | 
			
		||||
    FMT_THROW(FormatError("precision is not integer"));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  int visit_any_int(T value) {
 | 
			
		||||
    if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
 | 
			
		||||
      FMT_THROW(FormatError("number is too big"));
 | 
			
		||||
    return static_cast<int>(value);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
 | 
			
		||||
class IsZeroInt : public ArgVisitor<IsZeroInt, bool> {
 | 
			
		||||
 public:
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  bool visit_any_int(T value) { return value == 0; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// returns the default type for format specific "%s"
 | 
			
		||||
class DefaultType : public ArgVisitor<DefaultType, char> {
 | 
			
		||||
 public:
 | 
			
		||||
  char visit_char(int) { return 'c'; }
 | 
			
		||||
 | 
			
		||||
  char visit_bool(bool) { return 's'; }
 | 
			
		||||
 | 
			
		||||
  char visit_pointer(const void *) { return 'p'; }
 | 
			
		||||
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  char visit_any_int(T) { return 'd'; }
 | 
			
		||||
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  char visit_any_double(T) { return 'g'; }
 | 
			
		||||
 | 
			
		||||
  char visit_unhandled_arg() { return 's'; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T, typename U>
 | 
			
		||||
struct is_same {
 | 
			
		||||
  enum { value = 0 };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct is_same<T, T> {
 | 
			
		||||
  enum { value = 1 };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// An argument visitor that converts an integer argument to T for printf,
 | 
			
		||||
// if T is an integral type. If T is void, the argument is converted to
 | 
			
		||||
// corresponding signed or unsigned type depending on the type specifier:
 | 
			
		||||
// 'd' and 'i' - signed, other - unsigned)
 | 
			
		||||
template <typename T = void>
 | 
			
		||||
class ArgConverter : public ArgVisitor<ArgConverter<T>, void> {
 | 
			
		||||
 private:
 | 
			
		||||
  internal::Arg &arg_;
 | 
			
		||||
  wchar_t type_;
 | 
			
		||||
 | 
			
		||||
  FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  ArgConverter(internal::Arg &arg, wchar_t type)
 | 
			
		||||
    : arg_(arg), type_(type) {}
 | 
			
		||||
 | 
			
		||||
  void visit_bool(bool value) {
 | 
			
		||||
    if (type_ != 's')
 | 
			
		||||
      visit_any_int(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void visit_char(char value) {
 | 
			
		||||
    if (type_ != 's')
 | 
			
		||||
      visit_any_int(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  void visit_any_int(U value) {
 | 
			
		||||
    bool is_signed = type_ == 'd' || type_ == 'i';
 | 
			
		||||
    if (type_ == 's') {
 | 
			
		||||
      is_signed = std::numeric_limits<U>::is_signed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    using internal::Arg;
 | 
			
		||||
    typedef typename internal::Conditional<
 | 
			
		||||
        is_same<T, void>::value, U, T>::type TargetType;
 | 
			
		||||
    if (sizeof(TargetType) <= sizeof(int)) {
 | 
			
		||||
      // Extra casts are used to silence warnings.
 | 
			
		||||
      if (is_signed) {
 | 
			
		||||
        arg_.type = Arg::INT;
 | 
			
		||||
        arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
 | 
			
		||||
      } else {
 | 
			
		||||
        arg_.type = Arg::UINT;
 | 
			
		||||
        typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned;
 | 
			
		||||
        arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      if (is_signed) {
 | 
			
		||||
        arg_.type = Arg::LONG_LONG;
 | 
			
		||||
        // glibc's printf doesn't sign extend arguments of smaller types:
 | 
			
		||||
        //   std::printf("%lld", -42);  // prints "4294967254"
 | 
			
		||||
        // but we don't have to do the same because it's a UB.
 | 
			
		||||
        arg_.long_long_value = static_cast<LongLong>(value);
 | 
			
		||||
      } else {
 | 
			
		||||
        arg_.type = Arg::ULONG_LONG;
 | 
			
		||||
        arg_.ulong_long_value =
 | 
			
		||||
            static_cast<typename internal::MakeUnsigned<U>::Type>(value);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Converts an integer argument to char for printf.
 | 
			
		||||
class CharConverter : public ArgVisitor<CharConverter, void> {
 | 
			
		||||
 private:
 | 
			
		||||
  internal::Arg &arg_;
 | 
			
		||||
 | 
			
		||||
  FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  explicit CharConverter(internal::Arg &arg) : arg_(arg) {}
 | 
			
		||||
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  void visit_any_int(T value) {
 | 
			
		||||
    arg_.type = internal::Arg::CHAR;
 | 
			
		||||
    arg_.int_value = static_cast<char>(value);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Checks if an argument is a valid printf width specifier and sets
 | 
			
		||||
// left alignment if it is negative.
 | 
			
		||||
class WidthHandler : public ArgVisitor<WidthHandler, unsigned> {
 | 
			
		||||
 private:
 | 
			
		||||
  FormatSpec &spec_;
 | 
			
		||||
 | 
			
		||||
  FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  explicit WidthHandler(FormatSpec &spec) : spec_(spec) {}
 | 
			
		||||
 | 
			
		||||
  void report_unhandled_arg() {
 | 
			
		||||
    FMT_THROW(FormatError("width is not integer"));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  unsigned visit_any_int(T value) {
 | 
			
		||||
    typedef typename internal::IntTraits<T>::MainType UnsignedType;
 | 
			
		||||
    UnsignedType width = static_cast<UnsignedType>(value);
 | 
			
		||||
    if (internal::is_negative(value)) {
 | 
			
		||||
      spec_.align_ = ALIGN_LEFT;
 | 
			
		||||
      width = 0 - width;
 | 
			
		||||
    }
 | 
			
		||||
    unsigned int_max = std::numeric_limits<int>::max();
 | 
			
		||||
    if (width > int_max)
 | 
			
		||||
      FMT_THROW(FormatError("number is too big"));
 | 
			
		||||
    return static_cast<unsigned>(width);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
}  // namespace internal
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  A ``printf`` argument formatter based on the `curiously recurring template
 | 
			
		||||
  pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
 | 
			
		||||
 | 
			
		||||
  To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some
 | 
			
		||||
  or all of the visit methods with the same signatures as the methods in
 | 
			
		||||
  `~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`.
 | 
			
		||||
  Pass the subclass as the *Impl* template parameter. When a formatting
 | 
			
		||||
  function processes an argument, it will dispatch to a visit method
 | 
			
		||||
  specific to the argument type. For example, if the argument type is
 | 
			
		||||
  ``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
 | 
			
		||||
  will be called. If the subclass doesn't contain a method with this signature,
 | 
			
		||||
  then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its
 | 
			
		||||
  superclass will be called.
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
template <typename Impl, typename Char, typename Spec>
 | 
			
		||||
class BasicPrintfArgFormatter :
 | 
			
		||||
    public internal::ArgFormatterBase<Impl, Char, Spec> {
 | 
			
		||||
 private:
 | 
			
		||||
  void write_null_pointer() {
 | 
			
		||||
    this->spec().type_ = 0;
 | 
			
		||||
    this->write("(nil)");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  typedef internal::ArgFormatterBase<Impl, Char, Spec> Base;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  /**
 | 
			
		||||
    \rst
 | 
			
		||||
    Constructs an argument formatter object.
 | 
			
		||||
    *writer* is a reference to the output writer and *spec* contains format
 | 
			
		||||
    specifier information for standard argument types.
 | 
			
		||||
    \endrst
 | 
			
		||||
   */
 | 
			
		||||
  BasicPrintfArgFormatter(BasicWriter<Char> &w, Spec &s)
 | 
			
		||||
  : internal::ArgFormatterBase<Impl, Char, Spec>(w, s) {}
 | 
			
		||||
 | 
			
		||||
  /** Formats an argument of type ``bool``. */
 | 
			
		||||
  void visit_bool(bool value) {
 | 
			
		||||
    Spec &fmt_spec = this->spec();
 | 
			
		||||
    if (fmt_spec.type_ != 's')
 | 
			
		||||
      return this->visit_any_int(value);
 | 
			
		||||
    fmt_spec.type_ = 0;
 | 
			
		||||
    this->write(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Formats a character. */
 | 
			
		||||
  void visit_char(int value) {
 | 
			
		||||
    const Spec &fmt_spec = this->spec();
 | 
			
		||||
    BasicWriter<Char> &w = this->writer();
 | 
			
		||||
    if (fmt_spec.type_ && fmt_spec.type_ != 'c')
 | 
			
		||||
      w.write_int(value, fmt_spec);
 | 
			
		||||
    typedef typename BasicWriter<Char>::CharPtr CharPtr;
 | 
			
		||||
    CharPtr out = CharPtr();
 | 
			
		||||
    if (fmt_spec.width_ > 1) {
 | 
			
		||||
      Char fill = ' ';
 | 
			
		||||
      out = w.grow_buffer(fmt_spec.width_);
 | 
			
		||||
      if (fmt_spec.align_ != ALIGN_LEFT) {
 | 
			
		||||
        std::fill_n(out, fmt_spec.width_ - 1, fill);
 | 
			
		||||
        out += fmt_spec.width_ - 1;
 | 
			
		||||
      } else {
 | 
			
		||||
        std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      out = w.grow_buffer(1);
 | 
			
		||||
    }
 | 
			
		||||
    *out = static_cast<Char>(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Formats a null-terminated C string. */
 | 
			
		||||
  void visit_cstring(const char *value) {
 | 
			
		||||
    if (value)
 | 
			
		||||
      Base::visit_cstring(value);
 | 
			
		||||
    else if (this->spec().type_ == 'p')
 | 
			
		||||
      write_null_pointer();
 | 
			
		||||
    else
 | 
			
		||||
      this->write("(null)");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Formats a pointer. */
 | 
			
		||||
  void visit_pointer(const void *value) {
 | 
			
		||||
    if (value)
 | 
			
		||||
      return Base::visit_pointer(value);
 | 
			
		||||
    this->spec().type_ = 0;
 | 
			
		||||
    write_null_pointer();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Formats an argument of a custom (user-defined) type. */
 | 
			
		||||
  void visit_custom(internal::Arg::CustomValue c) {
 | 
			
		||||
    BasicFormatter<Char> formatter(ArgList(), this->writer());
 | 
			
		||||
    const Char format_str[] = {'}', 0};
 | 
			
		||||
    const Char *format = format_str;
 | 
			
		||||
    c.format(&formatter, c.value, &format);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** The default printf argument formatter. */
 | 
			
		||||
template <typename Char>
 | 
			
		||||
class PrintfArgFormatter :
 | 
			
		||||
    public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec> {
 | 
			
		||||
 public:
 | 
			
		||||
  /** Constructs an argument formatter object. */
 | 
			
		||||
  PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
 | 
			
		||||
  : BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char, FormatSpec>(w, s) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** This template formats data and writes the output to a writer. */
 | 
			
		||||
template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> >
 | 
			
		||||
class PrintfFormatter : private internal::FormatterBase {
 | 
			
		||||
 private:
 | 
			
		||||
  BasicWriter<Char> &writer_;
 | 
			
		||||
 | 
			
		||||
  void parse_flags(FormatSpec &spec, const Char *&s);
 | 
			
		||||
 | 
			
		||||
  // Returns the argument with specified index or, if arg_index is equal
 | 
			
		||||
  // to the maximum unsigned value, the next argument.
 | 
			
		||||
  internal::Arg get_arg(
 | 
			
		||||
      const Char *s,
 | 
			
		||||
      unsigned arg_index = (std::numeric_limits<unsigned>::max)());
 | 
			
		||||
 | 
			
		||||
  // Parses argument index, flags and width and returns the argument index.
 | 
			
		||||
  unsigned parse_header(const Char *&s, FormatSpec &spec);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  /**
 | 
			
		||||
   \rst
 | 
			
		||||
   Constructs a ``PrintfFormatter`` object. References to the arguments and
 | 
			
		||||
   the writer are stored in the formatter object so make sure they have
 | 
			
		||||
   appropriate lifetimes.
 | 
			
		||||
   \endrst
 | 
			
		||||
   */
 | 
			
		||||
  explicit PrintfFormatter(const ArgList &al, BasicWriter<Char> &w)
 | 
			
		||||
    : FormatterBase(al), writer_(w) {}
 | 
			
		||||
 | 
			
		||||
  /** Formats stored arguments and writes the output to the writer. */
 | 
			
		||||
  void format(BasicCStringRef<Char> format_str);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename AF>
 | 
			
		||||
void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s) {
 | 
			
		||||
  for (;;) {
 | 
			
		||||
    switch (*s++) {
 | 
			
		||||
      case '-':
 | 
			
		||||
        spec.align_ = ALIGN_LEFT;
 | 
			
		||||
        break;
 | 
			
		||||
      case '+':
 | 
			
		||||
        spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
 | 
			
		||||
        break;
 | 
			
		||||
      case '0':
 | 
			
		||||
        spec.fill_ = '0';
 | 
			
		||||
        break;
 | 
			
		||||
      case ' ':
 | 
			
		||||
        spec.flags_ |= SIGN_FLAG;
 | 
			
		||||
        break;
 | 
			
		||||
      case '#':
 | 
			
		||||
        spec.flags_ |= HASH_FLAG;
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        --s;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename AF>
 | 
			
		||||
internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
 | 
			
		||||
                                                 unsigned arg_index) {
 | 
			
		||||
  (void)s;
 | 
			
		||||
  const char *error = FMT_NULL;
 | 
			
		||||
  internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
 | 
			
		||||
    next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
 | 
			
		||||
  if (error)
 | 
			
		||||
    FMT_THROW(FormatError(!*s ? "invalid format string" : error));
 | 
			
		||||
  return arg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename AF>
 | 
			
		||||
unsigned PrintfFormatter<Char, AF>::parse_header(
 | 
			
		||||
  const Char *&s, FormatSpec &spec) {
 | 
			
		||||
  unsigned arg_index = std::numeric_limits<unsigned>::max();
 | 
			
		||||
  Char c = *s;
 | 
			
		||||
  if (c >= '0' && c <= '9') {
 | 
			
		||||
    // Parse an argument index (if followed by '$') or a width possibly
 | 
			
		||||
    // preceded with '0' flag(s).
 | 
			
		||||
    unsigned value = internal::parse_nonnegative_int(s);
 | 
			
		||||
    if (*s == '$') {  // value is an argument index
 | 
			
		||||
      ++s;
 | 
			
		||||
      arg_index = value;
 | 
			
		||||
    } else {
 | 
			
		||||
      if (c == '0')
 | 
			
		||||
        spec.fill_ = '0';
 | 
			
		||||
      if (value != 0) {
 | 
			
		||||
        // Nonzero value means that we parsed width and don't need to
 | 
			
		||||
        // parse it or flags again, so return now.
 | 
			
		||||
        spec.width_ = value;
 | 
			
		||||
        return arg_index;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  parse_flags(spec, s);
 | 
			
		||||
  // Parse width.
 | 
			
		||||
  if (*s >= '0' && *s <= '9') {
 | 
			
		||||
    spec.width_ = internal::parse_nonnegative_int(s);
 | 
			
		||||
  } else if (*s == '*') {
 | 
			
		||||
    ++s;
 | 
			
		||||
    spec.width_ = internal::WidthHandler(spec).visit(get_arg(s));
 | 
			
		||||
  }
 | 
			
		||||
  return arg_index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename AF>
 | 
			
		||||
void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str) {
 | 
			
		||||
  const Char *start = format_str.c_str();
 | 
			
		||||
  const Char *s = start;
 | 
			
		||||
  while (*s) {
 | 
			
		||||
    Char c = *s++;
 | 
			
		||||
    if (c != '%') continue;
 | 
			
		||||
    if (*s == c) {
 | 
			
		||||
      write(writer_, start, s);
 | 
			
		||||
      start = ++s;
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    write(writer_, start, s - 1);
 | 
			
		||||
 | 
			
		||||
    FormatSpec spec;
 | 
			
		||||
    spec.align_ = ALIGN_RIGHT;
 | 
			
		||||
 | 
			
		||||
    // Parse argument index, flags and width.
 | 
			
		||||
    unsigned arg_index = parse_header(s, spec);
 | 
			
		||||
 | 
			
		||||
    // Parse precision.
 | 
			
		||||
    if (*s == '.') {
 | 
			
		||||
      ++s;
 | 
			
		||||
      if ('0' <= *s && *s <= '9') {
 | 
			
		||||
        spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s));
 | 
			
		||||
      } else if (*s == '*') {
 | 
			
		||||
        ++s;
 | 
			
		||||
        spec.precision_ = internal::PrecisionHandler().visit(get_arg(s));
 | 
			
		||||
      } else {
 | 
			
		||||
        spec.precision_ = 0;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    using internal::Arg;
 | 
			
		||||
    Arg arg = get_arg(s, arg_index);
 | 
			
		||||
    if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg))
 | 
			
		||||
      spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG);
 | 
			
		||||
    if (spec.fill_ == '0') {
 | 
			
		||||
      if (arg.type <= Arg::LAST_NUMERIC_TYPE)
 | 
			
		||||
        spec.align_ = ALIGN_NUMERIC;
 | 
			
		||||
      else
 | 
			
		||||
        spec.fill_ = ' ';  // Ignore '0' flag for non-numeric types.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Parse length and convert the argument to the required type.
 | 
			
		||||
    using internal::ArgConverter;
 | 
			
		||||
    switch (*s++) {
 | 
			
		||||
    case 'h':
 | 
			
		||||
      if (*s == 'h')
 | 
			
		||||
        ArgConverter<signed char>(arg, *++s).visit(arg);
 | 
			
		||||
      else
 | 
			
		||||
        ArgConverter<short>(arg, *s).visit(arg);
 | 
			
		||||
      break;
 | 
			
		||||
    case 'l':
 | 
			
		||||
      if (*s == 'l')
 | 
			
		||||
        ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
 | 
			
		||||
      else
 | 
			
		||||
        ArgConverter<long>(arg, *s).visit(arg);
 | 
			
		||||
      break;
 | 
			
		||||
    case 'j':
 | 
			
		||||
      ArgConverter<intmax_t>(arg, *s).visit(arg);
 | 
			
		||||
      break;
 | 
			
		||||
    case 'z':
 | 
			
		||||
      ArgConverter<std::size_t>(arg, *s).visit(arg);
 | 
			
		||||
      break;
 | 
			
		||||
    case 't':
 | 
			
		||||
      ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
 | 
			
		||||
      break;
 | 
			
		||||
    case 'L':
 | 
			
		||||
      // printf produces garbage when 'L' is omitted for long double, no
 | 
			
		||||
      // need to do the same.
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      --s;
 | 
			
		||||
      ArgConverter<void>(arg, *s).visit(arg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Parse type.
 | 
			
		||||
    if (!*s)
 | 
			
		||||
      FMT_THROW(FormatError("invalid format string"));
 | 
			
		||||
    spec.type_ = static_cast<char>(*s++);
 | 
			
		||||
 | 
			
		||||
    if (spec.type_ == 's') {
 | 
			
		||||
      // set the format type to the default if 's' is specified
 | 
			
		||||
      spec.type_ = internal::DefaultType().visit(arg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (arg.type <= Arg::LAST_INTEGER_TYPE) {
 | 
			
		||||
      // Normalize type.
 | 
			
		||||
      switch (spec.type_) {
 | 
			
		||||
      case 'i': case 'u':
 | 
			
		||||
        spec.type_ = 'd';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'c':
 | 
			
		||||
        // TODO: handle wchar_t
 | 
			
		||||
        internal::CharConverter(arg).visit(arg);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    start = s;
 | 
			
		||||
 | 
			
		||||
    // Format argument.
 | 
			
		||||
    AF(writer_, spec).visit(arg);
 | 
			
		||||
  }
 | 
			
		||||
  write(writer_, start, s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void printf(Writer &w, CStringRef format, ArgList args) {
 | 
			
		||||
  PrintfFormatter<char>(args, w).format(format);
 | 
			
		||||
}
 | 
			
		||||
FMT_VARIADIC(void, printf, Writer &, CStringRef)
 | 
			
		||||
 | 
			
		||||
inline void printf(WWriter &w, WCStringRef format, ArgList args) {
 | 
			
		||||
  PrintfFormatter<wchar_t>(args, w).format(format);
 | 
			
		||||
}
 | 
			
		||||
FMT_VARIADIC(void, printf, WWriter &, WCStringRef)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Formats arguments and returns the result as a string.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    std::string message = fmt::sprintf("The answer is %d", 42);
 | 
			
		||||
  \endrst
 | 
			
		||||
*/
 | 
			
		||||
inline std::string sprintf(CStringRef format, ArgList args) {
 | 
			
		||||
  MemoryWriter w;
 | 
			
		||||
  printf(w, format, args);
 | 
			
		||||
  return w.str();
 | 
			
		||||
}
 | 
			
		||||
FMT_VARIADIC(std::string, sprintf, CStringRef)
 | 
			
		||||
 | 
			
		||||
inline std::wstring sprintf(WCStringRef format, ArgList args) {
 | 
			
		||||
  WMemoryWriter w;
 | 
			
		||||
  printf(w, format, args);
 | 
			
		||||
  return w.str();
 | 
			
		||||
}
 | 
			
		||||
FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Prints formatted data to the file *f*.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    fmt::fprintf(stderr, "Don't %s!", "panic");
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args);
 | 
			
		||||
FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Prints formatted data to ``stdout``.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    fmt::printf("Elapsed time: %.2f seconds", 1.23);
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
inline int printf(CStringRef format, ArgList args) {
 | 
			
		||||
  return fprintf(stdout, format, args);
 | 
			
		||||
}
 | 
			
		||||
FMT_VARIADIC(int, printf, CStringRef)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Prints formatted data to the stream *os*.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    fprintf(cerr, "Don't %s!", "panic");
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args) {
 | 
			
		||||
  MemoryWriter w;
 | 
			
		||||
  printf(w, format_str, args);
 | 
			
		||||
  internal::write(os, w);
 | 
			
		||||
  return static_cast<int>(w.size());
 | 
			
		||||
}
 | 
			
		||||
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
 | 
			
		||||
}  // namespace fmt
 | 
			
		||||
 | 
			
		||||
#ifdef FMT_HEADER_ONLY
 | 
			
		||||
# include "printf.cc"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_PRINTF_H_
 | 
			
		||||
							
								
								
									
										143
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/time.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								vendor/spdlog/include/spdlog/fmt/bundled/time.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,143 @@
 | 
			
		||||
/*
 | 
			
		||||
 Formatting library for C++ - time formatting
 | 
			
		||||
 | 
			
		||||
 Copyright (c) 2012 - 2016, Victor Zverovich
 | 
			
		||||
 All rights reserved.
 | 
			
		||||
 | 
			
		||||
 For the license information refer to format.h.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_TIME_H_
 | 
			
		||||
#define FMT_TIME_H_
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
#include <ctime>
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
# pragma warning(push)
 | 
			
		||||
# pragma warning(disable: 4702)  // unreachable code
 | 
			
		||||
# pragma warning(disable: 4996)  // "deprecated" functions
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace fmt {
 | 
			
		||||
template <typename ArgFormatter>
 | 
			
		||||
void format_arg(BasicFormatter<char, ArgFormatter> &f,
 | 
			
		||||
                const char *&format_str, const std::tm &tm) {
 | 
			
		||||
  if (*format_str == ':')
 | 
			
		||||
    ++format_str;
 | 
			
		||||
  const char *end = format_str;
 | 
			
		||||
  while (*end && *end != '}')
 | 
			
		||||
    ++end;
 | 
			
		||||
  if (*end != '}')
 | 
			
		||||
    FMT_THROW(FormatError("missing '}' in format string"));
 | 
			
		||||
  internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> format;
 | 
			
		||||
  format.append(format_str, end + 1);
 | 
			
		||||
  format[format.size() - 1] = '\0';
 | 
			
		||||
  Buffer<char> &buffer = f.writer().buffer();
 | 
			
		||||
  std::size_t start = buffer.size();
 | 
			
		||||
  for (;;) {
 | 
			
		||||
    std::size_t size = buffer.capacity() - start;
 | 
			
		||||
    std::size_t count = std::strftime(&buffer[start], size, &format[0], &tm);
 | 
			
		||||
    if (count != 0) {
 | 
			
		||||
      buffer.resize(start + count);
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    if (size >= format.size() * 256) {
 | 
			
		||||
      // If the buffer is 256 times larger than the format string, assume
 | 
			
		||||
      // that `strftime` gives an empty result. There doesn't seem to be a
 | 
			
		||||
      // better way to distinguish the two cases:
 | 
			
		||||
      // https://github.com/fmtlib/fmt/issues/367
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    const std::size_t MIN_GROWTH = 10;
 | 
			
		||||
    buffer.reserve(buffer.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
 | 
			
		||||
  }
 | 
			
		||||
  format_str = end + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace internal{
 | 
			
		||||
inline Null<> localtime_r(...) { return Null<>(); }
 | 
			
		||||
inline Null<> localtime_s(...) { return Null<>(); }
 | 
			
		||||
inline Null<> gmtime_r(...) { return Null<>(); }
 | 
			
		||||
inline Null<> gmtime_s(...) { return Null<>(); }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Thread-safe replacement for std::localtime
 | 
			
		||||
inline std::tm localtime(std::time_t time) {
 | 
			
		||||
  struct LocalTime {
 | 
			
		||||
    std::time_t time_;
 | 
			
		||||
    std::tm tm_;
 | 
			
		||||
 | 
			
		||||
    LocalTime(std::time_t t): time_(t) {}
 | 
			
		||||
 | 
			
		||||
    bool run() {
 | 
			
		||||
      using namespace fmt::internal;
 | 
			
		||||
      return handle(localtime_r(&time_, &tm_));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool handle(std::tm *tm) { return tm != FMT_NULL; }
 | 
			
		||||
 | 
			
		||||
    bool handle(internal::Null<>) {
 | 
			
		||||
      using namespace fmt::internal;
 | 
			
		||||
      return fallback(localtime_s(&tm_, &time_));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool fallback(int res) { return res == 0; }
 | 
			
		||||
 | 
			
		||||
    bool fallback(internal::Null<>) {
 | 
			
		||||
      using namespace fmt::internal;
 | 
			
		||||
      std::tm *tm = std::localtime(&time_);
 | 
			
		||||
      if (tm) tm_ = *tm;
 | 
			
		||||
      return tm != FMT_NULL;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  LocalTime lt(time);
 | 
			
		||||
  if (lt.run())
 | 
			
		||||
    return lt.tm_;
 | 
			
		||||
  // Too big time values may be unsupported.
 | 
			
		||||
  FMT_THROW(fmt::FormatError("time_t value out of range"));
 | 
			
		||||
  return std::tm();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Thread-safe replacement for std::gmtime
 | 
			
		||||
inline std::tm gmtime(std::time_t time) {
 | 
			
		||||
  struct GMTime {
 | 
			
		||||
    std::time_t time_;
 | 
			
		||||
    std::tm tm_;
 | 
			
		||||
 | 
			
		||||
    GMTime(std::time_t t): time_(t) {}
 | 
			
		||||
 | 
			
		||||
    bool run() {
 | 
			
		||||
      using namespace fmt::internal;
 | 
			
		||||
      return handle(gmtime_r(&time_, &tm_));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool handle(std::tm *tm) { return tm != FMT_NULL; }
 | 
			
		||||
 | 
			
		||||
    bool handle(internal::Null<>) {
 | 
			
		||||
      using namespace fmt::internal;
 | 
			
		||||
      return fallback(gmtime_s(&tm_, &time_));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool fallback(int res) { return res == 0; }
 | 
			
		||||
 | 
			
		||||
    bool fallback(internal::Null<>) {
 | 
			
		||||
      std::tm *tm = std::gmtime(&time_);
 | 
			
		||||
      if (tm != FMT_NULL) tm_ = *tm;
 | 
			
		||||
      return tm != FMT_NULL;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  GMTime gt(time);
 | 
			
		||||
  if (gt.run())
 | 
			
		||||
    return gt.tm_;
 | 
			
		||||
  // Too big time values may be unsupported.
 | 
			
		||||
  FMT_THROW(fmt::FormatError("time_t value out of range"));
 | 
			
		||||
  return std::tm();
 | 
			
		||||
}
 | 
			
		||||
} //namespace fmt
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
# pragma warning(pop)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_TIME_H_
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/spdlog/include/spdlog/fmt/fmt.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/spdlog/include/spdlog/fmt/fmt.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2016 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Include a bundled header-only copy of fmtlib or an external one.
 | 
			
		||||
// By default spdlog include its own copy.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#if !defined(SPDLOG_FMT_EXTERNAL)
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_HEADER_ONLY
 | 
			
		||||
#define FMT_HEADER_ONLY
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef FMT_USE_WINDOWS_H
 | 
			
		||||
#define FMT_USE_WINDOWS_H 0
 | 
			
		||||
#endif
 | 
			
		||||
#include "spdlog/fmt/bundled/format.h"
 | 
			
		||||
#if defined(SPDLOG_FMT_PRINTF)
 | 
			
		||||
#include "spdlog/fmt/bundled/printf.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#else //external fmtlib
 | 
			
		||||
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
#if defined(SPDLOG_FMT_PRINTF)
 | 
			
		||||
#include <fmt/printf.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/spdlog/include/spdlog/fmt/ostr.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/spdlog/include/spdlog/fmt/ostr.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2016 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// include external or bundled copy of fmtlib's ostream support
 | 
			
		||||
//
 | 
			
		||||
#if !defined(SPDLOG_FMT_EXTERNAL)
 | 
			
		||||
#include "spdlog/fmt/fmt.h"
 | 
			
		||||
#include "spdlog/fmt/bundled/ostream.h"
 | 
			
		||||
#else
 | 
			
		||||
#include <fmt/ostream.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										47
									
								
								vendor/spdlog/include/spdlog/formatter.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								vendor/spdlog/include/spdlog/formatter.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/log_msg.h"
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
class flag_formatter;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class formatter
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~formatter() {}
 | 
			
		||||
    virtual void format(details::log_msg& msg) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class pattern_formatter SPDLOG_FINAL : public formatter
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    explicit pattern_formatter(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local);
 | 
			
		||||
    pattern_formatter(const pattern_formatter&) = delete;
 | 
			
		||||
    pattern_formatter& operator=(const pattern_formatter&) = delete;
 | 
			
		||||
    void format(details::log_msg& msg) override;
 | 
			
		||||
private:
 | 
			
		||||
    const std::string _pattern;
 | 
			
		||||
    const pattern_time_type _pattern_time;
 | 
			
		||||
    std::vector<std::unique_ptr<details::flag_formatter>> _formatters;
 | 
			
		||||
    std::tm get_time(details::log_msg& msg);
 | 
			
		||||
    void handle_flag(char flag);
 | 
			
		||||
    void compile_pattern(const std::string& pattern);
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/pattern_formatter_impl.h"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										135
									
								
								vendor/spdlog/include/spdlog/logger.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								vendor/spdlog/include/spdlog/logger.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// Thread safe logger (except for set_pattern(..), set_formatter(..) and set_error_handler())
 | 
			
		||||
// Has name, log level, vector of std::shared sink pointers and formatter
 | 
			
		||||
// Upon each log write the logger:
 | 
			
		||||
// 1. Checks if its log level is enough to log the message
 | 
			
		||||
// 2. Format the message using the formatter function
 | 
			
		||||
// 3. Pass the formatted message to its sinks to performa the actual logging
 | 
			
		||||
 | 
			
		||||
#include "spdlog/sinks/base_sink.h"
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
class logger
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    logger(const std::string& logger_name, sink_ptr single_sink);
 | 
			
		||||
    logger(const std::string& name, sinks_init_list);
 | 
			
		||||
    template<class It>
 | 
			
		||||
    logger(const std::string& name, const It& begin, const It& end);
 | 
			
		||||
 | 
			
		||||
    virtual ~logger();
 | 
			
		||||
    logger(const logger&) = delete;
 | 
			
		||||
    logger& operator=(const logger&) = delete;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    template <typename... Args> void log(level::level_enum lvl, const char* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void log(level::level_enum lvl, const char* msg);
 | 
			
		||||
    template <typename Arg1, typename... Args> void trace(const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
    template <typename Arg1, typename... Args> void debug(const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
    template <typename Arg1, typename... Args> void info(const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
    template <typename Arg1, typename... Args> void warn(const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
    template <typename Arg1, typename... Args> void error(const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
    template <typename Arg1, typename... Args> void critical(const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
 | 
			
		||||
    template <typename... Args> void log_if(const bool flag, level::level_enum lvl, const char* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void log_if(const bool flag, level::level_enum lvl, const char* msg);
 | 
			
		||||
    template <typename Arg1, typename... Args> void trace_if(const bool flag, const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
    template <typename Arg1, typename... Args> void debug_if(const bool flag, const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
    template <typename Arg1, typename... Args> void info_if(const bool flag, const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
    template <typename Arg1, typename... Args> void warn_if(const bool flag, const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
    template <typename Arg1, typename... Args> void error_if(const bool flag, const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
    template <typename Arg1, typename... Args> void critical_if(const bool flag, const char* fmt, const Arg1&, const Args&... args);
 | 
			
		||||
 | 
			
		||||
#ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT
 | 
			
		||||
    template <typename... Args> void log(level::level_enum lvl, const wchar_t* msg);
 | 
			
		||||
    template <typename... Args> void log(level::level_enum lvl, const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void trace(const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void debug(const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void info(const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void warn(const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void error(const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void critical(const wchar_t* fmt, const Args&... args);
 | 
			
		||||
 | 
			
		||||
    template <typename... Args> void log_if(const bool flag, level::level_enum lvl, const wchar_t* msg);
 | 
			
		||||
    template <typename... Args> void log_if(const bool flag, level::level_enum lvl, const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void trace_if(const bool flag, const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void debug_if(const bool flag, const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void info_if(const bool flag, const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void warn_if(const bool flag, const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void error_if(const bool flag, const wchar_t* fmt, const Args&... args);
 | 
			
		||||
    template <typename... Args> void critical_if(const bool flag, const wchar_t* fmt, const Args&... args);
 | 
			
		||||
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
 | 
			
		||||
 | 
			
		||||
    template <typename T> void log(level::level_enum lvl, const T&);
 | 
			
		||||
    template <typename T> void trace(const T&);
 | 
			
		||||
    template <typename T> void debug(const T&);
 | 
			
		||||
    template <typename T> void info(const T&);
 | 
			
		||||
    template <typename T> void warn(const T&);
 | 
			
		||||
    template <typename T> void error(const T&);
 | 
			
		||||
    template <typename T> void critical(const T&);
 | 
			
		||||
 | 
			
		||||
    template <typename T> void log_if(const bool flag, level::level_enum lvl, const T&);
 | 
			
		||||
    template <typename T> void trace_if(const bool flag, const T&);
 | 
			
		||||
    template <typename T> void debug_if(const bool flag, const T&);
 | 
			
		||||
    template <typename T> void info_if(const bool flag, const T&);
 | 
			
		||||
    template <typename T> void warn_if(const bool flag, const T&);
 | 
			
		||||
    template <typename T> void error_if(const bool flag, const T&);
 | 
			
		||||
    template <typename T> void critical_if(const bool flag, const T&);
 | 
			
		||||
 | 
			
		||||
    bool should_log(level::level_enum) const;
 | 
			
		||||
    void set_level(level::level_enum);
 | 
			
		||||
    level::level_enum level() const;
 | 
			
		||||
    const std::string& name() const;
 | 
			
		||||
    void set_pattern(const std::string&, pattern_time_type = pattern_time_type::local);
 | 
			
		||||
    void set_formatter(formatter_ptr);
 | 
			
		||||
 | 
			
		||||
    // automatically call flush() if message level >= log_level
 | 
			
		||||
    void flush_on(level::level_enum log_level);
 | 
			
		||||
 | 
			
		||||
    virtual void flush();
 | 
			
		||||
 | 
			
		||||
    const std::vector<sink_ptr>& sinks() const;
 | 
			
		||||
 | 
			
		||||
    // error handler
 | 
			
		||||
    virtual void set_error_handler(log_err_handler);
 | 
			
		||||
    virtual log_err_handler error_handler();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual void _sink_it(details::log_msg&);
 | 
			
		||||
    virtual void _set_pattern(const std::string&, pattern_time_type);
 | 
			
		||||
    virtual void _set_formatter(formatter_ptr);
 | 
			
		||||
 | 
			
		||||
    // default error handler: print the error to stderr with the max rate of 1 message/minute
 | 
			
		||||
    virtual void _default_err_handler(const std::string &msg);
 | 
			
		||||
 | 
			
		||||
    // return true if the given message level should trigger a flush
 | 
			
		||||
    bool _should_flush_on(const details::log_msg&);
 | 
			
		||||
 | 
			
		||||
    // increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER))
 | 
			
		||||
    void _incr_msg_counter(details::log_msg &msg);
 | 
			
		||||
 | 
			
		||||
    const std::string _name;
 | 
			
		||||
    std::vector<sink_ptr> _sinks;
 | 
			
		||||
    formatter_ptr _formatter;
 | 
			
		||||
    spdlog::level_t _level;
 | 
			
		||||
    spdlog::level_t _flush_level;
 | 
			
		||||
    log_err_handler _err_handler;
 | 
			
		||||
    std::atomic<time_t> _last_err_time;
 | 
			
		||||
    std::atomic<size_t> _msg_counter;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/logger_impl.h"
 | 
			
		||||
							
								
								
									
										90
									
								
								vendor/spdlog/include/spdlog/sinks/android_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								vendor/spdlog/include/spdlog/sinks/android_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(__ANDROID__)
 | 
			
		||||
 | 
			
		||||
#include "spdlog/sinks/sink.h"
 | 
			
		||||
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <android/log.h>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
 | 
			
		||||
#if !defined(SPDLOG_ANDROID_RETRIES)
 | 
			
		||||
#define SPDLOG_ANDROID_RETRIES 2
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
* Android sink (logging using __android_log_write)
 | 
			
		||||
* __android_log_write is thread-safe. No lock is needed.
 | 
			
		||||
*/
 | 
			
		||||
class android_sink : public sink
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    explicit android_sink(const std::string& tag = "spdlog", bool use_raw_msg = false): _tag(tag), _use_raw_msg(use_raw_msg) {}
 | 
			
		||||
 | 
			
		||||
    void log(const details::log_msg& msg) override
 | 
			
		||||
    {
 | 
			
		||||
        const android_LogPriority priority = convert_to_android(msg.level);
 | 
			
		||||
        const char *msg_output = (_use_raw_msg ? msg.raw.c_str() : msg.formatted.c_str());
 | 
			
		||||
 | 
			
		||||
        // See system/core/liblog/logger_write.c for explanation of return value
 | 
			
		||||
        int ret = __android_log_write(priority, _tag.c_str(), msg_output);
 | 
			
		||||
        int retry_count = 0;
 | 
			
		||||
        while ((ret == -11/*EAGAIN*/) && (retry_count < SPDLOG_ANDROID_RETRIES))
 | 
			
		||||
        {
 | 
			
		||||
            std::this_thread::sleep_for(std::chrono::milliseconds(5));
 | 
			
		||||
            ret = __android_log_write(priority, _tag.c_str(), msg_output);
 | 
			
		||||
            retry_count++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (ret < 0)
 | 
			
		||||
        {
 | 
			
		||||
            throw spdlog_ex("__android_log_write() failed", ret);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void flush() override
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static android_LogPriority convert_to_android(spdlog::level::level_enum level)
 | 
			
		||||
    {
 | 
			
		||||
        switch(level)
 | 
			
		||||
        {
 | 
			
		||||
        case spdlog::level::trace:
 | 
			
		||||
            return ANDROID_LOG_VERBOSE;
 | 
			
		||||
        case spdlog::level::debug:
 | 
			
		||||
            return ANDROID_LOG_DEBUG;
 | 
			
		||||
        case spdlog::level::info:
 | 
			
		||||
            return ANDROID_LOG_INFO;
 | 
			
		||||
        case spdlog::level::warn:
 | 
			
		||||
            return ANDROID_LOG_WARN;
 | 
			
		||||
        case spdlog::level::err:
 | 
			
		||||
            return ANDROID_LOG_ERROR;
 | 
			
		||||
        case spdlog::level::critical:
 | 
			
		||||
            return ANDROID_LOG_FATAL;
 | 
			
		||||
        default:
 | 
			
		||||
            return ANDROID_LOG_DEFAULT;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string _tag;
 | 
			
		||||
    bool _use_raw_msg;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										133
									
								
								vendor/spdlog/include/spdlog/sinks/ansicolor_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								vendor/spdlog/include/spdlog/sinks/ansicolor_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,133 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2017 spdlog authors.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/sinks/base_sink.h"
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
#include "spdlog/details/os.h"
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This sink prefixes the output with an ANSI escape sequence color code depending on the severity
 | 
			
		||||
 * of the message.
 | 
			
		||||
 * If no color terminal detected, omit the escape codes.
 | 
			
		||||
 */
 | 
			
		||||
template <class Mutex>
 | 
			
		||||
class ansicolor_sink: public base_sink<Mutex>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    ansicolor_sink(FILE* file): target_file_(file)
 | 
			
		||||
    {
 | 
			
		||||
        should_do_colors_ = details::os::in_terminal(file) && details::os::is_color_terminal();
 | 
			
		||||
        colors_[level::trace] = cyan;
 | 
			
		||||
        colors_[level::debug] = cyan;
 | 
			
		||||
        colors_[level::info] = reset;
 | 
			
		||||
        colors_[level::warn] = yellow + bold;
 | 
			
		||||
        colors_[level::err] = red + bold;
 | 
			
		||||
        colors_[level::critical] = bold + on_red;
 | 
			
		||||
        colors_[level::off] = reset;
 | 
			
		||||
    }
 | 
			
		||||
    virtual ~ansicolor_sink()
 | 
			
		||||
    {
 | 
			
		||||
        _flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set_color(level::level_enum color_level, const std::string& color)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
 | 
			
		||||
        colors_[color_level] = color;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Formatting codes
 | 
			
		||||
    const std::string reset = "\033[00m";
 | 
			
		||||
    const std::string bold = "\033[1m";
 | 
			
		||||
    const std::string dark = "\033[2m";
 | 
			
		||||
    const std::string underline = "\033[4m";
 | 
			
		||||
    const std::string blink = "\033[5m";
 | 
			
		||||
    const std::string reverse = "\033[7m";
 | 
			
		||||
    const std::string concealed = "\033[8m";
 | 
			
		||||
 | 
			
		||||
    // Foreground colors
 | 
			
		||||
    const std::string grey = "\033[30m";
 | 
			
		||||
    const std::string red = "\033[31m";
 | 
			
		||||
    const std::string green = "\033[32m";
 | 
			
		||||
    const std::string yellow = "\033[33m";
 | 
			
		||||
    const std::string blue = "\033[34m";
 | 
			
		||||
    const std::string magenta = "\033[35m";
 | 
			
		||||
    const std::string cyan = "\033[36m";
 | 
			
		||||
    const std::string white = "\033[37m";
 | 
			
		||||
 | 
			
		||||
    /// Background colors
 | 
			
		||||
    const std::string on_grey = "\033[40m";
 | 
			
		||||
    const std::string on_red = "\033[41m";
 | 
			
		||||
    const std::string on_green = "\033[42m";
 | 
			
		||||
    const std::string on_yellow = "\033[43m";
 | 
			
		||||
    const std::string on_blue = "\033[44m";
 | 
			
		||||
    const std::string on_magenta = "\033[45m";
 | 
			
		||||
    const std::string on_cyan = "\033[46m";
 | 
			
		||||
    const std::string on_white = "\033[47m";
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual void _sink_it(const details::log_msg& msg) override
 | 
			
		||||
    {
 | 
			
		||||
        // Wrap the originally formatted message in color codes.
 | 
			
		||||
        // If color is not supported in the terminal, log as is instead.
 | 
			
		||||
        if (should_do_colors_)
 | 
			
		||||
        {
 | 
			
		||||
            const std::string& prefix = colors_[msg.level];
 | 
			
		||||
            fwrite(prefix.data(), sizeof(char), prefix.size(), target_file_);
 | 
			
		||||
            fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), target_file_);
 | 
			
		||||
            fwrite(reset.data(), sizeof(char), reset.size(), target_file_);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), target_file_);
 | 
			
		||||
        }
 | 
			
		||||
        _flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void _flush() override
 | 
			
		||||
    {
 | 
			
		||||
        fflush(target_file_);
 | 
			
		||||
    }
 | 
			
		||||
    FILE* target_file_;
 | 
			
		||||
    bool should_do_colors_;
 | 
			
		||||
    std::map<level::level_enum, std::string> colors_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template<class Mutex>
 | 
			
		||||
class ansicolor_stdout_sink: public ansicolor_sink<Mutex>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    ansicolor_stdout_sink(): ansicolor_sink<Mutex>(stdout)
 | 
			
		||||
    {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class Mutex>
 | 
			
		||||
class ansicolor_stderr_sink: public ansicolor_sink<Mutex>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    ansicolor_stderr_sink(): ansicolor_sink<Mutex>(stderr)
 | 
			
		||||
    {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef ansicolor_stdout_sink<std::mutex> ansicolor_stdout_sink_mt;
 | 
			
		||||
typedef ansicolor_stdout_sink<details::null_mutex> ansicolor_stdout_sink_st;
 | 
			
		||||
 | 
			
		||||
typedef ansicolor_stderr_sink<std::mutex> ansicolor_stderr_sink_mt;
 | 
			
		||||
typedef ansicolor_stderr_sink<details::null_mutex> ansicolor_stderr_sink_st;
 | 
			
		||||
 | 
			
		||||
} // namespace sinks
 | 
			
		||||
} // namespace spdlog
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										50
									
								
								vendor/spdlog/include/spdlog/sinks/base_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								vendor/spdlog/include/spdlog/sinks/base_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
//
 | 
			
		||||
// base sink templated over a mutex (either dummy or real)
 | 
			
		||||
// concrete implementation should only override the _sink_it method.
 | 
			
		||||
// all locking is taken care of here so no locking needed by the implementers..
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include "spdlog/sinks/sink.h"
 | 
			
		||||
#include "spdlog/formatter.h"
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
#include "spdlog/details/log_msg.h"
 | 
			
		||||
 | 
			
		||||
#include <mutex>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
template<class Mutex>
 | 
			
		||||
class base_sink:public sink
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    base_sink():_mutex() {}
 | 
			
		||||
    virtual ~base_sink() = default;
 | 
			
		||||
 | 
			
		||||
    base_sink(const base_sink&) = delete;
 | 
			
		||||
    base_sink& operator=(const base_sink&) = delete;
 | 
			
		||||
 | 
			
		||||
    void log(const details::log_msg& msg) SPDLOG_FINAL override
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(_mutex);
 | 
			
		||||
        _sink_it(msg);
 | 
			
		||||
    }
 | 
			
		||||
    void flush() SPDLOG_FINAL override
 | 
			
		||||
    {
 | 
			
		||||
        _flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual void _sink_it(const details::log_msg& msg) = 0;
 | 
			
		||||
    virtual void _flush() = 0;
 | 
			
		||||
    Mutex _mutex;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										73
									
								
								vendor/spdlog/include/spdlog/sinks/dist_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								vendor/spdlog/include/spdlog/sinks/dist_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2015 David Schury, Gabi Melman
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/log_msg.h"
 | 
			
		||||
#include "spdlog/details/null_mutex.h"
 | 
			
		||||
#include "spdlog/sinks/base_sink.h"
 | 
			
		||||
#include "spdlog/sinks/sink.h"
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
// Distribution sink (mux). Stores a vector of sinks which get called when log is called
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
template<class Mutex>
 | 
			
		||||
class dist_sink: public base_sink<Mutex>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    explicit dist_sink() :_sinks() {}
 | 
			
		||||
    dist_sink(const dist_sink&) = delete;
 | 
			
		||||
    dist_sink& operator=(const dist_sink&) = delete;
 | 
			
		||||
    virtual ~dist_sink() = default;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    std::vector<std::shared_ptr<sink>> _sinks;
 | 
			
		||||
 | 
			
		||||
    void _sink_it(const details::log_msg& msg) override
 | 
			
		||||
    {
 | 
			
		||||
        for (auto &sink : _sinks)
 | 
			
		||||
        {
 | 
			
		||||
            if( sink->should_log( msg.level))
 | 
			
		||||
            {
 | 
			
		||||
                sink->log(msg);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void _flush() override
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
 | 
			
		||||
        for (auto &sink : _sinks)
 | 
			
		||||
            sink->flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    void add_sink(std::shared_ptr<sink> sink)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
 | 
			
		||||
        _sinks.push_back(sink);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void remove_sink(std::shared_ptr<sink> sink)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
 | 
			
		||||
        _sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink), _sinks.end());
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef dist_sink<std::mutex> dist_sink_mt;
 | 
			
		||||
typedef dist_sink<details::null_mutex> dist_sink_st;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										242
									
								
								vendor/spdlog/include/spdlog/sinks/file_sinks.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								vendor/spdlog/include/spdlog/sinks/file_sinks.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,242 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/sinks/base_sink.h"
 | 
			
		||||
#include "spdlog/details/null_mutex.h"
 | 
			
		||||
#include "spdlog/details/file_helper.h"
 | 
			
		||||
#include "spdlog/fmt/fmt.h"
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <ctime>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <cerrno>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
/*
 | 
			
		||||
 * Trivial file sink with single file as target
 | 
			
		||||
 */
 | 
			
		||||
template<class Mutex>
 | 
			
		||||
class simple_file_sink SPDLOG_FINAL : public base_sink < Mutex >
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    explicit simple_file_sink(const filename_t &filename, bool truncate = false):_force_flush(false)
 | 
			
		||||
    {
 | 
			
		||||
        _file_helper.open(filename, truncate);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set_force_flush(bool force_flush)
 | 
			
		||||
    {
 | 
			
		||||
        _force_flush = force_flush;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void _sink_it(const details::log_msg& msg) override
 | 
			
		||||
    {
 | 
			
		||||
        _file_helper.write(msg);
 | 
			
		||||
        if(_force_flush)
 | 
			
		||||
            _file_helper.flush();
 | 
			
		||||
    }
 | 
			
		||||
    void _flush() override
 | 
			
		||||
    {
 | 
			
		||||
        _file_helper.flush();
 | 
			
		||||
    }
 | 
			
		||||
private:
 | 
			
		||||
    details::file_helper _file_helper;
 | 
			
		||||
    bool _force_flush;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef simple_file_sink<std::mutex> simple_file_sink_mt;
 | 
			
		||||
typedef simple_file_sink<details::null_mutex> simple_file_sink_st;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Rotating file sink based on size
 | 
			
		||||
 */
 | 
			
		||||
template<class Mutex>
 | 
			
		||||
class rotating_file_sink SPDLOG_FINAL : public base_sink < Mutex >
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    rotating_file_sink(const filename_t &base_filename,
 | 
			
		||||
                       std::size_t max_size, std::size_t max_files) :
 | 
			
		||||
        _base_filename(base_filename),
 | 
			
		||||
        _max_size(max_size),
 | 
			
		||||
        _max_files(max_files),
 | 
			
		||||
        _current_size(0),
 | 
			
		||||
        _file_helper()
 | 
			
		||||
    {
 | 
			
		||||
        _file_helper.open(calc_filename(_base_filename, 0));
 | 
			
		||||
        _current_size = _file_helper.size(); //expensive. called only once
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void _sink_it(const details::log_msg& msg) override
 | 
			
		||||
    {
 | 
			
		||||
        _current_size += msg.formatted.size();
 | 
			
		||||
        if (_current_size > _max_size)
 | 
			
		||||
        {
 | 
			
		||||
            _rotate();
 | 
			
		||||
            _current_size = msg.formatted.size();
 | 
			
		||||
        }
 | 
			
		||||
        _file_helper.write(msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void _flush() override
 | 
			
		||||
    {
 | 
			
		||||
        _file_helper.flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static filename_t calc_filename(const filename_t& filename, std::size_t index)
 | 
			
		||||
    {
 | 
			
		||||
        std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
 | 
			
		||||
        if (index)
 | 
			
		||||
            w.write(SPDLOG_FILENAME_T("{}.{}"), filename, index);
 | 
			
		||||
        else
 | 
			
		||||
            w.write(SPDLOG_FILENAME_T("{}"), filename);
 | 
			
		||||
        return w.str();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Rotate files:
 | 
			
		||||
    // log.txt -> log.txt.1
 | 
			
		||||
    // log.txt.1 -> log.txt.2
 | 
			
		||||
    // log.txt.2 -> log.txt.3
 | 
			
		||||
    // lo3.txt.3 -> delete
 | 
			
		||||
 | 
			
		||||
    void _rotate()
 | 
			
		||||
    {
 | 
			
		||||
        using details::os::filename_to_str;
 | 
			
		||||
        _file_helper.close();
 | 
			
		||||
        for (auto i = _max_files; i > 0; --i)
 | 
			
		||||
        {
 | 
			
		||||
            filename_t src = calc_filename(_base_filename, i - 1);
 | 
			
		||||
            filename_t target = calc_filename(_base_filename, i);
 | 
			
		||||
 | 
			
		||||
            if (details::file_helper::file_exists(target))
 | 
			
		||||
            {
 | 
			
		||||
                if (details::os::remove(target) != 0)
 | 
			
		||||
                {
 | 
			
		||||
                    throw spdlog_ex("rotating_file_sink: failed removing " + filename_to_str(target), errno);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (details::file_helper::file_exists(src) && details::os::rename(src, target))
 | 
			
		||||
            {
 | 
			
		||||
                throw spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        _file_helper.reopen(true);
 | 
			
		||||
    }
 | 
			
		||||
    filename_t _base_filename;
 | 
			
		||||
    std::size_t _max_size;
 | 
			
		||||
    std::size_t _max_files;
 | 
			
		||||
    std::size_t _current_size;
 | 
			
		||||
    details::file_helper _file_helper;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
 | 
			
		||||
typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Default generator of daily log file names.
 | 
			
		||||
 */
 | 
			
		||||
struct default_daily_file_name_calculator
 | 
			
		||||
{
 | 
			
		||||
    // Create filename for the form basename.YYYY-MM-DD_hh-mm
 | 
			
		||||
    static filename_t calc_filename(const filename_t& basename)
 | 
			
		||||
    {
 | 
			
		||||
        std::tm tm = spdlog::details::os::localtime();
 | 
			
		||||
        std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
 | 
			
		||||
        w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min);
 | 
			
		||||
        return w.str();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Generator of daily log file names in format basename.YYYY-MM-DD
 | 
			
		||||
 */
 | 
			
		||||
struct dateonly_daily_file_name_calculator
 | 
			
		||||
{
 | 
			
		||||
    // Create filename for the form basename.YYYY-MM-DD
 | 
			
		||||
    static filename_t calc_filename(const filename_t& basename)
 | 
			
		||||
    {
 | 
			
		||||
        std::tm tm = spdlog::details::os::localtime();
 | 
			
		||||
        std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
 | 
			
		||||
        w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
 | 
			
		||||
        return w.str();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Rotating file sink based on date. rotates at midnight
 | 
			
		||||
 */
 | 
			
		||||
template<class Mutex, class FileNameCalc = default_daily_file_name_calculator>
 | 
			
		||||
class daily_file_sink SPDLOG_FINAL :public base_sink < Mutex >
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    //create daily file sink which rotates on given time
 | 
			
		||||
    daily_file_sink(
 | 
			
		||||
        const filename_t& base_filename,
 | 
			
		||||
        int rotation_hour,
 | 
			
		||||
        int rotation_minute) : _base_filename(base_filename),
 | 
			
		||||
        _rotation_h(rotation_hour),
 | 
			
		||||
        _rotation_m(rotation_minute)
 | 
			
		||||
    {
 | 
			
		||||
        if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
 | 
			
		||||
            throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
 | 
			
		||||
        _rotation_tp = _next_rotation_tp();
 | 
			
		||||
        _file_helper.open(FileNameCalc::calc_filename(_base_filename));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void _sink_it(const details::log_msg& msg) override
 | 
			
		||||
    {
 | 
			
		||||
        if (std::chrono::system_clock::now() >= _rotation_tp)
 | 
			
		||||
        {
 | 
			
		||||
            _file_helper.open(FileNameCalc::calc_filename(_base_filename));
 | 
			
		||||
            _rotation_tp = _next_rotation_tp();
 | 
			
		||||
        }
 | 
			
		||||
        _file_helper.write(msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void _flush() override
 | 
			
		||||
    {
 | 
			
		||||
        _file_helper.flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::chrono::system_clock::time_point _next_rotation_tp()
 | 
			
		||||
    {
 | 
			
		||||
        auto now = std::chrono::system_clock::now();
 | 
			
		||||
        time_t tnow = std::chrono::system_clock::to_time_t(now);
 | 
			
		||||
        tm date = spdlog::details::os::localtime(tnow);
 | 
			
		||||
        date.tm_hour = _rotation_h;
 | 
			
		||||
        date.tm_min = _rotation_m;
 | 
			
		||||
        date.tm_sec = 0;
 | 
			
		||||
        auto rotation_time = std::chrono::system_clock::from_time_t(std::mktime(&date));
 | 
			
		||||
        if (rotation_time > now)
 | 
			
		||||
            return rotation_time;
 | 
			
		||||
        else
 | 
			
		||||
            return std::chrono::system_clock::time_point(rotation_time + std::chrono::hours(24));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    filename_t _base_filename;
 | 
			
		||||
    int _rotation_h;
 | 
			
		||||
    int _rotation_m;
 | 
			
		||||
    std::chrono::system_clock::time_point _rotation_tp;
 | 
			
		||||
    details::file_helper _file_helper;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef daily_file_sink<std::mutex> daily_file_sink_mt;
 | 
			
		||||
typedef daily_file_sink<details::null_mutex> daily_file_sink_st;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								vendor/spdlog/include/spdlog/sinks/msvc_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								vendor/spdlog/include/spdlog/sinks/msvc_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2016 Alexander Dalshov.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER)
 | 
			
		||||
 | 
			
		||||
#include "spdlog/sinks/base_sink.h"
 | 
			
		||||
#include "spdlog/details/null_mutex.h"
 | 
			
		||||
 | 
			
		||||
#include <WinBase.h>
 | 
			
		||||
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
/*
 | 
			
		||||
* MSVC sink (logging using OutputDebugStringA)
 | 
			
		||||
*/
 | 
			
		||||
template<class Mutex>
 | 
			
		||||
class msvc_sink : public base_sink < Mutex >
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    explicit msvc_sink()
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void _sink_it(const details::log_msg& msg) override
 | 
			
		||||
    {
 | 
			
		||||
        OutputDebugStringA(msg.formatted.c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void _flush() override
 | 
			
		||||
    {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef msvc_sink<std::mutex> msvc_sink_mt;
 | 
			
		||||
typedef msvc_sink<details::null_mutex> msvc_sink_st;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/spdlog/include/spdlog/sinks/null_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								vendor/spdlog/include/spdlog/sinks/null_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/sinks/base_sink.h"
 | 
			
		||||
#include "spdlog/details/null_mutex.h"
 | 
			
		||||
 | 
			
		||||
#include <mutex>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
template <class Mutex>
 | 
			
		||||
class null_sink : public base_sink < Mutex >
 | 
			
		||||
{
 | 
			
		||||
protected:
 | 
			
		||||
    void _sink_it(const details::log_msg&) override
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    void _flush() override
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
typedef null_sink<details::null_mutex> null_sink_st;
 | 
			
		||||
typedef null_sink<details::null_mutex> null_sink_mt;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										47
									
								
								vendor/spdlog/include/spdlog/sinks/ostream_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								vendor/spdlog/include/spdlog/sinks/ostream_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/null_mutex.h"
 | 
			
		||||
#include "spdlog/sinks/base_sink.h"
 | 
			
		||||
 | 
			
		||||
#include <ostream>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
template<class Mutex>
 | 
			
		||||
class ostream_sink: public base_sink<Mutex>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    explicit ostream_sink(std::ostream& os, bool force_flush=false) :_ostream(os), _force_flush(force_flush) {}
 | 
			
		||||
    ostream_sink(const ostream_sink&) = delete;
 | 
			
		||||
    ostream_sink& operator=(const ostream_sink&) = delete;
 | 
			
		||||
    virtual ~ostream_sink() = default;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    void _sink_it(const details::log_msg& msg) override
 | 
			
		||||
    {
 | 
			
		||||
        _ostream.write(msg.formatted.data(), msg.formatted.size());
 | 
			
		||||
        if (_force_flush)
 | 
			
		||||
            _ostream.flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void _flush() override
 | 
			
		||||
    {
 | 
			
		||||
        _ostream.flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::ostream& _ostream;
 | 
			
		||||
    bool _force_flush;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef ostream_sink<std::mutex> ostream_sink_mt;
 | 
			
		||||
typedef ostream_sink<details::null_mutex> ostream_sink_st;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								vendor/spdlog/include/spdlog/sinks/sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								vendor/spdlog/include/spdlog/sinks/sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/log_msg.h"
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
class sink
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    sink()
 | 
			
		||||
    {
 | 
			
		||||
        _level = level::trace;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual ~sink() {}
 | 
			
		||||
    virtual void log(const details::log_msg& msg) = 0;
 | 
			
		||||
    virtual void flush() = 0;
 | 
			
		||||
 | 
			
		||||
    bool should_log(level::level_enum msg_level) const;
 | 
			
		||||
    void set_level(level::level_enum log_level);
 | 
			
		||||
    level::level_enum level() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    level_t _level;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline bool sink::should_log(level::level_enum msg_level) const
 | 
			
		||||
{
 | 
			
		||||
    return msg_level >= _level.load(std::memory_order_relaxed);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void sink::set_level(level::level_enum log_level)
 | 
			
		||||
{
 | 
			
		||||
    _level.store(log_level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline level::level_enum sink::level() const
 | 
			
		||||
{
 | 
			
		||||
    return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										77
									
								
								vendor/spdlog/include/spdlog/sinks/stdout_sinks.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								vendor/spdlog/include/spdlog/sinks/stdout_sinks.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/null_mutex.h"
 | 
			
		||||
#include "spdlog/sinks/base_sink.h"
 | 
			
		||||
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <mutex>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
template <class Mutex>
 | 
			
		||||
class stdout_sink SPDLOG_FINAL : public base_sink<Mutex>
 | 
			
		||||
{
 | 
			
		||||
    using MyType = stdout_sink<Mutex>;
 | 
			
		||||
public:
 | 
			
		||||
    stdout_sink()
 | 
			
		||||
    {}
 | 
			
		||||
    static std::shared_ptr<MyType> instance()
 | 
			
		||||
    {
 | 
			
		||||
        static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
 | 
			
		||||
        return instance;
 | 
			
		||||
    }
 | 
			
		||||
protected:
 | 
			
		||||
    void _sink_it(const details::log_msg& msg) override
 | 
			
		||||
    {
 | 
			
		||||
        fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stdout);
 | 
			
		||||
        _flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void _flush() override
 | 
			
		||||
    {
 | 
			
		||||
        fflush(stdout);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef stdout_sink<details::null_mutex> stdout_sink_st;
 | 
			
		||||
typedef stdout_sink<std::mutex> stdout_sink_mt;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <class Mutex>
 | 
			
		||||
class stderr_sink SPDLOG_FINAL : public base_sink<Mutex>
 | 
			
		||||
{
 | 
			
		||||
    using MyType = stderr_sink<Mutex>;
 | 
			
		||||
public:
 | 
			
		||||
    stderr_sink()
 | 
			
		||||
    {}
 | 
			
		||||
    static std::shared_ptr<MyType> instance()
 | 
			
		||||
    {
 | 
			
		||||
        static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
 | 
			
		||||
        return instance;
 | 
			
		||||
    }
 | 
			
		||||
protected:
 | 
			
		||||
    void _sink_it(const details::log_msg& msg) override
 | 
			
		||||
    {
 | 
			
		||||
        fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stderr);
 | 
			
		||||
        _flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void _flush() override
 | 
			
		||||
    {
 | 
			
		||||
        fflush(stderr);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef stderr_sink<std::mutex> stderr_sink_mt;
 | 
			
		||||
typedef stderr_sink<details::null_mutex> stderr_sink_st;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										81
									
								
								vendor/spdlog/include/spdlog/sinks/syslog_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								vendor/spdlog/include/spdlog/sinks/syslog_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
 | 
			
		||||
#ifdef SPDLOG_ENABLE_SYSLOG
 | 
			
		||||
 | 
			
		||||
#include "spdlog/sinks/sink.h"
 | 
			
		||||
#include "spdlog/details/log_msg.h"
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
/**
 | 
			
		||||
 * Sink that write to syslog using the `syscall()` library call.
 | 
			
		||||
 *
 | 
			
		||||
 * Locking is not needed, as `syslog()` itself is thread-safe.
 | 
			
		||||
 */
 | 
			
		||||
class syslog_sink : public sink
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    //
 | 
			
		||||
    syslog_sink(const std::string& ident = "", int syslog_option=0, int syslog_facility=LOG_USER):
 | 
			
		||||
        _ident(ident)
 | 
			
		||||
    {
 | 
			
		||||
        _priorities[static_cast<int>(level::trace)] = LOG_DEBUG;
 | 
			
		||||
        _priorities[static_cast<int>(level::debug)] = LOG_DEBUG;
 | 
			
		||||
        _priorities[static_cast<int>(level::info)] = LOG_INFO;
 | 
			
		||||
        _priorities[static_cast<int>(level::warn)] = LOG_WARNING;
 | 
			
		||||
        _priorities[static_cast<int>(level::err)] = LOG_ERR;
 | 
			
		||||
        _priorities[static_cast<int>(level::critical)] = LOG_CRIT;
 | 
			
		||||
        _priorities[static_cast<int>(level::off)] = LOG_INFO;
 | 
			
		||||
 | 
			
		||||
        //set ident to be program name if empty
 | 
			
		||||
        ::openlog(_ident.empty()? nullptr:_ident.c_str(), syslog_option, syslog_facility);
 | 
			
		||||
    }
 | 
			
		||||
    ~syslog_sink()
 | 
			
		||||
    {
 | 
			
		||||
        ::closelog();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    syslog_sink(const syslog_sink&) = delete;
 | 
			
		||||
    syslog_sink& operator=(const syslog_sink&) = delete;
 | 
			
		||||
 | 
			
		||||
    void log(const details::log_msg &msg) override
 | 
			
		||||
    {
 | 
			
		||||
        ::syslog(syslog_prio_from_level(msg), "%s", msg.raw.str().c_str());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void flush() override
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::array<int, 7> _priorities;
 | 
			
		||||
    //must store the ident because the man says openlog might use the pointer as is and not a string copy
 | 
			
		||||
    const std::string _ident;
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
    // Simply maps spdlog's log level to syslog priority level.
 | 
			
		||||
    //
 | 
			
		||||
    int syslog_prio_from_level(const details::log_msg &msg) const
 | 
			
		||||
    {
 | 
			
		||||
        return _priorities[static_cast<int>(msg.level)];
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										121
									
								
								vendor/spdlog/include/spdlog/sinks/wincolor_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								vendor/spdlog/include/spdlog/sinks/wincolor_sink.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,121 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2016 spdlog
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "spdlog/sinks/base_sink.h"
 | 
			
		||||
#include "spdlog/details/null_mutex.h"
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
 | 
			
		||||
#include <mutex>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <wincon.h>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
namespace sinks
 | 
			
		||||
{
 | 
			
		||||
/*
 | 
			
		||||
 * Windows color console sink. Uses WriteConsoleA to write to the console with colors
 | 
			
		||||
 */
 | 
			
		||||
template<class Mutex>
 | 
			
		||||
class wincolor_sink: public  base_sink<Mutex>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    const WORD BOLD = FOREGROUND_INTENSITY;
 | 
			
		||||
    const WORD RED = FOREGROUND_RED;
 | 
			
		||||
    const WORD CYAN = FOREGROUND_GREEN | FOREGROUND_BLUE;
 | 
			
		||||
    const WORD WHITE = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
 | 
			
		||||
    const WORD YELLOW = FOREGROUND_RED | FOREGROUND_GREEN;
 | 
			
		||||
 | 
			
		||||
    wincolor_sink(HANDLE std_handle): out_handle_(std_handle)
 | 
			
		||||
    {
 | 
			
		||||
        colors_[level::trace] = CYAN;
 | 
			
		||||
        colors_[level::debug] = CYAN;
 | 
			
		||||
        colors_[level::info] = WHITE | BOLD;
 | 
			
		||||
        colors_[level::warn] = YELLOW | BOLD;
 | 
			
		||||
        colors_[level::err] = RED | BOLD; // red bold
 | 
			
		||||
        colors_[level::critical] = BACKGROUND_RED | WHITE | BOLD; // white bold on red background
 | 
			
		||||
        colors_[level::off] = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual ~wincolor_sink()
 | 
			
		||||
    {
 | 
			
		||||
        this->flush();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    wincolor_sink(const wincolor_sink& other) = delete;
 | 
			
		||||
    wincolor_sink& operator=(const wincolor_sink& other) = delete;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    virtual void _sink_it(const details::log_msg& msg) override
 | 
			
		||||
    {
 | 
			
		||||
        auto color = colors_[msg.level];
 | 
			
		||||
        auto orig_attribs = set_console_attribs(color);
 | 
			
		||||
        WriteConsoleA(out_handle_, msg.formatted.data(), static_cast<DWORD>(msg.formatted.size()), nullptr, nullptr);
 | 
			
		||||
        SetConsoleTextAttribute(out_handle_, orig_attribs); //reset to orig colors
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void _flush() override
 | 
			
		||||
    {
 | 
			
		||||
        // windows console always flushed?
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // change the  color for the given level
 | 
			
		||||
    void set_color(level::level_enum level, WORD color)
 | 
			
		||||
    {
 | 
			
		||||
        std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
 | 
			
		||||
        colors_[level] = color;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    HANDLE out_handle_;
 | 
			
		||||
    std::map<level::level_enum, WORD> colors_;
 | 
			
		||||
 | 
			
		||||
    // set color and return the orig console attributes (for resetting later)
 | 
			
		||||
    WORD set_console_attribs(WORD attribs)
 | 
			
		||||
    {
 | 
			
		||||
        CONSOLE_SCREEN_BUFFER_INFO orig_buffer_info;
 | 
			
		||||
        GetConsoleScreenBufferInfo(out_handle_, &orig_buffer_info);
 | 
			
		||||
        WORD back_color = orig_buffer_info.wAttributes;
 | 
			
		||||
        // retrieve the current background color
 | 
			
		||||
        back_color &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
 | 
			
		||||
        // keep the background color unchanged
 | 
			
		||||
        SetConsoleTextAttribute(out_handle_, attribs | back_color);
 | 
			
		||||
        return  orig_buffer_info.wAttributes; //return orig attribs
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// windows color console to stdout
 | 
			
		||||
//
 | 
			
		||||
template<class Mutex>
 | 
			
		||||
class wincolor_stdout_sink: public wincolor_sink<Mutex>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    wincolor_stdout_sink() : wincolor_sink<Mutex>(GetStdHandle(STD_OUTPUT_HANDLE))
 | 
			
		||||
    {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef wincolor_stdout_sink<std::mutex> wincolor_stdout_sink_mt;
 | 
			
		||||
typedef wincolor_stdout_sink<details::null_mutex> wincolor_stdout_sink_st;
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// windows color console to stderr
 | 
			
		||||
//
 | 
			
		||||
template<class Mutex>
 | 
			
		||||
class wincolor_stderr_sink: public wincolor_sink<Mutex>
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    wincolor_stderr_sink() : wincolor_sink<Mutex>(GetStdHandle(STD_ERROR_HANDLE))
 | 
			
		||||
    {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef wincolor_stderr_sink<std::mutex> wincolor_stderr_sink_mt;
 | 
			
		||||
typedef wincolor_stderr_sink<details::null_mutex> wincolor_stderr_sink_st;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										194
									
								
								vendor/spdlog/include/spdlog/spdlog.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								vendor/spdlog/include/spdlog/spdlog.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,194 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
// spdlog main header file.
 | 
			
		||||
// see example.cpp for usage example
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#define SPDLOG_VERSION "0.14.0"
 | 
			
		||||
 | 
			
		||||
#include "spdlog/tweakme.h"
 | 
			
		||||
#include "spdlog/common.h"
 | 
			
		||||
#include "spdlog/logger.h"
 | 
			
		||||
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace spdlog
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Return an existing logger or nullptr if a logger with such name doesn't exist.
 | 
			
		||||
// example: spdlog::get("my_logger")->info("hello {}", "world");
 | 
			
		||||
//
 | 
			
		||||
std::shared_ptr<logger> get(const std::string& name);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Set global formatting
 | 
			
		||||
// example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v");
 | 
			
		||||
//
 | 
			
		||||
void set_pattern(const std::string& format_string);
 | 
			
		||||
void set_formatter(formatter_ptr f);
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Set global logging level for
 | 
			
		||||
//
 | 
			
		||||
void set_level(level::level_enum log_level);
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Set global error handler
 | 
			
		||||
//
 | 
			
		||||
void set_error_handler(log_err_handler);
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Turn on async mode (off by default) and set the queue size for each async_logger.
 | 
			
		||||
// effective only for loggers created after this call.
 | 
			
		||||
// queue_size: size of queue (must be power of 2):
 | 
			
		||||
//    Each logger will pre-allocate a dedicated queue with queue_size entries upon construction.
 | 
			
		||||
//
 | 
			
		||||
// async_overflow_policy (optional, block_retry by default):
 | 
			
		||||
//    async_overflow_policy::block_retry - if queue is full, block until queue has room for the new log entry.
 | 
			
		||||
//    async_overflow_policy::discard_log_msg - never block and discard any new messages when queue  overflows.
 | 
			
		||||
//
 | 
			
		||||
// worker_warmup_cb (optional):
 | 
			
		||||
//     callback function that will be called in worker thread upon start (can be used to init stuff like thread affinity)
 | 
			
		||||
//
 | 
			
		||||
// worker_teardown_cb (optional):
 | 
			
		||||
//     callback function that will be called in worker thread upon exit
 | 
			
		||||
//
 | 
			
		||||
void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function<void()>& worker_teardown_cb = nullptr);
 | 
			
		||||
 | 
			
		||||
// Turn off async mode
 | 
			
		||||
void set_sync_mode();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Create and register multi/single threaded basic file logger.
 | 
			
		||||
// Basic logger simply writes to given file without any limitations or rotations.
 | 
			
		||||
//
 | 
			
		||||
std::shared_ptr<logger> basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate = false);
 | 
			
		||||
std::shared_ptr<logger> basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate = false);
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Create and register multi/single threaded rotating file logger
 | 
			
		||||
//
 | 
			
		||||
std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files);
 | 
			
		||||
std::shared_ptr<logger> rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files);
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Create file logger which creates new file on the given time (default in  midnight):
 | 
			
		||||
//
 | 
			
		||||
std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0);
 | 
			
		||||
std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0);
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Create and register stdout/stderr loggers
 | 
			
		||||
//
 | 
			
		||||
std::shared_ptr<logger> stdout_logger_mt(const std::string& logger_name);
 | 
			
		||||
std::shared_ptr<logger> stdout_logger_st(const std::string& logger_name);
 | 
			
		||||
std::shared_ptr<logger> stderr_logger_mt(const std::string& logger_name);
 | 
			
		||||
std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name);
 | 
			
		||||
//
 | 
			
		||||
// Create and register colored stdout/stderr loggers
 | 
			
		||||
//
 | 
			
		||||
std::shared_ptr<logger> stdout_color_mt(const std::string& logger_name);
 | 
			
		||||
std::shared_ptr<logger> stdout_color_st(const std::string& logger_name);
 | 
			
		||||
std::shared_ptr<logger> stderr_color_mt(const std::string& logger_name);
 | 
			
		||||
std::shared_ptr<logger> stderr_color_st(const std::string& logger_name);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Create and register a syslog logger
 | 
			
		||||
//
 | 
			
		||||
#ifdef SPDLOG_ENABLE_SYSLOG
 | 
			
		||||
std::shared_ptr<logger> syslog_logger(const std::string& logger_name, const std::string& ident = "", int syslog_option = 0);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__ANDROID__)
 | 
			
		||||
std::shared_ptr<logger> android_logger(const std::string& logger_name, const std::string& tag = "spdlog");
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Create and register a logger with a single sink
 | 
			
		||||
std::shared_ptr<logger> create(const std::string& logger_name, const sink_ptr& sink);
 | 
			
		||||
 | 
			
		||||
// Create and register a logger with multiple sinks
 | 
			
		||||
std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks);
 | 
			
		||||
template<class It>
 | 
			
		||||
std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Create and register a logger with templated sink type
 | 
			
		||||
// Example:
 | 
			
		||||
// spdlog::create<daily_file_sink_st>("mylog", "dailylog_filename");
 | 
			
		||||
template <typename Sink, typename... Args>
 | 
			
		||||
std::shared_ptr<spdlog::logger> create(const std::string& logger_name, Args...);
 | 
			
		||||
 | 
			
		||||
// Create and register an async logger with a single sink
 | 
			
		||||
std::shared_ptr<logger> create_async(const std::string& logger_name, const sink_ptr& sink, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function<void()>& worker_teardown_cb = nullptr);
 | 
			
		||||
 | 
			
		||||
// Create and register an async logger with multiple sinks
 | 
			
		||||
std::shared_ptr<logger> create_async(const std::string& logger_name, sinks_init_list sinks, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function<void()>& worker_teardown_cb = nullptr);
 | 
			
		||||
template<class It>
 | 
			
		||||
std::shared_ptr<logger> create_async(const std::string& logger_name, const It& sinks_begin, const It& sinks_end, size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function<void()>& worker_teardown_cb = nullptr);
 | 
			
		||||
 | 
			
		||||
// Register the given logger with the given name
 | 
			
		||||
void register_logger(std::shared_ptr<logger> logger);
 | 
			
		||||
 | 
			
		||||
// Apply a user defined function on all registered loggers
 | 
			
		||||
// Example:
 | 
			
		||||
// spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) {l->flush();});
 | 
			
		||||
void apply_all(std::function<void(std::shared_ptr<logger>)> fun);
 | 
			
		||||
 | 
			
		||||
// Drop the reference to the given logger
 | 
			
		||||
void drop(const std::string &name);
 | 
			
		||||
 | 
			
		||||
// Drop all references from the registry
 | 
			
		||||
void drop_all();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// Trace & Debug can be switched on/off at compile time for zero cost debug statements.
 | 
			
		||||
// Uncomment SPDLOG_DEBUG_ON/SPDLOG_TRACE_ON in tweakme.h to enable.
 | 
			
		||||
// SPDLOG_TRACE(..) will also print current file and line.
 | 
			
		||||
//
 | 
			
		||||
// Example:
 | 
			
		||||
// spdlog::set_level(spdlog::level::trace);
 | 
			
		||||
// SPDLOG_TRACE(my_logger, "some trace message");
 | 
			
		||||
// SPDLOG_TRACE(my_logger, "another trace message {} {}", 1, 2);
 | 
			
		||||
// SPDLOG_DEBUG(my_logger, "some debug message {} {}", 3, 4);
 | 
			
		||||
// SPDLOG_DEBUG_IF(my_logger, true, "some debug message {} {}", 3, 4);
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
#ifdef SPDLOG_TRACE_ON
 | 
			
		||||
#define SPDLOG_STR_H(x) #x
 | 
			
		||||
#define SPDLOG_STR_HELPER(x) SPDLOG_STR_H(x)
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
  #define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ "(" SPDLOG_STR_HELPER(__LINE__) ") ] " __VA_ARGS__)
 | 
			
		||||
  #define SPDLOG_TRACE_IF(logger, flag, ...) logger->trace_if(flag, "[ " __FILE__ "(" SPDLOG_STR_HELPER(__LINE__) ") ] " __VA_ARGS__)
 | 
			
		||||
#else
 | 
			
		||||
  #define SPDLOG_TRACE(logger, ...) logger->trace("[ " __FILE__ ":" SPDLOG_STR_HELPER(__LINE__) " ] " __VA_ARGS__)
 | 
			
		||||
  #define SPDLOG_TRACE_IF(logger, flag, ...) logger->trace_if(flag, "[ " __FILE__ ":" SPDLOG_STR_HELPER(__LINE__) " ] " __VA_ARGS__)
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
#define SPDLOG_TRACE(logger, ...)
 | 
			
		||||
#define SPDLOG_TRACE_IF(logger, flag, ...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef SPDLOG_DEBUG_ON
 | 
			
		||||
#define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__)
 | 
			
		||||
#define SPDLOG_DEBUG_IF(logger, flag, ...) logger->debug_if(flag, __VA_ARGS__)
 | 
			
		||||
#else
 | 
			
		||||
#define SPDLOG_DEBUG(logger, ...)
 | 
			
		||||
#define SPDLOG_DEBUG_IF(logger, flag, ...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "spdlog/details/spdlog_impl.h"
 | 
			
		||||
							
								
								
									
										148
									
								
								vendor/spdlog/include/spdlog/tweakme.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								vendor/spdlog/include/spdlog/tweakme.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,148 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright(c) 2015 Gabi Melman.
 | 
			
		||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
//
 | 
			
		||||
// Edit this file to squeeze more performance, and to customize supported features
 | 
			
		||||
//
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Under Linux, the much faster CLOCK_REALTIME_COARSE clock can be used.
 | 
			
		||||
// This clock is less accurate - can be off by dozens of millis - depending on the kernel HZ.
 | 
			
		||||
// Uncomment to use it instead of the regular clock.
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_CLOCK_COARSE
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment if date/time logging is not needed and never appear in the log pattern.
 | 
			
		||||
// This will prevent spdlog from quering the clock on each log call.
 | 
			
		||||
//
 | 
			
		||||
// WARNING: If the log pattern contains any date/time while this flag is on, the result is undefined.
 | 
			
		||||
//          You must set new pattern(spdlog::set_pattern(..") without any date/time in it
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_NO_DATETIME
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment if thread id logging is not needed (i.e. no %t in the log pattern).
 | 
			
		||||
// This will prevent spdlog from quering the thread id on each log call.
 | 
			
		||||
//
 | 
			
		||||
// WARNING: If the log pattern contains thread id (i.e, %t) while this flag is on, the result is undefined.
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_NO_THREAD_ID
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment if logger name logging is not needed.
 | 
			
		||||
// This will prevent spdlog from copying the logger name  on each log call.
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_NO_NAME
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to enable the SPDLOG_DEBUG/SPDLOG_TRACE macros.
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_DEBUG_ON
 | 
			
		||||
// #define SPDLOG_TRACE_ON
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to avoid locking in the registry operations (spdlog::get(), spdlog::drop() spdlog::register()).
 | 
			
		||||
// Use only if your code never modifes concurrently the registry.
 | 
			
		||||
// Note that upon creating a logger the registry is modified by spdlog..
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_NO_REGISTRY_MUTEX
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to avoid spdlog's usage of atomic log levels
 | 
			
		||||
// Use only if your code never modifies a logger's log levels concurrently by different threads.
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_NO_ATOMIC_LEVELS
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to enable usage of wchar_t for file names on Windows.
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_WCHAR_FILENAMES
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to override default eol ("\n" or "\r\n" under Linux/Windows)
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_EOL ";-)\n"
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to use your own copy of the fmt library instead of spdlog's copy.
 | 
			
		||||
// In this case spdlog will try to include <fmt/format.h> so set your -I flag accordingly.
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_FMT_EXTERNAL
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to use printf-style messages in your logs instead of the usual
 | 
			
		||||
// format-style used by default.
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_FMT_PRINTF
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to enable syslog (disabled by default)
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_ENABLE_SYSLOG
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to enable wchar_t support (convert to utf8)
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_WCHAR_TO_UTF8_SUPPORT
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to prevent child processes from inheriting log file descriptors
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_PREVENT_CHILD_FD
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to mark some types as final, allowing more optimizations in release
 | 
			
		||||
// mode with recent compilers. See GCC's documentation for -Wsuggest-final-types
 | 
			
		||||
// for instance.
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_FINAL final
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to enable message counting feature.
 | 
			
		||||
// Use the %i in the logger pattern to display log message sequence id.
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_ENABLE_MESSAGE_COUNTER
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Uncomment to enable user defined tag names
 | 
			
		||||
//
 | 
			
		||||
// #define SPDLOG_LEVEL_NAMES  { "TRACE", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL", "OFF" };
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
		Reference in New Issue
	
	Block a user