diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 8a901a22..06512248 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -9,6 +9,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") add_subdirectory(ex1) add_subdirectory(ex2) +add_subdirectory(ex3) # ---------------------------------------------------------------- # make standard directories for std:: includes explicit diff --git a/example/ex2/ex2.cpp b/example/ex2/ex2.cpp index 2084b551..3d246f0e 100644 --- a/example/ex2/ex2.cpp +++ b/example/ex2/ex2.cpp @@ -26,7 +26,7 @@ main(int argc, char ** argv) { int n = 4; - scope log(XO_SSETUP0(), ":n", 4); + scope log(XO_SSETUP0(), ":n ", 4); int fn = fib(n); diff --git a/example/ex3/CMakeLists.txt b/example/ex3/CMakeLists.txt new file mode 100644 index 00000000..d81e0e99 --- /dev/null +++ b/example/ex3/CMakeLists.txt @@ -0,0 +1,2 @@ +add_executable(ex3 ex3.cpp) +xo_include_options(ex3) diff --git a/example/ex3/ex3.cpp b/example/ex3/ex3.cpp new file mode 100644 index 00000000..58d81dc7 --- /dev/null +++ b/example/ex3/ex3.cpp @@ -0,0 +1,36 @@ +/* examples ex3/ex3.cpp */ + +#include "nestlog/scope.hpp" + +using namespace xo; + +int +fib(int n) { + scope log(XO_SSETUP0(), ":n ", n); + + int retval = 1; + + if (n >= 2) { + retval = fib(n - 1) + fib(n - 2); + log(":n ", n); + } + + log.end_scope("<- :retval ", retval); + + return retval; +} + +int +main(int argc, char ** argv) { + log_config::style = FS_Pretty; + log_config::indent_width = 4; + + int n = 4; + + scope log(XO_SSETUP0(), ":n ", 4); + + int fn = fib(n); + + log(":n ", n); + log("<- :fib(n) ", fn); +} diff --git a/include/nestlog/log_config.hpp b/include/nestlog/log_config.hpp index 9b1eff12..ce28665f 100644 --- a/include/nestlog/log_config.hpp +++ b/include/nestlog/log_config.hpp @@ -2,6 +2,7 @@ #pragma once +#include "function.hpp" #include namespace xo { @@ -10,12 +11,18 @@ namespace xo { struct log_config_impl { /* spaces per indent level */ static std::uint32_t indent_width; + /* display style for function names. FS_Simple|FS_Pretty|FS_Streamlined */ + static function_style style; }; /*log_config_impl*/ template std::uint32_t log_config_impl::indent_width = 1; + template + function_style + log_config_impl::style = FS_Streamlined; + using log_config = log_config_impl; } /*namespace xo*/ diff --git a/include/nestlog/log_state.hpp b/include/nestlog/log_state.hpp index ac25e043..59c3b4f6 100644 --- a/include/nestlog/log_state.hpp +++ b/include/nestlog/log_state.hpp @@ -27,11 +27,11 @@ namespace xo { std::ostream & ss() { return ss_; } /* call on entry to new scope */ - void preamble(std::string_view name1, std::string_view name2); + void preamble(function_style style, std::string_view name1, std::string_view name2); /* call before each new log entry */ void indent(char pad_char); /* call on exit from scope */ - void postamble(std::string_view name1, std::string_view name2); + void postamble(function_style style, std::string_view name1, std::string_view name2); /* write collected output to *p_sbuf */ void flush2sbuf(std::streambuf * p_sbuf); @@ -44,7 +44,8 @@ namespace xo { private: /* common implementation for .preamble(), .postamble() */ - void entryexit_aux(std::string_view name1, + void entryexit_aux(function_style style, + std::string_view name1, std::string_view name2, char label_char); @@ -107,7 +108,8 @@ namespace xo { template void - state_impl::entryexit_aux(std::string_view name1, + state_impl::entryexit_aux(function_style style, + std::string_view name1, std::string_view name2, char label_char) { @@ -119,24 +121,29 @@ namespace xo { /* mnemonic for scope entry/exit */ this->ss_ << label_char; + if (log_config::indent_width > 1) + this->ss_ << ' '; + /* scope name */ - this->ss_ << name1 << name2; + this->ss_ << function_name(style, name1) << name2; } /*entryexit_aux*/ template void - state_impl::preamble(std::string_view name1, + state_impl::preamble(function_style style, + std::string_view name1, std::string_view name2) { - this->entryexit_aux(name1, name2, '+' /*label_char*/); + this->entryexit_aux(style, name1, name2, '+' /*label_char*/); } /*preamble*/ template void - state_impl::postamble(std::string_view name1, + state_impl::postamble(function_style style, + std::string_view name1, std::string_view name2) { - this->entryexit_aux(name1, name2, '-' /*label_char*/); + this->entryexit_aux(style, name1, name2, '-' /*label_char*/); } /*postamble*/ template diff --git a/include/nestlog/scope.hpp b/include/nestlog/scope.hpp index 0f1af013..cd3219fe 100644 --- a/include/nestlog/scope.hpp +++ b/include/nestlog/scope.hpp @@ -16,28 +16,29 @@ namespace xo { class state_impl; //# define XO_SSETUP0() xo::scope_setup(__FUNCTION__) -# define XO_SSETUP0() xo::scope_setup(__PRETTY_FUNCTION__) +# define XO_SSETUP0() xo::scope_setup(log_config::style, __PRETTY_FUNCTION__) /* throw exception if condition not met*/ # define XO_EXPECT(f,msg) if(!(f)) { throw std::runtime_error(msg); } /* establish scope using current function name */ -# define XO_SCOPE(name) xo::scope name(xo::scope_setup(__FUNCTION__)) +# define XO_SCOPE(name) xo::scope name(xo::scope_setup(log_config::style, __PRETTY_FUNCTION__)) /* like XO_SCOPE(name), but also set enabled flag */ -# define XO_SCOPE2(name, debug_flag) xo::scope name(xo::scope_setup(__FUNCTION__, debug_flag)) -# define XO_SCOPE_DISABLED(name) xo::scope name(xo::scope_setup(__FUNCTION__, false)) +# define XOf_SCOPE2(name, debug_flag) xo::scope name(xo::scope_setup(log_config::style, __PRETTY_FUNCTION__, debug_flag)) +# define XO_SCOPE_DISABLED(name) xo::scope name(xo::scope_setup(log_config::style, __PRETTY_FUNCTION__, false)) # define XO_STUB() { XO_SCOPE(logr); logr.log("STUB"); } /* convenience class for basic_scope<..> construction (see below). * use to disambiguate setup from other arguments */ struct scope_setup { - scope_setup(std::string_view name1, std::string_view name2, bool enabled_flag) - : name1_{name1}, name2_{name2}, enabled_flag_{enabled_flag} {} - scope_setup(std::string_view name1, bool enabled_flag) - : scope_setup(name1, "", enabled_flag) {} - scope_setup(std::string_view name1) - : scope_setup(name1, true /*enabled_flag*/) {} + scope_setup(function_style style, std::string_view name1, std::string_view name2, bool enabled_flag) + : style_{style}, name1_{name1}, name2_{name2}, enabled_flag_{enabled_flag} {} + scope_setup(function_style style, std::string_view name1, bool enabled_flag) + : scope_setup(style, name1, "", enabled_flag) {} + scope_setup(function_style style, std::string_view name1) + : scope_setup(style, name1, true /*enabled_flag*/) {} + function_style style_ = FS_Pretty; std::string_view name1_ = "<.name1>"; std::string_view name2_ = "<.name2>"; bool enabled_flag_ = false; @@ -142,6 +143,8 @@ namespace xo { /* send indented output to this streambuf (e.g. std::clog.rdbuf()) */ std::streambuf * dest_sbuf_ = std::clog.rdbuf(); + /* style for displaying .name1 */ + function_style style_ = FS_Pretty; /* name of this scope (part 1) */ std::string_view name1_ = ""; /* name of this scope (part 2) */ @@ -154,14 +157,15 @@ namespace xo { template basic_scope::basic_scope(scope_setup setup, Tn&&... args) - : name1_{std::move(setup.name1_)}, + : style_{setup.style_}, + name1_{std::move(setup.name1_)}, name2_{std::move(setup.name2_)}, finalized_{!setup.enabled_flag_} { if(setup.enabled_flag_) { state_impl_type * logstate = basic_scope::require_thread_local_state(); - logstate->preamble(this->name1_, this->name2_); + logstate->preamble(this->style_, this->name1_, this->name2_); tosn(logstate2stream(logstate), " ", std::forward(args)...); @@ -240,7 +244,7 @@ namespace xo { logstate->decr_nesting(); - logstate->postamble(this->name1_, this->name2_); + logstate->postamble(this->style_, this->name1_, this->name2_); tosn(logstate2stream(logstate), " ", std::forward(args)...);