Merge from develop
This commit is contained in:
commit
9292aab373
@ -117,12 +117,12 @@ boost::optional<cpputils::unique_ref<EncryptedBlock<Cipher>>> EncryptedBlock<Cip
|
||||
boost::optional<cpputils::Data> plaintextWithHeader = Cipher::decrypt((byte*)baseBlock->data() + sizeof(FORMAT_VERSION_HEADER), baseBlock->size() - sizeof(FORMAT_VERSION_HEADER), encKey);
|
||||
if(plaintextWithHeader == boost::none) {
|
||||
//Decryption failed (e.g. an authenticated cipher detected modifications to the ciphertext)
|
||||
cpputils::logging::LOG(cpputils::logging::WARN) << "Decrypting block " << baseBlock->key().ToString() << " failed. Was the block modified by an attacker?";
|
||||
cpputils::logging::LOG(cpputils::logging::WARN, "Decrypting block {} failed. Was the block modified by an attacker?", baseBlock->key().ToString());
|
||||
return boost::none;
|
||||
}
|
||||
if(!_keyHeaderIsCorrect(baseBlock->key(), *plaintextWithHeader)) {
|
||||
//The stored key in the block data is incorrect - an attacker might have exchanged the contents with the encrypted data from a different block
|
||||
cpputils::logging::LOG(cpputils::logging::WARN) << "Decrypting block " << baseBlock->key().ToString() << " failed due to invalid block key. Was the block modified by an attacker?";
|
||||
cpputils::logging::LOG(cpputils::logging::WARN, "Decrypting block {} failed due to invalid block key. Was the block modified by an attacker?", baseBlock->key().ToString());
|
||||
return boost::none;
|
||||
}
|
||||
return cpputils::make_unique_ref<EncryptedBlock<Cipher>>(std::move(baseBlock), encKey, std::move(*plaintextWithHeader));
|
||||
|
@ -99,7 +99,7 @@ void OnDiskBlock::RemoveFromDisk(const bf::path &rootdir, const Key &key) {
|
||||
ASSERT(bf::is_regular_file(filepath), "Block not found on disk");
|
||||
bool retval = bf::remove(filepath);
|
||||
if (!retval) {
|
||||
LOG(ERROR) << "Couldn't find block " << key.ToString() << " to remove";
|
||||
LOG(ERROR, "Couldn't find block {} to remove", key.ToString());
|
||||
}
|
||||
if (bf::is_empty(filepath.parent_path())) {
|
||||
bf::remove(filepath.parent_path());
|
||||
|
@ -23,13 +23,13 @@ namespace cpputils {
|
||||
inline void assert_fail_release [[noreturn]] (const char *expr, const std::string &message, const char *file, int line) {
|
||||
auto msg = format(expr, message, file, line);
|
||||
using namespace logging;
|
||||
LOG(ERROR) << msg;
|
||||
LOG(ERROR, msg);
|
||||
throw AssertFailed(msg);
|
||||
}
|
||||
|
||||
inline void assert_fail_debug [[noreturn]] (const char *expr, const std::string &message, const char *file, int line) {
|
||||
using namespace logging;
|
||||
LOG(ERROR) << format(expr, message, file, line);
|
||||
LOG(ERROR, format(expr, message, file, line));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ namespace cpputils {
|
||||
}
|
||||
|
||||
void sigsegv_handler(int) {
|
||||
LOG(ERROR) << "SIGSEGV\n" << backtrace();
|
||||
LOG(ERROR, "SIGSEGV\n{}", backtrace());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ namespace cpputils {
|
||||
uint32_t size;
|
||||
std::memcpy(&size, reinterpret_cast<const char*>(data.data()), sizeof(size));
|
||||
if(sizeof(size) + size >= data.size()) {
|
||||
LOG(ERROR) << "Config file is invalid: Invalid padding.";
|
||||
LOG(ERROR, "Config file is invalid: Invalid padding.");
|
||||
return boost::none;
|
||||
};
|
||||
Data result(size);
|
||||
|
@ -2,6 +2,7 @@
|
||||
#ifndef MESSMER_CPPUTILS_LOGGING_LOGGER_H
|
||||
#define MESSMER_CPPUTILS_LOGGING_LOGGER_H
|
||||
|
||||
#define SPDLOG_ENABLE_SYSLOG
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "../macros.h"
|
||||
|
||||
|
@ -4,14 +4,15 @@
|
||||
|
||||
#include "Logger.h"
|
||||
#include <stdexcept>
|
||||
#include <spdlog/fmt/ostr.h>
|
||||
|
||||
namespace cpputils {
|
||||
namespace logging {
|
||||
|
||||
extern struct ERROR_TYPE {} ERROR;
|
||||
extern struct WARN_TYPE {} WARN;
|
||||
extern struct INFO_TYPE {} INFO;
|
||||
extern struct DEBUG_TYPE {} DEBUG;
|
||||
constexpr struct ERROR_TYPE {} ERROR;
|
||||
constexpr struct WARN_TYPE {} WARN;
|
||||
constexpr struct INFO_TYPE {} INFO;
|
||||
constexpr struct DEBUG_TYPE {} DEBUG;
|
||||
|
||||
inline void setLogger(std::shared_ptr<spdlog::logger> newLogger) {
|
||||
logger().setLogger(newLogger);
|
||||
@ -37,20 +38,28 @@ namespace cpputils {
|
||||
logger().setLevel(spdlog::level::debug);
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger LOG(ERROR_TYPE) {
|
||||
return logger()->error();
|
||||
template<class LogType> inline void LOG(LogType logType, const std::string &msg) {
|
||||
LOG(logType, msg.c_str());
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger LOG(WARN_TYPE) {
|
||||
return logger()->warn();
|
||||
template <typename... Args>
|
||||
inline void LOG(ERROR_TYPE, const char* fmt, const Args&... args) {
|
||||
logger()->error(fmt, args...);
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger LOG(INFO_TYPE) {
|
||||
return logger()->info();
|
||||
template <typename... Args>
|
||||
inline void LOG(WARN_TYPE, const char* fmt, const Args&... args) {
|
||||
logger()->warn(fmt, args...);
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger LOG(DEBUG_TYPE) {
|
||||
return logger()->debug();
|
||||
template <typename... Args>
|
||||
inline void LOG(INFO_TYPE, const char* fmt, const Args&... args) {
|
||||
logger()->info(fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline void LOG(DEBUG_TYPE, const char* fmt, const Args&... args) {
|
||||
logger()->debug(fmt, args...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,13 +34,13 @@ namespace cpputils {
|
||||
// Create a new SID for the child process
|
||||
pid_t sid = setsid();
|
||||
if (sid < 0) {
|
||||
LOG(ERROR) << "Failed to get SID for daemon process";
|
||||
LOG(ERROR, "Failed to get SID for daemon process");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Change the current working directory to a directory that's always existin
|
||||
if ((chdir("/")) < 0) {
|
||||
LOG(ERROR) << "Failed to change working directory for daemon process";
|
||||
LOG(ERROR, "Failed to change working directory for daemon process");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,11 @@
|
||||
#ifndef MESSMER_CPPUTILS_SYSTEM_CLOCKGETTIME_H
|
||||
#define MESSMER_CPPUTILS_SYSTEM_CLOCKGETTIME_H
|
||||
|
||||
// Implements clock_gettime for Mac OS X (where it is not implemented by in the standard library)
|
||||
// Implements clock_gettime for Mac OS X before 10.12 (where it is not implemented by in the standard library)
|
||||
// Source: http://stackoverflow.com/a/9781275/829568
|
||||
// Caution: The returned value is less precise than the returned value from a linux clock_gettime would be.
|
||||
|
||||
#ifdef __MACH__
|
||||
#if defined(__MACH__) && !defined(CLOCK_REALTIME)
|
||||
#include <sys/time.h>
|
||||
#define CLOCK_REALTIME 0
|
||||
inline int clock_gettime(int /*clk_id*/, struct timespec *result) {
|
||||
|
@ -21,7 +21,7 @@ void TempDir::remove() {
|
||||
bf::remove_all(_path);
|
||||
}
|
||||
} catch (const boost::filesystem::filesystem_error &e) {
|
||||
LOG(ERROR) << "Could not delete tempfile.";
|
||||
LOG(ERROR, "Could not delete tempfile.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ TempFile::~TempFile() {
|
||||
bf::remove(_path);
|
||||
}
|
||||
} catch (const boost::filesystem::filesystem_error &e) {
|
||||
LOG(ERROR) << "Could not delete tempfile.";
|
||||
LOG(ERROR, "Could not delete tempfile.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,9 +75,9 @@ namespace cpputils {
|
||||
} catch (const boost::thread_interrupted &e) {
|
||||
//Do nothing, exit thread.
|
||||
} catch (const std::exception &e) {
|
||||
LOG(ERROR) << "LoopThread crashed: " << e.what();
|
||||
LOG(ERROR, "LoopThread crashed: {}", e.what());
|
||||
} catch (...) {
|
||||
LOG(ERROR) << "LoopThread crashed";
|
||||
LOG(ERROR, "LoopThread crashed");
|
||||
}
|
||||
//TODO We should remove the thread from _runningThreads here, not in stop().
|
||||
}
|
||||
|
@ -252,9 +252,9 @@ namespace cryfs {
|
||||
#endif
|
||||
fuse.run(options.mountDir(), options.fuseOptions());
|
||||
} catch (const std::exception &e) {
|
||||
LOG(ERROR) << "Crashed: " << e.what();
|
||||
LOG(ERROR, "Crashed: {}", e.what());
|
||||
} catch (...) {
|
||||
LOG(ERROR) << "Crashed";
|
||||
LOG(ERROR, "Crashed");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ namespace cryfs {
|
||||
read_json(input, pt);
|
||||
return pt;
|
||||
} catch (const json_parser_error &e) {
|
||||
LOG(WARN) << "Error parsing version information json object";
|
||||
LOG(WARN, "Error parsing version information json object");
|
||||
return none;
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,13 @@
|
||||
#include "utils.h"
|
||||
#include <iostream>
|
||||
#include <boost/optional.hpp>
|
||||
#include <cryfs/config/CryConfigConsole.h>
|
||||
#include <cryfs-cli/Environment.h>
|
||||
|
||||
namespace po = boost::program_options;
|
||||
namespace bf = boost::filesystem;
|
||||
using namespace cryfs::program_options;
|
||||
using cryfs::CryConfigConsole;
|
||||
using std::pair;
|
||||
using std::vector;
|
||||
using std::cerr;
|
||||
@ -122,12 +124,16 @@ vector<const char*> Parser::_to_const_char_vector(const vector<string> &options)
|
||||
|
||||
void Parser::_addAllowedOptions(po::options_description *desc) {
|
||||
po::options_description options("Allowed options");
|
||||
string cipher_description = "Cipher to use for encryption. See possible values by calling cryfs with --show-ciphers. Default: ";
|
||||
cipher_description += CryConfigConsole::DEFAULT_CIPHER;
|
||||
string blocksize_description = "The block size used when storing ciphertext blocks (in bytes). Default: ";
|
||||
blocksize_description += std::to_string(CryConfigConsole::DEFAULT_BLOCKSIZE_BYTES);
|
||||
options.add_options()
|
||||
("help,h", "show help message")
|
||||
("config,c", po::value<string>(), "Configuration file")
|
||||
("foreground,f", "Run CryFS in foreground.")
|
||||
("cipher", po::value<string>(), "Cipher to use for encryption. See possible values by calling cryfs with --show-ciphers.")
|
||||
("blocksize", po::value<uint32_t>(), "The block size used when storing ciphertext blocks (in bytes).")
|
||||
("cipher", po::value<string>(), cipher_description.c_str())
|
||||
("blocksize", po::value<uint32_t>(), blocksize_description.c_str())
|
||||
("missing-block-is-integrity-violation", po::value<bool>(), "Whether to treat a missing block as an integrity violation. This makes sure you notice if an attacker deleted some of your files, but only works in single-client mode. You will not be able to use the file system on other devices.")
|
||||
("show-ciphers", "Show list of supported ciphers.")
|
||||
("unmount-idle", po::value<double>(), "Automatically unmount after specified number of idle minutes.")
|
||||
|
@ -28,7 +28,7 @@ CryConfigFile::~CryConfigFile() {
|
||||
optional<CryConfigFile> CryConfigFile::load(const bf::path &path, const string &password) {
|
||||
auto encryptedConfigData = Data::LoadFromFile(path);
|
||||
if (encryptedConfigData == none) {
|
||||
LOG(ERROR) << "Config file not found";
|
||||
LOG(ERROR, "Config file not found");
|
||||
return none;
|
||||
}
|
||||
auto encryptor = CryConfigEncryptorFactory::loadKey(*encryptedConfigData, password);
|
||||
@ -41,7 +41,7 @@ optional<CryConfigFile> CryConfigFile::load(const bf::path &path, const string &
|
||||
}
|
||||
CryConfig config = CryConfig::load(decrypted->data);
|
||||
if (config.Cipher() != decrypted->cipherName) {
|
||||
LOG(ERROR) << "Inner cipher algorithm used to encrypt config file doesn't match config value";
|
||||
LOG(ERROR, "Inner cipher algorithm used to encrypt config file doesn't match config value");
|
||||
return none;
|
||||
}
|
||||
auto configFile = CryConfigFile(path, std::move(config), std::move(*encryptor));
|
||||
|
@ -33,12 +33,12 @@ namespace cryfs {
|
||||
template<class Cipher>
|
||||
boost::optional<cpputils::Data> ConcreteInnerEncryptor<Cipher>::decrypt(const InnerConfig &innerConfig) const {
|
||||
if (innerConfig.cipherName != Cipher::NAME) {
|
||||
cpputils::logging::LOG(cpputils::logging::ERROR) << "Initialized ConcreteInnerEncryptor with wrong cipher";
|
||||
cpputils::logging::LOG(cpputils::logging::ERROR, "Initialized ConcreteInnerEncryptor with wrong cipher");
|
||||
return boost::none;
|
||||
}
|
||||
auto decrypted = Cipher::decrypt(static_cast<const uint8_t*>(innerConfig.encryptedConfig.data()), innerConfig.encryptedConfig.size(), _key);
|
||||
if (decrypted == boost::none) {
|
||||
cpputils::logging::LOG(cpputils::logging::ERROR) << "Failed decrypting configuration file";
|
||||
cpputils::logging::LOG(cpputils::logging::ERROR, "Failed decrypting configuration file");
|
||||
return boost::none;
|
||||
}
|
||||
auto configData = cpputils::RandomPadding::remove(*decrypted);
|
||||
|
@ -23,7 +23,7 @@ namespace cryfs {
|
||||
serializer.writeTailData(encryptedConfig);
|
||||
return serializer.finished();
|
||||
} catch (const exception &e) {
|
||||
LOG(ERROR) << "Error serializing inner configuration: " << e.what();
|
||||
LOG(ERROR, "Error serializing inner configuration: {}", e.what());
|
||||
throw; // This is a programming logic error, pass through exception.
|
||||
}
|
||||
}
|
||||
@ -37,7 +37,7 @@ namespace cryfs {
|
||||
deserializer.finished();
|
||||
return InnerConfig {cipherName, std::move(result)};
|
||||
} catch (const exception &e) {
|
||||
LOG(ERROR) << "Error deserializing inner configuration: " << e.what();
|
||||
LOG(ERROR, "Error deserializing inner configuration: {}", e.what());
|
||||
return none; // This can be caused by invalid input data and does not have to be a programming error. Don't throw exception.
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ namespace cryfs {
|
||||
serializer.writeTailData(encryptedInnerConfig);
|
||||
return serializer.finished();
|
||||
} catch (const exception &e) {
|
||||
LOG(ERROR) << "Error serializing CryConfigEncryptor: " << e.what();
|
||||
LOG(ERROR, "Error serializing CryConfigEncryptor: {}", e.what());
|
||||
throw; // This is a programming logic error. Pass through exception.
|
||||
}
|
||||
}
|
||||
@ -60,7 +60,7 @@ namespace cryfs {
|
||||
_deserializeNewFormat(&deserializer);
|
||||
#endif
|
||||
} catch (const exception &e) {
|
||||
LOG(ERROR) << "Error deserializing outer configuration: " << e.what();
|
||||
LOG(ERROR, "Error deserializing outer configuration: {}", e.what());
|
||||
return none; // This can be caused by invalid input data and does not have to be a programming error. Don't throw exception.
|
||||
}
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ CryDevice::BlobWithParent CryDevice::LoadBlobWithParent(const bf::path &path) {
|
||||
optional<unique_ref<DirBlobRef>> parentBlob = none;
|
||||
optional<unique_ref<FsBlobRef>> currentBlobOpt = _fsBlobStore->load(_rootKey);
|
||||
if (currentBlobOpt == none) {
|
||||
LOG(ERROR) << "Could not load root blob. Is the base directory accessible?";
|
||||
LOG(ERROR, "Could not load root blob. Is the base directory accessible?");
|
||||
throw FuseErrnoException(EIO);
|
||||
}
|
||||
unique_ref<FsBlobRef> currentBlob = std::move(*currentBlobOpt);
|
||||
@ -267,7 +267,7 @@ unique_ref<SymlinkBlobRef> CryDevice::CreateSymlinkBlob(const bf::path &target,
|
||||
unique_ref<FsBlobRef> CryDevice::LoadBlob(const blockstore::Key &key) {
|
||||
auto blob = _fsBlobStore->load(key);
|
||||
if (blob == none) {
|
||||
LOG(ERROR) << "Could not load blob " << key.ToString() << ". Is the base directory accessible?";
|
||||
LOG(ERROR, "Could not load blob {}. Is the base directory accessible?", key.ToString());
|
||||
throw FuseErrnoException(EIO);
|
||||
}
|
||||
return std::move(*blob);
|
||||
@ -276,7 +276,7 @@ unique_ref<FsBlobRef> CryDevice::LoadBlob(const blockstore::Key &key) {
|
||||
void CryDevice::RemoveBlob(const blockstore::Key &key) {
|
||||
auto blob = _fsBlobStore->load(key);
|
||||
if (blob == none) {
|
||||
LOG(ERROR) << "Could not load blob " << key.ToString() << ". Is the base directory accessible?";
|
||||
LOG(ERROR, "Could not load blob. Is the base directory accessible?", key.ToString());
|
||||
throw FuseErrnoException(EIO);
|
||||
}
|
||||
_fsBlobStore->remove(std::move(*blob));
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <blockstore/utils/Key.h>
|
||||
#include <fspp/fs_interface/Dir.h>
|
||||
#include <cpp-utils/system/time.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
// TODO Implement (and test) atime, noatime, strictatime, relatime mount options
|
||||
|
||||
|
@ -222,11 +222,11 @@ Fuse::Fuse(Filesystem *fs, const std::string &fstype, const boost::optional<std:
|
||||
}
|
||||
|
||||
void Fuse::_logException(const std::exception &e) {
|
||||
LOG(ERROR) << "Exception thrown: " << e.what();
|
||||
LOG(ERROR, "Exception thrown: ", e.what());
|
||||
}
|
||||
|
||||
void Fuse::_logUnknownException() {
|
||||
LOG(ERROR) << "Unknown exception thrown";
|
||||
LOG(ERROR, "Unknown exception thrown");
|
||||
}
|
||||
|
||||
void Fuse::run(const bf::path &mountdir, const vector<string> &fuseOptions) {
|
||||
@ -296,19 +296,19 @@ void Fuse::stop() {
|
||||
int ret = system(("fusermount -z -u " + _mountdir.native()).c_str()); // "-z" takes care that if the filesystem can't be unmounted right now because something is opened, it will be unmounted as soon as it can be.
|
||||
#endif
|
||||
if (ret != 0) {
|
||||
LOG(ERROR) << "Could not unmount filesystem";
|
||||
LOG(ERROR, "Could not unmount filesystem");
|
||||
}
|
||||
}
|
||||
|
||||
int Fuse::getattr(const bf::path &path, struct stat *stbuf) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "getattr(" << path << ", _, _)";
|
||||
LOG(DEBUG, "getattr({}, _, _)", path);
|
||||
#endif
|
||||
try {
|
||||
_fs->lstat(path, stbuf);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::getattr: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::getattr: {}", e.what());
|
||||
return -EIO;
|
||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -323,7 +323,7 @@ int Fuse::getattr(const bf::path &path, struct stat *stbuf) {
|
||||
|
||||
int Fuse::fgetattr(const bf::path &path, struct stat *stbuf, fuse_file_info *fileinfo) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "fgetattr(" << path << ", _, _)\n";
|
||||
LOG(DEBUG, "fgetattr({}, _, _)\n", path);
|
||||
#endif
|
||||
|
||||
// On FreeBSD, trying to do anything with the mountpoint ends up
|
||||
@ -339,7 +339,7 @@ int Fuse::fgetattr(const bf::path &path, struct stat *stbuf, fuse_file_info *fil
|
||||
_fs->fstat(fileinfo->fh, stbuf);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::fgetattr: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::fgetattr: {}", e.what());
|
||||
return -EIO;
|
||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -354,13 +354,13 @@ int Fuse::fgetattr(const bf::path &path, struct stat *stbuf, fuse_file_info *fil
|
||||
|
||||
int Fuse::readlink(const bf::path &path, char *buf, size_t size) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "readlink(" << path << ", _, " << size << ")";
|
||||
LOG(DEBUG, "readlink({}, _, {})", path, size);
|
||||
#endif
|
||||
try {
|
||||
_fs->readSymlink(path, buf, size);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::readlink: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::readlink: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (fspp::fuse::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -377,20 +377,20 @@ int Fuse::mknod(const bf::path &path, mode_t mode, dev_t rdev) {
|
||||
UNUSED(rdev);
|
||||
UNUSED(mode);
|
||||
UNUSED(path);
|
||||
LOG(WARN) << "Called non-implemented mknod(" << path << ", " << mode << ", _)";
|
||||
LOG(WARN, "Called non-implemented mknod({}, {}, _)", path, mode);
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
int Fuse::mkdir(const bf::path &path, mode_t mode) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "mkdir(" << path << ", " << mode << ")";
|
||||
LOG(DEBUG, "mkdir({}, {})", path, mode);
|
||||
#endif
|
||||
try {
|
||||
auto context = fuse_get_context();
|
||||
_fs->mkdir(path, mode, context->uid, context->gid);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::mkdir: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::mkdir: {}", e.what());
|
||||
return -EIO;
|
||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -405,13 +405,13 @@ int Fuse::mkdir(const bf::path &path, mode_t mode) {
|
||||
|
||||
int Fuse::unlink(const bf::path &path) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "unlink(" << path << ")";
|
||||
LOG(DEBUG, "unlink({})", path);
|
||||
#endif
|
||||
try {
|
||||
_fs->unlink(path);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::unlink: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::unlink: {}", e.what());
|
||||
return -EIO;
|
||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -426,13 +426,13 @@ int Fuse::unlink(const bf::path &path) {
|
||||
|
||||
int Fuse::rmdir(const bf::path &path) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "rmdir(" << path << ")";
|
||||
LOG(DEBUG, "rmdir({})", path);
|
||||
#endif
|
||||
try {
|
||||
_fs->rmdir(path);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::rmdir: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::rmdir: {}", e.what());
|
||||
return -EIO;
|
||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -447,14 +447,14 @@ int Fuse::rmdir(const bf::path &path) {
|
||||
|
||||
int Fuse::symlink(const bf::path &from, const bf::path &to) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "symlink(" << from << ", " << to << ")";
|
||||
LOG(DEBUG, "symlink({}, {})", from, to);
|
||||
#endif
|
||||
try {
|
||||
auto context = fuse_get_context();
|
||||
_fs->createSymlink(from, to, context->uid, context->gid);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::symlink: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::symlink: {}", e.what());
|
||||
return -EIO;
|
||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -469,7 +469,7 @@ int Fuse::symlink(const bf::path &from, const bf::path &to) {
|
||||
|
||||
int Fuse::rename(const bf::path &from, const bf::path &to) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "rename(" << from << ", " << to << ")";
|
||||
LOG(DEBUG, "rename({}, {})", from, to);
|
||||
#endif
|
||||
try {
|
||||
ASSERT(from.is_absolute(), "from has to be an absolute path");
|
||||
@ -477,7 +477,7 @@ int Fuse::rename(const bf::path &from, const bf::path &to) {
|
||||
_fs->rename(from, to);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::rename: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::rename: {}", e.what());
|
||||
return -EIO;
|
||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -492,7 +492,7 @@ int Fuse::rename(const bf::path &from, const bf::path &to) {
|
||||
|
||||
//TODO
|
||||
int Fuse::link(const bf::path &from, const bf::path &to) {
|
||||
LOG(WARN) << "NOT IMPLEMENTED: link(" << from << ", " << to << ")";
|
||||
LOG(WARN, "NOT IMPLEMENTED: link({}, {})", from, to);
|
||||
//auto real_from = _impl->RootDir() / from;
|
||||
//auto real_to = _impl->RootDir() / to;
|
||||
//int retstat = ::link(real_from.c_str(), real_to.c_str());
|
||||
@ -502,13 +502,13 @@ int Fuse::link(const bf::path &from, const bf::path &to) {
|
||||
|
||||
int Fuse::chmod(const bf::path &path, mode_t mode) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "chmod(" << path << ", " << mode << ")";
|
||||
LOG(DEBUG, "chmod({}, {})", path, mode);
|
||||
#endif
|
||||
try {
|
||||
_fs->chmod(path, mode);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::chmod: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::chmod: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (fspp::fuse::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -523,13 +523,13 @@ int Fuse::chmod(const bf::path &path, mode_t mode) {
|
||||
|
||||
int Fuse::chown(const bf::path &path, uid_t uid, gid_t gid) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "chown(" << path << ", " << uid << ", " << gid << ")";
|
||||
LOG(DEBUG, "chown({}, {}, {})", path, uid, gid);
|
||||
#endif
|
||||
try {
|
||||
_fs->chown(path, uid, gid);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::chown: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::chown: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (fspp::fuse::FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -544,13 +544,13 @@ int Fuse::chown(const bf::path &path, uid_t uid, gid_t gid) {
|
||||
|
||||
int Fuse::truncate(const bf::path &path, off_t size) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "truncate(" << path << ", " << size << ")";
|
||||
LOG(DEBUG, "truncate({}, {})", path, size);
|
||||
#endif
|
||||
try {
|
||||
_fs->truncate(path, size);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::truncate: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::truncate: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -565,14 +565,14 @@ int Fuse::truncate(const bf::path &path, off_t size) {
|
||||
|
||||
int Fuse::ftruncate(const bf::path &path, off_t size, fuse_file_info *fileinfo) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "ftruncate(" << path << ", " << size << ")";
|
||||
LOG(DEBUG, "ftruncate({}, {})", path, size);
|
||||
#endif
|
||||
UNUSED(path);
|
||||
try {
|
||||
_fs->ftruncate(fileinfo->fh, size);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::ftruncate: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::ftruncate: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -587,13 +587,13 @@ int Fuse::ftruncate(const bf::path &path, off_t size, fuse_file_info *fileinfo)
|
||||
|
||||
int Fuse::utimens(const bf::path &path, const timespec times[2]) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "utimens(" << path << ", _)";
|
||||
LOG(DEBUG, "utimens({}, _)", path);
|
||||
#endif
|
||||
try {
|
||||
_fs->utimens(path, times[0], times[1]);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::utimens: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::utimens: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -608,13 +608,13 @@ int Fuse::utimens(const bf::path &path, const timespec times[2]) {
|
||||
|
||||
int Fuse::open(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "open(" << path << ", _)";
|
||||
LOG(DEBUG, "open({}, _)", path);
|
||||
#endif
|
||||
try {
|
||||
fileinfo->fh = _fs->openFile(path, fileinfo->flags);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::open: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::open: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -629,14 +629,14 @@ int Fuse::open(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
|
||||
int Fuse::release(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "release(" << path << ", _)";
|
||||
LOG(DEBUG, "release({}, _)", path);
|
||||
#endif
|
||||
UNUSED(path);
|
||||
try {
|
||||
_fs->closeFile(fileinfo->fh);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::release: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::release: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -651,13 +651,13 @@ int Fuse::release(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
|
||||
int Fuse::read(const bf::path &path, char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "read(" << path << ", _, " << size << ", " << offset << ", _ )";
|
||||
LOG(DEBUG, "read({}, _, {}, {}, _)", path, size, offset);
|
||||
#endif
|
||||
UNUSED(path);
|
||||
try {
|
||||
return _fs->read(fileinfo->fh, buf, size, offset);
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::read: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::read: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -672,14 +672,14 @@ int Fuse::read(const bf::path &path, char *buf, size_t size, off_t offset, fuse_
|
||||
|
||||
int Fuse::write(const bf::path &path, const char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "write(" << path << ", _, " << size << ", " << offset << ", _)";
|
||||
LOG(DEBUG, "write({}, _, {}, {}, _)", path, size, offsset);
|
||||
#endif
|
||||
UNUSED(path);
|
||||
try {
|
||||
_fs->write(fileinfo->fh, buf, size, offset);
|
||||
return size;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::write: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::write: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -695,13 +695,13 @@ int Fuse::write(const bf::path &path, const char *buf, size_t size, off_t offset
|
||||
//TODO
|
||||
int Fuse::statfs(const bf::path &path, struct statvfs *fsstat) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "statfs(" << path << ", _)";
|
||||
LOG(DEBUG, "statfs({}, _)", path);
|
||||
#endif
|
||||
try {
|
||||
_fs->statfs(path, fsstat);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::statfs: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::statfs: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -716,14 +716,14 @@ int Fuse::statfs(const bf::path &path, struct statvfs *fsstat) {
|
||||
|
||||
int Fuse::flush(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(WARN) << "flush(" << path << ", _)";
|
||||
LOG(WARN, "flush({}, _)", path);
|
||||
#endif
|
||||
UNUSED(path);
|
||||
try {
|
||||
_fs->flush(fileinfo->fh);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::flush: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::flush: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -738,7 +738,7 @@ int Fuse::flush(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
|
||||
int Fuse::fsync(const bf::path &path, int datasync, fuse_file_info *fileinfo) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "fsync(" << path << ", " << datasync << ", _)";
|
||||
LOG(DEBUG, "fsync({}, {}, _)", path, datasync);
|
||||
#endif
|
||||
UNUSED(path);
|
||||
try {
|
||||
@ -749,7 +749,7 @@ int Fuse::fsync(const bf::path &path, int datasync, fuse_file_info *fileinfo) {
|
||||
}
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::fsync: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::fsync: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -765,14 +765,14 @@ int Fuse::fsync(const bf::path &path, int datasync, fuse_file_info *fileinfo) {
|
||||
int Fuse::opendir(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
UNUSED(path);
|
||||
UNUSED(fileinfo);
|
||||
//LOG(DEBUG) << "opendir(" << path << ", _)";
|
||||
//LOG(DEBUG, "opendir({}, _)", path);
|
||||
//We don't need opendir, because readdir works directly on the path
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Fuse::readdir(const bf::path &path, void *buf, fuse_fill_dir_t filler, off_t offset, fuse_file_info *fileinfo) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "readdir(" << path << ", _, _, " << offset << ", _)";
|
||||
LOG(DEBUG, "readdir({}, _, _, {}, _)", path, offest);
|
||||
#endif
|
||||
UNUSED(fileinfo);
|
||||
UNUSED(offset);
|
||||
@ -799,7 +799,7 @@ int Fuse::readdir(const bf::path &path, void *buf, fuse_fill_dir_t filler, off_t
|
||||
}
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::readdir: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::readdir: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -815,7 +815,7 @@ int Fuse::readdir(const bf::path &path, void *buf, fuse_fill_dir_t filler, off_t
|
||||
int Fuse::releasedir(const bf::path &path, fuse_file_info *fileinfo) {
|
||||
UNUSED(path);
|
||||
UNUSED(fileinfo);
|
||||
//LOG(DEBUG) << "releasedir(" << path << ", _)";
|
||||
//LOG(DEBUG, "releasedir({}, _)", path);
|
||||
//We don't need releasedir, because readdir works directly on the path
|
||||
return 0;
|
||||
}
|
||||
@ -825,13 +825,13 @@ int Fuse::fsyncdir(const bf::path &path, int datasync, fuse_file_info *fileinfo)
|
||||
UNUSED(fileinfo);
|
||||
UNUSED(datasync);
|
||||
UNUSED(path);
|
||||
//LOG(WARN) << "Called non-implemented fsyncdir(" << path << ", " << datasync << ", _)";
|
||||
//LOG(WARN, "Called non-implemented fsyncdir({}, {}, _)", path, datasync);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Fuse::init(fuse_conn_info *conn) {
|
||||
UNUSED(conn);
|
||||
LOG(INFO) << "Filesystem started.";
|
||||
LOG(INFO, "Filesystem started.");
|
||||
|
||||
_running = true;
|
||||
|
||||
@ -841,19 +841,19 @@ void Fuse::init(fuse_conn_info *conn) {
|
||||
}
|
||||
|
||||
void Fuse::destroy() {
|
||||
LOG(INFO) << "Filesystem stopped.";
|
||||
LOG(INFO, "Filesystem stopped.");
|
||||
_running = false;
|
||||
}
|
||||
|
||||
int Fuse::access(const bf::path &path, int mask) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "access(" << path << ", " << mask << ")";
|
||||
LOG(DEBUG, "access({}, {})", path, mask);
|
||||
#endif
|
||||
try {
|
||||
_fs->access(path, mask);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::access: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::access: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
@ -868,14 +868,14 @@ int Fuse::access(const bf::path &path, int mask) {
|
||||
|
||||
int Fuse::create(const bf::path &path, mode_t mode, fuse_file_info *fileinfo) {
|
||||
#ifdef FSPP_LOG
|
||||
LOG(DEBUG) << "create(" << path << ", " << mode << ", _)";
|
||||
LOG(DEBUG, "create({}, {}, _)", path, mode);
|
||||
#endif
|
||||
try {
|
||||
auto context = fuse_get_context();
|
||||
fileinfo->fh = _fs->createAndOpenFile(path, mode, context->uid, context->gid);
|
||||
return 0;
|
||||
} catch(const cpputils::AssertFailed &e) {
|
||||
LOG(ERROR) << "AssertFailed in Fuse::create: " << e.what();
|
||||
LOG(ERROR, "AssertFailed in Fuse::create: {}", e.what());
|
||||
return -EIO;
|
||||
} catch (FuseErrnoException &e) {
|
||||
return -e.getErrno();
|
||||
|
@ -88,7 +88,7 @@ FilesystemImpl::~FilesystemImpl() {
|
||||
<< std::setw(40) << "CreateSymlink (without loading): " << static_cast<double>(_createSymlinkNanosec_withoutLoading)/1000000000 << "\n"
|
||||
<< std::setw(40) << "ReadSymlink: " << static_cast<double>(_readSymlinkNanosec)/1000000000 << "\n"
|
||||
<< std::setw(40) << "ReadSymlink (without loading): " << static_cast<double>(_readSymlinkNanosec_withoutLoading)/1000000000 << "\n";
|
||||
LOG(INFO) << profilerInformation.str();
|
||||
LOG(INFO, profilerInformation.str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -7,42 +7,42 @@ using testing::MatchesRegex;
|
||||
class LoggingLevelTest: public LoggingTest {
|
||||
public:
|
||||
void EXPECT_DEBUG_LOG_ENABLED() {
|
||||
LOG(DEBUG) << "My log message";
|
||||
LOG(DEBUG, "My log message");
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[debug\\].*My log message.*"));
|
||||
}
|
||||
|
||||
void EXPECT_DEBUG_LOG_DISABLED() {
|
||||
LOG(DEBUG) << "My log message";
|
||||
LOG(DEBUG, "My log message");
|
||||
EXPECT_EQ("", mockLogger.capturedLog());
|
||||
}
|
||||
|
||||
void EXPECT_INFO_LOG_ENABLED() {
|
||||
LOG(INFO) << "My log message";
|
||||
LOG(INFO, "My log message");
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
|
||||
void EXPECT_INFO_LOG_DISABLED() {
|
||||
LOG(INFO) << "My log message";
|
||||
LOG(INFO, "My log message");
|
||||
EXPECT_EQ("", mockLogger.capturedLog());
|
||||
}
|
||||
|
||||
void EXPECT_WARNING_LOG_ENABLED() {
|
||||
LOG(WARN) << "My log message";
|
||||
LOG(WARN, "My log message");
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[warning\\].*My log message.*"));
|
||||
}
|
||||
|
||||
void EXPECT_WARNING_LOG_DISABLED() {
|
||||
LOG(WARN) << "My log message";
|
||||
LOG(WARN, "My log message");
|
||||
EXPECT_EQ("", mockLogger.capturedLog());
|
||||
}
|
||||
|
||||
void EXPECT_ERROR_LOG_ENABLED() {
|
||||
LOG(ERROR) << "My log message";
|
||||
LOG(ERROR, "My log message");
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[error\\].*My log message.*"));
|
||||
}
|
||||
|
||||
void EXPECT_ERROR_LOG_DISABLED() {
|
||||
LOG(ERROR) << "My log message";
|
||||
LOG(ERROR, "My log message");
|
||||
EXPECT_EQ("", mockLogger.capturedLog());
|
||||
}
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
* Contains test cases for the following logging interface:
|
||||
* LOG(INFO) << "My log message"
|
||||
* LOG(INFO, "My log message)"
|
||||
*/
|
||||
|
||||
using namespace cpputils::logging;
|
||||
@ -11,7 +11,7 @@ using testing::MatchesRegex;
|
||||
|
||||
TEST_F(LoggingTest, DefaultLoggerIsStderr) {
|
||||
string output = captureStderr([]{
|
||||
LOG(INFO) << "My log message";
|
||||
LOG(INFO, "My log message");
|
||||
});
|
||||
EXPECT_THAT(output, MatchesRegex(".*\\[Log\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
@ -19,52 +19,52 @@ TEST_F(LoggingTest, DefaultLoggerIsStderr) {
|
||||
TEST_F(LoggingTest, SetLogger_NewLoggerIsUsed) {
|
||||
setLogger(spdlog::stderr_logger_mt("MyTestLog2"));
|
||||
string output = captureStderr([]{
|
||||
LOG(INFO) << "My log message";
|
||||
LOG(INFO, "My log message");
|
||||
});
|
||||
EXPECT_THAT(output, MatchesRegex(".*\\[MyTestLog2\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, SetNonStderrLogger_LogsToNewLogger) {
|
||||
setLogger(mockLogger.get());
|
||||
logger()->info() << "My log message";
|
||||
logger()->info("My log message");
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, SetNonStderrLogger_DoesNotLogToStderr) {
|
||||
setLogger(mockLogger.get());
|
||||
string output = captureStderr([] {
|
||||
logger()->info() << "My log message";
|
||||
logger()->info("My log message");
|
||||
});
|
||||
EXPECT_EQ("", output);
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, InfoLog) {
|
||||
setLogger(mockLogger.get());
|
||||
LOG(INFO) << "My log message";
|
||||
LOG(INFO, "My log message");
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, WarningLog) {
|
||||
setLogger(mockLogger.get());
|
||||
LOG(WARN) << "My log message";
|
||||
LOG(WARN, "My log message");
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[warning\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, DebugLog) {
|
||||
setLevel(DEBUG);
|
||||
setLogger(mockLogger.get());
|
||||
LOG(DEBUG) << "My log message";
|
||||
LOG(DEBUG, "My log message");
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[debug\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, ErrorLog) {
|
||||
setLogger(mockLogger.get());
|
||||
LOG(ERROR) << "My log message";
|
||||
LOG(ERROR, "My log message");
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[error\\].*My log message.*"));
|
||||
}
|
||||
|
||||
void logAndExit(const string &message) {
|
||||
LOG(INFO) << message;
|
||||
LOG(INFO, message);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -78,3 +78,41 @@ TEST_F(LoggingTest, LoggingAlsoWorksAfterFork) {
|
||||
"My log message"
|
||||
);
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, MessageIsConstChar) {
|
||||
setLogger(mockLogger.get());
|
||||
LOG(INFO, "My log message");
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, MessageIsString) {
|
||||
setLogger(mockLogger.get());
|
||||
string msg = "My log message";
|
||||
LOG(INFO, msg);
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, FormatWithStringPlaceholder) {
|
||||
setLogger(mockLogger.get());
|
||||
string str = "placeholder";
|
||||
LOG(INFO, "My log message: {}", str);
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message: placeholder.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, FormatWithConstCharPlaceholder) {
|
||||
setLogger(mockLogger.get());
|
||||
LOG(INFO, "My log message: {}", "placeholder");
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message: placeholder.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, FormatWithIntPlaceholder) {
|
||||
setLogger(mockLogger.get());
|
||||
LOG(INFO, "My log message: {}", 4);
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message: 4.*"));
|
||||
}
|
||||
|
||||
TEST_F(LoggingTest, FormatWithMultiplePlaceholders) {
|
||||
setLogger(mockLogger.get());
|
||||
LOG(INFO, "My log message: {}, {}, {}", 4, "then", true);
|
||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message: 4, then, true.*"));
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include "cpp-utils/logging/logging.h"
|
||||
#include <spdlog/sinks/ostream_sink.h>
|
||||
|
||||
class MockLogger final {
|
||||
public:
|
||||
|
3
vendor/README
vendored
3
vendor/README
vendored
@ -1,5 +1,4 @@
|
||||
This directory contains external projects, taken from the following locations:
|
||||
scrypt: http://www.tarsnap.com/scrypt.html
|
||||
googletest: https://github.com/google/googletest/tree/release-1.8.0
|
||||
spdlog: https://github.com/gabime/spdlog/commit/0c7beb2e36008598cf80d0e8eb8635ac403febb9
|
||||
- with own fix: https://github.com/cryfs/spdlog/commit/7b8d507615b8075fc6c8793a0965a32a708288c4
|
||||
spdlog: https://github.com/gabime/spdlog/tree/v0.11.0/include/spdlog
|
||||
|
2
vendor/spdlog/CMakeLists.txt
vendored
2
vendor/spdlog/CMakeLists.txt
vendored
@ -5,4 +5,4 @@ set(SOURCES
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCES})
|
||||
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
27
vendor/spdlog/spdlog/async_logger.h
vendored
27
vendor/spdlog/spdlog/async_logger.h
vendored
@ -13,14 +13,15 @@
|
||||
// 1. Checks if its log level is enough to log the message
|
||||
// 2. Push a new copy of the message to a queue (or block the caller until space is available in the queue)
|
||||
// 3. will throw spdlog_ex upon log exceptions
|
||||
// Upong destruction, logs all remaining messages in the queue before destructing..
|
||||
// Upon destruction, logs all remaining messages in the queue before destructing..
|
||||
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/logger.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include "common.h"
|
||||
#include "logger.h"
|
||||
#include "spdlog.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -40,26 +41,30 @@ public:
|
||||
size_t queue_size,
|
||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
||||
const std::function<void()>& worker_warmup_cb = nullptr,
|
||||
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
|
||||
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
|
||||
const std::function<void()>& worker_teardown_cb = nullptr);
|
||||
|
||||
async_logger(const std::string& logger_name,
|
||||
sinks_init_list sinks,
|
||||
size_t queue_size,
|
||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
||||
const std::function<void()>& worker_warmup_cb = nullptr,
|
||||
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
|
||||
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
|
||||
const std::function<void()>& worker_teardown_cb = nullptr);
|
||||
|
||||
async_logger(const std::string& logger_name,
|
||||
sink_ptr single_sink,
|
||||
size_t queue_size,
|
||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
||||
const std::function<void()>& worker_warmup_cb = nullptr,
|
||||
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
|
||||
|
||||
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
|
||||
const std::function<void()>& worker_teardown_cb = nullptr);
|
||||
|
||||
//Wait for the queue to be empty, and flush synchronously
|
||||
//Warning: this can potentialy last forever as we wait it to complete
|
||||
void flush() override;
|
||||
protected:
|
||||
void _log_msg(details::log_msg& msg) override;
|
||||
void _sink_it(details::log_msg& msg) override;
|
||||
void _set_formatter(spdlog::formatter_ptr msg_formatter) override;
|
||||
void _set_pattern(const std::string& pattern) override;
|
||||
|
||||
@ -69,4 +74,4 @@ private:
|
||||
}
|
||||
|
||||
|
||||
#include "./details/async_logger_impl.h"
|
||||
#include <spdlog/details/async_logger_impl.h>
|
||||
|
82
vendor/spdlog/spdlog/common.h
vendored
82
vendor/spdlog/spdlog/common.h
vendored
@ -9,14 +9,36 @@
|
||||
#include <initializer_list>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
#include <exception>
|
||||
#include<functional>
|
||||
|
||||
//visual studio does not support noexcept yet
|
||||
#ifndef _MSC_VER
|
||||
#define SPDLOG_NOEXCEPT noexcept
|
||||
#else
|
||||
#define SPDLOG_NOEXCEPT throw()
|
||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#endif
|
||||
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
|
||||
//visual studio upto 2013 does not support noexcept nor constexpr
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
||||
#define SPDLOG_NOEXCEPT throw()
|
||||
#define SPDLOG_CONSTEXPR
|
||||
#else
|
||||
#define SPDLOG_NOEXCEPT noexcept
|
||||
#define SPDLOG_CONSTEXPR constexpr
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define DEPRECATED __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER)
|
||||
#define DEPRECATED __declspec(deprecated)
|
||||
#else
|
||||
#define DEPRECATED
|
||||
#endif
|
||||
|
||||
|
||||
#include <spdlog/fmt/fmt.h>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -28,12 +50,17 @@ namespace sinks
|
||||
class sink;
|
||||
}
|
||||
|
||||
// Common types across the lib
|
||||
using log_clock = std::chrono::system_clock;
|
||||
using sink_ptr = std::shared_ptr < sinks::sink >;
|
||||
using sinks_init_list = std::initializer_list < sink_ptr >;
|
||||
using formatter_ptr = std::shared_ptr<spdlog::formatter>;
|
||||
#if defined(SPDLOG_NO_ATOMIC_LEVELS)
|
||||
using level_t = details::null_atomic_int;
|
||||
#else
|
||||
using level_t = std::atomic_int;
|
||||
#endif
|
||||
|
||||
using log_err_handler = std::function<void(const std::string &err_msg)>;
|
||||
|
||||
//Log level enum
|
||||
namespace level
|
||||
@ -43,18 +70,15 @@ typedef enum
|
||||
trace = 0,
|
||||
debug = 1,
|
||||
info = 2,
|
||||
notice = 3,
|
||||
warn = 4,
|
||||
err = 5,
|
||||
critical = 6,
|
||||
alert = 7,
|
||||
emerg = 8,
|
||||
off = 9
|
||||
warn = 3,
|
||||
err = 4,
|
||||
critical = 5,
|
||||
off = 6
|
||||
} level_enum;
|
||||
|
||||
static const char* level_names[] { "trace", "debug", "info", "notice", "warning", "error", "critical", "alert", "emerg", "off"};
|
||||
static const char* level_names[] { "trace", "debug", "info", "warning", "error", "critical", "off" };
|
||||
|
||||
static const char* short_level_names[] { "T", "D", "I", "N", "W", "E", "C", "A", "M", "O"};
|
||||
static const char* short_level_names[] { "T", "D", "I", "W", "E", "C", "O" };
|
||||
|
||||
inline const char* to_str(spdlog::level::level_enum l)
|
||||
{
|
||||
@ -81,10 +105,22 @@ enum class async_overflow_policy
|
||||
//
|
||||
// Log exception
|
||||
//
|
||||
class spdlog_ex : public std::exception
|
||||
namespace details
|
||||
{
|
||||
namespace os
|
||||
{
|
||||
std::string errno_str(int err_num);
|
||||
}
|
||||
}
|
||||
class spdlog_ex: public std::exception
|
||||
{
|
||||
public:
|
||||
spdlog_ex(const std::string& msg) :_msg(msg) {}
|
||||
spdlog_ex(const std::string& msg):_msg(msg)
|
||||
{}
|
||||
spdlog_ex(const std::string& msg, int last_errno)
|
||||
{
|
||||
_msg = msg + ": " + details::os::errno_str(last_errno);
|
||||
}
|
||||
const char* what() const SPDLOG_NOEXCEPT override
|
||||
{
|
||||
return _msg.c_str();
|
||||
@ -94,4 +130,14 @@ private:
|
||||
|
||||
};
|
||||
|
||||
} //spdlog
|
||||
//
|
||||
// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
|
||||
//
|
||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
|
||||
using filename_t = std::wstring;
|
||||
#else
|
||||
using filename_t = std::string;
|
||||
#endif
|
||||
|
||||
|
||||
} //spdlog
|
||||
|
124
vendor/spdlog/spdlog/details/async_log_helper.h
vendored
124
vendor/spdlog/spdlog/details/async_log_helper.h
vendored
@ -14,17 +14,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/sinks/sink.h>
|
||||
#include <spdlog/details/mpmc_bounded_q.h>
|
||||
#include <spdlog/details/log_msg.h>
|
||||
#include <spdlog/details/os.h>
|
||||
#include <spdlog/formatter.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
|
||||
#include "../common.h"
|
||||
#include "../sinks/sink.h"
|
||||
#include "./mpmc_bounded_q.h"
|
||||
#include "./log_msg.h"
|
||||
#include "./format.h"
|
||||
#include "./os.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -82,21 +86,22 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
|
||||
|
||||
// construct from log_msg
|
||||
async_msg(const details::log_msg& m) :
|
||||
logger_name(m.logger_name),
|
||||
level(m.level),
|
||||
time(m.time),
|
||||
thread_id(m.thread_id),
|
||||
txt(m.raw.data(), m.raw.size()),
|
||||
msg_type(async_msg_type::log)
|
||||
{}
|
||||
|
||||
{
|
||||
#ifndef SPDLOG_NO_NAME
|
||||
logger_name = *m.logger_name;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// copy into log_msg
|
||||
void fill_log_msg(log_msg &msg)
|
||||
{
|
||||
msg.clear();
|
||||
msg.logger_name = logger_name;
|
||||
msg.logger_name = &logger_name;
|
||||
msg.level = level;
|
||||
msg.time = time;
|
||||
msg.thread_id = thread_id;
|
||||
@ -115,9 +120,11 @@ public:
|
||||
async_log_helper(formatter_ptr formatter,
|
||||
const std::vector<sink_ptr>& sinks,
|
||||
size_t queue_size,
|
||||
const log_err_handler err_handler,
|
||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
||||
const std::function<void()>& worker_warmup_cb = nullptr,
|
||||
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
|
||||
const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(),
|
||||
const std::function<void()>& worker_teardown_cb = nullptr);
|
||||
|
||||
void log(const details::log_msg& msg);
|
||||
|
||||
@ -126,7 +133,7 @@ public:
|
||||
|
||||
void set_formatter(formatter_ptr);
|
||||
|
||||
void flush();
|
||||
void flush(bool wait_for_q);
|
||||
|
||||
|
||||
private:
|
||||
@ -136,14 +143,13 @@ private:
|
||||
// queue of messages to log
|
||||
q_type _q;
|
||||
|
||||
log_err_handler _err_handler;
|
||||
|
||||
bool _flush_requested;
|
||||
|
||||
bool _terminate_requested;
|
||||
|
||||
|
||||
// last exception thrown from the worker thread
|
||||
std::shared_ptr<spdlog_ex> _last_workerthread_ex;
|
||||
|
||||
// overflow policy
|
||||
const async_overflow_policy _overflow_policy;
|
||||
|
||||
@ -153,13 +159,13 @@ private:
|
||||
// auto periodic sink flush parameter
|
||||
const std::chrono::milliseconds _flush_interval_ms;
|
||||
|
||||
// worker thread teardown callback
|
||||
const std::function<void()> _worker_teardown_cb;
|
||||
|
||||
// worker thread
|
||||
std::thread _worker_thread;
|
||||
|
||||
void push_msg(async_msg&& new_msg);
|
||||
// throw last worker thread exception or if worker thread is not active
|
||||
|
||||
void throw_if_bad_worker();
|
||||
|
||||
// worker thread main loop
|
||||
void worker_loop();
|
||||
@ -173,6 +179,9 @@ private:
|
||||
// sleep,yield or return immediatly using the time passed since last message as a hint
|
||||
static void sleep_or_yield(const spdlog::log_clock::time_point& now, const log_clock::time_point& last_op_time);
|
||||
|
||||
// wait until the queue is empty
|
||||
void wait_empty_q();
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -184,17 +193,21 @@ inline spdlog::details::async_log_helper::async_log_helper(
|
||||
formatter_ptr formatter,
|
||||
const std::vector<sink_ptr>& sinks,
|
||||
size_t queue_size,
|
||||
log_err_handler err_handler,
|
||||
const async_overflow_policy overflow_policy,
|
||||
const std::function<void()>& worker_warmup_cb,
|
||||
const std::chrono::milliseconds& flush_interval_ms):
|
||||
const std::chrono::milliseconds& flush_interval_ms,
|
||||
const std::function<void()>& worker_teardown_cb):
|
||||
_formatter(formatter),
|
||||
_sinks(sinks),
|
||||
_q(queue_size),
|
||||
_err_handler(err_handler),
|
||||
_flush_requested(false),
|
||||
_terminate_requested(false),
|
||||
_overflow_policy(overflow_policy),
|
||||
_worker_warmup_cb(worker_warmup_cb),
|
||||
_flush_interval_ms(flush_interval_ms),
|
||||
_worker_teardown_cb(worker_teardown_cb),
|
||||
_worker_thread(&async_log_helper::worker_loop, this)
|
||||
{}
|
||||
|
||||
@ -212,7 +225,7 @@ inline spdlog::details::async_log_helper::~async_log_helper()
|
||||
}
|
||||
|
||||
|
||||
//Try to push and block until succeeded
|
||||
//Try to push and block until succeeded (if the policy is not to discard when the queue is full)
|
||||
inline void spdlog::details::async_log_helper::log(const details::log_msg& msg)
|
||||
{
|
||||
push_msg(async_msg(msg));
|
||||
@ -220,10 +233,8 @@ inline void spdlog::details::async_log_helper::log(const details::log_msg& msg)
|
||||
|
||||
}
|
||||
|
||||
//Try to push and block until succeeded
|
||||
inline void spdlog::details::async_log_helper::push_msg(details::async_log_helper::async_msg&& new_msg)
|
||||
{
|
||||
throw_if_bad_worker();
|
||||
if (!_q.enqueue(std::move(new_msg)) && _overflow_policy != async_overflow_policy::discard_log_msg)
|
||||
{
|
||||
auto last_op_time = details::os::now();
|
||||
@ -238,9 +249,12 @@ inline void spdlog::details::async_log_helper::push_msg(details::async_log_helpe
|
||||
|
||||
}
|
||||
|
||||
inline void spdlog::details::async_log_helper::flush()
|
||||
// optionally wait for the queue be empty and request flush from the sinks
|
||||
inline void spdlog::details::async_log_helper::flush(bool wait_for_q)
|
||||
{
|
||||
push_msg(async_msg(async_msg_type::flush));
|
||||
if(wait_for_q)
|
||||
wait_empty_q(); //return only make after the above flush message was processed
|
||||
}
|
||||
|
||||
inline void spdlog::details::async_log_helper::worker_loop()
|
||||
@ -251,24 +265,25 @@ inline void spdlog::details::async_log_helper::worker_loop()
|
||||
auto last_pop = details::os::now();
|
||||
auto last_flush = last_pop;
|
||||
while(process_next_msg(last_pop, last_flush));
|
||||
if (_worker_teardown_cb) _worker_teardown_cb();
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
_last_workerthread_ex = std::make_shared<spdlog_ex>(std::string("async_logger worker thread exception: ") + ex.what());
|
||||
_err_handler(ex.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
_last_workerthread_ex = std::make_shared<spdlog_ex>("async_logger worker thread exception");
|
||||
_err_handler("Unknown exception");
|
||||
}
|
||||
}
|
||||
|
||||
// process next message in the queue
|
||||
// return true if this thread should still be active (no msg with level::off was received)
|
||||
// return true if this thread should still be active (while no terminate msg was received)
|
||||
inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_point& last_pop, log_clock::time_point& last_flush)
|
||||
{
|
||||
|
||||
async_msg incoming_async_msg;
|
||||
log_msg incoming_log_msg;
|
||||
|
||||
|
||||
if (_q.dequeue(incoming_async_msg))
|
||||
{
|
||||
@ -285,10 +300,16 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
|
||||
break;
|
||||
|
||||
default:
|
||||
log_msg incoming_log_msg;
|
||||
incoming_async_msg.fill_log_msg(incoming_log_msg);
|
||||
_formatter->format(incoming_log_msg);
|
||||
for (auto &s : _sinks)
|
||||
s->log(incoming_log_msg);
|
||||
{
|
||||
if(s->should_log( incoming_log_msg.level))
|
||||
{
|
||||
s->log(incoming_log_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -301,10 +322,10 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
|
||||
handle_flush_interval(now, last_flush);
|
||||
sleep_or_yield(now, last_pop);
|
||||
return !_terminate_requested;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// flush all sinks if _flush_interval_ms has expired
|
||||
inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock::time_point& now, log_clock::time_point& last_flush)
|
||||
{
|
||||
auto should_flush = _flush_requested || (_flush_interval_ms != std::chrono::milliseconds::zero() && now - last_flush >= _flush_interval_ms);
|
||||
@ -316,44 +337,48 @@ inline void spdlog::details::async_log_helper::handle_flush_interval(log_clock::
|
||||
_flush_requested = false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter)
|
||||
{
|
||||
_formatter = msg_formatter;
|
||||
}
|
||||
|
||||
|
||||
// sleep,yield or return immediatly using the time passed since last message as a hint
|
||||
// spin, yield or sleep. use the time passed since last message as a hint
|
||||
inline void spdlog::details::async_log_helper::sleep_or_yield(const spdlog::log_clock::time_point& now, const spdlog::log_clock::time_point& last_op_time)
|
||||
{
|
||||
using std::chrono::milliseconds;
|
||||
using namespace std::this_thread;
|
||||
using std::chrono::milliseconds;
|
||||
using std::chrono::microseconds;
|
||||
|
||||
auto time_since_op = now - last_op_time;
|
||||
|
||||
// spin upto 1 ms
|
||||
if (time_since_op <= milliseconds(1))
|
||||
// spin upto 50 micros
|
||||
if (time_since_op <= microseconds(50))
|
||||
return;
|
||||
|
||||
// yield upto 10ms
|
||||
if (time_since_op <= milliseconds(10))
|
||||
// yield upto 150 micros
|
||||
if (time_since_op <= microseconds(100))
|
||||
return yield();
|
||||
|
||||
|
||||
// sleep for half of duration since last op
|
||||
if (time_since_op <= milliseconds(100))
|
||||
return sleep_for(time_since_op / 2);
|
||||
// sleep for 20 ms upto 200 ms
|
||||
if (time_since_op <= milliseconds(200))
|
||||
return sleep_for(milliseconds(20));
|
||||
|
||||
return sleep_for(milliseconds(100));
|
||||
// sleep for 200 ms
|
||||
return sleep_for(milliseconds(200));
|
||||
}
|
||||
|
||||
// throw if the worker thread threw an exception or not active
|
||||
inline void spdlog::details::async_log_helper::throw_if_bad_worker()
|
||||
// wait for the queue to be empty
|
||||
inline void spdlog::details::async_log_helper::wait_empty_q()
|
||||
{
|
||||
if (_last_workerthread_ex)
|
||||
auto last_op = details::os::now();
|
||||
while (_q.approx_size() > 0)
|
||||
{
|
||||
auto ex = std::move(_last_workerthread_ex);
|
||||
throw *ex;
|
||||
sleep_or_yield(details::os::now(), last_op);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -362,3 +387,4 @@ inline void spdlog::details::async_log_helper::throw_if_bad_worker()
|
||||
|
||||
|
||||
|
||||
|
||||
|
42
vendor/spdlog/spdlog/details/async_logger_impl.h
vendored
42
vendor/spdlog/spdlog/details/async_logger_impl.h
vendored
@ -8,8 +8,13 @@
|
||||
// Async Logger implementation
|
||||
// Use an async_sink (queue per logger) to perform the logging in a worker thread
|
||||
|
||||
#include "./async_log_helper.h"
|
||||
#include <spdlog/details/async_log_helper.h>
|
||||
#include <spdlog/async_logger.h>
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
template<class It>
|
||||
inline spdlog::async_logger::async_logger(const std::string& logger_name,
|
||||
@ -18,9 +23,10 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name,
|
||||
size_t queue_size,
|
||||
const async_overflow_policy overflow_policy,
|
||||
const std::function<void()>& worker_warmup_cb,
|
||||
const std::chrono::milliseconds& flush_interval_ms) :
|
||||
const std::chrono::milliseconds& flush_interval_ms,
|
||||
const std::function<void()>& worker_teardown_cb) :
|
||||
logger(logger_name, begin, end),
|
||||
_async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms))
|
||||
_async_log_helper(new details::async_log_helper(_formatter, _sinks, queue_size, _err_handler, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb))
|
||||
{
|
||||
}
|
||||
|
||||
@ -29,25 +35,26 @@ inline spdlog::async_logger::async_logger(const std::string& logger_name,
|
||||
size_t queue_size,
|
||||
const async_overflow_policy overflow_policy,
|
||||
const std::function<void()>& worker_warmup_cb,
|
||||
const std::chrono::milliseconds& flush_interval_ms) :
|
||||
async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {}
|
||||
const std::chrono::milliseconds& flush_interval_ms,
|
||||
const std::function<void()>& worker_teardown_cb) :
|
||||
async_logger(logger_name, sinks.begin(), sinks.end(), queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
|
||||
|
||||
inline spdlog::async_logger::async_logger(const std::string& logger_name,
|
||||
sink_ptr single_sink,
|
||||
size_t queue_size,
|
||||
const async_overflow_policy overflow_policy,
|
||||
const std::function<void()>& worker_warmup_cb,
|
||||
const std::chrono::milliseconds& flush_interval_ms) :
|
||||
const std::chrono::milliseconds& flush_interval_ms,
|
||||
const std::function<void()>& worker_teardown_cb) :
|
||||
async_logger(logger_name,
|
||||
{
|
||||
single_sink
|
||||
}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms) {}
|
||||
}, queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb) {}
|
||||
|
||||
|
||||
inline void spdlog::async_logger::flush()
|
||||
{
|
||||
|
||||
_async_log_helper->flush();
|
||||
_async_log_helper->flush(true);
|
||||
}
|
||||
|
||||
inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter)
|
||||
@ -63,7 +70,20 @@ inline void spdlog::async_logger::_set_pattern(const std::string& pattern)
|
||||
}
|
||||
|
||||
|
||||
inline void spdlog::async_logger::_log_msg(details::log_msg& msg)
|
||||
inline void spdlog::async_logger::_sink_it(details::log_msg& msg)
|
||||
{
|
||||
_async_log_helper->log(msg);
|
||||
try
|
||||
{
|
||||
_async_log_helper->log(msg);
|
||||
if (_should_flush_on(msg))
|
||||
_async_log_helper->flush(false); // do async flush
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
_err_handler(ex.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
_err_handler("Unknown exception");
|
||||
}
|
||||
}
|
||||
|
62
vendor/spdlog/spdlog/details/file_helper.h
vendored
62
vendor/spdlog/spdlog/details/file_helper.h
vendored
@ -10,13 +10,14 @@
|
||||
// Can be set to auto flush on every line
|
||||
// Throw spdlog_ex exception on errors
|
||||
|
||||
#include <spdlog/details/os.h>
|
||||
#include <spdlog/details/log_msg.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include "os.h"
|
||||
#include "log_msg.h"
|
||||
|
||||
|
||||
#include <cerrno>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -25,13 +26,13 @@ namespace details
|
||||
|
||||
class file_helper
|
||||
{
|
||||
|
||||
public:
|
||||
const int open_tries = 5;
|
||||
const int open_interval = 10;
|
||||
|
||||
explicit file_helper(bool force_flush) :
|
||||
_fd(nullptr),
|
||||
_force_flush(force_flush)
|
||||
explicit file_helper() :
|
||||
_fd(nullptr)
|
||||
{}
|
||||
|
||||
file_helper(const file_helper&) = delete;
|
||||
@ -43,11 +44,11 @@ public:
|
||||
}
|
||||
|
||||
|
||||
void open(const std::string& fname, bool truncate = false)
|
||||
void open(const filename_t& fname, bool truncate = false)
|
||||
{
|
||||
|
||||
close();
|
||||
const char* mode = truncate ? "wb" : "ab";
|
||||
auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
|
||||
_filename = fname;
|
||||
for (int tries = 0; tries < open_tries; ++tries)
|
||||
{
|
||||
@ -57,7 +58,7 @@ public:
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(open_interval));
|
||||
}
|
||||
|
||||
throw spdlog_ex("Failed opening file " + fname + " for writing");
|
||||
throw spdlog_ex("Failed opening file " + os::filename_to_str(_filename) + " for writing", errno);
|
||||
}
|
||||
|
||||
void reopen(bool truncate)
|
||||
@ -88,55 +89,30 @@ public:
|
||||
size_t msg_size = msg.formatted.size();
|
||||
auto data = msg.formatted.data();
|
||||
if (std::fwrite(data, 1, msg_size, _fd) != msg_size)
|
||||
throw spdlog_ex("Failed writing to file " + _filename);
|
||||
|
||||
if (_force_flush)
|
||||
std::fflush(_fd);
|
||||
|
||||
throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno);
|
||||
}
|
||||
|
||||
long size()
|
||||
size_t size()
|
||||
{
|
||||
if (!_fd)
|
||||
throw spdlog_ex("Cannot use size() on closed file " + _filename);
|
||||
|
||||
auto pos = ftell(_fd);
|
||||
if (fseek(_fd, 0, SEEK_END) != 0)
|
||||
throw spdlog_ex("fseek failed on file " + _filename);
|
||||
|
||||
auto file_size = ftell(_fd);
|
||||
|
||||
if(fseek(_fd, pos, SEEK_SET) !=0)
|
||||
throw spdlog_ex("fseek failed on file " + _filename);
|
||||
|
||||
if (file_size == -1)
|
||||
throw spdlog_ex("ftell failed on file " + _filename);
|
||||
|
||||
|
||||
return file_size;
|
||||
|
||||
|
||||
throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename));
|
||||
return os::filesize(_fd);
|
||||
}
|
||||
|
||||
const std::string& filename() const
|
||||
const filename_t& filename() const
|
||||
{
|
||||
return _filename;
|
||||
}
|
||||
|
||||
static bool file_exists(const std::string& name)
|
||||
static bool file_exists(const filename_t& name)
|
||||
{
|
||||
|
||||
return os::file_exists(name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
FILE* _fd;
|
||||
std::string _filename;
|
||||
bool _force_flush;
|
||||
|
||||
|
||||
filename_t _filename;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
949
vendor/spdlog/spdlog/details/format.cc
vendored
949
vendor/spdlog/spdlog/details/format.cc
vendored
@ -1,949 +0,0 @@
|
||||
/*
|
||||
Formatting library for C++
|
||||
|
||||
Copyright (c) 2012 - 2015, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "format.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
#include <cstddef> // for std::ptrdiff_t
|
||||
|
||||
#if defined(_WIN32) && defined(__MINGW32__)
|
||||
# include <cstring>
|
||||
#endif
|
||||
|
||||
#if FMT_USE_WINDOWS_H
|
||||
# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
|
||||
# include <windows.h>
|
||||
# else
|
||||
# define NOMINMAX
|
||||
# include <windows.h>
|
||||
# undef NOMINMAX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
using fmt::internal::Arg;
|
||||
|
||||
#if FMT_EXCEPTIONS
|
||||
# define FMT_TRY try
|
||||
# define FMT_CATCH(x) catch (x)
|
||||
#else
|
||||
# define FMT_TRY if (true)
|
||||
# define FMT_CATCH(x) if (false)
|
||||
#endif
|
||||
|
||||
#ifdef FMT_HEADER_ONLY
|
||||
# define FMT_FUNC inline
|
||||
#else
|
||||
# define FMT_FUNC
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127) // conditional expression is constant
|
||||
# pragma warning(disable: 4702) // unreachable code
|
||||
// Disable deprecation warning for strerror. The latter is not called but
|
||||
// MSVC fails to detect it.
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
// Dummy implementations of strerror_r and strerror_s called if corresponding
|
||||
// system functions are not available.
|
||||
static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
|
||||
return fmt::internal::Null<>();
|
||||
}
|
||||
static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
|
||||
return fmt::internal::Null<>();
|
||||
}
|
||||
|
||||
namespace fmt {
|
||||
namespace {
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# define FMT_SNPRINTF snprintf
|
||||
#else // _MSC_VER
|
||||
inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
# define FMT_SNPRINTF fmt_snprintf
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
|
||||
# define FMT_SWPRINTF snwprintf
|
||||
#else
|
||||
# define FMT_SWPRINTF swprintf
|
||||
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
|
||||
|
||||
// Checks if a value fits in int - used to avoid warnings about comparing
|
||||
// signed and unsigned integers.
|
||||
template <bool IsSigned>
|
||||
struct IntChecker {
|
||||
template <typename T>
|
||||
static bool fits_in_int(T value) {
|
||||
unsigned max = INT_MAX;
|
||||
return value <= max;
|
||||
}
|
||||
static bool fits_in_int(bool) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IntChecker<true> {
|
||||
template <typename T>
|
||||
static bool fits_in_int(T value) {
|
||||
return value >= INT_MIN && value <= INT_MAX;
|
||||
}
|
||||
static bool fits_in_int(int) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const char RESET_COLOR[] = "\x1b[0m";
|
||||
|
||||
typedef void(*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
|
||||
|
||||
// Portable thread-safe version of strerror.
|
||||
// Sets buffer to point to a string describing the error code.
|
||||
// This can be either a pointer to a string stored in buffer,
|
||||
// or a pointer to some static immutable string.
|
||||
// Returns one of the following values:
|
||||
// 0 - success
|
||||
// ERANGE - buffer is not large enough to store the error message
|
||||
// other - failure
|
||||
// Buffer should be at least of size 1.
|
||||
int safe_strerror(
|
||||
int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT{
|
||||
FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
|
||||
|
||||
class StrError {
|
||||
private:
|
||||
int error_code_;
|
||||
char *&buffer_;
|
||||
std::size_t buffer_size_;
|
||||
|
||||
// A noop assignment operator to avoid bogus warnings.
|
||||
void operator=(const StrError &) {}
|
||||
|
||||
// Handle the result of XSI-compliant version of strerror_r.
|
||||
int handle(int result) {
|
||||
// glibc versions before 2.13 return result in errno.
|
||||
return result == -1 ? errno : result;
|
||||
}
|
||||
|
||||
// Handle the result of GNU-specific version of strerror_r.
|
||||
int handle(char *message) {
|
||||
// If the buffer is full then the message is probably truncated.
|
||||
if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
|
||||
return ERANGE;
|
||||
buffer_ = message;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle the case when strerror_r is not available.
|
||||
int handle(fmt::internal::Null<>) {
|
||||
return fallback(strerror_s(buffer_, buffer_size_, error_code_));
|
||||
}
|
||||
|
||||
// Fallback to strerror_s when strerror_r is not available.
|
||||
int fallback(int result) {
|
||||
// If the buffer is full then the message is probably truncated.
|
||||
return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
|
||||
ERANGE : result;
|
||||
}
|
||||
|
||||
// Fallback to strerror if strerror_r and strerror_s are not available.
|
||||
int fallback(fmt::internal::Null<>) {
|
||||
errno = 0;
|
||||
buffer_ = strerror(error_code_);
|
||||
return errno;
|
||||
}
|
||||
|
||||
public:
|
||||
StrError(int err_code, char *&buf, std::size_t buf_size)
|
||||
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
|
||||
|
||||
int run() {
|
||||
strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
|
||||
return handle(strerror_r(error_code_, buffer_, buffer_size_));
|
||||
}
|
||||
};
|
||||
return StrError(error_code, buffer, buffer_size).run();
|
||||
}
|
||||
|
||||
void format_error_code(fmt::Writer &out, int error_code,
|
||||
fmt::StringRef message) FMT_NOEXCEPT{
|
||||
// Report error code making sure that the output fits into
|
||||
// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
|
||||
// bad_alloc.
|
||||
out.clear();
|
||||
static const char SEP[] = ": ";
|
||||
static const char ERROR_STR[] = "error ";
|
||||
fmt::internal::IntTraits<int>::MainType ec_value = error_code;
|
||||
// Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
|
||||
std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
|
||||
error_code_size += fmt::internal::count_digits(ec_value);
|
||||
if (message.size() <= fmt::internal::INLINE_BUFFER_SIZE - error_code_size)
|
||||
out << message << SEP;
|
||||
out << ERROR_STR << error_code;
|
||||
assert(out.size() <= fmt::internal::INLINE_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void report_error(FormatFunc func,
|
||||
int error_code, fmt::StringRef message) FMT_NOEXCEPT{
|
||||
fmt::MemoryWriter full_message;
|
||||
func(full_message, error_code, message);
|
||||
// Use Writer::data instead of Writer::c_str to avoid potential memory
|
||||
// allocation.
|
||||
std::fwrite(full_message.data(), full_message.size(), 1, stderr);
|
||||
std::fputc('\n', stderr);
|
||||
}
|
||||
|
||||
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
|
||||
class IsZeroInt : public fmt::internal::ArgVisitor<IsZeroInt, bool> {
|
||||
public:
|
||||
template <typename T>
|
||||
bool visit_any_int(T value) {
|
||||
return value == 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Checks if an argument is a valid printf width specifier and sets
|
||||
// left alignment if it is negative.
|
||||
class WidthHandler : public fmt::internal::ArgVisitor<WidthHandler, unsigned> {
|
||||
private:
|
||||
fmt::FormatSpec &spec_;
|
||||
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
|
||||
|
||||
public:
|
||||
explicit WidthHandler(fmt::FormatSpec &spec) : spec_(spec) {}
|
||||
|
||||
void report_unhandled_arg() {
|
||||
FMT_THROW(fmt::FormatError("width is not integer"));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
unsigned visit_any_int(T value) {
|
||||
typedef typename fmt::internal::IntTraits<T>::MainType UnsignedType;
|
||||
UnsignedType width = value;
|
||||
if (fmt::internal::is_negative(value)) {
|
||||
spec_.align_ = fmt::ALIGN_LEFT;
|
||||
width = 0 - width;
|
||||
}
|
||||
if (width > INT_MAX)
|
||||
FMT_THROW(fmt::FormatError("number is too big"));
|
||||
return static_cast<unsigned>(width);
|
||||
}
|
||||
};
|
||||
|
||||
class PrecisionHandler :
|
||||
public fmt::internal::ArgVisitor<PrecisionHandler, int> {
|
||||
public:
|
||||
void report_unhandled_arg() {
|
||||
FMT_THROW(fmt::FormatError("precision is not integer"));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int visit_any_int(T value) {
|
||||
if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
|
||||
FMT_THROW(fmt::FormatError("number is too big"));
|
||||
return static_cast<int>(value);
|
||||
}
|
||||
};
|
||||
|
||||
// Converts an integer argument to an integral type T for printf.
|
||||
template <typename T>
|
||||
class ArgConverter : public fmt::internal::ArgVisitor<ArgConverter<T>, void> {
|
||||
private:
|
||||
fmt::internal::Arg &arg_;
|
||||
wchar_t type_;
|
||||
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
|
||||
|
||||
public:
|
||||
ArgConverter(fmt::internal::Arg &arg, wchar_t type)
|
||||
: arg_(arg), type_(type) {}
|
||||
|
||||
void visit_bool(bool value) {
|
||||
if (type_ != 's')
|
||||
visit_any_int(value);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void visit_any_int(U value) {
|
||||
bool is_signed = type_ == 'd' || type_ == 'i';
|
||||
using fmt::internal::Arg;
|
||||
if (sizeof(T) <= sizeof(int)) {
|
||||
// Extra casts are used to silence warnings.
|
||||
if (is_signed) {
|
||||
arg_.type = Arg::INT;
|
||||
arg_.int_value = static_cast<int>(static_cast<T>(value));
|
||||
}
|
||||
else {
|
||||
arg_.type = Arg::UINT;
|
||||
arg_.uint_value = static_cast<unsigned>(
|
||||
static_cast<typename fmt::internal::MakeUnsigned<T>::Type>(value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (is_signed) {
|
||||
arg_.type = Arg::LONG_LONG;
|
||||
arg_.long_long_value =
|
||||
static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
|
||||
}
|
||||
else {
|
||||
arg_.type = Arg::ULONG_LONG;
|
||||
arg_.ulong_long_value =
|
||||
static_cast<typename fmt::internal::MakeUnsigned<U>::Type>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Converts an integer argument to char for printf.
|
||||
class CharConverter : public fmt::internal::ArgVisitor<CharConverter, void> {
|
||||
private:
|
||||
fmt::internal::Arg &arg_;
|
||||
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
|
||||
|
||||
public:
|
||||
explicit CharConverter(fmt::internal::Arg &arg) : arg_(arg) {}
|
||||
|
||||
template <typename T>
|
||||
void visit_any_int(T value) {
|
||||
arg_.type = Arg::CHAR;
|
||||
arg_.int_value = static_cast<char>(value);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename Char>
|
||||
class PrintfArgFormatter :
|
||||
public ArgFormatterBase<PrintfArgFormatter<Char>, Char> {
|
||||
|
||||
void write_null_pointer() {
|
||||
this->spec().type_ = 0;
|
||||
this->write("(nil)");
|
||||
}
|
||||
|
||||
typedef ArgFormatterBase<PrintfArgFormatter<Char>, Char> Base;
|
||||
|
||||
public:
|
||||
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
|
||||
: ArgFormatterBase<PrintfArgFormatter<Char>, Char>(w, s) {}
|
||||
|
||||
void visit_bool(bool value) {
|
||||
FormatSpec &fmt_spec = this->spec();
|
||||
if (fmt_spec.type_ != 's')
|
||||
return this->visit_any_int(value);
|
||||
fmt_spec.type_ = 0;
|
||||
this->write(value);
|
||||
}
|
||||
|
||||
void visit_char(int value) {
|
||||
const FormatSpec &fmt_spec = this->spec();
|
||||
BasicWriter<Char> &w = this->writer();
|
||||
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
|
||||
w.write_int(value, fmt_spec);
|
||||
typedef typename BasicWriter<Char>::CharPtr CharPtr;
|
||||
CharPtr out = CharPtr();
|
||||
if (fmt_spec.width_ > 1) {
|
||||
Char fill = ' ';
|
||||
out = w.grow_buffer(fmt_spec.width_);
|
||||
if (fmt_spec.align_ != ALIGN_LEFT) {
|
||||
std::fill_n(out, fmt_spec.width_ - 1, fill);
|
||||
out += fmt_spec.width_ - 1;
|
||||
}
|
||||
else {
|
||||
std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
|
||||
}
|
||||
}
|
||||
else {
|
||||
out = w.grow_buffer(1);
|
||||
}
|
||||
*out = static_cast<Char>(value);
|
||||
}
|
||||
|
||||
void visit_cstring(const char *value) {
|
||||
if (value)
|
||||
Base::visit_cstring(value);
|
||||
else if (this->spec().type_ == 'p')
|
||||
write_null_pointer();
|
||||
else
|
||||
this->write("(null)");
|
||||
}
|
||||
|
||||
void visit_pointer(const void *value) {
|
||||
if (value)
|
||||
return Base::visit_pointer(value);
|
||||
this->spec().type_ = 0;
|
||||
write_null_pointer();
|
||||
}
|
||||
|
||||
void visit_custom(Arg::CustomValue c) {
|
||||
BasicFormatter<Char> formatter(ArgList(), this->writer());
|
||||
const Char format_str[] = { '}', 0 };
|
||||
const Char *format = format_str;
|
||||
c.format(&formatter, c.value, &format);
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace fmt
|
||||
|
||||
FMT_FUNC void fmt::SystemError::init(
|
||||
int err_code, CStringRef format_str, ArgList args) {
|
||||
error_code_ = err_code;
|
||||
MemoryWriter w;
|
||||
internal::format_system_error(w, err_code, format(format_str, args));
|
||||
std::runtime_error &base = *this;
|
||||
base = std::runtime_error(w.str());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int fmt::internal::CharTraits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
unsigned width, int precision, T value) {
|
||||
if (width == 0) {
|
||||
return precision < 0 ?
|
||||
FMT_SNPRINTF(buffer, size, format, value) :
|
||||
FMT_SNPRINTF(buffer, size, format, precision, value);
|
||||
}
|
||||
return precision < 0 ?
|
||||
FMT_SNPRINTF(buffer, size, format, width, value) :
|
||||
FMT_SNPRINTF(buffer, size, format, width, precision, value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int fmt::internal::CharTraits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
unsigned width, int precision, T value) {
|
||||
if (width == 0) {
|
||||
return precision < 0 ?
|
||||
FMT_SWPRINTF(buffer, size, format, value) :
|
||||
FMT_SWPRINTF(buffer, size, format, precision, value);
|
||||
}
|
||||
return precision < 0 ?
|
||||
FMT_SWPRINTF(buffer, size, format, width, value) :
|
||||
FMT_SWPRINTF(buffer, size, format, width, precision, value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const char fmt::internal::BasicData<T>::DIGITS[] =
|
||||
"0001020304050607080910111213141516171819"
|
||||
"2021222324252627282930313233343536373839"
|
||||
"4041424344454647484950515253545556575859"
|
||||
"6061626364656667686970717273747576777879"
|
||||
"8081828384858687888990919293949596979899";
|
||||
|
||||
#define FMT_POWERS_OF_10(factor) \
|
||||
factor * 10, \
|
||||
factor * 100, \
|
||||
factor * 1000, \
|
||||
factor * 10000, \
|
||||
factor * 100000, \
|
||||
factor * 1000000, \
|
||||
factor * 10000000, \
|
||||
factor * 100000000, \
|
||||
factor * 1000000000
|
||||
|
||||
template <typename T>
|
||||
const uint32_t fmt::internal::BasicData<T>::POWERS_OF_10_32[] = {
|
||||
0, FMT_POWERS_OF_10(1)
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const uint64_t fmt::internal::BasicData<T>::POWERS_OF_10_64[] = {
|
||||
0,
|
||||
FMT_POWERS_OF_10(1),
|
||||
FMT_POWERS_OF_10(fmt::ULongLong(1000000000)),
|
||||
// Multiply several constants instead of using a single long long constant
|
||||
// to avoid warnings about C++98 not supporting long long.
|
||||
fmt::ULongLong(1000000000) * fmt::ULongLong(1000000000) * 10
|
||||
};
|
||||
|
||||
FMT_FUNC void fmt::internal::report_unknown_type(char code, const char *type) {
|
||||
(void)type;
|
||||
if (std::isprint(static_cast<unsigned char>(code))) {
|
||||
FMT_THROW(fmt::FormatError(
|
||||
fmt::format("unknown format code '{}' for {}", code, type)));
|
||||
}
|
||||
FMT_THROW(fmt::FormatError(
|
||||
fmt::format("unknown format code '\\x{:02x}' for {}",
|
||||
static_cast<unsigned>(code), type)));
|
||||
}
|
||||
|
||||
#if FMT_USE_WINDOWS_H
|
||||
|
||||
FMT_FUNC fmt::internal::UTF8ToUTF16::UTF8ToUTF16(fmt::StringRef s) {
|
||||
static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
|
||||
if (s.size() > INT_MAX)
|
||||
FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
|
||||
int s_size = static_cast<int>(s.size());
|
||||
int length = MultiByteToWideChar(
|
||||
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
|
||||
if (length == 0)
|
||||
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
|
||||
buffer_.resize(length + 1);
|
||||
length = MultiByteToWideChar(
|
||||
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
|
||||
if (length == 0)
|
||||
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
|
||||
buffer_[length] = 0;
|
||||
}
|
||||
|
||||
FMT_FUNC fmt::internal::UTF16ToUTF8::UTF16ToUTF8(fmt::WStringRef s) {
|
||||
if (int error_code = convert(s)) {
|
||||
FMT_THROW(WindowsError(error_code,
|
||||
"cannot convert string from UTF-16 to UTF-8"));
|
||||
}
|
||||
}
|
||||
|
||||
FMT_FUNC int fmt::internal::UTF16ToUTF8::convert(fmt::WStringRef s) {
|
||||
if (s.size() > INT_MAX)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
int s_size = static_cast<int>(s.size());
|
||||
int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
|
||||
if (length == 0)
|
||||
return GetLastError();
|
||||
buffer_.resize(length + 1);
|
||||
length = WideCharToMultiByte(
|
||||
CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
|
||||
if (length == 0)
|
||||
return GetLastError();
|
||||
buffer_[length] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
FMT_FUNC void fmt::WindowsError::init(
|
||||
int err_code, CStringRef format_str, ArgList args) {
|
||||
error_code_ = err_code;
|
||||
MemoryWriter w;
|
||||
internal::format_windows_error(w, err_code, format(format_str, args));
|
||||
std::runtime_error &base = *this;
|
||||
base = std::runtime_error(w.str());
|
||||
}
|
||||
|
||||
FMT_FUNC void fmt::internal::format_windows_error(
|
||||
fmt::Writer &out, int error_code,
|
||||
fmt::StringRef message) FMT_NOEXCEPT{
|
||||
class String {
|
||||
private:
|
||||
LPWSTR str_;
|
||||
|
||||
public:
|
||||
String() : str_() {}
|
||||
~String() {
|
||||
LocalFree(str_);
|
||||
}
|
||||
LPWSTR *ptr() {
|
||||
return &str_;
|
||||
}
|
||||
LPCWSTR c_str() const { return str_; }
|
||||
};
|
||||
FMT_TRY{
|
||||
String system_message;
|
||||
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0,
|
||||
error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<LPWSTR>(system_message.ptr()), 0, 0)) {
|
||||
UTF16ToUTF8 utf8_message;
|
||||
if (utf8_message.convert(system_message.c_str()) == ERROR_SUCCESS) {
|
||||
out << message << ": " << utf8_message;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} FMT_CATCH(...) {}
|
||||
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
|
||||
}
|
||||
|
||||
#endif // FMT_USE_WINDOWS_H
|
||||
|
||||
FMT_FUNC void fmt::internal::format_system_error(
|
||||
fmt::Writer &out, int error_code,
|
||||
fmt::StringRef message) FMT_NOEXCEPT{
|
||||
FMT_TRY{
|
||||
MemoryBuffer<char, INLINE_BUFFER_SIZE> buffer;
|
||||
buffer.resize(INLINE_BUFFER_SIZE);
|
||||
for (;;) {
|
||||
char *system_message = &buffer[0];
|
||||
int result = safe_strerror(error_code, system_message, buffer.size());
|
||||
if (result == 0) {
|
||||
out << message << ": " << system_message;
|
||||
return;
|
||||
}
|
||||
if (result != ERANGE)
|
||||
break; // Can't get error message, report error code instead.
|
||||
buffer.resize(buffer.size() * 2);
|
||||
}
|
||||
} FMT_CATCH(...) {}
|
||||
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void fmt::internal::ArgMap<Char>::init(const ArgList &args) {
|
||||
if (!map_.empty())
|
||||
return;
|
||||
typedef internal::NamedArg<Char> NamedArg;
|
||||
const NamedArg *named_arg = 0;
|
||||
bool use_values =
|
||||
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
|
||||
if (use_values) {
|
||||
for (unsigned i = 0;/*nothing*/; ++i) {
|
||||
internal::Arg::Type arg_type = args.type(i);
|
||||
switch (arg_type) {
|
||||
case internal::Arg::NONE:
|
||||
return;
|
||||
case internal::Arg::NAMED_ARG:
|
||||
named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
|
||||
map_.insert(Pair(named_arg->name, *named_arg));
|
||||
break;
|
||||
default:
|
||||
/*nothing*/
|
||||
;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
|
||||
internal::Arg::Type arg_type = args.type(i);
|
||||
if (arg_type == internal::Arg::NAMED_ARG) {
|
||||
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
|
||||
map_.insert(Pair(named_arg->name, *named_arg));
|
||||
}
|
||||
}
|
||||
for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
|
||||
switch (args.args_[i].type) {
|
||||
case internal::Arg::NONE:
|
||||
return;
|
||||
case internal::Arg::NAMED_ARG:
|
||||
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
|
||||
map_.insert(Pair(named_arg->name, *named_arg));
|
||||
break;
|
||||
default:
|
||||
/*nothing*/
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void fmt::internal::FixedBuffer<Char>::grow(std::size_t) {
|
||||
FMT_THROW(std::runtime_error("buffer overflow"));
|
||||
}
|
||||
|
||||
FMT_FUNC Arg fmt::internal::FormatterBase::do_get_arg(
|
||||
unsigned arg_index, const char *&error) {
|
||||
Arg arg = args_[arg_index];
|
||||
switch (arg.type) {
|
||||
case Arg::NONE:
|
||||
error = "argument index out of range";
|
||||
break;
|
||||
case Arg::NAMED_ARG:
|
||||
arg = *static_cast<const internal::Arg*>(arg.pointer);
|
||||
default:
|
||||
/*nothing*/
|
||||
;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void fmt::internal::PrintfFormatter<Char>::parse_flags(
|
||||
FormatSpec &spec, const Char *&s) {
|
||||
for (;;) {
|
||||
switch (*s++) {
|
||||
case '-':
|
||||
spec.align_ = ALIGN_LEFT;
|
||||
break;
|
||||
case '+':
|
||||
spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
|
||||
break;
|
||||
case '0':
|
||||
spec.fill_ = '0';
|
||||
break;
|
||||
case ' ':
|
||||
spec.flags_ |= SIGN_FLAG;
|
||||
break;
|
||||
case '#':
|
||||
spec.flags_ |= HASH_FLAG;
|
||||
break;
|
||||
default:
|
||||
--s;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
Arg fmt::internal::PrintfFormatter<Char>::get_arg(
|
||||
const Char *s, unsigned arg_index) {
|
||||
(void)s;
|
||||
const char *error = 0;
|
||||
Arg arg = arg_index == UINT_MAX ?
|
||||
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
|
||||
if (error)
|
||||
FMT_THROW(FormatError(!*s ? "invalid format string" : error));
|
||||
return arg;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
unsigned fmt::internal::PrintfFormatter<Char>::parse_header(
|
||||
const Char *&s, FormatSpec &spec) {
|
||||
unsigned arg_index = UINT_MAX;
|
||||
Char c = *s;
|
||||
if (c >= '0' && c <= '9') {
|
||||
// Parse an argument index (if followed by '$') or a width possibly
|
||||
// preceded with '0' flag(s).
|
||||
unsigned value = parse_nonnegative_int(s);
|
||||
if (*s == '$') { // value is an argument index
|
||||
++s;
|
||||
arg_index = value;
|
||||
}
|
||||
else {
|
||||
if (c == '0')
|
||||
spec.fill_ = '0';
|
||||
if (value != 0) {
|
||||
// Nonzero value means that we parsed width and don't need to
|
||||
// parse it or flags again, so return now.
|
||||
spec.width_ = value;
|
||||
return arg_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
parse_flags(spec, s);
|
||||
// Parse width.
|
||||
if (*s >= '0' && *s <= '9') {
|
||||
spec.width_ = parse_nonnegative_int(s);
|
||||
}
|
||||
else if (*s == '*') {
|
||||
++s;
|
||||
spec.width_ = WidthHandler(spec).visit(get_arg(s));
|
||||
}
|
||||
return arg_index;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void fmt::internal::PrintfFormatter<Char>::format(
|
||||
BasicWriter<Char> &writer, BasicCStringRef<Char> format_str) {
|
||||
const Char *start = format_str.c_str();
|
||||
const Char *s = start;
|
||||
while (*s) {
|
||||
Char c = *s++;
|
||||
if (c != '%') continue;
|
||||
if (*s == c) {
|
||||
write(writer, start, s);
|
||||
start = ++s;
|
||||
continue;
|
||||
}
|
||||
write(writer, start, s - 1);
|
||||
|
||||
FormatSpec spec;
|
||||
spec.align_ = ALIGN_RIGHT;
|
||||
|
||||
// Parse argument index, flags and width.
|
||||
unsigned arg_index = parse_header(s, spec);
|
||||
|
||||
// Parse precision.
|
||||
if (*s == '.') {
|
||||
++s;
|
||||
if ('0' <= *s && *s <= '9') {
|
||||
spec.precision_ = parse_nonnegative_int(s);
|
||||
}
|
||||
else if (*s == '*') {
|
||||
++s;
|
||||
spec.precision_ = PrecisionHandler().visit(get_arg(s));
|
||||
}
|
||||
}
|
||||
|
||||
Arg arg = get_arg(s, arg_index);
|
||||
if (spec.flag(HASH_FLAG) && IsZeroInt().visit(arg))
|
||||
spec.flags_ &= ~HASH_FLAG;
|
||||
if (spec.fill_ == '0') {
|
||||
if (arg.type <= Arg::LAST_NUMERIC_TYPE)
|
||||
spec.align_ = ALIGN_NUMERIC;
|
||||
else
|
||||
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
|
||||
}
|
||||
|
||||
// Parse length and convert the argument to the required type.
|
||||
switch (*s++) {
|
||||
case 'h':
|
||||
if (*s == 'h')
|
||||
ArgConverter<signed char>(arg, *++s).visit(arg);
|
||||
else
|
||||
ArgConverter<short>(arg, *s).visit(arg);
|
||||
break;
|
||||
case 'l':
|
||||
if (*s == 'l')
|
||||
ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
|
||||
else
|
||||
ArgConverter<long>(arg, *s).visit(arg);
|
||||
break;
|
||||
case 'j':
|
||||
ArgConverter<intmax_t>(arg, *s).visit(arg);
|
||||
break;
|
||||
case 'z':
|
||||
ArgConverter<std::size_t>(arg, *s).visit(arg);
|
||||
break;
|
||||
case 't':
|
||||
ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
|
||||
break;
|
||||
case 'L':
|
||||
// printf produces garbage when 'L' is omitted for long double, no
|
||||
// need to do the same.
|
||||
break;
|
||||
default:
|
||||
--s;
|
||||
ArgConverter<int>(arg, *s).visit(arg);
|
||||
}
|
||||
|
||||
// Parse type.
|
||||
if (!*s)
|
||||
FMT_THROW(FormatError("invalid format string"));
|
||||
spec.type_ = static_cast<char>(*s++);
|
||||
if (arg.type <= Arg::LAST_INTEGER_TYPE) {
|
||||
// Normalize type.
|
||||
switch (spec.type_) {
|
||||
case 'i':
|
||||
case 'u':
|
||||
spec.type_ = 'd';
|
||||
break;
|
||||
case 'c':
|
||||
// TODO: handle wchar_t
|
||||
CharConverter(arg).visit(arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
start = s;
|
||||
|
||||
// Format argument.
|
||||
internal::PrintfArgFormatter<Char>(writer, spec).visit(arg);
|
||||
}
|
||||
write(writer, start, s);
|
||||
}
|
||||
|
||||
FMT_FUNC void fmt::report_system_error(
|
||||
int error_code, fmt::StringRef message) FMT_NOEXCEPT{
|
||||
// 'fmt::' is for bcc32.
|
||||
fmt::report_error(internal::format_system_error, error_code, message);
|
||||
}
|
||||
|
||||
#if FMT_USE_WINDOWS_H
|
||||
FMT_FUNC void fmt::report_windows_error(
|
||||
int error_code, fmt::StringRef message) FMT_NOEXCEPT{
|
||||
// 'fmt::' is for bcc32.
|
||||
fmt::report_error(internal::format_windows_error, error_code, message);
|
||||
}
|
||||
#endif
|
||||
|
||||
FMT_FUNC void fmt::print(std::FILE *f, CStringRef format_str, ArgList args) {
|
||||
MemoryWriter w;
|
||||
w.write(format_str, args);
|
||||
std::fwrite(w.data(), 1, w.size(), f);
|
||||
}
|
||||
|
||||
FMT_FUNC void fmt::print(CStringRef format_str, ArgList args) {
|
||||
print(stdout, format_str, args);
|
||||
}
|
||||
|
||||
FMT_FUNC void fmt::print(std::ostream &os, CStringRef format_str, ArgList args) {
|
||||
MemoryWriter w;
|
||||
w.write(format_str, args);
|
||||
os.write(w.data(), w.size());
|
||||
}
|
||||
|
||||
FMT_FUNC void fmt::print_colored(Color c, CStringRef format, ArgList args) {
|
||||
char escape[] = "\x1b[30m";
|
||||
escape[3] = static_cast<char>('0' + c);
|
||||
std::fputs(escape, stdout);
|
||||
print(format, args);
|
||||
std::fputs(RESET_COLOR, stdout);
|
||||
}
|
||||
|
||||
FMT_FUNC int fmt::fprintf(std::FILE *f, CStringRef format, ArgList args) {
|
||||
MemoryWriter w;
|
||||
printf(w, format, args);
|
||||
std::size_t size = w.size();
|
||||
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
|
||||
}
|
||||
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
|
||||
template struct fmt::internal::BasicData<void>;
|
||||
|
||||
// Explicit instantiations for char.
|
||||
|
||||
template void fmt::internal::FixedBuffer<char>::grow(std::size_t);
|
||||
|
||||
template void fmt::internal::ArgMap<char>::init(const fmt::ArgList &args);
|
||||
|
||||
template void fmt::internal::PrintfFormatter<char>::format(
|
||||
BasicWriter<char> &writer, CStringRef format);
|
||||
|
||||
template int fmt::internal::CharTraits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
unsigned width, int precision, double value);
|
||||
|
||||
template int fmt::internal::CharTraits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
unsigned width, int precision, long double value);
|
||||
|
||||
// Explicit instantiations for wchar_t.
|
||||
|
||||
template void fmt::internal::FixedBuffer<wchar_t>::grow(std::size_t);
|
||||
|
||||
template void fmt::internal::ArgMap<wchar_t>::init(const fmt::ArgList &args);
|
||||
|
||||
template void fmt::internal::PrintfFormatter<wchar_t>::format(
|
||||
BasicWriter<wchar_t> &writer, WCStringRef format);
|
||||
|
||||
template int fmt::internal::CharTraits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
unsigned width, int precision, double value);
|
||||
|
||||
template int fmt::internal::CharTraits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
unsigned width, int precision, long double value);
|
||||
|
||||
#endif // FMT_HEADER_ONLY
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
201
vendor/spdlog/spdlog/details/line_logger.h
vendored
201
vendor/spdlog/spdlog/details/line_logger.h
vendored
@ -1,201 +0,0 @@
|
||||
//
|
||||
// Copyright(c) 2015 Gabi Melman.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
//
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
#include "../common.h"
|
||||
#include "../logger.h"
|
||||
|
||||
// Line logger class - aggregates operator<< calls to fast ostream
|
||||
// and logs upon destruction
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
class line_logger
|
||||
{
|
||||
public:
|
||||
line_logger(logger* callback_logger, level::level_enum msg_level, bool enabled):
|
||||
_callback_logger(callback_logger),
|
||||
_log_msg(msg_level),
|
||||
_enabled(enabled)
|
||||
{}
|
||||
|
||||
// No copy intended. Only move
|
||||
line_logger(const line_logger& other) = delete;
|
||||
line_logger& operator=(const line_logger&) = delete;
|
||||
line_logger& operator=(line_logger&&) = delete;
|
||||
|
||||
|
||||
line_logger(line_logger&& other) :
|
||||
_callback_logger(other._callback_logger),
|
||||
_log_msg(std::move(other._log_msg)),
|
||||
_enabled(other._enabled)
|
||||
{
|
||||
other.disable();
|
||||
}
|
||||
|
||||
//Log the log message using the callback logger
|
||||
~line_logger()
|
||||
{
|
||||
if (_enabled)
|
||||
{
|
||||
#ifndef SPDLOG_NO_NAME
|
||||
_log_msg.logger_name = _callback_logger->name();
|
||||
#endif
|
||||
#ifndef SPDLOG_NO_DATETIME
|
||||
_log_msg.time = os::now();
|
||||
#endif
|
||||
|
||||
#ifndef SPDLOG_NO_THREAD_ID
|
||||
_log_msg.thread_id = os::thread_id();
|
||||
#endif
|
||||
_callback_logger->_log_msg(_log_msg);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Support for format string with variadic args
|
||||
//
|
||||
|
||||
|
||||
void write(const char* what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void write(const char* fmt, const Args&... args)
|
||||
{
|
||||
if (!_enabled)
|
||||
return;
|
||||
try
|
||||
{
|
||||
_log_msg.raw.write(fmt, args...);
|
||||
}
|
||||
catch (const fmt::FormatError& e)
|
||||
{
|
||||
throw spdlog_ex(fmt::format("formatting error while processing format string '{}': {}", fmt, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Support for operator<<
|
||||
//
|
||||
line_logger& operator<<(const char* what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
line_logger& operator<<(const std::string& what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
line_logger& operator<<(int what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
line_logger& operator<<(unsigned int what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
line_logger& operator<<(long what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
line_logger& operator<<(unsigned long what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
line_logger& operator<<(long long what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
line_logger& operator<<(unsigned long long what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
line_logger& operator<<(double what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
line_logger& operator<<(long double what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
line_logger& operator<<(float what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
line_logger& operator<<(char what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw << what;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//Support user types which implements operator<<
|
||||
template<typename T>
|
||||
line_logger& operator<<(const T& what)
|
||||
{
|
||||
if (_enabled)
|
||||
_log_msg.raw.write("{}", what);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void disable()
|
||||
{
|
||||
_enabled = false;
|
||||
}
|
||||
|
||||
bool is_enabled() const
|
||||
{
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
logger* _callback_logger;
|
||||
log_msg _log_msg;
|
||||
bool _enabled;
|
||||
};
|
||||
} //Namespace details
|
||||
} // Namespace spdlog
|
69
vendor/spdlog/spdlog/details/log_msg.h
vendored
69
vendor/spdlog/spdlog/details/log_msg.h
vendored
@ -5,9 +5,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
#include "../common.h"
|
||||
#include "./format.h"
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/details/os.h>
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -16,59 +19,23 @@ namespace details
|
||||
struct log_msg
|
||||
{
|
||||
log_msg() = default;
|
||||
log_msg(level::level_enum l):
|
||||
logger_name(),
|
||||
level(l),
|
||||
raw(),
|
||||
formatted() {}
|
||||
|
||||
|
||||
log_msg(const log_msg& other) :
|
||||
logger_name(other.logger_name),
|
||||
level(other.level),
|
||||
time(other.time),
|
||||
thread_id(other.thread_id)
|
||||
log_msg(const std::string *loggers_name, level::level_enum lvl) : logger_name(loggers_name), level(lvl)
|
||||
{
|
||||
if (other.raw.size())
|
||||
raw << fmt::BasicStringRef<char>(other.raw.data(), other.raw.size());
|
||||
if (other.formatted.size())
|
||||
formatted << fmt::BasicStringRef<char>(other.formatted.data(), other.formatted.size());
|
||||
#ifndef SPDLOG_NO_DATETIME
|
||||
time = os::now();
|
||||
#endif
|
||||
|
||||
#ifndef SPDLOG_NO_THREAD_ID
|
||||
thread_id = os::thread_id();
|
||||
#endif
|
||||
}
|
||||
|
||||
log_msg(log_msg&& other) :
|
||||
logger_name(std::move(other.logger_name)),
|
||||
level(other.level),
|
||||
time(std::move(other.time)),
|
||||
thread_id(other.thread_id),
|
||||
raw(std::move(other.raw)),
|
||||
formatted(std::move(other.formatted))
|
||||
{
|
||||
other.clear();
|
||||
}
|
||||
log_msg(const log_msg& other) = delete;
|
||||
log_msg& operator=(log_msg&& other) = delete;
|
||||
log_msg(log_msg&& other) = delete;
|
||||
|
||||
log_msg& operator=(log_msg&& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
logger_name = std::move(other.logger_name);
|
||||
level = other.level;
|
||||
time = std::move(other.time);
|
||||
thread_id = other.thread_id;
|
||||
raw = std::move(other.raw);
|
||||
formatted = std::move(other.formatted);
|
||||
other.clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
level = level::off;
|
||||
raw.clear();
|
||||
formatted.clear();
|
||||
}
|
||||
|
||||
std::string logger_name;
|
||||
const std::string *logger_name;
|
||||
level::level_enum level;
|
||||
log_clock::time_point time;
|
||||
size_t thread_id;
|
||||
|
320
vendor/spdlog/spdlog/details/logger_impl.h
vendored
320
vendor/spdlog/spdlog/details/logger_impl.h
vendored
@ -5,32 +5,43 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./line_logger.h"
|
||||
#include <spdlog/logger.h>
|
||||
#include <spdlog/sinks/stdout_sinks.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
|
||||
// create logger with given name, sinks and the default pattern formatter
|
||||
// all other ctors will call this one
|
||||
template<class It>
|
||||
inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end) :
|
||||
inline spdlog::logger::logger(const std::string& logger_name, const It& begin, const It& end):
|
||||
_name(logger_name),
|
||||
_sinks(begin, end),
|
||||
_formatter(std::make_shared<pattern_formatter>("%+"))
|
||||
{
|
||||
|
||||
// no support under vs2013 for member initialization for std::atomic
|
||||
_level = level::info;
|
||||
_flush_level = level::off;
|
||||
_last_err_time = 0;
|
||||
_err_handler = [this](const std::string &msg)
|
||||
{
|
||||
this->_default_err_handler(msg);
|
||||
};
|
||||
}
|
||||
|
||||
// ctor with sinks as init list
|
||||
inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list) :
|
||||
logger(logger_name, sinks_list.begin(), sinks_list.end()) {}
|
||||
inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list):
|
||||
logger(logger_name, sinks_list.begin(), sinks_list.end())
|
||||
{}
|
||||
|
||||
|
||||
// ctor with single sink
|
||||
inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink) :
|
||||
inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr single_sink):
|
||||
logger(logger_name,
|
||||
{
|
||||
single_sink
|
||||
}) {}
|
||||
})
|
||||
{}
|
||||
|
||||
|
||||
inline spdlog::logger::~logger() = default;
|
||||
@ -46,210 +57,149 @@ inline void spdlog::logger::set_pattern(const std::string& pattern)
|
||||
_set_pattern(pattern);
|
||||
}
|
||||
|
||||
//
|
||||
// log only if given level>=logger's log level
|
||||
//
|
||||
|
||||
|
||||
template <typename... Args>
|
||||
inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args)
|
||||
inline void spdlog::logger::log(level::level_enum lvl, const char* fmt, const Args&... args)
|
||||
{
|
||||
bool msg_enabled = should_log(lvl);
|
||||
details::line_logger l(this, lvl, msg_enabled);
|
||||
l.write(fmt, args...);
|
||||
return l;
|
||||
if (!should_log(lvl)) return;
|
||||
|
||||
try
|
||||
{
|
||||
details::log_msg log_msg(&_name, lvl);
|
||||
log_msg.raw.write(fmt, args...);
|
||||
_sink_it(log_msg);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
_err_handler(ex.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
_err_handler("Unknown exception");
|
||||
}
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl)
|
||||
template <typename... Args>
|
||||
inline void spdlog::logger::log(level::level_enum lvl, const char* msg)
|
||||
{
|
||||
return details::line_logger(this, lvl, should_log(lvl));
|
||||
if (!should_log(lvl)) return;
|
||||
try
|
||||
{
|
||||
details::log_msg log_msg(&_name, lvl);
|
||||
log_msg.raw << msg;
|
||||
_sink_it(log_msg);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
_err_handler(ex.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
_err_handler("Unknown exception");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline spdlog::details::line_logger spdlog::logger::_log_if_enabled(level::level_enum lvl, const T& msg)
|
||||
inline void spdlog::logger::log(level::level_enum lvl, const T& msg)
|
||||
{
|
||||
bool msg_enabled = should_log(lvl);
|
||||
details::line_logger l(this, lvl, msg_enabled);
|
||||
l << msg;
|
||||
return l;
|
||||
if (!should_log(lvl)) return;
|
||||
try
|
||||
{
|
||||
details::log_msg log_msg(&_name, lvl);
|
||||
log_msg.raw << msg;
|
||||
_sink_it(log_msg);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
_err_handler(ex.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
_err_handler("Unknown exception");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// logger.info(cppformat_string, arg1, arg2, arg3, ...) call style
|
||||
//
|
||||
|
||||
template <typename... Args>
|
||||
inline spdlog::details::line_logger spdlog::logger::trace(const char* fmt, const Args&... args)
|
||||
inline void spdlog::logger::trace(const char* fmt, const Args&... args)
|
||||
{
|
||||
return _log_if_enabled(level::trace, fmt, args...);
|
||||
log(level::trace, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline spdlog::details::line_logger spdlog::logger::debug(const char* fmt, const Args&... args)
|
||||
inline void spdlog::logger::debug(const char* fmt, const Args&... args)
|
||||
{
|
||||
return _log_if_enabled(level::debug, fmt, args...);
|
||||
log(level::debug, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline spdlog::details::line_logger spdlog::logger::info(const char* fmt, const Args&... args)
|
||||
inline void spdlog::logger::info(const char* fmt, const Args&... args)
|
||||
{
|
||||
return _log_if_enabled(level::info, fmt, args...);
|
||||
log(level::info, fmt, args...);
|
||||
}
|
||||
|
||||
|
||||
template <typename... Args>
|
||||
inline void spdlog::logger::warn(const char* fmt, const Args&... args)
|
||||
{
|
||||
log(level::warn, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline spdlog::details::line_logger spdlog::logger::notice(const char* fmt, const Args&... args)
|
||||
inline void spdlog::logger::error(const char* fmt, const Args&... args)
|
||||
{
|
||||
return _log_if_enabled(level::notice, fmt, args...);
|
||||
log(level::err, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline spdlog::details::line_logger spdlog::logger::warn(const char* fmt, const Args&... args)
|
||||
inline void spdlog::logger::critical(const char* fmt, const Args&... args)
|
||||
{
|
||||
return _log_if_enabled(level::warn, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline spdlog::details::line_logger spdlog::logger::error(const char* fmt, const Args&... args)
|
||||
{
|
||||
return _log_if_enabled(level::err, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline spdlog::details::line_logger spdlog::logger::critical(const char* fmt, const Args&... args)
|
||||
{
|
||||
return _log_if_enabled(level::critical, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline spdlog::details::line_logger spdlog::logger::alert(const char* fmt, const Args&... args)
|
||||
{
|
||||
return _log_if_enabled(level::alert, fmt, args...);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline spdlog::details::line_logger spdlog::logger::emerg(const char* fmt, const Args&... args)
|
||||
{
|
||||
return _log_if_enabled(level::emerg, fmt, args...);
|
||||
}
|
||||
|
||||
//
|
||||
// logger.info(msg) << ".." call style
|
||||
//
|
||||
template<typename T>
|
||||
inline spdlog::details::line_logger spdlog::logger::trace(const T& msg)
|
||||
{
|
||||
return _log_if_enabled(level::trace, msg);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline spdlog::details::line_logger spdlog::logger::debug(const T& msg)
|
||||
{
|
||||
return _log_if_enabled(level::debug, msg);
|
||||
log(level::critical, fmt, args...);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline spdlog::details::line_logger spdlog::logger::info(const T& msg)
|
||||
inline void spdlog::logger::trace(const T& msg)
|
||||
{
|
||||
return _log_if_enabled(level::info, msg);
|
||||
log(level::trace, msg);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline spdlog::details::line_logger spdlog::logger::notice(const T& msg)
|
||||
inline void spdlog::logger::debug(const T& msg)
|
||||
{
|
||||
return _log_if_enabled(level::notice, msg);
|
||||
log(level::debug, msg);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline void spdlog::logger::info(const T& msg)
|
||||
{
|
||||
log(level::info, msg);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline void spdlog::logger::warn(const T& msg)
|
||||
{
|
||||
log(level::warn, msg);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline spdlog::details::line_logger spdlog::logger::warn(const T& msg)
|
||||
inline void spdlog::logger::error(const T& msg)
|
||||
{
|
||||
return _log_if_enabled(level::warn, msg);
|
||||
log(level::err, msg);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline spdlog::details::line_logger spdlog::logger::error(const T& msg)
|
||||
inline void spdlog::logger::critical(const T& msg)
|
||||
{
|
||||
return _log_if_enabled(level::err, msg);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline spdlog::details::line_logger spdlog::logger::critical(const T& msg)
|
||||
{
|
||||
return _log_if_enabled(level::critical, msg);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline spdlog::details::line_logger spdlog::logger::alert(const T& msg)
|
||||
{
|
||||
return _log_if_enabled(level::alert, msg);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline spdlog::details::line_logger spdlog::logger::emerg(const T& msg)
|
||||
{
|
||||
return _log_if_enabled(level::emerg, msg);
|
||||
log(level::critical, msg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// logger.info() << ".." call style
|
||||
//
|
||||
inline spdlog::details::line_logger spdlog::logger::trace()
|
||||
{
|
||||
return _log_if_enabled(level::trace);
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger spdlog::logger::debug()
|
||||
{
|
||||
return _log_if_enabled(level::debug);
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger spdlog::logger::info()
|
||||
{
|
||||
return _log_if_enabled(level::info);
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger spdlog::logger::notice()
|
||||
{
|
||||
return _log_if_enabled(level::notice);
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger spdlog::logger::warn()
|
||||
{
|
||||
return _log_if_enabled(level::warn);
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger spdlog::logger::error()
|
||||
{
|
||||
return _log_if_enabled(level::err);
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger spdlog::logger::critical()
|
||||
{
|
||||
return _log_if_enabled(level::critical);
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger spdlog::logger::alert()
|
||||
{
|
||||
return _log_if_enabled(level::alert);
|
||||
}
|
||||
|
||||
inline spdlog::details::line_logger spdlog::logger::emerg()
|
||||
{
|
||||
return _log_if_enabled(level::emerg);
|
||||
}
|
||||
|
||||
|
||||
// always log, no matter what is the actual logger's log level
|
||||
template <typename... Args>
|
||||
inline spdlog::details::line_logger spdlog::logger::force_log(level::level_enum lvl, const char* fmt, const Args&... args)
|
||||
{
|
||||
details::line_logger l(this, lvl, true);
|
||||
l.write(fmt, args...);
|
||||
return l;
|
||||
}
|
||||
|
||||
//
|
||||
// name and level
|
||||
//
|
||||
@ -263,6 +213,22 @@ inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
|
||||
_level.store(log_level);
|
||||
}
|
||||
|
||||
inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler)
|
||||
{
|
||||
_err_handler = err_handler;
|
||||
}
|
||||
|
||||
inline spdlog::log_err_handler spdlog::logger::error_handler()
|
||||
{
|
||||
return _err_handler;
|
||||
}
|
||||
|
||||
|
||||
inline void spdlog::logger::flush_on(level::level_enum log_level)
|
||||
{
|
||||
_flush_level.store(log_level);
|
||||
}
|
||||
|
||||
inline spdlog::level::level_enum spdlog::logger::level() const
|
||||
{
|
||||
return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
|
||||
@ -276,11 +242,19 @@ inline bool spdlog::logger::should_log(spdlog::level::level_enum msg_level) cons
|
||||
//
|
||||
// protected virtual called at end of each user log call (if enabled) by the line_logger
|
||||
//
|
||||
inline void spdlog::logger::_log_msg(details::log_msg& msg)
|
||||
inline void spdlog::logger::_sink_it(details::log_msg& msg)
|
||||
{
|
||||
_formatter->format(msg);
|
||||
for (auto &sink : _sinks)
|
||||
sink->log(msg);
|
||||
{
|
||||
if( sink->should_log( msg.level))
|
||||
{
|
||||
sink->log(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if(_should_flush_on(msg))
|
||||
flush();
|
||||
}
|
||||
|
||||
inline void spdlog::logger::_set_pattern(const std::string& pattern)
|
||||
@ -296,4 +270,24 @@ inline void spdlog::logger::flush()
|
||||
{
|
||||
for (auto& sink : _sinks)
|
||||
sink->flush();
|
||||
}
|
||||
}
|
||||
|
||||
inline void spdlog::logger::_default_err_handler(const std::string &msg)
|
||||
{
|
||||
auto now = time(nullptr);
|
||||
if (now - _last_err_time < 60)
|
||||
return;
|
||||
auto tm_time = details::os::localtime(now);
|
||||
char date_buf[100];
|
||||
std::strftime(date_buf, sizeof(date_buf), "%Y-%m-%d %H:%M:%S", &tm_time);
|
||||
details::log_msg err_msg;
|
||||
err_msg.formatted.write("[*** LOG ERROR ***] [{}] [{}] [{}]{}", name(), msg, date_buf, details::os::eol);
|
||||
sinks::stderr_sink_mt::instance()->log(err_msg);
|
||||
_last_err_time = now;
|
||||
}
|
||||
|
||||
inline bool spdlog::logger::_should_flush_on(const details::log_msg &msg)
|
||||
{
|
||||
const auto flush_level = _flush_level.load(std::memory_order_relaxed);
|
||||
return (msg.level >= flush_level) && (msg.level != level::off);
|
||||
}
|
||||
|
25
vendor/spdlog/spdlog/details/mpmc_bounded_q.h
vendored
25
vendor/spdlog/spdlog/details/mpmc_bounded_q.h
vendored
@ -43,8 +43,10 @@ Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spdlog/common.h>
|
||||
|
||||
#include <atomic>
|
||||
#include "../common.h"
|
||||
#include <utility>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -58,8 +60,9 @@ public:
|
||||
|
||||
using item_type = T;
|
||||
mpmc_bounded_queue(size_t buffer_size)
|
||||
: buffer_(new cell_t [buffer_size]),
|
||||
buffer_mask_(buffer_size - 1)
|
||||
:max_size_(buffer_size),
|
||||
buffer_(new cell_t [buffer_size]),
|
||||
buffer_mask_(buffer_size - 1)
|
||||
{
|
||||
//queue size must be power of two
|
||||
if(!((buffer_size >= 2) && ((buffer_size & (buffer_size - 1)) == 0)))
|
||||
@ -130,6 +133,16 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t approx_size()
|
||||
{
|
||||
size_t first_pos = dequeue_pos_.load(std::memory_order_relaxed);
|
||||
size_t last_pos = enqueue_pos_.load(std::memory_order_relaxed);
|
||||
if (last_pos <= first_pos)
|
||||
return 0;
|
||||
auto size = last_pos - first_pos;
|
||||
return size < max_size_ ? size : max_size_;
|
||||
}
|
||||
|
||||
private:
|
||||
struct cell_t
|
||||
{
|
||||
@ -137,6 +150,8 @@ private:
|
||||
T data_;
|
||||
};
|
||||
|
||||
size_t const max_size_;
|
||||
|
||||
static size_t const cacheline_size = 64;
|
||||
typedef char cacheline_pad_t [cacheline_size];
|
||||
|
||||
@ -149,8 +164,8 @@ private:
|
||||
std::atomic<size_t> dequeue_pos_;
|
||||
cacheline_pad_t pad3_;
|
||||
|
||||
mpmc_bounded_queue(mpmc_bounded_queue const&);
|
||||
void operator = (mpmc_bounded_queue const&);
|
||||
mpmc_bounded_queue(mpmc_bounded_queue const&) = delete;
|
||||
void operator= (mpmc_bounded_queue const&) = delete;
|
||||
};
|
||||
|
||||
} // ns details
|
||||
|
23
vendor/spdlog/spdlog/details/null_mutex.h
vendored
23
vendor/spdlog/spdlog/details/null_mutex.h
vendored
@ -5,7 +5,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// null, no cost mutex
|
||||
#include <atomic>
|
||||
// null, no cost dummy "mutex" and dummy "atomic" int
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -20,5 +21,25 @@ struct null_mutex
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct null_atomic_int
|
||||
{
|
||||
int value;
|
||||
null_atomic_int() = default;
|
||||
|
||||
null_atomic_int(int val):value(val)
|
||||
{}
|
||||
|
||||
int load(std::memory_order) const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
void store(int val)
|
||||
{
|
||||
value = val;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
237
vendor/spdlog/spdlog/details/os.h
vendored
237
vendor/spdlog/spdlog/details/os.h
vendored
@ -4,29 +4,47 @@
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include<string>
|
||||
#include<cstdio>
|
||||
#include<ctime>
|
||||
#include <spdlog/common.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
# include <windows.h>
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX //prevent windows redefining min/max
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <share.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#elif __linux__
|
||||
|
||||
#include <sys/syscall.h> //Use gettid() syscall under linux to get thread id
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <chrono>
|
||||
|
||||
#elif __FreeBSD__
|
||||
#include <sys/thr.h> //Use thr_self() syscall under FreeBSD to get thread id
|
||||
|
||||
#else
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
#include "../common.h"
|
||||
#endif
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -105,66 +123,111 @@ inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
|
||||
return !(tm1 == tm2);
|
||||
}
|
||||
|
||||
// eol definition
|
||||
#if !defined (SPDLOG_EOL)
|
||||
#ifdef _WIN32
|
||||
inline const char* eol()
|
||||
{
|
||||
return "\r\n";
|
||||
}
|
||||
#define SPDLOG_EOL "\r\n"
|
||||
#else
|
||||
constexpr inline const char* eol()
|
||||
{
|
||||
return "\n";
|
||||
}
|
||||
#define SPDLOG_EOL "\n"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
inline unsigned short eol_size()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
#else
|
||||
constexpr inline unsigned short eol_size()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
SPDLOG_CONSTEXPR static const char* eol = SPDLOG_EOL;
|
||||
SPDLOG_CONSTEXPR static int eol_size = sizeof(SPDLOG_EOL) - 1;
|
||||
|
||||
|
||||
|
||||
//fopen_s on non windows for writing
|
||||
inline int fopen_s(FILE** fp, const std::string& filename, const char* mode)
|
||||
inline int fopen_s(FILE** fp, const filename_t& filename, const filename_t& mode)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
*fp = _fsopen((filename.c_str()), mode, _SH_DENYWR);
|
||||
#ifdef SPDLOG_WCHAR_FILENAMES
|
||||
*fp = _wfsopen((filename.c_str()), mode.c_str(), _SH_DENYWR);
|
||||
#else
|
||||
*fp = _fsopen((filename.c_str()), mode.c_str(), _SH_DENYWR);
|
||||
#endif
|
||||
return *fp == nullptr;
|
||||
#else
|
||||
*fp = fopen((filename.c_str()), mode);
|
||||
*fp = fopen((filename.c_str()), mode.c_str());
|
||||
return *fp == nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int remove(const filename_t &filename)
|
||||
{
|
||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
|
||||
return _wremove(filename.c_str());
|
||||
#else
|
||||
return std::remove(filename.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
inline int rename(const filename_t& filename1, const filename_t& filename2)
|
||||
{
|
||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
|
||||
return _wrename(filename1.c_str(), filename2.c_str());
|
||||
#else
|
||||
return std::rename(filename1.c_str(), filename2.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//Return if file exists
|
||||
inline bool file_exists(const std::string& filename)
|
||||
inline bool file_exists(const filename_t& filename)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#ifdef SPDLOG_WCHAR_FILENAMES
|
||||
auto attribs = GetFileAttributesW(filename.c_str());
|
||||
#else
|
||||
auto attribs = GetFileAttributesA(filename.c_str());
|
||||
#endif
|
||||
return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY));
|
||||
#elif __linux__
|
||||
#else //common linux/unix all have the stat system call
|
||||
struct stat buffer;
|
||||
return (stat (filename.c_str(), &buffer) == 0);
|
||||
#else
|
||||
auto *file = fopen(filename.c_str(), "r");
|
||||
if (file != nullptr)
|
||||
{
|
||||
fclose(file);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Return file size according to open FILE* object
|
||||
inline size_t filesize(FILE *f)
|
||||
{
|
||||
if (f == nullptr)
|
||||
throw spdlog_ex("Failed getting file size. fd is null");
|
||||
#ifdef _WIN32
|
||||
int fd = _fileno(f);
|
||||
#if _WIN64 //64 bits
|
||||
struct _stat64 st;
|
||||
if (_fstat64(fd, &st) == 0)
|
||||
return st.st_size;
|
||||
|
||||
#else //windows 32 bits
|
||||
struct _stat st;
|
||||
if (_fstat(fd, &st) == 0)
|
||||
return st.st_size;
|
||||
#endif
|
||||
|
||||
#else // unix
|
||||
int fd = fileno(f);
|
||||
//64 bits(but not in osx, where fstat64 is deprecated)
|
||||
#if !defined(__FreeBSD__) && !defined(__APPLE__) && (defined(__x86_64__) || defined(__ppc64__))
|
||||
struct stat64 st;
|
||||
if (fstat64(fd, &st) == 0)
|
||||
return st.st_size;
|
||||
#else // unix 32 bits or osx
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) == 0)
|
||||
return st.st_size;
|
||||
#endif
|
||||
#endif
|
||||
throw spdlog_ex("Failed getting file size from fd", errno);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Return utc offset in minutes or throw spdlog_ex on failure
|
||||
inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
|
||||
{
|
||||
@ -178,7 +241,7 @@ inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
|
||||
auto rv = GetDynamicTimeZoneInformation(&tzinfo);
|
||||
#endif
|
||||
if (rv == TIME_ZONE_ID_INVALID)
|
||||
throw spdlog::spdlog_ex("Failed getting timezone info. Last error: " + GetLastError());
|
||||
throw spdlog::spdlog_ex("Failed getting timezone info. ", errno);
|
||||
|
||||
int offset = -tzinfo.Bias;
|
||||
if (tm.tm_isdst)
|
||||
@ -187,7 +250,43 @@ inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
|
||||
offset -= tzinfo.StandardBias;
|
||||
return offset;
|
||||
#else
|
||||
return static_cast<int>(tm.tm_gmtoff / 60);
|
||||
|
||||
#if defined(sun) || defined(__sun)
|
||||
// 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
|
||||
struct helper
|
||||
{
|
||||
static long int calculate_gmt_offset(const std::tm & localtm = details::os::localtime(), const std::tm & gmtm = details::os::gmtime())
|
||||
{
|
||||
int local_year = localtm.tm_year + (1900 - 1);
|
||||
int gmt_year = gmtm.tm_year + (1900 - 1);
|
||||
|
||||
long int days = (
|
||||
// difference in day of year
|
||||
localtm.tm_yday - gmtm.tm_yday
|
||||
|
||||
// + intervening leap days
|
||||
+ ((local_year >> 2) - (gmt_year >> 2))
|
||||
- (local_year / 100 - gmt_year / 100)
|
||||
+ ((local_year / 100 >> 2) - (gmt_year / 100 >> 2))
|
||||
|
||||
// + difference in years * 365 */
|
||||
+ (long int)(local_year - gmt_year) * 365
|
||||
);
|
||||
|
||||
long int hours = (24 * days) + (localtm.tm_hour - gmtm.tm_hour);
|
||||
long int mins = (60 * hours) + (localtm.tm_min - gmtm.tm_min);
|
||||
long int secs = (60 * mins) + (localtm.tm_sec - gmtm.tm_sec);
|
||||
|
||||
return secs;
|
||||
}
|
||||
};
|
||||
|
||||
long int offset_seconds = helper::calculate_gmt_offset(tm);
|
||||
#else
|
||||
long int offset_seconds = tm.tm_gmtoff;
|
||||
#endif
|
||||
|
||||
return static_cast<int>(offset_seconds / 60);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -202,14 +301,60 @@ inline size_t thread_id()
|
||||
# define SYS_gettid __NR_gettid
|
||||
# endif
|
||||
return static_cast<size_t>(syscall(SYS_gettid));
|
||||
#elif __FreeBSD__
|
||||
long tid;
|
||||
thr_self(&tid);
|
||||
return static_cast<size_t>(tid);
|
||||
#else //Default to standard C++11 (OSX and other Unix)
|
||||
return static_cast<size_t>(std::hash<std::thread::id>()(std::this_thread::get_id()));
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// wchar support for windows file names (SPDLOG_WCHAR_FILENAMES must be defined)
|
||||
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
|
||||
#define SPDLOG_FILENAME_T(s) L ## s
|
||||
inline std::string filename_to_str(const filename_t& filename)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> c;
|
||||
return c.to_bytes(filename);
|
||||
}
|
||||
#else
|
||||
#define SPDLOG_FILENAME_T(s) s
|
||||
inline std::string filename_to_str(const filename_t& filename)
|
||||
{
|
||||
return filename;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Return errno string (thread safe)
|
||||
inline std::string errno_str(int err_num)
|
||||
{
|
||||
char buf[256];
|
||||
SPDLOG_CONSTEXPR auto buf_size = sizeof(buf);
|
||||
|
||||
#ifdef _WIN32
|
||||
if(strerror_s(buf, buf_size, err_num) == 0)
|
||||
return std::string(buf);
|
||||
else
|
||||
return "Unkown error";
|
||||
|
||||
#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || \
|
||||
((_POSIX_C_SOURCE >= 200112L) && ! _GNU_SOURCE) // posix version
|
||||
|
||||
if (strerror_r(err_num, buf, buf_size) == 0)
|
||||
return std::string(buf);
|
||||
else
|
||||
return "Unkown error";
|
||||
|
||||
#else // gnu version (might not use the given buf, so its retval pointer must be used)
|
||||
return std::string(strerror_r(err_num, buf, buf_size));
|
||||
#endif
|
||||
}
|
||||
|
||||
} //os
|
||||
} //details
|
||||
} //spdlog
|
||||
|
||||
|
||||
|
@ -5,16 +5,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <spdlog/formatter.h>
|
||||
#include <spdlog/details/log_msg.h>
|
||||
#include <spdlog/details/os.h>
|
||||
#include <spdlog/fmt/fmt.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
|
||||
#include "../formatter.h"
|
||||
#include "./log_msg.h"
|
||||
#include "./os.h"
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -23,7 +26,8 @@ namespace details
|
||||
class flag_formatter
|
||||
{
|
||||
public:
|
||||
virtual ~flag_formatter() {}
|
||||
virtual ~flag_formatter()
|
||||
{}
|
||||
virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0;
|
||||
};
|
||||
|
||||
@ -32,17 +36,17 @@ public:
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
namespace
|
||||
{
|
||||
class name_formatter :public flag_formatter
|
||||
class name_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
msg.formatted << msg.logger_name;
|
||||
msg.formatted << *msg.logger_name;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// log level appender
|
||||
class level_formatter :public flag_formatter
|
||||
class level_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -51,7 +55,7 @@ class level_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// short log level appender
|
||||
class short_level_formatter :public flag_formatter
|
||||
class short_level_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -75,7 +79,7 @@ static int to12h(const tm& t)
|
||||
|
||||
//Abbreviated weekday name
|
||||
static const std::string days[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
class a_formatter :public flag_formatter
|
||||
class a_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -85,7 +89,7 @@ class a_formatter :public flag_formatter
|
||||
|
||||
//Full weekday name
|
||||
static const std::string full_days[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
|
||||
class A_formatter :public flag_formatter
|
||||
class A_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -95,17 +99,17 @@ class A_formatter :public flag_formatter
|
||||
|
||||
//Abbreviated month
|
||||
static const std::string months[] { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" };
|
||||
class b_formatter :public flag_formatter
|
||||
class b_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
msg.formatted<< months[tm_time.tm_mon];
|
||||
msg.formatted << months[tm_time.tm_mon];
|
||||
}
|
||||
};
|
||||
|
||||
//Full month name
|
||||
static const std::string full_months[] { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
|
||||
class B_formatter :public flag_formatter
|
||||
class B_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -130,7 +134,7 @@ static fmt::MemoryWriter& pad_n_join(fmt::MemoryWriter& w, int v1, int v2, int v
|
||||
|
||||
|
||||
//Date and time representation (Thu Aug 23 15:35:46 2014)
|
||||
class c_formatter :public flag_formatter
|
||||
class c_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -141,7 +145,7 @@ class c_formatter :public flag_formatter
|
||||
|
||||
|
||||
// year - 2 digit
|
||||
class C_formatter :public flag_formatter
|
||||
class C_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -152,7 +156,7 @@ class C_formatter :public flag_formatter
|
||||
|
||||
|
||||
// Short MM/DD/YY date, equivalent to %m/%d/%y 08/23/01
|
||||
class D_formatter :public flag_formatter
|
||||
class D_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -162,7 +166,7 @@ class D_formatter :public flag_formatter
|
||||
|
||||
|
||||
// year - 4 digit
|
||||
class Y_formatter :public flag_formatter
|
||||
class Y_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -171,7 +175,7 @@ class Y_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// month 1-12
|
||||
class m_formatter :public flag_formatter
|
||||
class m_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -180,7 +184,7 @@ class m_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// day of month 1-31
|
||||
class d_formatter :public flag_formatter
|
||||
class d_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -189,7 +193,7 @@ class d_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// hours in 24 format 0-23
|
||||
class H_formatter :public flag_formatter
|
||||
class H_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -198,7 +202,7 @@ class H_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// hours in 12 format 1-12
|
||||
class I_formatter :public flag_formatter
|
||||
class I_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -207,7 +211,7 @@ class I_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// minutes 0-59
|
||||
class M_formatter :public flag_formatter
|
||||
class M_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -216,7 +220,7 @@ class M_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// seconds 0-59
|
||||
class S_formatter :public flag_formatter
|
||||
class S_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -225,7 +229,7 @@ class S_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// milliseconds
|
||||
class e_formatter :public flag_formatter
|
||||
class e_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -236,7 +240,7 @@ class e_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// microseconds
|
||||
class f_formatter :public flag_formatter
|
||||
class f_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -247,7 +251,7 @@ class f_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// nanoseconds
|
||||
class F_formatter :public flag_formatter
|
||||
class F_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -258,7 +262,7 @@ class F_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// AM/PM
|
||||
class p_formatter :public flag_formatter
|
||||
class p_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -268,7 +272,7 @@ class p_formatter :public flag_formatter
|
||||
|
||||
|
||||
// 12 hour clock 02:55:02 pm
|
||||
class r_formatter :public flag_formatter
|
||||
class r_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -277,7 +281,7 @@ class r_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// 24-hour HH:MM time, equivalent to %H:%M
|
||||
class R_formatter :public flag_formatter
|
||||
class R_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -286,7 +290,7 @@ class R_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S
|
||||
class T_formatter :public flag_formatter
|
||||
class T_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -296,12 +300,13 @@ class T_formatter :public flag_formatter
|
||||
|
||||
|
||||
// ISO 8601 offset from UTC in timezone (+-HH:MM)
|
||||
class z_formatter :public flag_formatter
|
||||
class z_formatter:public flag_formatter
|
||||
{
|
||||
public:
|
||||
const std::chrono::seconds cache_refresh = std::chrono::seconds(5);
|
||||
|
||||
z_formatter() :_last_update(std::chrono::seconds(0)) {}
|
||||
z_formatter():_last_update(std::chrono::seconds(0))
|
||||
{}
|
||||
z_formatter(const z_formatter&) = delete;
|
||||
z_formatter& operator=(const z_formatter&) = delete;
|
||||
|
||||
@ -314,13 +319,21 @@ public:
|
||||
// it is very fast (already stored in tm.tm_gmtoff)
|
||||
int total_minutes = os::utc_minutes_offset(tm_time);
|
||||
#endif
|
||||
bool is_negative = total_minutes < 0;
|
||||
char sign;
|
||||
if (is_negative)
|
||||
{
|
||||
total_minutes = -total_minutes;
|
||||
sign = '-';
|
||||
}
|
||||
else
|
||||
{
|
||||
sign = '+';
|
||||
}
|
||||
|
||||
int h = total_minutes / 60;
|
||||
int m = total_minutes % 60;
|
||||
if (h >= 0) //minus sign will be printed anyway if negative
|
||||
{
|
||||
msg.formatted << '+';
|
||||
}
|
||||
msg.formatted << sign;
|
||||
pad_n_join(msg.formatted, h, m, ':');
|
||||
}
|
||||
private:
|
||||
@ -344,7 +357,7 @@ private:
|
||||
|
||||
|
||||
//Thread id
|
||||
class t_formatter :public flag_formatter
|
||||
class t_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -353,7 +366,7 @@ class t_formatter :public flag_formatter
|
||||
};
|
||||
|
||||
|
||||
class v_formatter :public flag_formatter
|
||||
class v_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -361,10 +374,10 @@ class v_formatter :public flag_formatter
|
||||
}
|
||||
};
|
||||
|
||||
class ch_formatter :public flag_formatter
|
||||
class ch_formatter:public flag_formatter
|
||||
{
|
||||
public:
|
||||
explicit ch_formatter(char ch) : _ch(ch)
|
||||
explicit ch_formatter(char ch): _ch(ch)
|
||||
{}
|
||||
void format(details::log_msg& msg, const std::tm&) override
|
||||
{
|
||||
@ -376,7 +389,7 @@ private:
|
||||
|
||||
|
||||
//aggregate user chars to display as is
|
||||
class aggregate_formatter :public flag_formatter
|
||||
class aggregate_formatter:public flag_formatter
|
||||
{
|
||||
public:
|
||||
aggregate_formatter()
|
||||
@ -395,7 +408,7 @@ private:
|
||||
|
||||
// Full info formatter
|
||||
// pattern: [%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v
|
||||
class full_formatter :public flag_formatter
|
||||
class full_formatter:public flag_formatter
|
||||
{
|
||||
void format(details::log_msg& msg, const std::tm& tm_time) override
|
||||
{
|
||||
@ -426,13 +439,13 @@ class full_formatter :public flag_formatter
|
||||
<< fmt::pad(static_cast<unsigned int>(tm_time.tm_sec), 2, '0') << '.'
|
||||
<< fmt::pad(static_cast<unsigned int>(millis), 3, '0') << "] ";
|
||||
|
||||
//no datetime needed
|
||||
//no datetime needed
|
||||
#else
|
||||
(void)tm_time;
|
||||
#endif
|
||||
|
||||
#ifndef SPDLOG_NO_NAME
|
||||
msg.formatted << '[' << msg.logger_name << "] ";
|
||||
msg.formatted << '[' << *msg.logger_name << "] ";
|
||||
#endif
|
||||
|
||||
msg.formatted << '[' << level::to_str(msg.level) << "] ";
|
||||
@ -496,101 +509,101 @@ inline void spdlog::pattern_formatter::handle_flag(char flag)
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::short_level_formatter()));
|
||||
break;
|
||||
|
||||
case('t') :
|
||||
case('t'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::t_formatter()));
|
||||
break;
|
||||
|
||||
case('v') :
|
||||
case('v'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::v_formatter()));
|
||||
break;
|
||||
|
||||
case('a') :
|
||||
case('a'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::a_formatter()));
|
||||
break;
|
||||
|
||||
case('A') :
|
||||
case('A'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::A_formatter()));
|
||||
break;
|
||||
|
||||
case('b') :
|
||||
case('h') :
|
||||
case('b'):
|
||||
case('h'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::b_formatter()));
|
||||
break;
|
||||
|
||||
case('B') :
|
||||
case('B'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::B_formatter()));
|
||||
break;
|
||||
case('c') :
|
||||
case('c'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::c_formatter()));
|
||||
break;
|
||||
|
||||
case('C') :
|
||||
case('C'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::C_formatter()));
|
||||
break;
|
||||
|
||||
case('Y') :
|
||||
case('Y'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::Y_formatter()));
|
||||
break;
|
||||
|
||||
case('D') :
|
||||
case('x') :
|
||||
case('D'):
|
||||
case('x'):
|
||||
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::D_formatter()));
|
||||
break;
|
||||
|
||||
case('m') :
|
||||
case('m'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::m_formatter()));
|
||||
break;
|
||||
|
||||
case('d') :
|
||||
case('d'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::d_formatter()));
|
||||
break;
|
||||
|
||||
case('H') :
|
||||
case('H'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::H_formatter()));
|
||||
break;
|
||||
|
||||
case('I') :
|
||||
case('I'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::I_formatter()));
|
||||
break;
|
||||
|
||||
case('M') :
|
||||
case('M'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::M_formatter()));
|
||||
break;
|
||||
|
||||
case('S') :
|
||||
case('S'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::S_formatter()));
|
||||
break;
|
||||
|
||||
case('e') :
|
||||
case('e'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::e_formatter()));
|
||||
break;
|
||||
|
||||
case('f') :
|
||||
case('f'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::f_formatter()));
|
||||
break;
|
||||
case('F') :
|
||||
case('F'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::F_formatter()));
|
||||
break;
|
||||
|
||||
case('p') :
|
||||
case('p'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::p_formatter()));
|
||||
break;
|
||||
|
||||
case('r') :
|
||||
case('r'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::r_formatter()));
|
||||
break;
|
||||
|
||||
case('R') :
|
||||
case('R'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::R_formatter()));
|
||||
break;
|
||||
|
||||
case('T') :
|
||||
case('X') :
|
||||
case('T'):
|
||||
case('X'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::T_formatter()));
|
||||
break;
|
||||
|
||||
case('z') :
|
||||
case('z'):
|
||||
_formatters.push_back(std::unique_ptr<details::flag_formatter>(new details::z_formatter()));
|
||||
break;
|
||||
|
||||
@ -608,18 +621,16 @@ inline void spdlog::pattern_formatter::handle_flag(char flag)
|
||||
|
||||
inline void spdlog::pattern_formatter::format(details::log_msg& msg)
|
||||
{
|
||||
try
|
||||
|
||||
#ifndef SPDLOG_NO_DATETIME
|
||||
auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time));
|
||||
#else
|
||||
std::tm tm_time;
|
||||
#endif
|
||||
for (auto &f : _formatters)
|
||||
{
|
||||
auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time));
|
||||
for (auto &f : _formatters)
|
||||
{
|
||||
f->format(msg, tm_time);
|
||||
}
|
||||
//write eol
|
||||
msg.formatted << details::os::eol();
|
||||
}
|
||||
catch(const fmt::FormatError& e)
|
||||
{
|
||||
throw spdlog_ex(fmt::format("formatting error while processing format string: {}", e.what()));
|
||||
f->format(msg, tm_time);
|
||||
}
|
||||
//write eol
|
||||
msg.formatted.write(details::os::eol, details::os::eol_size);
|
||||
}
|
||||
|
71
vendor/spdlog/spdlog/details/registry.h
vendored
71
vendor/spdlog/spdlog/details/registry.h
vendored
@ -10,15 +10,17 @@
|
||||
// If user requests a non existing logger, nullptr will be returned
|
||||
// This class is thread safe
|
||||
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
#include <spdlog/logger.h>
|
||||
#include <spdlog/async_logger.h>
|
||||
#include <spdlog/common.h>
|
||||
|
||||
#include "./null_mutex.h"
|
||||
#include "../logger.h"
|
||||
#include "../async_logger.h"
|
||||
#include "../common.h"
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -31,7 +33,9 @@ public:
|
||||
void register_logger(std::shared_ptr<logger> logger)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(_mutex);
|
||||
register_logger_impl(logger);
|
||||
auto logger_name = logger->name();
|
||||
throw_if_exists(logger_name);
|
||||
_loggers[logger_name] = logger;
|
||||
}
|
||||
|
||||
|
||||
@ -45,25 +49,35 @@ public:
|
||||
template<class It>
|
||||
std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_begin, const It& sinks_end)
|
||||
{
|
||||
|
||||
std::shared_ptr<logger> new_logger;
|
||||
|
||||
std::lock_guard<Mutex> lock(_mutex);
|
||||
|
||||
|
||||
throw_if_exists(logger_name);
|
||||
std::shared_ptr<logger> new_logger;
|
||||
if (_async_mode)
|
||||
new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms);
|
||||
new_logger = std::make_shared<async_logger>(logger_name, sinks_begin, sinks_end, _async_q_size, _overflow_policy, _worker_warmup_cb, _flush_interval_ms, _worker_teardown_cb);
|
||||
else
|
||||
new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
|
||||
|
||||
if (_formatter)
|
||||
new_logger->set_formatter(_formatter);
|
||||
|
||||
if (_err_handler)
|
||||
new_logger->set_error_handler(_err_handler);
|
||||
|
||||
new_logger->set_level(_level);
|
||||
register_logger_impl(new_logger);
|
||||
|
||||
|
||||
//Add to registry
|
||||
_loggers[logger_name] = new_logger;
|
||||
return new_logger;
|
||||
}
|
||||
|
||||
void apply_all(std::function<void(std::shared_ptr<logger>)> fun)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(_mutex);
|
||||
for (auto &l : _loggers)
|
||||
fun(l.second);
|
||||
}
|
||||
|
||||
void drop(const std::string& logger_name)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(_mutex);
|
||||
@ -110,7 +124,14 @@ public:
|
||||
_level = log_level;
|
||||
}
|
||||
|
||||
void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms)
|
||||
void set_error_handler(log_err_handler handler)
|
||||
{
|
||||
for (auto& l : _loggers)
|
||||
l.second->set_error_handler(handler);
|
||||
_err_handler = handler;
|
||||
}
|
||||
|
||||
void set_async_mode(size_t q_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(_mutex);
|
||||
_async_mode = true;
|
||||
@ -118,6 +139,7 @@ public:
|
||||
_overflow_policy = overflow_policy;
|
||||
_worker_warmup_cb = worker_warmup_cb;
|
||||
_flush_interval_ms = flush_interval_ms;
|
||||
_worker_teardown_cb = worker_teardown_cb;
|
||||
}
|
||||
|
||||
void set_sync_mode()
|
||||
@ -133,25 +155,26 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void register_logger_impl(std::shared_ptr<logger> logger)
|
||||
{
|
||||
auto logger_name = logger->name();
|
||||
if (_loggers.find(logger_name) != std::end(_loggers))
|
||||
throw spdlog_ex("logger with name " + logger_name + " already exists");
|
||||
_loggers[logger->name()] = logger;
|
||||
}
|
||||
registry_t<Mutex>() {}
|
||||
registry_t<Mutex>(const registry_t<Mutex>&) = delete;
|
||||
registry_t<Mutex>& operator=(const registry_t<Mutex>&) = delete;
|
||||
|
||||
void throw_if_exists(const std::string &logger_name)
|
||||
{
|
||||
if (_loggers.find(logger_name) != _loggers.end())
|
||||
throw spdlog_ex("logger with name '" + logger_name + "' already exists");
|
||||
}
|
||||
Mutex _mutex;
|
||||
std::unordered_map <std::string, std::shared_ptr<logger>> _loggers;
|
||||
formatter_ptr _formatter;
|
||||
level::level_enum _level = level::info;
|
||||
log_err_handler _err_handler;
|
||||
bool _async_mode = false;
|
||||
size_t _async_q_size = 0;
|
||||
async_overflow_policy _overflow_policy = async_overflow_policy::block_retry;
|
||||
std::function<void()> _worker_warmup_cb = nullptr;
|
||||
std::chrono::milliseconds _flush_interval_ms;
|
||||
std::function<void()> _worker_teardown_cb = nullptr;
|
||||
};
|
||||
#ifdef SPDLOG_NO_REGISTRY_MUTEX
|
||||
typedef registry_t<spdlog::details::null_mutex> registry;
|
||||
|
107
vendor/spdlog/spdlog/details/spdlog_impl.h
vendored
107
vendor/spdlog/spdlog/details/spdlog_impl.h
vendored
@ -8,10 +8,18 @@
|
||||
//
|
||||
// Global registry functions
|
||||
//
|
||||
#include "registry.h"
|
||||
#include "../sinks/file_sinks.h"
|
||||
#include "../sinks/stdout_sinks.h"
|
||||
#include "../sinks/syslog_sink.h"
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/details/registry.h>
|
||||
#include <spdlog/sinks/file_sinks.h>
|
||||
#include <spdlog/sinks/stdout_sinks.h>
|
||||
#include <spdlog/sinks/syslog_sink.h>
|
||||
#include <spdlog/sinks/ansicolor_sink.h>
|
||||
#include <spdlog/sinks/android_sink.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
inline void spdlog::register_logger(std::shared_ptr<logger> logger)
|
||||
{
|
||||
@ -28,50 +36,68 @@ inline void spdlog::drop(const std::string &name)
|
||||
details::registry::instance().drop(name);
|
||||
}
|
||||
|
||||
// Create multi/single threaded rotating file logger
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush)
|
||||
// Create multi/single threaded simple file logger
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate)
|
||||
{
|
||||
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, "txt", max_file_size, max_files, force_flush);
|
||||
return create<spdlog::sinks::simple_file_sink_mt>(logger_name, filename, truncate);
|
||||
}
|
||||
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush)
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate)
|
||||
{
|
||||
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, "txt", max_file_size, max_files, force_flush);
|
||||
return create<spdlog::sinks::simple_file_sink_st>(logger_name, filename, truncate);
|
||||
}
|
||||
|
||||
// Create multi/single threaded rotating file logger
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
|
||||
{
|
||||
return create<spdlog::sinks::rotating_file_sink_mt>(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files);
|
||||
}
|
||||
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files)
|
||||
{
|
||||
return create<spdlog::sinks::rotating_file_sink_st>(logger_name, filename, SPDLOG_FILENAME_T("txt"), max_file_size, max_files);
|
||||
}
|
||||
|
||||
// Create file logger which creates new file at midnight):
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush)
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour, int minute)
|
||||
{
|
||||
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, "txt", hour, minute, force_flush);
|
||||
}
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const std::string& filename, int hour, int minute, bool force_flush)
|
||||
{
|
||||
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, "txt", hour, minute, force_flush);
|
||||
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute);
|
||||
}
|
||||
|
||||
|
||||
// Create stdout/stderr loggers
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name)
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute)
|
||||
{
|
||||
return details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_mt::instance());
|
||||
return create<spdlog::sinks::daily_file_sink_st>(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute);
|
||||
}
|
||||
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name)
|
||||
// Create stdout/stderr loggers (with optinal color support)
|
||||
inline std::shared_ptr<spdlog::logger> create_console_logger(const std::string& logger_name, spdlog::sink_ptr sink, bool color)
|
||||
{
|
||||
return details::registry::instance().create(logger_name, spdlog::sinks::stdout_sink_st::instance());
|
||||
if (color) //use color wrapper sink
|
||||
sink = std::make_shared<spdlog::sinks::ansicolor_sink>(sink);
|
||||
return spdlog::details::registry::instance().create(logger_name, sink);
|
||||
}
|
||||
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name)
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name, bool color)
|
||||
{
|
||||
return details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_mt::instance());
|
||||
return create_console_logger(logger_name, sinks::stdout_sink_mt::instance(), color);
|
||||
}
|
||||
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name)
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_st(const std::string& logger_name, bool color)
|
||||
{
|
||||
return details::registry::instance().create(logger_name, spdlog::sinks::stderr_sink_st::instance());
|
||||
return create_console_logger(logger_name, sinks::stdout_sink_st::instance(), color);
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_mt(const std::string& logger_name, bool color)
|
||||
{
|
||||
return create_console_logger(logger_name, sinks::stderr_sink_mt::instance(), color);
|
||||
}
|
||||
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::stderr_logger_st(const std::string& logger_name, bool color)
|
||||
{
|
||||
return create_console_logger(logger_name, sinks::stderr_sink_st::instance(), color);
|
||||
}
|
||||
|
||||
#ifdef SPDLOG_ENABLE_SYSLOG
|
||||
// Create syslog logger
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string& logger_name, const std::string& syslog_ident, int syslog_option)
|
||||
{
|
||||
@ -79,6 +105,18 @@ inline std::shared_ptr<spdlog::logger> spdlog::syslog_logger(const std::string&
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::android_logger(const std::string& logger_name, const std::string& tag)
|
||||
{
|
||||
return create<spdlog::sinks::android_sink>(logger_name, tag);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create and register a logger a single sink
|
||||
inline std::shared_ptr<spdlog::logger> spdlog::create(const std::string& logger_name, const spdlog::sink_ptr& sink)
|
||||
{
|
||||
return details::registry::instance().create(logger_name, sink);
|
||||
}
|
||||
|
||||
//Create logger with multiple sinks
|
||||
|
||||
@ -117,10 +155,15 @@ inline void spdlog::set_level(level::level_enum log_level)
|
||||
return details::registry::instance().set_level(log_level);
|
||||
}
|
||||
|
||||
|
||||
inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms)
|
||||
inline void spdlog::set_error_handler(log_err_handler handler)
|
||||
{
|
||||
details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms);
|
||||
return details::registry::instance().set_error_handler(handler);
|
||||
}
|
||||
|
||||
|
||||
inline void spdlog::set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy, const std::function<void()>& worker_warmup_cb, const std::chrono::milliseconds& flush_interval_ms, const std::function<void()>& worker_teardown_cb)
|
||||
{
|
||||
details::registry::instance().set_async_mode(queue_size, overflow_policy, worker_warmup_cb, flush_interval_ms, worker_teardown_cb);
|
||||
}
|
||||
|
||||
inline void spdlog::set_sync_mode()
|
||||
@ -128,8 +171,12 @@ inline void spdlog::set_sync_mode()
|
||||
details::registry::instance().set_sync_mode();
|
||||
}
|
||||
|
||||
inline void spdlog::apply_all(std::function<void(std::shared_ptr<logger>)> fun)
|
||||
{
|
||||
details::registry::instance().apply_all(fun);
|
||||
}
|
||||
|
||||
inline void spdlog::drop_all()
|
||||
{
|
||||
details::registry::instance().drop_all();
|
||||
}
|
||||
|
||||
|
557
vendor/spdlog/spdlog/fmt/bundled/format.cc
vendored
Normal file
557
vendor/spdlog/spdlog/fmt/bundled/format.cc
vendored
Normal file
@ -0,0 +1,557 @@
|
||||
/*
|
||||
Formatting library for C++
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// Commented out by spdlog to use header only
|
||||
// #include "fmt/format.h"
|
||||
// #include "fmt/printf.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
#include <cstddef> // for std::ptrdiff_t
|
||||
|
||||
#if defined(_WIN32) && defined(__MINGW32__)
|
||||
# include <cstring>
|
||||
#endif
|
||||
|
||||
#if FMT_USE_WINDOWS_H
|
||||
# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
|
||||
# include <windows.h>
|
||||
# else
|
||||
# define NOMINMAX
|
||||
# include <windows.h>
|
||||
# undef NOMINMAX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
using fmt::internal::Arg;
|
||||
|
||||
#if FMT_EXCEPTIONS
|
||||
# define FMT_TRY try
|
||||
# define FMT_CATCH(x) catch (x)
|
||||
#else
|
||||
# define FMT_TRY if (true)
|
||||
# define FMT_CATCH(x) if (false)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127) // conditional expression is constant
|
||||
# pragma warning(disable: 4702) // unreachable code
|
||||
// Disable deprecation warning for strerror. The latter is not called but
|
||||
// MSVC fails to detect it.
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
// Dummy implementations of strerror_r and strerror_s called if corresponding
|
||||
// system functions are not available.
|
||||
static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
|
||||
return fmt::internal::Null<>();
|
||||
}
|
||||
static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
|
||||
return fmt::internal::Null<>();
|
||||
}
|
||||
|
||||
namespace fmt {
|
||||
|
||||
FMT_FUNC internal::RuntimeError::~RuntimeError() throw() {}
|
||||
FMT_FUNC FormatError::~FormatError() throw() {}
|
||||
FMT_FUNC SystemError::~SystemError() throw() {}
|
||||
|
||||
namespace {
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# define FMT_SNPRINTF snprintf
|
||||
#else // _MSC_VER
|
||||
inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
# define FMT_SNPRINTF fmt_snprintf
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
|
||||
# define FMT_SWPRINTF snwprintf
|
||||
#else
|
||||
# define FMT_SWPRINTF swprintf
|
||||
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
|
||||
|
||||
const char RESET_COLOR[] = "\x1b[0m";
|
||||
|
||||
typedef void (*FormatFunc)(Writer &, int, StringRef);
|
||||
|
||||
// Portable thread-safe version of strerror.
|
||||
// Sets buffer to point to a string describing the error code.
|
||||
// This can be either a pointer to a string stored in buffer,
|
||||
// or a pointer to some static immutable string.
|
||||
// Returns one of the following values:
|
||||
// 0 - success
|
||||
// ERANGE - buffer is not large enough to store the error message
|
||||
// other - failure
|
||||
// Buffer should be at least of size 1.
|
||||
int safe_strerror(
|
||||
int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
|
||||
FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
|
||||
|
||||
class StrError {
|
||||
private:
|
||||
int error_code_;
|
||||
char *&buffer_;
|
||||
std::size_t buffer_size_;
|
||||
|
||||
// A noop assignment operator to avoid bogus warnings.
|
||||
void operator=(const StrError &) {}
|
||||
|
||||
// Handle the result of XSI-compliant version of strerror_r.
|
||||
int handle(int result) {
|
||||
// glibc versions before 2.13 return result in errno.
|
||||
return result == -1 ? errno : result;
|
||||
}
|
||||
|
||||
// Handle the result of GNU-specific version of strerror_r.
|
||||
int handle(char *message) {
|
||||
// If the buffer is full then the message is probably truncated.
|
||||
if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
|
||||
return ERANGE;
|
||||
buffer_ = message;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle the case when strerror_r is not available.
|
||||
int handle(internal::Null<>) {
|
||||
return fallback(strerror_s(buffer_, buffer_size_, error_code_));
|
||||
}
|
||||
|
||||
// Fallback to strerror_s when strerror_r is not available.
|
||||
int fallback(int result) {
|
||||
// If the buffer is full then the message is probably truncated.
|
||||
return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
|
||||
ERANGE : result;
|
||||
}
|
||||
|
||||
// Fallback to strerror if strerror_r and strerror_s are not available.
|
||||
int fallback(internal::Null<>) {
|
||||
errno = 0;
|
||||
buffer_ = strerror(error_code_);
|
||||
return errno;
|
||||
}
|
||||
|
||||
public:
|
||||
StrError(int err_code, char *&buf, std::size_t buf_size)
|
||||
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
|
||||
|
||||
int run() {
|
||||
strerror_r(0, 0, ""); // Suppress a warning about unused strerror_r.
|
||||
return handle(strerror_r(error_code_, buffer_, buffer_size_));
|
||||
}
|
||||
};
|
||||
return StrError(error_code, buffer, buffer_size).run();
|
||||
}
|
||||
|
||||
void format_error_code(Writer &out, int error_code,
|
||||
StringRef message) FMT_NOEXCEPT {
|
||||
// Report error code making sure that the output fits into
|
||||
// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
|
||||
// bad_alloc.
|
||||
out.clear();
|
||||
static const char SEP[] = ": ";
|
||||
static const char ERROR_STR[] = "error ";
|
||||
// Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
|
||||
std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
|
||||
typedef internal::IntTraits<int>::MainType MainType;
|
||||
MainType abs_value = static_cast<MainType>(error_code);
|
||||
if (internal::is_negative(error_code)) {
|
||||
abs_value = 0 - abs_value;
|
||||
++error_code_size;
|
||||
}
|
||||
error_code_size += internal::count_digits(abs_value);
|
||||
if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size)
|
||||
out << message << SEP;
|
||||
out << ERROR_STR << error_code;
|
||||
assert(out.size() <= internal::INLINE_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void report_error(FormatFunc func, int error_code,
|
||||
StringRef message) FMT_NOEXCEPT {
|
||||
MemoryWriter full_message;
|
||||
func(full_message, error_code, message);
|
||||
// Use Writer::data instead of Writer::c_str to avoid potential memory
|
||||
// allocation.
|
||||
std::fwrite(full_message.data(), full_message.size(), 1, stderr);
|
||||
std::fputc('\n', stderr);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace internal {
|
||||
|
||||
// This method is used to preserve binary compatibility with fmt 3.0.
|
||||
// It can be removed in 4.0.
|
||||
FMT_FUNC void format_system_error(
|
||||
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
|
||||
fmt::format_system_error(out, error_code, message);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
FMT_FUNC void SystemError::init(
|
||||
int err_code, CStringRef format_str, ArgList args) {
|
||||
error_code_ = err_code;
|
||||
MemoryWriter w;
|
||||
format_system_error(w, err_code, format(format_str, args));
|
||||
std::runtime_error &base = *this;
|
||||
base = std::runtime_error(w.str());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int internal::CharTraits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
unsigned width, int precision, T value) {
|
||||
if (width == 0) {
|
||||
return precision < 0 ?
|
||||
FMT_SNPRINTF(buffer, size, format, value) :
|
||||
FMT_SNPRINTF(buffer, size, format, precision, value);
|
||||
}
|
||||
return precision < 0 ?
|
||||
FMT_SNPRINTF(buffer, size, format, width, value) :
|
||||
FMT_SNPRINTF(buffer, size, format, width, precision, value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int internal::CharTraits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
unsigned width, int precision, T value) {
|
||||
if (width == 0) {
|
||||
return precision < 0 ?
|
||||
FMT_SWPRINTF(buffer, size, format, value) :
|
||||
FMT_SWPRINTF(buffer, size, format, precision, value);
|
||||
}
|
||||
return precision < 0 ?
|
||||
FMT_SWPRINTF(buffer, size, format, width, value) :
|
||||
FMT_SWPRINTF(buffer, size, format, width, precision, value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const char internal::BasicData<T>::DIGITS[] =
|
||||
"0001020304050607080910111213141516171819"
|
||||
"2021222324252627282930313233343536373839"
|
||||
"4041424344454647484950515253545556575859"
|
||||
"6061626364656667686970717273747576777879"
|
||||
"8081828384858687888990919293949596979899";
|
||||
|
||||
#define FMT_POWERS_OF_10(factor) \
|
||||
factor * 10, \
|
||||
factor * 100, \
|
||||
factor * 1000, \
|
||||
factor * 10000, \
|
||||
factor * 100000, \
|
||||
factor * 1000000, \
|
||||
factor * 10000000, \
|
||||
factor * 100000000, \
|
||||
factor * 1000000000
|
||||
|
||||
template <typename T>
|
||||
const uint32_t internal::BasicData<T>::POWERS_OF_10_32[] = {
|
||||
0, FMT_POWERS_OF_10(1)
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const uint64_t internal::BasicData<T>::POWERS_OF_10_64[] = {
|
||||
0,
|
||||
FMT_POWERS_OF_10(1),
|
||||
FMT_POWERS_OF_10(ULongLong(1000000000)),
|
||||
// Multiply several constants instead of using a single long long constant
|
||||
// to avoid warnings about C++98 not supporting long long.
|
||||
ULongLong(1000000000) * ULongLong(1000000000) * 10
|
||||
};
|
||||
|
||||
FMT_FUNC void internal::report_unknown_type(char code, const char *type) {
|
||||
(void)type;
|
||||
if (std::isprint(static_cast<unsigned char>(code))) {
|
||||
FMT_THROW(FormatError(
|
||||
format("unknown format code '{}' for {}", code, type)));
|
||||
}
|
||||
FMT_THROW(FormatError(
|
||||
format("unknown format code '\\x{:02x}' for {}",
|
||||
static_cast<unsigned>(code), type)));
|
||||
}
|
||||
|
||||
#if FMT_USE_WINDOWS_H
|
||||
|
||||
FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) {
|
||||
static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
|
||||
if (s.size() > INT_MAX)
|
||||
FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
|
||||
int s_size = static_cast<int>(s.size());
|
||||
int length = MultiByteToWideChar(
|
||||
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, 0, 0);
|
||||
if (length == 0)
|
||||
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
|
||||
buffer_.resize(length + 1);
|
||||
length = MultiByteToWideChar(
|
||||
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
|
||||
if (length == 0)
|
||||
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
|
||||
buffer_[length] = 0;
|
||||
}
|
||||
|
||||
FMT_FUNC internal::UTF16ToUTF8::UTF16ToUTF8(WStringRef s) {
|
||||
if (int error_code = convert(s)) {
|
||||
FMT_THROW(WindowsError(error_code,
|
||||
"cannot convert string from UTF-16 to UTF-8"));
|
||||
}
|
||||
}
|
||||
|
||||
FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) {
|
||||
if (s.size() > INT_MAX)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
int s_size = static_cast<int>(s.size());
|
||||
int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, 0, 0, 0, 0);
|
||||
if (length == 0)
|
||||
return GetLastError();
|
||||
buffer_.resize(length + 1);
|
||||
length = WideCharToMultiByte(
|
||||
CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, 0, 0);
|
||||
if (length == 0)
|
||||
return GetLastError();
|
||||
buffer_[length] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
FMT_FUNC void WindowsError::init(
|
||||
int err_code, CStringRef format_str, ArgList args) {
|
||||
error_code_ = err_code;
|
||||
MemoryWriter w;
|
||||
internal::format_windows_error(w, err_code, format(format_str, args));
|
||||
std::runtime_error &base = *this;
|
||||
base = std::runtime_error(w.str());
|
||||
}
|
||||
|
||||
FMT_FUNC void internal::format_windows_error(
|
||||
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
|
||||
FMT_TRY {
|
||||
MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
|
||||
buffer.resize(INLINE_BUFFER_SIZE);
|
||||
for (;;) {
|
||||
wchar_t *system_message = &buffer[0];
|
||||
int result = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
0, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
system_message, static_cast<uint32_t>(buffer.size()), 0);
|
||||
if (result != 0) {
|
||||
UTF16ToUTF8 utf8_message;
|
||||
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
|
||||
out << message << ": " << utf8_message;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
break; // Can't get error message, report error code instead.
|
||||
buffer.resize(buffer.size() * 2);
|
||||
}
|
||||
} FMT_CATCH(...) {}
|
||||
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
|
||||
}
|
||||
|
||||
#endif // FMT_USE_WINDOWS_H
|
||||
|
||||
FMT_FUNC void format_system_error(
|
||||
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
|
||||
FMT_TRY {
|
||||
internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> buffer;
|
||||
buffer.resize(internal::INLINE_BUFFER_SIZE);
|
||||
for (;;) {
|
||||
char *system_message = &buffer[0];
|
||||
int result = safe_strerror(error_code, system_message, buffer.size());
|
||||
if (result == 0) {
|
||||
out << message << ": " << system_message;
|
||||
return;
|
||||
}
|
||||
if (result != ERANGE)
|
||||
break; // Can't get error message, report error code instead.
|
||||
buffer.resize(buffer.size() * 2);
|
||||
}
|
||||
} FMT_CATCH(...) {}
|
||||
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void internal::ArgMap<Char>::init(const ArgList &args) {
|
||||
if (!map_.empty())
|
||||
return;
|
||||
typedef internal::NamedArg<Char> NamedArg;
|
||||
const NamedArg *named_arg = 0;
|
||||
bool use_values =
|
||||
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
|
||||
if (use_values) {
|
||||
for (unsigned i = 0;/*nothing*/; ++i) {
|
||||
internal::Arg::Type arg_type = args.type(i);
|
||||
switch (arg_type) {
|
||||
case internal::Arg::NONE:
|
||||
return;
|
||||
case internal::Arg::NAMED_ARG:
|
||||
named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
|
||||
map_.push_back(Pair(named_arg->name, *named_arg));
|
||||
break;
|
||||
default:
|
||||
/*nothing*/;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
|
||||
internal::Arg::Type arg_type = args.type(i);
|
||||
if (arg_type == internal::Arg::NAMED_ARG) {
|
||||
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
|
||||
map_.push_back(Pair(named_arg->name, *named_arg));
|
||||
}
|
||||
}
|
||||
for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
|
||||
switch (args.args_[i].type) {
|
||||
case internal::Arg::NONE:
|
||||
return;
|
||||
case internal::Arg::NAMED_ARG:
|
||||
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
|
||||
map_.push_back(Pair(named_arg->name, *named_arg));
|
||||
break;
|
||||
default:
|
||||
/*nothing*/;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void internal::FixedBuffer<Char>::grow(std::size_t) {
|
||||
FMT_THROW(std::runtime_error("buffer overflow"));
|
||||
}
|
||||
|
||||
FMT_FUNC Arg internal::FormatterBase::do_get_arg(
|
||||
unsigned arg_index, const char *&error) {
|
||||
Arg arg = args_[arg_index];
|
||||
switch (arg.type) {
|
||||
case Arg::NONE:
|
||||
error = "argument index out of range";
|
||||
break;
|
||||
case Arg::NAMED_ARG:
|
||||
arg = *static_cast<const internal::Arg*>(arg.pointer);
|
||||
break;
|
||||
default:
|
||||
/*nothing*/;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
FMT_FUNC void report_system_error(
|
||||
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
|
||||
// 'fmt::' is for bcc32.
|
||||
report_error(format_system_error, error_code, message);
|
||||
}
|
||||
|
||||
#if FMT_USE_WINDOWS_H
|
||||
FMT_FUNC void report_windows_error(
|
||||
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
|
||||
// 'fmt::' is for bcc32.
|
||||
report_error(internal::format_windows_error, error_code, message);
|
||||
}
|
||||
#endif
|
||||
|
||||
FMT_FUNC void print(std::FILE *f, CStringRef format_str, ArgList args) {
|
||||
MemoryWriter w;
|
||||
w.write(format_str, args);
|
||||
std::fwrite(w.data(), 1, w.size(), f);
|
||||
}
|
||||
|
||||
FMT_FUNC void print(CStringRef format_str, ArgList args) {
|
||||
print(stdout, format_str, args);
|
||||
}
|
||||
|
||||
FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) {
|
||||
char escape[] = "\x1b[30m";
|
||||
escape[3] = static_cast<char>('0' + c);
|
||||
std::fputs(escape, stdout);
|
||||
print(format, args);
|
||||
std::fputs(RESET_COLOR, stdout);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args);
|
||||
|
||||
FMT_FUNC int fprintf(std::FILE *f, CStringRef format, ArgList args) {
|
||||
MemoryWriter w;
|
||||
printf(w, format, args);
|
||||
std::size_t size = w.size();
|
||||
return std::fwrite(w.data(), 1, size, f) < size ? -1 : static_cast<int>(size);
|
||||
}
|
||||
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
|
||||
template struct internal::BasicData<void>;
|
||||
|
||||
// Explicit instantiations for char.
|
||||
|
||||
template void internal::FixedBuffer<char>::grow(std::size_t);
|
||||
|
||||
template void internal::ArgMap<char>::init(const ArgList &args);
|
||||
|
||||
template void PrintfFormatter<char>::format(CStringRef format);
|
||||
|
||||
template int internal::CharTraits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
unsigned width, int precision, double value);
|
||||
|
||||
template int internal::CharTraits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
unsigned width, int precision, long double value);
|
||||
|
||||
// Explicit instantiations for wchar_t.
|
||||
|
||||
template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
|
||||
|
||||
template void internal::ArgMap<wchar_t>::init(const ArgList &args);
|
||||
|
||||
template void PrintfFormatter<wchar_t>::format(WCStringRef format);
|
||||
|
||||
template int internal::CharTraits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
unsigned width, int precision, double value);
|
||||
|
||||
template int internal::CharTraits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
unsigned width, int precision, long double value);
|
||||
|
||||
#endif // FMT_HEADER_ONLY
|
||||
|
||||
} // namespace fmt
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
36
vendor/spdlog/spdlog/fmt/bundled/ostream.cc
vendored
Normal file
36
vendor/spdlog/spdlog/fmt/bundled/ostream.cc
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
Formatting library for C++ - std::ostream support
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
For the license information refer to format.h.
|
||||
*/
|
||||
|
||||
// Commented out by spdlog to use header only
|
||||
// #include "fmt/ostream.h"
|
||||
|
||||
namespace fmt {
|
||||
|
||||
namespace internal {
|
||||
FMT_FUNC void write(std::ostream &os, Writer &w) {
|
||||
const char *data = w.data();
|
||||
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
|
||||
UnsignedStreamSize size = w.size();
|
||||
UnsignedStreamSize max_size =
|
||||
internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
|
||||
do {
|
||||
UnsignedStreamSize n = size <= max_size ? size : max_size;
|
||||
os.write(data, static_cast<std::streamsize>(n));
|
||||
data += n;
|
||||
size -= n;
|
||||
} while (size != 0);
|
||||
}
|
||||
}
|
||||
|
||||
FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) {
|
||||
MemoryWriter w;
|
||||
w.write(format_str, args);
|
||||
internal::write(os, w);
|
||||
}
|
||||
} // namespace fmt
|
118
vendor/spdlog/spdlog/fmt/bundled/ostream.h
vendored
Normal file
118
vendor/spdlog/spdlog/fmt/bundled/ostream.h
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
Formatting library for C++ - std::ostream support
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
For the license information refer to format.h.
|
||||
*/
|
||||
|
||||
#ifndef FMT_OSTREAM_H_
|
||||
#define FMT_OSTREAM_H_
|
||||
|
||||
// Commented out by spdlog to use header only
|
||||
// #include "fmt/format.h"
|
||||
#include <ostream>
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
template <class Char>
|
||||
class FormatBuf : public std::basic_streambuf<Char>
|
||||
{
|
||||
private:
|
||||
typedef typename std::basic_streambuf<Char>::int_type int_type;
|
||||
typedef typename std::basic_streambuf<Char>::traits_type traits_type;
|
||||
|
||||
Buffer<Char> &buffer_;
|
||||
Char *start_;
|
||||
|
||||
public:
|
||||
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer), start_(&buffer[0])
|
||||
{
|
||||
this->setp(start_, start_ + buffer_.capacity());
|
||||
}
|
||||
|
||||
int_type overflow(int_type ch = traits_type::eof())
|
||||
{
|
||||
if (!traits_type::eq_int_type(ch, traits_type::eof()))
|
||||
{
|
||||
size_t buf_size = size();
|
||||
buffer_.resize(buf_size);
|
||||
buffer_.reserve(buf_size * 2);
|
||||
|
||||
start_ = &buffer_[0];
|
||||
start_[buf_size] = traits_type::to_char_type(ch);
|
||||
this->setp(start_+ buf_size + 1, start_ + buf_size * 2);
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return to_unsigned(this->pptr() - start_);
|
||||
}
|
||||
};
|
||||
|
||||
Yes &convert(std::ostream &);
|
||||
|
||||
struct DummyStream : std::ostream
|
||||
{
|
||||
DummyStream(); // Suppress a bogus warning in MSVC.
|
||||
// Hide all operator<< overloads from std::ostream.
|
||||
void operator<<(Null<>);
|
||||
};
|
||||
|
||||
No &operator<<(std::ostream &, int);
|
||||
|
||||
template<typename T>
|
||||
struct ConvertToIntImpl<T, true>
|
||||
{
|
||||
// Convert to int only if T doesn't have an overloaded operator<<.
|
||||
enum
|
||||
{
|
||||
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
|
||||
};
|
||||
};
|
||||
|
||||
// Write the content of w to os.
|
||||
void write(std::ostream &os, Writer &w);
|
||||
} // namespace internal
|
||||
|
||||
// Formats a value.
|
||||
template <typename Char, typename ArgFormatter, typename T>
|
||||
void format_arg(BasicFormatter<Char, ArgFormatter> &f,
|
||||
const Char *&format_str, const T &value)
|
||||
{
|
||||
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
|
||||
|
||||
internal::FormatBuf<Char> format_buf(buffer);
|
||||
std::basic_ostream<Char> output(&format_buf);
|
||||
output << value;
|
||||
|
||||
BasicStringRef<Char> str(&buffer[0], format_buf.size());
|
||||
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
|
||||
format_str = f.format(format_str, MakeArg(str));
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
|
||||
**Example**::
|
||||
|
||||
print(cerr, "Don't {}!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
|
||||
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
|
||||
} // namespace fmt
|
||||
|
||||
#ifdef FMT_HEADER_ONLY
|
||||
# include "ostream.cc"
|
||||
#endif
|
||||
|
||||
#endif // FMT_OSTREAM_H_
|
642
vendor/spdlog/spdlog/fmt/bundled/printf.h
vendored
Normal file
642
vendor/spdlog/spdlog/fmt/bundled/printf.h
vendored
Normal file
@ -0,0 +1,642 @@
|
||||
/*
|
||||
Formatting library for C++
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
For the license information refer to format.h.
|
||||
*/
|
||||
|
||||
#ifndef FMT_PRINTF_H_
|
||||
#define FMT_PRINTF_H_
|
||||
|
||||
#include <algorithm> // std::fill_n
|
||||
#include <limits> // std::numeric_limits
|
||||
|
||||
#include "fmt/ostream.h"
|
||||
|
||||
namespace fmt
|
||||
{
|
||||
namespace internal
|
||||
{
|
||||
|
||||
// Checks if a value fits in int - used to avoid warnings about comparing
|
||||
// signed and unsigned integers.
|
||||
template <bool IsSigned>
|
||||
struct IntChecker
|
||||
{
|
||||
template <typename T>
|
||||
static bool fits_in_int(T value)
|
||||
{
|
||||
unsigned max = std::numeric_limits<int>::max();
|
||||
return value <= max;
|
||||
}
|
||||
static bool fits_in_int(bool)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct IntChecker<true>
|
||||
{
|
||||
template <typename T>
|
||||
static bool fits_in_int(T value)
|
||||
{
|
||||
return value >= std::numeric_limits<int>::min() &&
|
||||
value <= std::numeric_limits<int>::max();
|
||||
}
|
||||
static bool fits_in_int(int)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class PrecisionHandler : public ArgVisitor<PrecisionHandler, int>
|
||||
{
|
||||
public:
|
||||
void report_unhandled_arg()
|
||||
{
|
||||
FMT_THROW(FormatError("precision is not integer"));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int visit_any_int(T value)
|
||||
{
|
||||
if (!IntChecker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
|
||||
FMT_THROW(FormatError("number is too big"));
|
||||
return static_cast<int>(value);
|
||||
}
|
||||
};
|
||||
|
||||
// IsZeroInt::visit(arg) returns true iff arg is a zero integer.
|
||||
class IsZeroInt : public ArgVisitor<IsZeroInt, bool>
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
bool visit_any_int(T value)
|
||||
{
|
||||
return value == 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_same
|
||||
{
|
||||
enum { value = 0 };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_same<T, T>
|
||||
{
|
||||
enum { value = 1 };
|
||||
};
|
||||
|
||||
// An argument visitor that converts an integer argument to T for printf,
|
||||
// if T is an integral type. If T is void, the argument is converted to
|
||||
// corresponding signed or unsigned type depending on the type specifier:
|
||||
// 'd' and 'i' - signed, other - unsigned)
|
||||
template <typename T = void>
|
||||
class ArgConverter : public ArgVisitor<ArgConverter<T>, void>
|
||||
{
|
||||
private:
|
||||
internal::Arg &arg_;
|
||||
wchar_t type_;
|
||||
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(ArgConverter);
|
||||
|
||||
public:
|
||||
ArgConverter(internal::Arg &arg, wchar_t type)
|
||||
: arg_(arg), type_(type) {}
|
||||
|
||||
void visit_bool(bool value)
|
||||
{
|
||||
if (type_ != 's')
|
||||
visit_any_int(value);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void visit_any_int(U value)
|
||||
{
|
||||
bool is_signed = type_ == 'd' || type_ == 'i';
|
||||
using internal::Arg;
|
||||
typedef typename internal::Conditional<
|
||||
is_same<T, void>::value, U, T>::type TargetType;
|
||||
if (sizeof(TargetType) <= sizeof(int))
|
||||
{
|
||||
// Extra casts are used to silence warnings.
|
||||
if (is_signed)
|
||||
{
|
||||
arg_.type = Arg::INT;
|
||||
arg_.int_value = static_cast<int>(static_cast<TargetType>(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
arg_.type = Arg::UINT;
|
||||
typedef typename internal::MakeUnsigned<TargetType>::Type Unsigned;
|
||||
arg_.uint_value = static_cast<unsigned>(static_cast<Unsigned>(value));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_signed)
|
||||
{
|
||||
arg_.type = Arg::LONG_LONG;
|
||||
// glibc's printf doesn't sign extend arguments of smaller types:
|
||||
// std::printf("%lld", -42); // prints "4294967254"
|
||||
// but we don't have to do the same because it's a UB.
|
||||
arg_.long_long_value = static_cast<LongLong>(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg_.type = Arg::ULONG_LONG;
|
||||
arg_.ulong_long_value =
|
||||
static_cast<typename internal::MakeUnsigned<U>::Type>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Converts an integer argument to char for printf.
|
||||
class CharConverter : public ArgVisitor<CharConverter, void>
|
||||
{
|
||||
private:
|
||||
internal::Arg &arg_;
|
||||
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(CharConverter);
|
||||
|
||||
public:
|
||||
explicit CharConverter(internal::Arg &arg) : arg_(arg) {}
|
||||
|
||||
template <typename T>
|
||||
void visit_any_int(T value)
|
||||
{
|
||||
arg_.type = internal::Arg::CHAR;
|
||||
arg_.int_value = static_cast<char>(value);
|
||||
}
|
||||
};
|
||||
|
||||
// Checks if an argument is a valid printf width specifier and sets
|
||||
// left alignment if it is negative.
|
||||
class WidthHandler : public ArgVisitor<WidthHandler, unsigned>
|
||||
{
|
||||
private:
|
||||
FormatSpec &spec_;
|
||||
|
||||
FMT_DISALLOW_COPY_AND_ASSIGN(WidthHandler);
|
||||
|
||||
public:
|
||||
explicit WidthHandler(FormatSpec &spec) : spec_(spec) {}
|
||||
|
||||
void report_unhandled_arg()
|
||||
{
|
||||
FMT_THROW(FormatError("width is not integer"));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
unsigned visit_any_int(T value)
|
||||
{
|
||||
typedef typename internal::IntTraits<T>::MainType UnsignedType;
|
||||
UnsignedType width = static_cast<UnsignedType>(value);
|
||||
if (internal::is_negative(value))
|
||||
{
|
||||
spec_.align_ = ALIGN_LEFT;
|
||||
width = 0 - width;
|
||||
}
|
||||
unsigned int_max = std::numeric_limits<int>::max();
|
||||
if (width > int_max)
|
||||
FMT_THROW(FormatError("number is too big"));
|
||||
return static_cast<unsigned>(width);
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
\rst
|
||||
A ``printf`` argument formatter based on the `curiously recurring template
|
||||
pattern <http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern>`_.
|
||||
|
||||
To use `~fmt::BasicPrintfArgFormatter` define a subclass that implements some
|
||||
or all of the visit methods with the same signatures as the methods in
|
||||
`~fmt::ArgVisitor`, for example, `~fmt::ArgVisitor::visit_int()`.
|
||||
Pass the subclass as the *Impl* template parameter. When a formatting
|
||||
function processes an argument, it will dispatch to a visit method
|
||||
specific to the argument type. For example, if the argument type is
|
||||
``double`` then the `~fmt::ArgVisitor::visit_double()` method of a subclass
|
||||
will be called. If the subclass doesn't contain a method with this signature,
|
||||
then a corresponding method of `~fmt::BasicPrintfArgFormatter` or its
|
||||
superclass will be called.
|
||||
\endrst
|
||||
*/
|
||||
template <typename Impl, typename Char>
|
||||
class BasicPrintfArgFormatter : public internal::ArgFormatterBase<Impl, Char>
|
||||
{
|
||||
private:
|
||||
void write_null_pointer()
|
||||
{
|
||||
this->spec().type_ = 0;
|
||||
this->write("(nil)");
|
||||
}
|
||||
|
||||
typedef internal::ArgFormatterBase<Impl, Char> Base;
|
||||
|
||||
public:
|
||||
/**
|
||||
\rst
|
||||
Constructs an argument formatter object.
|
||||
*writer* is a reference to the output writer and *spec* contains format
|
||||
specifier information for standard argument types.
|
||||
\endrst
|
||||
*/
|
||||
BasicPrintfArgFormatter(BasicWriter<Char> &writer, FormatSpec &spec)
|
||||
: internal::ArgFormatterBase<Impl, Char>(writer, spec) {}
|
||||
|
||||
/** Formats an argument of type ``bool``. */
|
||||
void visit_bool(bool value)
|
||||
{
|
||||
FormatSpec &fmt_spec = this->spec();
|
||||
if (fmt_spec.type_ != 's')
|
||||
return this->visit_any_int(value);
|
||||
fmt_spec.type_ = 0;
|
||||
this->write(value);
|
||||
}
|
||||
|
||||
/** Formats a character. */
|
||||
void visit_char(int value)
|
||||
{
|
||||
const FormatSpec &fmt_spec = this->spec();
|
||||
BasicWriter<Char> &w = this->writer();
|
||||
if (fmt_spec.type_ && fmt_spec.type_ != 'c')
|
||||
w.write_int(value, fmt_spec);
|
||||
typedef typename BasicWriter<Char>::CharPtr CharPtr;
|
||||
CharPtr out = CharPtr();
|
||||
if (fmt_spec.width_ > 1)
|
||||
{
|
||||
Char fill = ' ';
|
||||
out = w.grow_buffer(fmt_spec.width_);
|
||||
if (fmt_spec.align_ != ALIGN_LEFT)
|
||||
{
|
||||
std::fill_n(out, fmt_spec.width_ - 1, fill);
|
||||
out += fmt_spec.width_ - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fill_n(out + 1, fmt_spec.width_ - 1, fill);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out = w.grow_buffer(1);
|
||||
}
|
||||
*out = static_cast<Char>(value);
|
||||
}
|
||||
|
||||
/** Formats a null-terminated C string. */
|
||||
void visit_cstring(const char *value)
|
||||
{
|
||||
if (value)
|
||||
Base::visit_cstring(value);
|
||||
else if (this->spec().type_ == 'p')
|
||||
write_null_pointer();
|
||||
else
|
||||
this->write("(null)");
|
||||
}
|
||||
|
||||
/** Formats a pointer. */
|
||||
void visit_pointer(const void *value)
|
||||
{
|
||||
if (value)
|
||||
return Base::visit_pointer(value);
|
||||
this->spec().type_ = 0;
|
||||
write_null_pointer();
|
||||
}
|
||||
|
||||
/** Formats an argument of a custom (user-defined) type. */
|
||||
void visit_custom(internal::Arg::CustomValue c)
|
||||
{
|
||||
BasicFormatter<Char> formatter(ArgList(), this->writer());
|
||||
const Char format_str[] = {'}', 0};
|
||||
const Char *format = format_str;
|
||||
c.format(&formatter, c.value, &format);
|
||||
}
|
||||
};
|
||||
|
||||
/** The default printf argument formatter. */
|
||||
template <typename Char>
|
||||
class PrintfArgFormatter
|
||||
: public BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>
|
||||
{
|
||||
public:
|
||||
/** Constructs an argument formatter object. */
|
||||
PrintfArgFormatter(BasicWriter<Char> &w, FormatSpec &s)
|
||||
: BasicPrintfArgFormatter<PrintfArgFormatter<Char>, Char>(w, s) {}
|
||||
};
|
||||
|
||||
/** This template formats data and writes the output to a writer. */
|
||||
template <typename Char, typename ArgFormatter = PrintfArgFormatter<Char> >
|
||||
class PrintfFormatter : private internal::FormatterBase
|
||||
{
|
||||
private:
|
||||
BasicWriter<Char> &writer_;
|
||||
|
||||
void parse_flags(FormatSpec &spec, const Char *&s);
|
||||
|
||||
// Returns the argument with specified index or, if arg_index is equal
|
||||
// to the maximum unsigned value, the next argument.
|
||||
internal::Arg get_arg(
|
||||
const Char *s,
|
||||
unsigned arg_index = (std::numeric_limits<unsigned>::max)());
|
||||
|
||||
// Parses argument index, flags and width and returns the argument index.
|
||||
unsigned parse_header(const Char *&s, FormatSpec &spec);
|
||||
|
||||
public:
|
||||
/**
|
||||
\rst
|
||||
Constructs a ``PrintfFormatter`` object. References to the arguments and
|
||||
the writer are stored in the formatter object so make sure they have
|
||||
appropriate lifetimes.
|
||||
\endrst
|
||||
*/
|
||||
explicit PrintfFormatter(const ArgList &args, BasicWriter<Char> &w)
|
||||
: FormatterBase(args), writer_(w) {}
|
||||
|
||||
/** Formats stored arguments and writes the output to the writer. */
|
||||
FMT_API void format(BasicCStringRef<Char> format_str);
|
||||
};
|
||||
|
||||
template <typename Char, typename AF>
|
||||
void PrintfFormatter<Char, AF>::parse_flags(FormatSpec &spec, const Char *&s)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
switch (*s++)
|
||||
{
|
||||
case '-':
|
||||
spec.align_ = ALIGN_LEFT;
|
||||
break;
|
||||
case '+':
|
||||
spec.flags_ |= SIGN_FLAG | PLUS_FLAG;
|
||||
break;
|
||||
case '0':
|
||||
spec.fill_ = '0';
|
||||
break;
|
||||
case ' ':
|
||||
spec.flags_ |= SIGN_FLAG;
|
||||
break;
|
||||
case '#':
|
||||
spec.flags_ |= HASH_FLAG;
|
||||
break;
|
||||
default:
|
||||
--s;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char, typename AF>
|
||||
internal::Arg PrintfFormatter<Char, AF>::get_arg(const Char *s,
|
||||
unsigned arg_index)
|
||||
{
|
||||
(void)s;
|
||||
const char *error = 0;
|
||||
internal::Arg arg = arg_index == std::numeric_limits<unsigned>::max() ?
|
||||
next_arg(error) : FormatterBase::get_arg(arg_index - 1, error);
|
||||
if (error)
|
||||
FMT_THROW(FormatError(!*s ? "invalid format string" : error));
|
||||
return arg;
|
||||
}
|
||||
|
||||
template <typename Char, typename AF>
|
||||
unsigned PrintfFormatter<Char, AF>::parse_header(
|
||||
const Char *&s, FormatSpec &spec)
|
||||
{
|
||||
unsigned arg_index = std::numeric_limits<unsigned>::max();
|
||||
Char c = *s;
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
// Parse an argument index (if followed by '$') or a width possibly
|
||||
// preceded with '0' flag(s).
|
||||
unsigned value = internal::parse_nonnegative_int(s);
|
||||
if (*s == '$') // value is an argument index
|
||||
{
|
||||
++s;
|
||||
arg_index = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c == '0')
|
||||
spec.fill_ = '0';
|
||||
if (value != 0)
|
||||
{
|
||||
// Nonzero value means that we parsed width and don't need to
|
||||
// parse it or flags again, so return now.
|
||||
spec.width_ = value;
|
||||
return arg_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
parse_flags(spec, s);
|
||||
// Parse width.
|
||||
if (*s >= '0' && *s <= '9')
|
||||
{
|
||||
spec.width_ = internal::parse_nonnegative_int(s);
|
||||
}
|
||||
else if (*s == '*')
|
||||
{
|
||||
++s;
|
||||
spec.width_ = internal::WidthHandler(spec).visit(get_arg(s));
|
||||
}
|
||||
return arg_index;
|
||||
}
|
||||
|
||||
template <typename Char, typename AF>
|
||||
void PrintfFormatter<Char, AF>::format(BasicCStringRef<Char> format_str)
|
||||
{
|
||||
const Char *start = format_str.c_str();
|
||||
const Char *s = start;
|
||||
while (*s)
|
||||
{
|
||||
Char c = *s++;
|
||||
if (c != '%') continue;
|
||||
if (*s == c)
|
||||
{
|
||||
write(writer_, start, s);
|
||||
start = ++s;
|
||||
continue;
|
||||
}
|
||||
write(writer_, start, s - 1);
|
||||
|
||||
FormatSpec spec;
|
||||
spec.align_ = ALIGN_RIGHT;
|
||||
|
||||
// Parse argument index, flags and width.
|
||||
unsigned arg_index = parse_header(s, spec);
|
||||
|
||||
// Parse precision.
|
||||
if (*s == '.')
|
||||
{
|
||||
++s;
|
||||
if ('0' <= *s && *s <= '9')
|
||||
{
|
||||
spec.precision_ = static_cast<int>(internal::parse_nonnegative_int(s));
|
||||
}
|
||||
else if (*s == '*')
|
||||
{
|
||||
++s;
|
||||
spec.precision_ = internal::PrecisionHandler().visit(get_arg(s));
|
||||
}
|
||||
}
|
||||
|
||||
using internal::Arg;
|
||||
Arg arg = get_arg(s, arg_index);
|
||||
if (spec.flag(HASH_FLAG) && internal::IsZeroInt().visit(arg))
|
||||
spec.flags_ &= ~internal::to_unsigned<int>(HASH_FLAG);
|
||||
if (spec.fill_ == '0')
|
||||
{
|
||||
if (arg.type <= Arg::LAST_NUMERIC_TYPE)
|
||||
spec.align_ = ALIGN_NUMERIC;
|
||||
else
|
||||
spec.fill_ = ' '; // Ignore '0' flag for non-numeric types.
|
||||
}
|
||||
|
||||
// Parse length and convert the argument to the required type.
|
||||
using internal::ArgConverter;
|
||||
switch (*s++)
|
||||
{
|
||||
case 'h':
|
||||
if (*s == 'h')
|
||||
ArgConverter<signed char>(arg, *++s).visit(arg);
|
||||
else
|
||||
ArgConverter<short>(arg, *s).visit(arg);
|
||||
break;
|
||||
case 'l':
|
||||
if (*s == 'l')
|
||||
ArgConverter<fmt::LongLong>(arg, *++s).visit(arg);
|
||||
else
|
||||
ArgConverter<long>(arg, *s).visit(arg);
|
||||
break;
|
||||
case 'j':
|
||||
ArgConverter<intmax_t>(arg, *s).visit(arg);
|
||||
break;
|
||||
case 'z':
|
||||
ArgConverter<std::size_t>(arg, *s).visit(arg);
|
||||
break;
|
||||
case 't':
|
||||
ArgConverter<std::ptrdiff_t>(arg, *s).visit(arg);
|
||||
break;
|
||||
case 'L':
|
||||
// printf produces garbage when 'L' is omitted for long double, no
|
||||
// need to do the same.
|
||||
break;
|
||||
default:
|
||||
--s;
|
||||
ArgConverter<void>(arg, *s).visit(arg);
|
||||
}
|
||||
|
||||
// Parse type.
|
||||
if (!*s)
|
||||
FMT_THROW(FormatError("invalid format string"));
|
||||
spec.type_ = static_cast<char>(*s++);
|
||||
if (arg.type <= Arg::LAST_INTEGER_TYPE)
|
||||
{
|
||||
// Normalize type.
|
||||
switch (spec.type_)
|
||||
{
|
||||
case 'i':
|
||||
case 'u':
|
||||
spec.type_ = 'd';
|
||||
break;
|
||||
case 'c':
|
||||
// TODO: handle wchar_t
|
||||
internal::CharConverter(arg).visit(arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
start = s;
|
||||
|
||||
// Format argument.
|
||||
AF(writer_, spec).visit(arg);
|
||||
}
|
||||
write(writer_, start, s);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void printf(BasicWriter<Char> &w, BasicCStringRef<Char> format, ArgList args)
|
||||
{
|
||||
PrintfFormatter<Char>(args, w).format(format);
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Formats arguments and returns the result as a string.
|
||||
|
||||
**Example**::
|
||||
|
||||
std::string message = fmt::sprintf("The answer is %d", 42);
|
||||
\endrst
|
||||
*/
|
||||
inline std::string sprintf(CStringRef format, ArgList args)
|
||||
{
|
||||
MemoryWriter w;
|
||||
printf(w, format, args);
|
||||
return w.str();
|
||||
}
|
||||
FMT_VARIADIC(std::string, sprintf, CStringRef)
|
||||
|
||||
inline std::wstring sprintf(WCStringRef format, ArgList args)
|
||||
{
|
||||
WMemoryWriter w;
|
||||
printf(w, format, args);
|
||||
return w.str();
|
||||
}
|
||||
FMT_VARIADIC_W(std::wstring, sprintf, WCStringRef)
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the file *f*.
|
||||
|
||||
**Example**::
|
||||
|
||||
fmt::fprintf(stderr, "Don't %s!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
FMT_API int fprintf(std::FILE *f, CStringRef format, ArgList args);
|
||||
FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef)
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to ``stdout``.
|
||||
|
||||
**Example**::
|
||||
|
||||
fmt::printf("Elapsed time: %.2f seconds", 1.23);
|
||||
\endrst
|
||||
*/
|
||||
inline int printf(CStringRef format, ArgList args)
|
||||
{
|
||||
return fprintf(stdout, format, args);
|
||||
}
|
||||
FMT_VARIADIC(int, printf, CStringRef)
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
|
||||
**Example**::
|
||||
|
||||
fprintf(cerr, "Don't %s!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
inline int fprintf(std::ostream &os, CStringRef format_str, ArgList args)
|
||||
{
|
||||
MemoryWriter w;
|
||||
printf(w, format_str, args);
|
||||
internal::write(os, w);
|
||||
return static_cast<int>(w.size());
|
||||
}
|
||||
FMT_VARIADIC(int, fprintf, std::ostream &, CStringRef)
|
||||
} // namespace fmt
|
||||
|
||||
#endif // FMT_PRINTF_H_
|
28
vendor/spdlog/spdlog/fmt/fmt.h
vendored
Normal file
28
vendor/spdlog/spdlog/fmt/fmt.h
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// Copyright(c) 2016 Gabi Melman.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// Include a bundled header-only copy of fmtlib or an external one.
|
||||
// By default spdlog include its own copy.
|
||||
//
|
||||
|
||||
#if !defined(SPDLOG_FMT_EXTERNAL)
|
||||
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
#define FMT_HEADER_ONLY
|
||||
#endif
|
||||
#ifndef FMT_USE_WINDOWS_H
|
||||
#define FMT_USE_WINDOWS_H 0
|
||||
#endif
|
||||
#include <spdlog/fmt/bundled/format.h>
|
||||
|
||||
#else //external fmtlib
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#endif
|
||||
|
17
vendor/spdlog/spdlog/fmt/ostr.h
vendored
Normal file
17
vendor/spdlog/spdlog/fmt/ostr.h
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
//
|
||||
// Copyright(c) 2016 Gabi Melman.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
// include external or bundled copy of fmtlib's ostream support
|
||||
//
|
||||
#if !defined(SPDLOG_FMT_EXTERNAL)
|
||||
#include <spdlog/fmt/fmt.h>
|
||||
#include <spdlog/fmt/bundled/ostream.h>
|
||||
#else
|
||||
#include <fmt/ostream.h>
|
||||
#endif
|
||||
|
||||
|
9
vendor/spdlog/spdlog/formatter.h
vendored
9
vendor/spdlog/spdlog/formatter.h
vendored
@ -5,7 +5,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "details/log_msg.h"
|
||||
#include <spdlog/details/log_msg.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
namespace details
|
||||
@ -36,5 +41,5 @@ private:
|
||||
};
|
||||
}
|
||||
|
||||
#include "details/pattern_formatter_impl.h"
|
||||
#include <spdlog/details/pattern_formatter_impl.h>
|
||||
|
||||
|
111
vendor/spdlog/spdlog/logger.h
vendored
111
vendor/spdlog/spdlog/logger.h
vendored
@ -12,19 +12,16 @@
|
||||
// 2. Format the message using the formatter function
|
||||
// 3. Pass the formatted message to its sinks to performa the actual logging
|
||||
|
||||
#include<vector>
|
||||
#include<memory>
|
||||
#include "sinks/base_sink.h"
|
||||
#include "common.h"
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
#include <spdlog/common.h>
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
|
||||
namespace details
|
||||
{
|
||||
class line_logger;
|
||||
}
|
||||
|
||||
class logger
|
||||
{
|
||||
public:
|
||||
@ -37,77 +34,61 @@ public:
|
||||
logger(const logger&) = delete;
|
||||
logger& operator=(const logger&) = delete;
|
||||
|
||||
|
||||
template <typename... Args> void log(level::level_enum lvl, const char* fmt, const Args&... args);
|
||||
template <typename... Args> void log(level::level_enum lvl, const char* msg);
|
||||
template <typename... Args> void trace(const char* fmt, const Args&... args);
|
||||
template <typename... Args> void debug(const char* fmt, const Args&... args);
|
||||
template <typename... Args> void info(const char* fmt, const Args&... args);
|
||||
template <typename... Args> void warn(const char* fmt, const Args&... args);
|
||||
template <typename... Args> void error(const char* fmt, const Args&... args);
|
||||
template <typename... Args> void critical(const char* fmt, const Args&... args);
|
||||
|
||||
template <typename T> void log(level::level_enum lvl, const T&);
|
||||
template <typename T> void trace(const T&);
|
||||
template <typename T> void debug(const T&);
|
||||
template <typename T> void info(const T&);
|
||||
template <typename T> void warn(const T&);
|
||||
template <typename T> void error(const T&);
|
||||
template <typename T> void critical(const T&);
|
||||
|
||||
bool should_log(level::level_enum) const;
|
||||
void set_level(level::level_enum);
|
||||
level::level_enum level() const;
|
||||
|
||||
const std::string& name() const;
|
||||
bool should_log(level::level_enum) const;
|
||||
|
||||
// logger.info(cppformat_string, arg1, arg2, arg3, ...) call style
|
||||
template <typename... Args> details::line_logger trace(const char* fmt, const Args&... args);
|
||||
template <typename... Args> details::line_logger debug(const char* fmt, const Args&... args);
|
||||
template <typename... Args> details::line_logger info(const char* fmt, const Args&... args);
|
||||
template <typename... Args> details::line_logger notice(const char* fmt, const Args&... args);
|
||||
template <typename... Args> details::line_logger warn(const char* fmt, const Args&... args);
|
||||
template <typename... Args> details::line_logger error(const char* fmt, const Args&... args);
|
||||
template <typename... Args> details::line_logger critical(const char* fmt, const Args&... args);
|
||||
template <typename... Args> details::line_logger alert(const char* fmt, const Args&... args);
|
||||
template <typename... Args> details::line_logger emerg(const char* fmt, const Args&... args);
|
||||
|
||||
|
||||
// logger.info(msg) << ".." call style
|
||||
template <typename T> details::line_logger trace(const T&);
|
||||
template <typename T> details::line_logger debug(const T&);
|
||||
template <typename T> details::line_logger info(const T&);
|
||||
template <typename T> details::line_logger notice(const T&);
|
||||
template <typename T> details::line_logger warn(const T&);
|
||||
template <typename T> details::line_logger error(const T&);
|
||||
template <typename T> details::line_logger critical(const T&);
|
||||
template <typename T> details::line_logger alert(const T&);
|
||||
template <typename T> details::line_logger emerg(const T&);
|
||||
|
||||
|
||||
// logger.info() << ".." call style
|
||||
details::line_logger trace();
|
||||
details::line_logger debug();
|
||||
details::line_logger info();
|
||||
details::line_logger notice();
|
||||
details::line_logger warn();
|
||||
details::line_logger error();
|
||||
details::line_logger critical();
|
||||
details::line_logger alert();
|
||||
details::line_logger emerg();
|
||||
|
||||
|
||||
|
||||
// Create log message with the given level, no matter what is the actual logger's level
|
||||
template <typename... Args>
|
||||
details::line_logger force_log(level::level_enum lvl, const char* fmt, const Args&... args);
|
||||
|
||||
// Set the format of the log messages from this logger
|
||||
void set_pattern(const std::string&);
|
||||
void set_formatter(formatter_ptr);
|
||||
|
||||
// error handler
|
||||
void set_error_handler(log_err_handler);
|
||||
log_err_handler error_handler();
|
||||
|
||||
// automatically call flush() if message level >= log_level
|
||||
void flush_on(level::level_enum log_level);
|
||||
|
||||
virtual void flush();
|
||||
|
||||
protected:
|
||||
virtual void _log_msg(details::log_msg&);
|
||||
virtual void _sink_it(details::log_msg&);
|
||||
virtual void _set_pattern(const std::string&);
|
||||
virtual void _set_formatter(formatter_ptr);
|
||||
details::line_logger _log_if_enabled(level::level_enum lvl);
|
||||
template <typename... Args>
|
||||
details::line_logger _log_if_enabled(level::level_enum lvl, const char* fmt, const Args&... args);
|
||||
template<typename T>
|
||||
inline details::line_logger _log_if_enabled(level::level_enum lvl, const T& msg);
|
||||
|
||||
// default error handler: print the error to stderr with the max rate of 1 message/minute
|
||||
virtual void _default_err_handler(const std::string &msg);
|
||||
|
||||
friend details::line_logger;
|
||||
std::string _name;
|
||||
// return true if the given message level should trigger a flush
|
||||
bool _should_flush_on(const details::log_msg&);
|
||||
|
||||
const std::string _name;
|
||||
std::vector<sink_ptr> _sinks;
|
||||
formatter_ptr _formatter;
|
||||
std::atomic_int _level;
|
||||
|
||||
spdlog::level_t _level;
|
||||
spdlog::level_t _flush_level;
|
||||
log_err_handler _err_handler;
|
||||
std::atomic<time_t> _last_err_time;
|
||||
};
|
||||
}
|
||||
|
||||
#include "./details/logger_impl.h"
|
||||
#include <spdlog/details/logger_impl.h>
|
||||
|
||||
|
||||
|
53
vendor/spdlog/spdlog/sinks/android_sink.h
vendored
53
vendor/spdlog/spdlog/sinks/android_sink.h
vendored
@ -7,49 +7,43 @@
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
#include <mutex>
|
||||
#include "base_sink.h"
|
||||
#include "../details/null_mutex.h"
|
||||
#include <spdlog/sinks/sink.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <android/log.h>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
namespace sinks
|
||||
{
|
||||
|
||||
/*
|
||||
* Android sink (logging using __android_log_write)
|
||||
* __android_log_write is thread-safe. No lock is needed.
|
||||
*/
|
||||
template<class Mutex>
|
||||
class base_android_sink : public base_sink < Mutex >
|
||||
class android_sink : public sink
|
||||
{
|
||||
public:
|
||||
explicit base_android_sink(std::string tag="spdlog"): _tag(tag)
|
||||
explicit android_sink(const std::string& tag = "spdlog"): _tag(tag) {}
|
||||
|
||||
void log(const details::log_msg& msg) override
|
||||
{
|
||||
const android_LogPriority priority = convert_to_android(msg.level);
|
||||
// See system/core/liblog/logger_write.c for explanation of return value
|
||||
const int ret = __android_log_write(
|
||||
priority, _tag.c_str(), msg.formatted.c_str()
|
||||
);
|
||||
if (ret < 0)
|
||||
{
|
||||
throw spdlog_ex("__android_log_write() failed", ret);
|
||||
}
|
||||
}
|
||||
|
||||
void flush() override
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void _sink_it(const details::log_msg& msg) override
|
||||
{
|
||||
const android_LogPriority priority = convert_to_android(msg.level);
|
||||
const int expected_size = msg.formatted.size();
|
||||
const int size = __android_log_write(
|
||||
priority, _tag.c_str(), msg.formatted.c_str()
|
||||
);
|
||||
if (size > expected_size)
|
||||
{
|
||||
// Will write a little bit more than original message
|
||||
}
|
||||
else
|
||||
{
|
||||
throw spdlog_ex("Send to Android logcat failed");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static android_LogPriority convert_to_android(spdlog::level::level_enum level)
|
||||
{
|
||||
@ -61,29 +55,20 @@ private:
|
||||
return ANDROID_LOG_DEBUG;
|
||||
case spdlog::level::info:
|
||||
return ANDROID_LOG_INFO;
|
||||
case spdlog::level::notice:
|
||||
return ANDROID_LOG_INFO;
|
||||
case spdlog::level::warn:
|
||||
return ANDROID_LOG_WARN;
|
||||
case spdlog::level::err:
|
||||
return ANDROID_LOG_ERROR;
|
||||
case spdlog::level::critical:
|
||||
return ANDROID_LOG_FATAL;
|
||||
case spdlog::level::alert:
|
||||
return ANDROID_LOG_FATAL;
|
||||
case spdlog::level::emerg:
|
||||
return ANDROID_LOG_FATAL;
|
||||
default:
|
||||
throw spdlog_ex("Incorrect level value");
|
||||
return ANDROID_LOG_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
std::string _tag;
|
||||
};
|
||||
|
||||
typedef base_android_sink<std::mutex> android_sink_mt;
|
||||
typedef base_android_sink<details::null_mutex> android_sink_st;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
116
vendor/spdlog/spdlog/sinks/ansicolor_sink.h
vendored
Normal file
116
vendor/spdlog/spdlog/sinks/ansicolor_sink.h
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
//
|
||||
// Copyright(c) 2016 Kevin M. Godby (a modified version by spdlog).
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
#include <spdlog/common.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
namespace sinks
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The ansi_color_sink is a decorator around another sink and prefixes
|
||||
* the output with an ANSI escape sequence color code depending on the severity
|
||||
* of the message.
|
||||
*/
|
||||
class ansicolor_sink : public sink
|
||||
{
|
||||
public:
|
||||
ansicolor_sink(sink_ptr wrapped_sink);
|
||||
virtual ~ansicolor_sink();
|
||||
|
||||
ansicolor_sink(const ansicolor_sink& other) = delete;
|
||||
ansicolor_sink& operator=(const ansicolor_sink& other) = delete;
|
||||
|
||||
virtual void log(const details::log_msg& msg) override;
|
||||
virtual void flush() override;
|
||||
|
||||
void set_color(level::level_enum level, const std::string& color);
|
||||
|
||||
/// Formatting codes
|
||||
const std::string reset = "\033[00m";
|
||||
const std::string bold = "\033[1m";
|
||||
const std::string dark = "\033[2m";
|
||||
const std::string underline = "\033[4m";
|
||||
const std::string blink = "\033[5m";
|
||||
const std::string reverse = "\033[7m";
|
||||
const std::string concealed = "\033[8m";
|
||||
|
||||
// Foreground colors
|
||||
const std::string grey = "\033[30m";
|
||||
const std::string red = "\033[31m";
|
||||
const std::string green = "\033[32m";
|
||||
const std::string yellow = "\033[33m";
|
||||
const std::string blue = "\033[34m";
|
||||
const std::string magenta = "\033[35m";
|
||||
const std::string cyan = "\033[36m";
|
||||
const std::string white = "\033[37m";
|
||||
|
||||
/// Background colors
|
||||
const std::string on_grey = "\033[40m";
|
||||
const std::string on_red = "\033[41m";
|
||||
const std::string on_green = "\033[42m";
|
||||
const std::string on_yellow = "\033[43m";
|
||||
const std::string on_blue = "\033[44m";
|
||||
const std::string on_magenta = "\033[45m";
|
||||
const std::string on_cyan = "\033[46m";
|
||||
const std::string on_white = "\033[47m";
|
||||
|
||||
|
||||
protected:
|
||||
sink_ptr sink_;
|
||||
std::map<level::level_enum, std::string> colors_;
|
||||
};
|
||||
|
||||
inline ansicolor_sink::ansicolor_sink(sink_ptr wrapped_sink) : sink_(wrapped_sink)
|
||||
{
|
||||
colors_[level::trace] = cyan;
|
||||
colors_[level::debug] = cyan;
|
||||
colors_[level::info] = bold;
|
||||
colors_[level::warn] = yellow + bold;
|
||||
colors_[level::err] = red + bold;
|
||||
colors_[level::critical] = bold + on_red;
|
||||
colors_[level::off] = reset;
|
||||
}
|
||||
|
||||
inline void ansicolor_sink::log(const details::log_msg& msg)
|
||||
{
|
||||
// Wrap the originally formatted message in color codes
|
||||
const std::string& prefix = colors_[msg.level];
|
||||
const std::string& s = msg.formatted.str();
|
||||
const std::string& suffix = reset;
|
||||
details::log_msg m;
|
||||
m.level = msg.level;
|
||||
m.logger_name = msg.logger_name;
|
||||
m.time = msg.time;
|
||||
m.thread_id = msg.thread_id;
|
||||
m.formatted << prefix << s << suffix;
|
||||
sink_->log(m);
|
||||
}
|
||||
|
||||
inline void ansicolor_sink::flush()
|
||||
{
|
||||
sink_->flush();
|
||||
}
|
||||
|
||||
inline void ansicolor_sink::set_color(level::level_enum level, const std::string& color)
|
||||
{
|
||||
colors_[level] = color;
|
||||
}
|
||||
|
||||
inline ansicolor_sink::~ansicolor_sink()
|
||||
{
|
||||
flush();
|
||||
}
|
||||
|
||||
} // namespace sinks
|
||||
} // namespace spdlog
|
||||
|
14
vendor/spdlog/spdlog/sinks/base_sink.h
vendored
14
vendor/spdlog/spdlog/sinks/base_sink.h
vendored
@ -7,17 +7,15 @@
|
||||
//
|
||||
// base sink templated over a mutex (either dummy or realy)
|
||||
// concrete implementation should only overrid the _sink_it method.
|
||||
// all locking is taken care of here so no locking needed by the implementors..
|
||||
// all locking is taken care of here so no locking needed by the implementers..
|
||||
//
|
||||
|
||||
#include<string>
|
||||
#include<mutex>
|
||||
#include<atomic>
|
||||
#include "./sink.h"
|
||||
#include "../formatter.h"
|
||||
#include "../common.h"
|
||||
#include "../details/log_msg.h"
|
||||
#include <spdlog/sinks/sink.h>
|
||||
#include <spdlog/formatter.h>
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/details/log_msg.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
|
47
vendor/spdlog/spdlog/sinks/dist_sink.h
vendored
47
vendor/spdlog/spdlog/sinks/dist_sink.h
vendored
@ -5,15 +5,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <list>
|
||||
#include <spdlog/details/log_msg.h>
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
#include <spdlog/sinks/sink.h>
|
||||
|
||||
#include "../details/log_msg.h"
|
||||
#include "../details/null_mutex.h"
|
||||
#include "./base_sink.h"
|
||||
#include "./sink.h"
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
// Distribution sink (mux). Stores a vector of sinks which get called when log is called
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -29,40 +31,37 @@ public:
|
||||
virtual ~dist_sink() = default;
|
||||
|
||||
protected:
|
||||
std::vector<std::shared_ptr<sink>> _sinks;
|
||||
|
||||
void _sink_it(const details::log_msg& msg) override
|
||||
{
|
||||
for (auto iter = _sinks.begin(); iter != _sinks.end(); iter++)
|
||||
(*iter)->log(msg);
|
||||
for (auto &sink : _sinks)
|
||||
{
|
||||
if( sink->should_log( msg.level))
|
||||
{
|
||||
sink->log(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<sink>> _sinks;
|
||||
|
||||
public:
|
||||
void flush() override
|
||||
{
|
||||
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
|
||||
for (auto iter = _sinks.begin(); iter != _sinks.end(); iter++)
|
||||
(*iter)->flush();
|
||||
for (auto &sink : _sinks)
|
||||
sink->flush();
|
||||
}
|
||||
|
||||
void add_sink(std::shared_ptr<sink> sink)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
|
||||
if (sink &&
|
||||
_sinks.end() == std::find(_sinks.begin(), _sinks.end(), sink))
|
||||
{
|
||||
_sinks.push_back(sink);
|
||||
}
|
||||
_sinks.push_back(sink);
|
||||
}
|
||||
|
||||
void remove_sink(std::shared_ptr<sink> sink)
|
||||
{
|
||||
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
|
||||
auto pos = std::find(_sinks.begin(), _sinks.end(), sink);
|
||||
if (pos != _sinks.end())
|
||||
{
|
||||
_sinks.erase(pos);
|
||||
}
|
||||
_sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink), _sinks.end());
|
||||
}
|
||||
};
|
||||
|
||||
|
129
vendor/spdlog/spdlog/sinks/file_sinks.h
vendored
129
vendor/spdlog/spdlog/sinks/file_sinks.h
vendored
@ -5,28 +5,33 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
#include <spdlog/details/file_helper.h>
|
||||
#include <spdlog/fmt/fmt.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <mutex>
|
||||
#include "base_sink.h"
|
||||
#include "../details/null_mutex.h"
|
||||
#include "../details/file_helper.h"
|
||||
#include "../details/format.h"
|
||||
#include <string>
|
||||
#include <cerrno>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
namespace sinks
|
||||
{
|
||||
/*
|
||||
* Trivial file sink with single file as target
|
||||
*/
|
||||
* Trivial file sink with single file as target
|
||||
*/
|
||||
template<class Mutex>
|
||||
class simple_file_sink : public base_sink < Mutex >
|
||||
{
|
||||
public:
|
||||
explicit simple_file_sink(const std::string &filename,
|
||||
bool force_flush = false) :
|
||||
_file_helper(force_flush)
|
||||
explicit simple_file_sink(const filename_t &filename, bool truncate = false)
|
||||
{
|
||||
_file_helper.open(filename);
|
||||
_file_helper.open(filename, truncate);
|
||||
}
|
||||
void flush() override
|
||||
{
|
||||
@ -46,21 +51,20 @@ typedef simple_file_sink<std::mutex> simple_file_sink_mt;
|
||||
typedef simple_file_sink<details::null_mutex> simple_file_sink_st;
|
||||
|
||||
/*
|
||||
* Rotating file sink based on size
|
||||
*/
|
||||
* Rotating file sink based on size
|
||||
*/
|
||||
template<class Mutex>
|
||||
class rotating_file_sink : public base_sink < Mutex >
|
||||
{
|
||||
public:
|
||||
rotating_file_sink(const std::string &base_filename, const std::string &extension,
|
||||
std::size_t max_size, std::size_t max_files,
|
||||
bool force_flush = false) :
|
||||
rotating_file_sink(const filename_t &base_filename, const filename_t &extension,
|
||||
std::size_t max_size, std::size_t max_files ) :
|
||||
_base_filename(base_filename),
|
||||
_extension(extension),
|
||||
_max_size(max_size),
|
||||
_max_files(max_files),
|
||||
_current_size(0),
|
||||
_file_helper(force_flush)
|
||||
_file_helper()
|
||||
{
|
||||
_file_helper.open(calc_filename(_base_filename, 0, _extension));
|
||||
_current_size = _file_helper.size(); //expensive. called only once
|
||||
@ -84,13 +88,13 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
static std::string calc_filename(const std::string& filename, std::size_t index, const std::string& extension)
|
||||
static filename_t calc_filename(const filename_t& filename, std::size_t index, const filename_t& extension)
|
||||
{
|
||||
fmt::MemoryWriter w;
|
||||
std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
|
||||
if (index)
|
||||
w.write("{}.{}.{}", filename, index, extension);
|
||||
w.write(SPDLOG_FILENAME_T("{}.{}.{}"), filename, index, extension);
|
||||
else
|
||||
w.write("{}.{}", filename, extension);
|
||||
w.write(SPDLOG_FILENAME_T("{}.{}"), filename, extension);
|
||||
return w.str();
|
||||
}
|
||||
|
||||
@ -102,28 +106,29 @@ private:
|
||||
|
||||
void _rotate()
|
||||
{
|
||||
using details::os::filename_to_str;
|
||||
_file_helper.close();
|
||||
for (auto i = _max_files; i > 0; --i)
|
||||
{
|
||||
std::string src = calc_filename(_base_filename, i - 1, _extension);
|
||||
std::string target = calc_filename(_base_filename, i, _extension);
|
||||
filename_t src = calc_filename(_base_filename, i - 1, _extension);
|
||||
filename_t target = calc_filename(_base_filename, i, _extension);
|
||||
|
||||
if (details::file_helper::file_exists(target))
|
||||
{
|
||||
if (std::remove(target.c_str()) != 0)
|
||||
if (details::os::remove(target) != 0)
|
||||
{
|
||||
throw spdlog_ex("rotating_file_sink: failed removing " + target);
|
||||
throw spdlog_ex("rotating_file_sink: failed removing " + filename_to_str(target), errno);
|
||||
}
|
||||
}
|
||||
if (details::file_helper::file_exists(src) && std::rename(src.c_str(), target.c_str()))
|
||||
if (details::file_helper::file_exists(src) && details::os::rename(src, target))
|
||||
{
|
||||
throw spdlog_ex("rotating_file_sink: failed renaming " + src + " to " + target);
|
||||
throw spdlog_ex("rotating_file_sink: failed renaming " + filename_to_str(src) + " to " + filename_to_str(target), errno);
|
||||
}
|
||||
}
|
||||
_file_helper.reopen(true);
|
||||
}
|
||||
std::string _base_filename;
|
||||
std::string _extension;
|
||||
filename_t _base_filename;
|
||||
filename_t _extension;
|
||||
std::size_t _max_size;
|
||||
std::size_t _max_files;
|
||||
std::size_t _current_size;
|
||||
@ -134,28 +139,56 @@ typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
|
||||
typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;
|
||||
|
||||
/*
|
||||
* Rotating file sink based on date. rotates at midnight
|
||||
*/
|
||||
template<class Mutex>
|
||||
* Default generator of daily log file names.
|
||||
*/
|
||||
struct default_daily_file_name_calculator
|
||||
{
|
||||
// Create filename for the form basename.YYYY-MM-DD_hh-mm.extension
|
||||
static filename_t calc_filename(const filename_t& basename, const filename_t& extension)
|
||||
{
|
||||
std::tm tm = spdlog::details::os::localtime();
|
||||
std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
|
||||
w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, extension);
|
||||
return w.str();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Generator of daily log file names in format basename.YYYY-MM-DD.extension
|
||||
*/
|
||||
struct dateonly_daily_file_name_calculator
|
||||
{
|
||||
// Create filename for the form basename.YYYY-MM-DD.extension
|
||||
static filename_t calc_filename(const filename_t& basename, const filename_t& extension)
|
||||
{
|
||||
std::tm tm = spdlog::details::os::localtime();
|
||||
std::conditional<std::is_same<filename_t::value_type, char>::value, fmt::MemoryWriter, fmt::WMemoryWriter>::type w;
|
||||
w.write(SPDLOG_FILENAME_T("{}_{:04d}-{:02d}-{:02d}.{}"), basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, extension);
|
||||
return w.str();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Rotating file sink based on date. rotates at midnight
|
||||
*/
|
||||
template<class Mutex, class FileNameCalc = default_daily_file_name_calculator>
|
||||
class daily_file_sink :public base_sink < Mutex >
|
||||
{
|
||||
public:
|
||||
//create daily file sink which rotates on given time
|
||||
daily_file_sink(
|
||||
const std::string& base_filename,
|
||||
const std::string& extension,
|
||||
const filename_t& base_filename,
|
||||
const filename_t& extension,
|
||||
int rotation_hour,
|
||||
int rotation_minute,
|
||||
bool force_flush = false) : _base_filename(base_filename),
|
||||
int rotation_minute) : _base_filename(base_filename),
|
||||
_extension(extension),
|
||||
_rotation_h(rotation_hour),
|
||||
_rotation_m(rotation_minute),
|
||||
_file_helper(force_flush)
|
||||
_rotation_m(rotation_minute)
|
||||
{
|
||||
if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
|
||||
throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
|
||||
_rotation_tp = _next_rotation_tp();
|
||||
_file_helper.open(calc_filename(_base_filename, _extension));
|
||||
_file_helper.open(FileNameCalc::calc_filename(_base_filename, _extension));
|
||||
}
|
||||
|
||||
void flush() override
|
||||
@ -168,7 +201,7 @@ protected:
|
||||
{
|
||||
if (std::chrono::system_clock::now() >= _rotation_tp)
|
||||
{
|
||||
_file_helper.open(calc_filename(_base_filename, _extension));
|
||||
_file_helper.open(FileNameCalc::calc_filename(_base_filename, _extension));
|
||||
_rotation_tp = _next_rotation_tp();
|
||||
}
|
||||
_file_helper.write(msg);
|
||||
@ -177,8 +210,7 @@ protected:
|
||||
private:
|
||||
std::chrono::system_clock::time_point _next_rotation_tp()
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto now = system_clock::now();
|
||||
auto now = std::chrono::system_clock::now();
|
||||
time_t tnow = std::chrono::system_clock::to_time_t(now);
|
||||
tm date = spdlog::details::os::localtime(tnow);
|
||||
date.tm_hour = _rotation_h;
|
||||
@ -188,20 +220,11 @@ private:
|
||||
if (rotation_time > now)
|
||||
return rotation_time;
|
||||
else
|
||||
return system_clock::time_point(rotation_time + hours(24));
|
||||
return std::chrono::system_clock::time_point(rotation_time + std::chrono::hours(24));
|
||||
}
|
||||
|
||||
//Create filename for the form basename.YYYY-MM-DD.extension
|
||||
static std::string calc_filename(const std::string& basename, const std::string& extension)
|
||||
{
|
||||
std::tm tm = spdlog::details::os::localtime();
|
||||
fmt::MemoryWriter w;
|
||||
w.write("{}_{:04d}-{:02d}-{:02d}_{:02d}-{:02d}.{}", basename, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, extension);
|
||||
return w.str();
|
||||
}
|
||||
|
||||
std::string _base_filename;
|
||||
std::string _extension;
|
||||
filename_t _base_filename;
|
||||
filename_t _extension;
|
||||
int _rotation_h;
|
||||
int _rotation_m;
|
||||
std::chrono::system_clock::time_point _rotation_tp;
|
||||
|
50
vendor/spdlog/spdlog/sinks/msvc_sink.h
vendored
Normal file
50
vendor/spdlog/spdlog/sinks/msvc_sink.h
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// Copyright(c) 2016 Alexander Dalshov.
|
||||
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
|
||||
#include <WinBase.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
namespace sinks
|
||||
{
|
||||
/*
|
||||
* MSVC sink (logging using OutputDebugStringA)
|
||||
*/
|
||||
template<class Mutex>
|
||||
class msvc_sink : public base_sink < Mutex >
|
||||
{
|
||||
public:
|
||||
explicit msvc_sink()
|
||||
{
|
||||
}
|
||||
|
||||
void flush() override
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void _sink_it(const details::log_msg& msg) override
|
||||
{
|
||||
OutputDebugStringA(msg.formatted.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
typedef msvc_sink<std::mutex> msvc_sink_mt;
|
||||
typedef msvc_sink<details::null_mutex> msvc_sink_st;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
7
vendor/spdlog/spdlog/sinks/null_sink.h
vendored
7
vendor/spdlog/spdlog/sinks/null_sink.h
vendored
@ -4,10 +4,11 @@
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#include <mutex>
|
||||
#include "./base_sink.h"
|
||||
#include "../details/null_mutex.h"
|
||||
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
|
7
vendor/spdlog/spdlog/sinks/ostream_sink.h
vendored
7
vendor/spdlog/spdlog/sinks/ostream_sink.h
vendored
@ -5,12 +5,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
|
||||
#include <ostream>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
|
||||
#include "../details/null_mutex.h"
|
||||
#include "./base_sink.h"
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
|
28
vendor/spdlog/spdlog/sinks/sink.h
vendored
28
vendor/spdlog/spdlog/sinks/sink.h
vendored
@ -6,7 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../details/log_msg.h"
|
||||
#include <spdlog/details/log_msg.h>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -15,10 +15,36 @@ namespace sinks
|
||||
class sink
|
||||
{
|
||||
public:
|
||||
sink(): _level( level::trace ) {}
|
||||
|
||||
virtual ~sink() {}
|
||||
virtual void log(const details::log_msg& msg) = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
bool should_log(level::level_enum msg_level) const;
|
||||
void set_level(level::level_enum log_level);
|
||||
level::level_enum level() const;
|
||||
|
||||
private:
|
||||
level_t _level;
|
||||
|
||||
};
|
||||
|
||||
inline bool sink::should_log(level::level_enum msg_level) const
|
||||
{
|
||||
return msg_level >= _level.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
inline void sink::set_level(level::level_enum log_level)
|
||||
{
|
||||
_level.store(log_level);
|
||||
}
|
||||
|
||||
inline level::level_enum sink::level() const
|
||||
{
|
||||
return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
37
vendor/spdlog/spdlog/sinks/stdout_sinks.h
vendored
37
vendor/spdlog/spdlog/sinks/stdout_sinks.h
vendored
@ -5,10 +5,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <spdlog/details/null_mutex.h>
|
||||
#include <spdlog/sinks/base_sink.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "./ostream_sink.h"
|
||||
#include "../details/null_mutex.h"
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -16,16 +18,27 @@ namespace sinks
|
||||
{
|
||||
|
||||
template <class Mutex>
|
||||
class stdout_sink : public ostream_sink<Mutex>
|
||||
class stdout_sink : public base_sink<Mutex>
|
||||
{
|
||||
using MyType = stdout_sink<Mutex>;
|
||||
public:
|
||||
stdout_sink() : ostream_sink<Mutex>(std::cout, true) {}
|
||||
stdout_sink() {}
|
||||
static std::shared_ptr<MyType> instance()
|
||||
{
|
||||
static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
|
||||
return instance;
|
||||
}
|
||||
|
||||
void _sink_it(const details::log_msg& msg) override
|
||||
{
|
||||
fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stdout);
|
||||
flush();
|
||||
}
|
||||
|
||||
void flush() override
|
||||
{
|
||||
fflush(stdout);
|
||||
}
|
||||
};
|
||||
|
||||
typedef stdout_sink<details::null_mutex> stdout_sink_st;
|
||||
@ -33,17 +46,27 @@ typedef stdout_sink<std::mutex> stdout_sink_mt;
|
||||
|
||||
|
||||
template <class Mutex>
|
||||
class stderr_sink : public ostream_sink<Mutex>
|
||||
class stderr_sink : public base_sink<Mutex>
|
||||
{
|
||||
using MyType = stderr_sink<Mutex>;
|
||||
public:
|
||||
stderr_sink() : ostream_sink<Mutex>(std::cerr, true) {}
|
||||
stderr_sink() {}
|
||||
static std::shared_ptr<MyType> instance()
|
||||
{
|
||||
static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
|
||||
return instance;
|
||||
}
|
||||
|
||||
void _sink_it(const details::log_msg& msg) override
|
||||
{
|
||||
fwrite(msg.formatted.data(), sizeof(char), msg.formatted.size(), stderr);
|
||||
flush();
|
||||
}
|
||||
|
||||
void flush() override
|
||||
{
|
||||
fflush(stderr);
|
||||
}
|
||||
};
|
||||
|
||||
typedef stderr_sink<std::mutex> stderr_sink_mt;
|
||||
|
16
vendor/spdlog/spdlog/sinks/syslog_sink.h
vendored
16
vendor/spdlog/spdlog/sinks/syslog_sink.h
vendored
@ -5,16 +5,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#include <spdlog/common.h>
|
||||
|
||||
#ifdef SPDLOG_ENABLE_SYSLOG
|
||||
|
||||
#include <spdlog/sinks/sink.h>
|
||||
#include <spdlog/details/log_msg.h>
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "./sink.h"
|
||||
#include "../common.h"
|
||||
#include "../details/log_msg.h"
|
||||
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
@ -35,12 +36,9 @@ public:
|
||||
_priorities[static_cast<int>(level::trace)] = LOG_DEBUG;
|
||||
_priorities[static_cast<int>(level::debug)] = LOG_DEBUG;
|
||||
_priorities[static_cast<int>(level::info)] = LOG_INFO;
|
||||
_priorities[static_cast<int>(level::notice)] = LOG_NOTICE;
|
||||
_priorities[static_cast<int>(level::warn)] = LOG_WARNING;
|
||||
_priorities[static_cast<int>(level::err)] = LOG_ERR;
|
||||
_priorities[static_cast<int>(level::critical)] = LOG_CRIT;
|
||||
_priorities[static_cast<int>(level::alert)] = LOG_ALERT;
|
||||
_priorities[static_cast<int>(level::emerg)] = LOG_EMERG;
|
||||
_priorities[static_cast<int>(level::off)] = LOG_INFO;
|
||||
|
||||
//set ident to be program name if empty
|
||||
@ -65,7 +63,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
std::array<int, 10> _priorities;
|
||||
std::array<int, 7> _priorities;
|
||||
//must store the ident because the man says openlog might use the pointer as is and not a string copy
|
||||
const std::string _ident;
|
||||
|
||||
|
91
vendor/spdlog/spdlog/spdlog.h
vendored
91
vendor/spdlog/spdlog/spdlog.h
vendored
@ -8,21 +8,25 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tweakme.h"
|
||||
#include "common.h"
|
||||
#include "logger.h"
|
||||
#include <spdlog/tweakme.h>
|
||||
#include <spdlog/common.h>
|
||||
#include <spdlog/logger.h>
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
namespace spdlog
|
||||
{
|
||||
// Return an existing logger or nullptr if a logger with such name doesn't exist.
|
||||
// Examples:
|
||||
|
||||
//
|
||||
// Return an existing logger or nullptr if a logger with such name doesn't exist.
|
||||
// example: spdlog::get("my_logger")->info("hello {}", "world");
|
||||
//
|
||||
// spdlog::get("mylog")->info("Hello");
|
||||
// auto logger = spdlog::get("mylog");
|
||||
// logger.info("This is another message" , x, y, z);
|
||||
// logger.info() << "This is another message" << x << y << z;
|
||||
std::shared_ptr<logger> get(const std::string& name);
|
||||
|
||||
|
||||
//
|
||||
// Set global formatting
|
||||
// example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v");
|
||||
@ -35,6 +39,11 @@ void set_formatter(formatter_ptr f);
|
||||
//
|
||||
void set_level(level::level_enum log_level);
|
||||
|
||||
//
|
||||
// Set global error handler
|
||||
//
|
||||
void set_error_handler(log_err_handler);
|
||||
|
||||
//
|
||||
// Turn on async mode (off by default) and set the queue size for each async_logger.
|
||||
// effective only for loggers created after this call.
|
||||
@ -48,40 +57,56 @@ void set_level(level::level_enum log_level);
|
||||
// worker_warmup_cb (optional):
|
||||
// callback function that will be called in worker thread upon start (can be used to init stuff like thread affinity)
|
||||
//
|
||||
void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero());
|
||||
// worker_teardown_cb (optional):
|
||||
// callback function that will be called in worker thread upon exit
|
||||
//
|
||||
void set_async_mode(size_t queue_size, const async_overflow_policy overflow_policy = async_overflow_policy::block_retry, const std::function<void()>& worker_warmup_cb = nullptr, const std::chrono::milliseconds& flush_interval_ms = std::chrono::milliseconds::zero(), const std::function<void()>& worker_teardown_cb = nullptr);
|
||||
|
||||
// Turn off async mode
|
||||
void set_sync_mode();
|
||||
|
||||
|
||||
//
|
||||
// Create and register multi/single threaded basic file logger.
|
||||
// Basic logger simply writes to given file without any limitatons or rotations.
|
||||
//
|
||||
std::shared_ptr<logger> basic_logger_mt(const std::string& logger_name, const filename_t& filename, bool truncate = false);
|
||||
std::shared_ptr<logger> basic_logger_st(const std::string& logger_name, const filename_t& filename, bool truncate = false);
|
||||
|
||||
//
|
||||
// Create and register multi/single threaded rotating file logger
|
||||
//
|
||||
std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const std::string& filenameB, size_t max_file_size, size_t max_files, bool force_flush = false);
|
||||
std::shared_ptr<logger> rotating_logger_st(const std::string& logger_name, const std::string& filename, size_t max_file_size, size_t max_files, bool force_flush = false);
|
||||
std::shared_ptr<logger> rotating_logger_mt(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files);
|
||||
std::shared_ptr<logger> rotating_logger_st(const std::string& logger_name, const filename_t& filename, size_t max_file_size, size_t max_files);
|
||||
|
||||
//
|
||||
// Create file logger which creates new file on the given time (default in midnight):
|
||||
//
|
||||
std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const std::string& filename, int hour=0, int minute=0, bool force_flush = false);
|
||||
std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const std::string& filename, int hour=0, int minute=0, bool force_flush = false);
|
||||
|
||||
std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0);
|
||||
std::shared_ptr<logger> daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour=0, int minute=0);
|
||||
|
||||
//
|
||||
// Create and register stdout/stderr loggers
|
||||
//
|
||||
std::shared_ptr<logger> stdout_logger_mt(const std::string& logger_name);
|
||||
std::shared_ptr<logger> stdout_logger_st(const std::string& logger_name);
|
||||
std::shared_ptr<logger> stderr_logger_mt(const std::string& logger_name);
|
||||
std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name);
|
||||
std::shared_ptr<logger> stdout_logger_mt(const std::string& logger_name, bool color = false);
|
||||
std::shared_ptr<logger> stdout_logger_st(const std::string& logger_name, bool color = false);
|
||||
std::shared_ptr<logger> stderr_logger_mt(const std::string& logger_name, bool color = false);
|
||||
std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name, bool color = false);
|
||||
|
||||
|
||||
//
|
||||
// Create and register a syslog logger
|
||||
//
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#ifdef SPDLOG_ENABLE_SYSLOG
|
||||
std::shared_ptr<logger> syslog_logger(const std::string& logger_name, const std::string& ident = "", int syslog_option = 0);
|
||||
#endif
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
std::shared_ptr<logger> android_logger(const std::string& logger_name, const std::string& tag = "spdlog");
|
||||
#endif
|
||||
|
||||
// Create and register a logger a single sink
|
||||
std::shared_ptr<logger> create(const std::string& logger_name, const sink_ptr& sink);
|
||||
|
||||
// Create and register a logger with multiple sinks
|
||||
std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list sinks);
|
||||
@ -90,7 +115,8 @@ std::shared_ptr<logger> create(const std::string& logger_name, const It& sinks_b
|
||||
|
||||
|
||||
// Create and register a logger with templated sink type
|
||||
// Example: spdlog::create<daily_file_sink_st>("mylog", "dailylog_filename", "txt");
|
||||
// Example:
|
||||
// spdlog::create<daily_file_sink_st>("mylog", "dailylog_filename", "txt");
|
||||
template <typename Sink, typename... Args>
|
||||
std::shared_ptr<spdlog::logger> create(const std::string& logger_name, Args...);
|
||||
|
||||
@ -98,32 +124,41 @@ std::shared_ptr<spdlog::logger> create(const std::string& logger_name, Args...);
|
||||
// Register the given logger with the given name
|
||||
void register_logger(std::shared_ptr<logger> logger);
|
||||
|
||||
// Apply a user defined function on all registered loggers
|
||||
// Example:
|
||||
// spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) {l->flush();});
|
||||
void apply_all(std::function<void(std::shared_ptr<logger>)> fun);
|
||||
|
||||
// Drop the reference to the given logger
|
||||
void drop(const std::string &name);
|
||||
|
||||
// Drop all references
|
||||
// Drop all references from the registry
|
||||
void drop_all();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Macros to be display source file & line
|
||||
// Trace & Debug can be switched on/off at compile time for zero cost debug statements.
|
||||
// Uncomment SPDLOG_DEBUG_ON/SPDLOG_TRACE_ON in teakme.h to enable.
|
||||
// SPDLOG_TRACE(..) will also print current file and line.
|
||||
//
|
||||
// Example:
|
||||
// spdlog::set_level(spdlog::level::debug);
|
||||
// SPDLOG_DEBUG(my_logger, "Some debug message {} {}", 1, 3.2);
|
||||
// spdlog::set_level(spdlog::level::trace);
|
||||
// SPDLOG_TRACE(my_logger, "some trace message");
|
||||
// SPDLOG_TRACE(my_logger, "another trace message {} {}", 1, 2);
|
||||
// SPDLOG_DEBUG(my_logger, "some debug message {} {}", 3, 4);
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef SPDLOG_TRACE_ON
|
||||
#define SPDLOG_TRACE(logger, ...) logger->trace(__VA_ARGS__) << " (" << __FILE__ << " #" << __LINE__ <<")";
|
||||
#define SPDLOG_STR_H(x) #x
|
||||
#define SPDLOG_STR_HELPER(x) SPDLOG_STR_H(x)
|
||||
#define SPDLOG_TRACE(logger, ...) logger->trace("[" __FILE__ " line #" SPDLOG_STR_HELPER(__LINE__) "] " __VA_ARGS__)
|
||||
#else
|
||||
#define SPDLOG_TRACE(logger, ...)
|
||||
#endif
|
||||
|
||||
#ifdef SPDLOG_DEBUG_ON
|
||||
#define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__) << " (" << __FILE__ << " #" << __LINE__ <<")";
|
||||
#define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__)
|
||||
#else
|
||||
#define SPDLOG_DEBUG(logger, ...)
|
||||
#endif
|
||||
@ -132,4 +167,4 @@ void drop_all();
|
||||
}
|
||||
|
||||
|
||||
#include "details/spdlog_impl.h"
|
||||
#include <spdlog/details/spdlog_impl.h>
|
||||
|
58
vendor/spdlog/spdlog/tweakme.h
vendored
58
vendor/spdlog/spdlog/tweakme.h
vendored
@ -5,21 +5,29 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Edit this file to squeeze every last drop of performance out of spdlog.
|
||||
// Edit this file to squeeze more performance, and to customize supported features
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Under Linux, the much faster CLOCK_REALTIME_COARSE clock can be used.
|
||||
// This clock is less accurate - can be off by dozens of millis - depending on the kernel HZ.
|
||||
// Uncomment to use it instead of the regular (but slower) clock.
|
||||
// Uncomment to use it instead of the regular clock.
|
||||
//
|
||||
// #define SPDLOG_CLOCK_COARSE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment if date/time logging is not needed.
|
||||
// Uncomment if date/time logging is not needed and never appear in the log pattern.
|
||||
// This will prevent spdlog from quering the clock on each log call.
|
||||
//
|
||||
// WARNING: If the log pattern contains any date/time while this flag is on, the result is undefined.
|
||||
// You must set new pattern(spdlog::set_pattern(..") without any date/time in it
|
||||
//
|
||||
// #define SPDLOG_NO_DATETIME
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -27,6 +35,9 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment if thread id logging is not needed (i.e. no %t in the log pattern).
|
||||
// This will prevent spdlog from quering the thread id on each log call.
|
||||
//
|
||||
// WARNING: If the log pattern contains thread id (i.e, %t) while this flag is on, the result is undefined.
|
||||
//
|
||||
// #define SPDLOG_NO_THREAD_ID
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -34,12 +45,13 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment if logger name logging is not needed.
|
||||
// This will prevent spdlog from copying the logger name on each log call.
|
||||
//
|
||||
// #define SPDLOG_NO_NAME
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment to enable the SPDLOG_DEBUG/SPDLOG_TRACE macros.
|
||||
//
|
||||
// #define SPDLOG_DEBUG_ON
|
||||
// #define SPDLOG_TRACE_ON
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -49,5 +61,43 @@
|
||||
// Uncomment to avoid locking in the registry operations (spdlog::get(), spdlog::drop() spdlog::register()).
|
||||
// Use only if your code never modifes concurrently the registry.
|
||||
// Note that upon creating a logger the registry is modified by spdlog..
|
||||
//
|
||||
// #define SPDLOG_NO_REGISTRY_MUTEX
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment to avoid spdlog's usage of atomic log levels
|
||||
// Use only if your code never modifies a logger's log levels concurrently by different threads.
|
||||
//
|
||||
// #define SPDLOG_NO_ATOMIC_LEVELS
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment to enable usage of wchar_t for file names on Windows.
|
||||
//
|
||||
// #define SPDLOG_WCHAR_FILENAMES
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment to override default eol ("\n" or "\r\n" under Linux/Windows)
|
||||
//
|
||||
// #define SPDLOG_EOL ";-)\n"
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment to use your own copy of the fmt library instead of spdlog's copy.
|
||||
// In this case spdlog will try to include <fmt/format.h> so set your -I flag accordingly.
|
||||
//
|
||||
// #define SPDLOG_FMT_EXTERNAL
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment to enable syslog (disabled by default)
|
||||
//
|
||||
// #define SPDLOG_ENABLE_SYSLOG
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user