mirror of https://github.com/gabime/spdlog.git
Merged v1.x from upstream
commit
f6a5bdde65
@ -1,5 +1,4 @@
|
|||||||
executable('example', 'example.cpp', dependencies: spdlog_dep)
|
executable('example', 'example.cpp', dependencies: spdlog_dep)
|
||||||
executable('example_header_only', 'example.cpp', dependencies: spdlog_headeronly_dep)
|
executable('example_header_only', 'example.cpp', dependencies: spdlog_headeronly_dep)
|
||||||
run_command(find_program('mkdir'), meson.current_build_dir() + '/logs')
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
// Copyright(c) 2015-present, Gabi Melman & spdlog contributors.
|
||||||
|
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "spdlog/sinks/base_sink.h"
|
||||||
|
#include "spdlog/details/circular_q.h"
|
||||||
|
#include "spdlog/details/log_msg_buffer.h"
|
||||||
|
#include "spdlog/details/null_mutex.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace spdlog {
|
||||||
|
namespace sinks {
|
||||||
|
/*
|
||||||
|
* Ring buffer sink
|
||||||
|
*/
|
||||||
|
template<typename Mutex>
|
||||||
|
class ringbuffer_sink final : public base_sink<Mutex>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ringbuffer_sink(size_t n_items)
|
||||||
|
: q_{n_items}
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::vector<details::log_msg_buffer> last_raw(size_t lim = 0)
|
||||||
|
{
|
||||||
|
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
|
||||||
|
auto n_items = lim > 0 ? (std::min)(lim, q_.size()) : q_.size();
|
||||||
|
std::vector<details::log_msg_buffer> ret;
|
||||||
|
ret.reserve(n_items);
|
||||||
|
for (size_t i = 0; i < n_items; i++)
|
||||||
|
{
|
||||||
|
ret.push_back(q_.at(i));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> last_formatted(size_t lim = 0)
|
||||||
|
{
|
||||||
|
std::lock_guard<Mutex> lock(base_sink<Mutex>::mutex_);
|
||||||
|
auto n_items = lim > 0 ? (std::min)(lim, q_.size()) : q_.size();
|
||||||
|
std::vector<std::string> ret;
|
||||||
|
ret.reserve(n_items);
|
||||||
|
for (size_t i = 0; i < n_items; i++)
|
||||||
|
{
|
||||||
|
memory_buf_t formatted;
|
||||||
|
base_sink<Mutex>::formatter_->format(q_.at(i), formatted);
|
||||||
|
ret.push_back(fmt::to_string(formatted));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void sink_it_(const details::log_msg &msg) override
|
||||||
|
{
|
||||||
|
q_.push_back(details::log_msg_buffer{msg});
|
||||||
|
}
|
||||||
|
void flush_() override {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
details::circular_q<details::log_msg_buffer> q_;
|
||||||
|
};
|
||||||
|
|
||||||
|
using ringbuffer_sink_mt = ringbuffer_sink<std::mutex>;
|
||||||
|
using ringbuffer_sink_st = ringbuffer_sink<details::null_mutex>;
|
||||||
|
|
||||||
|
} // namespace sinks
|
||||||
|
|
||||||
|
} // namespace spdlog
|
@ -1,6 +1,15 @@
|
|||||||
option('external_fmt', type: 'boolean', value: false, description: 'Use external fmt package instead of the bundled')
|
option('external_fmt', type: 'boolean', value: false, description: 'Use external fmt package instead of the bundled')
|
||||||
option('enable_examples', type: 'boolean', value: true, description: 'Build examples')
|
option('enable_examples', type: 'boolean', value: true, description: 'Build examples')
|
||||||
option('enable_benchmarks', type: 'boolean', value: false, description: 'Build benchmarks')
|
option('enable_benchmarks', type: 'boolean', value: false, description: 'Build benchmarks')
|
||||||
option('enable_tests', type: 'boolean', value: false, description: 'Build tests')
|
option('enable_tests', type: 'boolean', value: true, description: 'Build tests')
|
||||||
|
option('enable_tests_ho', type: 'boolean', value: false, description: 'Build header-only tests')
|
||||||
option('library_type', type: 'combo', choices: ['static', 'shared'], value: 'static', description: 'Library build type')
|
option('library_type', type: 'combo', choices: ['static', 'shared'], value: 'static', description: 'Library build type')
|
||||||
option('no_exceptions', type: 'boolean', value: false, description: 'Disabled exceptions - abort() instead any error')
|
option('no_exceptions', type: 'boolean', value: false, description: 'Disabled exceptions - abort() instead any error')
|
||||||
|
|
||||||
|
option('wchar_support', type: 'boolean', value: false, description:'(Windows only) Support wchar api')
|
||||||
|
option('wchar_filenames', type: 'boolean', value: false, description: '(Windows only) Support wchar filenames')
|
||||||
|
option('clock_coarse', type: 'boolean', value: false, description: '(Linux only) Use the much faster (but much less accurate) CLOCK_REALTIME_COARSE instead of the regular clock')
|
||||||
|
option('prevent_child_fd', type: 'boolean', value: false, description: 'Prevent from child processes to inherit log file descriptors')
|
||||||
|
option('no_thread_id', type: 'boolean', value: false, description: 'prevent spdlog from querying the thread id on each log call if thread id is not needed')
|
||||||
|
option('no_tls', type: 'boolean', value: false, description: 'prevent spdlog from using thread local storage')
|
||||||
|
option('no_atomic_levels', type: 'boolean', value: false, description: 'prevent spdlog from using of std::atomic log levels (use only if your code never modifies log levels concurrently')
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* This content is released under the MIT License as specified in https://raw.githubusercontent.com/gabime/spdlog/master/LICENSE
|
||||||
|
*/
|
||||||
|
#include "includes.h"
|
||||||
|
|
||||||
|
using spdlog::details::os::create_dir;
|
||||||
|
using spdlog::details::os::path_exists;
|
||||||
|
|
||||||
|
bool try_create_dir(const char *path, const char *normalized_path)
|
||||||
|
{
|
||||||
|
auto rv = create_dir(path);
|
||||||
|
REQUIRE(rv == true);
|
||||||
|
return path_exists(normalized_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("create_dir", "[create_dir]")
|
||||||
|
{
|
||||||
|
prepare_logdir();
|
||||||
|
|
||||||
|
REQUIRE(try_create_dir("test_logs/dir1/dir1", "test_logs/dir1/dir1"));
|
||||||
|
REQUIRE(try_create_dir("test_logs/dir1/dir1", "test_logs/dir1/dir1")); // test existing
|
||||||
|
REQUIRE(try_create_dir("test_logs/dir1///dir2//", "test_logs/dir1/dir2"));
|
||||||
|
REQUIRE(try_create_dir("./test_logs/dir1/dir3", "test_logs/dir1/dir3"));
|
||||||
|
REQUIRE(try_create_dir("test_logs/../test_logs/dir1/dir4", "test_logs/dir1/dir4"));
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
// test backslash folder separator
|
||||||
|
REQUIRE(try_create_dir("test_logs\\dir1\\dir222", "test_logs\\dir1\\dir222"));
|
||||||
|
REQUIRE(try_create_dir("test_logs\\dir1\\dir223\\", "test_logs\\dir1\\dir223\\"));
|
||||||
|
REQUIRE(try_create_dir(".\\test_logs\\dir1\\dir2\\dir99\\..\\dir23", "test_logs\\dir1\\dir2\\dir23"));
|
||||||
|
REQUIRE(try_create_dir("test_logs\\..\\test_logs\\dir1\\dir5", "test_logs\\dir1\\dir5"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("create_invalid_dir", "[create_dir]")
|
||||||
|
{
|
||||||
|
REQUIRE(create_dir("") == false);
|
||||||
|
REQUIRE(create_dir(spdlog::filename_t{}) == false);
|
||||||
|
#ifdef __linux__
|
||||||
|
REQUIRE(create_dir("/proc/spdlog-utest") == false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("dir_name", "[create_dir]")
|
||||||
|
{
|
||||||
|
using spdlog::details::os::dir_name;
|
||||||
|
REQUIRE(dir_name("").empty());
|
||||||
|
REQUIRE(dir_name("dir").empty());
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
REQUIRE(dir_name(R"(dir\)") == "dir");
|
||||||
|
REQUIRE(dir_name(R"(dir\\\)") == R"(dir\\)");
|
||||||
|
REQUIRE(dir_name(R"(dir\file)") == "dir");
|
||||||
|
REQUIRE(dir_name(R"(dir/file)") == "dir");
|
||||||
|
REQUIRE(dir_name(R"(dir\file.txt)") == "dir");
|
||||||
|
REQUIRE(dir_name(R"(dir/file)") == "dir");
|
||||||
|
REQUIRE(dir_name(R"(dir\file.txt\)") == R"(dir\file.txt)");
|
||||||
|
REQUIRE(dir_name(R"(dir/file.txt/)") == R"(dir\file.txt)");
|
||||||
|
REQUIRE(dir_name(R"(\dir\file.txt)") == R"(\dir)");
|
||||||
|
REQUIRE(dir_name(R"(/dir/file.txt)") == R"(\dir)");
|
||||||
|
REQUIRE(dir_name(R"(\\dir\file.txt)") == R"(\\dir)");
|
||||||
|
REQUIRE(dir_name(R"(//dir/file.txt)") == R"(\\dir)");
|
||||||
|
REQUIRE(dir_name(R"(..\file.txt)") == "..");
|
||||||
|
REQUIRE(dir_name(R"(../file.txt)") == "..");
|
||||||
|
REQUIRE(dir_name(R"(.\file.txt)") == ".");
|
||||||
|
REQUIRE(dir_name(R"(./file.txt)") == ".");
|
||||||
|
REQUIRE(dir_name(R"(c:\\a\b\c\d\file.txt)") == R"(c:\\a\b\c\d)");
|
||||||
|
REQUIRE(dir_name(R"(c://a/b/c/d/file.txt)") == R"(c:\\a\b\c\d)");
|
||||||
|
#else
|
||||||
|
REQUIRE(dir_name("dir/") == "dir");
|
||||||
|
REQUIRE(dir_name("dir///") == "dir//");
|
||||||
|
REQUIRE(dir_name("dir/file") == "dir");
|
||||||
|
REQUIRE(dir_name("dir/file.txt") == "dir");
|
||||||
|
REQUIRE(dir_name("dir/file.txt/") == "dir/file.txt");
|
||||||
|
REQUIRE(dir_name("/dir/file.txt") == "/dir");
|
||||||
|
REQUIRE(dir_name("//dir/file.txt") == "//dir");
|
||||||
|
REQUIRE(dir_name("../file.txt") == "..");
|
||||||
|
REQUIRE(dir_name("./file.txt") == ".");
|
||||||
|
#endif
|
||||||
|
}
|
Loading…
Reference in New Issue