mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-27 00:19:25 -05:00
Merge pull request #1547 from G10h4ck/rs_debug
Comfortable and efficient RetroShare logging helpers
This commit is contained in:
commit
c754b32b06
@ -1,9 +1,8 @@
|
||||
/*******************************************************************************
|
||||
* libretroshare/src/util: rsdebug.h *
|
||||
* RetroShare debugging utilities *
|
||||
* *
|
||||
* libretroshare: retroshare core library *
|
||||
* *
|
||||
* Copyright 2004-2008 by Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2004-2008 Robert Fernie <retroshare@lunamutt.com> *
|
||||
* Copyright (C) 2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License as *
|
||||
@ -19,16 +18,211 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
/* Moved from pqi/ to util/ so it can be used more generally.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef RS_LOG_DEBUG_H
|
||||
#define RS_LOG_DEBUG_H
|
||||
#include <ostream>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
# include <android/log.h>
|
||||
# include <sstream>
|
||||
# include <string>
|
||||
|
||||
enum class RsLoggerCategories
|
||||
{
|
||||
DEBUG = ANDROID_LOG_DEBUG,
|
||||
INFO = ANDROID_LOG_INFO,
|
||||
WARNING = ANDROID_LOG_WARN,
|
||||
ERROR = ANDROID_LOG_ERROR,
|
||||
FATAL = ANDROID_LOG_FATAL
|
||||
};
|
||||
|
||||
template <RsLoggerCategories CATEGORY>
|
||||
struct t_RsLogger
|
||||
{
|
||||
inline t_RsLogger() = default;
|
||||
|
||||
template<typename T>
|
||||
inline t_RsLogger& operator<<(const T& val)
|
||||
{ ostr << val; return *this; }
|
||||
|
||||
/// needed for manipulators and things like std::endl
|
||||
t_RsLogger& operator<<(std::ostream& (*pf)(std::ostream&))
|
||||
{
|
||||
if(pf == static_cast<std::ostream& (*)(std::ostream&)>(
|
||||
&std::endl< char, std::char_traits<char> > ))
|
||||
{
|
||||
__android_log_write(
|
||||
static_cast<int>(CATEGORY),
|
||||
"RetroShare", ostr.str().c_str() );
|
||||
ostr.str() = "";
|
||||
}
|
||||
else ostr << pf;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostringstream ostr;
|
||||
};
|
||||
|
||||
#else // def __ANDROID__
|
||||
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
|
||||
enum class RsLoggerCategories
|
||||
{
|
||||
DEBUG = 'D',
|
||||
INFO = 'I',
|
||||
WARNING = 'W',
|
||||
ERROR = 'E',
|
||||
FATAL = 'F'
|
||||
};
|
||||
|
||||
template <RsLoggerCategories CATEGORY>
|
||||
struct t_RsLogger
|
||||
{
|
||||
inline t_RsLogger() = default;
|
||||
|
||||
template<typename T>
|
||||
inline std::ostream& operator<<(const T& val)
|
||||
{
|
||||
return std::cerr << static_cast<char>(CATEGORY) << " " << time(nullptr)
|
||||
<< " " << val;
|
||||
}
|
||||
};
|
||||
#endif // def __ANDROID__
|
||||
|
||||
|
||||
/**
|
||||
* Comfortable debug message loggin, supports chaining like std::cerr but can
|
||||
* be easly and selectively disabled at compile time to reduce generated binary
|
||||
* size and performance impact without too many #ifdef around.
|
||||
*
|
||||
* To selectively debug your context you can just add something like this in
|
||||
* in that context, as an example for a class you can just add a line like this
|
||||
* inside class declaration:
|
||||
@code{.cpp}
|
||||
RS_SET_CONTEXT_DEBUG_LEVEL(2)
|
||||
@endcode
|
||||
* And the you can write debug messages around the code of the class like this:
|
||||
@code{.cpp}
|
||||
Dbg1() << "Level 1 debug message example, this will be compiled and "
|
||||
<< "printed" << std::endl;
|
||||
Dbg2() << "Level 2 debug message example, this will be compiled and "
|
||||
<< "printed" << std::endl;
|
||||
Dbg3() << "Level 3 debug message example, this will not be compiled and "
|
||||
<< "printed, and without #ifdef around!!" << std::endl;
|
||||
Dbg4() << "Level 4 debug message example, this will not be compiled and "
|
||||
<< "printed, and without #ifdef around!!" << std::endl;
|
||||
@endcode
|
||||
* To change the debugging level, for example to completely disable debug
|
||||
* messages you can change it to 0
|
||||
@code{.cpp}
|
||||
RS_SET_CONTEXT_DEBUG_LEVEL(0)
|
||||
@endcode
|
||||
* While to set it to maximim level you have to pass 4.
|
||||
*/
|
||||
using RsDbg = t_RsLogger<RsLoggerCategories::DEBUG>;
|
||||
|
||||
|
||||
/**
|
||||
* Comfortable log information reporting helper, supports chaining like
|
||||
* std::cerr.
|
||||
* To report an information message you can just write:
|
||||
@code{.cpp}
|
||||
RsInfo() << __PRETTY_FUNCTION__ << "My information message" << std::cerr;
|
||||
@endcode
|
||||
*/
|
||||
using RsInfo = t_RsLogger<RsLoggerCategories::INFO>;
|
||||
|
||||
/// Similar to @see RsInfo but for warning messages
|
||||
using RsWarn = t_RsLogger<RsLoggerCategories::WARNING>;
|
||||
|
||||
/// Similar to @see RsInfo but for error messages
|
||||
using RsErr = t_RsLogger<RsLoggerCategories::ERROR>;
|
||||
|
||||
/** Similar to @see RsInfo but for fatal errors (the ones which cause RetroShare
|
||||
* to terminate) messages */
|
||||
using RsFatal = t_RsLogger<RsLoggerCategories::FATAL>;
|
||||
|
||||
/**
|
||||
* Keeps compatible syntax with RsDbg but explicitely do nothing in a way that
|
||||
* any modern compiler should be smart enough to optimize out all the function
|
||||
* calls.
|
||||
*/
|
||||
struct RsNoDbg
|
||||
{
|
||||
inline RsNoDbg() = default;
|
||||
|
||||
/**
|
||||
* This match most of the types, but might be not enough for templated
|
||||
* types
|
||||
*/
|
||||
template<typename T>
|
||||
inline RsNoDbg& operator<<(const T&) { return *this; }
|
||||
|
||||
/// needed for manipulators and things like std::endl
|
||||
inline RsNoDbg& operator<<(std::ostream& (*/*pf*/)(std::ostream&))
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Concatenate preprocessor tokens A and B without expanding macro definitions
|
||||
* (however, if invoked from a macro, macro arguments are expanded).
|
||||
*/
|
||||
#define RS_CONCAT_MACRO_NX(A, B) A ## B
|
||||
|
||||
/// Concatenate preprocessor tokens A and B after macro-expanding them.
|
||||
#define RS_CONCAT_MACRO(A, B) RS_CONCAT_MACRO_NX(A, B)
|
||||
|
||||
/**
|
||||
* Set local context debug level.
|
||||
* Avoid copy pasting boilerplate code around @see RsDbg for usage details
|
||||
*/
|
||||
#define RS_SET_CONTEXT_DEBUG_LEVEL(level) \
|
||||
RS_CONCAT_MACRO(RS_SET_CONTEXT_DEBUG_LEVEL, level)
|
||||
|
||||
// A bunch of boilerplate, but just in one place
|
||||
#define RS_SET_CONTEXT_DEBUG_LEVEL0 \
|
||||
using Dbg1 = RsNoDbg; \
|
||||
using Dbg2 = RsNoDbg; \
|
||||
using Dbg3 = RsNoDbg; \
|
||||
using Dbg4 = RsNoDbg;
|
||||
#define RS_SET_CONTEXT_DEBUG_LEVEL1 \
|
||||
using Dbg1 = RsDbg; \
|
||||
using Dbg2 = RsNoDbg; \
|
||||
using Dbg3 = RsNoDbg; \
|
||||
using Dbg4 = RsNoDbg;
|
||||
#define RS_SET_CONTEXT_DEBUG_LEVEL2 \
|
||||
using Dbg1 = RsDbg; \
|
||||
using Dbg2 = RsDbg; \
|
||||
using Dbg3 = RsNoDbg; \
|
||||
using Dbg4 = RsNoDbg;
|
||||
#define RS_SET_CONTEXT_DEBUG_LEVEL3 \
|
||||
using Dbg1 = RsDbg; \
|
||||
using Dbg2 = RsDbg; \
|
||||
using Dbg3 = RsDbg; \
|
||||
using Dbg4 = RsNoDbg;
|
||||
#define RS_SET_CONTEXT_DEBUG_LEVEL4 \
|
||||
using Dbg1 = RsDbg; \
|
||||
using Dbg2 = RsDbg; \
|
||||
using Dbg3 = RsDbg; \
|
||||
using Dbg4 = RsDbg;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// All the following lines are DEPRECATED!!
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "util/rsdeprecate.h"
|
||||
|
||||
namespace RsLog {
|
||||
enum logLvl {
|
||||
enum RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg") logLvl {
|
||||
None = -1,
|
||||
Default = 0,
|
||||
Alert = 1,
|
||||
@ -40,7 +234,7 @@ namespace RsLog {
|
||||
};
|
||||
|
||||
// this struct must be provided by the caller (to rslog())
|
||||
struct logInfo {
|
||||
struct RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg") logInfo {
|
||||
// module specific log lvl
|
||||
logLvl lvl;
|
||||
// module name (displayed in log)
|
||||
@ -48,9 +242,16 @@ namespace RsLog {
|
||||
};
|
||||
}
|
||||
|
||||
RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg")
|
||||
int setDebugCrashMode(const char *cfile);
|
||||
|
||||
RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg")
|
||||
int setDebugFile(const char *fname);
|
||||
|
||||
RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg")
|
||||
int setOutputLevel(RsLog::logLvl lvl);
|
||||
|
||||
RS_DEPRECATED_FOR("RsErr, RsDbg, RsNoDbg")
|
||||
void rslog(const RsLog::logLvl lvl, RsLog::logInfo *info, const std::string &msg);
|
||||
|
||||
|
||||
@ -76,7 +277,3 @@ void rslog(const RsLog::logLvl lvl, RsLog::logInfo *info, const std::string &msg
|
||||
#define PQL_DEBUG_ALERT RSL_DEBUG_ALERT
|
||||
#define PQL_DEBUG_BASIC RSL_DEBUG_BASIC
|
||||
#define PQL_DEBUG_ALL RSL_DEBUG_ALL
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -162,6 +162,9 @@ std::ostream &operator<<(std::ostream &out, const struct sockaddr_in &addr)
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const sockaddr_storage& addr)
|
||||
{ return o << sockaddr_storage_tostring(addr); }
|
||||
|
||||
/* thread-safe version of inet_ntoa */
|
||||
|
||||
std::string rs_inet_ntoa(struct in_addr in)
|
||||
|
@ -84,7 +84,8 @@ bool isExternalNet(const struct in_addr *addr);
|
||||
// uses a re-entrant version of gethostbyname
|
||||
bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) ;
|
||||
|
||||
std::ostream& operator<<(std::ostream& o,const struct sockaddr_in&) ;
|
||||
std::ostream& operator<<(std::ostream& o, const sockaddr_in&);
|
||||
std::ostream& operator<<(std::ostream& o, const sockaddr_storage&);
|
||||
|
||||
/* thread-safe version of inet_ntoa */
|
||||
std::string rs_inet_ntoa(struct in_addr in);
|
||||
@ -144,10 +145,6 @@ std::string sockaddr_storage_iptostring(const struct sockaddr_storage &addr);
|
||||
std::string sockaddr_storage_porttostring(const struct sockaddr_storage &addr);
|
||||
void sockaddr_storage_dump(const sockaddr_storage & addr, std::string * outputString = NULL);
|
||||
|
||||
// output
|
||||
//void sockaddr_storage_output(const struct sockaddr_storage &addr, std::ostream &out);
|
||||
//void sockaddr_storage_ipoutput(const struct sockaddr_storage &addr, std::ostream &out);
|
||||
|
||||
// net checks.
|
||||
bool sockaddr_storage_isnull(const struct sockaddr_storage &addr);
|
||||
bool sockaddr_storage_isValidNet(const struct sockaddr_storage &addr);
|
||||
|
@ -201,6 +201,13 @@ RsUrl& RsUrl::delQueryK(const std::string& key)
|
||||
mQuery.erase(key);
|
||||
return *this;
|
||||
}
|
||||
bool RsUrl::hasQueryK(const std::string& key)
|
||||
{ return (mQuery.find(key) != mQuery.end()); }
|
||||
const std::string* RsUrl::getQueryV(const std::string& key)
|
||||
{
|
||||
if(hasQueryK(key)) return &(mQuery.find(key)->second);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::string& RsUrl::fragment() const { return mFragment; }
|
||||
RsUrl& RsUrl::setFragment(const std::string& fragment)
|
||||
|
@ -59,6 +59,8 @@ struct RsUrl : RsSerializable
|
||||
RsUrl& setQuery(const std::map<std::string, std::string>& query);
|
||||
RsUrl& setQueryKV(const std::string& key, const std::string& value);
|
||||
RsUrl& delQueryK(const std::string& key);
|
||||
bool hasQueryK(const std::string& key);
|
||||
const std::string* getQueryV(const std::string& key);
|
||||
|
||||
const std::string& fragment() const;
|
||||
RsUrl& setFragment(const std::string& fragment);
|
||||
|
Loading…
Reference in New Issue
Block a user