
commit
69493bc857
13 changed files with 1069 additions and 0 deletions
@ -0,0 +1,42 @@ |
|||||
|
BasedOnStyle: LLVM |
||||
|
ReflowComments: false |
||||
|
|
||||
|
MacroBlockBegin: "^BEGIN_OPERATOR" |
||||
|
MacroBlockEnd: "^END_OPERATOR" |
||||
|
|
||||
|
Language: Cpp |
||||
|
DerivePointerAlignment: true |
||||
|
SortIncludes: Never |
||||
|
PointerAlignment: Left |
||||
|
AlignAfterOpenBracket: AlwaysBreak |
||||
|
AlignOperands: AlignAfterOperator |
||||
|
AlignTrailingComments: true |
||||
|
AllowAllArgumentsOnNextLine: false |
||||
|
AllowAllParametersOfDeclarationOnNextLine: false |
||||
|
AllowShortEnumsOnASingleLine: false |
||||
|
AllowShortFunctionsOnASingleLine: Empty |
||||
|
AllowShortIfStatementsOnASingleLine: Never |
||||
|
AllowShortLoopsOnASingleLine: false |
||||
|
BinPackArguments: false |
||||
|
BinPackParameters: false |
||||
|
ExperimentalAutoDetectBinPacking: true |
||||
|
BreakBeforeBraces: Custom |
||||
|
BraceWrapping: |
||||
|
AfterFunction: true |
||||
|
ColumnLimit: 100 |
||||
|
AlwaysBreakAfterDefinitionReturnType: None |
||||
|
AlwaysBreakAfterReturnType: None |
||||
|
PenaltyBreakBeforeFirstCallParameter: 0 |
||||
|
PenaltyReturnTypeOnItsOwnLine: 1000000 |
||||
|
PenaltyBreakAssignment: 1000000 |
||||
|
PenaltyExcessCharacter: 10 |
||||
|
IndentCaseLabels: true |
||||
|
IndentWidth: 4 |
||||
|
MaxEmptyLinesToKeep: 2 |
||||
|
NamespaceIndentation: All |
||||
|
SpaceAfterTemplateKeyword: false |
||||
|
AccessModifierOffset: -4 |
||||
|
AllowShortBlocksOnASingleLine: Always |
||||
|
IndentPPDirectives: BeforeHash |
||||
|
IndentExternBlock: Indent |
||||
|
Cpp11BracedListStyle: false |
@ -0,0 +1,35 @@ |
|||||
|
|
||||
|
# Build config |
||||
|
/build.conf |
||||
|
/.idea |
||||
|
|
||||
|
# Prerequisites |
||||
|
*.d |
||||
|
|
||||
|
# Object files |
||||
|
*.o |
||||
|
|
||||
|
# Precompiled Headers |
||||
|
*.gch |
||||
|
*.pch |
||||
|
|
||||
|
# Libraries |
||||
|
*.a |
||||
|
|
||||
|
# Executables |
||||
|
/src/main_cli |
||||
|
/src/main_tui |
||||
|
|
||||
|
# Debug files |
||||
|
*.dSYM/ |
||||
|
*.su |
||||
|
*.idb |
||||
|
*.pdb |
||||
|
|
||||
|
#Test |
||||
|
/test/test_main |
||||
|
/test/test_main2 |
||||
|
/test/test_log |
||||
|
/test/test_log_cxx |
||||
|
/test/customfile.log |
||||
|
/test/newlogfile.log |
@ -0,0 +1,21 @@ |
|||||
|
MIT License |
||||
|
|
||||
|
Copyright (c) 2017 Hundredrabbits |
||||
|
|
||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
|
of this software and associated documentation files (the "Software"), to deal |
||||
|
in the Software without restriction, including without limitation the rights |
||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
|
copies of the Software, and to permit persons to whom the Software is |
||||
|
furnished to do so, subject to the following conditions: |
||||
|
|
||||
|
The above copyright notice and this permission notice shall be included in all |
||||
|
copies or substantial portions of the Software. |
||||
|
|
||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
|
SOFTWARE. |
@ -0,0 +1,13 @@ |
|||||
|
.PHONY: all test src clean |
||||
|
|
||||
|
all: test src |
||||
|
|
||||
|
src: |
||||
|
$(MAKE) -C src |
||||
|
|
||||
|
test: |
||||
|
$(MAKE) -C test |
||||
|
|
||||
|
clean: |
||||
|
$(MAKE) -C src clean |
||||
|
$(MAKE) -C test clean |
@ -0,0 +1,80 @@ |
|||||
|
LIBNAME:=heck_log |
||||
|
LIB:=lib$(LIBNAME).a |
||||
|
|
||||
|
C_LANG_VERSION=c99 |
||||
|
CXX_LANG_VERSION=c++17 |
||||
|
|
||||
|
# Build option defaults
|
||||
|
PREFIX?=$(HOME)/local |
||||
|
SYS_PREFIX?=/opt/local |
||||
|
DEBUG?=1 |
||||
|
|
||||
|
COMPILE_FLAGS:= -MMD |
||||
|
|
||||
|
CFLAGS:=-std=$(C_LANG_VERSION) |
||||
|
CFLAGS+=\
|
||||
|
-finput-charset=UTF-8 \
|
||||
|
-Wpedantic \
|
||||
|
-Wextra \
|
||||
|
-Wwrite-strings \
|
||||
|
-Wconversion \
|
||||
|
-Wshadow \
|
||||
|
# -Wstrict-prototypes \
|
||||
|
# -Werror=implicit-function-declaration \
|
||||
|
-Werror=implicit-int \
|
||||
|
-Werror=incompatible-pointer-types \
|
||||
|
-Werror=int-conversion \
|
||||
|
-Wno-missing-field-initializers \
|
||||
|
|
||||
|
CXXFLAGS:=-std=$(CXX_LANG_VERSION) |
||||
|
CXXFLAGS+=\
|
||||
|
-fPIC \
|
||||
|
-Wall \
|
||||
|
-Wextra \
|
||||
|
-pedantic |
||||
|
|
||||
|
ifneq (,$(findstring g++,$(CXX))) |
||||
|
COMPILE_FLAGS+=-fdiagnostics-color=always |
||||
|
else ifneq (,$(findstring clang,$(CXX))) |
||||
|
COMPILE_FLAGS+=-fcolor-diagnostics |
||||
|
endif |
||||
|
|
||||
|
LIBS:=-lstdc++ |
||||
|
#-lpEpCxx11
|
||||
|
|
||||
|
LDFLAGS+=$(LIBS) |
||||
|
|
||||
|
######### Overrides from build.conf #########
|
||||
|
HERE:=$(dir $(lastword $(MAKEFILE_LIST))) |
||||
|
-include $(HERE)build.conf |
||||
|
|
||||
|
COMPILE_FLAGS+=-isystem$(SYS_PREFIX)/include |
||||
|
COMPILE_FLAGS+=-I$(PREFIX)/include |
||||
|
LDFLAGS+=-L$(SYS_PREFIX)/lib |
||||
|
LDFLAGS+=-L$(PREFIX)/lib |
||||
|
|
||||
|
ifeq ($(DEBUG),1) |
||||
|
COMPILE_FLAGS+=-g -O0 -DDEBUG |
||||
|
# -fsanitize=address \
|
||||
|
# -fsanitize=undefined \
|
||||
|
# -fsanitize=float-divide-by-zero \
|
||||
|
# -fsanitize=implicit-conversion \
|
||||
|
# -fsanitize=unsigned-integer-overflow
|
||||
|
else |
||||
|
COMPILE_FLAGS+=-DNDEBUG -O2 -g0 |
||||
|
endif |
||||
|
|
||||
|
ifeq ($(PORTMIDI_ENABLED),1) |
||||
|
COMPILE_FLAGS+= -DFEAT_PORTMIDI |
||||
|
LDFLAGS+= -lportmidi |
||||
|
endif |
||||
|
|
||||
|
ifeq ($(MOUSE_ENABLED),0) |
||||
|
COMPILE_FLAGS+=-DFEAT_NOMOUSE |
||||
|
endif |
||||
|
|
||||
|
CXXFLAGS+=$(COMPILE_FLAGS) |
||||
|
CFLAGS+=$(COMPILE_FLAGS) |
||||
|
|
||||
|
$(info C-Compiler: $(shell $(CC) --version)) |
||||
|
$(info C++-Compiler: $(shell $(CXX) --version)) |
@ -0,0 +1,3 @@ |
|||||
|
# HeckLog |
||||
|
|
||||
|
a little logging lib for mixed C and C++ projects, supporting linkage for both. |
@ -0,0 +1,5 @@ |
|||||
|
# The following values reflect the defaults |
||||
|
# uncomment and adjust |
||||
|
|
||||
|
# DEBUG?=1 |
||||
|
# PREFIX=/opt/local |
@ -0,0 +1,32 @@ |
|||||
|
include ../Makefile.conf |
||||
|
|
||||
|
SRC:=$(wildcard *.c*) |
||||
|
SRC_EXE:=$(filter main_%, $(SRC)) |
||||
|
SRC_LIB=$(filter-out main_%, $(SRC)) |
||||
|
OBJS:=$(addsuffix .o, $(basename $(SRC))) |
||||
|
OBJS_LIB:=$(addsuffix .o, $(basename $(SRC_LIB))) |
||||
|
EXE:=$(basename $(SRC_EXE)) |
||||
|
DEPS:=$(addsuffix .d, $(basename $(SRC))) |
||||
|
|
||||
|
.PHONY: all install uninstall clean |
||||
|
.DEFAULT_GOAL:= all |
||||
|
|
||||
|
ifneq ($(MAKECMDGOALS),clean) |
||||
|
-include $(DEPS) |
||||
|
endif |
||||
|
|
||||
|
all: $(EXE) |
||||
|
|
||||
|
$(LIB): $(OBJS) |
||||
|
$(AR) -rc $@ $(OBJS_LIB) |
||||
|
|
||||
|
$(EXE) : $(LIB) |
||||
|
|
||||
|
clean: |
||||
|
rm -rf \
|
||||
|
$(OBJS) \
|
||||
|
$(EXE) \
|
||||
|
$(LIB) \
|
||||
|
$(DEPS) \
|
||||
|
*.dSYM \
|
||||
|
*.h.gch |
@ -0,0 +1,465 @@ |
|||||
|
#include "log.h" |
||||
|
#include <iostream> |
||||
|
#include <sstream> |
||||
|
#include <cstdarg> |
||||
|
#include <unistd.h> |
||||
|
#include <thread> |
||||
|
#include <string_view> |
||||
|
#include <cmath> |
||||
|
#include <filesystem> |
||||
|
#include <fstream> |
||||
|
|
||||
|
//-------------------------------------------------------------------------------------------------
|
||||
|
// Internal functions Prototypes
|
||||
|
// Global State
|
||||
|
//-------------------------------------------------------------------------------------------------
|
||||
|
#ifdef __cplusplus |
||||
|
extern "C" { |
||||
|
#endif |
||||
|
const char* _heck_log_level_to_string(const HECK_LOG_LEVEL* level); |
||||
|
bool _heck_logfile_open(void); |
||||
|
void _heck_logfile_close(void); |
||||
|
#ifdef __cplusplus |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
namespace Heck { |
||||
|
namespace Utils { |
||||
|
std::atomic<int> termsize_x = 120; |
||||
|
std::string _to_termcol(const HECK_LOG_COLOR& col); |
||||
|
std::string _decorate_three_lines(std::string_view msg, char decoration = '-'); |
||||
|
std::string _decorate_centered(std::string_view msg, char decoration = '-'); |
||||
|
} // namespace Utils
|
||||
|
namespace Log { |
||||
|
std::atomic<HECK_LOG_LEVEL> _log_level{ HECK_LOG_LEVEL_NONE }; |
||||
|
std::atomic<HECK_LOG_COLOR> _log_color{ HECK_LOG_COLOR_WHITE }; |
||||
|
namespace Backend { |
||||
|
std::mutex _mtx_backends{}; |
||||
|
HECK_LOG_BACKEND |
||||
|
_backends = (HECK_LOG_BACKEND)(HECK_LOG_BACKEND_STDOUT | HECK_LOG_BACKEND_FILE); |
||||
|
void _dispatcher(std::string_view msg, HECK_LOG_COLOR col = HECK_LOG_COLOR_DEFAULT); |
||||
|
namespace Console { |
||||
|
std::mutex _mtx_stdout{}; |
||||
|
void _write_stdout(std::string_view msg, HECK_LOG_COLOR col = HECK_LOG_COLOR_DEFAULT); |
||||
|
std::mutex _mtx_stderr{}; |
||||
|
void _write_stderr(std::string_view msg, HECK_LOG_COLOR col = HECK_LOG_COLOR_DEFAULT); |
||||
|
} // namespace Console
|
||||
|
namespace Logfile { |
||||
|
std::recursive_mutex _mtx_path{}; |
||||
|
std::filesystem::path _path{ "heck.log" }; |
||||
|
std::recursive_mutex _mtx_stream{}; |
||||
|
std::ofstream _stream{}; |
||||
|
std::atomic<bool> _clear_on_open{ true }; |
||||
|
void _write(std::string_view msg); |
||||
|
} // namespace Logfile
|
||||
|
} // namespace Backend
|
||||
|
} // namespace Log
|
||||
|
} // namespace Heck
|
||||
|
|
||||
|
//-------------------------------------------------------------------------------------------------
|
||||
|
// C linkage functions
|
||||
|
//-------------------------------------------------------------------------------------------------
|
||||
|
#ifdef __cplusplus |
||||
|
extern "C" { |
||||
|
#endif |
||||
|
void heck_log_level_set(HECK_LOG_LEVEL level) |
||||
|
{ |
||||
|
Heck::Log::_log_level = level; |
||||
|
} |
||||
|
|
||||
|
HECK_LOG_LEVEL heck_log_level_get(void) |
||||
|
{ |
||||
|
return Heck::Log::_log_level; |
||||
|
} |
||||
|
|
||||
|
void heck_log_backends_set(HECK_LOG_BACKEND backend) |
||||
|
{ |
||||
|
std::lock_guard<std::mutex> l{ Heck::Log::Backend::_mtx_backends }; |
||||
|
Heck::Log::Backend::_backends = backend; |
||||
|
} |
||||
|
|
||||
|
HECK_LOG_BACKEND heck_log_backend_get(void) |
||||
|
{ |
||||
|
std::lock_guard<std::mutex> l{ Heck::Log::Backend::_mtx_backends }; |
||||
|
return Heck::Log::Backend::_backends; |
||||
|
} |
||||
|
|
||||
|
void heck_log_logfile_path_set(const char* path) |
||||
|
{ |
||||
|
std::lock_guard<std::recursive_mutex> l{ Heck::Log::Backend::Logfile::_mtx_path }; |
||||
|
std::lock_guard<std::recursive_mutex> l2{ Heck::Log::Backend::Logfile::_mtx_stream }; |
||||
|
Heck::Log::Backend::Logfile::_path = path; |
||||
|
if (Heck::Log::Backend::Logfile::_stream.is_open()) { |
||||
|
Heck::Log::Backend::Logfile::_stream.close(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void heck_log_logfile_path_get(const char** path) |
||||
|
{ |
||||
|
std::lock_guard<std::recursive_mutex> l{ Heck::Log::Backend::Logfile::_mtx_path }; |
||||
|
*path = Heck::Log::Backend::Logfile::_path.c_str(); |
||||
|
} |
||||
|
|
||||
|
void heck_log_color_set(HECK_LOG_COLOR col) |
||||
|
{ |
||||
|
if (col == HECK_LOG_COLOR_DEFAULT) { |
||||
|
col = HECK_LOG_COLOR_RESET; |
||||
|
} |
||||
|
Heck::Log::_log_color = col; |
||||
|
} |
||||
|
|
||||
|
HECK_LOG_COLOR heck_log_color_get(void) |
||||
|
{ |
||||
|
return Heck::Log::_log_color; |
||||
|
} |
||||
|
|
||||
|
void heck_log_logfile_clear_on_open_set(bool clear) |
||||
|
{ |
||||
|
Heck::Log::Backend::Logfile::_clear_on_open = clear; |
||||
|
} |
||||
|
|
||||
|
bool heck_log_logfile_clear_on_open_get(void) |
||||
|
{ |
||||
|
return Heck::Log::Backend::Logfile::_clear_on_open; |
||||
|
} |
||||
|
|
||||
|
void heck_log(const char* msg) |
||||
|
{ |
||||
|
Heck::Log::Backend::_dispatcher(msg, Heck::Log::_log_color); |
||||
|
} |
||||
|
|
||||
|
void heck_log_h1(const char* msg) |
||||
|
{ |
||||
|
Heck::Log::Backend::_dispatcher( |
||||
|
Heck::Utils::_decorate_three_lines(msg, '='), |
||||
|
Heck::Log::_log_color); |
||||
|
} |
||||
|
|
||||
|
void heck_log_h2(const char* msg) |
||||
|
{ |
||||
|
Heck::Log::Backend::_dispatcher( |
||||
|
"\n" + Heck::Utils::_decorate_centered(msg, '='), |
||||
|
Heck::Log::_log_color); |
||||
|
} |
||||
|
|
||||
|
void heck_log_h3(const char* msg) |
||||
|
{ |
||||
|
Heck::Log::Backend::_dispatcher( |
||||
|
Heck::Utils::_decorate_centered(msg, '-'), |
||||
|
Heck::Log::_log_color); |
||||
|
} |
||||
|
|
||||
|
void _heck_log_for_macro( |
||||
|
HECK_LOG_LEVEL level, |
||||
|
const char* file, |
||||
|
int line, |
||||
|
const char* funcname, |
||||
|
const char* fmt, |
||||
|
...) |
||||
|
{ |
||||
|
if (level > Heck::Log::_log_level) { |
||||
|
return; |
||||
|
} |
||||
|
std::string msg{ "heck log subsystem error" }; |
||||
|
va_list var_args; |
||||
|
va_start(var_args, fmt); |
||||
|
|
||||
|
char* msg_fmtd = nullptr; |
||||
|
int size = vasprintf(&msg_fmtd, fmt, var_args); |
||||
|
if (size >= 0) { |
||||
|
std::stringstream header{}; |
||||
|
header << _heck_log_level_to_string(&level) << " "; |
||||
|
header << getpid() << " "; |
||||
|
header << std::this_thread::get_id() << " "; |
||||
|
header << file << ":"; |
||||
|
header << line << " "; |
||||
|
header << funcname << " "; |
||||
|
msg = header.str(); |
||||
|
std::string_view msg_fmtd_cxx{ msg_fmtd }; |
||||
|
if (!msg_fmtd_cxx.empty()) { |
||||
|
msg += "- "; |
||||
|
msg += msg_fmtd_cxx; |
||||
|
} |
||||
|
} |
||||
|
free(msg_fmtd); |
||||
|
Heck::Log::Backend::_dispatcher(msg); |
||||
|
va_end(var_args); |
||||
|
} |
||||
|
|
||||
|
const char* _heck_log_level_to_string(const HECK_LOG_LEVEL* level) |
||||
|
{ |
||||
|
switch (*level) { |
||||
|
case HECK_LOG_LEVEL_NONE: |
||||
|
return "NONE"; |
||||
|
case HECK_LOG_LEVEL_ERROR: |
||||
|
return "ERROR"; |
||||
|
case HECK_LOG_LEVEL_WARN: |
||||
|
return "WARN"; |
||||
|
case HECK_LOG_LEVEL_INFO: |
||||
|
return "INFO"; |
||||
|
case HECK_LOG_LEVEL_ALL: |
||||
|
return "ALL"; |
||||
|
default: |
||||
|
return "invalid log level"; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bool _heck_logfile_open(void) |
||||
|
{ |
||||
|
std::lock_guard<std::recursive_mutex> l{ Heck::Log::Backend::Logfile::_mtx_stream }; |
||||
|
std::lock_guard<std::recursive_mutex> l2{ Heck::Log::Backend::Logfile::_mtx_path }; |
||||
|
|
||||
|
if (Heck::Log::Backend::Logfile::_stream.is_open()) { |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
// Append or clear
|
||||
|
unsigned int openmode = std::ios::app; |
||||
|
if (Heck::Log::Backend::Logfile::_clear_on_open) { |
||||
|
openmode = std::ios::out | std::ios::trunc; |
||||
|
} |
||||
|
|
||||
|
Heck::Log::Backend::Logfile::_stream.open(Heck::Log::Backend::Logfile::_path, openmode); |
||||
|
if (Heck::Log::Backend::Logfile::_stream.fail()) { |
||||
|
// TODO: Where to log error
|
||||
|
std::cerr << "LOGFILE ERROR" << std::endl; |
||||
|
Heck::Log::Backend::Logfile::_stream.clear(); |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
void _heck_logfile_close(void) |
||||
|
{ |
||||
|
std::lock_guard<std::recursive_mutex> l{ Heck::Log::Backend::Logfile::_mtx_stream }; |
||||
|
Heck::Log::Backend::Logfile::_stream.close(); |
||||
|
} |
||||
|
|
||||
|
#ifdef __cplusplus |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
//-------------------------------------------------------------------------------------------------
|
||||
|
// C++ Linkage functions
|
||||
|
//-------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
namespace Heck { |
||||
|
namespace Log { |
||||
|
// for C++ some functions are just wrappers for the
|
||||
|
// C linkage functions
|
||||
|
// to be nicely available in the namespace
|
||||
|
// C linkage functions are mutexed and therefore
|
||||
|
// wrapped here even if otherwise trivial
|
||||
|
|
||||
|
void set_level(HECK_LOG_LEVEL level) |
||||
|
{ |
||||
|
::heck_log_level_set(level); |
||||
|
} |
||||
|
|
||||
|
HECK_LOG_LEVEL get_level() |
||||
|
{ |
||||
|
return ::heck_log_level_get(); |
||||
|
} |
||||
|
|
||||
|
void set_color(HECK_LOG_COLOR col) |
||||
|
{ |
||||
|
::heck_log_color_set(col); |
||||
|
} |
||||
|
|
||||
|
HECK_LOG_COLOR get_color() |
||||
|
{ |
||||
|
return ::heck_log_color_get(); |
||||
|
} |
||||
|
|
||||
|
void _log_for_macro( |
||||
|
HECK_LOG_LEVEL level, |
||||
|
const std::string& file, |
||||
|
int line, |
||||
|
const std::string& funcname, |
||||
|
const std::string& msg) |
||||
|
{ |
||||
|
::_heck_log_for_macro(level, file.c_str(), line, funcname.c_str(), "%s", msg.c_str()); |
||||
|
} |
||||
|
|
||||
|
void log(std::string_view msg, HECK_LOG_COLOR col) |
||||
|
{ |
||||
|
Backend::_dispatcher(msg, col); |
||||
|
} |
||||
|
|
||||
|
void logH1(std::string_view msg, HECK_LOG_COLOR col) |
||||
|
{ |
||||
|
Backend::_dispatcher(Utils::_decorate_three_lines(msg, '='), col); |
||||
|
} |
||||
|
|
||||
|
void logH2(std::string_view msg, HECK_LOG_COLOR col) |
||||
|
{ |
||||
|
Backend::_dispatcher("\n" + Utils::_decorate_centered(msg, '='), col); |
||||
|
} |
||||
|
|
||||
|
void logH3(std::string_view msg, HECK_LOG_COLOR col) |
||||
|
{ |
||||
|
Backend::_dispatcher(Utils::_decorate_centered(msg, '-'), col); |
||||
|
} |
||||
|
|
||||
|
namespace Backend { |
||||
|
void set_backends(HECK_LOG_BACKEND backend) |
||||
|
{ |
||||
|
::heck_log_backends_set(backend); |
||||
|
} |
||||
|
|
||||
|
HECK_LOG_BACKEND get_backends() |
||||
|
{ |
||||
|
return ::heck_log_backend_get(); |
||||
|
} |
||||
|
|
||||
|
void _dispatcher(std::string_view msg, HECK_LOG_COLOR col) |
||||
|
{ |
||||
|
std::lock_guard<std::mutex> l{ Heck::Log::Backend::_mtx_backends }; |
||||
|
if (_backends & HECK_LOG_BACKEND_STDOUT) { |
||||
|
Console::_write_stdout(msg, col); |
||||
|
} |
||||
|
if (_backends & HECK_LOG_BACKEND_STDERR) { |
||||
|
Console::_write_stderr(msg, col); |
||||
|
} |
||||
|
if (_backends & HECK_LOG_BACKEND_FILE) { |
||||
|
Logfile::_write(msg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
namespace Console { |
||||
|
void _write_stdout(std::string_view msg, HECK_LOG_COLOR col) |
||||
|
{ |
||||
|
std::lock_guard<std::mutex> l{ _mtx_stdout }; |
||||
|
std::cerr << Utils::_to_termcol(col) << msg |
||||
|
<< Utils::_to_termcol(HECK_LOG_COLOR_RESET) |
||||
|
<< std::endl; //endl also flushes, but cerr is unbuffered anyways
|
||||
|
} |
||||
|
void _write_stderr(std::string_view msg, HECK_LOG_COLOR col) |
||||
|
{ |
||||
|
std::lock_guard<std::mutex> l{ _mtx_stderr }; |
||||
|
std::cerr << Utils::_to_termcol(col) << msg |
||||
|
<< Utils::_to_termcol(HECK_LOG_COLOR_RESET) |
||||
|
<< std::endl; //endl also flushes, but cerr is unbuffered anyways
|
||||
|
} |
||||
|
} // namespace Console
|
||||
|
|
||||
|
namespace Logfile { |
||||
|
void _write(std::string_view msg) |
||||
|
{ |
||||
|
std::lock_guard<std::recursive_mutex> l{ _mtx_stream }; |
||||
|
if (!_heck_logfile_open()) { |
||||
|
std::cerr << "ERROR: Logfile open failed" << std::endl; |
||||
|
} else { |
||||
|
_stream << msg << std::endl; |
||||
|
if (_stream.fail()) { |
||||
|
std::cerr << "ERROR: Logfile Write failed" << std::endl; |
||||
|
_stream.clear(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void set_path(const std::filesystem::path& path) |
||||
|
{ |
||||
|
::heck_log_logfile_path_set(path.c_str()); |
||||
|
} |
||||
|
|
||||
|
const std::filesystem::path& get_path() |
||||
|
{ |
||||
|
std::lock_guard<std::recursive_mutex> l{ Heck::Log::Backend::Logfile::_mtx_path }; |
||||
|
return Heck::Log::Backend::Logfile::_path; |
||||
|
} |
||||
|
|
||||
|
void set_clear_on_open(bool clear) |
||||
|
{ |
||||
|
::heck_log_logfile_clear_on_open_set(clear); |
||||
|
} |
||||
|
|
||||
|
bool get_clear_on_open() |
||||
|
{ |
||||
|
return ::heck_log_logfile_clear_on_open_get(); |
||||
|
} |
||||
|
|
||||
|
} // namespace Logfile
|
||||
|
} // namespace Backend
|
||||
|
} // namespace Log
|
||||
|
|
||||
|
|
||||
|
namespace Utils { |
||||
|
std::string _to_termcol(const HECK_LOG_COLOR& col) |
||||
|
{ |
||||
|
switch (col) { |
||||
|
case HECK_LOG_COLOR_DEFAULT: |
||||
|
// Caution: Make sure Heck::Log::_log_color can
|
||||
|
// NEVER be set to HECK_LOG_COLOR_DEFAULT
|
||||
|
return _to_termcol(Heck::Log::_log_color); |
||||
|
case HECK_LOG_COLOR_RESET: |
||||
|
return "\033[0m"; |
||||
|
case HECK_LOG_COLOR_BLACK: |
||||
|
return "\033[30m"; |
||||
|
case HECK_LOG_COLOR_RED: |
||||
|
return "\033[31m"; |
||||
|
case HECK_LOG_COLOR_GREEN: |
||||
|
return "\033[32m"; |
||||
|
case HECK_LOG_COLOR_YELLOW: |
||||
|
return "\033[33m"; |
||||
|
case HECK_LOG_COLOR_BLUE: |
||||
|
return "\033[34m"; |
||||
|
case HECK_LOG_COLOR_MAGENTA: |
||||
|
return "\033[35m"; |
||||
|
case HECK_LOG_COLOR_CYAN: |
||||
|
return "\033[36m"; |
||||
|
case HECK_LOG_COLOR_WHITE: |
||||
|
return "\033[37m"; |
||||
|
default: |
||||
|
return _to_termcol(HECK_LOG_COLOR_RESET); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
std::string _decorate_three_lines(std::string_view msg, char decoration) |
||||
|
{ |
||||
|
std::stringstream tmp; |
||||
|
tmp << std::string(termsize_x, decoration) << std::endl |
||||
|
<< msg << std::endl |
||||
|
<< std::string(termsize_x, decoration); |
||||
|
return tmp.str(); |
||||
|
} |
||||
|
|
||||
|
std::string _decorate_centered(std::string_view msg, char decoration) |
||||
|
{ |
||||
|
std::stringstream tmp; |
||||
|
size_t max_len = termsize_x - 10; |
||||
|
// truncate msg
|
||||
|
std::string msg_truncated{ msg }; |
||||
|
if (msg.length() >= max_len) { |
||||
|
msg_truncated = msg.substr(0, max_len); |
||||
|
msg_truncated += "..."; |
||||
|
} |
||||
|
|
||||
|
// define decolen
|
||||
|
int decolen = static_cast<int>(floor((double(termsize_x - msg_truncated.length()))) / 2.0); |
||||
|
|
||||
|
tmp << std::string(decolen, decoration) << ' ' << msg_truncated << ' ' |
||||
|
<< std::string(decolen, decoration); |
||||
|
return tmp.str(); |
||||
|
} |
||||
|
} // namespace Utils
|
||||
|
} // namespace Heck
|
||||
|
|
||||
|
//-------------------------------------------------------------------------------------------------
|
||||
|
// C++ Linkage global namespace members
|
||||
|
//-------------------------------------------------------------------------------------------------
|
||||
|
std::ostream& operator<<(std::ostream& o, const HECK_LOG_LEVEL* level) |
||||
|
{ |
||||
|
return o << std::string_view(_heck_log_level_to_string(level)); |
||||
|
} |
||||
|
|
||||
|
// Stuff like that would be fucking handy
|
||||
|
// TODO: make a lib with operator<< for ALL libstc++ types
|
||||
|
template<typename T> std::ostream& operator<<(std::ostream& o, std::vector<T>& vec) |
||||
|
{ |
||||
|
std::stringstream ss{}; |
||||
|
for (const T& elem : vec) { |
||||
|
o << elem; |
||||
|
} |
||||
|
return o; |
||||
|
} |
@ -0,0 +1,148 @@ |
|||||
|
#ifndef _HECK_VALOG_H |
||||
|
#define _HECK_VALOG_H |
||||
|
|
||||
|
#define HECK_LOG_FUNCTION_ENTRY 1 |
||||
|
|
||||
|
#ifdef HECK_LOG_HAVE_PRETTY_FUNCTION |
||||
|
#define HECK_LOG_MACRO_FUNCNAME __PRETTY_FUNCTION__ |
||||
|
#else |
||||
|
#define HECK_LOG_MACRO_FUNCNAME __func__ |
||||
|
#endif |
||||
|
|
||||
|
typedef enum { |
||||
|
HECK_LOG_BACKEND_STDOUT = 1, |
||||
|
HECK_LOG_BACKEND_STDERR = 2, |
||||
|
HECK_LOG_BACKEND_FILE = 4 |
||||
|
} HECK_LOG_BACKEND; |
||||
|
|
||||
|
typedef enum { |
||||
|
HECK_LOG_LEVEL_NONE = 0, // Logging Disabled
|
||||
|
HECK_LOG_LEVEL_ERROR = 100, |
||||
|
HECK_LOG_LEVEL_WARN = 200, |
||||
|
HECK_LOG_LEVEL_INFO = 300, |
||||
|
HECK_LOG_LEVEL_ALL = 1000000 // Convenience
|
||||
|
} HECK_LOG_LEVEL; |
||||
|
|
||||
|
typedef enum { |
||||
|
HECK_LOG_COLOR_DEFAULT, |
||||
|
HECK_LOG_COLOR_RESET, |
||||
|
HECK_LOG_COLOR_BLACK, |
||||
|
HECK_LOG_COLOR_RED, |
||||
|
HECK_LOG_COLOR_GREEN, |
||||
|
HECK_LOG_COLOR_YELLOW, |
||||
|
HECK_LOG_COLOR_BLUE, |
||||
|
HECK_LOG_COLOR_MAGENTA, |
||||
|
HECK_LOG_COLOR_CYAN, |
||||
|
HECK_LOG_COLOR_WHITE, |
||||
|
} HECK_LOG_COLOR; |
||||
|
|
||||
|
|
||||
|
//---------------------------------------------------------------------------------------
|
||||
|
// C99
|
||||
|
//---------------------------------------------------------------------------------------
|
||||
|
#ifndef __cplusplus |
||||
|
#include <stdbool.h> |
||||
|
|
||||
|
#define HECK_LOG_ERR(...) HECK_LOG(HECK_LOG_LEVEL_ERROR, __VA_ARGS__) |
||||
|
|
||||
|
#define HECK_LOG_WARN(...) HECK_LOG(HECK_LOG_LEVEL_WARN, __VA_ARGS__) |
||||
|
|
||||
|
#define HECK_LOG_INFO(...) HECK_LOG(HECK_LOG_LEVEL_INFO, __VA_ARGS__) |
||||
|
|
||||
|
#define HECK_LOG(level, ...) \ |
||||
|
do { \ |
||||
|
_heck_log_for_macro(level, __FILE__, __LINE__, HECK_LOG_MACRO_FUNCNAME, "" __VA_ARGS__); \ |
||||
|
} while (0) |
||||
|
|
||||
|
// config/settings
|
||||
|
void heck_log_level_set(HECK_LOG_LEVEL level); |
||||
|
HECK_LOG_LEVEL heck_log_level_get(void); |
||||
|
|
||||
|
void heck_log_backends_set(HECK_LOG_BACKEND backend); |
||||
|
HECK_LOG_BACKEND heck_log_backend_get(void); |
||||
|
|
||||
|
void heck_log_logfile_path_set(const char* path); |
||||
|
void heck_log_logfile_path_get(const char** path); |
||||
|
|
||||
|
void heck_log_color_set(HECK_LOG_COLOR col); |
||||
|
HECK_LOG_COLOR heck_log_color_get(void); |
||||
|
|
||||
|
void heck_log_logfile_clear_on_open_set(bool clear); |
||||
|
bool heck_log_logfile_clear_on_open_get(void); |
||||
|
|
||||
|
// logging
|
||||
|
void heck_log(const char* msg); |
||||
|
void heck_log_h1(const char* msg); |
||||
|
void heck_log_h2(const char* msg); |
||||
|
void heck_log_h3(const char* msg); |
||||
|
|
||||
|
// helper function for macro use only
|
||||
|
void _heck_log_for_macro( |
||||
|
HECK_LOG_LEVEL level, |
||||
|
const char* file, |
||||
|
int line, |
||||
|
const char* funcname, |
||||
|
const char* fmt, |
||||
|
...); |
||||
|
|
||||
|
#endif // NOT __cplusplus
|
||||
|
|
||||
|
//---------------------------------------------------------------------------------------
|
||||
|
// C++
|
||||
|
//---------------------------------------------------------------------------------------
|
||||
|
#ifdef __cplusplus |
||||
|
#include <string> |
||||
|
#include <sstream> |
||||
|
#include <filesystem> |
||||
|
|
||||
|
#define HECK_LOG_ERR(msg) HECK_LOG(HECK_LOG_LEVEL_ERROR, msg) |
||||
|
|
||||
|
#define HECK_LOG_WARN(msg) HECK_LOG(HECK_LOG_LEVEL_WARN, msg) |
||||
|
|
||||
|
#define HECK_LOG_INFO(msg) HECK_LOG(HECK_LOG_LEVEL_INFO, msg) |
||||
|
|
||||
|
#define HECK_LOG(level, msg) \ |
||||
|
do { \ |
||||
|
std::stringstream ss{}; \ |
||||
|
ss << msg; \ |
||||
|
::Heck::Log::_log_for_macro(level, __FILE__, __LINE__, HECK_LOG_MACRO_FUNCNAME, ss.str()); \ |
||||
|
} while (0) |
||||
|
|
||||
|
namespace Heck { |
||||
|
namespace Log { |
||||
|
// config/settings
|
||||
|
void set_level(HECK_LOG_LEVEL level); |
||||
|
HECK_LOG_LEVEL get_level(); |
||||
|
void set_color(HECK_LOG_COLOR col); |
||||
|
HECK_LOG_COLOR get_color(); |
||||
|
|
||||
|
namespace Backend { |
||||
|
void set_backends(HECK_LOG_BACKEND backend); |
||||
|
HECK_LOG_BACKEND get_backends(); |
||||
|
namespace Logfile { |
||||
|
void set_path(const std::filesystem::path& path); |
||||
|
const std::filesystem::path& get_path(); |
||||
|
void set_clear_on_open(bool clear); |
||||
|
bool get_clear_on_open(); |
||||
|
} // namespace Logfile
|
||||
|
} // namespace Backend
|
||||
|
|
||||
|
// logging
|
||||
|
void log(std::string_view msg, HECK_LOG_COLOR col = HECK_LOG_COLOR_DEFAULT); |
||||
|
void logH1(std::string_view msg, HECK_LOG_COLOR col = HECK_LOG_COLOR_DEFAULT); |
||||
|
void logH2(std::string_view msg, HECK_LOG_COLOR col = HECK_LOG_COLOR_DEFAULT); |
||||
|
void logH3(std::string_view msg, HECK_LOG_COLOR col = HECK_LOG_COLOR_DEFAULT); |
||||
|
|
||||
|
// helper function for macro use only
|
||||
|
void _log_for_macro( |
||||
|
HECK_LOG_LEVEL level, |
||||
|
const std::string& file, |
||||
|
int line, |
||||
|
const std::string& funcname, |
||||
|
const std::string& msg); |
||||
|
} // namespace Log
|
||||
|
} // namespace Heck
|
||||
|
|
||||
|
std::ostream& operator<<(std::ostream& o, const HECK_LOG_LEVEL* level); |
||||
|
#endif //__cplusplus
|
||||
|
#endif |
@ -0,0 +1,31 @@ |
|||||
|
include ../Makefile.conf |
||||
|
|
||||
|
SRC:=$(wildcard *.c*) |
||||
|
SRC_EXE:=$(filter test_%, $(SRC)) |
||||
|
EXE:=$(basename $(SRC_EXE)) |
||||
|
|
||||
|
$(info src exe: $(SRC_EXE)) |
||||
|
$(info lib: $(LIB)) |
||||
|
$(info exe: $(EXE)) |
||||
|
|
||||
|
LDFLAGS+=-L../src |
||||
|
CFLAGS+=-I../src |
||||
|
CXXFLAGS+=-I../src |
||||
|
|
||||
|
.PHONY: lib all clean ../src/$(LIB) |
||||
|
.DEFAULT_GOAL := all |
||||
|
|
||||
|
all: $(EXE) |
||||
|
|
||||
|
../src/$(LIB): |
||||
|
$(MAKE) -C ../src $(LIB) |
||||
|
|
||||
|
$(EXE): ../src/$(LIB) |
||||
|
|
||||
|
clean: |
||||
|
rm -rf \
|
||||
|
$(OBJS) \
|
||||
|
$(EXE) \
|
||||
|
$(DEPS) \
|
||||
|
*.dSYM \
|
||||
|
*.h.gch |
@ -0,0 +1,95 @@ |
|||||
|
//#include <iostream>
|
||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
#include "../src/log.h" |
||||
|
#include <stdbool.h> |
||||
|
|
||||
|
// HECK LOG C usage
|
||||
|
|
||||
|
int main(void) |
||||
|
{ |
||||
|
// Test Levels
|
||||
|
{ |
||||
|
HECK_LOG_ERR("SHOULD NOT SEE THIS"); |
||||
|
|
||||
|
heck_log_level_set(HECK_LOG_LEVEL_ALL); |
||||
|
HECK_LOG_ERR(); |
||||
|
HECK_LOG_WARN(); |
||||
|
HECK_LOG_INFO(); |
||||
|
|
||||
|
heck_log_level_set(HECK_LOG_LEVEL_ERROR); |
||||
|
HECK_LOG_ERR(); |
||||
|
HECK_LOG_WARN("SHOULD NOT SEE THIS"); |
||||
|
HECK_LOG_INFO("SHOULD NOT SEE THIS"); |
||||
|
} |
||||
|
|
||||
|
// Logfile
|
||||
|
{ |
||||
|
const char *path = NULL; |
||||
|
heck_log_logfile_path_get(&path); |
||||
|
printf("LOGFILE PATH: %s\n", path); |
||||
|
heck_log_logfile_path_set("newlogfile.log"); |
||||
|
} |
||||
|
|
||||
|
// BASIC USAGE MACRO
|
||||
|
{ |
||||
|
heck_log_level_set(HECK_LOG_LEVEL_INFO); |
||||
|
// no message
|
||||
|
HECK_LOG_INFO(); |
||||
|
|
||||
|
// simple string literal
|
||||
|
HECK_LOG_INFO("HELLO"); |
||||
|
|
||||
|
// sprintf style formatting
|
||||
|
char *str2 = strdup("best"); |
||||
|
HECK_LOG_INFO("The %s number is %i", str2, 23); |
||||
|
free(str2); |
||||
|
|
||||
|
// does not compile, 1st must be literal fmt string
|
||||
|
// HECK_LOG_WARN(str1);
|
||||
|
} |
||||
|
|
||||
|
// BASIC USAGE FUNC
|
||||
|
{ |
||||
|
heck_log_level_set(HECK_LOG_LEVEL_INFO); |
||||
|
// literal
|
||||
|
heck_log("Literal RAW"); |
||||
|
|
||||
|
// c-string
|
||||
|
char *str2 = strdup("c-string RAW"); |
||||
|
heck_log(str2); |
||||
|
free(str2); |
||||
|
|
||||
|
heck_log_h1("HEADING 1"); |
||||
|
heck_log_h2("HEADING 2"); |
||||
|
heck_log_h3("HEADING 3"); |
||||
|
} |
||||
|
|
||||
|
// Colors functions only
|
||||
|
{ |
||||
|
heck_log_h1("Colors functions only"); |
||||
|
heck_log("DEFAULT COLOR"); |
||||
|
heck_log_color_set(HECK_LOG_COLOR_GREEN); |
||||
|
heck_log("DEFAULT COLOR AFTER SET GREEN"); |
||||
|
heck_log_color_set(HECK_LOG_COLOR_YELLOW); |
||||
|
strdup("YELLOW ONE OFF"); |
||||
|
heck_log(strdup("YELLOW ONE OFF")); |
||||
|
heck_log_color_set(HECK_LOG_COLOR_RESET); |
||||
|
heck_log("COLOR RESET"); |
||||
|
} |
||||
|
|
||||
|
// Colors using Macros
|
||||
|
{ |
||||
|
heck_log_h1("Colors using Macros"); |
||||
|
heck_log("DEFAULT COLOR"); |
||||
|
heck_log_color_set(HECK_LOG_COLOR_GREEN); |
||||
|
HECK_LOG_ERR("DEFAULT COLOR AFTER SET GREEN"); |
||||
|
heck_log_color_set(HECK_LOG_COLOR_YELLOW); |
||||
|
HECK_LOG_ERR("YELLOW ONE OFF"); |
||||
|
heck_log_color_set(HECK_LOG_COLOR_RESET); |
||||
|
HECK_LOG_ERR("COLOR RESET"); |
||||
|
} |
||||
|
|
||||
|
heck_log("ALL TEST SUCCESSFUL"); |
||||
|
} |
@ -0,0 +1,99 @@ |
|||||
|
//#include <iostream>
|
||||
|
//#include <stdio.h>
|
||||
|
#include <iostream> |
||||
|
#include <cstring> |
||||
|
#include "../src/log.h" |
||||
|
#include <string> |
||||
|
#include <vector> |
||||
|
|
||||
|
// HECK LOG C++ usage
|
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
// Test Levels
|
||||
|
{ |
||||
|
HECK_LOG_ERR("SHOULD NOT SEE THIS"); |
||||
|
|
||||
|
Heck::Log::set_level(HECK_LOG_LEVEL_ALL); |
||||
|
HECK_LOG_ERR(""); |
||||
|
HECK_LOG_WARN(""); |
||||
|
HECK_LOG_INFO(""); |
||||
|
|
||||
|
Heck::Log::set_level(HECK_LOG_LEVEL_ERROR); |
||||
|
HECK_LOG_ERR(""); |
||||
|
HECK_LOG_WARN("SHOULD NOT SEE THIS"); |
||||
|
HECK_LOG_INFO("SHOULD NOT SEE THIS"); |
||||
|
} |
||||
|
|
||||
|
// Logfile
|
||||
|
{ |
||||
|
std::cout << " LOGFILE PATH: " << Heck::Log::Backend::Logfile::get_path(); |
||||
|
Heck::Log::Backend::Logfile::set_path("newlogfile.log"); |
||||
|
} |
||||
|
|
||||
|
// BASIC USAGE MACRO
|
||||
|
{ |
||||
|
Heck::Log::set_level(HECK_LOG_LEVEL_INFO); |
||||
|
// no message
|
||||
|
HECK_LOG_INFO(""); |
||||
|
|
||||
|
// literals
|
||||
|
HECK_LOG_INFO("literal"); |
||||
|
|
||||
|
// string concats
|
||||
|
std::string str{ "casts" }; |
||||
|
HECK_LOG_ERR("everything " + str + " to a string"); |
||||
|
|
||||
|
// operator<< overloads
|
||||
|
int i{ 23 }; |
||||
|
HECK_LOG_ERR(i); |
||||
|
} |
||||
|
|
||||
|
// BASIC USAGE FUNCTIONS
|
||||
|
{ |
||||
|
Heck::Log::set_level(HECK_LOG_LEVEL_INFO); |
||||
|
// no message
|
||||
|
Heck::Log::log(""); |
||||
|
|
||||
|
// literals
|
||||
|
Heck::Log::log("literal"); |
||||
|
|
||||
|
// string concats
|
||||
|
std::string str{ "casts" }; |
||||
|
Heck::Log::log("everything " + str + " to a string"); |
||||
|
|
||||
|
// operator<< overloads
|
||||
|
// WONT compile, needs std::string
|
||||
|
// int i{ 23 };
|
||||
|
// Heck::Log::log(i);
|
||||
|
|
||||
|
Heck::Log::logH1("HEADING 1"); |
||||
|
Heck::Log::logH2("HEADING 2"); |
||||
|
Heck::Log::logH3("HEADING 3"); |
||||
|
} |
||||
|
|
||||
|
// Colors functions only
|
||||
|
{ |
||||
|
Heck::Log::logH1("Colors functions only"); |
||||
|
Heck::Log::log("BLUE LOG", HECK_LOG_COLOR_BLUE); |
||||
|
Heck::Log::log("DEFAULT COLOR"); |
||||
|
Heck::Log::set_color(HECK_LOG_COLOR_GREEN); |
||||
|
Heck::Log::log("DEFAULT COLOR AFTER SET GREEN"); |
||||
|
Heck::Log::log("YELLOW ONE OFF", HECK_LOG_COLOR_YELLOW); |
||||
|
Heck::Log::log("DEFAULT COLOR AGAIN"); |
||||
|
} |
||||
|
|
||||
|
// Colors using Macros
|
||||
|
{ |
||||
|
Heck::Log::set_color(HECK_LOG_COLOR_DEFAULT); |
||||
|
Heck::Log::logH1("Colors using Macros"); |
||||
|
HECK_LOG_ERR("DEFAULT COLOR"); |
||||
|
Heck::Log::log("BLUE LOG", HECK_LOG_COLOR_BLUE); |
||||
|
HECK_LOG_ERR("DEFAULT COLOR AGAIN"); |
||||
|
Heck::Log::set_color(HECK_LOG_COLOR_GREEN); |
||||
|
Heck::Log::log("YELLOW ONE OFF", HECK_LOG_COLOR_YELLOW); |
||||
|
HECK_LOG_ERR("DEFAULT COLOR GREEN"); |
||||
|
} |
||||
|
|
||||
|
Heck::Log::log("ALL TEST SUCCESSFUL"); |
||||
|
} |
Loading…
Reference in new issue