eina-cxx: Added eina_log support for C++, using IOStreams syntax

Summary:
Added eina_log support for C++ using the following macros:

For logging into a domain:

EINA_CXX_DOM_LOG
EINA_CXX_DOM_LOG_CRIT
EINA_CXX_DOM_LOG_ERR
EINA_CXX_DOM_LOG_INFO
EINA_CXX_DOM_LOG_DBG
EINA_CXX_DOM_LOG_WARN

And for logging into the default domain:

EINA_CXX_LOG
EINA_CXX_LOG_CRIT
EINA_CXX_LOG_ERR
EINA_CXX_LOG_INFO
EINA_CXX_LOG_DBG
EINA_CXX_LOG_WARN

The usage is simple as can be seen in the tests:

  efl::eina::log_domain domain("error_domain_name");
  domain.set_level(efl::eina::log_level::critical);
  EINA_CXX_DOM_LOG_CRIT(domain, "something went wrong with the following error: " << error);

@feature

Reviewers: cedric

CC: raster, savio, cedric, sanjeev

Differential Revision: https://phab.enlightenment.org/D605
This commit is contained in:
Felipe Magno de Almeida 2014-03-10 12:25:20 +09:00 committed by Cedric BAIL
parent 5942207b25
commit 416376e03c
7 changed files with 254 additions and 0 deletions

View File

@ -33,6 +33,7 @@ TESTS += tests/eina_cxx/eina_cxx_suite
tests_eina_cxx_eina_cxx_suite_SOURCES = \ tests_eina_cxx_eina_cxx_suite_SOURCES = \
tests/eina_cxx/eina_cxx_suite.cc \ tests/eina_cxx/eina_cxx_suite.cc \
tests/eina_cxx/eina_cxx_test_inlist.cc \ tests/eina_cxx/eina_cxx_test_inlist.cc \
tests/eina_cxx/eina_cxx_test_log.cc \
tests/eina_cxx/eina_cxx_test_inarray.cc \ tests/eina_cxx/eina_cxx_test_inarray.cc \
tests/eina_cxx/eina_cxx_test_iterator.cc \ tests/eina_cxx/eina_cxx_test_iterator.cc \
tests/eina_cxx/eina_cxx_test_ptrarray.cc \ tests/eina_cxx/eina_cxx_test_ptrarray.cc \

View File

@ -12,6 +12,7 @@
#include <eina_thread.hh> #include <eina_thread.hh>
#include <eina_value.hh> #include <eina_value.hh>
#include <eina_ref.hh> #include <eina_ref.hh>
#include <eina_log.hh>
namespace efl { namespace eina { namespace efl { namespace eina {

View File

@ -0,0 +1,122 @@
#ifndef EFL_EINA_LOG_HH
#define EFL_EINA_LOG_HH
#include <sstream>
namespace efl { namespace eina {
namespace log_level {
struct critical_t { static constexpr ::Eina_Log_Level value = ::EINA_LOG_LEVEL_CRITICAL; };
critical_t const critical = {};
struct error_t { static constexpr ::Eina_Log_Level value = ::EINA_LOG_LEVEL_ERR; };
error_t const error = {};
struct info_t { static constexpr ::Eina_Log_Level value = ::EINA_LOG_LEVEL_INFO; };
info_t const info = {};
struct debug_t { static constexpr ::Eina_Log_Level value = ::EINA_LOG_LEVEL_DBG; };
debug_t const debug = {};
struct warn_t { static constexpr ::Eina_Log_Level value = ::EINA_LOG_LEVEL_WARN; };
warn_t const warning = {};
}
template <typename D>
struct _domain_base
{
void set_level(log_level::critical_t l) { set_level(l.value); }
void set_level(log_level::error_t l) { set_level(l.value); }
void set_level(log_level::info_t l) { set_level(l.value); }
void set_level(log_level::debug_t l) { set_level(l.value); }
void set_level(log_level::warn_t l) { set_level(l.value); }
void set_level( ::Eina_Log_Level l)
{
::eina_log_domain_registered_level_set(static_cast<D&>(*this).domain_raw(), l);
}
::Eina_Log_Level get_level() const
{
return static_cast< ::Eina_Log_Level>
(::eina_log_domain_registered_level_get(static_cast<D const&>(*this).domain_raw()));
}
};
const struct global_domain : _domain_base<global_domain>
{
int domain_raw() const { return EINA_LOG_DOMAIN_GLOBAL; }
} global_domain;
const struct default_domain : _domain_base<default_domain>
{
int domain_raw() const { return EINA_LOG_DOMAIN_DEFAULT; }
} default_domain;
struct log_domain : _domain_base<log_domain>
{
log_domain(char const* name, char const* color = "black")
: _domain( ::eina_log_domain_register(name, color))
{
}
~log_domain()
{
::eina_log_domain_unregister(_domain);
}
int domain_raw() const { return _domain; }
private:
int _domain;
};
inline void _log(std::stringstream const& stream, int domain, ::Eina_Log_Level level
, const char* file, const char* function, int line)
{
::eina_log_print(domain, level, file, function, line
, "%s", stream.str().c_str());
}
#define EINA_CXX_DOM_LOG(DOMAIN, LEVEL, EXPR) \
if( ::eina_log_domain_level_check((DOMAIN), LEVEL)) \
{ \
std::stringstream stream; \
stream << EXPR; \
::efl::eina::_log(std::move(stream), (DOMAIN), LEVEL \
, __FILE__, __FUNCTION__, __LINE__); \
}
#define EINA_CXX_DOM_LOG_CRIT(DOMAIN, EXPR) \
EINA_CXX_DOM_LOG(DOMAIN.domain_raw(), ::EINA_LOG_LEVEL_CRITICAL, EXPR)
#define EINA_CXX_DOM_LOG_ERR(DOMAIN, EXPR) \
EINA_CXX_DOM_LOG(DOMAIN.domain_raw(), ::EINA_LOG_LEVEL_ERR, EXPR)
#define EINA_CXX_DOM_LOG_INFO(DOMAIN, EXPR) \
EINA_CXX_DOM_LOG(DOMAIN.domain_raw(), ::EINA_LOG_LEVEL_INFO, EXPR)
#define EINA_CXX_DOM_LOG_DBG(DOMAIN, EXPR) \
EINA_CXX_DOM_LOG(DOMAIN.domain_raw(), ::EINA_LOG_LEVEL_DBG, EXPR)
#define EINA_CXX_DOM_LOG_WARN(DOMAIN, EXPR) \
EINA_CXX_DOM_LOG(DOMAIN.domain_raw(), ::EINA_LOG_LEVEL_WARN, EXPR)
#define EINA_CXX_LOG(LEVEL, EXPR) \
EINA_CXX_DOM_LOG(EINA_LOG_DOMAIN_DEFAULT, LEVEL, EXPR)
#define EINA_CXX_LOG_CRIT(EXPR) \
EINA_CXX_LOG(EINA_LOG_LEVEL_CRITICAL, EXPR)
#define EINA_CXX_LOG_ERR(EXPR) \
EINA_CXX_LOG(EINA_LOG_LEVEL_ERR, EXPR)
#define EINA_CXX_LOG_INFO(EXPR) \
EINA_CXX_LOG(EINA_LOG_LEVEL_INFO, EXPR)
#define EINA_CXX_LOG_DBG(EXPR) \
EINA_CXX_LOG(EINA_LOG_LEVEL_DBG, EXPR)
#define EINA_CXX_LOG_WARN(EXPR) \
EINA_CXX_LOG(EINA_LOG_LEVEL_WARN, EXPR)
} }
#endif

View File

@ -1837,6 +1837,20 @@ eina_log_domain_registered_level_get(int domain)
#endif #endif
} }
EAPI void
eina_log_domain_registered_level_set(int domain, int level)
{
#ifdef EINA_ENABLE_LOG
EINA_SAFETY_ON_FALSE_RETURN(domain >= 0);
EINA_SAFETY_ON_FALSE_RETURN((unsigned int)domain < _log_domains_count);
EINA_SAFETY_ON_TRUE_RETURN(_log_domains[domain].deleted);
_log_domains[domain].level = level;
#else
(void) domain;
(void) level;
#endif
}
#ifdef EINA_LOG_BACKTRACE #ifdef EINA_LOG_BACKTRACE
# define DISPLAY_BACKTRACE(File, Level) \ # define DISPLAY_BACKTRACE(File, Level) \
if (EINA_UNLIKELY(Level < _backtrace_level)) \ if (EINA_UNLIKELY(Level < _backtrace_level)) \

View File

@ -695,6 +695,18 @@ EAPI int eina_log_domain_level_get(const char *domain_name) EINA_
*/ */
EAPI int eina_log_domain_registered_level_get(int domain) EINA_WARN_UNUSED_RESULT; EAPI int eina_log_domain_registered_level_get(int domain) EINA_WARN_UNUSED_RESULT;
/**
* Set the domain level given its identifier.
*
* @param domain identifier, so it must be previously registered with
* eina_log_domain_register(). It's a much faster version of
* eina_log_domain_level_get(), but relies on domain being
* present.
* @param level level to use to limit eina_log_print() for given domain.
* @since 1.10
*/
EAPI void eina_log_domain_registered_level_set(int domain, int level);
static inline Eina_Bool eina_log_domain_level_check(int domain, int level); static inline Eina_Bool eina_log_domain_level_check(int domain, int level);
/* /*

View File

@ -16,6 +16,7 @@ void eina_test_error(TCase* tc);
void eina_test_accessor(TCase* tc); void eina_test_accessor(TCase* tc);
void eina_test_thread(TCase* tc); void eina_test_thread(TCase* tc);
void eina_test_value(TCase* tc); void eina_test_value(TCase* tc);
void eina_test_log(TCase* tc);
typedef struct _Eina_Test_Case Eina_Test_Case; typedef struct _Eina_Test_Case Eina_Test_Case;
struct _Eina_Test_Case struct _Eina_Test_Case
@ -35,6 +36,7 @@ static const Eina_Test_Case etc[] = {
{ "Accessor", eina_test_accessor }, { "Accessor", eina_test_accessor },
{ "Thread", eina_test_thread }, { "Thread", eina_test_thread },
{ "Value", eina_test_value }, { "Value", eina_test_value },
{ "Log", eina_test_log },
{ NULL, NULL } { NULL, NULL }
}; };

View File

@ -0,0 +1,102 @@
#include "Eina.hh"
#include <algorithm>
#include <check.h>
bool expensive_called = false;
int expensive_call()
{
expensive_called = true;
return 11;
}
START_TEST(eina_cxx_level_log)
{
efl::eina::eina_init init;
efl::eina::log_domain domain("level_error_domain");
domain.set_level(efl::eina::log_level::critical);
ck_assert(domain.get_level() == ::EINA_LOG_LEVEL_CRITICAL);
domain.set_level(efl::eina::log_level::warning);
ck_assert(domain.get_level() == ::EINA_LOG_LEVEL_WARN);
domain.set_level(efl::eina::log_level::debug);
ck_assert(domain.get_level() == ::EINA_LOG_LEVEL_DBG);
domain.set_level(efl::eina::log_level::info);
ck_assert(domain.get_level() == ::EINA_LOG_LEVEL_INFO);
domain.set_level(efl::eina::log_level::error);
ck_assert(domain.get_level() == ::EINA_LOG_LEVEL_ERR);
}
END_TEST
START_TEST(eina_cxx_expensive_log)
{
efl::eina::eina_init init;
efl::eina::log_domain domain("expensive_call_error_domain");
domain.set_level(EINA_LOG_LEVEL_CRITICAL);
EINA_CXX_DOM_LOG_ERR(domain, "foo " << ::expensive_call());
ck_assert(!expensive_called);
}
END_TEST
START_TEST(eina_cxx_domain_log)
{
efl::eina::eina_init init;
efl::eina::log_domain domain("error_domain");
EINA_CXX_DOM_LOG_CRIT(domain, "foo 0x" << std::hex << 10);
EINA_CXX_DOM_LOG_ERR(domain, "foo " << 5);
EINA_CXX_DOM_LOG_INFO(domain, "foo " << 5);
EINA_CXX_DOM_LOG_DBG(domain, "foo " << 5);
EINA_CXX_DOM_LOG_WARN(domain, "foo " << 5);
EINA_CXX_LOG_CRIT("foo " << 5);
EINA_CXX_LOG_ERR("foo " << 5);
EINA_CXX_LOG_INFO("foo " << 5);
EINA_CXX_LOG_DBG("foo " << 5);
EINA_CXX_LOG_WARN("foo " << 5);
}
END_TEST
START_TEST(eina_cxx_default_domain_log)
{
efl::eina::eina_init init;
EINA_CXX_DOM_LOG_CRIT(efl::eina::default_domain, "foo " << 5);
EINA_CXX_DOM_LOG_ERR(efl::eina::default_domain, "foo " << 5);
EINA_CXX_DOM_LOG_INFO(efl::eina::default_domain, "foo " << 5);
EINA_CXX_DOM_LOG_DBG(efl::eina::default_domain, "foo " << 5);
EINA_CXX_DOM_LOG_WARN(efl::eina::default_domain, "foo " << 5);
}
END_TEST
START_TEST(eina_cxx_global_domain_log)
{
efl::eina::eina_init init;
efl::eina::log_domain domain("domain");
EINA_CXX_DOM_LOG_CRIT(efl::eina::global_domain, "foo " << 5);
EINA_CXX_DOM_LOG_ERR(efl::eina::global_domain, "foo " << 5);
EINA_CXX_DOM_LOG_INFO(efl::eina::global_domain, "foo " << 5);
EINA_CXX_DOM_LOG_DBG(efl::eina::global_domain, "foo " << 5);
EINA_CXX_DOM_LOG_WARN(efl::eina::global_domain, "foo " << 5);
}
END_TEST
void
eina_test_log(TCase* tc)
{
tcase_add_test(tc, eina_cxx_domain_log);
tcase_add_test(tc, eina_cxx_default_domain_log);
tcase_add_test(tc, eina_cxx_global_domain_log);
tcase_add_test(tc, eina_cxx_expensive_log);
tcase_add_test(tc, eina_cxx_level_log);
}