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);
|
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) {
|
if(plaintextWithHeader == boost::none) {
|
||||||
//Decryption failed (e.g. an authenticated cipher detected modifications to the ciphertext)
|
//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;
|
return boost::none;
|
||||||
}
|
}
|
||||||
if(!_keyHeaderIsCorrect(baseBlock->key(), *plaintextWithHeader)) {
|
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
|
//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 boost::none;
|
||||||
}
|
}
|
||||||
return cpputils::make_unique_ref<EncryptedBlock<Cipher>>(std::move(baseBlock), encKey, std::move(*plaintextWithHeader));
|
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");
|
ASSERT(bf::is_regular_file(filepath), "Block not found on disk");
|
||||||
bool retval = bf::remove(filepath);
|
bool retval = bf::remove(filepath);
|
||||||
if (!retval) {
|
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())) {
|
if (bf::is_empty(filepath.parent_path())) {
|
||||||
bf::remove(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) {
|
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);
|
auto msg = format(expr, message, file, line);
|
||||||
using namespace logging;
|
using namespace logging;
|
||||||
LOG(ERROR) << msg;
|
LOG(ERROR, msg);
|
||||||
throw AssertFailed(msg);
|
throw AssertFailed(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void assert_fail_debug [[noreturn]] (const char *expr, const std::string &message, const char *file, int line) {
|
inline void assert_fail_debug [[noreturn]] (const char *expr, const std::string &message, const char *file, int line) {
|
||||||
using namespace logging;
|
using namespace logging;
|
||||||
LOG(ERROR) << format(expr, message, file, line);
|
LOG(ERROR, format(expr, message, file, line));
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ namespace cpputils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sigsegv_handler(int) {
|
void sigsegv_handler(int) {
|
||||||
LOG(ERROR) << "SIGSEGV\n" << backtrace();
|
LOG(ERROR, "SIGSEGV\n{}", backtrace());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ namespace cpputils {
|
|||||||
uint32_t size;
|
uint32_t size;
|
||||||
std::memcpy(&size, reinterpret_cast<const char*>(data.data()), sizeof(size));
|
std::memcpy(&size, reinterpret_cast<const char*>(data.data()), sizeof(size));
|
||||||
if(sizeof(size) + size >= data.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;
|
return boost::none;
|
||||||
};
|
};
|
||||||
Data result(size);
|
Data result(size);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#ifndef MESSMER_CPPUTILS_LOGGING_LOGGER_H
|
#ifndef MESSMER_CPPUTILS_LOGGING_LOGGER_H
|
||||||
#define MESSMER_CPPUTILS_LOGGING_LOGGER_H
|
#define MESSMER_CPPUTILS_LOGGING_LOGGER_H
|
||||||
|
|
||||||
|
#define SPDLOG_ENABLE_SYSLOG
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include "../macros.h"
|
#include "../macros.h"
|
||||||
|
|
||||||
|
@ -4,14 +4,15 @@
|
|||||||
|
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <spdlog/fmt/ostr.h>
|
||||||
|
|
||||||
namespace cpputils {
|
namespace cpputils {
|
||||||
namespace logging {
|
namespace logging {
|
||||||
|
|
||||||
extern struct ERROR_TYPE {} ERROR;
|
constexpr struct ERROR_TYPE {} ERROR;
|
||||||
extern struct WARN_TYPE {} WARN;
|
constexpr struct WARN_TYPE {} WARN;
|
||||||
extern struct INFO_TYPE {} INFO;
|
constexpr struct INFO_TYPE {} INFO;
|
||||||
extern struct DEBUG_TYPE {} DEBUG;
|
constexpr struct DEBUG_TYPE {} DEBUG;
|
||||||
|
|
||||||
inline void setLogger(std::shared_ptr<spdlog::logger> newLogger) {
|
inline void setLogger(std::shared_ptr<spdlog::logger> newLogger) {
|
||||||
logger().setLogger(newLogger);
|
logger().setLogger(newLogger);
|
||||||
@ -37,20 +38,28 @@ namespace cpputils {
|
|||||||
logger().setLevel(spdlog::level::debug);
|
logger().setLevel(spdlog::level::debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger LOG(ERROR_TYPE) {
|
template<class LogType> inline void LOG(LogType logType, const std::string &msg) {
|
||||||
return logger()->error();
|
LOG(logType, msg.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger LOG(WARN_TYPE) {
|
template <typename... Args>
|
||||||
return logger()->warn();
|
inline void LOG(ERROR_TYPE, const char* fmt, const Args&... args) {
|
||||||
|
logger()->error(fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger LOG(INFO_TYPE) {
|
template <typename... Args>
|
||||||
return logger()->info();
|
inline void LOG(WARN_TYPE, const char* fmt, const Args&... args) {
|
||||||
|
logger()->warn(fmt, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline spdlog::details::line_logger LOG(DEBUG_TYPE) {
|
template <typename... Args>
|
||||||
return logger()->debug();
|
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
|
// Create a new SID for the child process
|
||||||
pid_t sid = setsid();
|
pid_t sid = setsid();
|
||||||
if (sid < 0) {
|
if (sid < 0) {
|
||||||
LOG(ERROR) << "Failed to get SID for daemon process";
|
LOG(ERROR, "Failed to get SID for daemon process");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the current working directory to a directory that's always existin
|
// Change the current working directory to a directory that's always existin
|
||||||
if ((chdir("/")) < 0) {
|
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);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
#ifndef MESSMER_CPPUTILS_SYSTEM_CLOCKGETTIME_H
|
#ifndef MESSMER_CPPUTILS_SYSTEM_CLOCKGETTIME_H
|
||||||
#define 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
|
// 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.
|
// 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>
|
#include <sys/time.h>
|
||||||
#define CLOCK_REALTIME 0
|
#define CLOCK_REALTIME 0
|
||||||
inline int clock_gettime(int /*clk_id*/, struct timespec *result) {
|
inline int clock_gettime(int /*clk_id*/, struct timespec *result) {
|
||||||
|
@ -21,7 +21,7 @@ void TempDir::remove() {
|
|||||||
bf::remove_all(_path);
|
bf::remove_all(_path);
|
||||||
}
|
}
|
||||||
} catch (const boost::filesystem::filesystem_error &e) {
|
} 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);
|
bf::remove(_path);
|
||||||
}
|
}
|
||||||
} catch (const boost::filesystem::filesystem_error &e) {
|
} 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) {
|
} catch (const boost::thread_interrupted &e) {
|
||||||
//Do nothing, exit thread.
|
//Do nothing, exit thread.
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
LOG(ERROR) << "LoopThread crashed: " << e.what();
|
LOG(ERROR, "LoopThread crashed: {}", e.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
LOG(ERROR) << "LoopThread crashed";
|
LOG(ERROR, "LoopThread crashed");
|
||||||
}
|
}
|
||||||
//TODO We should remove the thread from _runningThreads here, not in stop().
|
//TODO We should remove the thread from _runningThreads here, not in stop().
|
||||||
}
|
}
|
||||||
|
@ -252,9 +252,9 @@ namespace cryfs {
|
|||||||
#endif
|
#endif
|
||||||
fuse.run(options.mountDir(), options.fuseOptions());
|
fuse.run(options.mountDir(), options.fuseOptions());
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
LOG(ERROR) << "Crashed: " << e.what();
|
LOG(ERROR, "Crashed: {}", e.what());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
LOG(ERROR) << "Crashed";
|
LOG(ERROR, "Crashed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ namespace cryfs {
|
|||||||
read_json(input, pt);
|
read_json(input, pt);
|
||||||
return pt;
|
return pt;
|
||||||
} catch (const json_parser_error &e) {
|
} catch (const json_parser_error &e) {
|
||||||
LOG(WARN) << "Error parsing version information json object";
|
LOG(WARN, "Error parsing version information json object");
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,13 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
#include <cryfs/config/CryConfigConsole.h>
|
||||||
#include <cryfs-cli/Environment.h>
|
#include <cryfs-cli/Environment.h>
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
namespace bf = boost::filesystem;
|
namespace bf = boost::filesystem;
|
||||||
using namespace cryfs::program_options;
|
using namespace cryfs::program_options;
|
||||||
|
using cryfs::CryConfigConsole;
|
||||||
using std::pair;
|
using std::pair;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::cerr;
|
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) {
|
void Parser::_addAllowedOptions(po::options_description *desc) {
|
||||||
po::options_description options("Allowed options");
|
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()
|
options.add_options()
|
||||||
("help,h", "show help message")
|
("help,h", "show help message")
|
||||||
("config,c", po::value<string>(), "Configuration file")
|
("config,c", po::value<string>(), "Configuration file")
|
||||||
("foreground,f", "Run CryFS in foreground.")
|
("foreground,f", "Run CryFS in foreground.")
|
||||||
("cipher", po::value<string>(), "Cipher to use for encryption. See possible values by calling cryfs with --show-ciphers.")
|
("cipher", po::value<string>(), cipher_description.c_str())
|
||||||
("blocksize", po::value<uint32_t>(), "The block size used when storing ciphertext blocks (in bytes).")
|
("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.")
|
("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.")
|
("show-ciphers", "Show list of supported ciphers.")
|
||||||
("unmount-idle", po::value<double>(), "Automatically unmount after specified number of idle minutes.")
|
("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) {
|
optional<CryConfigFile> CryConfigFile::load(const bf::path &path, const string &password) {
|
||||||
auto encryptedConfigData = Data::LoadFromFile(path);
|
auto encryptedConfigData = Data::LoadFromFile(path);
|
||||||
if (encryptedConfigData == none) {
|
if (encryptedConfigData == none) {
|
||||||
LOG(ERROR) << "Config file not found";
|
LOG(ERROR, "Config file not found");
|
||||||
return none;
|
return none;
|
||||||
}
|
}
|
||||||
auto encryptor = CryConfigEncryptorFactory::loadKey(*encryptedConfigData, password);
|
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);
|
CryConfig config = CryConfig::load(decrypted->data);
|
||||||
if (config.Cipher() != decrypted->cipherName) {
|
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;
|
return none;
|
||||||
}
|
}
|
||||||
auto configFile = CryConfigFile(path, std::move(config), std::move(*encryptor));
|
auto configFile = CryConfigFile(path, std::move(config), std::move(*encryptor));
|
||||||
|
@ -33,12 +33,12 @@ namespace cryfs {
|
|||||||
template<class Cipher>
|
template<class Cipher>
|
||||||
boost::optional<cpputils::Data> ConcreteInnerEncryptor<Cipher>::decrypt(const InnerConfig &innerConfig) const {
|
boost::optional<cpputils::Data> ConcreteInnerEncryptor<Cipher>::decrypt(const InnerConfig &innerConfig) const {
|
||||||
if (innerConfig.cipherName != Cipher::NAME) {
|
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;
|
return boost::none;
|
||||||
}
|
}
|
||||||
auto decrypted = Cipher::decrypt(static_cast<const uint8_t*>(innerConfig.encryptedConfig.data()), innerConfig.encryptedConfig.size(), _key);
|
auto decrypted = Cipher::decrypt(static_cast<const uint8_t*>(innerConfig.encryptedConfig.data()), innerConfig.encryptedConfig.size(), _key);
|
||||||
if (decrypted == boost::none) {
|
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;
|
return boost::none;
|
||||||
}
|
}
|
||||||
auto configData = cpputils::RandomPadding::remove(*decrypted);
|
auto configData = cpputils::RandomPadding::remove(*decrypted);
|
||||||
|
@ -23,7 +23,7 @@ namespace cryfs {
|
|||||||
serializer.writeTailData(encryptedConfig);
|
serializer.writeTailData(encryptedConfig);
|
||||||
return serializer.finished();
|
return serializer.finished();
|
||||||
} catch (const exception &e) {
|
} 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.
|
throw; // This is a programming logic error, pass through exception.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,7 +37,7 @@ namespace cryfs {
|
|||||||
deserializer.finished();
|
deserializer.finished();
|
||||||
return InnerConfig {cipherName, std::move(result)};
|
return InnerConfig {cipherName, std::move(result)};
|
||||||
} catch (const exception &e) {
|
} 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.
|
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);
|
serializer.writeTailData(encryptedInnerConfig);
|
||||||
return serializer.finished();
|
return serializer.finished();
|
||||||
} catch (const exception &e) {
|
} 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.
|
throw; // This is a programming logic error. Pass through exception.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ namespace cryfs {
|
|||||||
_deserializeNewFormat(&deserializer);
|
_deserializeNewFormat(&deserializer);
|
||||||
#endif
|
#endif
|
||||||
} catch (const exception &e) {
|
} 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.
|
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<DirBlobRef>> parentBlob = none;
|
||||||
optional<unique_ref<FsBlobRef>> currentBlobOpt = _fsBlobStore->load(_rootKey);
|
optional<unique_ref<FsBlobRef>> currentBlobOpt = _fsBlobStore->load(_rootKey);
|
||||||
if (currentBlobOpt == none) {
|
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);
|
throw FuseErrnoException(EIO);
|
||||||
}
|
}
|
||||||
unique_ref<FsBlobRef> currentBlob = std::move(*currentBlobOpt);
|
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) {
|
unique_ref<FsBlobRef> CryDevice::LoadBlob(const blockstore::Key &key) {
|
||||||
auto blob = _fsBlobStore->load(key);
|
auto blob = _fsBlobStore->load(key);
|
||||||
if (blob == none) {
|
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);
|
throw FuseErrnoException(EIO);
|
||||||
}
|
}
|
||||||
return std::move(*blob);
|
return std::move(*blob);
|
||||||
@ -276,7 +276,7 @@ unique_ref<FsBlobRef> CryDevice::LoadBlob(const blockstore::Key &key) {
|
|||||||
void CryDevice::RemoveBlob(const blockstore::Key &key) {
|
void CryDevice::RemoveBlob(const blockstore::Key &key) {
|
||||||
auto blob = _fsBlobStore->load(key);
|
auto blob = _fsBlobStore->load(key);
|
||||||
if (blob == none) {
|
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);
|
throw FuseErrnoException(EIO);
|
||||||
}
|
}
|
||||||
_fsBlobStore->remove(std::move(*blob));
|
_fsBlobStore->remove(std::move(*blob));
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <blockstore/utils/Key.h>
|
#include <blockstore/utils/Key.h>
|
||||||
#include <fspp/fs_interface/Dir.h>
|
#include <fspp/fs_interface/Dir.h>
|
||||||
#include <cpp-utils/system/time.h>
|
#include <cpp-utils/system/time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
// TODO Implement (and test) atime, noatime, strictatime, relatime mount options
|
// 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) {
|
void Fuse::_logException(const std::exception &e) {
|
||||||
LOG(ERROR) << "Exception thrown: " << e.what();
|
LOG(ERROR, "Exception thrown: ", e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuse::_logUnknownException() {
|
void Fuse::_logUnknownException() {
|
||||||
LOG(ERROR) << "Unknown exception thrown";
|
LOG(ERROR, "Unknown exception thrown");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuse::run(const bf::path &mountdir, const vector<string> &fuseOptions) {
|
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.
|
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
|
#endif
|
||||||
if (ret != 0) {
|
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) {
|
int Fuse::getattr(const bf::path &path, struct stat *stbuf) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "getattr(" << path << ", _, _)";
|
LOG(DEBUG, "getattr({}, _, _)", path);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
_fs->lstat(path, stbuf);
|
_fs->lstat(path, stbuf);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::getattr: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::getattr: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::fgetattr(const bf::path &path, struct stat *stbuf, fuse_file_info *fileinfo) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "fgetattr(" << path << ", _, _)\n";
|
LOG(DEBUG, "fgetattr({}, _, _)\n", path);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// On FreeBSD, trying to do anything with the mountpoint ends up
|
// 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);
|
_fs->fstat(fileinfo->fh, stbuf);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::fgetattr: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::fgetattr: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::readlink(const bf::path &path, char *buf, size_t size) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "readlink(" << path << ", _, " << size << ")";
|
LOG(DEBUG, "readlink({}, _, {})", path, size);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
_fs->readSymlink(path, buf, size);
|
_fs->readSymlink(path, buf, size);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::readlink: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::readlink: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (fspp::fuse::FuseErrnoException &e) {
|
} catch (fspp::fuse::FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
return -e.getErrno();
|
||||||
@ -377,20 +377,20 @@ int Fuse::mknod(const bf::path &path, mode_t mode, dev_t rdev) {
|
|||||||
UNUSED(rdev);
|
UNUSED(rdev);
|
||||||
UNUSED(mode);
|
UNUSED(mode);
|
||||||
UNUSED(path);
|
UNUSED(path);
|
||||||
LOG(WARN) << "Called non-implemented mknod(" << path << ", " << mode << ", _)";
|
LOG(WARN, "Called non-implemented mknod({}, {}, _)", path, mode);
|
||||||
return ENOSYS;
|
return ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Fuse::mkdir(const bf::path &path, mode_t mode) {
|
int Fuse::mkdir(const bf::path &path, mode_t mode) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "mkdir(" << path << ", " << mode << ")";
|
LOG(DEBUG, "mkdir({}, {})", path, mode);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
auto context = fuse_get_context();
|
auto context = fuse_get_context();
|
||||||
_fs->mkdir(path, mode, context->uid, context->gid);
|
_fs->mkdir(path, mode, context->uid, context->gid);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::mkdir: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::mkdir: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
return -e.getErrno();
|
||||||
@ -405,13 +405,13 @@ int Fuse::mkdir(const bf::path &path, mode_t mode) {
|
|||||||
|
|
||||||
int Fuse::unlink(const bf::path &path) {
|
int Fuse::unlink(const bf::path &path) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "unlink(" << path << ")";
|
LOG(DEBUG, "unlink({})", path);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
_fs->unlink(path);
|
_fs->unlink(path);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::unlink: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::unlink: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
return -e.getErrno();
|
||||||
@ -426,13 +426,13 @@ int Fuse::unlink(const bf::path &path) {
|
|||||||
|
|
||||||
int Fuse::rmdir(const bf::path &path) {
|
int Fuse::rmdir(const bf::path &path) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "rmdir(" << path << ")";
|
LOG(DEBUG, "rmdir({})", path);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
_fs->rmdir(path);
|
_fs->rmdir(path);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::rmdir: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::rmdir: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::symlink(const bf::path &from, const bf::path &to) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "symlink(" << from << ", " << to << ")";
|
LOG(DEBUG, "symlink({}, {})", from, to);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
auto context = fuse_get_context();
|
auto context = fuse_get_context();
|
||||||
_fs->createSymlink(from, to, context->uid, context->gid);
|
_fs->createSymlink(from, to, context->uid, context->gid);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::symlink: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::symlink: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::rename(const bf::path &from, const bf::path &to) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "rename(" << from << ", " << to << ")";
|
LOG(DEBUG, "rename({}, {})", from, to);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
ASSERT(from.is_absolute(), "from has to be an absolute path");
|
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);
|
_fs->rename(from, to);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::rename: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::rename: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch(fspp::fuse::FuseErrnoException &e) {
|
} catch(fspp::fuse::FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
return -e.getErrno();
|
||||||
@ -492,7 +492,7 @@ int Fuse::rename(const bf::path &from, const bf::path &to) {
|
|||||||
|
|
||||||
//TODO
|
//TODO
|
||||||
int Fuse::link(const bf::path &from, const bf::path &to) {
|
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_from = _impl->RootDir() / from;
|
||||||
//auto real_to = _impl->RootDir() / to;
|
//auto real_to = _impl->RootDir() / to;
|
||||||
//int retstat = ::link(real_from.c_str(), real_to.c_str());
|
//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) {
|
int Fuse::chmod(const bf::path &path, mode_t mode) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "chmod(" << path << ", " << mode << ")";
|
LOG(DEBUG, "chmod({}, {})", path, mode);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
_fs->chmod(path, mode);
|
_fs->chmod(path, mode);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::chmod: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::chmod: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (fspp::fuse::FuseErrnoException &e) {
|
} catch (fspp::fuse::FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::chown(const bf::path &path, uid_t uid, gid_t gid) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "chown(" << path << ", " << uid << ", " << gid << ")";
|
LOG(DEBUG, "chown({}, {}, {})", path, uid, gid);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
_fs->chown(path, uid, gid);
|
_fs->chown(path, uid, gid);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::chown: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::chown: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (fspp::fuse::FuseErrnoException &e) {
|
} catch (fspp::fuse::FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::truncate(const bf::path &path, off_t size) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "truncate(" << path << ", " << size << ")";
|
LOG(DEBUG, "truncate({}, {})", path, size);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
_fs->truncate(path, size);
|
_fs->truncate(path, size);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::truncate: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::truncate: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::ftruncate(const bf::path &path, off_t size, fuse_file_info *fileinfo) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "ftruncate(" << path << ", " << size << ")";
|
LOG(DEBUG, "ftruncate({}, {})", path, size);
|
||||||
#endif
|
#endif
|
||||||
UNUSED(path);
|
UNUSED(path);
|
||||||
try {
|
try {
|
||||||
_fs->ftruncate(fileinfo->fh, size);
|
_fs->ftruncate(fileinfo->fh, size);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::ftruncate: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::ftruncate: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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]) {
|
int Fuse::utimens(const bf::path &path, const timespec times[2]) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "utimens(" << path << ", _)";
|
LOG(DEBUG, "utimens({}, _)", path);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
_fs->utimens(path, times[0], times[1]);
|
_fs->utimens(path, times[0], times[1]);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::utimens: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::utimens: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::open(const bf::path &path, fuse_file_info *fileinfo) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "open(" << path << ", _)";
|
LOG(DEBUG, "open({}, _)", path);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
fileinfo->fh = _fs->openFile(path, fileinfo->flags);
|
fileinfo->fh = _fs->openFile(path, fileinfo->flags);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::open: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::open: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::release(const bf::path &path, fuse_file_info *fileinfo) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "release(" << path << ", _)";
|
LOG(DEBUG, "release({}, _)", path);
|
||||||
#endif
|
#endif
|
||||||
UNUSED(path);
|
UNUSED(path);
|
||||||
try {
|
try {
|
||||||
_fs->closeFile(fileinfo->fh);
|
_fs->closeFile(fileinfo->fh);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::release: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::release: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::read(const bf::path &path, char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "read(" << path << ", _, " << size << ", " << offset << ", _ )";
|
LOG(DEBUG, "read({}, _, {}, {}, _)", path, size, offset);
|
||||||
#endif
|
#endif
|
||||||
UNUSED(path);
|
UNUSED(path);
|
||||||
try {
|
try {
|
||||||
return _fs->read(fileinfo->fh, buf, size, offset);
|
return _fs->read(fileinfo->fh, buf, size, offset);
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::read: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::read: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::write(const bf::path &path, const char *buf, size_t size, off_t offset, fuse_file_info *fileinfo) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "write(" << path << ", _, " << size << ", " << offset << ", _)";
|
LOG(DEBUG, "write({}, _, {}, {}, _)", path, size, offsset);
|
||||||
#endif
|
#endif
|
||||||
UNUSED(path);
|
UNUSED(path);
|
||||||
try {
|
try {
|
||||||
_fs->write(fileinfo->fh, buf, size, offset);
|
_fs->write(fileinfo->fh, buf, size, offset);
|
||||||
return size;
|
return size;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::write: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::write: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
return -e.getErrno();
|
||||||
@ -695,13 +695,13 @@ int Fuse::write(const bf::path &path, const char *buf, size_t size, off_t offset
|
|||||||
//TODO
|
//TODO
|
||||||
int Fuse::statfs(const bf::path &path, struct statvfs *fsstat) {
|
int Fuse::statfs(const bf::path &path, struct statvfs *fsstat) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "statfs(" << path << ", _)";
|
LOG(DEBUG, "statfs({}, _)", path);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
_fs->statfs(path, fsstat);
|
_fs->statfs(path, fsstat);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::statfs: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::statfs: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::flush(const bf::path &path, fuse_file_info *fileinfo) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(WARN) << "flush(" << path << ", _)";
|
LOG(WARN, "flush({}, _)", path);
|
||||||
#endif
|
#endif
|
||||||
UNUSED(path);
|
UNUSED(path);
|
||||||
try {
|
try {
|
||||||
_fs->flush(fileinfo->fh);
|
_fs->flush(fileinfo->fh);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::flush: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::flush: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::fsync(const bf::path &path, int datasync, fuse_file_info *fileinfo) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "fsync(" << path << ", " << datasync << ", _)";
|
LOG(DEBUG, "fsync({}, {}, _)", path, datasync);
|
||||||
#endif
|
#endif
|
||||||
UNUSED(path);
|
UNUSED(path);
|
||||||
try {
|
try {
|
||||||
@ -749,7 +749,7 @@ int Fuse::fsync(const bf::path &path, int datasync, fuse_file_info *fileinfo) {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::fsync: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::fsync: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::opendir(const bf::path &path, fuse_file_info *fileinfo) {
|
||||||
UNUSED(path);
|
UNUSED(path);
|
||||||
UNUSED(fileinfo);
|
UNUSED(fileinfo);
|
||||||
//LOG(DEBUG) << "opendir(" << path << ", _)";
|
//LOG(DEBUG, "opendir({}, _)", path);
|
||||||
//We don't need opendir, because readdir works directly on the path
|
//We don't need opendir, because readdir works directly on the path
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Fuse::readdir(const bf::path &path, void *buf, fuse_fill_dir_t filler, off_t offset, fuse_file_info *fileinfo) {
|
int Fuse::readdir(const bf::path &path, void *buf, fuse_fill_dir_t filler, off_t offset, fuse_file_info *fileinfo) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "readdir(" << path << ", _, _, " << offset << ", _)";
|
LOG(DEBUG, "readdir({}, _, _, {}, _)", path, offest);
|
||||||
#endif
|
#endif
|
||||||
UNUSED(fileinfo);
|
UNUSED(fileinfo);
|
||||||
UNUSED(offset);
|
UNUSED(offset);
|
||||||
@ -799,7 +799,7 @@ int Fuse::readdir(const bf::path &path, void *buf, fuse_fill_dir_t filler, off_t
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::readdir: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::readdir: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::releasedir(const bf::path &path, fuse_file_info *fileinfo) {
|
||||||
UNUSED(path);
|
UNUSED(path);
|
||||||
UNUSED(fileinfo);
|
UNUSED(fileinfo);
|
||||||
//LOG(DEBUG) << "releasedir(" << path << ", _)";
|
//LOG(DEBUG, "releasedir({}, _)", path);
|
||||||
//We don't need releasedir, because readdir works directly on the path
|
//We don't need releasedir, because readdir works directly on the path
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -825,13 +825,13 @@ int Fuse::fsyncdir(const bf::path &path, int datasync, fuse_file_info *fileinfo)
|
|||||||
UNUSED(fileinfo);
|
UNUSED(fileinfo);
|
||||||
UNUSED(datasync);
|
UNUSED(datasync);
|
||||||
UNUSED(path);
|
UNUSED(path);
|
||||||
//LOG(WARN) << "Called non-implemented fsyncdir(" << path << ", " << datasync << ", _)";
|
//LOG(WARN, "Called non-implemented fsyncdir({}, {}, _)", path, datasync);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fuse::init(fuse_conn_info *conn) {
|
void Fuse::init(fuse_conn_info *conn) {
|
||||||
UNUSED(conn);
|
UNUSED(conn);
|
||||||
LOG(INFO) << "Filesystem started.";
|
LOG(INFO, "Filesystem started.");
|
||||||
|
|
||||||
_running = true;
|
_running = true;
|
||||||
|
|
||||||
@ -841,19 +841,19 @@ void Fuse::init(fuse_conn_info *conn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Fuse::destroy() {
|
void Fuse::destroy() {
|
||||||
LOG(INFO) << "Filesystem stopped.";
|
LOG(INFO, "Filesystem stopped.");
|
||||||
_running = false;
|
_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Fuse::access(const bf::path &path, int mask) {
|
int Fuse::access(const bf::path &path, int mask) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "access(" << path << ", " << mask << ")";
|
LOG(DEBUG, "access({}, {})", path, mask);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
_fs->access(path, mask);
|
_fs->access(path, mask);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::access: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::access: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) {
|
int Fuse::create(const bf::path &path, mode_t mode, fuse_file_info *fileinfo) {
|
||||||
#ifdef FSPP_LOG
|
#ifdef FSPP_LOG
|
||||||
LOG(DEBUG) << "create(" << path << ", " << mode << ", _)";
|
LOG(DEBUG, "create({}, {}, _)", path, mode);
|
||||||
#endif
|
#endif
|
||||||
try {
|
try {
|
||||||
auto context = fuse_get_context();
|
auto context = fuse_get_context();
|
||||||
fileinfo->fh = _fs->createAndOpenFile(path, mode, context->uid, context->gid);
|
fileinfo->fh = _fs->createAndOpenFile(path, mode, context->uid, context->gid);
|
||||||
return 0;
|
return 0;
|
||||||
} catch(const cpputils::AssertFailed &e) {
|
} catch(const cpputils::AssertFailed &e) {
|
||||||
LOG(ERROR) << "AssertFailed in Fuse::create: " << e.what();
|
LOG(ERROR, "AssertFailed in Fuse::create: {}", e.what());
|
||||||
return -EIO;
|
return -EIO;
|
||||||
} catch (FuseErrnoException &e) {
|
} catch (FuseErrnoException &e) {
|
||||||
return -e.getErrno();
|
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) << "CreateSymlink (without loading): " << static_cast<double>(_createSymlinkNanosec_withoutLoading)/1000000000 << "\n"
|
||||||
<< std::setw(40) << "ReadSymlink: " << static_cast<double>(_readSymlinkNanosec)/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";
|
<< std::setw(40) << "ReadSymlink (without loading): " << static_cast<double>(_readSymlinkNanosec_withoutLoading)/1000000000 << "\n";
|
||||||
LOG(INFO) << profilerInformation.str();
|
LOG(INFO, profilerInformation.str());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,42 +7,42 @@ using testing::MatchesRegex;
|
|||||||
class LoggingLevelTest: public LoggingTest {
|
class LoggingLevelTest: public LoggingTest {
|
||||||
public:
|
public:
|
||||||
void EXPECT_DEBUG_LOG_ENABLED() {
|
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.*"));
|
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[debug\\].*My log message.*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_DEBUG_LOG_DISABLED() {
|
void EXPECT_DEBUG_LOG_DISABLED() {
|
||||||
LOG(DEBUG) << "My log message";
|
LOG(DEBUG, "My log message");
|
||||||
EXPECT_EQ("", mockLogger.capturedLog());
|
EXPECT_EQ("", mockLogger.capturedLog());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_INFO_LOG_ENABLED() {
|
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.*"));
|
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_INFO_LOG_DISABLED() {
|
void EXPECT_INFO_LOG_DISABLED() {
|
||||||
LOG(INFO) << "My log message";
|
LOG(INFO, "My log message");
|
||||||
EXPECT_EQ("", mockLogger.capturedLog());
|
EXPECT_EQ("", mockLogger.capturedLog());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_WARNING_LOG_ENABLED() {
|
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.*"));
|
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[warning\\].*My log message.*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_WARNING_LOG_DISABLED() {
|
void EXPECT_WARNING_LOG_DISABLED() {
|
||||||
LOG(WARN) << "My log message";
|
LOG(WARN, "My log message");
|
||||||
EXPECT_EQ("", mockLogger.capturedLog());
|
EXPECT_EQ("", mockLogger.capturedLog());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_ERROR_LOG_ENABLED() {
|
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.*"));
|
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[error\\].*My log message.*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EXPECT_ERROR_LOG_DISABLED() {
|
void EXPECT_ERROR_LOG_DISABLED() {
|
||||||
LOG(ERROR) << "My log message";
|
LOG(ERROR, "My log message");
|
||||||
EXPECT_EQ("", mockLogger.capturedLog());
|
EXPECT_EQ("", mockLogger.capturedLog());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Contains test cases for the following logging interface:
|
* Contains test cases for the following logging interface:
|
||||||
* LOG(INFO) << "My log message"
|
* LOG(INFO, "My log message)"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using namespace cpputils::logging;
|
using namespace cpputils::logging;
|
||||||
@ -11,7 +11,7 @@ using testing::MatchesRegex;
|
|||||||
|
|
||||||
TEST_F(LoggingTest, DefaultLoggerIsStderr) {
|
TEST_F(LoggingTest, DefaultLoggerIsStderr) {
|
||||||
string output = captureStderr([]{
|
string output = captureStderr([]{
|
||||||
LOG(INFO) << "My log message";
|
LOG(INFO, "My log message");
|
||||||
});
|
});
|
||||||
EXPECT_THAT(output, MatchesRegex(".*\\[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) {
|
TEST_F(LoggingTest, SetLogger_NewLoggerIsUsed) {
|
||||||
setLogger(spdlog::stderr_logger_mt("MyTestLog2"));
|
setLogger(spdlog::stderr_logger_mt("MyTestLog2"));
|
||||||
string output = captureStderr([]{
|
string output = captureStderr([]{
|
||||||
LOG(INFO) << "My log message";
|
LOG(INFO, "My log message");
|
||||||
});
|
});
|
||||||
EXPECT_THAT(output, MatchesRegex(".*\\[MyTestLog2\\].*\\[info\\].*My log message.*"));
|
EXPECT_THAT(output, MatchesRegex(".*\\[MyTestLog2\\].*\\[info\\].*My log message.*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(LoggingTest, SetNonStderrLogger_LogsToNewLogger) {
|
TEST_F(LoggingTest, SetNonStderrLogger_LogsToNewLogger) {
|
||||||
setLogger(mockLogger.get());
|
setLogger(mockLogger.get());
|
||||||
logger()->info() << "My log message";
|
logger()->info("My log message");
|
||||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(LoggingTest, SetNonStderrLogger_DoesNotLogToStderr) {
|
TEST_F(LoggingTest, SetNonStderrLogger_DoesNotLogToStderr) {
|
||||||
setLogger(mockLogger.get());
|
setLogger(mockLogger.get());
|
||||||
string output = captureStderr([] {
|
string output = captureStderr([] {
|
||||||
logger()->info() << "My log message";
|
logger()->info("My log message");
|
||||||
});
|
});
|
||||||
EXPECT_EQ("", output);
|
EXPECT_EQ("", output);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(LoggingTest, InfoLog) {
|
TEST_F(LoggingTest, InfoLog) {
|
||||||
setLogger(mockLogger.get());
|
setLogger(mockLogger.get());
|
||||||
LOG(INFO) << "My log message";
|
LOG(INFO, "My log message");
|
||||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[info\\].*My log message.*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(LoggingTest, WarningLog) {
|
TEST_F(LoggingTest, WarningLog) {
|
||||||
setLogger(mockLogger.get());
|
setLogger(mockLogger.get());
|
||||||
LOG(WARN) << "My log message";
|
LOG(WARN, "My log message");
|
||||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[warning\\].*My log message.*"));
|
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[warning\\].*My log message.*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(LoggingTest, DebugLog) {
|
TEST_F(LoggingTest, DebugLog) {
|
||||||
setLevel(DEBUG);
|
setLevel(DEBUG);
|
||||||
setLogger(mockLogger.get());
|
setLogger(mockLogger.get());
|
||||||
LOG(DEBUG) << "My log message";
|
LOG(DEBUG, "My log message");
|
||||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[debug\\].*My log message.*"));
|
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[debug\\].*My log message.*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(LoggingTest, ErrorLog) {
|
TEST_F(LoggingTest, ErrorLog) {
|
||||||
setLogger(mockLogger.get());
|
setLogger(mockLogger.get());
|
||||||
LOG(ERROR) << "My log message";
|
LOG(ERROR, "My log message");
|
||||||
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[error\\].*My log message.*"));
|
EXPECT_THAT(mockLogger.capturedLog(), MatchesRegex(".*\\[MockLogger\\].*\\[error\\].*My log message.*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void logAndExit(const string &message) {
|
void logAndExit(const string &message) {
|
||||||
LOG(INFO) << message;
|
LOG(INFO, message);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,3 +78,41 @@ TEST_F(LoggingTest, LoggingAlsoWorksAfterFork) {
|
|||||||
"My log message"
|
"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 <gtest/gtest.h>
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
#include "cpp-utils/logging/logging.h"
|
#include "cpp-utils/logging/logging.h"
|
||||||
|
#include <spdlog/sinks/ostream_sink.h>
|
||||||
|
|
||||||
class MockLogger final {
|
class MockLogger final {
|
||||||
public:
|
public:
|
||||||
|
3
vendor/README
vendored
3
vendor/README
vendored
@ -1,5 +1,4 @@
|
|||||||
This directory contains external projects, taken from the following locations:
|
This directory contains external projects, taken from the following locations:
|
||||||
scrypt: http://www.tarsnap.com/scrypt.html
|
scrypt: http://www.tarsnap.com/scrypt.html
|
||||||
googletest: https://github.com/google/googletest/tree/release-1.8.0
|
googletest: https://github.com/google/googletest/tree/release-1.8.0
|
||||||
spdlog: https://github.com/gabime/spdlog/commit/0c7beb2e36008598cf80d0e8eb8635ac403febb9
|
spdlog: https://github.com/gabime/spdlog/tree/v0.11.0/include/spdlog
|
||||||
- with own fix: https://github.com/cryfs/spdlog/commit/7b8d507615b8075fc6c8793a0965a32a708288c4
|
|
||||||
|
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
|
// 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)
|
// 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
|
// 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 <chrono>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "common.h"
|
#include <string>
|
||||||
#include "logger.h"
|
#include <memory>
|
||||||
#include "spdlog.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -40,26 +41,30 @@ public:
|
|||||||
size_t queue_size,
|
size_t queue_size,
|
||||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
||||||
const std::function<void()>& worker_warmup_cb = nullptr,
|
const std::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,
|
async_logger(const std::string& logger_name,
|
||||||
sinks_init_list sinks,
|
sinks_init_list sinks,
|
||||||
size_t queue_size,
|
size_t queue_size,
|
||||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
||||||
const std::function<void()>& worker_warmup_cb = nullptr,
|
const std::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,
|
async_logger(const std::string& logger_name,
|
||||||
sink_ptr single_sink,
|
sink_ptr single_sink,
|
||||||
size_t queue_size,
|
size_t queue_size,
|
||||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
||||||
const std::function<void()>& worker_warmup_cb = nullptr,
|
const std::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;
|
void flush() override;
|
||||||
protected:
|
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_formatter(spdlog::formatter_ptr msg_formatter) override;
|
||||||
void _set_pattern(const std::string& pattern) 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>
|
||||||
|
78
vendor/spdlog/spdlog/common.h
vendored
78
vendor/spdlog/spdlog/common.h
vendored
@ -9,14 +9,36 @@
|
|||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <atomic>
|
||||||
|
#include <exception>
|
||||||
|
#include<functional>
|
||||||
|
|
||||||
//visual studio does not support noexcept yet
|
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
|
||||||
#ifndef _MSC_VER
|
#include <codecvt>
|
||||||
#define SPDLOG_NOEXCEPT noexcept
|
#include <locale>
|
||||||
#else
|
|
||||||
#define SPDLOG_NOEXCEPT throw()
|
|
||||||
#endif
|
#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
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -28,12 +50,17 @@ namespace sinks
|
|||||||
class sink;
|
class sink;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common types across the lib
|
|
||||||
using log_clock = std::chrono::system_clock;
|
using log_clock = std::chrono::system_clock;
|
||||||
using sink_ptr = std::shared_ptr < sinks::sink >;
|
using sink_ptr = std::shared_ptr < sinks::sink >;
|
||||||
using sinks_init_list = std::initializer_list < sink_ptr >;
|
using sinks_init_list = std::initializer_list < sink_ptr >;
|
||||||
using formatter_ptr = std::shared_ptr<spdlog::formatter>;
|
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
|
//Log level enum
|
||||||
namespace level
|
namespace level
|
||||||
@ -43,18 +70,15 @@ typedef enum
|
|||||||
trace = 0,
|
trace = 0,
|
||||||
debug = 1,
|
debug = 1,
|
||||||
info = 2,
|
info = 2,
|
||||||
notice = 3,
|
warn = 3,
|
||||||
warn = 4,
|
err = 4,
|
||||||
err = 5,
|
critical = 5,
|
||||||
critical = 6,
|
off = 6
|
||||||
alert = 7,
|
|
||||||
emerg = 8,
|
|
||||||
off = 9
|
|
||||||
} level_enum;
|
} 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)
|
inline const char* to_str(spdlog::level::level_enum l)
|
||||||
{
|
{
|
||||||
@ -81,10 +105,22 @@ enum class async_overflow_policy
|
|||||||
//
|
//
|
||||||
// Log exception
|
// Log exception
|
||||||
//
|
//
|
||||||
|
namespace details
|
||||||
|
{
|
||||||
|
namespace os
|
||||||
|
{
|
||||||
|
std::string errno_str(int err_num);
|
||||||
|
}
|
||||||
|
}
|
||||||
class spdlog_ex: public std::exception
|
class spdlog_ex: public std::exception
|
||||||
{
|
{
|
||||||
public:
|
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
|
const char* what() const SPDLOG_NOEXCEPT override
|
||||||
{
|
{
|
||||||
return _msg.c_str();
|
return _msg.c_str();
|
||||||
@ -94,4 +130,14 @@ private:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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
|
} //spdlog
|
120
vendor/spdlog/spdlog/details/async_log_helper.h
vendored
120
vendor/spdlog/spdlog/details/async_log_helper.h
vendored
@ -14,17 +14,21 @@
|
|||||||
|
|
||||||
#pragma once
|
#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 <chrono>
|
||||||
#include <thread>
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
#include "../common.h"
|
#include <string>
|
||||||
#include "../sinks/sink.h"
|
#include <thread>
|
||||||
#include "./mpmc_bounded_q.h"
|
#include <utility>
|
||||||
#include "./log_msg.h"
|
#include <vector>
|
||||||
#include "./format.h"
|
|
||||||
#include "./os.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -82,21 +86,22 @@ async_msg(async_msg&& other) SPDLOG_NOEXCEPT:
|
|||||||
|
|
||||||
// construct from log_msg
|
// construct from log_msg
|
||||||
async_msg(const details::log_msg& m) :
|
async_msg(const details::log_msg& m) :
|
||||||
logger_name(m.logger_name),
|
|
||||||
level(m.level),
|
level(m.level),
|
||||||
time(m.time),
|
time(m.time),
|
||||||
thread_id(m.thread_id),
|
thread_id(m.thread_id),
|
||||||
txt(m.raw.data(), m.raw.size()),
|
txt(m.raw.data(), m.raw.size()),
|
||||||
msg_type(async_msg_type::log)
|
msg_type(async_msg_type::log)
|
||||||
{}
|
{
|
||||||
|
#ifndef SPDLOG_NO_NAME
|
||||||
|
logger_name = *m.logger_name;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// copy into log_msg
|
// copy into log_msg
|
||||||
void fill_log_msg(log_msg &msg)
|
void fill_log_msg(log_msg &msg)
|
||||||
{
|
{
|
||||||
msg.clear();
|
msg.logger_name = &logger_name;
|
||||||
msg.logger_name = logger_name;
|
|
||||||
msg.level = level;
|
msg.level = level;
|
||||||
msg.time = time;
|
msg.time = time;
|
||||||
msg.thread_id = thread_id;
|
msg.thread_id = thread_id;
|
||||||
@ -115,9 +120,11 @@ public:
|
|||||||
async_log_helper(formatter_ptr formatter,
|
async_log_helper(formatter_ptr formatter,
|
||||||
const std::vector<sink_ptr>& sinks,
|
const std::vector<sink_ptr>& sinks,
|
||||||
size_t queue_size,
|
size_t queue_size,
|
||||||
|
const log_err_handler err_handler,
|
||||||
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
const async_overflow_policy overflow_policy = async_overflow_policy::block_retry,
|
||||||
const std::function<void()>& worker_warmup_cb = nullptr,
|
const std::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);
|
void log(const details::log_msg& msg);
|
||||||
|
|
||||||
@ -126,7 +133,7 @@ public:
|
|||||||
|
|
||||||
void set_formatter(formatter_ptr);
|
void set_formatter(formatter_ptr);
|
||||||
|
|
||||||
void flush();
|
void flush(bool wait_for_q);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -136,14 +143,13 @@ private:
|
|||||||
// queue of messages to log
|
// queue of messages to log
|
||||||
q_type _q;
|
q_type _q;
|
||||||
|
|
||||||
|
log_err_handler _err_handler;
|
||||||
|
|
||||||
bool _flush_requested;
|
bool _flush_requested;
|
||||||
|
|
||||||
bool _terminate_requested;
|
bool _terminate_requested;
|
||||||
|
|
||||||
|
|
||||||
// last exception thrown from the worker thread
|
|
||||||
std::shared_ptr<spdlog_ex> _last_workerthread_ex;
|
|
||||||
|
|
||||||
// overflow policy
|
// overflow policy
|
||||||
const async_overflow_policy _overflow_policy;
|
const async_overflow_policy _overflow_policy;
|
||||||
|
|
||||||
@ -153,13 +159,13 @@ private:
|
|||||||
// auto periodic sink flush parameter
|
// auto periodic sink flush parameter
|
||||||
const std::chrono::milliseconds _flush_interval_ms;
|
const std::chrono::milliseconds _flush_interval_ms;
|
||||||
|
|
||||||
|
// worker thread teardown callback
|
||||||
|
const std::function<void()> _worker_teardown_cb;
|
||||||
|
|
||||||
// worker thread
|
// worker thread
|
||||||
std::thread _worker_thread;
|
std::thread _worker_thread;
|
||||||
|
|
||||||
void push_msg(async_msg&& new_msg);
|
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
|
// worker thread main loop
|
||||||
void worker_loop();
|
void worker_loop();
|
||||||
@ -173,6 +179,9 @@ private:
|
|||||||
// sleep,yield or return immediatly using the time passed since last message as a hint
|
// 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);
|
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,
|
formatter_ptr formatter,
|
||||||
const std::vector<sink_ptr>& sinks,
|
const std::vector<sink_ptr>& sinks,
|
||||||
size_t queue_size,
|
size_t queue_size,
|
||||||
|
log_err_handler err_handler,
|
||||||
const async_overflow_policy overflow_policy,
|
const async_overflow_policy overflow_policy,
|
||||||
const std::function<void()>& worker_warmup_cb,
|
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),
|
_formatter(formatter),
|
||||||
_sinks(sinks),
|
_sinks(sinks),
|
||||||
_q(queue_size),
|
_q(queue_size),
|
||||||
|
_err_handler(err_handler),
|
||||||
_flush_requested(false),
|
_flush_requested(false),
|
||||||
_terminate_requested(false),
|
_terminate_requested(false),
|
||||||
_overflow_policy(overflow_policy),
|
_overflow_policy(overflow_policy),
|
||||||
_worker_warmup_cb(worker_warmup_cb),
|
_worker_warmup_cb(worker_warmup_cb),
|
||||||
_flush_interval_ms(flush_interval_ms),
|
_flush_interval_ms(flush_interval_ms),
|
||||||
|
_worker_teardown_cb(worker_teardown_cb),
|
||||||
_worker_thread(&async_log_helper::worker_loop, this)
|
_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)
|
inline void spdlog::details::async_log_helper::log(const details::log_msg& msg)
|
||||||
{
|
{
|
||||||
push_msg(async_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)
|
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)
|
if (!_q.enqueue(std::move(new_msg)) && _overflow_policy != async_overflow_policy::discard_log_msg)
|
||||||
{
|
{
|
||||||
auto last_op_time = details::os::now();
|
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));
|
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()
|
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_pop = details::os::now();
|
||||||
auto last_flush = last_pop;
|
auto last_flush = last_pop;
|
||||||
while(process_next_msg(last_pop, last_flush));
|
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 (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
_last_workerthread_ex = std::make_shared<spdlog_ex>("async_logger worker thread exception");
|
_err_handler("Unknown exception");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// process next message in the queue
|
// 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)
|
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;
|
async_msg incoming_async_msg;
|
||||||
log_msg incoming_log_msg;
|
|
||||||
|
|
||||||
if (_q.dequeue(incoming_async_msg))
|
if (_q.dequeue(incoming_async_msg))
|
||||||
{
|
{
|
||||||
@ -285,11 +300,17 @@ inline bool spdlog::details::async_log_helper::process_next_msg(log_clock::time_
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
log_msg incoming_log_msg;
|
||||||
incoming_async_msg.fill_log_msg(incoming_log_msg);
|
incoming_async_msg.fill_log_msg(incoming_log_msg);
|
||||||
_formatter->format(incoming_log_msg);
|
_formatter->format(incoming_log_msg);
|
||||||
for (auto &s : _sinks)
|
for (auto &s : _sinks)
|
||||||
|
{
|
||||||
|
if(s->should_log( incoming_log_msg.level))
|
||||||
|
{
|
||||||
s->log(incoming_log_msg);
|
s->log(incoming_log_msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
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);
|
handle_flush_interval(now, last_flush);
|
||||||
sleep_or_yield(now, last_pop);
|
sleep_or_yield(now, last_pop);
|
||||||
return !_terminate_requested;
|
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)
|
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);
|
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;
|
_flush_requested = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter)
|
inline void spdlog::details::async_log_helper::set_formatter(formatter_ptr msg_formatter)
|
||||||
{
|
{
|
||||||
_formatter = 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)
|
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 namespace std::this_thread;
|
||||||
|
using std::chrono::milliseconds;
|
||||||
|
using std::chrono::microseconds;
|
||||||
|
|
||||||
auto time_since_op = now - last_op_time;
|
auto time_since_op = now - last_op_time;
|
||||||
|
|
||||||
// spin upto 1 ms
|
// spin upto 50 micros
|
||||||
if (time_since_op <= milliseconds(1))
|
if (time_since_op <= microseconds(50))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// yield upto 10ms
|
// yield upto 150 micros
|
||||||
if (time_since_op <= milliseconds(10))
|
if (time_since_op <= microseconds(100))
|
||||||
return yield();
|
return yield();
|
||||||
|
|
||||||
|
|
||||||
// sleep for half of duration since last op
|
// sleep for 20 ms upto 200 ms
|
||||||
if (time_since_op <= milliseconds(100))
|
if (time_since_op <= milliseconds(200))
|
||||||
return sleep_for(time_since_op / 2);
|
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
|
// wait for the queue to be empty
|
||||||
inline void spdlog::details::async_log_helper::throw_if_bad_worker()
|
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);
|
sleep_or_yield(details::os::now(), last_op);
|
||||||
throw *ex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -362,3 +387,4 @@ inline void spdlog::details::async_log_helper::throw_if_bad_worker()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
40
vendor/spdlog/spdlog/details/async_logger_impl.h
vendored
40
vendor/spdlog/spdlog/details/async_logger_impl.h
vendored
@ -8,8 +8,13 @@
|
|||||||
// Async Logger implementation
|
// Async Logger implementation
|
||||||
// Use an async_sink (queue per logger) to perform the logging in a worker thread
|
// 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>
|
template<class It>
|
||||||
inline spdlog::async_logger::async_logger(const std::string& logger_name,
|
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,
|
size_t queue_size,
|
||||||
const async_overflow_policy overflow_policy,
|
const async_overflow_policy overflow_policy,
|
||||||
const std::function<void()>& worker_warmup_cb,
|
const std::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),
|
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,
|
size_t queue_size,
|
||||||
const async_overflow_policy overflow_policy,
|
const async_overflow_policy overflow_policy,
|
||||||
const std::function<void()>& worker_warmup_cb,
|
const std::function<void()>& worker_warmup_cb,
|
||||||
const std::chrono::milliseconds& flush_interval_ms) :
|
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::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,
|
inline spdlog::async_logger::async_logger(const std::string& logger_name,
|
||||||
sink_ptr single_sink,
|
sink_ptr single_sink,
|
||||||
size_t queue_size,
|
size_t queue_size,
|
||||||
const async_overflow_policy overflow_policy,
|
const async_overflow_policy overflow_policy,
|
||||||
const std::function<void()>& worker_warmup_cb,
|
const std::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,
|
async_logger(logger_name,
|
||||||
{
|
{
|
||||||
single_sink
|
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()
|
inline void spdlog::async_logger::flush()
|
||||||
{
|
{
|
||||||
|
_async_log_helper->flush(true);
|
||||||
_async_log_helper->flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void spdlog::async_logger::_set_formatter(spdlog::formatter_ptr msg_formatter)
|
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)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
_async_log_helper->log(msg);
|
_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
|
// Can be set to auto flush on every line
|
||||||
// Throw spdlog_ex exception on errors
|
// Throw spdlog_ex exception on errors
|
||||||
|
|
||||||
|
#include <spdlog/details/os.h>
|
||||||
|
#include <spdlog/details/log_msg.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <chrono>
|
#include <cerrno>
|
||||||
#include "os.h"
|
|
||||||
#include "log_msg.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -25,13 +26,13 @@ namespace details
|
|||||||
|
|
||||||
class file_helper
|
class file_helper
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const int open_tries = 5;
|
const int open_tries = 5;
|
||||||
const int open_interval = 10;
|
const int open_interval = 10;
|
||||||
|
|
||||||
explicit file_helper(bool force_flush) :
|
explicit file_helper() :
|
||||||
_fd(nullptr),
|
_fd(nullptr)
|
||||||
_force_flush(force_flush)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
file_helper(const file_helper&) = delete;
|
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();
|
close();
|
||||||
const char* mode = truncate ? "wb" : "ab";
|
auto *mode = truncate ? SPDLOG_FILENAME_T("wb") : SPDLOG_FILENAME_T("ab");
|
||||||
_filename = fname;
|
_filename = fname;
|
||||||
for (int tries = 0; tries < open_tries; ++tries)
|
for (int tries = 0; tries < open_tries; ++tries)
|
||||||
{
|
{
|
||||||
@ -57,7 +58,7 @@ public:
|
|||||||
std::this_thread::sleep_for(std::chrono::milliseconds(open_interval));
|
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)
|
void reopen(bool truncate)
|
||||||
@ -88,55 +89,30 @@ public:
|
|||||||
size_t msg_size = msg.formatted.size();
|
size_t msg_size = msg.formatted.size();
|
||||||
auto data = msg.formatted.data();
|
auto data = msg.formatted.data();
|
||||||
if (std::fwrite(data, 1, msg_size, _fd) != msg_size)
|
if (std::fwrite(data, 1, msg_size, _fd) != msg_size)
|
||||||
throw spdlog_ex("Failed writing to file " + _filename);
|
throw spdlog_ex("Failed writing to file " + os::filename_to_str(_filename), errno);
|
||||||
|
|
||||||
if (_force_flush)
|
|
||||||
std::fflush(_fd);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long size()
|
size_t size()
|
||||||
{
|
{
|
||||||
if (!_fd)
|
if (!_fd)
|
||||||
throw spdlog_ex("Cannot use size() on closed file " + _filename);
|
throw spdlog_ex("Cannot use size() on closed file " + os::filename_to_str(_filename));
|
||||||
|
return os::filesize(_fd);
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& filename() const
|
const filename_t& filename() const
|
||||||
{
|
{
|
||||||
return _filename;
|
return _filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool file_exists(const std::string& name)
|
static bool file_exists(const filename_t& name)
|
||||||
{
|
{
|
||||||
|
|
||||||
return os::file_exists(name);
|
return os::file_exists(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FILE* _fd;
|
FILE* _fd;
|
||||||
std::string _filename;
|
filename_t _filename;
|
||||||
bool _force_flush;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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
|
#pragma once
|
||||||
|
|
||||||
#include <thread>
|
#include <spdlog/common.h>
|
||||||
#include "../common.h"
|
#include <spdlog/details/os.h>
|
||||||
#include "./format.h"
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -16,59 +19,23 @@ namespace details
|
|||||||
struct log_msg
|
struct log_msg
|
||||||
{
|
{
|
||||||
log_msg() = default;
|
log_msg() = default;
|
||||||
log_msg(level::level_enum l):
|
log_msg(const std::string *loggers_name, level::level_enum lvl) : logger_name(loggers_name), level(lvl)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (other.raw.size())
|
#ifndef SPDLOG_NO_DATETIME
|
||||||
raw << fmt::BasicStringRef<char>(other.raw.data(), other.raw.size());
|
time = os::now();
|
||||||
if (other.formatted.size())
|
#endif
|
||||||
formatted << fmt::BasicStringRef<char>(other.formatted.data(), other.formatted.size());
|
|
||||||
|
#ifndef SPDLOG_NO_THREAD_ID
|
||||||
|
thread_id = os::thread_id();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
log_msg(log_msg&& other) :
|
log_msg(const log_msg& other) = delete;
|
||||||
logger_name(std::move(other.logger_name)),
|
log_msg& operator=(log_msg&& other) = delete;
|
||||||
level(other.level),
|
log_msg(log_msg&& other) = delete;
|
||||||
time(std::move(other.time)),
|
|
||||||
thread_id(other.thread_id),
|
|
||||||
raw(std::move(other.raw)),
|
|
||||||
formatted(std::move(other.formatted))
|
|
||||||
{
|
|
||||||
other.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
log_msg& operator=(log_msg&& other)
|
|
||||||
{
|
|
||||||
if (this == &other)
|
|
||||||
return *this;
|
|
||||||
|
|
||||||
logger_name = std::move(other.logger_name);
|
const std::string *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;
|
|
||||||
level::level_enum level;
|
level::level_enum level;
|
||||||
log_clock::time_point time;
|
log_clock::time_point time;
|
||||||
size_t thread_id;
|
size_t thread_id;
|
||||||
|
310
vendor/spdlog/spdlog/details/logger_impl.h
vendored
310
vendor/spdlog/spdlog/details/logger_impl.h
vendored
@ -5,7 +5,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#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
|
// create logger with given name, sinks and the default pattern formatter
|
||||||
// all other ctors will call this one
|
// all other ctors will call this one
|
||||||
@ -15,14 +20,19 @@ inline spdlog::logger::logger(const std::string& logger_name, const It& begin, c
|
|||||||
_sinks(begin, end),
|
_sinks(begin, end),
|
||||||
_formatter(std::make_shared<pattern_formatter>("%+"))
|
_formatter(std::make_shared<pattern_formatter>("%+"))
|
||||||
{
|
{
|
||||||
|
|
||||||
// no support under vs2013 for member initialization for std::atomic
|
|
||||||
_level = level::info;
|
_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
|
// ctor with sinks as init list
|
||||||
inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list):
|
inline spdlog::logger::logger(const std::string& logger_name, sinks_init_list sinks_list):
|
||||||
logger(logger_name, sinks_list.begin(), sinks_list.end()) {}
|
logger(logger_name, sinks_list.begin(), sinks_list.end())
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
// ctor with single sink
|
// ctor with single sink
|
||||||
@ -30,7 +40,8 @@ inline spdlog::logger::logger(const std::string& logger_name, spdlog::sink_ptr s
|
|||||||
logger(logger_name,
|
logger(logger_name,
|
||||||
{
|
{
|
||||||
single_sink
|
single_sink
|
||||||
}) {}
|
})
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
inline spdlog::logger::~logger() = default;
|
inline spdlog::logger::~logger() = default;
|
||||||
@ -46,210 +57,149 @@ inline void spdlog::logger::set_pattern(const std::string& pattern)
|
|||||||
_set_pattern(pattern);
|
_set_pattern(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// log only if given level>=logger's log level
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
template <typename... Args>
|
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);
|
if (!should_log(lvl)) return;
|
||||||
details::line_logger l(this, lvl, msg_enabled);
|
|
||||||
l.write(fmt, args...);
|
try
|
||||||
return l;
|
{
|
||||||
|
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>
|
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);
|
if (!should_log(lvl)) return;
|
||||||
details::line_logger l(this, lvl, msg_enabled);
|
try
|
||||||
l << msg;
|
{
|
||||||
return l;
|
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>
|
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>
|
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>
|
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>
|
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>
|
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...);
|
log(level::critical, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
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>
|
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>
|
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>
|
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);
|
log(level::critical, 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// 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
|
// name and level
|
||||||
//
|
//
|
||||||
@ -263,6 +213,22 @@ inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
|
|||||||
_level.store(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
|
inline spdlog::level::level_enum spdlog::logger::level() const
|
||||||
{
|
{
|
||||||
return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
|
return static_cast<spdlog::level::level_enum>(_level.load(std::memory_order_relaxed));
|
||||||
@ -276,12 +242,20 @@ 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
|
// 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);
|
_formatter->format(msg);
|
||||||
for (auto &sink : _sinks)
|
for (auto &sink : _sinks)
|
||||||
|
{
|
||||||
|
if( sink->should_log( msg.level))
|
||||||
|
{
|
||||||
sink->log(msg);
|
sink->log(msg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_should_flush_on(msg))
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
inline void spdlog::logger::_set_pattern(const std::string& pattern)
|
inline void spdlog::logger::_set_pattern(const std::string& pattern)
|
||||||
{
|
{
|
||||||
@ -297,3 +271,23 @@ inline void spdlog::logger::flush()
|
|||||||
for (auto& sink : _sinks)
|
for (auto& sink : _sinks)
|
||||||
sink->flush();
|
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);
|
||||||
|
}
|
||||||
|
23
vendor/spdlog/spdlog/details/mpmc_bounded_q.h
vendored
23
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
|
#pragma once
|
||||||
|
|
||||||
|
#include <spdlog/common.h>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include "../common.h"
|
#include <utility>
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -58,7 +60,8 @@ public:
|
|||||||
|
|
||||||
using item_type = T;
|
using item_type = T;
|
||||||
mpmc_bounded_queue(size_t buffer_size)
|
mpmc_bounded_queue(size_t buffer_size)
|
||||||
: buffer_(new cell_t [buffer_size]),
|
:max_size_(buffer_size),
|
||||||
|
buffer_(new cell_t [buffer_size]),
|
||||||
buffer_mask_(buffer_size - 1)
|
buffer_mask_(buffer_size - 1)
|
||||||
{
|
{
|
||||||
//queue size must be power of two
|
//queue size must be power of two
|
||||||
@ -130,6 +133,16 @@ public:
|
|||||||
return true;
|
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:
|
private:
|
||||||
struct cell_t
|
struct cell_t
|
||||||
{
|
{
|
||||||
@ -137,6 +150,8 @@ private:
|
|||||||
T data_;
|
T data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
size_t const max_size_;
|
||||||
|
|
||||||
static size_t const cacheline_size = 64;
|
static size_t const cacheline_size = 64;
|
||||||
typedef char cacheline_pad_t [cacheline_size];
|
typedef char cacheline_pad_t [cacheline_size];
|
||||||
|
|
||||||
@ -149,8 +164,8 @@ private:
|
|||||||
std::atomic<size_t> dequeue_pos_;
|
std::atomic<size_t> dequeue_pos_;
|
||||||
cacheline_pad_t pad3_;
|
cacheline_pad_t pad3_;
|
||||||
|
|
||||||
mpmc_bounded_queue(mpmc_bounded_queue const&);
|
mpmc_bounded_queue(mpmc_bounded_queue const&) = delete;
|
||||||
void operator = (mpmc_bounded_queue const&);
|
void operator= (mpmc_bounded_queue const&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // ns details
|
} // 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
|
#pragma once
|
||||||
|
|
||||||
// null, no cost mutex
|
#include <atomic>
|
||||||
|
// null, no cost dummy "mutex" and dummy "atomic" int
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -20,5 +21,25 @@ struct null_mutex
|
|||||||
return true;
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
223
vendor/spdlog/spdlog/details/os.h
vendored
223
vendor/spdlog/spdlog/details/os.h
vendored
@ -4,11 +4,23 @@
|
|||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include<string>
|
#include <spdlog/common.h>
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#ifndef NOMINMAX
|
||||||
|
#define NOMINMAX //prevent windows redefining min/max
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
@ -18,15 +30,21 @@
|
|||||||
#include <share.h>
|
#include <share.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
|
|
||||||
#include <sys/syscall.h> //Use gettid() syscall under linux to get thread id
|
#include <sys/syscall.h> //Use gettid() syscall under linux to get thread id
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#elif __FreeBSD__
|
||||||
|
#include <sys/thr.h> //Use thr_self() syscall under FreeBSD to get thread id
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../common.h"
|
#endif
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -105,66 +123,111 @@ inline bool operator!=(const std::tm& tm1, const std::tm& tm2)
|
|||||||
return !(tm1 == tm2);
|
return !(tm1 == tm2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eol definition
|
||||||
|
#if !defined (SPDLOG_EOL)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
inline const char* eol()
|
#define SPDLOG_EOL "\r\n"
|
||||||
{
|
|
||||||
return "\r\n";
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
constexpr inline const char* eol()
|
#define SPDLOG_EOL "\n"
|
||||||
{
|
#endif
|
||||||
return "\n";
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
SPDLOG_CONSTEXPR static const char* eol = SPDLOG_EOL;
|
||||||
inline unsigned short eol_size()
|
SPDLOG_CONSTEXPR static int eol_size = sizeof(SPDLOG_EOL) - 1;
|
||||||
{
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
constexpr inline unsigned short eol_size()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//fopen_s on non windows for writing
|
//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
|
#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;
|
return *fp == nullptr;
|
||||||
#else
|
#else
|
||||||
*fp = fopen((filename.c_str()), mode);
|
*fp = fopen((filename.c_str()), mode.c_str());
|
||||||
return *fp == nullptr;
|
return *fp == nullptr;
|
||||||
#endif
|
#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
|
//Return if file exists
|
||||||
inline bool file_exists(const std::string& filename)
|
inline bool file_exists(const filename_t& filename)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#ifdef SPDLOG_WCHAR_FILENAMES
|
||||||
|
auto attribs = GetFileAttributesW(filename.c_str());
|
||||||
|
#else
|
||||||
auto attribs = GetFileAttributesA(filename.c_str());
|
auto attribs = GetFileAttributesA(filename.c_str());
|
||||||
|
#endif
|
||||||
return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY));
|
return (attribs != INVALID_FILE_ATTRIBUTES && !(attribs & FILE_ATTRIBUTE_DIRECTORY));
|
||||||
#elif __linux__
|
#else //common linux/unix all have the stat system call
|
||||||
struct stat buffer;
|
struct stat buffer;
|
||||||
return (stat (filename.c_str(), &buffer) == 0);
|
return (stat (filename.c_str(), &buffer) == 0);
|
||||||
#else
|
#endif
|
||||||
auto *file = fopen(filename.c_str(), "r");
|
|
||||||
if (file != nullptr)
|
|
||||||
{
|
|
||||||
fclose(file);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//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
|
#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
|
//Return utc offset in minutes or throw spdlog_ex on failure
|
||||||
inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
|
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);
|
auto rv = GetDynamicTimeZoneInformation(&tzinfo);
|
||||||
#endif
|
#endif
|
||||||
if (rv == TIME_ZONE_ID_INVALID)
|
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;
|
int offset = -tzinfo.Bias;
|
||||||
if (tm.tm_isdst)
|
if (tm.tm_isdst)
|
||||||
@ -187,7 +250,43 @@ inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
|
|||||||
offset -= tzinfo.StandardBias;
|
offset -= tzinfo.StandardBias;
|
||||||
return offset;
|
return offset;
|
||||||
#else
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,14 +301,60 @@ inline size_t thread_id()
|
|||||||
# define SYS_gettid __NR_gettid
|
# define SYS_gettid __NR_gettid
|
||||||
# endif
|
# endif
|
||||||
return static_cast<size_t>(syscall(SYS_gettid));
|
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)
|
#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()));
|
return static_cast<size_t>(std::hash<std::thread::id>()(std::this_thread::get_id()));
|
||||||
#endif
|
#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
|
} //os
|
||||||
} //details
|
} //details
|
||||||
} //spdlog
|
} //spdlog
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,16 +5,19 @@
|
|||||||
|
|
||||||
#pragma once
|
#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 <chrono>
|
||||||
|
#include <ctime>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
#include "../formatter.h"
|
|
||||||
#include "./log_msg.h"
|
|
||||||
#include "./os.h"
|
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -23,7 +26,8 @@ namespace details
|
|||||||
class flag_formatter
|
class flag_formatter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~flag_formatter() {}
|
virtual ~flag_formatter()
|
||||||
|
{}
|
||||||
virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0;
|
virtual void format(details::log_msg& msg, const std::tm& tm_time) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -36,7 +40,7 @@ class name_formatter :public flag_formatter
|
|||||||
{
|
{
|
||||||
void format(details::log_msg& msg, const std::tm&) override
|
void format(details::log_msg& msg, const std::tm&) override
|
||||||
{
|
{
|
||||||
msg.formatted << msg.logger_name;
|
msg.formatted << *msg.logger_name;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -301,7 +305,8 @@ class z_formatter :public flag_formatter
|
|||||||
public:
|
public:
|
||||||
const std::chrono::seconds cache_refresh = std::chrono::seconds(5);
|
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(const z_formatter&) = delete;
|
||||||
z_formatter& operator=(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)
|
// it is very fast (already stored in tm.tm_gmtoff)
|
||||||
int total_minutes = os::utc_minutes_offset(tm_time);
|
int total_minutes = os::utc_minutes_offset(tm_time);
|
||||||
#endif
|
#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 h = total_minutes / 60;
|
||||||
int m = total_minutes % 60;
|
int m = total_minutes % 60;
|
||||||
if (h >= 0) //minus sign will be printed anyway if negative
|
msg.formatted << sign;
|
||||||
{
|
|
||||||
msg.formatted << '+';
|
|
||||||
}
|
|
||||||
pad_n_join(msg.formatted, h, m, ':');
|
pad_n_join(msg.formatted, h, m, ':');
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
@ -432,7 +445,7 @@ class full_formatter :public flag_formatter
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SPDLOG_NO_NAME
|
#ifndef SPDLOG_NO_NAME
|
||||||
msg.formatted << '[' << msg.logger_name << "] ";
|
msg.formatted << '[' << *msg.logger_name << "] ";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
msg.formatted << '[' << level::to_str(msg.level) << "] ";
|
msg.formatted << '[' << level::to_str(msg.level) << "] ";
|
||||||
@ -608,18 +621,16 @@ inline void spdlog::pattern_formatter::handle_flag(char flag)
|
|||||||
|
|
||||||
inline void spdlog::pattern_formatter::format(details::log_msg& msg)
|
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));
|
auto tm_time = details::os::localtime(log_clock::to_time_t(msg.time));
|
||||||
|
#else
|
||||||
|
std::tm tm_time;
|
||||||
|
#endif
|
||||||
for (auto &f : _formatters)
|
for (auto &f : _formatters)
|
||||||
{
|
{
|
||||||
f->format(msg, tm_time);
|
f->format(msg, tm_time);
|
||||||
}
|
}
|
||||||
//write eol
|
//write eol
|
||||||
msg.formatted << details::os::eol();
|
msg.formatted.write(details::os::eol, details::os::eol_size);
|
||||||
}
|
|
||||||
catch(const fmt::FormatError& e)
|
|
||||||
{
|
|
||||||
throw spdlog_ex(fmt::format("formatting error while processing format string: {}", e.what()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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
|
// If user requests a non existing logger, nullptr will be returned
|
||||||
// This class is thread safe
|
// This class is thread safe
|
||||||
|
|
||||||
#include <string>
|
#include <spdlog/details/null_mutex.h>
|
||||||
#include <mutex>
|
#include <spdlog/logger.h>
|
||||||
#include <unordered_map>
|
#include <spdlog/async_logger.h>
|
||||||
#include <functional>
|
#include <spdlog/common.h>
|
||||||
|
|
||||||
#include "./null_mutex.h"
|
#include <chrono>
|
||||||
#include "../logger.h"
|
#include <functional>
|
||||||
#include "../async_logger.h"
|
#include <memory>
|
||||||
#include "../common.h"
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -31,7 +33,9 @@ public:
|
|||||||
void register_logger(std::shared_ptr<logger> logger)
|
void register_logger(std::shared_ptr<logger> logger)
|
||||||
{
|
{
|
||||||
std::lock_guard<Mutex> lock(_mutex);
|
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>
|
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> 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);
|
std::lock_guard<Mutex> lock(_mutex);
|
||||||
|
throw_if_exists(logger_name);
|
||||||
|
std::shared_ptr<logger> new_logger;
|
||||||
if (_async_mode)
|
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
|
else
|
||||||
new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
|
new_logger = std::make_shared<logger>(logger_name, sinks_begin, sinks_end);
|
||||||
|
|
||||||
if (_formatter)
|
if (_formatter)
|
||||||
new_logger->set_formatter(_formatter);
|
new_logger->set_formatter(_formatter);
|
||||||
|
|
||||||
|
if (_err_handler)
|
||||||
|
new_logger->set_error_handler(_err_handler);
|
||||||
|
|
||||||
new_logger->set_level(_level);
|
new_logger->set_level(_level);
|
||||||
register_logger_impl(new_logger);
|
|
||||||
|
|
||||||
|
//Add to registry
|
||||||
|
_loggers[logger_name] = new_logger;
|
||||||
return 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)
|
void drop(const std::string& logger_name)
|
||||||
{
|
{
|
||||||
std::lock_guard<Mutex> lock(_mutex);
|
std::lock_guard<Mutex> lock(_mutex);
|
||||||
@ -110,7 +124,14 @@ public:
|
|||||||
_level = log_level;
|
_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);
|
std::lock_guard<Mutex> lock(_mutex);
|
||||||
_async_mode = true;
|
_async_mode = true;
|
||||||
@ -118,6 +139,7 @@ public:
|
|||||||
_overflow_policy = overflow_policy;
|
_overflow_policy = overflow_policy;
|
||||||
_worker_warmup_cb = worker_warmup_cb;
|
_worker_warmup_cb = worker_warmup_cb;
|
||||||
_flush_interval_ms = flush_interval_ms;
|
_flush_interval_ms = flush_interval_ms;
|
||||||
|
_worker_teardown_cb = worker_teardown_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_sync_mode()
|
void set_sync_mode()
|
||||||
@ -133,25 +155,26 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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>() {}
|
||||||
registry_t<Mutex>(const registry_t<Mutex>&) = delete;
|
registry_t<Mutex>(const registry_t<Mutex>&) = delete;
|
||||||
registry_t<Mutex>& operator=(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;
|
Mutex _mutex;
|
||||||
std::unordered_map <std::string, std::shared_ptr<logger>> _loggers;
|
std::unordered_map <std::string, std::shared_ptr<logger>> _loggers;
|
||||||
formatter_ptr _formatter;
|
formatter_ptr _formatter;
|
||||||
level::level_enum _level = level::info;
|
level::level_enum _level = level::info;
|
||||||
|
log_err_handler _err_handler;
|
||||||
bool _async_mode = false;
|
bool _async_mode = false;
|
||||||
size_t _async_q_size = 0;
|
size_t _async_q_size = 0;
|
||||||
async_overflow_policy _overflow_policy = async_overflow_policy::block_retry;
|
async_overflow_policy _overflow_policy = async_overflow_policy::block_retry;
|
||||||
std::function<void()> _worker_warmup_cb = nullptr;
|
std::function<void()> _worker_warmup_cb = nullptr;
|
||||||
std::chrono::milliseconds _flush_interval_ms;
|
std::chrono::milliseconds _flush_interval_ms;
|
||||||
|
std::function<void()> _worker_teardown_cb = nullptr;
|
||||||
};
|
};
|
||||||
#ifdef SPDLOG_NO_REGISTRY_MUTEX
|
#ifdef SPDLOG_NO_REGISTRY_MUTEX
|
||||||
typedef registry_t<spdlog::details::null_mutex> registry;
|
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
|
// Global registry functions
|
||||||
//
|
//
|
||||||
#include "registry.h"
|
#include <spdlog/spdlog.h>
|
||||||
#include "../sinks/file_sinks.h"
|
#include <spdlog/details/registry.h>
|
||||||
#include "../sinks/stdout_sinks.h"
|
#include <spdlog/sinks/file_sinks.h>
|
||||||
#include "../sinks/syslog_sink.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)
|
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);
|
details::registry::instance().drop(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create multi/single threaded rotating file logger
|
// Create multi/single threaded simple 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)
|
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):
|
// 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);
|
return create<spdlog::sinks::daily_file_sink_mt>(logger_name, filename, SPDLOG_FILENAME_T("txt"), hour, minute);
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline std::shared_ptr<spdlog::logger> spdlog::daily_logger_st(const std::string& logger_name, const filename_t& filename, int hour, int minute)
|
||||||
// Create stdout/stderr loggers
|
|
||||||
inline std::shared_ptr<spdlog::logger> spdlog::stdout_logger_mt(const std::string& logger_name)
|
|
||||||
{
|
{
|
||||||
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
|
// 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)
|
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
|
#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
|
//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);
|
return details::registry::instance().set_level(log_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void spdlog::set_error_handler(log_err_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)
|
|
||||||
{
|
{
|
||||||
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()
|
inline void spdlog::set_sync_mode()
|
||||||
@ -128,8 +171,12 @@ inline void spdlog::set_sync_mode()
|
|||||||
details::registry::instance().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()
|
inline void spdlog::drop_all()
|
||||||
{
|
{
|
||||||
details::registry::instance().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
|
#pragma once
|
||||||
|
|
||||||
#include "details/log_msg.h"
|
#include <spdlog/details/log_msg.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
namespace details
|
namespace details
|
||||||
@ -36,5 +41,5 @@ private:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "details/pattern_formatter_impl.h"
|
#include <spdlog/details/pattern_formatter_impl.h>
|
||||||
|
|
||||||
|
107
vendor/spdlog/spdlog/logger.h
vendored
107
vendor/spdlog/spdlog/logger.h
vendored
@ -12,19 +12,16 @@
|
|||||||
// 2. Format the message using the formatter function
|
// 2. Format the message using the formatter function
|
||||||
// 3. Pass the formatted message to its sinks to performa the actual logging
|
// 3. Pass the formatted message to its sinks to performa the actual logging
|
||||||
|
|
||||||
|
#include <spdlog/sinks/base_sink.h>
|
||||||
|
#include <spdlog/common.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "sinks/base_sink.h"
|
#include <string>
|
||||||
#include "common.h"
|
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace details
|
|
||||||
{
|
|
||||||
class line_logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
class logger
|
class logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -37,77 +34,61 @@ public:
|
|||||||
logger(const logger&) = delete;
|
logger(const logger&) = delete;
|
||||||
logger& operator=(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);
|
void set_level(level::level_enum);
|
||||||
level::level_enum level() const;
|
level::level_enum level() const;
|
||||||
|
|
||||||
const std::string& name() 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_pattern(const std::string&);
|
||||||
void set_formatter(formatter_ptr);
|
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();
|
virtual void flush();
|
||||||
|
|
||||||
protected:
|
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_pattern(const std::string&);
|
||||||
virtual void _set_formatter(formatter_ptr);
|
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;
|
// return true if the given message level should trigger a flush
|
||||||
std::string _name;
|
bool _should_flush_on(const details::log_msg&);
|
||||||
|
|
||||||
|
const std::string _name;
|
||||||
std::vector<sink_ptr> _sinks;
|
std::vector<sink_ptr> _sinks;
|
||||||
formatter_ptr _formatter;
|
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__)
|
#if defined(__ANDROID__)
|
||||||
|
|
||||||
#include <mutex>
|
#include <spdlog/sinks/sink.h>
|
||||||
#include "base_sink.h"
|
|
||||||
#include "../details/null_mutex.h"
|
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
namespace sinks
|
namespace sinks
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Android sink (logging using __android_log_write)
|
* Android sink (logging using __android_log_write)
|
||||||
|
* __android_log_write is thread-safe. No lock is needed.
|
||||||
*/
|
*/
|
||||||
template<class Mutex>
|
class android_sink : public sink
|
||||||
class base_android_sink : public base_sink < Mutex >
|
|
||||||
{
|
{
|
||||||
public:
|
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
|
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:
|
private:
|
||||||
static android_LogPriority convert_to_android(spdlog::level::level_enum level)
|
static android_LogPriority convert_to_android(spdlog::level::level_enum level)
|
||||||
{
|
{
|
||||||
@ -61,29 +55,20 @@ private:
|
|||||||
return ANDROID_LOG_DEBUG;
|
return ANDROID_LOG_DEBUG;
|
||||||
case spdlog::level::info:
|
case spdlog::level::info:
|
||||||
return ANDROID_LOG_INFO;
|
return ANDROID_LOG_INFO;
|
||||||
case spdlog::level::notice:
|
|
||||||
return ANDROID_LOG_INFO;
|
|
||||||
case spdlog::level::warn:
|
case spdlog::level::warn:
|
||||||
return ANDROID_LOG_WARN;
|
return ANDROID_LOG_WARN;
|
||||||
case spdlog::level::err:
|
case spdlog::level::err:
|
||||||
return ANDROID_LOG_ERROR;
|
return ANDROID_LOG_ERROR;
|
||||||
case spdlog::level::critical:
|
case spdlog::level::critical:
|
||||||
return ANDROID_LOG_FATAL;
|
return ANDROID_LOG_FATAL;
|
||||||
case spdlog::level::alert:
|
|
||||||
return ANDROID_LOG_FATAL;
|
|
||||||
case spdlog::level::emerg:
|
|
||||||
return ANDROID_LOG_FATAL;
|
|
||||||
default:
|
default:
|
||||||
throw spdlog_ex("Incorrect level value");
|
return ANDROID_LOG_DEFAULT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string _tag;
|
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)
|
// base sink templated over a mutex (either dummy or realy)
|
||||||
// concrete implementation should only overrid the _sink_it method.
|
// 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 <spdlog/sinks/sink.h>
|
||||||
#include<mutex>
|
#include <spdlog/formatter.h>
|
||||||
#include<atomic>
|
#include <spdlog/common.h>
|
||||||
#include "./sink.h"
|
#include <spdlog/details/log_msg.h>
|
||||||
#include "../formatter.h"
|
|
||||||
#include "../common.h"
|
|
||||||
#include "../details/log_msg.h"
|
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
|
45
vendor/spdlog/spdlog/sinks/dist_sink.h
vendored
45
vendor/spdlog/spdlog/sinks/dist_sink.h
vendored
@ -5,15 +5,17 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
#include <spdlog/details/log_msg.h>
|
||||||
#include <memory>
|
#include <spdlog/details/null_mutex.h>
|
||||||
#include <mutex>
|
#include <spdlog/sinks/base_sink.h>
|
||||||
#include <list>
|
#include <spdlog/sinks/sink.h>
|
||||||
|
|
||||||
#include "../details/log_msg.h"
|
#include <algorithm>
|
||||||
#include "../details/null_mutex.h"
|
#include <mutex>
|
||||||
#include "./base_sink.h"
|
#include <memory>
|
||||||
#include "./sink.h"
|
#include <vector>
|
||||||
|
|
||||||
|
// Distribution sink (mux). Stores a vector of sinks which get called when log is called
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -29,40 +31,37 @@ public:
|
|||||||
virtual ~dist_sink() = default;
|
virtual ~dist_sink() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
std::vector<std::shared_ptr<sink>> _sinks;
|
||||||
|
|
||||||
void _sink_it(const details::log_msg& msg) override
|
void _sink_it(const details::log_msg& msg) override
|
||||||
{
|
{
|
||||||
for (auto iter = _sinks.begin(); iter != _sinks.end(); iter++)
|
for (auto &sink : _sinks)
|
||||||
(*iter)->log(msg);
|
{
|
||||||
|
if( sink->should_log( msg.level))
|
||||||
|
{
|
||||||
|
sink->log(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<sink>> _sinks;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void flush() override
|
void flush() override
|
||||||
{
|
{
|
||||||
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
|
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
|
||||||
for (auto iter = _sinks.begin(); iter != _sinks.end(); iter++)
|
for (auto &sink : _sinks)
|
||||||
(*iter)->flush();
|
sink->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_sink(std::shared_ptr<sink> sink)
|
void add_sink(std::shared_ptr<sink> sink)
|
||||||
{
|
{
|
||||||
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
|
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)
|
void remove_sink(std::shared_ptr<sink> sink)
|
||||||
{
|
{
|
||||||
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
|
std::lock_guard<Mutex> lock(base_sink<Mutex>::_mutex);
|
||||||
auto pos = std::find(_sinks.begin(), _sinks.end(), sink);
|
_sinks.erase(std::remove(_sinks.begin(), _sinks.end(), sink), _sinks.end());
|
||||||
if (pos != _sinks.end())
|
|
||||||
{
|
|
||||||
_sinks.erase(pos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
117
vendor/spdlog/spdlog/sinks/file_sinks.h
vendored
117
vendor/spdlog/spdlog/sinks/file_sinks.h
vendored
@ -5,11 +5,18 @@
|
|||||||
|
|
||||||
#pragma once
|
#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 <mutex>
|
||||||
#include "base_sink.h"
|
#include <string>
|
||||||
#include "../details/null_mutex.h"
|
#include <cerrno>
|
||||||
#include "../details/file_helper.h"
|
|
||||||
#include "../details/format.h"
|
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -22,11 +29,9 @@ template<class Mutex>
|
|||||||
class simple_file_sink : public base_sink < Mutex >
|
class simple_file_sink : public base_sink < Mutex >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit simple_file_sink(const std::string &filename,
|
explicit simple_file_sink(const filename_t &filename, bool truncate = false)
|
||||||
bool force_flush = false) :
|
|
||||||
_file_helper(force_flush)
|
|
||||||
{
|
{
|
||||||
_file_helper.open(filename);
|
_file_helper.open(filename, truncate);
|
||||||
}
|
}
|
||||||
void flush() override
|
void flush() override
|
||||||
{
|
{
|
||||||
@ -52,15 +57,14 @@ template<class Mutex>
|
|||||||
class rotating_file_sink : public base_sink < Mutex >
|
class rotating_file_sink : public base_sink < Mutex >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
rotating_file_sink(const std::string &base_filename, const std::string &extension,
|
rotating_file_sink(const filename_t &base_filename, const filename_t &extension,
|
||||||
std::size_t max_size, std::size_t max_files,
|
std::size_t max_size, std::size_t max_files ) :
|
||||||
bool force_flush = false) :
|
|
||||||
_base_filename(base_filename),
|
_base_filename(base_filename),
|
||||||
_extension(extension),
|
_extension(extension),
|
||||||
_max_size(max_size),
|
_max_size(max_size),
|
||||||
_max_files(max_files),
|
_max_files(max_files),
|
||||||
_current_size(0),
|
_current_size(0),
|
||||||
_file_helper(force_flush)
|
_file_helper()
|
||||||
{
|
{
|
||||||
_file_helper.open(calc_filename(_base_filename, 0, _extension));
|
_file_helper.open(calc_filename(_base_filename, 0, _extension));
|
||||||
_current_size = _file_helper.size(); //expensive. called only once
|
_current_size = _file_helper.size(); //expensive. called only once
|
||||||
@ -84,13 +88,13 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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)
|
if (index)
|
||||||
w.write("{}.{}.{}", filename, index, extension);
|
w.write(SPDLOG_FILENAME_T("{}.{}.{}"), filename, index, extension);
|
||||||
else
|
else
|
||||||
w.write("{}.{}", filename, extension);
|
w.write(SPDLOG_FILENAME_T("{}.{}"), filename, extension);
|
||||||
return w.str();
|
return w.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,28 +106,29 @@ private:
|
|||||||
|
|
||||||
void _rotate()
|
void _rotate()
|
||||||
{
|
{
|
||||||
|
using details::os::filename_to_str;
|
||||||
_file_helper.close();
|
_file_helper.close();
|
||||||
for (auto i = _max_files; i > 0; --i)
|
for (auto i = _max_files; i > 0; --i)
|
||||||
{
|
{
|
||||||
std::string src = calc_filename(_base_filename, i - 1, _extension);
|
filename_t src = calc_filename(_base_filename, i - 1, _extension);
|
||||||
std::string target = calc_filename(_base_filename, i, _extension);
|
filename_t target = calc_filename(_base_filename, i, _extension);
|
||||||
|
|
||||||
if (details::file_helper::file_exists(target))
|
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);
|
_file_helper.reopen(true);
|
||||||
}
|
}
|
||||||
std::string _base_filename;
|
filename_t _base_filename;
|
||||||
std::string _extension;
|
filename_t _extension;
|
||||||
std::size_t _max_size;
|
std::size_t _max_size;
|
||||||
std::size_t _max_files;
|
std::size_t _max_files;
|
||||||
std::size_t _current_size;
|
std::size_t _current_size;
|
||||||
@ -133,29 +138,57 @@ private:
|
|||||||
typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
|
typedef rotating_file_sink<std::mutex> rotating_file_sink_mt;
|
||||||
typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;
|
typedef rotating_file_sink<details::null_mutex>rotating_file_sink_st;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default generator of daily log file names.
|
||||||
|
*/
|
||||||
|
struct default_daily_file_name_calculator
|
||||||
|
{
|
||||||
|
// Create filename for the form basename.YYYY-MM-DD_hh-mm.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
|
* Rotating file sink based on date. rotates at midnight
|
||||||
*/
|
*/
|
||||||
template<class Mutex>
|
template<class Mutex, class FileNameCalc = default_daily_file_name_calculator>
|
||||||
class daily_file_sink :public base_sink < Mutex >
|
class daily_file_sink :public base_sink < Mutex >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//create daily file sink which rotates on given time
|
//create daily file sink which rotates on given time
|
||||||
daily_file_sink(
|
daily_file_sink(
|
||||||
const std::string& base_filename,
|
const filename_t& base_filename,
|
||||||
const std::string& extension,
|
const filename_t& extension,
|
||||||
int rotation_hour,
|
int rotation_hour,
|
||||||
int rotation_minute,
|
int rotation_minute) : _base_filename(base_filename),
|
||||||
bool force_flush = false) : _base_filename(base_filename),
|
|
||||||
_extension(extension),
|
_extension(extension),
|
||||||
_rotation_h(rotation_hour),
|
_rotation_h(rotation_hour),
|
||||||
_rotation_m(rotation_minute),
|
_rotation_m(rotation_minute)
|
||||||
_file_helper(force_flush)
|
|
||||||
{
|
{
|
||||||
if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
|
if (rotation_hour < 0 || rotation_hour > 23 || rotation_minute < 0 || rotation_minute > 59)
|
||||||
throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
|
throw spdlog_ex("daily_file_sink: Invalid rotation time in ctor");
|
||||||
_rotation_tp = _next_rotation_tp();
|
_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
|
void flush() override
|
||||||
@ -168,7 +201,7 @@ protected:
|
|||||||
{
|
{
|
||||||
if (std::chrono::system_clock::now() >= _rotation_tp)
|
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();
|
_rotation_tp = _next_rotation_tp();
|
||||||
}
|
}
|
||||||
_file_helper.write(msg);
|
_file_helper.write(msg);
|
||||||
@ -177,8 +210,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
std::chrono::system_clock::time_point _next_rotation_tp()
|
std::chrono::system_clock::time_point _next_rotation_tp()
|
||||||
{
|
{
|
||||||
using namespace std::chrono;
|
auto now = std::chrono::system_clock::now();
|
||||||
auto now = system_clock::now();
|
|
||||||
time_t tnow = std::chrono::system_clock::to_time_t(now);
|
time_t tnow = std::chrono::system_clock::to_time_t(now);
|
||||||
tm date = spdlog::details::os::localtime(tnow);
|
tm date = spdlog::details::os::localtime(tnow);
|
||||||
date.tm_hour = _rotation_h;
|
date.tm_hour = _rotation_h;
|
||||||
@ -188,20 +220,11 @@ private:
|
|||||||
if (rotation_time > now)
|
if (rotation_time > now)
|
||||||
return rotation_time;
|
return rotation_time;
|
||||||
else
|
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
|
filename_t _base_filename;
|
||||||
static std::string calc_filename(const std::string& basename, const std::string& extension)
|
filename_t _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;
|
|
||||||
int _rotation_h;
|
int _rotation_h;
|
||||||
int _rotation_m;
|
int _rotation_m;
|
||||||
std::chrono::system_clock::time_point _rotation_tp;
|
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
|
#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
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include <spdlog/details/null_mutex.h>
|
||||||
|
#include <spdlog/sinks/base_sink.h>
|
||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "../details/null_mutex.h"
|
|
||||||
#include "./base_sink.h"
|
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
|
28
vendor/spdlog/spdlog/sinks/sink.h
vendored
28
vendor/spdlog/spdlog/sinks/sink.h
vendored
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../details/log_msg.h"
|
#include <spdlog/details/log_msg.h>
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -15,10 +15,36 @@ namespace sinks
|
|||||||
class sink
|
class sink
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
sink(): _level( level::trace ) {}
|
||||||
|
|
||||||
virtual ~sink() {}
|
virtual ~sink() {}
|
||||||
virtual void log(const details::log_msg& msg) = 0;
|
virtual void log(const details::log_msg& msg) = 0;
|
||||||
virtual void flush() = 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
|
#pragma once
|
||||||
|
|
||||||
#include <iostream>
|
#include <spdlog/details/null_mutex.h>
|
||||||
|
#include <spdlog/sinks/base_sink.h>
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "./ostream_sink.h"
|
|
||||||
#include "../details/null_mutex.h"
|
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -16,16 +18,27 @@ namespace sinks
|
|||||||
{
|
{
|
||||||
|
|
||||||
template <class Mutex>
|
template <class Mutex>
|
||||||
class stdout_sink : public ostream_sink<Mutex>
|
class stdout_sink : public base_sink<Mutex>
|
||||||
{
|
{
|
||||||
using MyType = stdout_sink<Mutex>;
|
using MyType = stdout_sink<Mutex>;
|
||||||
public:
|
public:
|
||||||
stdout_sink() : ostream_sink<Mutex>(std::cout, true) {}
|
stdout_sink() {}
|
||||||
static std::shared_ptr<MyType> instance()
|
static std::shared_ptr<MyType> instance()
|
||||||
{
|
{
|
||||||
static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
|
static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
|
||||||
return instance;
|
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;
|
typedef stdout_sink<details::null_mutex> stdout_sink_st;
|
||||||
@ -33,17 +46,27 @@ typedef stdout_sink<std::mutex> stdout_sink_mt;
|
|||||||
|
|
||||||
|
|
||||||
template <class Mutex>
|
template <class Mutex>
|
||||||
class stderr_sink : public ostream_sink<Mutex>
|
class stderr_sink : public base_sink<Mutex>
|
||||||
{
|
{
|
||||||
using MyType = stderr_sink<Mutex>;
|
using MyType = stderr_sink<Mutex>;
|
||||||
public:
|
public:
|
||||||
stderr_sink() : ostream_sink<Mutex>(std::cerr, true) {}
|
stderr_sink() {}
|
||||||
static std::shared_ptr<MyType> instance()
|
static std::shared_ptr<MyType> instance()
|
||||||
{
|
{
|
||||||
static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
|
static std::shared_ptr<MyType> instance = std::make_shared<MyType>();
|
||||||
return instance;
|
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;
|
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
|
#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 <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
|
||||||
#include "./sink.h"
|
|
||||||
#include "../common.h"
|
|
||||||
#include "../details/log_msg.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace spdlog
|
namespace spdlog
|
||||||
{
|
{
|
||||||
@ -35,12 +36,9 @@ public:
|
|||||||
_priorities[static_cast<int>(level::trace)] = LOG_DEBUG;
|
_priorities[static_cast<int>(level::trace)] = LOG_DEBUG;
|
||||||
_priorities[static_cast<int>(level::debug)] = LOG_DEBUG;
|
_priorities[static_cast<int>(level::debug)] = LOG_DEBUG;
|
||||||
_priorities[static_cast<int>(level::info)] = LOG_INFO;
|
_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::warn)] = LOG_WARNING;
|
||||||
_priorities[static_cast<int>(level::err)] = LOG_ERR;
|
_priorities[static_cast<int>(level::err)] = LOG_ERR;
|
||||||
_priorities[static_cast<int>(level::critical)] = LOG_CRIT;
|
_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;
|
_priorities[static_cast<int>(level::off)] = LOG_INFO;
|
||||||
|
|
||||||
//set ident to be program name if empty
|
//set ident to be program name if empty
|
||||||
@ -65,7 +63,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
private:
|
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
|
//must store the ident because the man says openlog might use the pointer as is and not a string copy
|
||||||
const std::string _ident;
|
const std::string _ident;
|
||||||
|
|
||||||
|
91
vendor/spdlog/spdlog/spdlog.h
vendored
91
vendor/spdlog/spdlog/spdlog.h
vendored
@ -8,21 +8,25 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "tweakme.h"
|
#include <spdlog/tweakme.h>
|
||||||
#include "common.h"
|
#include <spdlog/common.h>
|
||||||
#include "logger.h"
|
#include <spdlog/logger.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
#include <chrono>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace spdlog
|
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);
|
std::shared_ptr<logger> get(const std::string& name);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set global formatting
|
// Set global formatting
|
||||||
// example: spdlog::set_pattern("%Y-%m-%d %H:%M:%S.%e %l : %v");
|
// 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);
|
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.
|
// Turn on async mode (off by default) and set the queue size for each async_logger.
|
||||||
// effective only for loggers created after this call.
|
// effective only for loggers created after this call.
|
||||||
@ -48,40 +57,56 @@ void set_level(level::level_enum log_level);
|
|||||||
// worker_warmup_cb (optional):
|
// worker_warmup_cb (optional):
|
||||||
// callback function that will be called in worker thread upon start (can be used to init stuff like thread affinity)
|
// 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
|
// Turn off async mode
|
||||||
void set_sync_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
|
// 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_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 std::string& filename, 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 filename_t& filename, size_t max_file_size, size_t max_files);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create file logger which creates new file on the given time (default in midnight):
|
// Create file logger which creates new file on the given time (default in midnight):
|
||||||
//
|
//
|
||||||
std::shared_ptr<logger> daily_logger_mt(const std::string& logger_name, const 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 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 filename_t& filename, int hour=0, int minute=0);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create and register stdout/stderr loggers
|
// Create and register stdout/stderr loggers
|
||||||
//
|
//
|
||||||
std::shared_ptr<logger> stdout_logger_mt(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);
|
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);
|
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);
|
std::shared_ptr<logger> stderr_logger_st(const std::string& logger_name, bool color = false);
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create and register a syslog logger
|
// 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);
|
std::shared_ptr<logger> syslog_logger(const std::string& logger_name, const std::string& ident = "", int syslog_option = 0);
|
||||||
#endif
|
#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
|
// Create and register a logger with multiple sinks
|
||||||
std::shared_ptr<logger> create(const std::string& logger_name, sinks_init_list 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
|
// 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>
|
template <typename Sink, typename... Args>
|
||||||
std::shared_ptr<spdlog::logger> create(const std::string& logger_name, Args...);
|
std::shared_ptr<spdlog::logger> create(const std::string& logger_name, Args...);
|
||||||
|
|
||||||
@ -98,32 +124,41 @@ std::shared_ptr<spdlog::logger> create(const std::string& logger_name, Args...);
|
|||||||
// Register the given logger with the given name
|
// Register the given logger with the given name
|
||||||
void register_logger(std::shared_ptr<logger> logger);
|
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
|
// Drop the reference to the given logger
|
||||||
void drop(const std::string &name);
|
void drop(const std::string &name);
|
||||||
|
|
||||||
// Drop all references
|
// Drop all references from the registry
|
||||||
void drop_all();
|
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.
|
// 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.
|
// Uncomment SPDLOG_DEBUG_ON/SPDLOG_TRACE_ON in teakme.h to enable.
|
||||||
|
// SPDLOG_TRACE(..) will also print current file and line.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
// spdlog::set_level(spdlog::level::debug);
|
// spdlog::set_level(spdlog::level::trace);
|
||||||
// SPDLOG_DEBUG(my_logger, "Some debug message {} {}", 1, 3.2);
|
// 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
|
#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
|
#else
|
||||||
#define SPDLOG_TRACE(logger, ...)
|
#define SPDLOG_TRACE(logger, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SPDLOG_DEBUG_ON
|
#ifdef SPDLOG_DEBUG_ON
|
||||||
#define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__) << " (" << __FILE__ << " #" << __LINE__ <<")";
|
#define SPDLOG_DEBUG(logger, ...) logger->debug(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define SPDLOG_DEBUG(logger, ...)
|
#define SPDLOG_DEBUG(logger, ...)
|
||||||
#endif
|
#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
|
#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.
|
// 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.
|
// 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
|
// #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.
|
// 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
|
// #define SPDLOG_NO_DATETIME
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -27,6 +35,9 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Uncomment if thread id logging is not needed (i.e. no %t in the log pattern).
|
// 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.
|
// 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
|
// #define SPDLOG_NO_THREAD_ID
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -34,12 +45,13 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Uncomment if logger name logging is not needed.
|
// Uncomment if logger name logging is not needed.
|
||||||
// This will prevent spdlog from copying the logger name on each log call.
|
// This will prevent spdlog from copying the logger name on each log call.
|
||||||
|
//
|
||||||
// #define SPDLOG_NO_NAME
|
// #define SPDLOG_NO_NAME
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// Uncomment to enable the SPDLOG_DEBUG/SPDLOG_TRACE macros.
|
// Uncomment to enable the SPDLOG_DEBUG/SPDLOG_TRACE macros.
|
||||||
|
//
|
||||||
// #define SPDLOG_DEBUG_ON
|
// #define SPDLOG_DEBUG_ON
|
||||||
// #define SPDLOG_TRACE_ON
|
// #define SPDLOG_TRACE_ON
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -49,5 +61,43 @@
|
|||||||
// Uncomment to avoid locking in the registry operations (spdlog::get(), spdlog::drop() spdlog::register()).
|
// Uncomment to avoid locking in the registry operations (spdlog::get(), spdlog::drop() spdlog::register()).
|
||||||
// Use only if your code never modifes concurrently the registry.
|
// Use only if your code never modifes concurrently the registry.
|
||||||
// Note that upon creating a logger the registry is modified by spdlog..
|
// Note that upon creating a logger the registry is modified by spdlog..
|
||||||
|
//
|
||||||
// #define SPDLOG_NO_REGISTRY_MUTEX
|
// #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