(third_party deps) fix #177, update bundled spdlog to 1.6.0
This commit is contained in:
@ -32,7 +32,7 @@ SPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg &msg)
|
||||
}
|
||||
else
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("async log: thread pool doesn't exist anymore"));
|
||||
throw_spdlog_ex("async log: thread pool doesn't exist anymore");
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ SPDLOG_INLINE void spdlog::async_logger::flush_()
|
||||
}
|
||||
else
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("async flush: thread pool doesn't exist anymore"));
|
||||
throw_spdlog_ex("async flush: thread pool doesn't exist anymore");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ namespace details {
|
||||
class thread_pool;
|
||||
}
|
||||
|
||||
class async_logger final : public std::enable_shared_from_this<async_logger>, public logger
|
||||
class SPDLOG_API async_logger final : public std::enable_shared_from_this<async_logger>, public logger
|
||||
{
|
||||
friend class details::thread_pool;
|
||||
|
||||
|
45
third_party/spdlog/include/spdlog/cfg/argv.h
vendored
Normal file
45
third_party/spdlog/include/spdlog/cfg/argv.h
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
#include <spdlog/cfg/helpers.h>
|
||||
#include <spdlog/details/registry.h>
|
||||
|
||||
//
|
||||
// Init log levels using each argv entry that starts with "SPDLOG_LEVEL="
|
||||
//
|
||||
// set all loggers to debug level:
|
||||
// example.exe "SPDLOG_LEVEL=debug"
|
||||
|
||||
// set logger1 to trace level
|
||||
// example.exe "SPDLOG_LEVEL=logger1=trace"
|
||||
|
||||
// turn off all logging except for logger1 and logger2:
|
||||
// example.exe "SPDLOG_LEVEL=off,logger1=debug,logger2=info"
|
||||
|
||||
namespace spdlog {
|
||||
namespace cfg {
|
||||
|
||||
// search for SPDLOG_LEVEL= in the args and use it to init the levels
|
||||
void load_argv_levels(int argc, const char **argv)
|
||||
{
|
||||
const std::string spdlog_level_prefix = "SPDLOG_LEVEL=";
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
std::string arg = argv[i];
|
||||
if (arg.find(spdlog_level_prefix) == 0)
|
||||
{
|
||||
auto levels_string = arg.substr(spdlog_level_prefix.size());
|
||||
auto levels = helpers::extract_levels(levels_string);
|
||||
details::registry::instance().update_levels(std::move(levels));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void load_argv_levels(int argc, char **argv)
|
||||
{
|
||||
load_argv_levels(argc, const_cast<const char **>(argv));
|
||||
}
|
||||
|
||||
} // namespace cfg
|
||||
} // namespace spdlog
|
36
third_party/spdlog/include/spdlog/cfg/env.h
vendored
Normal file
36
third_party/spdlog/include/spdlog/cfg/env.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
#include <spdlog/cfg/helpers.h>
|
||||
#include <spdlog/details/registry.h>
|
||||
#include <spdlog/details/os.h>
|
||||
|
||||
//
|
||||
// Init levels and patterns from env variables SPDLOG_LEVEL
|
||||
// Inspired from Rust's "env_logger" crate (https://crates.io/crates/env_logger).
|
||||
// Note - fallback to "info" level on unrecognized levels
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// set global level to debug:
|
||||
// export SPDLOG_LEVEL=debug
|
||||
//
|
||||
// turn off all logging except for logger1:
|
||||
// export SPDLOG_LEVEL="off,logger1=debug"
|
||||
//
|
||||
|
||||
// turn off all logging except for logger1 and logger2:
|
||||
// export SPDLOG_LEVEL="off,logger1=debug,logger2=info"
|
||||
|
||||
namespace spdlog {
|
||||
namespace cfg {
|
||||
void load_env_levels()
|
||||
{
|
||||
auto env_val = details::os::getenv("SPDLOG_LEVEL");
|
||||
auto levels = helpers::extract_levels(env_val);
|
||||
details::registry::instance().update_levels(std::move(levels));
|
||||
}
|
||||
|
||||
} // namespace cfg
|
||||
} // namespace spdlog
|
103
third_party/spdlog/include/spdlog/cfg/helpers-inl.h
vendored
Normal file
103
third_party/spdlog/include/spdlog/cfg/helpers-inl.h
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_HEADER_ONLY
|
||||
#include <spdlog/cfg/helpers.h>
|
||||
#endif
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/details/os.h>
|
||||
#include <spdlog/details/registry.h>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <sstream>
|
||||
|
||||
namespace spdlog {
|
||||
namespace cfg {
|
||||
namespace helpers {
|
||||
|
||||
// inplace convert to lowercase
|
||||
inline std::string &to_lower_(std::string &str)
|
||||
{
|
||||
std::transform(
|
||||
str.begin(), str.end(), str.begin(), [](char ch) { return static_cast<char>((ch >= 'A' && ch <= 'Z') ? ch + ('a' - 'A') : ch); });
|
||||
return str;
|
||||
}
|
||||
|
||||
// inplace trim spaces
|
||||
inline std::string &trim_(std::string &str)
|
||||
{
|
||||
const char *spaces = " \n\r\t";
|
||||
str.erase(str.find_last_not_of(spaces) + 1);
|
||||
str.erase(0, str.find_first_not_of(spaces));
|
||||
return str;
|
||||
}
|
||||
|
||||
// return (name,value) trimmed pair from given "name=value" string.
|
||||
// return empty string on missing parts
|
||||
// "key=val" => ("key", "val")
|
||||
// " key = val " => ("key", "val")
|
||||
// "key=" => ("key", "")
|
||||
// "val" => ("", "val")
|
||||
|
||||
inline std::pair<std::string, std::string> extract_kv_(char sep, const std::string &str)
|
||||
{
|
||||
auto n = str.find(sep);
|
||||
std::string k, v;
|
||||
if (n == std::string::npos)
|
||||
{
|
||||
v = str;
|
||||
}
|
||||
else
|
||||
{
|
||||
k = str.substr(0, n);
|
||||
v = str.substr(n + 1);
|
||||
}
|
||||
return std::make_pair(trim_(k), trim_(v));
|
||||
}
|
||||
|
||||
// return vector of key/value pairs from sequence of "K1=V1,K2=V2,.."
|
||||
// "a=AAA,b=BBB,c=CCC,.." => {("a","AAA"),("b","BBB"),("c", "CCC"),...}
|
||||
inline std::unordered_map<std::string, std::string> extract_key_vals_(const std::string &str)
|
||||
{
|
||||
std::string token;
|
||||
std::istringstream token_stream(str);
|
||||
std::unordered_map<std::string, std::string> rv{};
|
||||
while (std::getline(token_stream, token, ','))
|
||||
{
|
||||
if (token.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
auto kv = extract_kv_('=', token);
|
||||
rv[kv.first] = kv.second;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
SPDLOG_INLINE log_levels extract_levels(const std::string &input)
|
||||
{
|
||||
auto key_vals = extract_key_vals_(input);
|
||||
log_levels rv;
|
||||
|
||||
for (auto &name_level : key_vals)
|
||||
{
|
||||
auto &logger_name = name_level.first;
|
||||
auto level_name = to_lower_(name_level.second);
|
||||
auto level = level::from_str(level_name);
|
||||
// fallback to "info" if unrecognized level name
|
||||
if (level == level::off && level_name != "off")
|
||||
{
|
||||
level = level::info;
|
||||
}
|
||||
rv.set(logger_name, level);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace helpers
|
||||
} // namespace cfg
|
||||
} // namespace spdlog
|
28
third_party/spdlog/include/spdlog/cfg/helpers.h
vendored
Normal file
28
third_party/spdlog/include/spdlog/cfg/helpers.h
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spdlog/cfg/log_levels.h>
|
||||
|
||||
namespace spdlog {
|
||||
namespace cfg {
|
||||
namespace helpers {
|
||||
//
|
||||
// Init levels from given string
|
||||
//
|
||||
// Examples:
|
||||
//
|
||||
// set global level to debug: "debug"
|
||||
// turn off all logging except for logger1: "off,logger1=debug"
|
||||
// turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info"
|
||||
//
|
||||
SPDLOG_API log_levels extract_levels(const std::string &txt);
|
||||
} // namespace helpers
|
||||
|
||||
} // namespace cfg
|
||||
} // namespace spdlog
|
||||
|
||||
#ifdef SPDLOG_HEADER_ONLY
|
||||
#include "helpers-inl.h"
|
||||
#endif // SPDLOG_HEADER_ONLY
|
47
third_party/spdlog/include/spdlog/cfg/log_levels.h
vendored
Normal file
47
third_party/spdlog/include/spdlog/cfg/log_levels.h
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spdlog/common.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace spdlog {
|
||||
namespace cfg {
|
||||
class log_levels
|
||||
{
|
||||
std::unordered_map<std::string, spdlog::level::level_enum> levels_;
|
||||
spdlog::level::level_enum default_level_ = level::info;
|
||||
|
||||
public:
|
||||
void set(const std::string &logger_name, level::level_enum lvl)
|
||||
{
|
||||
if (logger_name.empty())
|
||||
{
|
||||
default_level_ = lvl;
|
||||
}
|
||||
else
|
||||
{
|
||||
levels_[logger_name] = lvl;
|
||||
}
|
||||
}
|
||||
|
||||
void set_default(level::level_enum lvl)
|
||||
{
|
||||
default_level_ = lvl;
|
||||
}
|
||||
|
||||
level::level_enum get(const std::string &logger_name)
|
||||
{
|
||||
auto it = levels_.find(logger_name);
|
||||
return it != levels_.end() ? it->second : default_level_;
|
||||
}
|
||||
|
||||
level::level_enum default_level()
|
||||
{
|
||||
return default_level_;
|
||||
}
|
||||
};
|
||||
} // namespace cfg
|
||||
} // namespace spdlog
|
19
third_party/spdlog/include/spdlog/common-inl.h
vendored
19
third_party/spdlog/include/spdlog/common-inl.h
vendored
@ -34,6 +34,15 @@ SPDLOG_INLINE spdlog::level::level_enum from_str(const std::string &name) SPDLOG
|
||||
}
|
||||
level++;
|
||||
}
|
||||
// check also for "warn" and "err" before giving up..
|
||||
if (name == "warn")
|
||||
{
|
||||
return level::warn;
|
||||
}
|
||||
if (name == "err")
|
||||
{
|
||||
return level::err;
|
||||
}
|
||||
return level::off;
|
||||
}
|
||||
} // namespace level
|
||||
@ -54,4 +63,14 @@ SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT
|
||||
return msg_.c_str();
|
||||
}
|
||||
|
||||
SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex(msg, last_errno));
|
||||
}
|
||||
|
||||
SPDLOG_INLINE void throw_spdlog_ex(std::string msg)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex(std::move(msg)));
|
||||
}
|
||||
|
||||
} // namespace spdlog
|
||||
|
35
third_party/spdlog/include/spdlog/common.h
vendored
35
third_party/spdlog/include/spdlog/common.h
vendored
@ -15,22 +15,20 @@
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX // prevent windows redefining min/max
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef SPDLOG_COMPILED_LIB
|
||||
#undef SPDLOG_HEADER_ONLY
|
||||
#if defined(_WIN32) && defined(SPDLOG_SHARED_LIB)
|
||||
#ifdef spdlog_EXPORTS
|
||||
#define SPDLOG_API __declspec(dllexport)
|
||||
#else
|
||||
#define SPDLOG_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define SPDLOG_API
|
||||
#endif
|
||||
#define SPDLOG_INLINE
|
||||
#else
|
||||
#define SPDLOG_API
|
||||
#define SPDLOG_HEADER_ONLY
|
||||
#define SPDLOG_INLINE inline
|
||||
#endif
|
||||
@ -147,6 +145,7 @@ enum level_enum
|
||||
err = SPDLOG_LEVEL_ERROR,
|
||||
critical = SPDLOG_LEVEL_CRITICAL,
|
||||
off = SPDLOG_LEVEL_OFF,
|
||||
n_levels
|
||||
};
|
||||
|
||||
#if !defined(SPDLOG_LEVEL_NAMES)
|
||||
@ -164,9 +163,9 @@ enum level_enum
|
||||
}
|
||||
#endif
|
||||
|
||||
string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
|
||||
const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
|
||||
spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT;
|
||||
|
||||
using level_hasher = std::hash<int>;
|
||||
} // namespace level
|
||||
@ -194,7 +193,7 @@ enum class pattern_time_type
|
||||
//
|
||||
// Log exception
|
||||
//
|
||||
class spdlog_ex : public std::exception
|
||||
class SPDLOG_API spdlog_ex : public std::exception
|
||||
{
|
||||
public:
|
||||
explicit spdlog_ex(std::string msg);
|
||||
@ -205,6 +204,9 @@ private:
|
||||
std::string msg_;
|
||||
};
|
||||
|
||||
void throw_spdlog_ex(const std::string &msg, int last_errno);
|
||||
void throw_spdlog_ex(std::string msg);
|
||||
|
||||
struct source_loc
|
||||
{
|
||||
SPDLOG_CONSTEXPR source_loc() = default;
|
||||
@ -237,7 +239,6 @@ std::unique_ptr<T> make_unique(Args &&... args)
|
||||
}
|
||||
#endif
|
||||
} // namespace details
|
||||
|
||||
} // namespace spdlog
|
||||
|
||||
#ifdef SPDLOG_HEADER_ONLY
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
class backtracer
|
||||
class SPDLOG_API backtracer
|
||||
{
|
||||
mutable std::mutex mutex_;
|
||||
std::atomic<bool> enabled_{false};
|
||||
|
@ -43,14 +43,14 @@ SPDLOG_INLINE void file_helper::open(const filename_t &fname, bool truncate)
|
||||
details::os::sleep_for_millis(open_interval_);
|
||||
}
|
||||
|
||||
SPDLOG_THROW(spdlog_ex("Failed opening file " + os::filename_to_str(filename_) + " for writing", errno));
|
||||
throw_spdlog_ex("Failed opening file " + os::filename_to_str(filename_) + " for writing", errno);
|
||||
}
|
||||
|
||||
SPDLOG_INLINE void file_helper::reopen(bool truncate)
|
||||
{
|
||||
if (filename_.empty())
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("Failed re opening file - was not opened before"));
|
||||
throw_spdlog_ex("Failed re opening file - was not opened before");
|
||||
}
|
||||
this->open(filename_, truncate);
|
||||
}
|
||||
@ -75,7 +75,7 @@ SPDLOG_INLINE void file_helper::write(const memory_buf_t &buf)
|
||||
auto data = buf.data();
|
||||
if (std::fwrite(data, 1, msg_size, fd_) != msg_size)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno));
|
||||
throw_spdlog_ex("Failed writing to file " + os::filename_to_str(filename_), errno);
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ SPDLOG_INLINE size_t file_helper::size() const
|
||||
{
|
||||
if (fd_ == nullptr)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(filename_)));
|
||||
throw_spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(filename_));
|
||||
}
|
||||
return os::filesize(fd_);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ namespace details {
|
||||
// When failing to open a file, retry several times(5) with a delay interval(10 ms).
|
||||
// Throw spdlog_ex exception on errors.
|
||||
|
||||
class file_helper
|
||||
class SPDLOG_API file_helper
|
||||
{
|
||||
public:
|
||||
explicit file_helper() = default;
|
||||
|
@ -20,10 +20,7 @@ inline spdlog::string_view_t to_string_view(const memory_buf_t &buf) SPDLOG_NOEX
|
||||
inline void append_string_view(spdlog::string_view_t view, memory_buf_t &dest)
|
||||
{
|
||||
auto *buf_ptr = view.data();
|
||||
if (buf_ptr != nullptr)
|
||||
{
|
||||
dest.append(buf_ptr, buf_ptr + view.size());
|
||||
}
|
||||
dest.append(buf_ptr, buf_ptr + view.size());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@ -34,10 +31,10 @@ inline void append_int(T n, memory_buf_t &dest)
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline unsigned count_digits(T n)
|
||||
inline unsigned int count_digits(T n)
|
||||
{
|
||||
using count_type = typename std::conditional<(sizeof(T) > sizeof(uint32_t)), uint64_t, uint32_t>::type;
|
||||
return static_cast<unsigned>(fmt::internal::count_digits(static_cast<count_type>(n)));
|
||||
return static_cast<unsigned int>(fmt::internal::count_digits(static_cast<count_type>(n)));
|
||||
}
|
||||
|
||||
inline void pad2(int n, memory_buf_t &dest)
|
||||
@ -66,11 +63,9 @@ template<typename T>
|
||||
inline void pad_uint(T n, unsigned int width, memory_buf_t &dest)
|
||||
{
|
||||
static_assert(std::is_unsigned<T>::value, "pad_uint must get unsigned T");
|
||||
auto digits = count_digits(n);
|
||||
if (width > digits)
|
||||
for (auto digits = count_digits(n); digits < width; digits++)
|
||||
{
|
||||
const char *zeroes = "0000000000000000000";
|
||||
dest.append(zeroes, zeroes + width - digits);
|
||||
dest.push_back('0');
|
||||
}
|
||||
append_int(n, dest);
|
||||
}
|
||||
@ -78,7 +73,18 @@ inline void pad_uint(T n, unsigned int width, memory_buf_t &dest)
|
||||
template<typename T>
|
||||
inline void pad3(T n, memory_buf_t &dest)
|
||||
{
|
||||
pad_uint(n, 3, dest);
|
||||
static_assert(std::is_unsigned<T>::value, "pad3 must get unsigned T");
|
||||
if(n < 1000)
|
||||
{
|
||||
dest.push_back(static_cast<char>(n / 100 + '0'));
|
||||
n = n % 100;
|
||||
dest.push_back(static_cast<char>((n / 10) + '0'));
|
||||
dest.push_back(static_cast<char>((n % 10) + '0'));
|
||||
}
|
||||
else
|
||||
{
|
||||
append_int(n, dest);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
struct log_msg
|
||||
struct SPDLOG_API log_msg
|
||||
{
|
||||
log_msg() = default;
|
||||
log_msg(source_loc loc, string_view_t logger_name, level::level_enum lvl, string_view_t msg);
|
||||
|
@ -11,7 +11,7 @@ namespace details {
|
||||
// Extend log_msg with internal buffer to store its payload.
|
||||
// THis is needed since log_msg holds string_views that points to stack data.
|
||||
|
||||
class log_msg_buffer : public log_msg
|
||||
class SPDLOG_API log_msg_buffer : public log_msg
|
||||
{
|
||||
memory_buf_t buffer;
|
||||
void update_string_views();
|
||||
|
@ -23,16 +23,9 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX // prevent windows redefining min/max
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <io.h> // _get_osfhandle and _isatty support
|
||||
#include <process.h> // _get_pid support
|
||||
#include <windows.h>
|
||||
#include <spdlog/details/windows_include.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <share.h>
|
||||
@ -126,23 +119,6 @@ SPDLOG_INLINE std::tm gmtime() SPDLOG_NOEXCEPT
|
||||
return gmtime(now_t);
|
||||
}
|
||||
|
||||
#ifdef SPDLOG_PREVENT_CHILD_FD
|
||||
SPDLOG_INLINE void prevent_child_fd(FILE *f)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
auto file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(::_fileno(f)));
|
||||
if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0))
|
||||
SPDLOG_THROW(spdlog_ex("SetHandleInformation failed", errno));
|
||||
#else
|
||||
auto fd = ::fileno(f);
|
||||
if (::fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("fcntl with FD_CLOEXEC failed", errno));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif // SPDLOG_PREVENT_CHILD_FD
|
||||
|
||||
// fopen_s on non windows for writing
|
||||
SPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode)
|
||||
{
|
||||
@ -152,17 +128,35 @@ SPDLOG_INLINE bool fopen_s(FILE **fp, const filename_t &filename, const filename
|
||||
#else
|
||||
*fp = ::_fsopen((filename.c_str()), mode.c_str(), _SH_DENYNO);
|
||||
#endif
|
||||
#else // unix
|
||||
*fp = ::fopen((filename.c_str()), mode.c_str());
|
||||
#endif
|
||||
|
||||
#ifdef SPDLOG_PREVENT_CHILD_FD
|
||||
// prevent child processes from inheriting log file descriptors
|
||||
#if defined(SPDLOG_PREVENT_CHILD_FD)
|
||||
if (*fp != nullptr)
|
||||
{
|
||||
prevent_child_fd(*fp);
|
||||
auto file_handle = reinterpret_cast<HANDLE>(_get_osfhandle(::_fileno(*fp)));
|
||||
if (!::SetHandleInformation(file_handle, HANDLE_FLAG_INHERIT, 0))
|
||||
{
|
||||
::fclose(*fp);
|
||||
*fp = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else // unix
|
||||
#if defined(SPDLOG_PREVENT_CHILD_FD)
|
||||
const int mode_flag = mode == SPDLOG_FILENAME_T("ab") ? O_APPEND : O_TRUNC;
|
||||
const int fd = ::open((filename.c_str()), O_CREAT | O_WRONLY | O_CLOEXEC | mode_flag, mode_t(0644));
|
||||
if (fd == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*fp = ::fdopen(fd, mode.c_str());
|
||||
if (*fp == nullptr)
|
||||
{
|
||||
::close(fd);
|
||||
}
|
||||
#else
|
||||
*fp = ::fopen((filename.c_str()), mode.c_str());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return *fp == nullptr;
|
||||
}
|
||||
|
||||
@ -210,7 +204,7 @@ SPDLOG_INLINE size_t filesize(FILE *f)
|
||||
{
|
||||
if (f == nullptr)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("Failed getting file size. fd is null"));
|
||||
throw_spdlog_ex("Failed getting file size. fd is null");
|
||||
}
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
int fd = ::_fileno(f);
|
||||
@ -251,7 +245,8 @@ SPDLOG_INLINE size_t filesize(FILE *f)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
SPDLOG_THROW(spdlog_ex("Failed getting file size from fd", errno));
|
||||
throw_spdlog_ex("Failed getting file size from fd", errno);
|
||||
return 0; // will not be reached.
|
||||
}
|
||||
|
||||
// Return utc offset in minutes or throw spdlog_ex on failure
|
||||
@ -267,7 +262,7 @@ SPDLOG_INLINE int utc_minutes_offset(const std::tm &tm)
|
||||
auto rv = ::GetDynamicTimeZoneInformation(&tzinfo);
|
||||
#endif
|
||||
if (rv == TIME_ZONE_ID_INVALID)
|
||||
SPDLOG_THROW(spdlog::spdlog_ex("Failed getting timezone info. ", errno));
|
||||
throw_spdlog_ex("Failed getting timezone info. ", errno);
|
||||
|
||||
int offset = -tzinfo.Bias;
|
||||
if (tm.tm_isdst)
|
||||
@ -396,13 +391,13 @@ SPDLOG_INLINE int pid() SPDLOG_NOEXCEPT
|
||||
}
|
||||
|
||||
// Determine if the terminal supports colors
|
||||
// Source: https://github.com/agauniyal/rang/
|
||||
// Based on: https://github.com/agauniyal/rang/
|
||||
SPDLOG_INLINE bool is_color_terminal() SPDLOG_NOEXCEPT
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return true;
|
||||
#else
|
||||
static constexpr std::array<const char *, 14> Terms = {
|
||||
static constexpr std::array<const char *, 14> terms = {
|
||||
{"ansi", "color", "console", "cygwin", "gnome", "konsole", "kterm", "linux", "msys", "putty", "rxvt", "screen", "vt100", "xterm"}};
|
||||
|
||||
const char *env_p = std::getenv("TERM");
|
||||
@ -412,7 +407,7 @@ SPDLOG_INLINE bool is_color_terminal() SPDLOG_NOEXCEPT
|
||||
}
|
||||
|
||||
static const bool result =
|
||||
std::any_of(std::begin(Terms), std::end(Terms), [&](const char *term) { return std::strstr(env_p, term) != nullptr; });
|
||||
std::any_of(terms.begin(), terms.end(), [&](const char *term) { return std::strstr(env_p, term) != nullptr; });
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
@ -434,7 +429,7 @@ SPDLOG_INLINE void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target)
|
||||
{
|
||||
if (wstr.size() > static_cast<size_t>((std::numeric_limits<int>::max)()))
|
||||
{
|
||||
SPDLOG_THROW(spdlog::spdlog_ex("UTF-16 string is too big to be converted to UTF-8"));
|
||||
throw_spdlog_ex("UTF-16 string is too big to be converted to UTF-8");
|
||||
}
|
||||
|
||||
int wstr_size = static_cast<int>(wstr.size());
|
||||
@ -462,7 +457,7 @@ SPDLOG_INLINE void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target)
|
||||
}
|
||||
}
|
||||
|
||||
SPDLOG_THROW(spdlog::spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError())));
|
||||
throw_spdlog_ex(fmt::format("WideCharToMultiByte failed. Last error: {}", ::GetLastError()));
|
||||
}
|
||||
#endif // (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
|
||||
|
||||
@ -536,6 +531,24 @@ SPDLOG_INLINE filename_t dir_name(filename_t path)
|
||||
return pos != filename_t::npos ? path.substr(0, pos) : filename_t{};
|
||||
}
|
||||
|
||||
std::string SPDLOG_INLINE getenv(const char *field)
|
||||
{
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(__cplusplus_winrt)
|
||||
return std::string{}; // not supported under uwp
|
||||
#else
|
||||
size_t len = 0;
|
||||
char buf[128];
|
||||
bool ok = ::getenv_s(&len, buf, sizeof(buf), field) == 0;
|
||||
return ok ? buf : std::string{};
|
||||
#endif
|
||||
#else // revert to getenv
|
||||
char *buf = ::getenv(field);
|
||||
return buf ? buf : std::string{};
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace os
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
||||
|
50
third_party/spdlog/include/spdlog/details/os.h
vendored
50
third_party/spdlog/include/spdlog/details/os.h
vendored
@ -10,15 +10,15 @@ namespace spdlog {
|
||||
namespace details {
|
||||
namespace os {
|
||||
|
||||
spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API spdlog::log_clock::time_point now() SPDLOG_NOEXCEPT;
|
||||
|
||||
std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API std::tm localtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT;
|
||||
|
||||
std::tm localtime() SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API std::tm localtime() SPDLOG_NOEXCEPT;
|
||||
|
||||
std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API std::tm gmtime(const std::time_t &time_tt) SPDLOG_NOEXCEPT;
|
||||
|
||||
std::tm gmtime() SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API std::tm gmtime() SPDLOG_NOEXCEPT;
|
||||
|
||||
// eol definition
|
||||
#if !defined(SPDLOG_EOL)
|
||||
@ -38,54 +38,50 @@ static const char folder_sep = '\\';
|
||||
SPDLOG_CONSTEXPR static const char folder_sep = '/';
|
||||
#endif
|
||||
|
||||
#ifdef SPDLOG_PREVENT_CHILD_FD
|
||||
void prevent_child_fd(FILE *f);
|
||||
#endif
|
||||
|
||||
// fopen_s on non windows for writing
|
||||
bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode);
|
||||
SPDLOG_API bool fopen_s(FILE **fp, const filename_t &filename, const filename_t &mode);
|
||||
|
||||
// Remove filename. return 0 on success
|
||||
int remove(const filename_t &filename) SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API int remove(const filename_t &filename) SPDLOG_NOEXCEPT;
|
||||
|
||||
// Remove file if exists. return 0 on success
|
||||
// Note: Non atomic (might return failure to delete if concurrently deleted by other process/thread)
|
||||
int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API int remove_if_exists(const filename_t &filename) SPDLOG_NOEXCEPT;
|
||||
|
||||
int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API int rename(const filename_t &filename1, const filename_t &filename2) SPDLOG_NOEXCEPT;
|
||||
|
||||
// Return if file exists.
|
||||
bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API bool path_exists(const filename_t &filename) SPDLOG_NOEXCEPT;
|
||||
|
||||
// Return file size according to open FILE* object
|
||||
size_t filesize(FILE *f);
|
||||
SPDLOG_API size_t filesize(FILE *f);
|
||||
|
||||
// Return utc offset in minutes or throw spdlog_ex on failure
|
||||
int utc_minutes_offset(const std::tm &tm = details::os::localtime());
|
||||
SPDLOG_API int utc_minutes_offset(const std::tm &tm = details::os::localtime());
|
||||
|
||||
// Return current thread id as size_t
|
||||
// It exists because the std::this_thread::get_id() is much slower(especially
|
||||
// under VS 2013)
|
||||
size_t _thread_id() SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API size_t _thread_id() SPDLOG_NOEXCEPT;
|
||||
|
||||
// Return current thread id as size_t (from thread local storage)
|
||||
size_t thread_id() SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API size_t thread_id() SPDLOG_NOEXCEPT;
|
||||
|
||||
// This is avoid msvc issue in sleep_for that happens if the clock changes.
|
||||
// See https://github.com/gabime/spdlog/issues/609
|
||||
void sleep_for_millis(int milliseconds) SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API void sleep_for_millis(int milliseconds) SPDLOG_NOEXCEPT;
|
||||
|
||||
std::string filename_to_str(const filename_t &filename);
|
||||
SPDLOG_API std::string filename_to_str(const filename_t &filename);
|
||||
|
||||
int pid() SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API int pid() SPDLOG_NOEXCEPT;
|
||||
|
||||
// Determine if the terminal supports colors
|
||||
// Source: https://github.com/agauniyal/rang/
|
||||
bool is_color_terminal() SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API bool is_color_terminal() SPDLOG_NOEXCEPT;
|
||||
|
||||
// Determine if the terminal attached
|
||||
// Source: https://github.com/agauniyal/rang/
|
||||
bool in_terminal(FILE *file) SPDLOG_NOEXCEPT;
|
||||
SPDLOG_API bool in_terminal(FILE *file) SPDLOG_NOEXCEPT;
|
||||
|
||||
#if (defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT) || defined(SPDLOG_WCHAR_FILENAMES)) && defined(_WIN32)
|
||||
void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target);
|
||||
@ -96,11 +92,15 @@ void wstr_to_utf8buf(wstring_view_t wstr, memory_buf_t &target);
|
||||
// "abc/" => "abc"
|
||||
// "abc" => ""
|
||||
// "abc///" => "abc//"
|
||||
filename_t dir_name(filename_t path);
|
||||
SPDLOG_API filename_t dir_name(filename_t path);
|
||||
|
||||
// Create a dir from the given path.
|
||||
// Return true if succeeded or if this dir already exists.
|
||||
bool create_dir(filename_t path);
|
||||
SPDLOG_API bool create_dir(filename_t path);
|
||||
|
||||
// non thread safe, cross platform getenv/getenv_s
|
||||
// return empty string if field not found
|
||||
SPDLOG_API std::string getenv(const char *field);
|
||||
|
||||
} // namespace os
|
||||
} // namespace details
|
||||
|
@ -17,7 +17,7 @@
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
|
||||
class periodic_worker
|
||||
class SPDLOG_API periodic_worker
|
||||
{
|
||||
public:
|
||||
periodic_worker(const std::function<void()> &callback_fun, std::chrono::seconds interval);
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/details/periodic_worker.h>
|
||||
#include <spdlog/logger.h>
|
||||
#include <spdlog/details/pattern_formatter.h>
|
||||
#include <spdlog/pattern_formatter.h>
|
||||
|
||||
#ifndef SPDLOG_DISABLE_DEFAULT_LOGGER
|
||||
// support for the default stdout color logger
|
||||
@ -48,6 +48,9 @@ SPDLOG_INLINE registry::registry()
|
||||
|
||||
#endif // SPDLOG_DISABLE_DEFAULT_LOGGER
|
||||
}
|
||||
|
||||
SPDLOG_INLINE registry::~registry() = default;
|
||||
|
||||
SPDLOG_INLINE void registry::register_logger(std::shared_ptr<logger> new_logger)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(logger_map_mutex_);
|
||||
@ -64,7 +67,7 @@ SPDLOG_INLINE void registry::initialize_logger(std::shared_ptr<logger> new_logge
|
||||
new_logger->set_error_handler(err_handler_);
|
||||
}
|
||||
|
||||
new_logger->set_level(level_);
|
||||
new_logger->set_level(levels_.get(new_logger->name()));
|
||||
new_logger->flush_on(flush_level_);
|
||||
|
||||
if (backtrace_n_messages_ > 0)
|
||||
@ -168,7 +171,7 @@ SPDLOG_INLINE void registry::set_level(level::level_enum log_level)
|
||||
{
|
||||
l.second->set_level(log_level);
|
||||
}
|
||||
level_ = log_level;
|
||||
levels_.set_default(log_level);
|
||||
}
|
||||
|
||||
SPDLOG_INLINE void registry::flush_on(level::level_enum log_level)
|
||||
@ -184,7 +187,7 @@ SPDLOG_INLINE void registry::flush_on(level::level_enum log_level)
|
||||
SPDLOG_INLINE void registry::flush_every(std::chrono::seconds interval)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(flusher_mutex_);
|
||||
std::function<void()> clbk = std::bind(®istry::flush_all, this);
|
||||
auto clbk = [this]() { this->flush_all(); };
|
||||
periodic_flusher_ = details::make_unique<periodic_worker>(clbk, interval);
|
||||
}
|
||||
|
||||
@ -260,6 +263,17 @@ SPDLOG_INLINE void registry::set_automatic_registration(bool automatic_registrat
|
||||
automatic_registration_ = automatic_registration;
|
||||
}
|
||||
|
||||
SPDLOG_INLINE void registry::update_levels(cfg::log_levels levels)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(logger_map_mutex_);
|
||||
levels_ = std::move(levels);
|
||||
for (auto &l : loggers_)
|
||||
{
|
||||
auto &logger = l.second;
|
||||
logger->set_level(levels_.get(logger->name()));
|
||||
}
|
||||
}
|
||||
|
||||
SPDLOG_INLINE registry ®istry::instance()
|
||||
{
|
||||
static registry s_instance;
|
||||
@ -270,7 +284,7 @@ SPDLOG_INLINE void registry::throw_if_exists_(const std::string &logger_name)
|
||||
{
|
||||
if (loggers_.find(logger_name) != loggers_.end())
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("logger with name '" + logger_name + "' already exists"));
|
||||
throw_spdlog_ex("logger with name '" + logger_name + "' already exists");
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,5 +294,6 @@ SPDLOG_INLINE void registry::register_logger_(std::shared_ptr<logger> new_logger
|
||||
throw_if_exists_(logger_name);
|
||||
loggers_[logger_name] = std::move(new_logger);
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
||||
|
@ -9,6 +9,7 @@
|
||||
// This class is thread safe
|
||||
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/cfg/log_levels.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
@ -24,7 +25,7 @@ namespace details {
|
||||
class thread_pool;
|
||||
class periodic_worker;
|
||||
|
||||
class registry
|
||||
class SPDLOG_API registry
|
||||
{
|
||||
public:
|
||||
registry(const registry &) = delete;
|
||||
@ -79,19 +80,21 @@ public:
|
||||
|
||||
void set_automatic_registration(bool automatic_registration);
|
||||
|
||||
void update_levels(cfg::log_levels levels);
|
||||
|
||||
static registry &instance();
|
||||
|
||||
private:
|
||||
registry();
|
||||
~registry() = default;
|
||||
~registry();
|
||||
|
||||
void throw_if_exists_(const std::string &logger_name);
|
||||
void register_logger_(std::shared_ptr<logger> new_logger);
|
||||
std::mutex logger_map_mutex_, flusher_mutex_;
|
||||
std::recursive_mutex tp_mutex_;
|
||||
std::unordered_map<std::string, std::shared_ptr<logger>> loggers_;
|
||||
cfg::log_levels levels_;
|
||||
std::unique_ptr<formatter> formatter_;
|
||||
level::level_enum level_ = level::info;
|
||||
level::level_enum flush_level_ = level::off;
|
||||
void (*err_handler_)(const std::string &msg);
|
||||
std::shared_ptr<thread_pool> tp_;
|
||||
|
175
third_party/spdlog/include/spdlog/details/tcp_client-windows.h
vendored
Normal file
175
third_party/spdlog/include/spdlog/details/tcp_client-windows.h
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
// tcp client helper
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/details/os.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
#pragma comment(lib, "Mswsock.lib")
|
||||
#pragma comment(lib, "AdvApi32.lib")
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
class tcp_client
|
||||
{
|
||||
SOCKET socket_ = INVALID_SOCKET;
|
||||
|
||||
static bool winsock_initialized_()
|
||||
{
|
||||
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (s == INVALID_SOCKET)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
closesocket(s);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void init_winsock_()
|
||||
{
|
||||
WSADATA wsaData;
|
||||
auto rv = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (rv != 0)
|
||||
{
|
||||
throw_winsock_error_("WSAStartup failed", ::WSAGetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
static void throw_winsock_error_(const std::string &msg, int last_error)
|
||||
{
|
||||
char buf[512];
|
||||
::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_error,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, (sizeof(buf) / sizeof(char)), NULL);
|
||||
|
||||
throw_spdlog_ex(fmt::format("tcp_sink - {}: {}", msg, buf));
|
||||
}
|
||||
|
||||
public:
|
||||
bool is_connected() const
|
||||
{
|
||||
return socket_ != INVALID_SOCKET;
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
::closesocket(socket_);
|
||||
socket_ = INVALID_SOCKET;
|
||||
WSACleanup();
|
||||
}
|
||||
|
||||
SOCKET fd() const
|
||||
{
|
||||
return socket_;
|
||||
}
|
||||
|
||||
~tcp_client()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
// try to connect or throw on failure
|
||||
void connect(const std::string &host, int port)
|
||||
{
|
||||
// initialize winsock if needed
|
||||
if (!winsock_initialized_())
|
||||
{
|
||||
init_winsock_();
|
||||
}
|
||||
|
||||
if (is_connected())
|
||||
{
|
||||
close();
|
||||
}
|
||||
struct addrinfo hints
|
||||
{};
|
||||
ZeroMemory(&hints, sizeof(hints));
|
||||
|
||||
hints.ai_family = AF_INET; // IPv4
|
||||
hints.ai_socktype = SOCK_STREAM; // TCP
|
||||
hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value
|
||||
hints.ai_protocol = 0;
|
||||
|
||||
auto port_str = std::to_string(port);
|
||||
struct addrinfo *addrinfo_result;
|
||||
auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result);
|
||||
int last_error = 0;
|
||||
if (rv != 0)
|
||||
{
|
||||
last_error = ::WSAGetLastError();
|
||||
WSACleanup();
|
||||
throw_winsock_error_("getaddrinfo failed", last_error);
|
||||
}
|
||||
|
||||
// Try each address until we successfully connect(2).
|
||||
|
||||
for (auto *rp = addrinfo_result; rp != nullptr; rp = rp->ai_next)
|
||||
{
|
||||
socket_ = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||
if (socket_ == INVALID_SOCKET)
|
||||
{
|
||||
last_error = ::WSAGetLastError();
|
||||
WSACleanup();
|
||||
continue;
|
||||
}
|
||||
if (::connect(socket_, rp->ai_addr, (int)rp->ai_addrlen) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_error = ::WSAGetLastError();
|
||||
close();
|
||||
}
|
||||
}
|
||||
::freeaddrinfo(addrinfo_result);
|
||||
if (socket_ == INVALID_SOCKET)
|
||||
{
|
||||
WSACleanup();
|
||||
throw_winsock_error_("connect failed", last_error);
|
||||
}
|
||||
|
||||
// set TCP_NODELAY
|
||||
int enable_flag = 1;
|
||||
::setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (char *)&enable_flag, sizeof(enable_flag));
|
||||
}
|
||||
|
||||
// Send exactly n_bytes of the given data.
|
||||
// On error close the connection and throw.
|
||||
void send(const char *data, size_t n_bytes)
|
||||
{
|
||||
size_t bytes_sent = 0;
|
||||
while (bytes_sent < n_bytes)
|
||||
{
|
||||
const int send_flags = 0;
|
||||
auto write_result = ::send(socket_, data + bytes_sent, (int)(n_bytes - bytes_sent), send_flags);
|
||||
if (write_result == SOCKET_ERROR)
|
||||
{
|
||||
int last_error = ::WSAGetLastError();
|
||||
close();
|
||||
throw_winsock_error_("send failed", last_error);
|
||||
}
|
||||
|
||||
if (write_result == 0) // (probably should not happen but in any case..)
|
||||
{
|
||||
break;
|
||||
}
|
||||
bytes_sent += static_cast<size_t>(write_result);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
145
third_party/spdlog/include/spdlog/details/tcp_client.h
vendored
Normal file
145
third_party/spdlog/include/spdlog/details/tcp_client.h
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#error include tcp_client-windows.h instead
|
||||
#endif
|
||||
|
||||
// tcp client helper
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/details/os.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
class tcp_client
|
||||
{
|
||||
int socket_ = -1;
|
||||
|
||||
public:
|
||||
bool is_connected() const
|
||||
{
|
||||
return socket_ != -1;
|
||||
}
|
||||
|
||||
void close()
|
||||
{
|
||||
if (is_connected())
|
||||
{
|
||||
::close(socket_);
|
||||
socket_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int fd() const
|
||||
{
|
||||
return socket_;
|
||||
}
|
||||
|
||||
~tcp_client()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
// try to connect or throw on failure
|
||||
void connect(const std::string &host, int port)
|
||||
{
|
||||
close();
|
||||
struct addrinfo hints
|
||||
{};
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_INET; // IPv4
|
||||
hints.ai_socktype = SOCK_STREAM; // TCP
|
||||
hints.ai_flags = AI_NUMERICSERV; // port passed as as numeric value
|
||||
hints.ai_protocol = 0;
|
||||
|
||||
auto port_str = std::to_string(port);
|
||||
struct addrinfo *addrinfo_result;
|
||||
auto rv = ::getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addrinfo_result);
|
||||
if (rv != 0)
|
||||
{
|
||||
auto msg = fmt::format("::getaddrinfo failed: {}", gai_strerror(rv));
|
||||
throw_spdlog_ex(msg);
|
||||
}
|
||||
|
||||
// Try each address until we successfully connect(2).
|
||||
int last_errno = 0;
|
||||
for (auto *rp = addrinfo_result; rp != nullptr; rp = rp->ai_next)
|
||||
{
|
||||
int const flags = SOCK_CLOEXEC;
|
||||
socket_ = ::socket(rp->ai_family, rp->ai_socktype | flags, rp->ai_protocol);
|
||||
if (socket_ == -1)
|
||||
{
|
||||
last_errno = errno;
|
||||
continue;
|
||||
}
|
||||
rv = ::connect(socket_, rp->ai_addr, rp->ai_addrlen);
|
||||
if (rv == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_errno = errno;
|
||||
::close(socket_);
|
||||
socket_ = -1;
|
||||
}
|
||||
}
|
||||
::freeaddrinfo(addrinfo_result);
|
||||
if (socket_ == -1)
|
||||
{
|
||||
throw_spdlog_ex("::connect failed", last_errno);
|
||||
}
|
||||
|
||||
// set TCP_NODELAY
|
||||
int enable_flag = 1;
|
||||
::setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (char *)&enable_flag, sizeof(enable_flag));
|
||||
|
||||
// prevent sigpipe on systems where MSG_NOSIGNAL is not available
|
||||
#if defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL)
|
||||
::setsockopt(socket_, SOL_SOCKET, SO_NOSIGPIPE, (char *)&enable_flag, sizeof(enable_flag));
|
||||
#endif
|
||||
|
||||
#if !defined(SO_NOSIGPIPE) && !defined(MSG_NOSIGNAL)
|
||||
#error "tcp_sink would raise SIGPIPE since niether SO_NOSIGPIPE nor MSG_NOSIGNAL are available"
|
||||
#endif
|
||||
}
|
||||
|
||||
// Send exactly n_bytes of the given data.
|
||||
// On error close the connection and throw.
|
||||
void send(const char *data, size_t n_bytes)
|
||||
{
|
||||
size_t bytes_sent = 0;
|
||||
while (bytes_sent < n_bytes)
|
||||
{
|
||||
#if defined(MSG_NOSIGNAL)
|
||||
const int send_flags = MSG_NOSIGNAL;
|
||||
#else
|
||||
const int send_flags = 0;
|
||||
#endif
|
||||
auto write_result = ::send(socket_, data + bytes_sent, n_bytes - bytes_sent, send_flags);
|
||||
if (write_result < 0)
|
||||
{
|
||||
close();
|
||||
throw_spdlog_ex("write(2) failed", errno);
|
||||
}
|
||||
|
||||
if (write_result == 0) // (probably should not happen but in any case..)
|
||||
{
|
||||
break;
|
||||
}
|
||||
bytes_sent += static_cast<size_t>(write_result);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace details
|
||||
} // namespace spdlog
|
@ -18,8 +18,8 @@ SPDLOG_INLINE thread_pool::thread_pool(size_t q_max_items, size_t threads_n, std
|
||||
{
|
||||
if (threads_n == 0 || threads_n > 1000)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("spdlog::thread_pool(): invalid threads_n param (valid "
|
||||
"range is 1-1000)"));
|
||||
throw_spdlog_ex("spdlog::thread_pool(): invalid threads_n param (valid "
|
||||
"range is 1-1000)");
|
||||
}
|
||||
for (size_t i = 0; i < threads_n; i++)
|
||||
{
|
||||
@ -113,7 +113,7 @@ bool SPDLOG_INLINE thread_pool::process_next_msg_()
|
||||
}
|
||||
|
||||
default: {
|
||||
assert(false && "Unexpected async_msg_type");
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ struct async_msg : log_msg_buffer
|
||||
{}
|
||||
};
|
||||
|
||||
class thread_pool
|
||||
class SPDLOG_API thread_pool
|
||||
{
|
||||
public:
|
||||
using item_type = async_msg;
|
||||
|
11
third_party/spdlog/include/spdlog/details/windows_include.h
vendored
Normal file
11
third_party/spdlog/include/spdlog/details/windows_include.h
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX // prevent windows redefining min/max
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
101
third_party/spdlog/include/spdlog/fmt/bin_to_hex.h
vendored
101
third_party/spdlog/include/spdlog/fmt/bin_to_hex.h
vendored
@ -5,6 +5,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cctype>
|
||||
|
||||
//
|
||||
// Support for logging binary data as hex
|
||||
// format flags:
|
||||
@ -12,6 +14,7 @@
|
||||
// {:s} - don't separate each byte with space.
|
||||
// {:p} - don't print the position on each line start.
|
||||
// {:n} - don't split the output to lines.
|
||||
// {:a} - show ASCII if :n is not set
|
||||
|
||||
//
|
||||
// Examples:
|
||||
@ -20,17 +23,19 @@
|
||||
// logger->info("Some buffer {}", spdlog::to_hex(v));
|
||||
// char buf[128];
|
||||
// logger->info("Some buffer {:X}", spdlog::to_hex(std::begin(buf), std::end(buf)));
|
||||
// logger->info("Some buffer {:X}", spdlog::to_hex(std::begin(buf), std::end(buf), 16));
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
|
||||
template<typename It>
|
||||
class bytes_range
|
||||
class dump_info
|
||||
{
|
||||
public:
|
||||
bytes_range(It range_begin, It range_end)
|
||||
dump_info(It range_begin, It range_end, size_t size_per_line)
|
||||
: begin_(range_begin)
|
||||
, end_(range_end)
|
||||
, size_per_line_(size_per_line)
|
||||
{}
|
||||
|
||||
It begin() const
|
||||
@ -41,26 +46,31 @@ public:
|
||||
{
|
||||
return end_;
|
||||
}
|
||||
size_t size_per_line() const
|
||||
{
|
||||
return size_per_line_;
|
||||
}
|
||||
|
||||
private:
|
||||
It begin_, end_;
|
||||
size_t size_per_line_;
|
||||
};
|
||||
} // namespace details
|
||||
|
||||
// create a bytes_range that wraps the given container
|
||||
// create a dump_info that wraps the given container
|
||||
template<typename Container>
|
||||
inline details::bytes_range<typename Container::const_iterator> to_hex(const Container &container)
|
||||
inline details::dump_info<typename Container::const_iterator> to_hex(const Container &container, size_t size_per_line = 32)
|
||||
{
|
||||
static_assert(sizeof(typename Container::value_type) == 1, "sizeof(Container::value_type) != 1");
|
||||
using Iter = typename Container::const_iterator;
|
||||
return details::bytes_range<Iter>(std::begin(container), std::end(container));
|
||||
return details::dump_info<Iter>(std::begin(container), std::end(container), size_per_line);
|
||||
}
|
||||
|
||||
// create bytes_range from ranges
|
||||
// create dump_info from ranges
|
||||
template<typename It>
|
||||
inline details::bytes_range<It> to_hex(const It range_begin, const It range_end)
|
||||
inline details::dump_info<It> to_hex(const It range_begin, const It range_end, size_t size_per_line = 32)
|
||||
{
|
||||
return details::bytes_range<It>(range_begin, range_end);
|
||||
return details::dump_info<It>(range_begin, range_end, size_per_line);
|
||||
}
|
||||
|
||||
} // namespace spdlog
|
||||
@ -68,15 +78,14 @@ inline details::bytes_range<It> to_hex(const It range_begin, const It range_end)
|
||||
namespace fmt {
|
||||
|
||||
template<typename T>
|
||||
struct formatter<spdlog::details::bytes_range<T>>
|
||||
struct formatter<spdlog::details::dump_info<T>>
|
||||
{
|
||||
const std::size_t line_size = 100;
|
||||
const char delimiter = ' ';
|
||||
|
||||
bool put_newlines = true;
|
||||
bool put_delimiters = true;
|
||||
bool use_uppercase = false;
|
||||
bool put_positions = true; // position on start of each line
|
||||
bool show_ascii = false;
|
||||
|
||||
// parse the format string flags
|
||||
template<typename ParseContext>
|
||||
@ -98,6 +107,13 @@ struct formatter<spdlog::details::bytes_range<T>>
|
||||
break;
|
||||
case 'n':
|
||||
put_newlines = false;
|
||||
show_ascii = false;
|
||||
break;
|
||||
case 'a':
|
||||
if (put_newlines)
|
||||
{
|
||||
show_ascii = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -108,53 +124,83 @@ struct formatter<spdlog::details::bytes_range<T>>
|
||||
|
||||
// format the given bytes range as hex
|
||||
template<typename FormatContext, typename Container>
|
||||
auto format(const spdlog::details::bytes_range<Container> &the_range, FormatContext &ctx) -> decltype(ctx.out())
|
||||
auto format(const spdlog::details::dump_info<Container> &the_range, FormatContext &ctx) -> decltype(ctx.out())
|
||||
{
|
||||
SPDLOG_CONSTEXPR const char *hex_upper = "0123456789ABCDEF";
|
||||
SPDLOG_CONSTEXPR const char *hex_lower = "0123456789abcdef";
|
||||
const char *hex_chars = use_uppercase ? hex_upper : hex_lower;
|
||||
|
||||
std::size_t pos = 0;
|
||||
std::size_t column = line_size;
|
||||
#if FMT_VERSION < 60000
|
||||
auto inserter = ctx.begin();
|
||||
#else
|
||||
auto inserter = ctx.out();
|
||||
#endif
|
||||
|
||||
for (auto &item : the_range)
|
||||
int size_per_line = static_cast<int>(the_range.size_per_line());
|
||||
auto start_of_line = the_range.begin();
|
||||
for (auto i = the_range.begin(); i != the_range.end(); i++)
|
||||
{
|
||||
auto ch = static_cast<unsigned char>(item);
|
||||
pos++;
|
||||
auto ch = static_cast<unsigned char>(*i);
|
||||
|
||||
if (put_newlines && column >= line_size)
|
||||
if (put_newlines && (i == the_range.begin() || i - start_of_line >= size_per_line))
|
||||
{
|
||||
column = put_newline(inserter, pos);
|
||||
if (show_ascii && i != the_range.begin())
|
||||
{
|
||||
*inserter++ = delimiter;
|
||||
*inserter++ = delimiter;
|
||||
for (auto j = start_of_line; j < i; j++)
|
||||
{
|
||||
auto pc = static_cast<unsigned char>(*j);
|
||||
*inserter++ = std::isprint(pc) ? static_cast<char>(*j) : '.';
|
||||
}
|
||||
}
|
||||
|
||||
put_newline(inserter, static_cast<size_t>(i - the_range.begin()));
|
||||
|
||||
// put first byte without delimiter in front of it
|
||||
*inserter++ = hex_chars[(ch >> 4) & 0x0f];
|
||||
*inserter++ = hex_chars[ch & 0x0f];
|
||||
column += 2;
|
||||
start_of_line = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (put_delimiters)
|
||||
{
|
||||
*inserter++ = delimiter;
|
||||
++column;
|
||||
}
|
||||
|
||||
*inserter++ = hex_chars[(ch >> 4) & 0x0f];
|
||||
*inserter++ = hex_chars[ch & 0x0f];
|
||||
column += 2;
|
||||
}
|
||||
if (show_ascii) // add ascii to last line
|
||||
{
|
||||
if (the_range.end() - the_range.begin() > size_per_line)
|
||||
{
|
||||
auto blank_num = size_per_line - (the_range.end() - start_of_line);
|
||||
while (blank_num-- > 0)
|
||||
{
|
||||
*inserter++ = delimiter;
|
||||
*inserter++ = delimiter;
|
||||
if (put_delimiters)
|
||||
{
|
||||
*inserter++ = delimiter;
|
||||
}
|
||||
}
|
||||
}
|
||||
*inserter++ = delimiter;
|
||||
*inserter++ = delimiter;
|
||||
for (auto j = start_of_line; j != the_range.end(); j++)
|
||||
{
|
||||
auto pc = static_cast<unsigned char>(*j);
|
||||
*inserter++ = std::isprint(pc) ? static_cast<char>(*j) : '.';
|
||||
}
|
||||
}
|
||||
return inserter;
|
||||
}
|
||||
|
||||
// put newline(and position header)
|
||||
// return the next column
|
||||
template<typename It>
|
||||
std::size_t put_newline(It inserter, std::size_t pos)
|
||||
void put_newline(It inserter, std::size_t pos)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
*inserter++ = '\r';
|
||||
@ -163,12 +209,7 @@ struct formatter<spdlog::details::bytes_range<T>>
|
||||
|
||||
if (put_positions)
|
||||
{
|
||||
fmt::format_to(inserter, "{:<04X}: ", pos - 1);
|
||||
return 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
fmt::format_to(inserter, "{:<04X}: ", pos);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -696,7 +696,7 @@ inline int to_nonnegative_int(T value, int upper) {
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
inline T mod(T x, int y) {
|
||||
return x % y;
|
||||
return x % static_cast<T>(y);
|
||||
}
|
||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||
inline T mod(T x, int y) {
|
||||
@ -793,7 +793,10 @@ struct chrono_formatter {
|
||||
|
||||
explicit chrono_formatter(FormatContext& ctx, OutputIt o,
|
||||
std::chrono::duration<Rep, Period> d)
|
||||
: context(ctx), out(o), val(d.count()), negative(false) {
|
||||
: context(ctx),
|
||||
out(o),
|
||||
val(static_cast<rep>(d.count())),
|
||||
negative(false) {
|
||||
if (d.count() < 0) {
|
||||
val = 0 - val;
|
||||
negative = true;
|
||||
@ -1023,8 +1026,8 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
void on_error(const char* msg) { FMT_THROW(format_error(msg)); }
|
||||
void on_fill(Char fill) { f.specs.fill[0] = fill; }
|
||||
void on_align(align_t align) { f.specs.align = align; }
|
||||
void on_width(unsigned width) { f.specs.width = width; }
|
||||
void on_precision(unsigned _precision) { f.precision = _precision; }
|
||||
void on_width(int width) { f.specs.width = width; }
|
||||
void on_precision(int _precision) { f.precision = _precision; }
|
||||
void end_precision() {}
|
||||
|
||||
template <typename Id> void on_dynamic_width(Id arg_id) {
|
||||
|
@ -26,11 +26,11 @@ template <typename Char> struct format_part {
|
||||
|
||||
kind part_kind;
|
||||
union value {
|
||||
unsigned arg_index;
|
||||
int arg_index;
|
||||
basic_string_view<Char> str;
|
||||
replacement repl;
|
||||
|
||||
FMT_CONSTEXPR value(unsigned index = 0) : arg_index(index) {}
|
||||
FMT_CONSTEXPR value(int index = 0) : arg_index(index) {}
|
||||
FMT_CONSTEXPR value(basic_string_view<Char> s) : str(s) {}
|
||||
FMT_CONSTEXPR value(replacement r) : repl(r) {}
|
||||
} val;
|
||||
@ -40,7 +40,7 @@ template <typename Char> struct format_part {
|
||||
FMT_CONSTEXPR format_part(kind k = kind::arg_index, value v = {})
|
||||
: part_kind(k), val(v) {}
|
||||
|
||||
static FMT_CONSTEXPR format_part make_arg_index(unsigned index) {
|
||||
static FMT_CONSTEXPR format_part make_arg_index(int index) {
|
||||
return format_part(kind::arg_index, index);
|
||||
}
|
||||
static FMT_CONSTEXPR format_part make_arg_name(basic_string_view<Char> name) {
|
||||
@ -62,7 +62,7 @@ template <typename Char> struct part_counter {
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void on_arg_id() { ++num_parts; }
|
||||
FMT_CONSTEXPR void on_arg_id(unsigned) { ++num_parts; }
|
||||
FMT_CONSTEXPR void on_arg_id(int) { ++num_parts; }
|
||||
FMT_CONSTEXPR void on_arg_id(basic_string_view<Char>) { ++num_parts; }
|
||||
|
||||
FMT_CONSTEXPR void on_replacement_field(const Char*) {}
|
||||
@ -119,7 +119,7 @@ class format_string_compiler : public error_handler {
|
||||
part_ = part::make_arg_index(parse_context_.next_arg_id());
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void on_arg_id(unsigned id) {
|
||||
FMT_CONSTEXPR void on_arg_id(int id) {
|
||||
parse_context_.check_arg_id(id);
|
||||
part_ = part::make_arg_index(id);
|
||||
}
|
||||
@ -512,8 +512,6 @@ template <typename CompiledFormat, typename... Args,
|
||||
CompiledFormat>::value)>
|
||||
std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
using range = buffer_range<Char>;
|
||||
using context = buffer_context<Char>;
|
||||
cf.format(std::back_inserter(buffer), args...);
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <type_traits>
|
||||
|
||||
// The fmt library version in the form major * 10000 + minor * 100 + patch.
|
||||
#define FMT_VERSION 60101
|
||||
#define FMT_VERSION 60102
|
||||
|
||||
#ifdef __has_feature
|
||||
# define FMT_HAS_FEATURE(x) __has_feature(x)
|
||||
@ -878,7 +878,7 @@ template <typename Context> struct arg_mapper {
|
||||
FMT_ENABLE_IF(
|
||||
std::is_constructible<std_string_view<char_type>, T>::value &&
|
||||
!std::is_constructible<basic_string_view<char_type>, T>::value &&
|
||||
!is_string<T>::value)>
|
||||
!is_string<T>::value && !has_formatter<T, Context>::value)>
|
||||
FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) {
|
||||
return std_string_view<char_type>(val);
|
||||
}
|
||||
@ -911,12 +911,14 @@ template <typename Context> struct arg_mapper {
|
||||
map(static_cast<typename std::underlying_type<T>::type>(val))) {
|
||||
return map(static_cast<typename std::underlying_type<T>::type>(val));
|
||||
}
|
||||
template <typename T,
|
||||
FMT_ENABLE_IF(!is_string<T>::value && !is_char<T>::value &&
|
||||
!std::is_constructible<basic_string_view<char_type>,
|
||||
T>::value &&
|
||||
(has_formatter<T, Context>::value ||
|
||||
has_fallback_formatter<T, Context>::value))>
|
||||
template <
|
||||
typename T,
|
||||
FMT_ENABLE_IF(
|
||||
!is_string<T>::value && !is_char<T>::value &&
|
||||
!std::is_constructible<basic_string_view<char_type>, T>::value &&
|
||||
(has_formatter<T, Context>::value ||
|
||||
(has_fallback_formatter<T, Context>::value &&
|
||||
!std::is_constructible<std_string_view<char_type>, T>::value)))>
|
||||
FMT_CONSTEXPR const T& map(const T& val) {
|
||||
return val;
|
||||
}
|
||||
@ -1283,7 +1285,7 @@ template <typename Context> class basic_format_args {
|
||||
*/
|
||||
template <typename... Args>
|
||||
basic_format_args(const format_arg_store<Context, Args...>& store)
|
||||
: types_(static_cast<unsigned long long>(store.types)) {
|
||||
: types_(store.types) {
|
||||
set_data(store.data_);
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,8 @@
|
||||
# define FMT_HAS_BUILTIN(x) 0
|
||||
#endif
|
||||
|
||||
#if FMT_HAS_CPP_ATTRIBUTE(fallthrough) >= 201603 && __cplusplus >= 201703
|
||||
#if FMT_HAS_CPP_ATTRIBUTE(fallthrough) && \
|
||||
(__cplusplus >= 201703 || FMT_GCC_VERSION != 0)
|
||||
# define FMT_FALLTHROUGH [[fallthrough]]
|
||||
#else
|
||||
# define FMT_FALLTHROUGH
|
||||
@ -801,60 +802,6 @@ template <> int count_digits<4>(internal::fallback_uintptr n);
|
||||
# define FMT_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
// Computes g = floor(log10(n)) and calls h.on<g>(n);
|
||||
template <typename Handler> FMT_ALWAYS_INLINE char* lg(uint32_t n, Handler h) {
|
||||
return n < 100 ? n < 10 ? h.template on<0>(n) : h.template on<1>(n)
|
||||
: n < 1000000
|
||||
? n < 10000 ? n < 1000 ? h.template on<2>(n)
|
||||
: h.template on<3>(n)
|
||||
: n < 100000 ? h.template on<4>(n)
|
||||
: h.template on<5>(n)
|
||||
: n < 100000000 ? n < 10000000 ? h.template on<6>(n)
|
||||
: h.template on<7>(n)
|
||||
: n < 1000000000 ? h.template on<8>(n)
|
||||
: h.template on<9>(n);
|
||||
}
|
||||
|
||||
// An lg handler that formats a decimal number.
|
||||
// Usage: lg(n, decimal_formatter(buffer));
|
||||
class decimal_formatter {
|
||||
private:
|
||||
char* buffer_;
|
||||
|
||||
void write_pair(unsigned N, uint32_t index) {
|
||||
std::memcpy(buffer_ + N, data::digits + index * 2, 2);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit decimal_formatter(char* buf) : buffer_(buf) {}
|
||||
|
||||
template <unsigned N> char* on(uint32_t u) {
|
||||
if (N == 0) {
|
||||
*buffer_ = static_cast<char>(u) + '0';
|
||||
} else if (N == 1) {
|
||||
write_pair(0, u);
|
||||
} else {
|
||||
// The idea of using 4.32 fixed-point numbers is based on
|
||||
// https://github.com/jeaiii/itoa
|
||||
unsigned n = N - 1;
|
||||
unsigned a = n / 5 * n * 53 / 16;
|
||||
uint64_t t =
|
||||
((1ULL << (32 + a)) / data::zero_or_powers_of_10_32[n] + 1 - n / 9);
|
||||
t = ((t * u) >> a) + n / 5 * 4;
|
||||
write_pair(0, t >> 32);
|
||||
for (unsigned i = 2; i < N; i += 2) {
|
||||
t = 100ULL * static_cast<uint32_t>(t);
|
||||
write_pair(i, t >> 32);
|
||||
}
|
||||
if (N % 2 == 0) {
|
||||
buffer_[N] =
|
||||
static_cast<char>((10ULL * static_cast<uint32_t>(t)) >> 32) + '0';
|
||||
}
|
||||
}
|
||||
return buffer_ += N + 1;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef FMT_BUILTIN_CLZ
|
||||
// Optional version of count_digits for better performance on 32-bit platforms.
|
||||
inline int count_digits(uint32_t n) {
|
||||
@ -2620,7 +2567,7 @@ class format_string_checker {
|
||||
public:
|
||||
explicit FMT_CONSTEXPR format_string_checker(
|
||||
basic_string_view<Char> format_str, ErrorHandler eh)
|
||||
: arg_id_(max_value<unsigned>()),
|
||||
: arg_id_(-1),
|
||||
context_(format_str, eh),
|
||||
parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}
|
||||
|
||||
@ -2661,7 +2608,7 @@ class format_string_checker {
|
||||
// Format specifier parsing function.
|
||||
using parse_func = const Char* (*)(parse_context_type&);
|
||||
|
||||
unsigned arg_id_;
|
||||
int arg_id_;
|
||||
parse_context_type context_;
|
||||
parse_func parse_funcs_[num_args > 0 ? num_args : 1];
|
||||
};
|
||||
|
@ -333,12 +333,12 @@ template <typename OutputIt, typename Char> class basic_printf_context {
|
||||
static void parse_flags(format_specs& specs, const Char*& it,
|
||||
const Char* end);
|
||||
|
||||
// Returns the argument with specified index or, if arg_index is equal
|
||||
// to the maximum unsigned value, the next argument.
|
||||
format_arg get_arg(unsigned arg_index = internal::max_value<unsigned>());
|
||||
// Returns the argument with specified index or, if arg_index is -1, the next
|
||||
// argument.
|
||||
format_arg get_arg(int arg_index = -1);
|
||||
|
||||
// Parses argument index, flags and width and returns the argument index.
|
||||
unsigned parse_header(const Char*& it, const Char* end, format_specs& specs);
|
||||
int parse_header(const Char*& it, const Char* end, format_specs& specs);
|
||||
|
||||
public:
|
||||
/**
|
||||
@ -355,7 +355,7 @@ template <typename OutputIt, typename Char> class basic_printf_context {
|
||||
OutputIt out() { return out_; }
|
||||
void advance_to(OutputIt it) { out_ = it; }
|
||||
|
||||
format_arg arg(unsigned id) const { return args_.get(id); }
|
||||
format_arg arg(int id) const { return args_.get(id); }
|
||||
|
||||
basic_format_parse_context<Char>& parse_context() { return parse_ctx_; }
|
||||
|
||||
@ -397,8 +397,8 @@ void basic_printf_context<OutputIt, Char>::parse_flags(format_specs& specs,
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
typename basic_printf_context<OutputIt, Char>::format_arg
|
||||
basic_printf_context<OutputIt, Char>::get_arg(unsigned arg_index) {
|
||||
if (arg_index == internal::max_value<unsigned>())
|
||||
basic_printf_context<OutputIt, Char>::get_arg(int arg_index) {
|
||||
if (arg_index < 0)
|
||||
arg_index = parse_ctx_.next_arg_id();
|
||||
else
|
||||
parse_ctx_.check_arg_id(--arg_index);
|
||||
@ -406,15 +406,15 @@ basic_printf_context<OutputIt, Char>::get_arg(unsigned arg_index) {
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
unsigned basic_printf_context<OutputIt, Char>::parse_header(
|
||||
int basic_printf_context<OutputIt, Char>::parse_header(
|
||||
const Char*& it, const Char* end, format_specs& specs) {
|
||||
unsigned arg_index = internal::max_value<unsigned>();
|
||||
int arg_index = -1;
|
||||
char_type c = *it;
|
||||
if (c >= '0' && c <= '9') {
|
||||
// Parse an argument index (if followed by '$') or a width possibly
|
||||
// preceded with '0' flag(s).
|
||||
internal::error_handler eh;
|
||||
unsigned value = parse_nonnegative_int(it, end, eh);
|
||||
int value = parse_nonnegative_int(it, end, eh);
|
||||
if (it != end && *it == '$') { // value is an argument index
|
||||
++it;
|
||||
arg_index = value;
|
||||
@ -436,8 +436,8 @@ unsigned basic_printf_context<OutputIt, Char>::parse_header(
|
||||
specs.width = parse_nonnegative_int(it, end, eh);
|
||||
} else if (*it == '*') {
|
||||
++it;
|
||||
specs.width = visit_format_arg(
|
||||
internal::printf_width_handler<char_type>(specs), get_arg());
|
||||
specs.width = static_cast<int>(visit_format_arg(
|
||||
internal::printf_width_handler<char_type>(specs), get_arg()));
|
||||
}
|
||||
}
|
||||
return arg_index;
|
||||
@ -464,7 +464,7 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
||||
specs.align = align::right;
|
||||
|
||||
// Parse argument index, flags and width.
|
||||
unsigned arg_index = parse_header(it, end, specs);
|
||||
int arg_index = parse_header(it, end, specs);
|
||||
if (arg_index == 0) on_error("argument index out of range");
|
||||
|
||||
// Parse precision.
|
||||
@ -473,11 +473,11 @@ OutputIt basic_printf_context<OutputIt, Char>::format() {
|
||||
c = it != end ? *it : 0;
|
||||
if ('0' <= c && c <= '9') {
|
||||
internal::error_handler eh;
|
||||
specs.precision = static_cast<int>(parse_nonnegative_int(it, end, eh));
|
||||
specs.precision = parse_nonnegative_int(it, end, eh);
|
||||
} else if (c == '*') {
|
||||
++it;
|
||||
specs.precision =
|
||||
visit_format_arg(internal::printf_precision_handler(), get_arg());
|
||||
static_cast<int>(visit_format_arg(internal::printf_precision_handler(), get_arg()));
|
||||
} else {
|
||||
specs.precision = 0;
|
||||
}
|
||||
|
22
third_party/spdlog/include/spdlog/fmt/fmt.h
vendored
22
third_party/spdlog/include/spdlog/fmt/fmt.h
vendored
@ -10,30 +10,16 @@
|
||||
// By default spdlog include its own copy.
|
||||
//
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif // __GNUC__ || __clang__
|
||||
|
||||
|
||||
#if !defined(SPDLOG_FMT_EXTERNAL)
|
||||
#ifdef SPDLOG_HEADER_ONLY
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
#if !defined(SPDLOG_COMPILED_LIB) && !defined(FMT_HEADER_ONLY)
|
||||
#define FMT_HEADER_ONLY
|
||||
#endif
|
||||
#endif
|
||||
#ifndef FMT_USE_WINDOWS_H
|
||||
#define FMT_USE_WINDOWS_H 0
|
||||
#endif
|
||||
#include "bundled/core.h"
|
||||
#include "bundled/format.h"
|
||||
#include <spdlog/fmt/bundled/core.h>
|
||||
#include <spdlog/fmt/bundled/format.h>
|
||||
#else // SPDLOG_FMT_EXTERNAL is defined - use external fmtlib
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#endif
|
||||
|
||||
// pop warnings supressions
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
6
third_party/spdlog/include/spdlog/fmt/ostr.h
vendored
6
third_party/spdlog/include/spdlog/fmt/ostr.h
vendored
@ -7,12 +7,14 @@
|
||||
//
|
||||
// include bundled or external copy of fmtlib's ostream support
|
||||
//
|
||||
|
||||
#if !defined(SPDLOG_FMT_EXTERNAL)
|
||||
#ifdef SPDLOG_HEADER_ONLY
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
#define FMT_HEADER_ONLY
|
||||
#endif
|
||||
#include "bundled/ostream.h"
|
||||
#include "fmt.h"
|
||||
#endif
|
||||
#include <spdlog/fmt/bundled/ostream.h>
|
||||
#else
|
||||
#include <fmt/ostream.h>
|
||||
#endif
|
||||
|
14
third_party/spdlog/include/spdlog/fwd.h
vendored
Normal file
14
third_party/spdlog/include/spdlog/fwd.h
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace spdlog {
|
||||
class logger;
|
||||
class formatter;
|
||||
|
||||
namespace sinks {
|
||||
class sink;
|
||||
}
|
||||
|
||||
} // namespace spdlog
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include <spdlog/sinks/sink.h>
|
||||
#include <spdlog/details/backtracer.h>
|
||||
#include <spdlog/details/pattern_formatter.h>
|
||||
#include <spdlog/pattern_formatter.h>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
@ -89,6 +89,7 @@ SPDLOG_INLINE void logger::set_formatter(std::unique_ptr<formatter> f)
|
||||
{
|
||||
// last element - we can be move it.
|
||||
(*it)->set_formatter(std::move(f));
|
||||
break; // to prevent clang-tidy warning
|
||||
}
|
||||
else
|
||||
{
|
||||
|
7
third_party/spdlog/include/spdlog/logger.h
vendored
7
third_party/spdlog/include/spdlog/logger.h
vendored
@ -39,7 +39,7 @@
|
||||
|
||||
namespace spdlog {
|
||||
|
||||
class logger
|
||||
class SPDLOG_API logger
|
||||
{
|
||||
public:
|
||||
// Empty logger
|
||||
@ -143,6 +143,11 @@ public:
|
||||
// T can be statically converted to string_view
|
||||
template<class T, typename std::enable_if<std::is_convertible<const T &, spdlog::string_view_t>::value, T>::type * = nullptr>
|
||||
void log(source_loc loc, level::level_enum lvl, const T &msg)
|
||||
{
|
||||
log(loc, lvl, string_view_t{msg});
|
||||
}
|
||||
|
||||
void log(source_loc loc, level::level_enum lvl, string_view_t msg)
|
||||
{
|
||||
bool log_enabled = should_log(lvl);
|
||||
bool traceback_enabled = tracer_.enabled();
|
||||
|
@ -4,7 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SPDLOG_HEADER_ONLY
|
||||
#include <spdlog/details/pattern_formatter.h>
|
||||
#include <spdlog/pattern_formatter.h>
|
||||
#endif
|
||||
|
||||
#include <spdlog/details/fmt_helper.h>
|
||||
@ -90,7 +90,7 @@ struct null_scoped_padder
|
||||
};
|
||||
|
||||
template<typename ScopedPadder>
|
||||
class name_formatter : public flag_formatter
|
||||
class name_formatter final : public flag_formatter
|
||||
{
|
||||
public:
|
||||
explicit name_formatter(padding_info padinfo)
|
||||
@ -106,7 +106,7 @@ public:
|
||||
|
||||
// log level appender
|
||||
template<typename ScopedPadder>
|
||||
class level_formatter : public flag_formatter
|
||||
class level_formatter final : public flag_formatter
|
||||
{
|
||||
public:
|
||||
explicit level_formatter(padding_info padinfo)
|
||||
@ -123,7 +123,7 @@ public:
|
||||
|
||||
// short log level appender
|
||||
template<typename ScopedPadder>
|
||||
class short_level_formatter : public flag_formatter
|
||||
class short_level_formatter final : public flag_formatter
|
||||
{
|
||||
public:
|
||||
explicit short_level_formatter(padding_info padinfo)
|
||||
@ -156,7 +156,7 @@ static int to12h(const tm &t)
|
||||
static std::array<const char *, 7> days{{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}};
|
||||
|
||||
template<typename ScopedPadder>
|
||||
class a_formatter : public flag_formatter
|
||||
class a_formatter final : public flag_formatter
|
||||
{
|
||||
public:
|
||||
explicit a_formatter(padding_info padinfo)
|
||||
@ -194,7 +194,7 @@ public:
|
||||
static const std::array<const char *, 12> months{{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"}};
|
||||
|
||||
template<typename ScopedPadder>
|
||||
class b_formatter : public flag_formatter
|
||||
class b_formatter final : public flag_formatter
|
||||
{
|
||||
public:
|
||||
explicit b_formatter(padding_info padinfo)
|
||||
@ -214,7 +214,7 @@ static const std::array<const char *, 12> full_months{
|
||||
{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}};
|
||||
|
||||
template<typename ScopedPadder>
|
||||
class B_formatter : public flag_formatter
|
||||
class B_formatter final : public flag_formatter
|
||||
{
|
||||
public:
|
||||
explicit B_formatter(padding_info padinfo)
|
||||
@ -933,16 +933,15 @@ public:
|
||||
dest.push_back(']');
|
||||
dest.push_back(' ');
|
||||
|
||||
#ifndef SPDLOG_NO_NAME
|
||||
// append logger name if exists
|
||||
if (msg.logger_name.size() > 0)
|
||||
{
|
||||
dest.push_back('[');
|
||||
// fmt_helper::append_str(*msg.logger_name, dest);
|
||||
fmt_helper::append_string_view(msg.logger_name, dest);
|
||||
dest.push_back(']');
|
||||
dest.push_back(' ');
|
||||
}
|
||||
#endif
|
||||
|
||||
dest.push_back('[');
|
||||
// wrap the level name with color
|
||||
msg.color_range_start = dest.size();
|
||||
@ -974,11 +973,13 @@ private:
|
||||
|
||||
} // namespace details
|
||||
|
||||
SPDLOG_INLINE pattern_formatter::pattern_formatter(std::string pattern, pattern_time_type time_type, std::string eol)
|
||||
SPDLOG_INLINE pattern_formatter::pattern_formatter(
|
||||
std::string pattern, pattern_time_type time_type, std::string eol, custom_flags custom_user_flags)
|
||||
: pattern_(std::move(pattern))
|
||||
, eol_(std::move(eol))
|
||||
, pattern_time_type_(time_type)
|
||||
, last_log_secs_(0)
|
||||
, custom_handlers_(std::move(custom_user_flags))
|
||||
{
|
||||
std::memset(&cached_tm_, 0, sizeof(cached_tm_));
|
||||
compile_pattern_(pattern_);
|
||||
@ -997,7 +998,12 @@ SPDLOG_INLINE pattern_formatter::pattern_formatter(pattern_time_type time_type,
|
||||
|
||||
SPDLOG_INLINE std::unique_ptr<formatter> pattern_formatter::clone() const
|
||||
{
|
||||
return details::make_unique<pattern_formatter>(pattern_, pattern_time_type_, eol_);
|
||||
custom_flags cloned_custom_formatters;
|
||||
for (auto &it : custom_handlers_)
|
||||
{
|
||||
cloned_custom_formatters[it.first] = it.second->clone();
|
||||
}
|
||||
return details::make_unique<pattern_formatter>(pattern_, pattern_time_type_, eol_, std::move(cloned_custom_formatters));
|
||||
}
|
||||
|
||||
SPDLOG_INLINE void pattern_formatter::format(const details::log_msg &msg, memory_buf_t &dest)
|
||||
@ -1017,6 +1023,12 @@ SPDLOG_INLINE void pattern_formatter::format(const details::log_msg &msg, memory
|
||||
details::fmt_helper::append_string_view(eol_, dest);
|
||||
}
|
||||
|
||||
SPDLOG_INLINE void pattern_formatter::set_pattern(std::string pattern)
|
||||
{
|
||||
pattern_ = std::move(pattern);
|
||||
compile_pattern_(pattern_);
|
||||
}
|
||||
|
||||
SPDLOG_INLINE std::tm pattern_formatter::get_time_(const details::log_msg &msg)
|
||||
{
|
||||
if (pattern_time_type_ == pattern_time_type::local)
|
||||
@ -1029,9 +1041,19 @@ SPDLOG_INLINE std::tm pattern_formatter::get_time_(const details::log_msg &msg)
|
||||
template<typename Padder>
|
||||
SPDLOG_INLINE void pattern_formatter::handle_flag_(char flag, details::padding_info padding)
|
||||
{
|
||||
// process custom flags
|
||||
auto it = custom_handlers_.find(flag);
|
||||
if (it != custom_handlers_.end())
|
||||
{
|
||||
auto custom_handler = it->second->clone();
|
||||
custom_handler->set_padding_info(padding);
|
||||
formatters_.push_back(std::move(custom_handler));
|
||||
return;
|
||||
}
|
||||
|
||||
// process built-in flags
|
||||
switch (flag)
|
||||
{
|
||||
|
||||
case ('+'): // default formatter
|
||||
formatters_.push_back(details::make_unique<details::full_formatter>(padding));
|
||||
break;
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace spdlog {
|
||||
namespace details {
|
||||
@ -40,13 +41,13 @@ struct padding_info
|
||||
{
|
||||
return enabled_;
|
||||
}
|
||||
const size_t width_ = 0;
|
||||
const pad_side side_ = left;
|
||||
size_t width_ = 0;
|
||||
pad_side side_ = left;
|
||||
bool truncate_ = false;
|
||||
bool enabled_ = false;
|
||||
};
|
||||
|
||||
class flag_formatter
|
||||
class SPDLOG_API flag_formatter
|
||||
{
|
||||
public:
|
||||
explicit flag_formatter(padding_info padinfo)
|
||||
@ -62,11 +63,24 @@ protected:
|
||||
|
||||
} // namespace details
|
||||
|
||||
class pattern_formatter final : public formatter
|
||||
class SPDLOG_API custom_flag_formatter : public details::flag_formatter
|
||||
{
|
||||
public:
|
||||
explicit pattern_formatter(
|
||||
std::string pattern, pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol);
|
||||
virtual std::unique_ptr<custom_flag_formatter> clone() const = 0;
|
||||
|
||||
void set_padding_info(details::padding_info padding)
|
||||
{
|
||||
flag_formatter::padinfo_ = padding;
|
||||
}
|
||||
};
|
||||
|
||||
class SPDLOG_API pattern_formatter final : public formatter
|
||||
{
|
||||
public:
|
||||
using custom_flags = std::unordered_map<char, std::unique_ptr<custom_flag_formatter>>;
|
||||
|
||||
explicit pattern_formatter(std::string pattern, pattern_time_type time_type = pattern_time_type::local,
|
||||
std::string eol = spdlog::details::os::default_eol, custom_flags custom_user_flags = {});
|
||||
|
||||
// use default pattern is not given
|
||||
explicit pattern_formatter(pattern_time_type time_type = pattern_time_type::local, std::string eol = spdlog::details::os::default_eol);
|
||||
@ -77,6 +91,14 @@ public:
|
||||
std::unique_ptr<formatter> clone() const override;
|
||||
void format(const details::log_msg &msg, memory_buf_t &dest) override;
|
||||
|
||||
template<typename T, typename... Args>
|
||||
pattern_formatter &add_flag(char flag, const Args &... args)
|
||||
{
|
||||
custom_handlers_[flag] = details::make_unique<T>(args...);
|
||||
return *this;
|
||||
}
|
||||
void set_pattern(std::string pattern);
|
||||
|
||||
private:
|
||||
std::string pattern_;
|
||||
std::string eol_;
|
||||
@ -84,6 +106,7 @@ private:
|
||||
std::tm cached_tm_;
|
||||
std::chrono::seconds last_log_secs_;
|
||||
std::vector<std::unique_ptr<details::flag_formatter>> formatters_;
|
||||
custom_flags custom_handlers_;
|
||||
|
||||
std::tm get_time_(const details::log_msg &msg);
|
||||
template<typename Padder>
|
||||
@ -92,7 +115,7 @@ private:
|
||||
// Extract given pad spec (e.g. %8X)
|
||||
// Advance the given it pass the end of the padding spec found (if any)
|
||||
// Return padding.
|
||||
details::padding_info handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end);
|
||||
static details::padding_info handle_padspec_(std::string::const_iterator &it, std::string::const_iterator end);
|
||||
|
||||
void compile_pattern_(const std::string &pattern);
|
||||
};
|
@ -64,7 +64,7 @@ protected:
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("__android_log_write() failed", ret));
|
||||
throw_spdlog_ex("__android_log_write() failed", ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <spdlog/sinks/ansicolor_sink.h>
|
||||
#endif
|
||||
|
||||
#include <spdlog/details/pattern_formatter.h>
|
||||
#include <spdlog/pattern_formatter.h>
|
||||
#include <spdlog/details/os.h>
|
||||
|
||||
namespace spdlog {
|
||||
@ -43,7 +43,8 @@ SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::log(const details::log_msg &msg
|
||||
// Wrap the originally formatted message in color codes.
|
||||
// If color is not supported in the terminal, log as is instead.
|
||||
std::lock_guard<mutex_t> lock(mutex_);
|
||||
|
||||
msg.color_range_start = 0;
|
||||
msg.color_range_end = 0;
|
||||
memory_buf_t formatted;
|
||||
formatter_->format(msg, formatted);
|
||||
if (should_do_colors_ && msg.color_range_end > msg.color_range_start)
|
||||
@ -111,7 +112,7 @@ SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::set_color_mode(color_mode mode)
|
||||
template<typename ConsoleMutex>
|
||||
SPDLOG_INLINE void ansicolor_sink<ConsoleMutex>::print_ccode_(const string_view_t &color_code)
|
||||
{
|
||||
fwrite(color_code.data(), sizeof(string_view_t::char_type), color_code.size(), target_file_);
|
||||
fwrite(color_code.data(), sizeof(char), color_code.size(), target_file_);
|
||||
}
|
||||
|
||||
template<typename ConsoleMutex>
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <array>
|
||||
|
||||
namespace spdlog {
|
||||
namespace sinks {
|
||||
@ -30,7 +30,11 @@ public:
|
||||
~ansicolor_sink() override = default;
|
||||
|
||||
ansicolor_sink(const ansicolor_sink &other) = delete;
|
||||
ansicolor_sink(ansicolor_sink &&other) = delete;
|
||||
|
||||
ansicolor_sink &operator=(const ansicolor_sink &other) = delete;
|
||||
ansicolor_sink &operator=(ansicolor_sink &&other) = delete;
|
||||
|
||||
void set_color(level::level_enum color_level, string_view_t color);
|
||||
void set_color_mode(color_mode mode);
|
||||
bool should_color();
|
||||
@ -80,7 +84,7 @@ private:
|
||||
mutex_t &mutex_;
|
||||
bool should_do_colors_;
|
||||
std::unique_ptr<spdlog::formatter> formatter_;
|
||||
std::unordered_map<level::level_enum, string_view_t, level::level_hasher> colors_;
|
||||
std::array<string_view_t, level::n_levels> colors_;
|
||||
void print_ccode_(const string_view_t &color_code);
|
||||
void print_range_(const memory_buf_t &formatted, size_t start, size_t end);
|
||||
};
|
||||
|
@ -8,7 +8,7 @@
|
||||
#endif
|
||||
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/details/pattern_formatter.h>
|
||||
#include <spdlog/pattern_formatter.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
@ -21,8 +21,14 @@ class base_sink : public sink
|
||||
public:
|
||||
base_sink();
|
||||
explicit base_sink(std::unique_ptr<spdlog::formatter> formatter);
|
||||
~base_sink() override = default;
|
||||
|
||||
base_sink(const base_sink &) = delete;
|
||||
base_sink(base_sink &&) = delete;
|
||||
|
||||
base_sink &operator=(const base_sink &) = delete;
|
||||
base_sink &operator=(base_sink &&) = delete;
|
||||
|
||||
void log(const details::log_msg &msg) final;
|
||||
void flush() final;
|
||||
void set_pattern(const std::string &pattern) final;
|
||||
|
@ -56,7 +56,7 @@ public:
|
||||
{
|
||||
if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("daily_file_sink: Invalid rotation time in ctor"));
|
||||
throw_spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
|
||||
}
|
||||
|
||||
auto now = log_clock::now();
|
||||
@ -66,13 +66,13 @@ public:
|
||||
|
||||
if (max_files_ > 0)
|
||||
{
|
||||
filenames_q_ = details::circular_q<filename_t>(static_cast<size_t>(max_files_));
|
||||
filenames_q_.push_back(std::move(filename));
|
||||
init_filenames_q_();
|
||||
}
|
||||
}
|
||||
|
||||
const filename_t &filename() const
|
||||
filename_t filename()
|
||||
{
|
||||
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
|
||||
return file_helper_.filename();
|
||||
}
|
||||
|
||||
@ -104,6 +104,29 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
void init_filenames_q_()
|
||||
{
|
||||
using details::os::path_exists;
|
||||
|
||||
filenames_q_ = details::circular_q<filename_t>(static_cast<size_t>(max_files_));
|
||||
std::vector<filename_t> filenames;
|
||||
auto now = log_clock::now();
|
||||
while (filenames.size() < max_files_)
|
||||
{
|
||||
auto filename = FileNameCalc::calc_filename(base_filename_, now_tm(now));
|
||||
if (!path_exists(filename))
|
||||
{
|
||||
break;
|
||||
}
|
||||
filenames.emplace_back(filename);
|
||||
now -= std::chrono::hours(24);
|
||||
}
|
||||
for (auto iter = filenames.rbegin(); iter != filenames.rend(); ++iter)
|
||||
{
|
||||
filenames_q_.push_back(std::move(*iter));
|
||||
}
|
||||
}
|
||||
|
||||
tm now_tm(log_clock::time_point tp)
|
||||
{
|
||||
time_t tnow = log_clock::to_time_t(tp);
|
||||
@ -141,7 +164,7 @@ private:
|
||||
if (!ok)
|
||||
{
|
||||
filenames_q_.push_back(std::move(current_file));
|
||||
SPDLOG_THROW(spdlog_ex("Failed removing daily file " + filename_to_str(old_filename), errno));
|
||||
throw_spdlog_ex("Failed removing daily file " + filename_to_str(old_filename), errno);
|
||||
}
|
||||
}
|
||||
filenames_q_.push_back(std::move(current_file));
|
||||
@ -167,15 +190,15 @@ using daily_file_sink_st = daily_file_sink<details::null_mutex>;
|
||||
//
|
||||
template<typename Factory = spdlog::synchronous_factory>
|
||||
inline std::shared_ptr<logger> daily_logger_mt(
|
||||
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false)
|
||||
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
|
||||
{
|
||||
return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate);
|
||||
return Factory::template create<sinks::daily_file_sink_mt>(logger_name, filename, hour, minute, truncate, max_files);
|
||||
}
|
||||
|
||||
template<typename Factory = spdlog::synchronous_factory>
|
||||
inline std::shared_ptr<logger> daily_logger_st(
|
||||
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false)
|
||||
const std::string &logger_name, const filename_t &filename, int hour = 0, int minute = 0, bool truncate = false, uint16_t max_files = 0)
|
||||
{
|
||||
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate);
|
||||
return Factory::template create<sinks::daily_file_sink_st>(logger_name, filename, hour, minute, truncate, max_files);
|
||||
}
|
||||
} // namespace spdlog
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "base_sink.h"
|
||||
#include <spdlog/details/log_msg.h>
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
#include <spdlog/details/pattern_formatter.h>
|
||||
#include <spdlog/pattern_formatter.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
|
||||
#include <spdlog/details/windows_include.h>
|
||||
#include <winbase.h>
|
||||
|
||||
#include <mutex>
|
||||
|
@ -54,8 +54,9 @@ SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::calc_filename(const filename
|
||||
}
|
||||
|
||||
template<typename Mutex>
|
||||
SPDLOG_INLINE const filename_t &rotating_file_sink<Mutex>::filename() const
|
||||
SPDLOG_INLINE filename_t rotating_file_sink<Mutex>::filename()
|
||||
{
|
||||
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
|
||||
return file_helper_.filename();
|
||||
}
|
||||
|
||||
@ -99,18 +100,17 @@ SPDLOG_INLINE void rotating_file_sink<Mutex>::rotate_()
|
||||
}
|
||||
filename_t target = calc_filename(base_filename_, i);
|
||||
|
||||
if (!rename_file(src, target))
|
||||
if (!rename_file_(src, target))
|
||||
{
|
||||
// if failed try again after a small delay.
|
||||
// this is a workaround to a windows issue, where very high rotation
|
||||
// rates can cause the rename to fail with permission denied (because of antivirus?).
|
||||
details::os::sleep_for_millis(100);
|
||||
if (!rename_file(src, target))
|
||||
if (!rename_file_(src, target))
|
||||
{
|
||||
file_helper_.reopen(true); // truncate the log file anyway to prevent it to grow beyond its limit!
|
||||
current_size_ = 0;
|
||||
SPDLOG_THROW(
|
||||
spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno));
|
||||
throw_spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -120,7 +120,7 @@ SPDLOG_INLINE void rotating_file_sink<Mutex>::rotate_()
|
||||
// delete the target if exists, and rename the src file to target
|
||||
// return true on success, false otherwise.
|
||||
template<typename Mutex>
|
||||
SPDLOG_INLINE bool rotating_file_sink<Mutex>::rename_file(const filename_t &src_filename, const filename_t &target_filename)
|
||||
SPDLOG_INLINE bool rotating_file_sink<Mutex>::rename_file_(const filename_t &src_filename, const filename_t &target_filename)
|
||||
{
|
||||
// try to delete the target file in case it already exists.
|
||||
(void)details::os::remove(target_filename);
|
||||
|
@ -24,7 +24,7 @@ class rotating_file_sink final : public base_sink<Mutex>
|
||||
public:
|
||||
rotating_file_sink(filename_t base_filename, std::size_t max_size, std::size_t max_files, bool rotate_on_open = false);
|
||||
static filename_t calc_filename(const filename_t &filename, std::size_t index);
|
||||
const filename_t &filename() const;
|
||||
filename_t filename();
|
||||
|
||||
protected:
|
||||
void sink_it_(const details::log_msg &msg) override;
|
||||
@ -40,7 +40,7 @@ private:
|
||||
|
||||
// delete the target if exists, and rename the src file to target
|
||||
// return true on success, false otherwise.
|
||||
bool rename_file(const filename_t &src_filename, const filename_t &target_filename);
|
||||
bool rename_file_(const filename_t &src_filename, const filename_t &target_filename);
|
||||
|
||||
filename_t base_filename_;
|
||||
std::size_t max_size_;
|
||||
@ -75,4 +75,4 @@ inline std::shared_ptr<logger> rotating_logger_st(
|
||||
|
||||
#ifdef SPDLOG_HEADER_ONLY
|
||||
#include "rotating_file_sink-inl.h"
|
||||
#endif
|
||||
#endif
|
||||
|
@ -9,7 +9,7 @@
|
||||
namespace spdlog {
|
||||
|
||||
namespace sinks {
|
||||
class sink
|
||||
class SPDLOG_API sink
|
||||
{
|
||||
public:
|
||||
virtual ~sink() = default;
|
||||
|
@ -8,7 +8,7 @@
|
||||
#endif
|
||||
|
||||
#include <spdlog/details/console_globals.h>
|
||||
#include <spdlog/details/pattern_formatter.h>
|
||||
#include <spdlog/pattern_formatter.h>
|
||||
#include <memory>
|
||||
|
||||
namespace spdlog {
|
||||
|
@ -19,8 +19,12 @@ public:
|
||||
using mutex_t = typename ConsoleMutex::mutex_t;
|
||||
explicit stdout_sink_base(FILE *file);
|
||||
~stdout_sink_base() override = default;
|
||||
|
||||
stdout_sink_base(const stdout_sink_base &other) = delete;
|
||||
stdout_sink_base(stdout_sink_base &&other) = delete;
|
||||
|
||||
stdout_sink_base &operator=(const stdout_sink_base &other) = delete;
|
||||
stdout_sink_base &operator=(stdout_sink_base &&other) = delete;
|
||||
|
||||
void log(const details::log_msg &msg) override;
|
||||
void flush() override;
|
||||
|
@ -72,7 +72,7 @@ protected:
|
||||
|
||||
if (err)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("Failed writing to systemd", errno));
|
||||
throw_spdlog_ex("Failed writing to systemd", errno);
|
||||
}
|
||||
}
|
||||
|
||||
|
81
third_party/spdlog/include/spdlog/sinks/tcp_sink.h
vendored
Normal file
81
third_party/spdlog/include/spdlog/sinks/tcp_sink.h
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
#ifdef _WIN32
|
||||
#include <spdlog/details/tcp_client-windows.h>
|
||||
#else
|
||||
#include <spdlog/details/tcp_client.h>
|
||||
#endif
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
|
||||
#pragma once
|
||||
|
||||
// Simple tcp client sink
|
||||
// Connects to remote address and send the formatted log.
|
||||
// Will attempt to reconnect if connection drops.
|
||||
// If more complicated behaviour is needed (i.e get responses), you can inherit it and override the sink_it_ method.
|
||||
|
||||
namespace spdlog {
|
||||
namespace sinks {
|
||||
|
||||
struct tcp_sink_config
|
||||
{
|
||||
std::string server_host;
|
||||
int server_port;
|
||||
bool lazy_connect = false; // if true connect on first log call instead of on construction
|
||||
|
||||
tcp_sink_config(std::string host, int port)
|
||||
: server_host{std::move(host)}
|
||||
, server_port{port}
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename Mutex>
|
||||
class tcp_sink : public spdlog::sinks::base_sink<Mutex>
|
||||
{
|
||||
public:
|
||||
// connect to tcp host/port or throw if failed
|
||||
// host can be hostname or ip address
|
||||
|
||||
explicit tcp_sink(tcp_sink_config sink_config)
|
||||
: config_{std::move(sink_config)}
|
||||
{
|
||||
if (!config_.lazy_connect)
|
||||
{
|
||||
this->client_.connect(config_.server_host, config_.server_port);
|
||||
}
|
||||
}
|
||||
|
||||
~tcp_sink() override = default;
|
||||
|
||||
protected:
|
||||
void sink_it_(const spdlog::details::log_msg &msg) override
|
||||
{
|
||||
spdlog::memory_buf_t formatted;
|
||||
spdlog::sinks::base_sink<Mutex>::formatter_->format(msg, formatted);
|
||||
if (!client_.is_connected())
|
||||
{
|
||||
client_.connect(config_.server_host, config_.server_port);
|
||||
}
|
||||
client_.send(formatted.data(), formatted.size());
|
||||
}
|
||||
|
||||
void flush_() override {}
|
||||
tcp_sink_config config_;
|
||||
details::tcp_client client_;
|
||||
};
|
||||
|
||||
using tcp_sink_mt = tcp_sink<std::mutex>;
|
||||
using tcp_sink_st = tcp_sink<spdlog::details::null_mutex>;
|
||||
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
266
third_party/spdlog/include/spdlog/sinks/win_eventlog_sink.h
vendored
Normal file
266
third_party/spdlog/include/spdlog/sinks/win_eventlog_sink.h
vendored
Normal file
@ -0,0 +1,266 @@
|
||||
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
// Writing to Windows Event Log requires the registry entries below to be present, with the following modifications:
|
||||
// 1. <log_name> should be replaced with your log name (e.g. your application name)
|
||||
// 2. <source_name> should be replaced with the specific source name and the key should be duplicated for
|
||||
// each source used in the application
|
||||
//
|
||||
// Since typically modifications of this kind require elevation, it's better to do it as a part of setup procedure.
|
||||
// The snippet below uses mscoree.dll as the message file as it exists on most of the Windows systems anyway and
|
||||
// happens to contain the needed resource.
|
||||
//
|
||||
// You can also specify a custom message file if needed.
|
||||
// Please refer to Event Log functions descriptions in MSDN for more details on custom message files.
|
||||
|
||||
/*---------------------------------------------------------------------------------------
|
||||
|
||||
Windows Registry Editor Version 5.00
|
||||
|
||||
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\<log_name>]
|
||||
|
||||
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\<log_name>\<source_name>]
|
||||
"TypesSupported"=dword:00000007
|
||||
"EventMessageFile"=hex(2):25,00,73,00,79,00,73,00,74,00,65,00,6d,00,72,00,6f,\
|
||||
00,6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,\
|
||||
5c,00,6d,00,73,00,63,00,6f,00,72,00,65,00,65,00,2e,00,64,00,6c,00,6c,00,00,\
|
||||
00
|
||||
|
||||
-----------------------------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
|
||||
#include <spdlog/details/windows_include.h>
|
||||
#include <winbase.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace spdlog {
|
||||
namespace sinks {
|
||||
|
||||
namespace win_eventlog {
|
||||
|
||||
namespace internal {
|
||||
|
||||
/** Windows error */
|
||||
struct win32_error : public spdlog_ex
|
||||
{
|
||||
/** Formats an error report line: "user-message: error-code (system message)" */
|
||||
static std::string format(std::string const &user_message, DWORD error_code = GetLastError())
|
||||
{
|
||||
std::string system_message;
|
||||
|
||||
LPSTR format_message_result{};
|
||||
auto format_message_succeeded =
|
||||
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
|
||||
error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&format_message_result, 0, nullptr);
|
||||
|
||||
if (format_message_succeeded && format_message_result)
|
||||
{
|
||||
system_message = fmt::format(" ({})", format_message_result);
|
||||
}
|
||||
|
||||
if (format_message_result)
|
||||
{
|
||||
LocalFree((HLOCAL)format_message_result);
|
||||
}
|
||||
|
||||
return fmt::format("{}: {}{}", user_message, error_code, system_message);
|
||||
}
|
||||
|
||||
explicit win32_error(std::string const &func_name, DWORD error = GetLastError())
|
||||
: spdlog_ex(format(func_name, error))
|
||||
{}
|
||||
};
|
||||
|
||||
/** Wrapper for security identifiers (SID) on Windows */
|
||||
struct sid_t
|
||||
{
|
||||
std::vector<char> buffer_;
|
||||
|
||||
public:
|
||||
sid_t() {}
|
||||
|
||||
/** creates a wrapped SID copy */
|
||||
static sid_t duplicate_sid(PSID psid)
|
||||
{
|
||||
if (!::IsValidSid(psid))
|
||||
{
|
||||
throw_spdlog_ex("sid_t::sid_t(): invalid SID received");
|
||||
}
|
||||
|
||||
auto const sid_length{::GetLengthSid(psid)};
|
||||
|
||||
sid_t result;
|
||||
result.buffer_.resize(sid_length);
|
||||
if (!::CopySid(sid_length, (PSID)result.as_sid(), psid))
|
||||
{
|
||||
SPDLOG_THROW(win32_error("CopySid"));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Retrieves pointer to the internal buffer contents as SID* */
|
||||
SID *as_sid() const
|
||||
{
|
||||
return buffer_.empty() ? nullptr : (SID *)buffer_.data();
|
||||
}
|
||||
|
||||
/** Get SID for the current user */
|
||||
static sid_t get_current_user_sid()
|
||||
{
|
||||
/* create and init RAII holder for process token */
|
||||
struct process_token_t
|
||||
{
|
||||
HANDLE token_handle_ = INVALID_HANDLE_VALUE;
|
||||
explicit process_token_t(HANDLE process)
|
||||
{
|
||||
if (!::OpenProcessToken(process, TOKEN_QUERY, &token_handle_))
|
||||
{
|
||||
SPDLOG_THROW(win32_error("OpenProcessToken"));
|
||||
}
|
||||
}
|
||||
|
||||
~process_token_t()
|
||||
{
|
||||
::CloseHandle(token_handle_);
|
||||
}
|
||||
|
||||
} current_process_token(::GetCurrentProcess()); // GetCurrentProcess returns pseudohandle, no leak here!
|
||||
|
||||
// Get the required size, this is expected to fail with ERROR_INSUFFICIENT_BUFFER and return the token size
|
||||
DWORD tusize = 0;
|
||||
if (::GetTokenInformation(current_process_token.token_handle_, TokenUser, NULL, 0, &tusize))
|
||||
{
|
||||
SPDLOG_THROW(win32_error("GetTokenInformation should fail"));
|
||||
}
|
||||
|
||||
// get user token
|
||||
std::vector<unsigned char> buffer(static_cast<size_t>(tusize));
|
||||
if (!::GetTokenInformation(current_process_token.token_handle_, TokenUser, (LPVOID)buffer.data(), tusize, &tusize))
|
||||
{
|
||||
SPDLOG_THROW(win32_error("GetTokenInformation"));
|
||||
}
|
||||
|
||||
// create a wrapper of the SID data as stored in the user token
|
||||
return sid_t::duplicate_sid(((TOKEN_USER *)buffer.data())->User.Sid);
|
||||
}
|
||||
};
|
||||
|
||||
struct eventlog
|
||||
{
|
||||
static WORD get_event_type(details::log_msg const &msg)
|
||||
{
|
||||
switch (msg.level)
|
||||
{
|
||||
case level::trace:
|
||||
case level::debug:
|
||||
return EVENTLOG_SUCCESS;
|
||||
|
||||
case level::info:
|
||||
return EVENTLOG_INFORMATION_TYPE;
|
||||
|
||||
case level::warn:
|
||||
return EVENTLOG_WARNING_TYPE;
|
||||
|
||||
case level::err:
|
||||
case level::critical:
|
||||
case level::off:
|
||||
return EVENTLOG_ERROR_TYPE;
|
||||
|
||||
default:
|
||||
return EVENTLOG_INFORMATION_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
static WORD get_event_category(details::log_msg const &msg)
|
||||
{
|
||||
return (WORD)msg.level;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/*
|
||||
* Windows Event Log sink
|
||||
*/
|
||||
template<typename Mutex>
|
||||
class win_eventlog_sink : public base_sink<Mutex>
|
||||
{
|
||||
private:
|
||||
HANDLE hEventLog_{NULL};
|
||||
internal::sid_t current_user_sid_;
|
||||
std::string source_;
|
||||
WORD event_id_;
|
||||
|
||||
HANDLE event_log_handle()
|
||||
{
|
||||
if (!hEventLog_)
|
||||
{
|
||||
hEventLog_ = ::RegisterEventSource(nullptr, source_.c_str());
|
||||
if (!hEventLog_ || hEventLog_ == (HANDLE)ERROR_ACCESS_DENIED)
|
||||
{
|
||||
SPDLOG_THROW(internal::win32_error("RegisterEventSource"));
|
||||
}
|
||||
}
|
||||
|
||||
return hEventLog_;
|
||||
}
|
||||
|
||||
protected:
|
||||
void sink_it_(const details::log_msg &msg) override
|
||||
{
|
||||
using namespace internal;
|
||||
|
||||
memory_buf_t formatted;
|
||||
base_sink<Mutex>::formatter_->format(msg, formatted);
|
||||
formatted.push_back('\0');
|
||||
LPCSTR lp_str = static_cast<LPCSTR>(formatted.data());
|
||||
|
||||
auto succeeded = ::ReportEvent(event_log_handle(), eventlog::get_event_type(msg), eventlog::get_event_category(msg), event_id_,
|
||||
current_user_sid_.as_sid(), 1, 0, &lp_str, nullptr);
|
||||
|
||||
if (!succeeded)
|
||||
{
|
||||
SPDLOG_THROW(win32_error("ReportEvent"));
|
||||
}
|
||||
}
|
||||
|
||||
void flush_() override {}
|
||||
|
||||
public:
|
||||
win_eventlog_sink(std::string const &source, WORD event_id = 1000 /* according to mscoree.dll */)
|
||||
: source_(source)
|
||||
, event_id_(event_id)
|
||||
{
|
||||
try
|
||||
{
|
||||
current_user_sid_ = internal::sid_t::get_current_user_sid();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// get_current_user_sid() is unlikely to fail and if it does, we can still proceed without
|
||||
// current_user_sid but in the event log the record will have no user name
|
||||
}
|
||||
}
|
||||
|
||||
~win_eventlog_sink()
|
||||
{
|
||||
if (hEventLog_)
|
||||
DeregisterEventSource(hEventLog_);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace win_eventlog
|
||||
|
||||
using win_eventlog_sink_mt = win_eventlog::win_eventlog_sink<std::mutex>;
|
||||
using win_eventlog_sink_st = win_eventlog::win_eventlog_sink<details::null_mutex>;
|
||||
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
@ -8,7 +8,7 @@
|
||||
#endif
|
||||
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/details/pattern_formatter.h>
|
||||
#include <spdlog/pattern_formatter.h>
|
||||
|
||||
namespace spdlog {
|
||||
namespace sinks {
|
||||
@ -52,6 +52,8 @@ template<typename ConsoleMutex>
|
||||
void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::log(const details::log_msg &msg)
|
||||
{
|
||||
std::lock_guard<mutex_t> lock(mutex_);
|
||||
msg.color_range_start = 0;
|
||||
msg.color_range_end = 0;
|
||||
memory_buf_t formatted;
|
||||
formatter_->format(msg, formatted);
|
||||
if (!in_console_)
|
||||
@ -59,7 +61,6 @@ void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::log(const details::log_msg &msg)
|
||||
write_to_file_(formatted);
|
||||
return;
|
||||
}
|
||||
|
||||
if (should_do_colors_ && msg.color_range_end > msg.color_range_start)
|
||||
{
|
||||
// before color range
|
||||
@ -157,7 +158,7 @@ void SPDLOG_INLINE wincolor_sink<ConsoleMutex>::write_to_file_(const memory_buf_
|
||||
bool ok = ::WriteFile(out_handle_, formatted.data() + total_written, size - total_written, &bytes_written, nullptr) != 0;
|
||||
if (!ok || bytes_written == 0)
|
||||
{
|
||||
SPDLOG_THROW(spdlog_ex("wincolor_sink: write_to_file_ failed. GetLastError(): " + std::to_string(::GetLastError())));
|
||||
throw_spdlog_ex("wincolor_sink: write_to_file_ failed. GetLastError(): " + std::to_string(::GetLastError()));
|
||||
}
|
||||
total_written += bytes_written;
|
||||
} while (total_written < size);
|
||||
|
@ -11,7 +11,9 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <array>
|
||||
|
||||
#include <spdlog/details/windows_include.h>
|
||||
#include <wincon.h>
|
||||
|
||||
namespace spdlog {
|
||||
@ -52,7 +54,7 @@ protected:
|
||||
bool in_console_;
|
||||
bool should_do_colors_;
|
||||
std::unique_ptr<spdlog::formatter> formatter_;
|
||||
std::unordered_map<level::level_enum, WORD, level::level_hasher> colors_;
|
||||
std::array<WORD, level::n_levels> colors_;
|
||||
|
||||
// set foreground color and return the orig console attributes (for resetting later)
|
||||
WORD set_foreground_color_(WORD attribs);
|
||||
|
@ -8,7 +8,7 @@
|
||||
#endif
|
||||
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/details/pattern_formatter.h>
|
||||
#include <spdlog/pattern_formatter.h>
|
||||
|
||||
namespace spdlog {
|
||||
|
||||
|
48
third_party/spdlog/include/spdlog/spdlog.h
vendored
48
third_party/spdlog/include/spdlog/spdlog.h
vendored
@ -39,68 +39,66 @@ inline std::shared_ptr<spdlog::logger> create(std::string logger_name, SinkArgs
|
||||
// Initialize and register a logger,
|
||||
// formatter and flush level will be set according the global settings.
|
||||
//
|
||||
// NOTE:
|
||||
// Use this function when creating loggers manually.
|
||||
// Useful for initializing manually created loggers with the global settings.
|
||||
//
|
||||
// Example:
|
||||
// auto console_sink = std::make_shared<spdlog::sinks::stdout_sink_mt>();
|
||||
// auto console_logger = std::make_shared<spdlog::logger>("console_logger", console_sink);
|
||||
// spdlog::initialize_logger(console_logger);
|
||||
void initialize_logger(std::shared_ptr<logger> logger);
|
||||
// auto mylogger = std::make_shared<spdlog::logger>("mylogger", ...);
|
||||
// spdlog::initialize_logger(mylogger);
|
||||
SPDLOG_API void initialize_logger(std::shared_ptr<logger> logger);
|
||||
|
||||
// Return an existing logger or nullptr if a logger with such name doesn't
|
||||
// exist.
|
||||
// example: spdlog::get("my_logger")->info("hello {}", "world");
|
||||
std::shared_ptr<logger> get(const std::string &name);
|
||||
SPDLOG_API std::shared_ptr<logger> get(const std::string &name);
|
||||
|
||||
// Set global formatter. Each sink in each logger will get a clone of this object
|
||||
void set_formatter(std::unique_ptr<spdlog::formatter> formatter);
|
||||
SPDLOG_API void set_formatter(std::unique_ptr<spdlog::formatter> formatter);
|
||||
|
||||
// Set global format string.
|
||||
// example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v");
|
||||
void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local);
|
||||
SPDLOG_API void set_pattern(std::string pattern, pattern_time_type time_type = pattern_time_type::local);
|
||||
|
||||
// enable global backtrace support
|
||||
void enable_backtrace(size_t n_messages);
|
||||
SPDLOG_API void enable_backtrace(size_t n_messages);
|
||||
|
||||
// disable global backtrace support
|
||||
void disable_backtrace();
|
||||
SPDLOG_API void disable_backtrace();
|
||||
|
||||
// call dump backtrace on default logger
|
||||
void dump_backtrace();
|
||||
SPDLOG_API void dump_backtrace();
|
||||
|
||||
// Set global logging level
|
||||
void set_level(level::level_enum log_level);
|
||||
SPDLOG_API void set_level(level::level_enum log_level);
|
||||
|
||||
// Set global flush level
|
||||
void flush_on(level::level_enum log_level);
|
||||
SPDLOG_API void flush_on(level::level_enum log_level);
|
||||
|
||||
// Start/Restart a periodic flusher thread
|
||||
// Warning: Use only if all your loggers are thread safe!
|
||||
void flush_every(std::chrono::seconds interval);
|
||||
SPDLOG_API void flush_every(std::chrono::seconds interval);
|
||||
|
||||
// Set global error handler
|
||||
void set_error_handler(void (*handler)(const std::string &msg));
|
||||
SPDLOG_API void set_error_handler(void (*handler)(const std::string &msg));
|
||||
|
||||
// Register the given logger with the given name
|
||||
void register_logger(std::shared_ptr<logger> logger);
|
||||
SPDLOG_API void register_logger(std::shared_ptr<logger> logger);
|
||||
|
||||
// Apply a user defined function on all registered loggers
|
||||
// Example:
|
||||
// spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) {l->flush();});
|
||||
void apply_all(const std::function<void(std::shared_ptr<logger>)> &fun);
|
||||
SPDLOG_API void apply_all(const std::function<void(std::shared_ptr<logger>)> &fun);
|
||||
|
||||
// Drop the reference to the given logger
|
||||
void drop(const std::string &name);
|
||||
SPDLOG_API void drop(const std::string &name);
|
||||
|
||||
// Drop all references from the registry
|
||||
void drop_all();
|
||||
SPDLOG_API void drop_all();
|
||||
|
||||
// stop any running threads started by spdlog and clean registry loggers
|
||||
void shutdown();
|
||||
SPDLOG_API void shutdown();
|
||||
|
||||
// Automatic registration of loggers when using spdlog::create() or spdlog::create_async
|
||||
void set_automatic_registration(bool automatic_registration);
|
||||
SPDLOG_API void set_automatic_registration(bool automatic_registration);
|
||||
|
||||
// API for using default logger (stdout_color_mt),
|
||||
// e.g: spdlog::info("Message {}", 1);
|
||||
@ -117,11 +115,11 @@ void set_automatic_registration(bool automatic_registration);
|
||||
// set_default_logger() *should not* be used concurrently with the default API.
|
||||
// e.g do not call set_default_logger() from one thread while calling spdlog::info() from another.
|
||||
|
||||
std::shared_ptr<spdlog::logger> default_logger();
|
||||
SPDLOG_API std::shared_ptr<spdlog::logger> default_logger();
|
||||
|
||||
spdlog::logger *default_logger_raw();
|
||||
SPDLOG_API spdlog::logger *default_logger_raw();
|
||||
|
||||
void set_default_logger(std::shared_ptr<spdlog::logger> default_logger);
|
||||
SPDLOG_API void set_default_logger(std::shared_ptr<spdlog::logger> default_logger);
|
||||
|
||||
template<typename... Args>
|
||||
inline void log(source_loc source, level::level_enum lvl, string_view_t fmt, const Args &... args)
|
||||
|
9
third_party/spdlog/include/spdlog/tweakme.h
vendored
9
third_party/spdlog/include/spdlog/tweakme.h
vendored
@ -24,7 +24,7 @@
|
||||
// This will prevent spdlog from querying the thread id on each log call.
|
||||
//
|
||||
// WARNING: If the log pattern contains thread id (i.e, %t) while this flag is
|
||||
// on, the result is undefined.
|
||||
// on, zero will be logged as thread id.
|
||||
//
|
||||
// #define SPDLOG_NO_THREAD_ID
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -38,13 +38,6 @@
|
||||
// #define SPDLOG_NO_TLS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment if logger name logging is not needed.
|
||||
// This will prevent spdlog from copying the logger name on each log call.
|
||||
//
|
||||
// #define SPDLOG_NO_NAME
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment to avoid spdlog's usage of atomic log levels
|
||||
// Use only if your code never modifies a logger's log levels concurrently by
|
||||
|
2
third_party/spdlog/include/spdlog/version.h
vendored
2
third_party/spdlog/include/spdlog/version.h
vendored
@ -4,7 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#define SPDLOG_VER_MAJOR 1
|
||||
#define SPDLOG_VER_MINOR 5
|
||||
#define SPDLOG_VER_MINOR 6
|
||||
#define SPDLOG_VER_PATCH 0
|
||||
|
||||
#define SPDLOG_VERSION (SPDLOG_VER_MAJOR * 10000 + SPDLOG_VER_MINOR * 100 + SPDLOG_VER_PATCH)
|
||||
|
Reference in New Issue
Block a user