9 #include <experimental/filesystem>
10 namespace fs = std::experimental::filesystem;
13 namespace fs = std::filesystem;
28#if __has_include(<execinfo.h>) && __has_include(<stdlib.h>) && __has_include(<libgen.h>)
32 #define CLUTCHLOG_HAVE_UNIX_SYSINFO 1
34 #define CLUTCHLOG_HAVE_UNIX_SYSINFO 0
38#if __has_include(<sys/ioctl.h>) && __has_include(<stdio.h>) && __has_include(<unistd.h>)
39 #include <sys/ioctl.h>
42 #define CLUTCHLOG_HAVE_UNIX_SYSIOCTL 1
44 #define CLUTCHLOG_HAVE_UNIX_SYSIOCTL 0
54 #define WITH_CLUTCHLOG
66#ifndef CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG
68 #define CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG clutchlog::level::progress
78#define CLUTCHLOC __FILE__, __FUNCTION__, __LINE__
82 #define CLUTCHLOGD( LEVEL, WHAT, DEPTH_DELTA ) do { \
83 auto& clutchlog__logger = clutchlog::logger(); \
84 std::ostringstream clutchlog__msg ; clutchlog__msg << WHAT; \
85 clutchlog__logger.log(clutchlog::level::LEVEL, clutchlog__msg.str(), CLUTCHLOC, DEPTH_DELTA); \
88 #define CLUTCHLOGD( LEVEL, WHAT, DEPTH_DELTA ) do { \
89 if(clutchlog::level::LEVEL <= CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG) { \
90 auto& clutchlog__logger = clutchlog::logger(); \
91 std::ostringstream clutchlog__msg ; clutchlog__msg << WHAT; \
92 clutchlog__logger.log(clutchlog::level::LEVEL, clutchlog__msg.str(), CLUTCHLOC, DEPTH_DELTA); \
99 #define CLUTCHLOG( LEVEL, WHAT ) \
100 CLUTCHLOGD(LEVEL, WHAT, 0)
102 #define CLUTCHLOG( LEVEL, WHAT ) \
103 CLUTCHLOGD(LEVEL, WHAT, 0)
108 #define CLUTCHDUMP( LEVEL, CONTAINER, FILENAME ) do { \
109 auto& clutchlog__logger = clutchlog::logger(); \
110 clutchlog__logger.dump(clutchlog::level::LEVEL, std::begin(CONTAINER), std::end(CONTAINER), \
111 CLUTCHLOC, FILENAME, CLUTCHDUMP_DEFAULT_SEP); \
114 #define CLUTCHDUMP( LEVEL, CONTAINER, FILENAME ) do { \
115 if(clutchlog::level::LEVEL <= CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG) { \
116 auto& clutchlog__logger = clutchlog::logger(); \
117 clutchlog__logger.dump(clutchlog::level::LEVEL, std::begin(CONTAINER), std::end(CONTAINER), \
118 CLUTCHLOC, FILENAME, CLUTCHDUMP_DEFAULT_SEP); \
125 #define CLUTCHFUNC( LEVEL, FUNC, ... ) do { \
126 auto& clutchlog__logger = clutchlog::logger(); \
127 clutchlog::scope_t clutchlog__scope = clutchlog__logger.locate(clutchlog::level::LEVEL, CLUTCHLOC); \
128 if(clutchlog__scope.matches) { \
133 #define CLUTCHFUNC( LEVEL, FUNC, ... ) do { \
134 if(clutchlog::level::LEVEL <= CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG) { \
135 auto& clutchlog__logger = clutchlog::logger(); \
136 clutchlog::scope_t clutchlog__scope = clutchlog__logger.locate(clutchlog::level::LEVEL, CLUTCHLOC); \
137 if(clutchlog__scope.matches) { \
146 #define CLUTCHCODE( LEVEL, ... ) do { \
147 auto& clutchlog__logger = clutchlog::logger(); \
148 clutchlog::scope_t clutchlog__scope = clutchlog__logger.locate(clutchlog::level::LEVEL, CLUTCHLOC); \
149 if(clutchlog__scope.matches) { \
154 #define CLUTCHCODE( LEVEL, CODE ) do { \
155 if(clutchlog::level::LEVEL <= CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG) { \
156 auto& clutchlog__logger = clutchlog::logger(); \
157 clutchlog::scope_t clutchlog__scope = clutchlog__logger.locate(clutchlog::level::LEVEL, CLUTCHLOC); \
158 if(clutchlog__scope.matches) { \
169 #define CLUTCHLOG( LEVEL, WHAT ) do {} while(0)
170 #define CLUTCHLOGD( LEVEL, WHAT, DEPTH_DELTA ) do {} while(0)
171 #define CLUTCHDUMP( LEVEL, CONTAINER, FILENAME ) do {} while(0)
172 #define CLUTCHFUNC( LEVEL, FUNC, ... ) do {} while(0)
173 #define CLUTCHCODE( LEVEL, CODE ) do {} while(0)
197 #ifndef CLUTCHLOG_DEFAULT_FORMAT
199 #if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
200 #if CLUTCHLOG_HAVE_UNIX_SYSIOCTL == 1
201 #define CLUTCHLOG_DEFAULT_FORMAT "[{name}] {level_letter}:{depth_marks} {msg} {hfill} {func} @ {file}:{line}\n"
203 #define CLUTCHLOG_DEFAULT_FORMAT "[{name}] {level_letter}:{depth_marks} {msg}\t\t\t\t\t{func} @ {file}:{line}\n"
206 #if CLUTCHLOG_HAVE_UNIX_SYSIOCTL == 1
207 #define CLUTCHLOG_DEFAULT_FORMAT "{level_letter} {msg} {hfill} {func} @ {file}:{line}\n"
209 #define CLUTCHLOG_DEFAULT_FORMAT "{level_letter} {msg}\t\t\t\t\t{func} @ {file}:{line}\n"
214 #ifndef CLUTCHLOG_DEFAULT_FORMAT
216 #if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
217 #define CLUTCHLOG_DEFAULT_FORMAT "[{name}] {level_letter}:{depth_marks} {msg} {hfill} {func}\n"
219 #define CLUTCHLOG_DEFAULT_FORMAT "{level_letter} {msg}\t\t\t\t\t{func}\n"
227 #ifndef CLUTCHDUMP_DEFAULT_FORMAT
229 #if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
230 #define CLUTCHDUMP_DEFAULT_FORMAT "# [{name}] {level} in {func} (at depth {depth}) @ {file}:{line}"
232 #define CLUTCHDUMP_DEFAULT_FORMAT "# {level} in {func} @ {file}:{line}"
236 #ifndef CLUTCHDUMP_DEFAULT_FORMAT
238 #if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
239 #define CLUTCHDUMP_DEFAULT_FORMAT "# [{name}] {level} in {func} (at depth {depth})"
241 #define CLUTCHDUMP_DEFAULT_FORMAT "# {level} in {func}"
248 #ifndef CLUTCHDUMP_DEFAULT_SEP
250 #define CLUTCHDUMP_DEFAULT_SEP "\n"
253 static inline std::string dump_default_sep = CLUTCHDUMP_DEFAULT_SEP;
255 #ifndef CLUTCHLOG_DEFAULT_DEPTH_MARK
257 #define CLUTCHLOG_DEFAULT_DEPTH_MARK ">"
260 static inline std::string default_depth_mark = CLUTCHLOG_DEFAULT_DEPTH_MARK;
262 #ifndef CLUTCHLOG_STRIP_CALLS
264 #define CLUTCHLOG_STRIP_CALLS 5
267 static inline unsigned int default_strip_calls = CLUTCHLOG_STRIP_CALLS;
269 #ifndef CLUTCHLOG_DEFAULT_HFILL_MARK
271 #define CLUTCHLOG_DEFAULT_HFILL_MARK '.'
274 static inline char default_hfill_char = CLUTCHLOG_DEFAULT_HFILL_MARK;
277 #if CLUTCHLOG_HAVE_UNIX_SYSIOCTL == 1
278 #ifndef CLUTCHLOG_DEFAULT_HFILL_MAX
279 #define CLUTCHLOG_DEFAULT_HFILL_MAX 300
281 #ifndef CLUTCHLOG_DEFAULT_HFILL_MIN
282 #define CLUTCHLOG_DEFAULT_HFILL_MIN 150
314 enum level {critical=0, error=1, warning=2, progress=3, note=4, info=5, debug=6, xdebug=7};
317 enum filename {path, base, dir, dirbase, stem, dirstem};
439 bright_magenta = 105,
447 friend std::ostream&
operator<<(std::ostream& os,
const std::tuple<fg,bg,typo>& fbs)
450 std::vector<short> codes; codes.reserve(3);
451 if(f != fg::none) { codes.push_back(
static_cast<short>(f));}
452 if(b != bg::none) { codes.push_back(
static_cast<short>(b));}
453 if(s != typo::none) { codes.push_back(
static_cast<short>(s));}
454 if(codes.size() == 0) {
460 for(
size_t i=1; i < codes.size(); ++i) {
461 os <<
";" << codes[i];
471 if(s != typo::none) {
472 os <<
"\033[" <<
static_cast<short>(s) <<
"m";
504 virtual std::ostream&
print_on( std::ostream& os)
const = 0;
510 os <<
"\033[" <<
static_cast<short>(c.
type) <<
";" <<
static_cast<short>(c.mode) <<
";";
606 :
color(
ansi::colors_16M, t),
red(r), green(g), blue(b) {}
617 assert(srgb.size() == 7);
618 if(srgb.size() != 7) {
624 if(srgb.at(0) ==
'#') {
627 std::istringstream(srgb.substr(0+i,2)) >> std::hex >>
red;
628 std::istringstream(srgb.substr(2+i,2)) >> std::hex >> green;
629 std::istringstream(srgb.substr(4+i,2)) >> std::hex >> blue;
631 assert(-1 <=
red and
red <= 255);
632 assert(-1 <= green and green <= 255);
633 assert(-1 <= blue and blue <= 255);
637 bool is_set()
const {
return red > -1 and green > -1 and blue > -1;}
642 os <<
red <<
";" << green <<
";" << blue;
733 explicit fmt(
const short fr,
const short fg,
const short fb,
734 const short gr,
const short gg,
const short gb,
738 const short gr,
const short gg,
const short gb,
741 explicit fmt(
const short fr,
const short fg,
const short fb,
744 explicit fmt(
const short fr,
const short fg,
const short fb,
748 explicit fmt(
const std::string& f,
const std::string& b,
typo s = typo::none)
750 explicit fmt(
fg,
const std::string& b,
typo s = typo::none)
752 explicit fmt(
const std::string& f,
bg,
typo s = typo::none)
754 explicit fmt(
const std::string& f,
typo s = typo::none)
812 std::ostringstream os;
814 fmt reset(fmt::typo::reset);
824 std::ostringstream os;
829 static fmt hash(
const std::string&
str,
const std::vector<fmt> domain = {})
831 size_t h = std::hash<std::string>{}(
str);
832 if(domain.size() == 0) {
833 return fmt(
static_cast<short>(h % 256));
835 return domain[h % domain.size()];
847 void operator=(
clutchlog const&) =
delete;
854 {level::critical,
"Critical"},
855 {level::error ,
"Error"},
856 {level::warning ,
"Warning"},
857 {level::progress,
"Progress"},
858 {level::note ,
"Note"},
859 {level::info ,
"Info"},
860 {level::debug ,
"Debug"},
861 {level::xdebug ,
"XDebug"}
864 {level::critical,
"Crit"},
865 {level::error ,
"Erro"},
866 {level::warning ,
"Warn"},
867 {level::progress,
"Prog"},
868 {level::note ,
"Note"},
869 {level::info ,
"Info"},
870 {level::debug ,
"Dbug"},
871 {level::xdebug ,
"XDbg"}
874 {level::critical,fmt(fmt::fg::red, fmt::typo::underline)},
875 {level::error ,fmt(fmt::fg::red, fmt::typo::bold)},
876 {level::warning ,fmt(fmt::fg::magenta, fmt::typo::bold)},
877 {level::progress,fmt()},
878 {level::note ,fmt()},
879 {level::info ,fmt()},
880 {level::debug ,fmt()},
881 {level::xdebug ,fmt()}
885 #if CLUTCHLOG_HAVE_UNIX_SYSIOCTL
887 _hfill_fmt(fmt::fg::none),
892 #if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
893 _depth(std::numeric_limits<size_t>::max() -
_strip_calls),
910#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL
912 ioctl(STDERR_FILENO, TIOCGWINSZ, &w);
932 #if CLUTCHLOG_HAVE_UNIX_SYSIOCTL
944 #if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
948 std::string _depth_mark;
964#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
966 static const size_t _max_buffer = 4096;
968 std::vector<fmt> _depth_fmts;
971#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL
1000#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
1002 void depth(
size_t d) {_depth = d;}
1004 size_t depth()
const {
return _depth;}
1007 void depth_mark(
const std::string mark) {_depth_mark = mark;}
1009 std::string depth_mark()
const {
return _depth_mark;}
1016#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL == 1
1018 void hfill_mark(
const char mark) {_hfill_char = mark;}
1020 char hfill_mark()
const {
return _hfill_char;}
1022 void hfill_style(fmt
style) {_hfill_fmt =
style;}
1027 template<
class ... FMT>
1028 void hfill_style(FMT... styles) { this->hfill_style(fmt(styles...)); }
1030 fmt hfill_style()
const {
return _hfill_fmt;}
1032 void hfill_max(
const size_t nmax) {_hfill_max = nmax;}
1034 size_t hfill_max() {
return _hfill_max;}
1036 void hfill_min(
const size_t nmin) {_hfill_min = nmin;}
1038 size_t hfill_min() {
return _hfill_min;}
1083 return ilevel->second;
1085 throw std::out_of_range(
"'" + name +
"' is not a valid log level name");
1098 const std::string& in_file,
1099 const std::string& in_function=
".*",
1100 const std::string& in_line=
".*"
1112 template<
class ... FMT>
1135#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
1156 const std::string&
file,
1157 const std::string&
func,
1165 scope.
stage = stage;
1171#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
1175 void *buffer[_max_buffer];
1176 stack_depth = backtrace(buffer, _max_buffer);
1177 scope.depth = stack_depth;
1186 std::ostringstream sline; sline <<
line;
1190 and std::regex_search(sline.str(),
_in_line);
1206 const std::string& form,
1207 const std::string& mark,
1208 const std::string& tag
1265 const std::regex re(mark);
1266 return std::regex_replace(form, re, tag);
1271 const std::string& form,
1272 const std::string& mark,
1276 std::ostringstream stag; stag << tag;
1277 return replace(form, mark, stag.str());
1283 const std::string& what,
1285 const std::string& name,
1288 const std::string&
file,
1289 const std::string&
func,
1297 row =
replace(row,
"\\{msg\\}", what);
1299 const std::filesystem::path filepath(
file);
1301 std::filesystem::path::iterator ip = filepath.end();
1302 std::advance(ip, -2);
1304 case filename::base:
1305 filename = filepath.filename().string();
1310 case filename::dirbase:
1311 filename = (*ip / filepath.filename()).
string();
1313 case filename::stem:
1314 filename = filepath.stem().string();
1316 case filename::dirstem:
1317 filename = (*ip / filepath.stem()).
string();
1319 case filename::path:
1331 std::string letter(1,
_level_word.at(stage).at(0));
1332 row =
replace(row,
"\\{level_letter\\}", letter);
1335#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
1337 row =
replace(row,
"\\{name\\}", name);
1338 row =
replace(row,
"\\{depth\\}", actual_depth);
1340 if(_depth_fmts.size() == 0) {
1341 row =
replace(row,
"\\{depth_fmt\\}",
fmt(actual_depth % 256).str() );
1343 std::ostringstream chevrons;
1344 for(
size_t i = 0; i < actual_depth; ++i) {
1345 chevrons << _depth_mark;
1347 row =
replace(row,
"\\{depth_marks\\}", chevrons.str());
1350 row =
replace(row,
"\\{depth_fmt\\}",
1351 _depth_fmts[std::min(actual_depth,_depth_fmts.size()-1)].str() );
1353 std::ostringstream chevrons;
1354 for(
size_t i = 0; i < actual_depth; ++i) {
1355 chevrons << _depth_fmts[std::min(i+1,_depth_fmts.size()-1)].str()
1358 row =
replace(row,
"\\{depth_marks\\}", chevrons.str());
1365#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL
1367 const std::string raw_row =
replace(row,
"(\\x9B|\\x1B\\[)[0-?]*[ -\\/]*[@-~]",
"");
1368 const std::string hfill_tag =
"{hfill}";
1369 const size_t hfill_pos = row.find(hfill_tag);
1370 const size_t raw_hfill_pos = raw_row.find(hfill_tag);
1371 const size_t nb_columns = std::max(std::min((
size_t)_nb_columns, _hfill_max), _hfill_min);
1372 if(hfill_pos != std::string::npos) {
1373 assert(raw_hfill_pos != std::string::npos);
1374 if(nb_columns > 0) {
1375 const size_t left_len = raw_hfill_pos;
1376 const size_t right_len = raw_row.size() - raw_hfill_pos - hfill_tag.size();
1377 if(right_len+left_len > nb_columns) {
1379 if(right_len < nb_columns) {
1381 const std::string hfill(std::max((
size_t)0, nb_columns-right_len), _hfill_char);
1382 const std::string hfill_styled = _hfill_fmt(hfill);
1383 row =
replace(row,
"\\{hfill\\}",
"\n"+hfill_styled);
1386 const std::string hfill(1, _hfill_char);
1387 const std::string hfill_styled = _hfill_fmt(hfill);
1388 row =
replace(row,
"\\{hfill\\}",
"\n"+hfill_styled);
1392 const std::string hfill(std::max((
size_t)0, nb_columns - (right_len+left_len)), _hfill_char);
1393 const std::string hfill_styled = _hfill_fmt(hfill);
1394 row =
replace(row,
"\\{hfill\\}", hfill_styled);
1398 const std::string hfill(1, _hfill_char);
1399 const std::string hfill_styled = _hfill_fmt(hfill);
1400 row =
replace(row,
"\\{hfill\\}", hfill_styled);
1405 const std::string hfill(1, _hfill_char);
1406 const std::string hfill_styled = _hfill_fmt(hfill);
1407 row =
replace(row,
"\\{hfill\\}", hfill_styled);
1415 const std::string& what,
1416 const std::string&
file,
const std::string&
func,
const size_t line,
1417 const size_t depth_delta = 0
1423#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
1426 line, scope.depth + depth_delta );
1440 const In container_begin,
const In container_end,
1441 const std::string&
file,
const std::string&
func,
const size_t line,
1442 const std::string& filename_template =
"dump_{n}.dat",
1449 const std::string tag =
"\\{n\\}";
1450 const std::regex re(tag);
1451 std::string outfile =
"";
1454 if(std::regex_search(filename_template, re)) {
1458 outfile =
replace(filename_template, tag, n);
1460 }
while( fs::exists( outfile ) );
1464 outfile = filename_template;
1467 std::ofstream fd(outfile);
1470#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
1473 line, scope.depth );
1482 std::copy(container_begin, container_end,
1483 std::ostream_iterator<typename In::value_type>(fd, sep.c_str()));
1503#pragma GCC diagnostic push
1504#pragma GCC diagnostic ignored "-Wreturn-type"
1512 enum level {critical=0, error=1, warning=2, progress=3, note=4, info=5, debug=6, xdebug=7};
1513 enum filename {path, base, dir, dirbase, stem, dirstem};
1516 enum class ansi { colors_16, colors_256, colors_16M}
mode;
1517 enum class typo { reset, bold, underline, inverse, none}
style;
1518 enum class fg { black, red, green, yellow, blue, magenta, cyan, white, bright_black, bright_red, bright_green, bright_yellow, bright_blue, bright_magenta, bright_cyan, bright_white, none}
fore;
1519 enum class bg { black, red, green, yellow, blue, magenta, cyan, white, bright_black, bright_red, bright_green, bright_yellow, bright_blue, bright_magenta, bright_cyan, bright_white, none }
back;
1521 friend std::ostream&
operator<<(std::ostream&,
const std::tuple<fg,bg,typo>&) {}
1528 virtual bool is_set()
const = 0;
1529 virtual std::ostream&
print_on( std::ostream&)
const = 0;
1532 struct color_256 :
public color {
1537 std::ostream&
print_on( std::ostream&)
const {}
1539 struct fg_256 :
public color_256 {
1544 struct bg_256 :
public color_256 {
1549 struct color_16M :
public color {
1550 short red, green, blue;
1554 bool is_set()
const {
return red > -1 and green > -1 and blue > -1;}
1555 std::ostream&
print_on( std::ostream&)
const {}
1557 struct fg_16M :
public color_16M {
1563 struct bg_16M :
public color_16M {
1580 fmt(
const short fr,
const short fg,
const short fb,
1581 const short gr,
const short gg,
const short gb,
1582 typo s = typo::none)
1585 const short gr,
const short gg,
const short gb,
1586 typo s = typo::none)
1588 fmt(
const short fr,
const short fg,
const short fb,
1591 fmt(
const short fr,
const short fg,
const short fb,
1592 typo s = typo::none)
1595 fmt(
const std::string& f,
const std::string& b,
typo s = typo::none)
1597 fmt(
fg,
const std::string& b,
typo s = typo::none)
1599 fmt(
const std::string& f,
bg,
typo s = typo::none)
1601 fmt(
const std::string& f,
typo s = typo::none)
1604 std::ostream&
print_on( std::ostream&)
const {}
1606 friend std::ostream&
operator<<(std::ostream& os,
const fmt&) {
return os; }
1607 std::string
operator()(
const std::string& msg)
const {
return msg; }
1608 std::string
str()
const {
return ""; }
1609 static fmt hash(
const std::string&,
const std::vector<fmt>) {}
1613 void operator=(
clutchlog const&) =
delete;
1626 void format(
const std::string&) {}
1627 std::string
format()
const {
return ""; }
1632 void out(std::ostream&) {}
1633 std::ostream&
out() {}
1635#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1
1636 void depth(
size_t) {}
1637 size_t depth()
const {
return 0; }
1639 void depth_mark(
const std::string) {}
1640 std::string depth_mark()
const {
return ""; }
1641 void strip_calls(
const size_t) {}
1642 size_t strip_calls()
const {
return 0; }
1644#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL == 1
1645 void hfill_mark(
const char) {}
1646 char hfill_mark()
const {
return '\0'; }
1647 void hfill_fmt(fmt) {}
1648 fmt hfill_fmt()
const {
return fmt(); }
1649 void hfill_min(
const size_t) {}
1650 size_t hfill_min() {
return 0; }
1651 void hfill_max(
const size_t) {}
1652 size_t hfill_max() {
return 0; }
1661 const std::map<std::string,level>
levels()
const {}
1664 void file(std::string) {}
1665 void func(std::string) {}
1666 void line(std::string) {}
1668#pragma GCC diagnostic push
1669#pragma GCC diagnostic ignored "-Wunused-parameter"
1672 const std::string& in_function=
".*",
1673 const std::string& in_line=
".*"
1676#pragma GCC diagnostic pop
1677 template<
class ... FMT>
1684 const std::string& form,
1693 const std::string& form,
1723 const std::string&,
const std::string&,
size_t
1731 const std::string&,
const std::string&,
size_t,
1737#pragma GCC diagnostic pop
Color and style formatter for ANSI terminal escape sequences.
enum clutchlog::fmt::ansi mode
Current ANSI color mode.
friend std::ostream & operator<<(std::ostream &os, const fmt &fmt)
Output stream overload.
enum clutchlog::fmt::typo style
Typographic style.
fmt()
Empty constructor, only useful for a no-op formatter.
ansi
ANSI code configuring the available number of colors.
@ colors_16M
16 millions ("true") colors mode.
@ colors_16
16 colors mode.
@ colors_256
256 colors mode.
typo
Typographic style codes.
std::string str() const
Return the formatting code as a string.
std::ostream & print_on(std::ostream &os) const
Print the currently encoded format escape code on the given output stream.
std::string operator()(const std::string &msg) const
Format the given string with the currently encoded format.
The single class which holds everything.
filename _filename
Filename rendering method.
void depth_styles(std::vector< fmt > styles)
Set the styles for value-dependant depth formatting.
std::map< level, std::string > _level_short
dictionary of level identifier to their 4-letters representation.
std::vector< fmt > _funchash_fmts
List of candidate format objects for value-dependant function name styling.
static std::string default_format
Default format of the messages.
void file(std::string file)
Set the regular expression filtering the file location.
level
Available log levels.
std::regex _in_func
Current function location filter.
void log(const level &stage, const std::string &what, const std::string &file, const std::string &func, const size_t line, const size_t depth_delta=0) const
Print a log message IF the location matches the given one.
std::ostream * _out
Standard output.
static unsigned int default_strip_calls
Number of call stack levels to remove from depth display by default.
void format_comment(const std::string &format)
Set the template string for dumps.
static std::string default_depth_mark
Default mark for stack depth.
std::vector< fmt > _filehash_fmts
List of candidate format objects for value-dependant file name styling.
size_t _strip_calls
Current number of call stack levels to remove from depth display.
void threshold(level l)
Set the log level (below which logs are not printed) with an identifier.
std::regex _in_line
Current line location filter.
fmt style(level stage) const
Get the configured fmt instance of the given log level.
scope_t locate(const level &stage, const std::string &file, const std::string &func, const size_t line) const
Gather information on the current location of the call.
static size_t default_hfill_min
Default minimum width (number of characters) at which to fill for right-aligning the right part of me...
std::string _format_dump
Current format of the file output.
void format(const std::string &format)
Set the template string.
void location(const std::string &in_file, const std::string &in_function=".*", const std::string &in_line=".*")
Set the regular expressions filtering the location.
static clutchlog & logger()
Get the logger instance.
static char default_hfill_char
Default character used as a filling for right-align the right part of messages with "{hfill}".
void threshold(const std::string &l)
Set the log level (below which logs are not printed) with a string.
std::string _format_log
Current format of the standard output.
void out(std::ostream &out)
Set the output stream on which to print.
filename
Available filename rendering methods.
void filename(filename f)
Sets the file naming scheme. */.
const std::map< std::string, level > & levels() const
Get the map of available log levels string representations toward their identifier....
std::string replace(const std::string &form, const std::string &mark, const std::string &tag) const
Replace mark by tag in form.
void line(std::string line)
Set the regular expression filtering the line location.
std::string format_comment() const
Get the template string for dumps.
const std::map< level, std::string > _level_word
Dictionary of level identifier to their string representation.
level threshold() const
Get the log level below which logs are not printed.
void dump(const level &stage, const In container_begin, const In container_end, const std::string &file, const std::string &func, const size_t line, const std::string &filename_template="dump_{n}.dat", const std::string sep=dump_default_sep) const
Dump a serializable container after a comment line with log information.
std::ostream & out()
Get the output stream on which to print.
std::map< level, fmt > _level_fmt
Dictionary of level identifier to their format.
std::map< std::string, level > _word_level
Dictionary of level string to their identifier.
std::string format(std::string row, const std::string &what, const level &stage, const std::string &file, const std::string &func, const size_t line) const
Substitute all tags in the format string with the corresponding information and apply the style corre...
void style(level stage, FMT... styles)
Set the style (color and typo) of the given log level.
static size_t default_hfill_max
Default maximum width (number of characters) for which to fill for right-aligning the right part of m...
void funchash_styles(std::vector< fmt > styles)
Set the candidate styles for value-dependant function name formatting.
static std::string dump_default_format
Default format of the comment line in file dump.
level level_of(const std::string name)
Return the log level tag corresponding to the given pre-configured name.
void style(level stage, fmt style)
Set the style (color and typo) of the given log level, passing a fmt instance.
void func(std::string func)
Set the regular expression filtering the function location.
std::regex _in_file
Current file location filter.
void filehash_styles(std::vector< fmt > styles)
Set the candidate styles for value-dependant file name formatting.
std::string replace(const std::string &form, const std::string &mark, const size_t tag) const
Replace mark by tag in form, converting tag to its string representation first.
level _stage
Current log level.
static std::string dump_default_sep
Default item separator for dump.
std::string format() const
Get the template string.
#define CLUTCHLOG_HAVE_UNIX_SYSINFO
True if POSIX headers necessary for stack depth management are available.
#define CLUTCHDUMP_DEFAULT_FORMAT
Compile-time default format of the comment line in file dump.
#define CLUTCHLOG_DEFAULT_FORMAT
bg
Background color codes.
fg
Foreground color codes.
enum clutchlog::fmt::fg fore
Foreground color.
enum clutchlog::fmt::bg back
Background color.
friend std::ostream & operator<<(std::ostream &os, const typo &s)
Output stream operator for a typo tag alone, in 16-colors mode.
friend std::ostream & operator<<(std::ostream &os, const std::tuple< fg, bg, typo > &fbs)
Output stream operator for a 3-tuple of 16-colors mode tags.
clutchlog::fmt::bg_256 back_256
Current background in 256-colors mode.
clutchlog::fmt::fg_16M fore_16M
Current foreground in 16M-colors mode.
clutchlog::fmt::bg_16M back_16M
Current background in 16M-colors mode.
clutchlog::fmt::fg_256 fore_256
Current foreground in 256-colors mode.
background in 256-colors mode.
bg_16M()
Empty constructor: no color.
bg_16M(const bg &)
Conversion constructor from 16-colors mode.
bg_16M(short r, short g, short b)
Numeric triplet constructor.
bg_16M(const std::string &srgb)
Hex triplet string constructor.
Background in 256-colors mode.
bg_256(const bg &)
Conversion constructor from 16-colors mode.
bg_256()
Empty constructor: no color.
bg_256(const short b)
Constructor.
Abstract base class for 16M colors objects (24-bits ANSI).
short red
The encoded RGB indices.
color_16M(ground t, short r, short g, short b)
Numeric triplet constructor.
color_16M(ground t, const std::string &srgb)
Hex triplet string constructor.
bool is_set() const
Returns true if the underying representation encodes an existing color.
std::ostream & print_on(std::ostream &os) const
Print the color RGB triplet on the given stream.
color_16M(ground t)
Constructor.
Abstract base class for 256 colors objects (8-bits ANSI).
color_256(ground t)
Constructor.
color_256(ground t, const short i)
Constructor.
short index
The encoded color index in 4-bits ANSI.
std::ostream & print_on(std::ostream &os) const
Print the color index on the given stream.
bool is_set() const
Returns true if the underying representation encodes an existing color.
Interface class for colors representation.
virtual std::ostream & print_on(std::ostream &os) const =0
Should print the underlying representation on the given stream.
enum clutchlog::fmt::color::ground type
Type of color (foreground or background).
friend std::ostream & operator<<(std::ostream &os, const color &c)
Print the actually encoded escaped color sequence on the given stream.
color(ansi a, ground g)
Constructor.
virtual bool is_set() const =0
Should return true if the underying representation encodes an existing color.
ground
Codes for representing foreground or background.
Foreground in 256-colors mode.
fg_16M(short r, short g, short b)
Numeric triplet constructor.
fg_16M()
Empty constructor: no color.
fg_16M(const fg &)
Conversion constructor from 16-colors mode.
fg_16M(const std::string &srgb)
Hex triplet string constructor.
Foreground in 256-colors mode.
fg_256(const fg &)
Conversion constructor from 16-colors mode.
fg_256(const short f)
Constructor.
fg_256()
Empty constructor: no color.
Structure holding a location matching.
bool there
Location is compatible.
level stage
Current log level.
bool matches
Everything is compatible.