mirror of
https://github.com/gabime/spdlog.git
synced 2024-12-25 10:01:33 +08:00
Merge branch 'master' into to_level
This commit is contained in:
commit
f9750dddee
@ -4,7 +4,7 @@
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(spdlog VERSION 0.16.3)
|
||||
project(spdlog VERSION 0.16.3 LANGUAGES CXX)
|
||||
include(CTest)
|
||||
include(CMakeDependentOption)
|
||||
include(GNUInstallDirs)
|
||||
@ -73,7 +73,6 @@ configure_file("cmake/spdlog.pc.in" "${pkg_config}" @ONLY)
|
||||
install(
|
||||
TARGETS spdlog
|
||||
EXPORT "${targets_export_name}"
|
||||
INCLUDES DESTINATION "${include_install_dir}"
|
||||
)
|
||||
|
||||
# install headers
|
||||
|
@ -1,49 +1,49 @@
|
||||
# *************************************************************************/
|
||||
# * Copyright (c) 2015 Ruslan Baratov. */
|
||||
# * */
|
||||
# * Permission is hereby granted, free of charge, to any person obtaining */
|
||||
# * a copy of this software and associated documentation files (the */
|
||||
# * "Software"), to deal in the Software without restriction, including */
|
||||
# * without limitation the rights to use, copy, modify, merge, publish, */
|
||||
# * distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
# * permit persons to whom the Software is furnished to do so, subject to */
|
||||
# * the following conditions: */
|
||||
# * */
|
||||
# * The above copyright notice and this permission notice shall be */
|
||||
# * included in all copies or substantial portions of the Software. */
|
||||
# * */
|
||||
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
# * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
# * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
# * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
# * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
# * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
# *************************************************************************/
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(SpdlogExamples)
|
||||
|
||||
if(TARGET spdlog)
|
||||
# Part of the main project
|
||||
add_library(spdlog::spdlog ALIAS spdlog)
|
||||
else()
|
||||
# Stand-alone build
|
||||
find_package(spdlog CONFIG REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
add_executable(example example.cpp)
|
||||
target_link_libraries(example spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
add_executable(benchmark bench.cpp)
|
||||
target_link_libraries(benchmark spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
add_executable(multisink multisink.cpp)
|
||||
target_link_libraries(multisink spdlog::spdlog ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
enable_testing()
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")
|
||||
add_test(NAME RunExample COMMAND example)
|
||||
add_test(NAME RunBenchmark COMMAND benchmark)
|
||||
# *************************************************************************/
|
||||
# * Copyright (c) 2015 Ruslan Baratov. */
|
||||
# * */
|
||||
# * Permission is hereby granted, free of charge, to any person obtaining */
|
||||
# * a copy of this software and associated documentation files (the */
|
||||
# * "Software"), to deal in the Software without restriction, including */
|
||||
# * without limitation the rights to use, copy, modify, merge, publish, */
|
||||
# * distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
# * permit persons to whom the Software is furnished to do so, subject to */
|
||||
# * the following conditions: */
|
||||
# * */
|
||||
# * The above copyright notice and this permission notice shall be */
|
||||
# * included in all copies or substantial portions of the Software. */
|
||||
# * */
|
||||
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
# * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
# * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
# * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
# * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
# * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
# *************************************************************************/
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(SpdlogExamples CXX)
|
||||
|
||||
if(TARGET spdlog)
|
||||
# Part of the main project
|
||||
add_library(spdlog::spdlog ALIAS spdlog)
|
||||
else()
|
||||
# Stand-alone build
|
||||
find_package(spdlog CONFIG REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
add_executable(example example.cpp)
|
||||
target_link_libraries(example spdlog::spdlog Threads::Threads)
|
||||
|
||||
add_executable(benchmark bench.cpp)
|
||||
target_link_libraries(benchmark spdlog::spdlog Threads::Threads)
|
||||
|
||||
add_executable(multisink multisink.cpp)
|
||||
target_link_libraries(multisink spdlog::spdlog Threads::Threads)
|
||||
|
||||
enable_testing()
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")
|
||||
add_test(NAME RunExample COMMAND example)
|
||||
add_test(NAME RunBenchmark COMMAND benchmark)
|
||||
|
@ -31,15 +31,15 @@ namespace details
|
||||
class async_log_helper;
|
||||
}
|
||||
|
||||
class async_logger SPDLOG_FINAL :public logger
|
||||
class async_logger SPDLOG_FINAL : public logger
|
||||
{
|
||||
public:
|
||||
template<class It>
|
||||
async_logger(const std::string& name,
|
||||
async_logger(const std::string& logger_name,
|
||||
const It& begin,
|
||||
const It& end,
|
||||
size_t queue_size,
|
||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
||||
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);
|
||||
@ -55,7 +55,7 @@ public:
|
||||
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 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);
|
||||
@ -65,8 +65,8 @@ public:
|
||||
void flush() override;
|
||||
|
||||
// Error handler
|
||||
virtual void set_error_handler(log_err_handler) override;
|
||||
virtual log_err_handler error_handler() override;
|
||||
void set_error_handler(log_err_handler) override;
|
||||
log_err_handler error_handler() override;
|
||||
|
||||
protected:
|
||||
void _sink_it(details::log_msg& msg) override;
|
||||
@ -78,5 +78,4 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#include "details/async_logger_impl.h"
|
||||
|
@ -5,6 +5,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define SPDLOG_VERSION "0.16.3"
|
||||
|
||||
#include "tweakme.h"
|
||||
|
||||
#include <string>
|
||||
#include <initializer_list>
|
||||
#include <chrono>
|
||||
@ -74,7 +78,7 @@ using log_err_handler = std::function<void(const std::string &err_msg)>;
|
||||
//Log level enum
|
||||
namespace level
|
||||
{
|
||||
typedef enum
|
||||
enum level_enum
|
||||
{
|
||||
trace = 0,
|
||||
debug = 1,
|
||||
@ -83,10 +87,10 @@ typedef enum
|
||||
err = 4,
|
||||
critical = 5,
|
||||
off = 6
|
||||
} level_enum;
|
||||
};
|
||||
|
||||
#if !defined(SPDLOG_LEVEL_NAMES)
|
||||
#define SPDLOG_LEVEL_NAMES { "trace", "debug", "info", "warning", "error", "critical", "off" }
|
||||
#define SPDLOG_LEVEL_NAMES { "trace", "debug", "info", "warning", "error", "critical", "off" }
|
||||
#endif
|
||||
static const char* level_names[] SPDLOG_LEVEL_NAMES;
|
||||
|
||||
@ -115,7 +119,6 @@ inline spdlog::level::level_enum to_level_enum(const char* name)
|
||||
using level_hasher = std::hash<int>;
|
||||
} //level
|
||||
|
||||
|
||||
//
|
||||
// Async overflow policy - block by default.
|
||||
//
|
||||
@ -145,22 +148,24 @@ namespace os
|
||||
std::string errno_str(int err_num);
|
||||
}
|
||||
}
|
||||
class spdlog_ex: public std::exception
|
||||
class spdlog_ex : public std::exception
|
||||
{
|
||||
public:
|
||||
spdlog_ex(const std::string& msg):_msg(msg)
|
||||
explicit spdlog_ex(std::string msg) : _msg(std::move(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;
|
||||
|
||||
};
|
||||
|
||||
//
|
||||
@ -172,5 +177,4 @@ using filename_t = std::wstring;
|
||||
using filename_t = std::string;
|
||||
#endif
|
||||
|
||||
|
||||
} //spdlog
|
||||
|
@ -43,6 +43,7 @@ class async_log_helper
|
||||
flush,
|
||||
terminate
|
||||
};
|
||||
|
||||
struct async_msg
|
||||
{
|
||||
std::string logger_name;
|
||||
@ -56,8 +57,14 @@ class async_log_helper
|
||||
async_msg() = default;
|
||||
~async_msg() = default;
|
||||
|
||||
explicit async_msg(async_msg_type m_type) :
|
||||
level(level::info),
|
||||
thread_id(0),
|
||||
msg_type(m_type),
|
||||
msg_id(0)
|
||||
{}
|
||||
|
||||
async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
|
||||
async_msg(async_msg&& other) SPDLOG_NOEXCEPT :
|
||||
logger_name(std::move(other.logger_name)),
|
||||
level(std::move(other.level)),
|
||||
time(std::move(other.time)),
|
||||
@ -67,13 +74,6 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
|
||||
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);
|
||||
@ -91,7 +91,7 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
|
||||
async_msg& operator=(const async_msg& other) = delete;
|
||||
|
||||
// construct from log_msg
|
||||
async_msg(const details::log_msg& m):
|
||||
explicit async_msg(const details::log_msg& m):
|
||||
level(m.level),
|
||||
time(m.time),
|
||||
thread_id(m.thread_id),
|
||||
@ -104,7 +104,6 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// copy into log_msg
|
||||
void fill_log_msg(log_msg &msg)
|
||||
{
|
||||
@ -118,28 +117,29 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
|
||||
};
|
||||
|
||||
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,
|
||||
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,
|
||||
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);
|
||||
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);
|
||||
async_log_helper(const async_log_helper&) = delete;
|
||||
async_log_helper& operator=(const async_log_helper&) = delete;
|
||||
|
||||
void set_formatter(formatter_ptr msg_formatter);
|
||||
|
||||
void flush(bool wait_for_q);
|
||||
|
||||
@ -158,7 +158,6 @@ private:
|
||||
|
||||
bool _terminate_requested;
|
||||
|
||||
|
||||
// overflow policy
|
||||
const async_overflow_policy _overflow_policy;
|
||||
|
||||
@ -200,25 +199,26 @@ private:
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
inline spdlog::details::async_log_helper::async_log_helper(
|
||||
formatter_ptr formatter,
|
||||
const std::vector<sink_ptr>& sinks,
|
||||
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,
|
||||
std::function<void()> worker_warmup_cb,
|
||||
const std::chrono::milliseconds& flush_interval_ms,
|
||||
const std::function<void()>& worker_teardown_cb):
|
||||
_formatter(formatter),
|
||||
_sinks(sinks),
|
||||
std::function<void()> worker_teardown_cb):
|
||||
_formatter(std::move(formatter)),
|
||||
_sinks(std::move(sinks)),
|
||||
_q(queue_size),
|
||||
_err_handler(err_handler),
|
||||
_err_handler(std::move(err_handler)),
|
||||
_flush_requested(false),
|
||||
_terminate_requested(false),
|
||||
_overflow_policy(overflow_policy),
|
||||
_worker_warmup_cb(worker_warmup_cb),
|
||||
_worker_warmup_cb(std::move(worker_warmup_cb)),
|
||||
_flush_interval_ms(flush_interval_ms),
|
||||
_worker_teardown_cb(worker_teardown_cb),
|
||||
_worker_thread(&async_log_helper::worker_loop, this)
|
||||
{}
|
||||
_worker_teardown_cb(std::move(worker_teardown_cb))
|
||||
{
|
||||
_worker_thread = std::thread(&async_log_helper::worker_loop, this);
|
||||
}
|
||||
|
||||
// Send to the worker thread termination message(level=off)
|
||||
// and wait for it to finish gracefully
|
||||
@ -327,13 +327,10 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
|
||||
|
||||
// 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;
|
||||
}
|
||||
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
|
||||
@ -351,10 +348,9 @@ inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock::
|
||||
|
||||
inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter)
|
||||
{
|
||||
_formatter = msg_formatter;
|
||||
_formatter = std::move(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)
|
||||
{
|
||||
@ -391,8 +387,5 @@ inline void spdlog::details::async_log_helper::wait_empty_q()
|
||||
|
||||
inline void spdlog::details::async_log_helper::set_error_handler(spdlog::log_err_handler err_handler)
|
||||
{
|
||||
_err_handler = err_handler;
|
||||
_err_handler = std::move(err_handler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@ 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 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) :
|
||||
@ -33,7 +33,7 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name,
|
||||
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 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) :
|
||||
@ -42,13 +42,13 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name,
|
||||
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 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
|
||||
std::move(single_sink)
|
||||
}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
|
||||
|
||||
|
||||
|
@ -31,9 +31,7 @@ public:
|
||||
const int open_tries = 5;
|
||||
const int open_interval = 10;
|
||||
|
||||
explicit file_helper() :
|
||||
_fd(nullptr)
|
||||
{}
|
||||
explicit file_helper() = default;
|
||||
|
||||
file_helper(const file_helper&) = delete;
|
||||
file_helper& operator=(const file_helper&) = delete;
|
||||
@ -46,7 +44,6 @@ public:
|
||||
|
||||
void open(const filename_t& fname, bool truncate = false)
|
||||
{
|
||||
|
||||
close();
|
||||
auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
|
||||
_filename = fname;
|
||||
@ -76,7 +73,7 @@ public:
|
||||
|
||||
void close()
|
||||
{
|
||||
if (_fd)
|
||||
if (_fd != nullptr)
|
||||
{
|
||||
std::fclose(_fd);
|
||||
_fd = nullptr;
|
||||
@ -93,8 +90,10 @@ public:
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
if (!_fd)
|
||||
if (_fd == nullptr)
|
||||
{
|
||||
throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename));
|
||||
}
|
||||
return os::filesize(_fd);
|
||||
}
|
||||
|
||||
@ -137,8 +136,9 @@ public:
|
||||
// finally - return a valid base and extension tuple
|
||||
return std::make_tuple(fname.substr(0, ext_index), fname.substr(ext_index));
|
||||
}
|
||||
|
||||
private:
|
||||
FILE* _fd;
|
||||
FILE* _fd{ nullptr };
|
||||
filename_t _filename;
|
||||
};
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "../common.h"
|
||||
#include "../details/os.h"
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@ -21,8 +20,7 @@ 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)
|
||||
level(lvl)
|
||||
{
|
||||
#ifndef SPDLOG_NO_DATETIME
|
||||
time = os::now();
|
||||
@ -33,18 +31,18 @@ struct log_msg
|
||||
#endif
|
||||
}
|
||||
|
||||
log_msg(const log_msg& other) = delete;
|
||||
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;
|
||||
const std::string *logger_name{ nullptr };
|
||||
level::level_enum level;
|
||||
log_clock::time_point time;
|
||||
size_t thread_id;
|
||||
fmt::MemoryWriter raw;
|
||||
fmt::MemoryWriter formatted;
|
||||
size_t msg_id;
|
||||
size_t msg_id{ 0 };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -14,14 +14,14 @@
|
||||
// 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),
|
||||
inline spdlog::logger::logger(std::string logger_name, const It& begin, const It& end):
|
||||
_name(std::move(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
|
||||
_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)
|
||||
{
|
||||
@ -39,7 +39,7 @@ inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list si
|
||||
inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink):
|
||||
logger(logger_name,
|
||||
{
|
||||
single_sink
|
||||
std::move(single_sink)
|
||||
})
|
||||
{}
|
||||
|
||||
@ -49,7 +49,7 @@ inline spdlog::logger::~logger() = default;
|
||||
|
||||
inline void spdlog::logger::set_formatter(spdlog::formatter_ptr msg_formatter)
|
||||
{
|
||||
_set_formatter(msg_formatter);
|
||||
_set_formatter(std::move(msg_formatter));
|
||||
}
|
||||
|
||||
inline void spdlog::logger::set_pattern(const std::string& pattern, pattern_time_type pattern_time)
|
||||
@ -281,7 +281,7 @@ inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
|
||||
|
||||
inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler)
|
||||
{
|
||||
_err_handler = err_handler;
|
||||
_err_handler = std::move(err_handler);
|
||||
}
|
||||
|
||||
inline spdlog::log_err_handler spdlog::logger::error_handler()
|
||||
@ -289,7 +289,6 @@ 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);
|
||||
@ -330,9 +329,10 @@ inline void spdlog::logger::_set_pattern(const std::string& pattern, pattern_tim
|
||||
{
|
||||
_formatter = std::make_shared<pattern_formatter>(pattern, pattern_time);
|
||||
}
|
||||
|
||||
inline void spdlog::logger::_set_formatter(formatter_ptr msg_formatter)
|
||||
{
|
||||
_formatter = msg_formatter;
|
||||
_formatter = std::move(msg_formatter);
|
||||
}
|
||||
|
||||
inline void spdlog::logger::flush()
|
||||
@ -349,8 +349,8 @@ inline void spdlog::logger::_default_err_handler(const std::string &msg)
|
||||
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);
|
||||
details::log_msg err_msg;
|
||||
err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::default_eol);
|
||||
sinks::stderr_sink_mt::instance()->log(err_msg);
|
||||
_last_err_time = now;
|
||||
}
|
||||
|
@ -53,13 +53,13 @@ namespace spdlog
|
||||
namespace details
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
class mpmc_bounded_queue
|
||||
{
|
||||
public:
|
||||
|
||||
using item_type = T;
|
||||
mpmc_bounded_queue(size_t buffer_size)
|
||||
|
||||
explicit mpmc_bounded_queue(size_t buffer_size)
|
||||
:max_size_(buffer_size),
|
||||
buffer_(new cell_t[buffer_size]),
|
||||
buffer_mask_(buffer_size - 1)
|
||||
@ -79,6 +79,8 @@ public:
|
||||
delete[] buffer_;
|
||||
}
|
||||
|
||||
mpmc_bounded_queue(mpmc_bounded_queue const&) = delete;
|
||||
void operator=(mpmc_bounded_queue const&) = delete;
|
||||
|
||||
bool enqueue(T&& data)
|
||||
{
|
||||
@ -157,7 +159,7 @@ private:
|
||||
size_t const max_size_;
|
||||
|
||||
static size_t const cacheline_size = 64;
|
||||
typedef char cacheline_pad_t[cacheline_size];
|
||||
using cacheline_pad_t = char[cacheline_size];
|
||||
|
||||
cacheline_pad_t pad0_;
|
||||
cell_t* const buffer_;
|
||||
@ -167,9 +169,6 @@ private:
|
||||
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
|
||||
|
@ -27,7 +27,7 @@ struct null_atomic_int
|
||||
int value;
|
||||
null_atomic_int() = default;
|
||||
|
||||
null_atomic_int(int val):value(val)
|
||||
explicit null_atomic_int(int val) : value(val)
|
||||
{}
|
||||
|
||||
int load(std::memory_order) const
|
||||
|
@ -96,7 +96,6 @@ inline std::tm localtime()
|
||||
return localtime(now_t);
|
||||
}
|
||||
|
||||
|
||||
inline std::tm gmtime(const std::time_t &time_tt)
|
||||
{
|
||||
|
||||
@ -140,8 +139,7 @@ inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
SPDLOG_CONSTEXPR static const char* eol = SPDLOG_EOL;
|
||||
SPDLOG_CONSTEXPR static int eol_size = sizeof(SPDLOG_EOL) - 1;
|
||||
SPDLOG_CONSTEXPR static const char* default_eol = SPDLOG_EOL;
|
||||
|
||||
|
||||
|
||||
@ -155,10 +153,13 @@ SPDLOG_CONSTEXPR static const char folder_sep = '/';
|
||||
|
||||
inline void prevent_child_fd(FILE *f)
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
#if !defined(__cplusplus_winrt)
|
||||
auto file_handle = (HANDLE)_get_osfhandle(_fileno(f));
|
||||
if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0))
|
||||
throw spdlog_ex("SetHandleInformation failed", errno);
|
||||
#endif
|
||||
#else
|
||||
auto fd = fileno(f);
|
||||
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||
@ -168,7 +169,7 @@ inline void prevent_child_fd(FILE *f)
|
||||
|
||||
|
||||
//fopen_s on non windows for writing
|
||||
inline int fopen_s(FILE** fp, const filename_t& filename, const filename_t& mode)
|
||||
inline bool fopen_s(FILE** fp, const filename_t& filename, const filename_t& mode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#ifdef SPDLOG_WCHAR_FILENAMES
|
||||
@ -248,7 +249,7 @@ inline size_t filesize(FILE *f)
|
||||
int fd = fileno(f);
|
||||
//64 bits(but not in osx or cygwin, where fstat64 is deprecated)
|
||||
#if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__)) && !defined(__CYGWIN__)
|
||||
struct stat64 st;
|
||||
struct stat64 st ;
|
||||
if (fstat64(fd, &st) == 0)
|
||||
return static_cast<size_t>(st.st_size);
|
||||
#else // unix 32 bits or cygwin
|
||||
@ -316,9 +317,9 @@ inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
|
||||
}
|
||||
};
|
||||
|
||||
long int offset_seconds = helper::calculate_gmt_offset(tm);
|
||||
auto offset_seconds = helper::calculate_gmt_offset(tm);
|
||||
#else
|
||||
long int offset_seconds = tm.tm_gmtoff;
|
||||
auto offset_seconds = tm.tm_gmtoff;
|
||||
#endif
|
||||
|
||||
return static_cast<int>(offset_seconds / 60);
|
||||
@ -330,12 +331,12 @@ inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
|
||||
inline size_t _thread_id()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return static_cast<size_t>(::GetCurrentThreadId());
|
||||
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));
|
||||
return static_cast<size_t>(syscall(SYS_gettid));
|
||||
#elif __FreeBSD__
|
||||
long tid;
|
||||
thr_self(&tid);
|
||||
@ -352,7 +353,7 @@ inline size_t _thread_id()
|
||||
//Return current thread id as size_t (from thread local storage)
|
||||
inline size_t thread_id()
|
||||
{
|
||||
#if defined(SPDLOG_DISABLE_TID_CACHING) || (defined(_MSC_VER) && (_MSC_VER < 1900)) || (defined(__clang__) && !__has_feature(cxx_thread_local))
|
||||
#if defined(SPDLOG_DISABLE_TID_CACHING) || (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__cplusplus_winrt ) || (defined(__clang__) && !__has_feature(cxx_thread_local))
|
||||
return _thread_id();
|
||||
#else // cache thread id in tls
|
||||
static thread_local const size_t tid = _thread_id();
|
||||
@ -368,7 +369,7 @@ inline size_t thread_id()
|
||||
inline void sleep_for_millis(int milliseconds)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
Sleep(milliseconds);
|
||||
::Sleep(milliseconds);
|
||||
#else
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
|
||||
#endif
|
||||
@ -401,10 +402,7 @@ inline std::string errno_to_string(char buf[256], int res)
|
||||
{
|
||||
return std::string(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Unknown error";
|
||||
}
|
||||
return "Unknown error";
|
||||
}
|
||||
|
||||
// Return errno string (thread safe)
|
||||
@ -437,7 +435,7 @@ inline int pid()
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
return ::_getpid();
|
||||
return static_cast<int>(::GetCurrentProcessId());
|
||||
#else
|
||||
return static_cast<int>(::getpid());
|
||||
#endif
|
||||
@ -480,9 +478,9 @@ inline bool in_terminal(FILE* file)
|
||||
{
|
||||
|
||||
#ifdef _WIN32
|
||||
return _isatty(_fileno(file)) ? true : false;
|
||||
return _isatty(_fileno(file)) != 0;
|
||||
#else
|
||||
return isatty(fileno(file)) ? true : false;
|
||||
return isatty(fileno(file)) != 0;
|
||||
#endif
|
||||
}
|
||||
} //os
|
||||
|
@ -27,27 +27,23 @@ namespace details
|
||||
class flag_formatter
|
||||
{
|
||||
public:
|
||||
virtual ~flag_formatter()
|
||||
{}
|
||||
virtual ~flag_formatter() = default;
|
||||
virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// name & level pattern appenders
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
namespace
|
||||
{
|
||||
class name_formatter:public flag_formatter
|
||||
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
|
||||
class level_formatter : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -56,7 +52,7 @@ class level_formatter:public flag_formatter
|
||||
};
|
||||
|
||||
// short log level appender
|
||||
class short_level_formatter:public flag_formatter
|
||||
class short_level_formatter : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -80,7 +76,7 @@ static int to12h(const tm& t)
|
||||
|
||||
//Abbreviated weekday name
|
||||
static const std::string days[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
class a_formatter:public flag_formatter
|
||||
class a_formatter : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -90,7 +86,7 @@ class a_formatter:public flag_formatter
|
||||
|
||||
//Full weekday name
|
||||
static const std::string full_days[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
|
||||
class A_formatter:public flag_formatter
|
||||
class A_formatter : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -99,8 +95,8 @@ class A_formatter:public flag_formatter
|
||||
};
|
||||
|
||||
//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
|
||||
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
|
||||
{
|
||||
@ -110,7 +106,7 @@ class b_formatter:public flag_formatter
|
||||
|
||||
//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
|
||||
class B_formatter : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -118,7 +114,6 @@ class B_formatter:public flag_formatter
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//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)
|
||||
{
|
||||
@ -133,9 +128,8 @@ static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v
|
||||
return w;
|
||||
}
|
||||
|
||||
|
||||
//Date and time representation (Thu Aug 23 15:35:46 2014)
|
||||
class c_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class c_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -144,9 +138,8 @@ class c_formatter SPDLOG_FINAL:public flag_formatter
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// year - 2 digit
|
||||
class C_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class C_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -154,10 +147,8 @@ class C_formatter SPDLOG_FINAL:public flag_formatter
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01
|
||||
class D_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class D_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -165,9 +156,8 @@ class D_formatter SPDLOG_FINAL:public flag_formatter
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// year - 4 digit
|
||||
class Y_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class Y_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -176,7 +166,7 @@ class Y_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// month 1-12
|
||||
class m_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class m_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -185,7 +175,7 @@ class m_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// day of month 1-31
|
||||
class d_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class d_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -193,8 +183,8 @@ class d_formatter SPDLOG_FINAL:public flag_formatter
|
||||
}
|
||||
};
|
||||
|
||||
// hours in 24 format 0-23
|
||||
class H_formatter SPDLOG_FINAL:public flag_formatter
|
||||
// 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
|
||||
{
|
||||
@ -202,8 +192,8 @@ class H_formatter SPDLOG_FINAL:public flag_formatter
|
||||
}
|
||||
};
|
||||
|
||||
// hours in 12 format 1-12
|
||||
class I_formatter SPDLOG_FINAL:public flag_formatter
|
||||
// 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
|
||||
{
|
||||
@ -212,7 +202,7 @@ class I_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// minutes 0-59
|
||||
class M_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class M_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -221,7 +211,7 @@ class M_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// seconds 0-59
|
||||
class S_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class S_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -230,7 +220,7 @@ class S_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// milliseconds
|
||||
class e_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class e_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -241,7 +231,7 @@ class e_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// microseconds
|
||||
class f_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class f_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -252,7 +242,7 @@ class f_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// nanoseconds
|
||||
class F_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class F_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -262,7 +252,7 @@ class F_formatter SPDLOG_FINAL:public flag_formatter
|
||||
}
|
||||
};
|
||||
|
||||
class E_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class E_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -273,7 +263,7 @@ class E_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// AM/PM
|
||||
class p_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class p_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -281,9 +271,8 @@ class p_formatter SPDLOG_FINAL:public flag_formatter
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 12 hour clock 02:55:02 pm
|
||||
class r_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class r_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -292,7 +281,7 @@ class r_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// 24-hour HH:MM time, equivalent to %H:%M
|
||||
class R_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class R_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -301,7 +290,7 @@ class R_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
|
||||
class T_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class T_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -310,13 +299,12 @@ class T_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// ISO 8601 offset from UTC in timezone (+-HH:MM)
|
||||
class z_formatter SPDLOG_FINAL:public flag_formatter
|
||||
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() = default;
|
||||
z_formatter(const z_formatter&) = delete;
|
||||
z_formatter& operator=(const z_formatter&) = delete;
|
||||
|
||||
@ -347,13 +335,12 @@ public:
|
||||
pad_n_join(msg.formatted, h, m, ':');
|
||||
}
|
||||
private:
|
||||
log_clock::time_point _last_update;
|
||||
int _offset_minutes;
|
||||
log_clock::time_point _last_update{ std::chrono::seconds(0) };
|
||||
int _offset_minutes{ 0 };
|
||||
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)
|
||||
{
|
||||
@ -364,10 +351,8 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Thread id
|
||||
class t_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class t_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -376,7 +361,7 @@ class t_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// Current pid
|
||||
class pid_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class pid_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -385,7 +370,7 @@ class pid_formatter SPDLOG_FINAL:public flag_formatter
|
||||
};
|
||||
|
||||
// message counter formatter
|
||||
class i_formatter SPDLOG_FINAL :public flag_formatter
|
||||
class i_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -393,7 +378,7 @@ class i_formatter SPDLOG_FINAL :public flag_formatter
|
||||
}
|
||||
};
|
||||
|
||||
class v_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class v_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -401,7 +386,7 @@ class v_formatter SPDLOG_FINAL:public flag_formatter
|
||||
}
|
||||
};
|
||||
|
||||
class ch_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class ch_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
public:
|
||||
explicit ch_formatter(char ch): _ch(ch)
|
||||
@ -416,11 +401,11 @@ private:
|
||||
|
||||
|
||||
//aggregate user chars to display as is
|
||||
class aggregate_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class aggregate_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
public:
|
||||
aggregate_formatter()
|
||||
{}
|
||||
aggregate_formatter() = default;
|
||||
|
||||
void add_ch(char ch)
|
||||
{
|
||||
_str += ch;
|
||||
@ -435,7 +420,7 @@ private:
|
||||
|
||||
// Full info formatter
|
||||
// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v
|
||||
class full_formatter SPDLOG_FINAL:public flag_formatter
|
||||
class full_formatter SPDLOG_FINAL : public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -487,8 +472,9 @@ class full_formatter SPDLOG_FINAL:public flag_formatter
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// pattern_formatter inline impl
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern, pattern_time_type pattern_time)
|
||||
: _pattern_time(pattern_time)
|
||||
inline spdlog::pattern_formatter::pattern_formatter(const std::string& pattern, pattern_time_type pattern_time, std::string eol) :
|
||||
_eol(std::move(eol)),
|
||||
_pattern_time(pattern_time)
|
||||
{
|
||||
compile_pattern(pattern);
|
||||
}
|
||||
@ -503,7 +489,6 @@ inline void spdlog::pattern_formatter::compile_pattern(const std::string& patter
|
||||
{
|
||||
if (user_chars) //append user chars found so far
|
||||
_formatters.push_back(std::move(user_chars));
|
||||
|
||||
if (++it != end)
|
||||
handle_flag(*it);
|
||||
else
|
||||
@ -528,135 +513,135 @@ inline void spdlog::pattern_formatter::handle_flag(char flag)
|
||||
{
|
||||
// logger name
|
||||
case 'n':
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::name_formatter()));
|
||||
_formatters.emplace_back(new details::name_formatter());
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::level_formatter()));
|
||||
_formatters.emplace_back(new details::level_formatter());
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::short_level_formatter()));
|
||||
_formatters.emplace_back(new details::short_level_formatter());
|
||||
break;
|
||||
|
||||
case('t'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::t_formatter()));
|
||||
_formatters.emplace_back(new details::t_formatter());
|
||||
break;
|
||||
|
||||
case('v'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::v_formatter()));
|
||||
_formatters.emplace_back(new details::v_formatter());
|
||||
break;
|
||||
|
||||
case('a'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::a_formatter()));
|
||||
_formatters.emplace_back(new details::a_formatter());
|
||||
break;
|
||||
|
||||
case('A'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::A_formatter()));
|
||||
_formatters.emplace_back(new details::A_formatter());
|
||||
break;
|
||||
|
||||
case('b'):
|
||||
case('h'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::b_formatter()));
|
||||
_formatters.emplace_back(new details::b_formatter());
|
||||
break;
|
||||
|
||||
case('B'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::B_formatter()));
|
||||
_formatters.emplace_back(new details::B_formatter());
|
||||
break;
|
||||
case('c'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::c_formatter()));
|
||||
_formatters.emplace_back(new details::c_formatter());
|
||||
break;
|
||||
|
||||
case('C'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::C_formatter()));
|
||||
_formatters.emplace_back(new details::C_formatter());
|
||||
break;
|
||||
|
||||
case('Y'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::Y_formatter()));
|
||||
_formatters.emplace_back(new details::Y_formatter());
|
||||
break;
|
||||
|
||||
case('D'):
|
||||
case('x'):
|
||||
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::D_formatter()));
|
||||
_formatters.emplace_back(new details::D_formatter());
|
||||
break;
|
||||
|
||||
case('m'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::m_formatter()));
|
||||
_formatters.emplace_back(new details::m_formatter());
|
||||
break;
|
||||
|
||||
case('d'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::d_formatter()));
|
||||
_formatters.emplace_back(new details::d_formatter());
|
||||
break;
|
||||
|
||||
case('H'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::H_formatter()));
|
||||
_formatters.emplace_back(new details::H_formatter());
|
||||
break;
|
||||
|
||||
case('I'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::I_formatter()));
|
||||
_formatters.emplace_back(new details::I_formatter());
|
||||
break;
|
||||
|
||||
case('M'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::M_formatter()));
|
||||
_formatters.emplace_back(new details::M_formatter());
|
||||
break;
|
||||
|
||||
case('S'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::S_formatter()));
|
||||
_formatters.emplace_back(new details::S_formatter());
|
||||
break;
|
||||
|
||||
case('e'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::e_formatter()));
|
||||
_formatters.emplace_back(new details::e_formatter());
|
||||
break;
|
||||
|
||||
case('f'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::f_formatter()));
|
||||
_formatters.emplace_back(new details::f_formatter());
|
||||
break;
|
||||
case('F'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::F_formatter()));
|
||||
_formatters.emplace_back(new details::F_formatter());
|
||||
break;
|
||||
|
||||
case('E'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::E_formatter()));
|
||||
_formatters.emplace_back(new details::E_formatter());
|
||||
break;
|
||||
|
||||
case('p'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::p_formatter()));
|
||||
_formatters.emplace_back(new details::p_formatter());
|
||||
break;
|
||||
|
||||
case('r'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::r_formatter()));
|
||||
_formatters.emplace_back(new details::r_formatter());
|
||||
break;
|
||||
|
||||
case('R'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::R_formatter()));
|
||||
_formatters.emplace_back(new details::R_formatter());
|
||||
break;
|
||||
|
||||
case('T'):
|
||||
case('X'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::T_formatter()));
|
||||
_formatters.emplace_back(new details::T_formatter());
|
||||
break;
|
||||
|
||||
case('z'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::z_formatter()));
|
||||
_formatters.emplace_back(new details::z_formatter());
|
||||
break;
|
||||
|
||||
case ('+'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::full_formatter()));
|
||||
_formatters.emplace_back(new details::full_formatter());
|
||||
break;
|
||||
|
||||
case ('P'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::pid_formatter()));
|
||||
_formatters.emplace_back(new details::pid_formatter());
|
||||
break;
|
||||
|
||||
|
||||
case ('i'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::i_formatter()));
|
||||
_formatters.emplace_back(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)));
|
||||
_formatters.emplace_back(new details::ch_formatter('%'));
|
||||
_formatters.emplace_back(new details::ch_formatter(flag));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -664,9 +649,10 @@ inline void spdlog::pattern_formatter::handle_flag(char flag)
|
||||
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));
|
||||
}
|
||||
return details::os::gmtime(log_clock::to_time_t(msg.time));
|
||||
}
|
||||
|
||||
inline void spdlog::pattern_formatter::format(details::log_msg& msg)
|
||||
@ -682,5 +668,5 @@ inline void spdlog::pattern_formatter::format(details::log_msg& msg)
|
||||
f->format(msg, tm_time);
|
||||
}
|
||||
//write eol
|
||||
msg.formatted.write(details::os::eol, details::os::eol_size);
|
||||
msg.formatted.write(_eol.data(), _eol.size());
|
||||
}
|
||||
|
@ -26,9 +26,12 @@ namespace spdlog
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
template <class Mutex> class registry_t
|
||||
template <class Mutex>
|
||||
class registry_t
|
||||
{
|
||||
public:
|
||||
registry_t<Mutex>(const registry_t<Mutex>&) = delete;
|
||||
registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete;
|
||||
|
||||
void register_logger(std::shared_ptr<logger> logger)
|
||||
{
|
||||
@ -38,7 +41,6 @@ public:
|
||||
_loggers[logger_name] = logger;
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<logger> get(const std::string& logger_name)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(_mutex);
|
||||
@ -111,6 +113,7 @@ public:
|
||||
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());
|
||||
@ -194,15 +197,14 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
registry_t<Mutex>() {}
|
||||
registry_t<Mutex>(const registry_t<Mutex>&) = delete;
|
||||
registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete;
|
||||
registry_t<Mutex>() = default;
|
||||
|
||||
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;
|
||||
@ -212,14 +214,16 @@ private:
|
||||
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::function<void()> _worker_warmup_cb;
|
||||
std::chrono::milliseconds _flush_interval_ms;
|
||||
std::function<void()> _worker_teardown_cb = nullptr;
|
||||
std::function<void()> _worker_teardown_cb;
|
||||
};
|
||||
|
||||
#ifdef SPDLOG_NO_REGISTRY_MUTEX
|
||||
typedef registry_t<spdlog::details::null_mutex> registry;
|
||||
using registry = registry_t<spdlog::details::null_mutex>;
|
||||
#else
|
||||
typedef registry_t<std::mutex> registry;
|
||||
using registry = registry_t<std::mutex>;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "../sinks/syslog_sink.h"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined _WIN32 && !defined(__cplusplus_winrt)
|
||||
#include "../sinks/wincolor_sink.h"
|
||||
#else
|
||||
#include "../sinks/ansicolor_sink.h"
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
inline void spdlog::register_logger(std::shared_ptr<logger> logger)
|
||||
{
|
||||
return details::registry::instance().register_logger(logger);
|
||||
return details::registry::instance().register_logger(std::move(logger));
|
||||
}
|
||||
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::get(const std::string& name)
|
||||
@ -107,7 +107,8 @@ inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::strin
|
||||
//
|
||||
// stdout/stderr color loggers
|
||||
//
|
||||
#ifdef _WIN32
|
||||
#if defined _WIN32 && !defined(__cplusplus_winrt)
|
||||
|
||||
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>();
|
||||
@ -182,13 +183,11 @@ inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
@ -196,7 +195,6 @@ inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_
|
||||
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)
|
||||
{
|
||||
@ -223,7 +221,7 @@ inline std::shared_ptr<spdlog::logger> spdlog::create_async(const std::string& l
|
||||
|
||||
inline void spdlog::set_formatter(spdlog::formatter_ptr f)
|
||||
{
|
||||
details::registry::instance().formatter(f);
|
||||
details::registry::instance().formatter(std::move(f));
|
||||
}
|
||||
|
||||
inline void spdlog::set_pattern(const std::string& format_string)
|
||||
@ -243,10 +241,9 @@ inline void spdlog::flush_on(level::level_enum log_level)
|
||||
|
||||
inline void spdlog::set_error_handler(log_err_handler handler)
|
||||
{
|
||||
return details::registry::instance().set_error_handler(handler);
|
||||
return details::registry::instance().set_error_handler(std::move(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);
|
||||
@ -259,7 +256,7 @@ inline void spdlog::set_sync_mode()
|
||||
|
||||
inline void spdlog::apply_all(std::function<void(std::shared_ptr<logger>)> fun)
|
||||
{
|
||||
details::registry::instance().apply_all(fun);
|
||||
details::registry::instance().apply_all(std::move(fun));
|
||||
}
|
||||
|
||||
inline void spdlog::drop_all()
|
||||
|
@ -72,9 +72,11 @@
|
||||
|
||||
// Dummy implementations of strerror_r and strerror_s called if corresponding
|
||||
// system functions are not available.
|
||||
FMT_MAYBE_UNUSED
|
||||
static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
|
||||
return fmt::internal::Null<>();
|
||||
}
|
||||
FMT_MAYBE_UNUSED
|
||||
static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
|
||||
return fmt::internal::Null<>();
|
||||
}
|
||||
@ -121,7 +123,7 @@ typedef void (*FormatFunc)(Writer &, int, StringRef);
|
||||
// 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");
|
||||
FMT_ASSERT(buffer != FMT_NULL && buffer_size != 0, "invalid buffer");
|
||||
|
||||
class StrError {
|
||||
private:
|
||||
@ -159,6 +161,11 @@ int safe_strerror(
|
||||
ERANGE : result;
|
||||
}
|
||||
|
||||
#ifdef __c2__
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
// Fallback to strerror if strerror_r and strerror_s are not available.
|
||||
int fallback(internal::Null<>) {
|
||||
errno = 0;
|
||||
@ -166,13 +173,15 @@ int safe_strerror(
|
||||
return errno;
|
||||
}
|
||||
|
||||
#ifdef __c2__
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
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_));
|
||||
}
|
||||
};
|
||||
@ -396,51 +405,6 @@ FMT_FUNC void format_system_error(
|
||||
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"));
|
||||
@ -502,8 +466,6 @@ template struct internal::BasicData<void>;
|
||||
|
||||
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);
|
||||
@ -516,8 +478,6 @@ template FMT_API int internal::CharTraits<char>::format_float(
|
||||
|
||||
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);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#ifndef FMT_FORMAT_H_
|
||||
#define FMT_FORMAT_H_
|
||||
|
||||
#define FMT_INCLUDE
|
||||
#include <cassert>
|
||||
#include <clocale>
|
||||
#include <cmath>
|
||||
@ -39,11 +40,26 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility> // for std::pair
|
||||
#undef FMT_INCLUDE
|
||||
|
||||
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
||||
#define FMT_VERSION 40000
|
||||
#define FMT_VERSION 40100
|
||||
|
||||
#ifdef _SECURE_SCL
|
||||
#if defined(__has_include)
|
||||
# define FMT_HAS_INCLUDE(x) __has_include(x)
|
||||
#else
|
||||
# define FMT_HAS_INCLUDE(x) 0
|
||||
#endif
|
||||
|
||||
#if (FMT_HAS_INCLUDE(<string_view>) && __cplusplus > 201402L) || \
|
||||
(defined(_MSVC_LANG) && _MSVC_LANG > 201402L && _MSC_VER >= 1910)
|
||||
# include <string_view>
|
||||
# define FMT_HAS_STRING_VIEW 1
|
||||
#else
|
||||
# define FMT_HAS_STRING_VIEW 0
|
||||
#endif
|
||||
|
||||
#if defined _SECURE_SCL && _SECURE_SCL
|
||||
# define FMT_SECURE_SCL _SECURE_SCL
|
||||
#else
|
||||
# define FMT_SECURE_SCL 0
|
||||
@ -97,7 +113,9 @@ typedef __int64 intmax_t;
|
||||
# define FMT_HAS_GXX_CXX11 1
|
||||
# endif
|
||||
#else
|
||||
# define FMT_GCC_VERSION 0
|
||||
# define FMT_GCC_EXTENSION
|
||||
# define FMT_HAS_GXX_CXX11 0
|
||||
#endif
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
@ -135,6 +153,32 @@ typedef __int64 intmax_t;
|
||||
# define FMT_HAS_CPP_ATTRIBUTE(x) 0
|
||||
#endif
|
||||
|
||||
#if FMT_HAS_CPP_ATTRIBUTE(maybe_unused)
|
||||
# define FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
|
||||
// VC++ 1910 support /std: option and that will set _MSVC_LANG macro
|
||||
// Clang with Microsoft CodeGen doesn't define _MSVC_LANG macro
|
||||
#elif defined(_MSVC_LANG) && _MSVC_LANG > 201402 && _MSC_VER >= 1910
|
||||
# define FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
#ifdef FMT_HAS_CXX17_ATTRIBUTE_MAYBE_UNUSED
|
||||
# define FMT_MAYBE_UNUSED [[maybe_unused]]
|
||||
// g++/clang++ also support [[gnu::unused]]. However, we don't use it.
|
||||
#elif defined(__GNUC__)
|
||||
# define FMT_MAYBE_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define FMT_MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
// Use the compiler's attribute noreturn
|
||||
#if defined(__MINGW32__) || defined(__MINGW64__)
|
||||
# define FMT_NORETURN __attribute__((noreturn))
|
||||
#elif FMT_HAS_CPP_ATTRIBUTE(noreturn) && __cplusplus >= 201103L
|
||||
# define FMT_NORETURN [[noreturn]]
|
||||
#else
|
||||
# define FMT_NORETURN
|
||||
#endif
|
||||
|
||||
#ifndef FMT_USE_VARIADIC_TEMPLATES
|
||||
// Variadic templates are available in GCC since version 4.4
|
||||
// (http://gcc.gnu.org/projects/cxx0x.html) and in Visual C++
|
||||
@ -156,6 +200,12 @@ typedef __int64 intmax_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L || FMT_MSC_VER >= 1700
|
||||
# define FMT_USE_ALLOCATOR_TRAITS 1
|
||||
#else
|
||||
# define FMT_USE_ALLOCATOR_TRAITS 0
|
||||
#endif
|
||||
|
||||
// Check if exceptions are disabled.
|
||||
#if defined(__GNUC__) && !defined(__EXCEPTIONS)
|
||||
# define FMT_EXCEPTIONS 0
|
||||
@ -262,11 +312,14 @@ typedef __int64 intmax_t;
|
||||
// makes the fmt::literals implementation easier. However, an explicit check
|
||||
// for variadic templates is added here just in case.
|
||||
// For Intel's compiler both it and the system gcc/msc must support UDLs.
|
||||
# define FMT_USE_USER_DEFINED_LITERALS \
|
||||
FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
|
||||
# if FMT_USE_VARIADIC_TEMPLATES && FMT_USE_RVALUE_REFERENCES && \
|
||||
(FMT_HAS_FEATURE(cxx_user_literals) || \
|
||||
(FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || FMT_MSC_VER >= 1900) && \
|
||||
(!defined(FMT_ICC_VERSION) || FMT_ICC_VERSION >= 1500)
|
||||
# define FMT_USE_USER_DEFINED_LITERALS 1
|
||||
# else
|
||||
# define FMT_USE_USER_DEFINED_LITERALS 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef FMT_USE_EXTERN_TEMPLATES
|
||||
@ -307,7 +360,10 @@ namespace fmt
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
# pragma intrinsic(_BitScanReverse)
|
||||
// avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning
|
||||
# ifndef __clang__
|
||||
# pragma intrinsic(_BitScanReverse)
|
||||
# endif
|
||||
inline uint32_t clz(uint32_t x)
|
||||
{
|
||||
unsigned long r = 0;
|
||||
@ -322,7 +378,8 @@ inline uint32_t clz(uint32_t x)
|
||||
}
|
||||
# define FMT_BUILTIN_CLZ(n) fmt::internal::clz(n)
|
||||
|
||||
# ifdef _WIN64
|
||||
// avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning
|
||||
# if defined(_WIN64) && !defined(__clang__)
|
||||
# pragma intrinsic(_BitScanReverse64)
|
||||
# endif
|
||||
|
||||
@ -546,6 +603,27 @@ public:
|
||||
const std::basic_string<Char, std::char_traits<Char>, Allocator> &s)
|
||||
: data_(s.c_str()), size_(s.size()) {}
|
||||
|
||||
#if FMT_HAS_STRING_VIEW
|
||||
/**
|
||||
\rst
|
||||
Constructs a string reference from a ``std::basic_string_view`` object.
|
||||
\endrst
|
||||
*/
|
||||
BasicStringRef(
|
||||
const std::basic_string_view<Char, std::char_traits<Char>> &s)
|
||||
: data_(s.data()), size_(s.size()) {}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Converts a string reference to an ``std::string_view`` object.
|
||||
\endrst
|
||||
*/
|
||||
explicit operator std::basic_string_view<Char>() const FMT_NOEXCEPT
|
||||
{
|
||||
return std::basic_string_view<Char>(data_, size_);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
\rst
|
||||
Converts a string reference to an ``std::string`` object.
|
||||
@ -669,7 +747,7 @@ public:
|
||||
explicit FormatError(CStringRef message)
|
||||
: std::runtime_error(message.c_str()) {}
|
||||
FormatError(const FormatError &ferr) : std::runtime_error(ferr) {}
|
||||
FMT_API ~FormatError() FMT_DTOR_NOEXCEPT;
|
||||
FMT_API ~FormatError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
|
||||
};
|
||||
|
||||
namespace internal
|
||||
@ -812,7 +890,7 @@ template <typename U>
|
||||
void Buffer<T>::append(const U *begin, const U *end)
|
||||
{
|
||||
FMT_ASSERT(end >= begin, "negative value");
|
||||
std::size_t new_size = size_ + (end - begin);
|
||||
std::size_t new_size = size_ + static_cast<std::size_t>(end - begin);
|
||||
if (new_size > capacity_)
|
||||
grow(new_size);
|
||||
std::uninitialized_copy(begin, end,
|
||||
@ -843,10 +921,7 @@ protected:
|
||||
public:
|
||||
explicit MemoryBuffer(const Allocator &alloc = Allocator())
|
||||
: Allocator(alloc), Buffer<T>(data_, SIZE) {}
|
||||
~MemoryBuffer()
|
||||
{
|
||||
deallocate();
|
||||
}
|
||||
~MemoryBuffer() FMT_OVERRIDE { deallocate(); }
|
||||
|
||||
#if FMT_USE_RVALUE_REFERENCES
|
||||
private:
|
||||
@ -900,7 +975,12 @@ void MemoryBuffer<T, SIZE, Allocator>::grow(std::size_t size)
|
||||
std::size_t new_capacity = this->capacity_ + this->capacity_ / 2;
|
||||
if (size > new_capacity)
|
||||
new_capacity = size;
|
||||
#if FMT_USE_ALLOCATOR_TRAITS
|
||||
T *new_ptr =
|
||||
std::allocator_traits<Allocator>::allocate(*this, new_capacity, FMT_NULL);
|
||||
#else
|
||||
T *new_ptr = this->allocate(new_capacity, FMT_NULL);
|
||||
#endif
|
||||
// The following code doesn't throw, so the raw pointer above doesn't leak.
|
||||
std::uninitialized_copy(this->ptr_, this->ptr_ + this->size_,
|
||||
make_ptr(new_ptr, new_capacity));
|
||||
@ -1050,7 +1130,7 @@ struct IntTraits
|
||||
TypeSelector<std::numeric_limits<T>::digits <= 32>::Type MainType;
|
||||
};
|
||||
|
||||
FMT_API void report_unknown_type(char code, const char *type);
|
||||
FMT_API FMT_NORETURN void report_unknown_type(char code, const char *type);
|
||||
|
||||
// Static data is placed in this class template to allow header-only
|
||||
// configuration.
|
||||
@ -1335,19 +1415,19 @@ T &get();
|
||||
Yes &convert(fmt::ULongLong);
|
||||
No &convert(...);
|
||||
|
||||
template<typename T, bool ENABLE_CONVERSION>
|
||||
template <typename T, bool ENABLE_CONVERSION>
|
||||
struct ConvertToIntImpl
|
||||
{
|
||||
enum { value = ENABLE_CONVERSION };
|
||||
};
|
||||
|
||||
template<typename T, bool ENABLE_CONVERSION>
|
||||
template <typename T, bool ENABLE_CONVERSION>
|
||||
struct ConvertToIntImpl2
|
||||
{
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
struct ConvertToIntImpl2<T, true>
|
||||
{
|
||||
enum
|
||||
@ -1357,7 +1437,7 @@ struct ConvertToIntImpl2<T, true>
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
struct ConvertToInt
|
||||
{
|
||||
enum
|
||||
@ -1376,22 +1456,22 @@ FMT_DISABLE_CONVERSION_TO_INT(float);
|
||||
FMT_DISABLE_CONVERSION_TO_INT(double);
|
||||
FMT_DISABLE_CONVERSION_TO_INT(long double);
|
||||
|
||||
template<bool B, class T = void>
|
||||
template <bool B, class T = void>
|
||||
struct EnableIf {};
|
||||
|
||||
template<class T>
|
||||
template <class T>
|
||||
struct EnableIf<true, T>
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<bool B, class T, class F>
|
||||
template <bool B, class T, class F>
|
||||
struct Conditional
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T, class F>
|
||||
template <class T, class F>
|
||||
struct Conditional<false, T, F>
|
||||
{
|
||||
typedef F type;
|
||||
@ -1457,10 +1537,10 @@ inline fmt::StringRef thousands_sep(...)
|
||||
typedef int FMT_CONCAT_(Assert, __LINE__)[(cond) ? 1 : -1] FMT_UNUSED
|
||||
#endif
|
||||
|
||||
template <typename Formatter, typename Char, typename T>
|
||||
void format_arg(Formatter &, const Char *, const T &)
|
||||
template <typename Formatter>
|
||||
void format_arg(Formatter&, ...)
|
||||
{
|
||||
FMT_STATIC_ASSERT(FalseType<T>::value,
|
||||
FMT_STATIC_ASSERT(FalseType<Formatter>::value,
|
||||
"Cannot format argument. To enable the use of ostream "
|
||||
"operator<< include fmt/ostream.h. Otherwise provide "
|
||||
"an overload of format_arg.");
|
||||
@ -1494,6 +1574,9 @@ private:
|
||||
MakeValue(typename WCharHelper<wchar_t *, Char>::Unsupported);
|
||||
MakeValue(typename WCharHelper<const wchar_t *, Char>::Unsupported);
|
||||
MakeValue(typename WCharHelper<const std::wstring &, Char>::Unsupported);
|
||||
#if FMT_HAS_STRING_VIEW
|
||||
MakeValue(typename WCharHelper<const std::wstring_view &, Char>::Unsupported);
|
||||
#endif
|
||||
MakeValue(typename WCharHelper<WStringRef, Char>::Unsupported);
|
||||
|
||||
void set_string(StringRef str)
|
||||
@ -1570,6 +1653,26 @@ public:
|
||||
FMT_MAKE_VALUE(unsigned char, uint_value, UINT)
|
||||
FMT_MAKE_VALUE(char, int_value, CHAR)
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template <
|
||||
typename T,
|
||||
typename = typename std::enable_if<
|
||||
std::is_enum<T>::value && ConvertToInt<T>::value>::type>
|
||||
MakeValue(T value)
|
||||
{
|
||||
int_value = value;
|
||||
}
|
||||
|
||||
template <
|
||||
typename T,
|
||||
typename = typename std::enable_if<
|
||||
std::is_enum<T>::value && ConvertToInt<T>::value>::type>
|
||||
static uint64_t type(T)
|
||||
{
|
||||
return Arg::INT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
MakeValue(typename WCharHelper<wchar_t, Char>::Supported value)
|
||||
{
|
||||
@ -1592,6 +1695,9 @@ public:
|
||||
FMT_MAKE_VALUE(unsigned char *, ustring.value, CSTRING)
|
||||
FMT_MAKE_VALUE(const unsigned char *, ustring.value, CSTRING)
|
||||
FMT_MAKE_STR_VALUE(const std::string &, STRING)
|
||||
#if FMT_HAS_STRING_VIEW
|
||||
FMT_MAKE_STR_VALUE(const std::string_view &, STRING)
|
||||
#endif
|
||||
FMT_MAKE_STR_VALUE(StringRef, STRING)
|
||||
FMT_MAKE_VALUE_(CStringRef, string.value, CSTRING, value.c_str())
|
||||
|
||||
@ -1604,6 +1710,9 @@ public:
|
||||
FMT_MAKE_WSTR_VALUE(wchar_t *, WSTRING)
|
||||
FMT_MAKE_WSTR_VALUE(const wchar_t *, WSTRING)
|
||||
FMT_MAKE_WSTR_VALUE(const std::wstring &, WSTRING)
|
||||
#if FMT_HAS_STRING_VIEW
|
||||
FMT_MAKE_WSTR_VALUE(const std::wstring_view &, WSTRING)
|
||||
#endif
|
||||
FMT_MAKE_WSTR_VALUE(WStringRef, WSTRING)
|
||||
|
||||
FMT_MAKE_VALUE(void *, pointer, POINTER)
|
||||
@ -1689,7 +1798,7 @@ class RuntimeError : public std::runtime_error
|
||||
protected:
|
||||
RuntimeError() : std::runtime_error("") {}
|
||||
RuntimeError(const RuntimeError &rerr) : std::runtime_error(rerr) {}
|
||||
FMT_API ~RuntimeError() FMT_DTOR_NOEXCEPT;
|
||||
FMT_API ~RuntimeError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
@ -2267,7 +2376,7 @@ private:
|
||||
MapType map_;
|
||||
|
||||
public:
|
||||
FMT_API void init(const ArgList &args);
|
||||
void init(const ArgList &args);
|
||||
|
||||
const internal::Arg *find(const fmt::BasicStringRef<Char> &name) const
|
||||
{
|
||||
@ -2282,6 +2391,61 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
void 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 Impl, typename Char, typename Spec = fmt::FormatSpec>
|
||||
class ArgFormatterBase : public ArgVisitor<Impl, void>
|
||||
{
|
||||
@ -2623,7 +2787,8 @@ template <std::size_t N, bool/*IsPacked*/= (N < ArgList::MAX_PACKED_ARGS)>
|
||||
template <std::size_t N>
|
||||
struct ArgArray<N, true/*IsPacked*/>
|
||||
{
|
||||
typedef Value Type[N > 0 ? N : 1];
|
||||
// '+' is used to silence GCC -Wduplicated-branches warning.
|
||||
typedef Value Type[N > 0 ? N : +1];
|
||||
|
||||
template <typename Formatter, typename T>
|
||||
static Value make(const T &value)
|
||||
@ -2823,7 +2988,7 @@ public:
|
||||
FMT_DEFAULTED_COPY_CTOR(SystemError)
|
||||
FMT_VARIADIC_CTOR(SystemError, init, int, CStringRef)
|
||||
|
||||
FMT_API ~SystemError() FMT_DTOR_NOEXCEPT;
|
||||
FMT_API ~SystemError() FMT_DTOR_NOEXCEPT FMT_OVERRIDE;
|
||||
|
||||
int error_code() const
|
||||
{
|
||||
@ -4057,10 +4222,10 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
|
||||
#define FMT_GET_ARG_NAME(type, index) arg##index
|
||||
|
||||
#if FMT_USE_VARIADIC_TEMPLATES
|
||||
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
|
||||
# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \
|
||||
template <typename... Args> \
|
||||
ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
||||
const Args & ... args) { \
|
||||
const Args & ... args) Const { \
|
||||
typedef fmt::internal::ArgArray<sizeof...(Args)> ArgArray; \
|
||||
typename ArgArray::Type array{ \
|
||||
ArgArray::template make<fmt::BasicFormatter<Char> >(args)...}; \
|
||||
@ -4070,35 +4235,35 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
|
||||
#else
|
||||
// Defines a wrapper for a function taking __VA_ARGS__ arguments
|
||||
// and n additional arguments of arbitrary types.
|
||||
# define FMT_WRAP(Char, ReturnType, func, call, n, ...) \
|
||||
# define FMT_WRAP(Const, Char, ReturnType, func, call, n, ...) \
|
||||
template <FMT_GEN(n, FMT_MAKE_TEMPLATE_ARG)> \
|
||||
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__), \
|
||||
FMT_GEN(n, FMT_MAKE_ARG)) { \
|
||||
FMT_GEN(n, FMT_MAKE_ARG)) Const { \
|
||||
fmt::internal::ArgArray<n>::Type arr; \
|
||||
FMT_GEN(n, FMT_ASSIGN_##Char); \
|
||||
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList( \
|
||||
fmt::internal::make_type(FMT_GEN(n, FMT_MAKE_REF2)), arr)); \
|
||||
}
|
||||
|
||||
# define FMT_VARIADIC_(Char, ReturnType, func, call, ...) \
|
||||
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) { \
|
||||
# define FMT_VARIADIC_(Const, Char, ReturnType, func, call, ...) \
|
||||
inline ReturnType func(FMT_FOR_EACH(FMT_ADD_ARG_NAME, __VA_ARGS__)) Const { \
|
||||
call(FMT_FOR_EACH(FMT_GET_ARG_NAME, __VA_ARGS__), fmt::ArgList()); \
|
||||
} \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 1, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 2, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 3, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 4, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 5, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 6, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 7, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 8, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 9, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 10, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 11, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 12, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 13, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 14, __VA_ARGS__) \
|
||||
FMT_WRAP(Char, ReturnType, func, call, 15, __VA_ARGS__)
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 1, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 2, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 3, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 4, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 5, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 6, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 7, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 8, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 9, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 10, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 11, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 12, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 13, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 14, __VA_ARGS__) \
|
||||
FMT_WRAP(Const, Char, ReturnType, func, call, 15, __VA_ARGS__)
|
||||
#endif // FMT_USE_VARIADIC_TEMPLATES
|
||||
|
||||
/**
|
||||
@ -4129,10 +4294,16 @@ void arg(WStringRef, const internal::NamedArg<Char>&) FMT_DELETED_OR_UNDEFINED;
|
||||
\endrst
|
||||
*/
|
||||
#define FMT_VARIADIC(ReturnType, func, ...) \
|
||||
FMT_VARIADIC_(char, ReturnType, func, return func, __VA_ARGS__)
|
||||
FMT_VARIADIC_(, char, ReturnType, func, return func, __VA_ARGS__)
|
||||
|
||||
#define FMT_VARIADIC_CONST(ReturnType, func, ...) \
|
||||
FMT_VARIADIC_(const, char, ReturnType, func, return func, __VA_ARGS__)
|
||||
|
||||
#define FMT_VARIADIC_W(ReturnType, func, ...) \
|
||||
FMT_VARIADIC_(wchar_t, ReturnType, func, return func, __VA_ARGS__)
|
||||
FMT_VARIADIC_(, wchar_t, ReturnType, func, return func, __VA_ARGS__)
|
||||
|
||||
#define FMT_VARIADIC_CONST_W(ReturnType, func, ...) \
|
||||
FMT_VARIADIC_(const, wchar_t, ReturnType, func, return func, __VA_ARGS__)
|
||||
|
||||
#define FMT_CAPTURE_ARG_(id, index) ::fmt::arg(#id, id)
|
||||
|
||||
@ -4179,20 +4350,22 @@ unsigned parse_nonnegative_int(const Char *&s)
|
||||
{
|
||||
assert('0' <= *s && *s <= '9');
|
||||
unsigned value = 0;
|
||||
// Convert to unsigned to prevent a warning.
|
||||
unsigned max_int = (std::numeric_limits<int>::max)();
|
||||
unsigned big = max_int / 10;
|
||||
do
|
||||
{
|
||||
unsigned new_value = value * 10 + (*s++ - '0');
|
||||
// Check if value wrapped around.
|
||||
if (new_value < value)
|
||||
// Check for overflow.
|
||||
if (value > big)
|
||||
{
|
||||
value = (std::numeric_limits<unsigned>::max)();
|
||||
value = max_int + 1;
|
||||
break;
|
||||
}
|
||||
value = new_value;
|
||||
value = value * 10 + (*s - '0');
|
||||
++s;
|
||||
}
|
||||
while ('0' <= *s && *s <= '9');
|
||||
// Convert to unsigned to prevent a warning.
|
||||
unsigned max_int = (std::numeric_limits<int>::max)();
|
||||
if (value > max_int)
|
||||
FMT_THROW(FormatError("number is too big"));
|
||||
return value;
|
||||
@ -4392,7 +4565,8 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
|
||||
default:
|
||||
FMT_THROW(FormatError("width is not integer"));
|
||||
}
|
||||
if (value > (std::numeric_limits<int>::max)())
|
||||
unsigned max_int = (std::numeric_limits<int>::max)();
|
||||
if (value > max_int)
|
||||
FMT_THROW(FormatError("number is too big"));
|
||||
spec.width_ = static_cast<int>(value);
|
||||
}
|
||||
@ -4435,7 +4609,8 @@ const Char *BasicFormatter<Char, ArgFormatter>::format(
|
||||
default:
|
||||
FMT_THROW(FormatError("precision is not integer"));
|
||||
}
|
||||
if (value > (std::numeric_limits<int>::max)())
|
||||
unsigned max_int = (std::numeric_limits<int>::max)();
|
||||
if (value > max_int)
|
||||
FMT_THROW(FormatError("number is too big"));
|
||||
spec.precision_ = static_cast<int>(value);
|
||||
}
|
||||
|
@ -58,13 +58,15 @@ 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<>);
|
||||
template <typename T>
|
||||
typename EnableIf<sizeof(T) == 0>::type operator<<(const T &);
|
||||
};
|
||||
|
||||
No &operator<<(std::ostream &, int);
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
struct ConvertToIntImpl<T, true>
|
||||
{
|
||||
// Convert to int only if T doesn't have an overloaded operator<<.
|
||||
@ -87,6 +89,7 @@ void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
|
||||
|
||||
internal::FormatBuf<Char> format_buf(buffer);
|
||||
std::basic_ostream<Char> output(&format_buf);
|
||||
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||
output << value;
|
||||
|
||||
BasicStringRef<Char> str(&buffer[0], buffer.size());
|
||||
|
@ -152,7 +152,7 @@ public:
|
||||
visit_any_int(value);
|
||||
}
|
||||
|
||||
void visit_char(char value)
|
||||
void visit_char(int value)
|
||||
{
|
||||
if (type_ != 's')
|
||||
visit_any_int(value);
|
||||
@ -170,7 +170,7 @@ public:
|
||||
using internal::Arg;
|
||||
typedef typename internal::Conditional<
|
||||
is_same<T, void>::value, U, T>::type TargetType;
|
||||
if (sizeof(TargetType) <= sizeof(int))
|
||||
if (const_check(sizeof(TargetType) <= sizeof(int)))
|
||||
{
|
||||
// Extra casts are used to silence warnings.
|
||||
if (is_signed)
|
||||
|
@ -21,19 +21,20 @@ class flag_formatter;
|
||||
class formatter
|
||||
{
|
||||
public:
|
||||
virtual ~formatter() {}
|
||||
virtual ~formatter() = default;
|
||||
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);
|
||||
explicit pattern_formatter(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol);
|
||||
pattern_formatter(const pattern_formatter&) = delete;
|
||||
pattern_formatter& operator=(const pattern_formatter&) = delete;
|
||||
void format(details::log_msg& msg) override;
|
||||
|
||||
private:
|
||||
const std::string _eol;
|
||||
const std::string _pattern;
|
||||
const pattern_time_type _pattern_time;
|
||||
std::vector<std::unique_ptr<details::flag_formatter>> _formatters;
|
||||
@ -44,4 +45,3 @@ private:
|
||||
}
|
||||
|
||||
#include "details/pattern_formatter_impl.h"
|
||||
|
||||
|
@ -25,16 +25,17 @@ 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);
|
||||
logger(const std::string& name, sink_ptr single_sink);
|
||||
logger(const std::string& name, sinks_init_list sinks);
|
||||
|
||||
template <class It>
|
||||
logger(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);
|
||||
@ -44,7 +45,6 @@ public:
|
||||
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);
|
||||
|
||||
|
||||
#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);
|
||||
@ -57,19 +57,19 @@ public:
|
||||
#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 trace(const T& msg);
|
||||
template <typename T> void debug(const T& msg);
|
||||
template <typename T> void info(const T& msg);
|
||||
template <typename T> void warn(const T& msg);
|
||||
template <typename T> void error(const T& msg);
|
||||
template <typename T> void critical(const T& msg);
|
||||
|
||||
bool should_log(level::level_enum) const;
|
||||
void set_level(level::level_enum);
|
||||
bool should_log(level::level_enum msg_level) const;
|
||||
void set_level(level::level_enum log_level);
|
||||
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);
|
||||
void set_pattern(const std::string& pattern, pattern_time_type pattern_time = pattern_time_type::local);
|
||||
void set_formatter(formatter_ptr msg_formatter);
|
||||
|
||||
// automatically call flush() if message level >= log_level
|
||||
void flush_on(level::level_enum log_level);
|
||||
@ -79,22 +79,22 @@ public:
|
||||
const std::vector<sink_ptr>& sinks() const;
|
||||
|
||||
// error handler
|
||||
virtual void set_error_handler(log_err_handler);
|
||||
virtual void set_error_handler(log_err_handler 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);
|
||||
virtual void _sink_it(details::log_msg& msg);
|
||||
virtual void _set_pattern(const std::string& pattern, pattern_time_type pattern_time);
|
||||
virtual void _set_formatter(formatter_ptr msg_formatter);
|
||||
|
||||
// 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&);
|
||||
bool _should_flush_on(const details::log_msg& msg);
|
||||
|
||||
// increment the message count (only if defined(SPDLOG_ENABLE_MESSAGE_COUNTER))
|
||||
void _incr_msg_counter(details::log_msg &msg);
|
||||
void _incr_msg_counter(details::log_msg& msg);
|
||||
|
||||
const std::string _name;
|
||||
std::vector<sink_ptr> _sinks;
|
||||
|
@ -23,10 +23,10 @@ namespace sinks
|
||||
* If no color terminal detected, omit the escape codes.
|
||||
*/
|
||||
template <class Mutex>
|
||||
class ansicolor_sink: public base_sink<Mutex>
|
||||
class ansicolor_sink : public base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
ansicolor_sink(FILE* file): target_file_(file)
|
||||
explicit ansicolor_sink(FILE* file) : target_file_(file)
|
||||
{
|
||||
should_do_colors_ = details::os::in_terminal(file) && details::os::is_color_terminal();
|
||||
colors_[level::trace] = cyan;
|
||||
@ -37,7 +37,8 @@ public:
|
||||
colors_[level::critical] = bold + on_red;
|
||||
colors_[level::off] = reset;
|
||||
}
|
||||
virtual ~ansicolor_sink()
|
||||
|
||||
~ansicolor_sink() override
|
||||
{
|
||||
_flush();
|
||||
}
|
||||
@ -79,7 +80,7 @@ public:
|
||||
const std::string on_white = "\033[47m";
|
||||
|
||||
protected:
|
||||
virtual void _sink_it(const details::log_msg& msg) override
|
||||
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.
|
||||
@ -102,6 +103,7 @@ protected:
|
||||
{
|
||||
fflush(target_file_);
|
||||
}
|
||||
|
||||
FILE* target_file_;
|
||||
bool should_do_colors_;
|
||||
std::unordered_map<level::level_enum, std::string, level::level_hasher> colors_;
|
||||
@ -116,6 +118,9 @@ public:
|
||||
{}
|
||||
};
|
||||
|
||||
using ansicolor_stdout_sink_mt = ansicolor_stdout_sink<std::mutex>;
|
||||
using ansicolor_stdout_sink_st = ansicolor_stdout_sink<details::null_mutex>;
|
||||
|
||||
template<class Mutex>
|
||||
class ansicolor_stderr_sink: public ansicolor_sink<Mutex>
|
||||
{
|
||||
@ -124,11 +129,8 @@ public:
|
||||
{}
|
||||
};
|
||||
|
||||
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;
|
||||
using ansicolor_stderr_sink_mt = ansicolor_stderr_sink<std::mutex>;
|
||||
using ansicolor_stderr_sink_st = ansicolor_stderr_sink<details::null_mutex>;
|
||||
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
||||
|
@ -22,11 +22,10 @@ namespace spdlog
|
||||
namespace sinks
|
||||
{
|
||||
template<class Mutex>
|
||||
class base_sink:public sink
|
||||
class base_sink : public sink
|
||||
{
|
||||
public:
|
||||
base_sink():_mutex() {}
|
||||
virtual ~base_sink() = default;
|
||||
base_sink() = default;
|
||||
|
||||
base_sink(const base_sink&) = delete;
|
||||
base_sink& operator=(const base_sink&) = delete;
|
||||
@ -36,6 +35,7 @@ public:
|
||||
std::lock_guard<Mutex> lock(_mutex);
|
||||
_sink_it(msg);
|
||||
}
|
||||
|
||||
void flush() SPDLOG_FINAL override
|
||||
{
|
||||
std::lock_guard<Mutex> lock(_mutex);
|
||||
|
@ -22,13 +22,12 @@ namespace spdlog
|
||||
namespace sinks
|
||||
{
|
||||
template<class Mutex>
|
||||
class dist_sink: public base_sink<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;
|
||||
@ -51,8 +50,6 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
void add_sink(std::shared_ptr<sink> sink)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
|
||||
@ -66,7 +63,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
typedef dist_sink<std::mutex> dist_sink_mt;
|
||||
typedef dist_sink<details::null_mutex> dist_sink_st;
|
||||
using dist_sink_mt = dist_sink<std::mutex>;
|
||||
using dist_sink_st = dist_sink<details::null_mutex>;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ namespace sinks
|
||||
/*
|
||||
* Trivial file sink with single file as target
|
||||
*/
|
||||
template<class Mutex>
|
||||
class simple_file_sink SPDLOG_FINAL : public base_sink < Mutex >
|
||||
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)
|
||||
@ -46,32 +46,32 @@ protected:
|
||||
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;
|
||||
using simple_file_sink_mt = simple_file_sink<std::mutex>;
|
||||
using simple_file_sink_st = simple_file_sink<details::null_mutex>;
|
||||
|
||||
/*
|
||||
* Rotating file sink based on size
|
||||
*/
|
||||
template<class Mutex>
|
||||
class rotating_file_sink SPDLOG_FINAL : public base_sink < Mutex >
|
||||
template <class Mutex>
|
||||
class rotating_file_sink SPDLOG_FINAL : public base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
rotating_file_sink(const filename_t &base_filename,
|
||||
rotating_file_sink(filename_t base_filename,
|
||||
std::size_t max_size, std::size_t max_files) :
|
||||
_base_filename(base_filename),
|
||||
_base_filename(std::move(base_filename)),
|
||||
_max_size(max_size),
|
||||
_max_files(max_files),
|
||||
_current_size(0),
|
||||
_file_helper()
|
||||
_max_files(max_files)
|
||||
{
|
||||
_file_helper.open(calc_filename(_base_filename, 0));
|
||||
_current_size = _file_helper.size(); //expensive. called only once
|
||||
@ -81,8 +81,8 @@ public:
|
||||
// e.g. calc_filename("logs/mylog.txt, 3) => "logs/mylog.3.txt".
|
||||
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)
|
||||
typename std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
|
||||
if (index != 0u)
|
||||
{
|
||||
filename_t basename, ext;
|
||||
std::tie(basename, ext) = details::file_helper::split_by_extenstion(filename);
|
||||
@ -112,7 +112,6 @@ protected:
|
||||
_file_helper.flush();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// Rotate files:
|
||||
// log.txt -> log.1.txt
|
||||
@ -135,13 +134,14 @@ private:
|
||||
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))
|
||||
if (details::file_helper::file_exists(src) && details::os::rename(src, target) != 0)
|
||||
{
|
||||
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;
|
||||
@ -149,8 +149,8 @@ private:
|
||||
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;
|
||||
using rotating_file_sink_mt = rotating_file_sink<std::mutex>;
|
||||
using rotating_file_sink_st = rotating_file_sink<details::null_mutex>;
|
||||
|
||||
/*
|
||||
* Default generator of daily log file names.
|
||||
@ -195,9 +195,10 @@ 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,
|
||||
filename_t base_filename,
|
||||
int rotation_hour,
|
||||
int rotation_minute) : _base_filename(base_filename),
|
||||
int rotation_minute) :
|
||||
_base_filename(std::move(base_filename)),
|
||||
_rotation_h(rotation_hour),
|
||||
_rotation_m(rotation_minute)
|
||||
{
|
||||
@ -235,9 +236,10 @@ private:
|
||||
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));
|
||||
}
|
||||
return{ rotation_time + std::chrono::hours(24) };
|
||||
}
|
||||
|
||||
filename_t _base_filename;
|
||||
@ -247,7 +249,8 @@ private:
|
||||
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;
|
||||
using daily_file_sink_mt = daily_file_sink<std::mutex>;
|
||||
using daily_file_sink_st = daily_file_sink<details::null_mutex>;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -23,15 +23,13 @@ namespace sinks
|
||||
* MSVC sink (logging using OutputDebugStringA)
|
||||
*/
|
||||
template<class Mutex>
|
||||
class msvc_sink : public base_sink < Mutex >
|
||||
class msvc_sink : public base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
explicit msvc_sink()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
void _sink_it(const details::log_msg& msg) override
|
||||
{
|
||||
@ -42,8 +40,8 @@ protected:
|
||||
{}
|
||||
};
|
||||
|
||||
typedef msvc_sink<std::mutex> msvc_sink_mt;
|
||||
typedef msvc_sink<details::null_mutex> msvc_sink_st;
|
||||
using msvc_sink_mt = msvc_sink<std::mutex>;
|
||||
using msvc_sink_st = msvc_sink<details::null_mutex>;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ namespace sinks
|
||||
{
|
||||
|
||||
template <class Mutex>
|
||||
class null_sink : public base_sink < Mutex >
|
||||
class null_sink : public base_sink<Mutex>
|
||||
{
|
||||
protected:
|
||||
void _sink_it(const details::log_msg&) override
|
||||
@ -26,8 +26,9 @@ protected:
|
||||
{}
|
||||
|
||||
};
|
||||
typedef null_sink<details::null_mutex> null_sink_st;
|
||||
typedef null_sink<details::null_mutex> null_sink_mt;
|
||||
|
||||
using null_sink_mt = null_sink<details::null_mutex>;
|
||||
using null_sink_st = null_sink<details::null_mutex>;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -16,13 +16,12 @@ namespace spdlog
|
||||
namespace sinks
|
||||
{
|
||||
template<class Mutex>
|
||||
class ostream_sink: public base_sink<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
|
||||
@ -41,7 +40,8 @@ protected:
|
||||
bool _force_flush;
|
||||
};
|
||||
|
||||
typedef ostream_sink<std::mutex> ostream_sink_mt;
|
||||
typedef ostream_sink<details::null_mutex> ostream_sink_st;
|
||||
using ostream_sink_mt = ostream_sink<std::mutex>;
|
||||
using ostream_sink_st = ostream_sink<details::null_mutex>;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
//
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../details/log_msg.h"
|
||||
@ -15,12 +14,8 @@ namespace sinks
|
||||
class sink
|
||||
{
|
||||
public:
|
||||
sink()
|
||||
{
|
||||
_level = level::trace;
|
||||
}
|
||||
virtual ~sink() = default;
|
||||
|
||||
virtual ~sink() {}
|
||||
virtual void log(const details::log_msg& msg) = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
@ -29,8 +24,7 @@ public:
|
||||
level::level_enum level() const;
|
||||
|
||||
private:
|
||||
level_t _level;
|
||||
|
||||
level_t _level{ level::trace };
|
||||
};
|
||||
|
||||
inline bool sink::should_log(level::level_enum msg_level) const
|
||||
@ -50,4 +44,3 @@ inline level::level_enum sink::level() const
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,14 +21,16 @@ template <class Mutex>
|
||||
class stdout_sink SPDLOG_FINAL : public base_sink<Mutex>
|
||||
{
|
||||
using MyType = stdout_sink<Mutex>;
|
||||
|
||||
public:
|
||||
stdout_sink()
|
||||
{}
|
||||
explicit stdout_sink() = default;
|
||||
|
||||
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
|
||||
{
|
||||
@ -42,22 +44,23 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
typedef stdout_sink<details::null_mutex> stdout_sink_st;
|
||||
typedef stdout_sink<std::mutex> stdout_sink_mt;
|
||||
|
||||
using stdout_sink_mt = stdout_sink<std::mutex>;
|
||||
using stdout_sink_st = stdout_sink<details::null_mutex>;
|
||||
|
||||
template <class Mutex>
|
||||
class stderr_sink SPDLOG_FINAL : public base_sink<Mutex>
|
||||
{
|
||||
using MyType = stderr_sink<Mutex>;
|
||||
|
||||
public:
|
||||
stderr_sink()
|
||||
{}
|
||||
explicit stderr_sink() = default;
|
||||
|
||||
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
|
||||
{
|
||||
@ -71,7 +74,8 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
typedef stderr_sink<std::mutex> stderr_sink_mt;
|
||||
typedef stderr_sink<details::null_mutex> stderr_sink_st;
|
||||
using stderr_sink_mt = stderr_sink<std::mutex>;
|
||||
using stderr_sink_st = stderr_sink<details::null_mutex>;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -33,18 +33,19 @@ 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;
|
||||
_priorities[static_cast<size_t>(level::trace)] = LOG_DEBUG;
|
||||
_priorities[static_cast<size_t>(level::debug)] = LOG_DEBUG;
|
||||
_priorities[static_cast<size_t>(level::info)] = LOG_INFO;
|
||||
_priorities[static_cast<size_t>(level::warn)] = LOG_WARNING;
|
||||
_priorities[static_cast<size_t>(level::err)] = LOG_ERR;
|
||||
_priorities[static_cast<size_t>(level::critical)] = LOG_CRIT;
|
||||
_priorities[static_cast<size_t>(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()
|
||||
|
||||
~syslog_sink() override
|
||||
{
|
||||
::closelog();
|
||||
}
|
||||
@ -72,7 +73,7 @@ private:
|
||||
//
|
||||
int syslog_prio_from_level(const details::log_msg &msg) const
|
||||
{
|
||||
return _priorities[static_cast<int>(msg.level)];
|
||||
return _priorities[static_cast<size_t>(msg.level)];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ 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>
|
||||
template <class Mutex>
|
||||
class wincolor_sink : public base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
const WORD BOLD = FOREGROUND_INTENSITY;
|
||||
@ -42,7 +42,7 @@ public:
|
||||
colors_[level::off] = 0;
|
||||
}
|
||||
|
||||
virtual ~wincolor_sink()
|
||||
~wincolor_sink() override
|
||||
{
|
||||
this->flush();
|
||||
}
|
||||
@ -50,8 +50,15 @@ public:
|
||||
wincolor_sink(const wincolor_sink& other) = delete;
|
||||
wincolor_sink& operator=(const wincolor_sink& other) = delete;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void _sink_it(const details::log_msg& msg) override
|
||||
void _sink_it(const details::log_msg& msg) override
|
||||
{
|
||||
auto color = colors_[msg.level];
|
||||
auto orig_attribs = set_console_attribs(color);
|
||||
@ -59,18 +66,11 @@ protected:
|
||||
SetConsoleTextAttribute(out_handle_, orig_attribs); //reset to orig colors
|
||||
}
|
||||
|
||||
virtual void _flush() override
|
||||
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::unordered_map<level::level_enum, WORD, level::level_hasher> colors_;
|
||||
@ -85,37 +85,37 @@ private:
|
||||
back_color &= static_cast<WORD>(~(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
|
||||
return orig_buffer_info.wAttributes; //return orig attribs
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// windows color console to stdout
|
||||
//
|
||||
template<class Mutex>
|
||||
class wincolor_stdout_sink: public wincolor_sink<Mutex>
|
||||
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;
|
||||
using wincolor_stdout_sink_mt = wincolor_stdout_sink<std::mutex>;
|
||||
using wincolor_stdout_sink_st = wincolor_stdout_sink<details::null_mutex>;
|
||||
|
||||
//
|
||||
// windows color console to stderr
|
||||
//
|
||||
template<class Mutex>
|
||||
class wincolor_stderr_sink: public wincolor_sink<Mutex>
|
||||
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;
|
||||
using wincolor_stderr_sink_mt = wincolor_stderr_sink<std::mutex>;
|
||||
using wincolor_stderr_sink_st = wincolor_stderr_sink<details::null_mutex>;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -17,11 +17,11 @@ namespace sinks
|
||||
/*
|
||||
* Windows debug sink (logging using OutputDebugStringA, synonym for msvc_sink)
|
||||
*/
|
||||
template<class Mutex>
|
||||
template <class Mutex>
|
||||
using windebug_sink = msvc_sink<Mutex>;
|
||||
|
||||
typedef msvc_sink_mt windebug_sink_mt;
|
||||
typedef msvc_sink_st windebug_sink_st;
|
||||
using windebug_sink_mt = msvc_sink_mt;
|
||||
using windebug_sink_st = msvc_sink_st;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define SPDLOG_VERSION "0.16.3"
|
||||
|
||||
#include "tweakme.h"
|
||||
#include "common.h"
|
||||
#include "logger.h"
|
||||
|
||||
@ -48,7 +46,7 @@ void flush_on(level::level_enum log_level);
|
||||
//
|
||||
// Set global error handler
|
||||
//
|
||||
void set_error_handler(log_err_handler);
|
||||
void set_error_handler(log_err_handler handler);
|
||||
|
||||
//
|
||||
// Turn on async mode (off by default) and set the queue size for each async_logger.
|
||||
@ -58,7 +56,7 @@ void set_error_handler(log_err_handler);
|
||||
//
|
||||
// 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.
|
||||
// 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)
|
||||
@ -86,7 +84,7 @@ std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const
|
||||
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):
|
||||
// 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);
|
||||
@ -131,7 +129,7 @@ std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_b
|
||||
// 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...);
|
||||
std::shared_ptr<spdlog::logger> create(const std::string& logger_name, Args... 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);
|
||||
|
@ -54,7 +54,7 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment if logger name logging is not needed.
|
||||
// This will prevent spdlog from copying the logger name on each log call.
|
||||
// This will prevent spdlog from copying the logger name on each log call.
|
||||
//
|
||||
// #define SPDLOG_NO_NAME
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -156,5 +156,5 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment to customize level names (e.g. "MT TRACE")
|
||||
//
|
||||
// #define SPDLOG_LEVEL_NAMES { "MY TRACE", "MY DEBUG", "MY INFO", "MY WARNING", "MY ERROR", "MY CRITICAL", "OFF" }
|
||||
// #define SPDLOG_LEVEL_NAMES { "MY TRACE", "MY DEBUG", "MY INFO", "MY WARNING", "MY ERROR", "MY CRITICAL", "OFF" }
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1,23 +1,23 @@
|
||||
project(spdlog-utests)
|
||||
|
||||
enable_testing()
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
set(SPDLOG_UTESTS_SOURCES
|
||||
errors.cpp
|
||||
file_helper.cpp
|
||||
file_log.cpp
|
||||
format.cpp
|
||||
includes.h
|
||||
registry.cpp
|
||||
test_macros.cpp
|
||||
utils.cpp
|
||||
utils.h
|
||||
main.cpp)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SPDLOG_UTESTS_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE spdlog)
|
||||
|
||||
add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME})
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")
|
||||
project(spdlog-utests CXX)
|
||||
enable_testing()
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
set(SPDLOG_UTESTS_SOURCES
|
||||
errors.cpp
|
||||
file_helper.cpp
|
||||
file_log.cpp
|
||||
test_misc.cpp
|
||||
test_pattern_formatter
|
||||
includes.h
|
||||
registry.cpp
|
||||
test_macros.cpp
|
||||
utils.cpp
|
||||
utils.h
|
||||
main.cpp)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SPDLOG_UTESTS_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Threads::Threads)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE spdlog)
|
||||
|
||||
add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME})
|
||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")
|
||||
|
@ -1,10 +1,10 @@
|
||||
CXX ?= g++
|
||||
ifeq ($(STYLE),printf)
|
||||
$(info *** PRINTF STYLE ***)
|
||||
CXXFLAGS = -DSPDLOG_FMT_PRINTF -Wall -pedantic -std=c++11 -pthread -O2 -I../include
|
||||
CXXFLAGS = -DSPDLOG_FMT_PRINTF -Wall -pedantic -std=c++11 -pthread -O3 -I../include
|
||||
else
|
||||
$(info *** FORMAT STYLE ***)
|
||||
CXXFLAGS = -Wall -pedantic -std=c++11 -pthread -O2 -I../include
|
||||
CXXFLAGS = -Wall -pedantic -std=c++11 -pthread -O3 -I../include
|
||||
endif
|
||||
LDPFALGS = -pthread
|
||||
|
||||
|
@ -2913,7 +2913,7 @@ namespace Catch {
|
||||
for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
|
||||
if( !(*it)->matches( testCase ) )
|
||||
return false;
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3,7 +3,8 @@
|
||||
*/
|
||||
#include "includes.h"
|
||||
|
||||
using namespace spdlog::details;
|
||||
using spdlog::details::log_msg;
|
||||
using spdlog::details::file_helper;
|
||||
|
||||
static const std::string target_filename = "logs/file_helper_test.txt";
|
||||
|
||||
@ -15,7 +16,6 @@ static void write_with_helper(file_helper &helper, size_t howmany)
|
||||
helper.flush();
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("file_helper_filename", "[file_helper::filename()]]")
|
||||
{
|
||||
prepare_logdir();
|
||||
@ -25,8 +25,6 @@ TEST_CASE("file_helper_filename", "[file_helper::filename()]]")
|
||||
REQUIRE(helper.filename() == target_filename);
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE("file_helper_size", "[file_helper::size()]]")
|
||||
{
|
||||
prepare_logdir();
|
||||
@ -40,7 +38,6 @@ TEST_CASE("file_helper_size", "[file_helper::size()]]")
|
||||
REQUIRE(get_filesize(target_filename) == expected_size);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("file_helper_exists", "[file_helper::file_exists()]]")
|
||||
{
|
||||
prepare_logdir();
|
||||
@ -73,8 +70,6 @@ TEST_CASE("file_helper_reopen2", "[file_helper::reopen(false)]]")
|
||||
REQUIRE(helper.size() == expected_size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void test_split_ext(const char* fname, const char* expect_base, const char* expect_ext)
|
||||
{
|
||||
spdlog::filename_t filename(fname);
|
||||
@ -91,7 +86,6 @@ static void test_split_ext(const char* fname, const char* expect_base, const cha
|
||||
REQUIRE(ext == expected_ext);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("file_helper_split_by_extenstion", "[file_helper::split_by_extenstion()]]")
|
||||
{
|
||||
test_split_ext("mylog.txt", "mylog", ".txt");
|
||||
@ -113,6 +107,3 @@ TEST_CASE("file_helper_split_by_extenstion", "[file_helper::split_by_extenstion(
|
||||
test_split_ext(".", ".", "");
|
||||
test_split_ext("..txt", ".", ".txt");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
template<class T>
|
||||
@ -13,14 +12,9 @@ std::string log_info(const T& what, spdlog::level::level_enum logger_level = spd
|
||||
oss_logger.set_pattern("%v");
|
||||
oss_logger.info(what);
|
||||
|
||||
return oss.str().substr(0, oss.str().length() - spdlog::details::os::eol_size);
|
||||
return oss.str().substr(0, oss.str().length() - strlen(spdlog::details::os::default_eol));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TEST_CASE("basic_logging ", "[basic_logging]")
|
||||
{
|
||||
//const char
|
||||
@ -39,7 +33,6 @@ TEST_CASE("basic_logging ", "[basic_logging]")
|
||||
//REQUIRE(log_info(some_logged_class("some_val")) == "some_val");
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("log_levels", "[log_levels]")
|
||||
{
|
||||
REQUIRE(log_info("Hello", spdlog::level::err) == "");
|
||||
@ -54,3 +47,6 @@ TEST_CASE("log_levels", "[log_levels]")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
61
tests/test_pattern_formatter.cpp
Normal file
61
tests/test_pattern_formatter.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include "includes.h"
|
||||
|
||||
// log to str and return it
|
||||
static std::string log_to_str(const std::string& msg, const std::shared_ptr<spdlog::formatter>& formatter = nullptr)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
auto oss_sink = std::make_shared<spdlog::sinks::ostream_sink_mt>(oss);
|
||||
spdlog::logger oss_logger("pattern_tester", oss_sink);
|
||||
oss_logger.set_level(spdlog::level::info);
|
||||
if (formatter) oss_logger.set_formatter(formatter);
|
||||
oss_logger.info(msg);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
TEST_CASE("custom eol", "[pattern_formatter]")
|
||||
{
|
||||
std::string msg = "Hello custom eol test";
|
||||
std::string eol = ";)";
|
||||
auto formatter = std::make_shared<spdlog::pattern_formatter>("%v", spdlog::pattern_time_type::local, ";)");
|
||||
|
||||
REQUIRE(log_to_str(msg, formatter) == msg + eol);
|
||||
}
|
||||
|
||||
TEST_CASE("empty format", "[pattern_formatter]")
|
||||
{
|
||||
auto formatter = std::make_shared<spdlog::pattern_formatter>("", spdlog::pattern_time_type::local, "");
|
||||
REQUIRE(log_to_str("Some message", formatter) == "");
|
||||
}
|
||||
|
||||
TEST_CASE("empty format2", "[pattern_formatter]")
|
||||
{
|
||||
auto formatter = std::make_shared<spdlog::pattern_formatter>("", spdlog::pattern_time_type::local, "\n");
|
||||
REQUIRE(log_to_str("Some message", formatter) == "\n");
|
||||
}
|
||||
|
||||
TEST_CASE("level", "[pattern_formatter]")
|
||||
{
|
||||
auto formatter = std::make_shared<spdlog::pattern_formatter>("[%l] %v", spdlog::pattern_time_type::local, "\n");
|
||||
REQUIRE(log_to_str("Some message", formatter) == "[info] Some message\n");
|
||||
}
|
||||
|
||||
TEST_CASE("short level", "[pattern_formatter]")
|
||||
{
|
||||
auto formatter = std::make_shared<spdlog::pattern_formatter>("[%L] %v", spdlog::pattern_time_type::local, "\n");
|
||||
REQUIRE(log_to_str("Some message", formatter) == "[I] Some message\n");
|
||||
}
|
||||
|
||||
TEST_CASE("name", "[pattern_formatter]")
|
||||
{
|
||||
auto formatter = std::make_shared<spdlog::pattern_formatter>("[%n] %v", spdlog::pattern_time_type::local, "\n");
|
||||
REQUIRE(log_to_str("Some message", formatter) == "[pattern_tester] Some message\n");
|
||||
}
|
||||
|
||||
TEST_CASE("date MM/DD/YY ", "[pattern_formatter]")
|
||||
{
|
||||
auto formatter = std::make_shared<spdlog::pattern_formatter>("%D %v", spdlog::pattern_time_type::local, "\n");
|
||||
auto now_tm = spdlog::details::os::localtime();
|
||||
std::stringstream oss;
|
||||
oss << std::setfill('0') << std::setw(2) << now_tm.tm_mon + 1 << "/" << std::setw(2) << now_tm.tm_mday << "/" << std::setw(2) << (now_tm.tm_year + 1900) % 1000 << " Some message\n";
|
||||
REQUIRE(log_to_str("Some message", formatter) == oss.str());
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{59A07559-5F38-4DD6-A7FA-DB4153690B42}</ProjectGuid>
|
||||
<RootNamespace>tests</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
@ -128,10 +129,11 @@
|
||||
<ClCompile Include="errors.cpp" />
|
||||
<ClCompile Include="file_helper.cpp" />
|
||||
<ClCompile Include="file_log.cpp" />
|
||||
<ClCompile Include="format.cpp" />
|
||||
<ClCompile Include="test_misc.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="registry.cpp" />
|
||||
<ClCompile Include="test_macros.cpp" />
|
||||
<ClCompile Include="test_pattern_formatter.cpp" />
|
||||
<ClCompile Include="utils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -18,9 +18,6 @@
|
||||
<ClCompile Include="file_log.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="format.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -39,6 +36,12 @@
|
||||
<ClCompile Include="test_macros.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="test_pattern_formatter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="test_misc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="includes.h">
|
||||
|
Loading…
Reference in New Issue
Block a user