Browse Source

Moved: module pEpLog to libpEpCxx11

pull/15/head
heck 3 years ago
parent
commit
6df8386754
  1. 158
      src/pEpLog.cc
  2. 228
      src/pEpLog.hh

158
src/pEpLog.cc

@ -1,158 +0,0 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#include "pEpLog.hh"
#include <iostream>
#include <sstream>
#include <mutex>
#include <atomic>
#include <cmath>
#include "std_utils.hh"
#ifdef ANDROID
#include <android/log.h>
#endif
using namespace std;
namespace pEp {
namespace Adapter {
namespace pEpLog {
int line_width = 120;
// NON CLASS
mutex mtx;
atomic_bool is_enabled{ false };
void set_enabled(const bool& enabled)
{
is_enabled.store(enabled);
}
bool get_enabled()
{
return is_enabled.load();
}
// Common "print" function implementing the actual "backends"
void _log(const string& msg, Utils::Color col = Utils::Color::WHITE)
{
lock_guard<mutex> l(mtx);
#ifdef ANDROID
__android_log_print(ANDROID_LOG_DEBUG, "pEpDebugLog", "%s", msg.c_str());
#else
cerr << Utils::to_termcol(col) << msg << Utils::to_termcol(Utils::Color::RESET)
<< endl; //endl also flushes, but cerr is unbuffered anyways
#endif
}
void log(const string& msg, Utils::Color col)
{
_log(msg, col);
}
void logH1(const string& msg, Utils::Color col)
{
log(decorate_three_lines(msg, '='), col);
}
void logH2(const string& msg, Utils::Color col)
{
log("\n" + decorate_centered(msg, '='), col);
}
void logH3(const string& msg, Utils::Color col)
{
log(decorate_centered(msg, '-'), col);
}
string decorate_three_lines(const string& msg, char decoration)
{
stringstream tmp;
tmp << std::string(line_width, decoration) << endl
<< msg << endl
<< std::string(line_width, decoration);
return tmp.str();
}
string decorate_centered(const string& msg, char decoration)
{
stringstream tmp;
size_t max_len = line_width - 10;
// truncate msg
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(line_width - msg_truncated.length()))) / 2.0);
tmp << std::string(decolen, decoration) << ' ' << msg_truncated << ' '
<< std::string(decolen, decoration);
return tmp.str();
}
} // namespace pEpLog
} // namespace Adapter
} // namespace pEp
namespace pEp {
namespace Adapter {
namespace pEpLog {
// Class pEpLogger
int pEpLogger::auto_instance_nr = 0;
pEpLogger::pEpLogger(const string& classname, const bool& enabled) :
classname(classname), is_enabled(enabled)
{
auto_instance_nr++;
this->set_instancename(to_string(auto_instance_nr));
}
void pEpLogger::log(const string& msg, Utils::Color col) const
{
std::stringstream msg_;
msg_ << "[" << getpid() << " " << std::this_thread::get_id() << "]";
msg_ << " - ";
msg_ << this->get_classname() << "[" << this->get_instancename() << "]";
msg_ << " - " << msg;
this->logRaw(msg_.str(), col);
}
void pEpLogger::logRaw(const string& msg, Utils::Color col) const
{
if (this->is_enabled) {
_log(msg, col);
}
}
void pEpLogger::set_enabled(const bool& enabled)
{
this->is_enabled = enabled;
}
bool pEpLogger::get_enabled() const
{
return this->is_enabled;
}
string pEpLogger::get_classname() const
{
return this->classname;
}
void pEpLogger::set_instancename(const string& name)
{
this->instancename = name;
}
string pEpLogger::get_instancename() const
{
return this->instancename;
}
} // namespace pEpLog
} // namespace Adapter
} // namespace pEp

228
src/pEpLog.hh

@ -1,228 +0,0 @@
// This file is under GNU General Public License 3.0
// see LICENSE.txt
#ifndef LIBPEPADAPTER_PEPLOG_HH
#define LIBPEPADAPTER_PEPLOG_HH
// getpid
// Linux - unistd.h
// macOS - unistd.h
// Android - unistd.h
// Win - process.h
#ifdef WIN32
#include <process.h>
// TODO: once this works, move this to pEpEngine platform_windows.h and file a PR
#ifndef getpid
#define getpid() _getpid()
#endif
#else
#include <unistd.h>
#endif
#include <sstream>
#include <thread>
#include "std_utils.hh"
// pEpLog
// ======
// a "to be kept ultra small and simple" logging unit.
// featuring:
// * Logging macros that completely eliminate any logging calls in release-builds (NDEBUG)
// * thread safe (no interleave when logging from diff threads) TODO: pEpLogger: REALLY?
// * OS dependent backend switches:
// * android: __android_log_print
// * all other OS: cerr
// * Logging without any class/object (pEpLog / pEpLogRaw macros)
// * runtime switchable (on/off) only on a global level
// * Class backed Logging macros (pEpLogClass / pEpLogClassRaw)
// * * runtime switchable (on/off) on a class and object level
//
// There are already too many features and you might want even more and more.
// But the feature-policy of this logging unit is very restrictive, and there is a
// primary design goal to keep it very simple, maintainable and portable.
//
// pEpLog - logformat "thread - __FILE__::__FUNTION__ - <message>"
// To be used in a non-class/object context
#ifdef NDEBUG
#define pEpLog(msg) \
do { \
} while (0)
#else
#define pEpLog(msg) \
do { \
if (pEp::Adapter::pEpLog::get_enabled()) { \
std::stringstream msg_; \
msg_ << "[" << getpid() << " " << std::this_thread::get_id() << "]"; \
msg_ << " - " << __FILE__ << "::" << __FUNCTION__; \
msg_ << " - " << msg; \
pEp::Adapter::pEpLog::log(msg_.str()); \
} \
} while (0)
#endif // NDEBUG
// RAW == without prefix of thread, file, function
// pEpLogRaw - logformat "<message>"
#ifdef NDEBUG
#define pEpLogRaw(msg) \
do { \
} while (0)
#else
#define pEpLogRaw(msg) \
do { \
if (pEp::Adapter::pEpLog::get_enabled()) { \
std::stringstream ss_msg{}; \
ss_msg << msg; \
pEp::Adapter::pEpLog::log(ss_msg.str()); \
} \
} while (0)
#endif // NDEBUG
// pEpLogH1 - logformat "<==============================>"
// pEpLogH1 - logformat message"
// pEpLogH1 - logformat "<==============================>"
#ifdef NDEBUG
#define pEpLogH1(msg) \
do { \
} while (0)
#else
#define pEpLogH1(msg) \
do { \
if (pEp::Adapter::pEpLog::get_enabled()) { \
std::stringstream ss_msg{}; \
ss_msg << msg; \
pEp::Adapter::pEpLog::logH1(ss_msg.str()); \
} \
} while (0)
#endif // NDEBUG
// pEpLogH2 - logformat <=============== message ==============>"
#ifdef NDEBUG
#define pEpLogH2(msg) \
do { \
} while (0)
#else
#define pEpLogH2(msg) \
do { \
if (pEp::Adapter::pEpLog::get_enabled()) { \
std::stringstream ss_msg{}; \
ss_msg << msg; \
pEp::Adapter::pEpLog::logH2(ss_msg.str()); \
} \
} while (0)
#endif // NDEBUG
// pEpLogH2 - logformat <---------------- message ----------------"
#ifdef NDEBUG
#define pEpLogH3(msg) \
do { \
} while (0)
#else
#define pEpLogH3(msg) \
do { \
if (pEp::Adapter::pEpLog::get_enabled()) { \
std::stringstream ss_msg{}; \
ss_msg << msg; \
pEp::Adapter::pEpLog::logH3(ss_msg.str()); \
} \
} while (0)
#endif // NDEBUG
namespace pEp {
namespace Adapter {
namespace pEpLog {
// Logging functions to control pEpLog() macro
void set_enabled(const bool& is_enabled);
bool get_enabled();
void log(const std::string& msg, Utils::Color col = Utils::Color::WHITE);
void logH1(const std::string& msg, Utils::Color col = Utils::Color::WHITE);
void logH2(const std::string& msg, Utils::Color col = Utils::Color::WHITE);
void logH3(const std::string& msg, Utils::Color col = Utils::Color::WHITE);
std::string decorate_three_lines(const std::string& msg, char decoration = '-');
std::string decorate_centered(const std::string& msg, char decoration = '-');
} // namespace pEpLog
} // namespace Adapter
} // namespace pEp
// --------------------------------------------------------------------------------------------------
// pEpLogClass is to be used in a class
// pEpLogger can only print the "thread - file::class::function - <message>" format using this macro
// WARNING: Some magic is needed
// Usage:
// create your logger obj in your class as a public member (usually)
// Adapter::pEpLog::pEpLogger logger{"<CLASSNAME>", enabled: true|false};
// then, create an alias for your logger called "m4gic_logger_n4me" as a private member
// Adapter::pEpLog::pEpLogger& m4gic_logger_n4me = logger;
// Thats all.
// Now in your implementation, to log a message you just write:
// pEpLogClass("my great logging message");
#ifdef NDEBUG
#define pEpLogClass(msg) \
do { \
} while (0)
#else
#define pEpLogClass(msg) \
do { \
std::stringstream msg_; \
msg_ << "[" << getpid() << " " << std::this_thread::get_id() << "]"; \
msg_ << " - " << this->m4gic_logger_n4me.get_classname(); \
msg_ << "[" << this->m4gic_logger_n4me.get_instancename() << "]"; \
msg_ << "::" << __FUNCTION__; \
msg_ << " - " << (msg); \
this->m4gic_logger_n4me.logRaw(msg_.str()); \
} while (0)
#endif // NDEBUG
// pEpLogClassRaw is the same as pEpLogClass, but does not print anything except the supplied msg
// This can also be achieved without this macro, just use the log method of pEpLogger
// You also need to set up the logger in your class as for pEpLogClass
// The only advantage of this macro is that is compiled away to nothing with NDEBUG
#ifdef NDEBUG
#define pEpLogClassRaw(msg) \
do { \
} while (0)
#else
#define pEpLogClassRaw(msg) \
do { \
this->m4gic_logger_n4me.logRaw(msg); \
} while (0)
#endif // NDEBUG
namespace pEp {
namespace Adapter {
namespace pEpLog {
class pEpLogger {
public:
pEpLogger() = delete;
pEpLogger(const std::string& classname, const bool& enabled);
// Print a logging message in the format "thread - classname[instancename] - <msg>"
void log(const std::string& msg, Utils::Color col = Utils::Color::WHITE) const;
// Prints just "<msg>"
void logRaw(const std::string& msg, Utils::Color col = Utils::Color::WHITE) const;
void set_enabled(const bool& enabled);
bool get_enabled() const;
std::string get_classname() const;
// If never set, the default instancename is a unique number
void set_instancename(const std::string& name);
std::string get_instancename() const;
private:
static int auto_instance_nr;
bool is_enabled;
std::string classname;
std::string instancename;
};
} // namespace pEpLog
} // namespace Adapter
} // namespace pEp
#endif // LIBPEPADAPTER_PEPLOG_HH
Loading…
Cancel
Save