diff --git a/.clang-format b/.clang-format
index a49eace5..9560a2e3 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,7 +1,8 @@
---
-BasedOnStyle: Chromium
AlignAfterOpenBracket: AlwaysBreak
+AllowShortBlocksOnASingleLine: "Always"
AllowShortIfStatementsOnASingleLine: WithoutElse
+BasedOnStyle: Chromium
ColumnLimit: '100'
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
Cpp11BracedListStyle: 'true'
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 41dd4470..be97a596 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -11,22 +11,30 @@ jobs:
- run: sudo apt-get install ninja-build clang-19
- run: ./run.py
env:
- IRIS_CXX_COMPILER: clang++-19
+ CXX: clang++-19
- uses: pre-commit/action@v3.0.0
- unit_tests:
+ gcc_unit_tests:
+ runs-on: ubuntu-24.04
+ steps:
+ - uses: actions/checkout@v4
+ - run: sudo apt-get install ninja-build g++-14
+ - run: ./run.py test
+ env:
+ CXX: /usr/bin/g++-14
+ clang_unit_tests:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- run: sudo apt-get install clang-19
- run: ./run.py test
env:
- IRIS_CXX_COMPILER: clang++-19
+ CXX: clang++-19
integration_tests:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- - run: sudo apt-get install clang-19
+ - run: sudo apt-get install ninja-build g++-14
- run: ./run.py test -I
env:
+ CXX: /usr/bin/g++-14
PYTEST_ADDOPTS: "--color=yes"
- IRIS_CXX_COMPILER: clang++-19
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index fca2de7d..c435a058 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -13,7 +13,7 @@ repos:
exclude: "tests/fixture/no_newline_file.txt"
- id: trailing-whitespace
- repo: https://github.com/pre-commit/mirrors-clang-format
- rev: v21.1.2
+ rev: v21.1.8
hooks:
- id: clang-format
exclude: ".json"
@@ -31,19 +31,28 @@ repos:
rev: v4.0.0
hooks:
- id: add-trailing-comma
+ - repo: https://github.com/hhatto/autopep8
+ rev: v2.3.2
+ hooks:
+ - id: autopep8
+ args: [--in-place, --max-line-length=100]
- repo: https://github.com/PyCQA/flake8
rev: 7.3.0
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: v1.18.2
+ rev: v1.19.1
hooks:
- id: mypy
- repo: https://github.com/rhysd/actionlint
- rev: v1.7.8
+ rev: v1.7.10
hooks:
- id: actionlint
- repo: https://github.com/sco1/brie-commit
rev: v1.1.0
hooks:
- id: brie-commit
+ - repo: https://github.com/GideonBear/pre-comet
+ rev: v1.0.0
+ hooks:
+ - id: pre-comet
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b25d60ca..7526d2b3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,9 +9,20 @@
* Ensure the block cursor is restored when iris is closed
* Refactored how `;s` works for find and replace
* Added `;f` command to find a given string further on in the buffer
+* Use `wqa` to save and close all files
+* Iris now handles horizontal scrolling when a line is longer than the screen
+* Pressing backspace at the end of a tab width's worth of whitespace now
+moves back that amount of space
+* Allow for specifying file to save to from command bar
+* `e` key now moves cursor to end of the current word
* Resolved issue with iris crashing after opening an existing file with 0 bytes
* Resolved issue where filename isn't centered in the status bar
+* Resolved issue with `ctrl+bspace` inserting an `h`
+* Resolved issue where the cursor would stay in the command bar when escaping
+out of it
+* Resolved issue where iris wouldn't resize after SIGCONT if the terminal had
+been resized while backgrounded
### v0.0.2
* Added ability to jump to a line number entered as a command: `;42`
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 838458e0..dbd86539 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,4 @@
cmake_minimum_required(VERSION 3.22.0)
-set(CMAKE_CXX_COMPILER "/usr/bin/clang++")
project(iris LANGUAGES CXX)
option(RUN_TESTS "Run unit tests" OFF)
@@ -21,7 +20,6 @@ add_compile_options(-Wall)
add_compile_options(-Wextra)
add_compile_options(-pedantic)
add_compile_options(-Wconversion)
-add_compile_options(-Wno-implicit-int-float-conversion)
add_compile_options(-Wimplicit-fallthrough)
if(ENABLE_ASAN)
diff --git a/README.md b/README.md
index 003b513b..f6527c31 100644
--- a/README.md
+++ b/README.md
@@ -44,7 +44,8 @@ perform the following actions (alphabetically ordered):
| b | Move cursor back one word |
| dl | Delete the current line |
| dw | Delete the current word |
-| f | Find next entered char ahead in file |
+| e | Find next entered char ahead in file |
+| f | Move cursor to end of current word |
| F | Find next entered char back in file |
| g | Go to top of file |
| G | Go to bottom of file |
@@ -92,6 +93,7 @@ following commands in alphabetical order are available:
| `;w` | Save file |
| `;wa` | Save all files |
| `;qa` | Quit all |
+| `;wqa` | Write and quit all files |
Search flags for `;s` include:
* `m` Multiline search
diff --git a/cmake/ci_toolchain.cmake b/cmake/ci_toolchain.cmake
deleted file mode 100644
index 9d699efd..00000000
--- a/cmake/ci_toolchain.cmake
+++ /dev/null
@@ -1,2 +0,0 @@
-set(CMAKE_CXX_COMPILER "/usr/bin/clang++-19")
-set(CMAKE_C_COMPILER "/usr/bin/clang-19")
diff --git a/include/README.md b/include/README.md
index e2ce5fc6..49b6b279 100644
--- a/include/README.md
+++ b/include/README.md
@@ -4,3 +4,10 @@
- `cmake -S . - B build && cmake --build build`
- Install it to this repo
- `cmake --install build --prefix ../iris/include/catch2`
+
+### SPDLOG
+- Clone the git repo: `git@github.com:gabime/spdlog.git` and checkout the git tag
+ - Currently, git commit `32dd298d` is used as the latest tag (v1.16.0) does
+ not work with clang21
+- copy `spdlog/include/spdlog` to `iris/include/spdlog`
+
diff --git a/include/spdlog/async.h b/include/spdlog/async.h
index fa99bb7e..92fcd9a7 100644
--- a/include/spdlog/async.h
+++ b/include/spdlog/async.h
@@ -14,88 +14,86 @@
// This is because each message in the queue holds a shared_ptr to the
// originating logger.
-#include
-#include
-#include
-
#include
#include
#include
-namespace spdlog {
-
- namespace details {
- static const size_t default_async_q_size = 8192;
- }
-
- // async logger factory - creates async loggers backed with thread pool.
- // if a global thread pool doesn't already exist, create it with default queue
- // size of 8192 items and single thread.
- template
- struct async_factory_impl {
- template
- static std::shared_ptr create(std::string logger_name, SinkArgs&&... args) {
- auto& registry_inst = details::registry::instance();
-
- // create global thread pool if not already exists..
-
- auto& mutex = registry_inst.tp_mutex();
- std::lock_guard tp_lock(mutex);
- auto tp = registry_inst.get_tp();
- if (tp == nullptr) {
- tp = std::make_shared(details::default_async_q_size, 1U);
- registry_inst.set_tp(tp);
- }
-
- auto sink = std::make_shared(std::forward(args)...);
- auto new_logger = std::make_shared(
- std::move(logger_name), std::move(sink), std::move(tp), OverflowPolicy);
- registry_inst.initialize_logger(new_logger);
- return new_logger;
- }
- };
+#include
+#include
+#include
- using async_factory = async_factory_impl;
- using async_factory_nonblock = async_factory_impl;
+namespace spdlog {
- template
- inline std::shared_ptr create_async(
- std::string logger_name,
- SinkArgs&&... sink_args) {
- return async_factory::create(
- std::move(logger_name), std::forward(sink_args)...);
- }
+namespace details {
+static const size_t default_async_q_size = 8192;
+}
+// async logger factory - creates async loggers backed with thread pool.
+// if a global thread pool doesn't already exist, create it with default queue
+// size of 8192 items and single thread.
+template
+struct async_factory_impl {
template
- inline std::shared_ptr create_async_nb(
- std::string logger_name,
- SinkArgs&&... sink_args) {
- return async_factory_nonblock::create(
- std::move(logger_name), std::forward(sink_args)...);
- }
+ static std::shared_ptr create(std::string logger_name, SinkArgs &&...args) {
+ auto ®istry_inst = details::registry::instance();
- // set global thread pool.
- inline void init_thread_pool(
- size_t q_size,
- size_t thread_count,
- std::function on_thread_start,
- std::function on_thread_stop) {
- auto tp = std::make_shared(
- q_size, thread_count, on_thread_start, on_thread_stop);
- details::registry::instance().set_tp(std::move(tp));
- }
-
- inline void
- init_thread_pool(size_t q_size, size_t thread_count, std::function on_thread_start) {
- init_thread_pool(q_size, thread_count, on_thread_start, [] {});
- }
+ // create global thread pool if not already exists..
- inline void init_thread_pool(size_t q_size, size_t thread_count) {
- init_thread_pool(q_size, thread_count, [] {}, [] {});
- }
+ auto &mutex = registry_inst.tp_mutex();
+ std::lock_guard tp_lock(mutex);
+ auto tp = registry_inst.get_tp();
+ if (tp == nullptr) {
+ tp = std::make_shared(details::default_async_q_size, 1U);
+ registry_inst.set_tp(tp);
+ }
- // get the global thread pool.
- inline std::shared_ptr thread_pool() {
- return details::registry::instance().get_tp();
+ auto sink = std::make_shared(std::forward(args)...);
+ auto new_logger = std::make_shared(std::move(logger_name), std::move(sink),
+ std::move(tp), OverflowPolicy);
+ registry_inst.initialize_logger(new_logger);
+ return new_logger;
}
+};
+
+using async_factory = async_factory_impl;
+using async_factory_nonblock = async_factory_impl;
+
+template
+inline std::shared_ptr create_async(std::string logger_name,
+ SinkArgs &&...sink_args) {
+ return async_factory::create(std::move(logger_name),
+ std::forward(sink_args)...);
+}
+
+template
+inline std::shared_ptr create_async_nb(std::string logger_name,
+ SinkArgs &&...sink_args) {
+ return async_factory_nonblock::create(std::move(logger_name),
+ std::forward(sink_args)...);
+}
+
+// set global thread pool.
+inline void init_thread_pool(size_t q_size,
+ size_t thread_count,
+ std::function on_thread_start,
+ std::function on_thread_stop) {
+ auto tp = std::make_shared(q_size, thread_count, on_thread_start,
+ on_thread_stop);
+ details::registry::instance().set_tp(std::move(tp));
+}
+
+inline void init_thread_pool(size_t q_size,
+ size_t thread_count,
+ std::function on_thread_start) {
+ init_thread_pool(q_size, thread_count, on_thread_start, [] {});
+}
+
+inline void init_thread_pool(size_t q_size, size_t thread_count) {
+ init_thread_pool(q_size, thread_count, [] {}, [] {});
+}
+
+// get the global thread pool.
+inline std::shared_ptr thread_pool() {
+ return details::registry::instance().get_tp();
+}
} // namespace spdlog
diff --git a/include/spdlog/async_logger-inl.h b/include/spdlog/async_logger-inl.h
index 58241062..cde73f90 100644
--- a/include/spdlog/async_logger-inl.h
+++ b/include/spdlog/async_logger-inl.h
@@ -7,38 +7,32 @@
#include
#endif
-#include
-#include
-
#include
#include
-SPDLOG_INLINE spdlog::async_logger::async_logger(
- std::string logger_name,
- sinks_init_list sinks_list,
- std::weak_ptr tp,
- async_overflow_policy overflow_policy)
- : async_logger(
- std::move(logger_name),
- sinks_list.begin(),
- sinks_list.end(),
- std::move(tp),
- overflow_policy) {}
+#include
+#include
-SPDLOG_INLINE spdlog::async_logger::async_logger(
- std::string logger_name,
- sink_ptr single_sink,
- std::weak_ptr tp,
- async_overflow_policy overflow_policy)
+SPDLOG_INLINE spdlog::async_logger::async_logger(std::string logger_name,
+ sinks_init_list sinks_list,
+ std::weak_ptr tp,
+ async_overflow_policy overflow_policy)
+ : async_logger(std::move(logger_name),
+ sinks_list.begin(),
+ sinks_list.end(),
+ std::move(tp),
+ overflow_policy) {}
+
+SPDLOG_INLINE spdlog::async_logger::async_logger(std::string logger_name,
+ sink_ptr single_sink,
+ std::weak_ptr tp,
+ async_overflow_policy overflow_policy)
: async_logger(
- std::move(logger_name),
- {std::move(single_sink)},
- std::move(tp),
- overflow_policy) {}
+ std::move(logger_name), {std::move(single_sink)}, std::move(tp), overflow_policy) {}
// send the log message to the thread pool
-SPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg& msg) {
- SPDLOG_TRY {if (auto pool_ptr = thread_pool_.lock()) {
+SPDLOG_INLINE void spdlog::async_logger::sink_it_(const details::log_msg &msg){
+ SPDLOG_TRY{if (auto pool_ptr = thread_pool_.lock()){
pool_ptr -> post_log(shared_from_this(), msg, overflow_policy_);
}
else {
@@ -49,8 +43,8 @@ SPDLOG_LOGGER_CATCH(msg.source)
}
// send flush request to the thread pool
-SPDLOG_INLINE void spdlog::async_logger::flush_() {
- SPDLOG_TRY {if (auto pool_ptr = thread_pool_.lock()) {
+SPDLOG_INLINE void spdlog::async_logger::flush_(){
+ SPDLOG_TRY{if (auto pool_ptr = thread_pool_.lock()){
pool_ptr -> post_flush(shared_from_this(), overflow_policy_);
}
else {
@@ -63,12 +57,10 @@ SPDLOG_LOGGER_CATCH(source_loc())
//
// backend functions - called from the thread pool to do the actual job
//
-SPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg& msg) {
- for (auto& sink : sinks_) {
+SPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg &msg) {
+ for (auto &sink : sinks_) {
if (sink->should_log(msg.level)) {
- SPDLOG_TRY {
- sink->log(msg);
- }
+ SPDLOG_TRY { sink->log(msg); }
SPDLOG_LOGGER_CATCH(msg.source)
}
}
@@ -79,10 +71,8 @@ SPDLOG_INLINE void spdlog::async_logger::backend_sink_it_(const details::log_msg
}
SPDLOG_INLINE void spdlog::async_logger::backend_flush_() {
- for (auto& sink : sinks_) {
- SPDLOG_TRY {
- sink->flush();
- }
+ for (auto &sink : sinks_) {
+ SPDLOG_TRY { sink->flush(); }
SPDLOG_LOGGER_CATCH(source_loc())
}
}
diff --git a/include/spdlog/async_logger.h b/include/spdlog/async_logger.h
index 1ccc4f0e..be361538 100644
--- a/include/spdlog/async_logger.h
+++ b/include/spdlog/async_logger.h
@@ -18,58 +18,55 @@
namespace spdlog {
- // Async overflow policy - block by default.
- enum class async_overflow_policy {
- block, // Block until message can be enqueued
- overrun_oldest, // Discard oldest message in the queue if full when trying to
- // add new item.
- discard_new // Discard new message if the queue is full when trying to add new item.
- };
+// Async overflow policy - block by default.
+enum class async_overflow_policy {
+ block, // Block until message can be enqueued
+ overrun_oldest, // Discard oldest message in the queue if full when trying to
+ // add new item.
+ discard_new // Discard new message if the queue is full when trying to add new item.
+};
- namespace details {
- class thread_pool;
- }
+namespace details {
+class thread_pool;
+}
- class SPDLOG_API async_logger final : public std::enable_shared_from_this,
- public logger {
- friend class details::thread_pool;
+class SPDLOG_API async_logger final : public std::enable_shared_from_this,
+ public logger {
+ friend class details::thread_pool;
- public:
- template
- async_logger(
- std::string logger_name,
- It begin,
- It end,
- std::weak_ptr tp,
- async_overflow_policy overflow_policy = async_overflow_policy::block)
- : logger(std::move(logger_name), begin, end),
- thread_pool_(std::move(tp)),
- overflow_policy_(overflow_policy) {}
+public:
+ template
+ async_logger(std::string logger_name,
+ It begin,
+ It end,
+ std::weak_ptr tp,
+ async_overflow_policy overflow_policy = async_overflow_policy::block)
+ : logger(std::move(logger_name), begin, end),
+ thread_pool_(std::move(tp)),
+ overflow_policy_(overflow_policy) {}
- async_logger(
- std::string logger_name,
- sinks_init_list sinks_list,
- std::weak_ptr tp,
- async_overflow_policy overflow_policy = async_overflow_policy::block);
+ async_logger(std::string logger_name,
+ sinks_init_list sinks_list,
+ std::weak_ptr tp,
+ async_overflow_policy overflow_policy = async_overflow_policy::block);
- async_logger(
- std::string logger_name,
- sink_ptr single_sink,
- std::weak_ptr tp,
- async_overflow_policy overflow_policy = async_overflow_policy::block);
+ async_logger(std::string logger_name,
+ sink_ptr single_sink,
+ std::weak_ptr tp,
+ async_overflow_policy overflow_policy = async_overflow_policy::block);
- std::shared_ptr clone(std::string new_name) override;
+ std::shared_ptr clone(std::string new_name) override;
- protected:
- void sink_it_(const details::log_msg& msg) override;
- void flush_() override;
- void backend_sink_it_(const details::log_msg& incoming_log_msg);
- void backend_flush_();
+protected:
+ void sink_it_(const details::log_msg &msg) override;
+ void flush_() override;
+ void backend_sink_it_(const details::log_msg &incoming_log_msg);
+ void backend_flush_();
- private:
- std::weak_ptr thread_pool_;
- async_overflow_policy overflow_policy_;
- };
+private:
+ std::weak_ptr thread_pool_;
+ async_overflow_policy overflow_policy_;
+};
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
diff --git a/include/spdlog/cfg/argv.h b/include/spdlog/cfg/argv.h
index a72612ca..7de2f83e 100644
--- a/include/spdlog/cfg/argv.h
+++ b/include/spdlog/cfg/argv.h
@@ -18,23 +18,23 @@
// example.exe "SPDLOG_LEVEL=off,logger1=debug,logger2=info"
namespace spdlog {
- namespace cfg {
-
- // search for SPDLOG_LEVEL= in the args and use it to init the levels
- inline void load_argv_levels(int argc, const char** argv) {
- const std::string spdlog_level_prefix = "SPDLOG_LEVEL=";
- for (int i = 1; i < argc; i++) {
- std::string arg = argv[i];
- if (arg.find(spdlog_level_prefix) == 0) {
- auto levels_string = arg.substr(spdlog_level_prefix.size());
- helpers::load_levels(levels_string);
- }
- }
+namespace cfg {
+
+// search for SPDLOG_LEVEL= in the args and use it to init the levels
+inline void load_argv_levels(int argc, const char **argv) {
+ const std::string spdlog_level_prefix = "SPDLOG_LEVEL=";
+ for (int i = 1; i < argc; i++) {
+ std::string arg = argv[i];
+ if (arg.find(spdlog_level_prefix) == 0) {
+ auto levels_string = arg.substr(spdlog_level_prefix.size());
+ helpers::load_levels(levels_string);
}
+ }
+}
- inline void load_argv_levels(int argc, char** argv) {
- load_argv_levels(argc, const_cast(argv));
- }
+inline void load_argv_levels(int argc, char **argv) {
+ load_argv_levels(argc, const_cast(argv));
+}
- } // namespace cfg
+} // namespace cfg
} // namespace spdlog
diff --git a/include/spdlog/cfg/env.h b/include/spdlog/cfg/env.h
index 3c8cddf2..47bf61c7 100644
--- a/include/spdlog/cfg/env.h
+++ b/include/spdlog/cfg/env.h
@@ -24,13 +24,13 @@
// export SPDLOG_LEVEL="off,logger1=debug,logger2=info"
namespace spdlog {
- namespace cfg {
- inline void load_env_levels() {
- auto env_val = details::os::getenv("SPDLOG_LEVEL");
- if (!env_val.empty()) {
- helpers::load_levels(env_val);
- }
- }
+namespace cfg {
+inline void load_env_levels(const char* var = "SPDLOG_LEVEL") {
+ auto env_val = details::os::getenv(var);
+ if (!env_val.empty()) {
+ helpers::load_levels(env_val);
+ }
+}
- } // namespace cfg
+} // namespace cfg
} // namespace spdlog
diff --git a/include/spdlog/cfg/helpers-inl.h b/include/spdlog/cfg/helpers-inl.h
index 5b2e6652..6ed86955 100644
--- a/include/spdlog/cfg/helpers-inl.h
+++ b/include/spdlog/cfg/helpers-inl.h
@@ -7,104 +7,100 @@
#include
#endif
+#include
+#include
+
#include
#include
#include
#include
-#include
-#include
-#include
-
namespace spdlog {
- namespace cfg {
- namespace helpers {
+namespace cfg {
+namespace helpers {
- // inplace convert to lowercase
- inline std::string& to_lower_(std::string& str) {
- std::transform(str.begin(), str.end(), str.begin(), [](char ch) {
- return static_cast((ch >= 'A' && ch <= 'Z') ? ch + ('a' - 'A') : ch);
- });
- return str;
- }
+// inplace convert to lowercase
+inline std::string &to_lower_(std::string &str) {
+ std::transform(str.begin(), str.end(), str.begin(), [](char ch) {
+ return static_cast((ch >= 'A' && ch <= 'Z') ? ch + ('a' - 'A') : ch);
+ });
+ return str;
+}
- // inplace trim spaces
- inline std::string& trim_(std::string& str) {
- const char* spaces = " \n\r\t";
- str.erase(str.find_last_not_of(spaces) + 1);
- str.erase(0, str.find_first_not_of(spaces));
- return str;
- }
+// inplace trim spaces
+inline std::string &trim_(std::string &str) {
+ const char *spaces = " \n\r\t";
+ str.erase(str.find_last_not_of(spaces) + 1);
+ str.erase(0, str.find_first_not_of(spaces));
+ return str;
+}
- // return (name,value) trimmed pair from given "name=value" string.
- // return empty string on missing parts
- // "key=val" => ("key", "val")
- // " key = val " => ("key", "val")
- // "key=" => ("key", "")
- // "val" => ("", "val")
+// return (name,value) trimmed pair from the given "name = value" string.
+// return empty string on missing parts
+// "key=val" => ("key", "val")
+// " key = val " => ("key", "val")
+// "key=" => ("key", "")
+// "val" => ("", "val")
- inline std::pair extract_kv_(
- char sep,
- const std::string& str) {
- auto n = str.find(sep);
- std::string k, v;
- if (n == std::string::npos) {
- v = str;
- } else {
- k = str.substr(0, n);
- v = str.substr(n + 1);
- }
- return std::make_pair(trim_(k), trim_(v));
- }
+inline std::pair extract_kv_(char sep, const std::string &str) {
+ auto n = str.find(sep);
+ std::string k, v;
+ if (n == std::string::npos) {
+ v = str;
+ } else {
+ k = str.substr(0, n);
+ v = str.substr(n + 1);
+ }
+ return std::make_pair(trim_(k), trim_(v));
+}
- // return vector of key/value pairs from sequence of "K1=V1,K2=V2,.."
- // "a=AAA,b=BBB,c=CCC,.." => {("a","AAA"),("b","BBB"),("c", "CCC"),...}
- inline std::unordered_map extract_key_vals_(
- const std::string& str) {
- std::string token;
- std::istringstream token_stream(str);
- std::unordered_map rv {};
- while (std::getline(token_stream, token, ',')) {
- if (token.empty()) {
- continue;
- }
- auto kv = extract_kv_('=', token);
- rv[kv.first] = kv.second;
- }
- return rv;
- }
+// return vector of key/value pairs from a sequence of "K1=V1,K2=V2,.."
+// "a=AAA,b=BBB,c=CCC,.." => {("a","AAA"),("b","BBB"),("c", "CCC"),...}
+inline std::unordered_map extract_key_vals_(const std::string &str) {
+ std::string token;
+ std::istringstream token_stream(str);
+ std::unordered_map rv{};
+ while (std::getline(token_stream, token, ',')) {
+ if (token.empty()) {
+ continue;
+ }
+ auto kv = extract_kv_('=', token);
+ rv[kv.first] = kv.second;
+ }
+ return rv;
+}
- SPDLOG_INLINE void load_levels(const std::string& input) {
- if (input.empty() || input.size() > 512) {
- return;
- }
+SPDLOG_INLINE void load_levels(const std::string &input) {
+ if (input.empty() || input.size() >= 32768) {
+ return;
+ }
- auto key_vals = extract_key_vals_(input);
- std::unordered_map levels;
- level::level_enum global_level = level::info;
- bool global_level_found = false;
+ auto key_vals = extract_key_vals_(input);
+ std::unordered_map levels;
+ level::level_enum global_level = level::info;
+ bool global_level_found = false;
- for (auto& name_level : key_vals) {
- auto& logger_name = name_level.first;
- auto level_name = to_lower_(name_level.second);
- auto level = level::from_str(level_name);
- // ignore unrecognized level names
- if (level == level::off && level_name != "off") {
- continue;
- }
- if (logger_name.empty()) // no logger name indicate global level
- {
- global_level_found = true;
- global_level = level;
- } else {
- levels[logger_name] = level;
- }
- }
+ for (auto &name_level : key_vals) {
+ const auto &logger_name = name_level.first;
+ const auto &level_name = to_lower_(name_level.second);
+ auto level = level::from_str(level_name);
+ // ignore unrecognized level names
+ if (level == level::off && level_name != "off") {
+ continue;
+ }
+ if (logger_name.empty()) // no logger name indicates global level
+ {
+ global_level_found = true;
+ global_level = level;
+ } else {
+ levels[logger_name] = level;
+ }
+ }
- details::registry::instance().set_levels(
- std::move(levels), global_level_found ? &global_level : nullptr);
- }
+ details::registry::instance().set_levels(std::move(levels),
+ global_level_found ? &global_level : nullptr);
+}
- } // namespace helpers
- } // namespace cfg
+} // namespace helpers
+} // namespace cfg
} // namespace spdlog
diff --git a/include/spdlog/cfg/helpers.h b/include/spdlog/cfg/helpers.h
index fdf6a098..d09a1e97 100644
--- a/include/spdlog/cfg/helpers.h
+++ b/include/spdlog/cfg/helpers.h
@@ -3,26 +3,25 @@
#pragma once
-#include
-
#include
+#include
namespace spdlog {
- namespace cfg {
- namespace helpers {
- //
- // Init levels from given string
- //
- // Examples:
- //
- // set global level to debug: "debug"
- // turn off all logging except for logger1: "off,logger1=debug"
- // turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info"
- //
- SPDLOG_API void load_levels(const std::string& txt);
- } // namespace helpers
+namespace cfg {
+namespace helpers {
+//
+// Init levels from given string
+//
+// Examples:
+//
+// set global level to debug: "debug"
+// turn off all logging except for logger1: "off,logger1=debug"
+// turn off all logging except for logger1 and logger2: "off,logger1=debug,logger2=info"
+//
+SPDLOG_API void load_levels(const std::string &txt);
+} // namespace helpers
- } // namespace cfg
+} // namespace cfg
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
diff --git a/include/spdlog/common-inl.h b/include/spdlog/common-inl.h
index 95e8f03f..f35901c5 100644
--- a/include/spdlog/common-inl.h
+++ b/include/spdlog/common-inl.h
@@ -11,63 +11,58 @@
#include
namespace spdlog {
- namespace level {
+namespace level {
#if __cplusplus >= 201703L
- constexpr
+constexpr
#endif
- static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES;
-
- static const char* short_level_names[] SPDLOG_SHORT_LEVEL_NAMES;
-
- SPDLOG_INLINE const string_view_t& to_string_view(spdlog::level::level_enum l)
- SPDLOG_NOEXCEPT {
- return level_string_views[l];
- }
-
- SPDLOG_INLINE const char* to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT {
- return short_level_names[l];
- }
-
- SPDLOG_INLINE spdlog::level::level_enum from_str(const std::string& name) SPDLOG_NOEXCEPT {
- auto it = std::find(std::begin(level_string_views), std::end(level_string_views), name);
- if (it != std::end(level_string_views))
- return static_cast(
- std::distance(std::begin(level_string_views), it));
-
- // check also for "warn" and "err" before giving up..
- if (name == "warn") {
- return level::warn;
- }
- if (name == "err") {
- return level::err;
- }
- return level::off;
- }
- } // namespace level
-
- SPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg) : msg_(std::move(msg)) {}
-
- SPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string& msg, int last_errno) {
+ static string_view_t level_string_views[] SPDLOG_LEVEL_NAMES;
+
+static const char *short_level_names[] SPDLOG_SHORT_LEVEL_NAMES;
+
+SPDLOG_INLINE const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT {
+ return level_string_views[l];
+}
+
+SPDLOG_INLINE const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT {
+ return short_level_names[l];
+}
+
+SPDLOG_INLINE spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT {
+ auto it = std::find(std::begin(level_string_views), std::end(level_string_views), name);
+ if (it != std::end(level_string_views))
+ return static_cast(std::distance(std::begin(level_string_views), it));
+
+ // check also for "warn" and "err" before giving up..
+ if (name == "warn") {
+ return level::warn;
+ }
+ if (name == "err") {
+ return level::err;
+ }
+ return level::off;
+}
+} // namespace level
+
+SPDLOG_INLINE spdlog_ex::spdlog_ex(std::string msg)
+ : msg_(std::move(msg)) {}
+
+SPDLOG_INLINE spdlog_ex::spdlog_ex(const std::string &msg, int last_errno) {
#ifdef SPDLOG_USE_STD_FORMAT
- msg_ = std::system_error(std::error_code(last_errno, std::generic_category()), msg).what();
+ msg_ = std::system_error(std::error_code(last_errno, std::generic_category()), msg).what();
#else
- memory_buf_t outbuf;
- fmt::format_system_error(outbuf, last_errno, msg.c_str());
- msg_ = fmt::to_string(outbuf);
+ memory_buf_t outbuf;
+ fmt::format_system_error(outbuf, last_errno, msg.c_str());
+ msg_ = fmt::to_string(outbuf);
#endif
- }
+}
- SPDLOG_INLINE const char* spdlog_ex::what() const SPDLOG_NOEXCEPT {
- return msg_.c_str();
- }
+SPDLOG_INLINE const char *spdlog_ex::what() const SPDLOG_NOEXCEPT { return msg_.c_str(); }
- SPDLOG_INLINE void throw_spdlog_ex(const std::string& msg, int last_errno) {
- SPDLOG_THROW(spdlog_ex(msg, last_errno));
- }
+SPDLOG_INLINE void throw_spdlog_ex(const std::string &msg, int last_errno) {
+ SPDLOG_THROW(spdlog_ex(msg, last_errno));
+}
- SPDLOG_INLINE void throw_spdlog_ex(std::string msg) {
- SPDLOG_THROW(spdlog_ex(std::move(msg)));
- }
+SPDLOG_INLINE void throw_spdlog_ex(std::string msg) { SPDLOG_THROW(spdlog_ex(std::move(msg))); }
} // namespace spdlog
diff --git a/include/spdlog/common.h b/include/spdlog/common.h
index 98b12399..20dbca45 100644
--- a/include/spdlog/common.h
+++ b/include/spdlog/common.h
@@ -3,6 +3,9 @@
#pragma once
+#include
+#include
+
#include
#include
#include
@@ -13,9 +16,6 @@
#include
#include
-#include
-#include
-
#ifdef SPDLOG_USE_STD_FORMAT
#include
#if __cpp_lib_format >= 202207L
@@ -101,7 +101,7 @@
#endif
#ifndef SPDLOG_FUNCTION
-#define SPDLOG_FUNCTION static_cast(__FUNCTION__)
+#define SPDLOG_FUNCTION static_cast(__FUNCTION__)
#endif
#ifdef SPDLOG_NO_EXCEPTIONS
@@ -115,99 +115,97 @@
#else
#define SPDLOG_TRY try
#define SPDLOG_THROW(ex) throw(ex)
-#define SPDLOG_CATCH_STD \
- catch (const std::exception&) { \
+#define SPDLOG_CATCH_STD \
+ catch (const std::exception &) { \
}
#endif
namespace spdlog {
- class formatter;
+class formatter;
- namespace sinks {
- class sink;
- }
+namespace sinks {
+class sink;
+}
#if defined(_WIN32) && defined(SPDLOG_WCHAR_FILENAMES)
- using filename_t = std::wstring;
+using filename_t = std::wstring;
// allow macro expansion to occur in SPDLOG_FILENAME_T
#define SPDLOG_FILENAME_T_INNER(s) L##s
#define SPDLOG_FILENAME_T(s) SPDLOG_FILENAME_T_INNER(s)
#else
- using filename_t = std::string;
+using filename_t = std::string;
#define SPDLOG_FILENAME_T(s) s
#endif
- using log_clock = std::chrono::system_clock;
- using sink_ptr = std::shared_ptr;
- using sinks_init_list = std::initializer_list;
- using err_handler = std::function;
+using log_clock = std::chrono::system_clock;
+using sink_ptr = std::shared_ptr;
+using sinks_init_list = std::initializer_list;
+using err_handler = std::function;
#ifdef SPDLOG_USE_STD_FORMAT
- namespace fmt_lib = std;
+namespace fmt_lib = std;
- using string_view_t = std::string_view;
- using memory_buf_t = std::string;
+using string_view_t = std::string_view;
+using memory_buf_t = std::string;
- template
+template
#if __cpp_lib_format >= 202207L
- using format_string_t = std::format_string;
+using format_string_t = std::format_string;
#else
- using format_string_t = std::string_view;
+using format_string_t = std::string_view;
#endif
- template
- struct is_convertible_to_basic_format_string
- : std::
- integral_constant>::value> {
- };
+template
+struct is_convertible_to_basic_format_string
+ : std::integral_constant>::value> {};
#if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
- using wstring_view_t = std::wstring_view;
- using wmemory_buf_t = std::wstring;
+using wstring_view_t = std::wstring_view;
+using wmemory_buf_t = std::wstring;
- template
+template
#if __cpp_lib_format >= 202207L
- using wformat_string_t = std::wformat_string;
+using wformat_string_t = std::wformat_string;
#else
- using wformat_string_t = std::wstring_view;
+using wformat_string_t = std::wstring_view;
#endif
#endif
#define SPDLOG_BUF_TO_STRING(x) x
#else // use fmt lib instead of std::format
- namespace fmt_lib = fmt;
+namespace fmt_lib = fmt;
- using string_view_t = fmt::basic_string_view;
- using memory_buf_t = fmt::basic_memory_buffer;
+using string_view_t = fmt::basic_string_view;
+using memory_buf_t = fmt::basic_memory_buffer;
- template
- using format_string_t = fmt::format_string;
+template
+using format_string_t = fmt::format_string;
- template
- using remove_cvref_t = typename std::remove_cv::type>::type;
+template
+using remove_cvref_t = typename std::remove_cv::type>::type;
- template
+template
#if FMT_VERSION >= 90101
- using fmt_runtime_string = fmt::runtime_format_string;
+using fmt_runtime_string = fmt::runtime_format_string;
#else
- using fmt_runtime_string = fmt::basic_runtime;
+using fmt_runtime_string = fmt::basic_runtime;
#endif
- // clang doesn't like SFINAE disabled constructor in std::is_convertible<> so have to repeat the
- // condition from basic_format_string here, in addition, fmt::basic_runtime is only
- // convertible to basic_format_string but not basic_string_view
- template
- struct is_convertible_to_basic_format_string
- : std::integral_constant<
- bool,
- std::is_convertible>::value ||
- std::is_same, fmt_runtime_string>::value> {};
+// clang doesn't like SFINAE disabled constructor in std::is_convertible<> so have to repeat the
+// condition from basic_format_string here, in addition, fmt::basic_runtime is only
+// convertible to basic_format_string but not basic_string_view
+template
+struct is_convertible_to_basic_format_string
+ : std::integral_constant>::value ||
+ std::is_same, fmt_runtime_string>::value> {
+};
#if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
- using wstring_view_t = fmt::basic_string_view;
- using wmemory_buf_t = fmt::basic_memory_buffer;
+using wstring_view_t = fmt::basic_string_view;
+using wmemory_buf_t = fmt::basic_memory_buffer;
- template
- using wformat_string_t = fmt::wformat_string;
+template
+using wformat_string_t = fmt::wformat_string;
#endif
#define SPDLOG_BUF_TO_STRING(x) fmt::to_string(x)
#endif
@@ -218,17 +216,16 @@ namespace spdlog {
#endif // _WIN32
#endif // SPDLOG_WCHAR_TO_UTF8_SUPPORT
- template
- struct is_convertible_to_any_format_string
- : std::integral_constant<
- bool,
- is_convertible_to_basic_format_string::value ||
- is_convertible_to_basic_format_string::value> {};
+template
+struct is_convertible_to_any_format_string
+ : std::integral_constant::value ||
+ is_convertible_to_basic_format_string::value> {};
#if defined(SPDLOG_NO_ATOMIC_LEVELS)
- using level_t = details::null_atomic_int;
+using level_t = details::null_atomic_int;
#else
- using level_t = std::atomic;
+using level_t = std::atomic;
#endif
#define SPDLOG_LEVEL_TRACE 0
@@ -243,18 +240,18 @@ namespace spdlog {
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
#endif
- // Log level enum
- namespace level {
- enum level_enum : int {
- trace = SPDLOG_LEVEL_TRACE,
- debug = SPDLOG_LEVEL_DEBUG,
- info = SPDLOG_LEVEL_INFO,
- warn = SPDLOG_LEVEL_WARN,
- err = SPDLOG_LEVEL_ERROR,
- critical = SPDLOG_LEVEL_CRITICAL,
- off = SPDLOG_LEVEL_OFF,
- n_levels
- };
+// Log level enum
+namespace level {
+enum level_enum : int {
+ trace = SPDLOG_LEVEL_TRACE,
+ debug = SPDLOG_LEVEL_DEBUG,
+ info = SPDLOG_LEVEL_INFO,
+ warn = SPDLOG_LEVEL_WARN,
+ err = SPDLOG_LEVEL_ERROR,
+ critical = SPDLOG_LEVEL_CRITICAL,
+ off = SPDLOG_LEVEL_OFF,
+ n_levels
+};
#define SPDLOG_LEVEL_NAME_TRACE spdlog::string_view_t("trace", 5)
#define SPDLOG_LEVEL_NAME_DEBUG spdlog::string_view_t("debug", 5)
@@ -265,144 +262,143 @@ namespace spdlog {
#define SPDLOG_LEVEL_NAME_OFF spdlog::string_view_t("off", 3)
#if !defined(SPDLOG_LEVEL_NAMES)
-#define SPDLOG_LEVEL_NAMES \
- {SPDLOG_LEVEL_NAME_TRACE, SPDLOG_LEVEL_NAME_DEBUG, SPDLOG_LEVEL_NAME_INFO, \
- SPDLOG_LEVEL_NAME_WARNING, SPDLOG_LEVEL_NAME_ERROR, SPDLOG_LEVEL_NAME_CRITICAL, \
- SPDLOG_LEVEL_NAME_OFF}
+#define SPDLOG_LEVEL_NAMES \
+ { \
+ SPDLOG_LEVEL_NAME_TRACE, SPDLOG_LEVEL_NAME_DEBUG, SPDLOG_LEVEL_NAME_INFO, \
+ SPDLOG_LEVEL_NAME_WARNING, SPDLOG_LEVEL_NAME_ERROR, SPDLOG_LEVEL_NAME_CRITICAL, \
+ SPDLOG_LEVEL_NAME_OFF \
+ }
#endif
#if !defined(SPDLOG_SHORT_LEVEL_NAMES)
-#define SPDLOG_SHORT_LEVEL_NAMES {"T", "D", "I", "W", "E", "C", "O"}
+#define SPDLOG_SHORT_LEVEL_NAMES \
+ { "T", "D", "I", "W", "E", "C", "O" }
#endif
- SPDLOG_API const string_view_t& to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
- SPDLOG_API const char* to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
- SPDLOG_API spdlog::level::level_enum from_str(const std::string& name) SPDLOG_NOEXCEPT;
-
- } // namespace level
-
- //
- // Color mode used by sinks with color support.
- //
- enum class color_mode { always, automatic, never };
-
- //
- // Pattern time - specific time getting to use for pattern_formatter.
- // local time by default
- //
- enum class pattern_time_type {
- local, // log localtime
- utc // log utc
- };
-
- //
- // Log exception
- //
- class SPDLOG_API spdlog_ex : public std::exception {
- public:
- explicit spdlog_ex(std::string msg);
- spdlog_ex(const std::string& msg, int last_errno);
- const char* what() const SPDLOG_NOEXCEPT override;
-
- private:
- std::string msg_;
- };
-
- [[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string& msg, int last_errno);
- [[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg);
-
- struct source_loc {
- SPDLOG_CONSTEXPR source_loc() = default;
- SPDLOG_CONSTEXPR source_loc(const char* filename_in, int line_in, const char* funcname_in)
- : filename {filename_in}, line {line_in}, funcname {funcname_in} {}
-
- SPDLOG_CONSTEXPR bool empty() const SPDLOG_NOEXCEPT { return line <= 0; }
- const char* filename {nullptr};
- int line {0};
- const char* funcname {nullptr};
- };
-
- struct file_event_handlers {
- file_event_handlers()
- : before_open(nullptr),
- after_open(nullptr),
- before_close(nullptr),
- after_close(nullptr) {}
-
- std::function before_open;
- std::function after_open;
- std::function before_close;
- std::function after_close;
- };
-
- namespace details {
-
- // to_string_view
-
- SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(const memory_buf_t& buf)
- SPDLOG_NOEXCEPT {
- return spdlog::string_view_t {buf.data(), buf.size()};
- }
-
- SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(spdlog::string_view_t str)
- SPDLOG_NOEXCEPT {
- return str;
- }
+SPDLOG_API const string_view_t &to_string_view(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
+SPDLOG_API const char *to_short_c_str(spdlog::level::level_enum l) SPDLOG_NOEXCEPT;
+SPDLOG_API spdlog::level::level_enum from_str(const std::string &name) SPDLOG_NOEXCEPT;
+
+} // namespace level
+
+//
+// Color mode used by sinks with color support.
+//
+enum class color_mode { always, automatic, never };
+
+//
+// Pattern time - specific time getting to use for pattern_formatter.
+// local time by default
+//
+enum class pattern_time_type {
+ local, // log localtime
+ utc // log utc
+};
+
+//
+// Log exception
+//
+class SPDLOG_API spdlog_ex : public std::exception {
+public:
+ explicit spdlog_ex(std::string msg);
+ spdlog_ex(const std::string &msg, int last_errno);
+ const char *what() const SPDLOG_NOEXCEPT override;
+
+private:
+ std::string msg_;
+};
+
+[[noreturn]] SPDLOG_API void throw_spdlog_ex(const std::string &msg, int last_errno);
+[[noreturn]] SPDLOG_API void throw_spdlog_ex(std::string msg);
+
+struct source_loc {
+ SPDLOG_CONSTEXPR source_loc() = default;
+ SPDLOG_CONSTEXPR source_loc(const char *filename_in, int line_in, const char *funcname_in)
+ : filename{filename_in},
+ line{line_in},
+ funcname{funcname_in} {}
+
+ SPDLOG_CONSTEXPR bool empty() const SPDLOG_NOEXCEPT { return line <= 0; }
+ const char *filename{nullptr};
+ int line{0};
+ const char *funcname{nullptr};
+};
+
+struct file_event_handlers {
+ file_event_handlers()
+ : before_open(nullptr),
+ after_open(nullptr),
+ before_close(nullptr),
+ after_close(nullptr) {}
+
+ std::function before_open;
+ std::function after_open;
+ std::function before_close;
+ std::function after_close;
+};
+
+namespace details {
+
+// to_string_view
+
+SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(const memory_buf_t &buf)
+ SPDLOG_NOEXCEPT {
+ return spdlog::string_view_t{buf.data(), buf.size()};
+}
+
+SPDLOG_CONSTEXPR_FUNC spdlog::string_view_t to_string_view(spdlog::string_view_t str)
+ SPDLOG_NOEXCEPT {
+ return str;
+}
#if defined(SPDLOG_WCHAR_FILENAMES) || defined(SPDLOG_WCHAR_TO_UTF8_SUPPORT)
- SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(const wmemory_buf_t& buf)
- SPDLOG_NOEXCEPT {
- return spdlog::wstring_view_t {buf.data(), buf.size()};
- }
-
- SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(spdlog::wstring_view_t str)
- SPDLOG_NOEXCEPT {
- return str;
- }
+SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(const wmemory_buf_t &buf)
+ SPDLOG_NOEXCEPT {
+ return spdlog::wstring_view_t{buf.data(), buf.size()};
+}
+
+SPDLOG_CONSTEXPR_FUNC spdlog::wstring_view_t to_string_view(spdlog::wstring_view_t str)
+ SPDLOG_NOEXCEPT {
+ return str;
+}
#endif
-#ifndef SPDLOG_USE_STD_FORMAT
- template
- inline fmt::basic_string_view to_string_view(fmt::basic_format_string fmt) {
- return fmt;
- }
-#elif __cpp_lib_format >= 202207L
- template
- SPDLOG_CONSTEXPR_FUNC std::basic_string_view to_string_view(
- std::basic_format_string fmt) SPDLOG_NOEXCEPT {
- return fmt.get();
- }
+#if defined(SPDLOG_USE_STD_FORMAT) && __cpp_lib_format >= 202207L
+template
+SPDLOG_CONSTEXPR_FUNC std::basic_string_view to_string_view(
+ std::basic_format_string fmt) SPDLOG_NOEXCEPT {
+ return fmt.get();
+}
#endif
// make_unique support for pre c++14
#if __cplusplus >= 201402L // C++14 and beyond
- using std::enable_if_t;
- using std::make_unique;
+using std::enable_if_t;
+using std::make_unique;
#else
- template
- using enable_if_t = typename std::enable_if::type;
-
- template
- std::unique_ptr make_unique(Args&&... args) {
- static_assert(!std::is_array::value, "arrays not supported");
- return std::unique_ptr(new T(std::forward(args)...));
- }
+template
+using enable_if_t = typename std::enable_if::type;
+
+template
+std::unique_ptr make_unique(Args &&...args) {
+ static_assert(!std::is_array::value, "arrays not supported");
+ return std::unique_ptr(new T(std::forward(args)...));
+}
#endif
- // to avoid useless casts (see
- // https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
- template ::value, int> = 0>
- constexpr T conditional_static_cast(U value) {
- return static_cast(value);
- }
+// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
+template ::value, int> = 0>
+constexpr T conditional_static_cast(U value) {
+ return static_cast(value);
+}
- template ::value, int> = 0>
- constexpr T conditional_static_cast(U value) {
- return value;
- }
+template ::value, int> = 0>
+constexpr T conditional_static_cast(U value) {
+ return value;
+}
- } // namespace details
+} // namespace details
} // namespace spdlog
#ifdef SPDLOG_HEADER_ONLY
diff --git a/include/spdlog/details/backtracer-inl.h b/include/spdlog/details/backtracer-inl.h
index 4a5e5d1c..baa06b6a 100644
--- a/include/spdlog/details/backtracer-inl.h
+++ b/include/spdlog/details/backtracer-inl.h
@@ -7,60 +7,57 @@
#include
#endif
namespace spdlog {
- namespace details {
- SPDLOG_INLINE backtracer::backtracer(const backtracer& other) {
- std::lock_guard lock(other.mutex_);
- enabled_ = other.enabled();
- messages_ = other.messages_;
- }
-
- SPDLOG_INLINE backtracer::backtracer(backtracer&& other) SPDLOG_NOEXCEPT {
- std::lock_guard lock(other.mutex_);
- enabled_ = other.enabled();
- messages_ = std::move(other.messages_);
- }
-
- SPDLOG_INLINE backtracer& backtracer::operator=(backtracer other) {
- std::lock_guard lock(mutex_);
- enabled_ = other.enabled();
- messages_ = std::move(other.messages_);
- return *this;
- }
-
- SPDLOG_INLINE void backtracer::enable(size_t size) {
- std::lock_guard lock {mutex_};
- enabled_.store(true, std::memory_order_relaxed);
- messages_ = circular_q {size};
- }
-
- SPDLOG_INLINE void backtracer::disable() {
- std::lock_guard lock {mutex_};
- enabled_.store(false, std::memory_order_relaxed);
- }
-
- SPDLOG_INLINE bool backtracer::enabled() const {
- return enabled_.load(std::memory_order_relaxed);
- }
-
- SPDLOG_INLINE void backtracer::push_back(const log_msg& msg) {
- std::lock_guard lock {mutex_};
- messages_.push_back(log_msg_buffer {msg});
- }
-
- SPDLOG_INLINE bool backtracer::empty() const {
- std::lock_guard lock {mutex_};
- return messages_.empty();
- }
-
- // pop all items in the q and apply the given fun on each of them.
- SPDLOG_INLINE void backtracer::foreach_pop(
- std::function fun) {
- std::lock_guard lock {mutex_};
- while (!messages_.empty()) {
- auto& front_msg = messages_.front();
- fun(front_msg);
- messages_.pop_front();
- }
- }
- } // namespace details
+namespace details {
+SPDLOG_INLINE backtracer::backtracer(const backtracer &other) {
+ std::lock_guard lock(other.mutex_);
+ enabled_ = other.enabled();
+ messages_ = other.messages_;
+}
+
+SPDLOG_INLINE backtracer::backtracer(backtracer &&other) SPDLOG_NOEXCEPT {
+ std::lock_guard lock(other.mutex_);
+ enabled_ = other.enabled();
+ messages_ = std::move(other.messages_);
+}
+
+SPDLOG_INLINE backtracer &backtracer::operator=(backtracer other) {
+ std::lock_guard lock(mutex_);
+ enabled_ = other.enabled();
+ messages_ = std::move(other.messages_);
+ return *this;
+}
+
+SPDLOG_INLINE void backtracer::enable(size_t size) {
+ std::lock_guard lock{mutex_};
+ enabled_.store(true, std::memory_order_relaxed);
+ messages_ = circular_q{size};
+}
+
+SPDLOG_INLINE void backtracer::disable() {
+ std::lock_guard lock{mutex_};
+ enabled_.store(false, std::memory_order_relaxed);
+}
+
+SPDLOG_INLINE bool backtracer::enabled() const { return enabled_.load(std::memory_order_relaxed); }
+
+SPDLOG_INLINE void backtracer::push_back(const log_msg &msg) {
+ std::lock_guard lock{mutex_};
+ messages_.push_back(log_msg_buffer{msg});
+}
+
+SPDLOG_INLINE bool backtracer::empty() const {
+ std::lock_guard lock{mutex_};
+ return messages_.empty();
+}
+
+// pop all items in the q and apply the given fun on each of them.
+SPDLOG_INLINE void backtracer::foreach_pop(std::function fun) {
+ std::lock_guard lock{mutex_};
+ while (!messages_.empty()) {
+ auto &front_msg = messages_.front();
+ fun(front_msg);
+ messages_.pop_front();
+ }
+}
+} // namespace details
} // namespace spdlog
diff --git a/include/spdlog/details/backtracer.h b/include/spdlog/details/backtracer.h
index 1920fa0d..f9eb4b43 100644
--- a/include/spdlog/details/backtracer.h
+++ b/include/spdlog/details/backtracer.h
@@ -3,41 +3,41 @@
#pragma once
+#include
+#include
+
#include
#include
#include
-#include
-#include
-
// Store log messages in circular buffer.
// Useful for storing debug data in case of error/warning happens.
namespace spdlog {
- namespace details {
- class SPDLOG_API backtracer {
- mutable std::mutex mutex_;
- std::atomic enabled_ {false};
- circular_q messages_;
-
- public:
- backtracer() = default;
- backtracer(const backtracer& other);
-
- backtracer(backtracer&& other) SPDLOG_NOEXCEPT;
- backtracer& operator=(backtracer other);
-
- void enable(size_t size);
- void disable();
- bool enabled() const;
- void push_back(const log_msg& msg);
- bool empty() const;
-
- // pop all items in the q and apply the given fun on each of them.
- void foreach_pop(std::function fun);
- };
-
- } // namespace details
+namespace details {
+class SPDLOG_API backtracer {
+ mutable std::mutex mutex_;
+ std::atomic enabled_{false};
+ circular_q