poet/include/highfive/H5Utility.hpp

219 lines
6.1 KiB
C++

/*
* Copyright (c), 2017, Blue Brain Project - EPFL (CH)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
*/
#pragma once
#include <functional>
#include <string>
#include <iostream>
#include "bits/h5e_wrapper.hpp"
#include "bits/H5Friends.hpp"
namespace HighFive {
///
/// \brief Utility class to disable HDF5 stack printing inside a scope.
///
class SilenceHDF5 {
public:
inline explicit SilenceHDF5(bool enable = true)
: _client_data(nullptr) {
detail::nothrow::h5e_get_auto2(H5E_DEFAULT, &_func, &_client_data);
if (enable) {
detail::nothrow::h5e_set_auto2(H5E_DEFAULT, nullptr, nullptr);
}
}
inline ~SilenceHDF5() {
detail::nothrow::h5e_set_auto2(H5E_DEFAULT, _func, _client_data);
}
private:
H5E_auto2_t _func;
void* _client_data;
};
#define HIGHFIVE_LOG_LEVEL_DEBUG 10
#define HIGHFIVE_LOG_LEVEL_INFO 20
#define HIGHFIVE_LOG_LEVEL_WARN 30
#define HIGHFIVE_LOG_LEVEL_ERROR 40
#ifndef HIGHFIVE_LOG_LEVEL
#define HIGHFIVE_LOG_LEVEL HIGHFIVE_LOG_LEVEL_WARN
#endif
enum class LogSeverity {
Debug = HIGHFIVE_LOG_LEVEL_DEBUG,
Info = HIGHFIVE_LOG_LEVEL_INFO,
Warn = HIGHFIVE_LOG_LEVEL_WARN,
Error = HIGHFIVE_LOG_LEVEL_ERROR
};
inline std::string to_string(LogSeverity severity) {
switch (severity) {
case LogSeverity::Debug:
return "DEBUG";
case LogSeverity::Info:
return "INFO";
case LogSeverity::Warn:
return "WARN";
case LogSeverity::Error:
return "ERROR";
default:
return "??";
}
}
/** \brief A logger with supporting basic functionality.
*
* This logger delegates the logging task to a callback. This level of
* indirection enables using the default Python logger from C++; or
* integrating HighFive into some custom logging solution.
*
* Using this class directly to log is not intended. Rather you should use
* - `HIGHFIVE_LOG_DEBUG{,_IF}`
* - `HIGHFIVE_LOG_INFO{,_IF}`
* - `HIGHFIVE_LOG_WARNING{,_IF}`
* - `HIGHFIVE_LOG_ERROR{,_IF}`
*
* This is intended to used as a singleton, via `get_global_logger()`.
*/
class Logger {
public:
using callback_type =
std::function<void(LogSeverity, const std::string&, const std::string&, int)>;
public:
Logger() = delete;
Logger(const Logger&) = delete;
Logger(Logger&&) = delete;
explicit Logger(callback_type cb)
: _cb(std::move(cb)) {}
Logger& operator=(const Logger&) = delete;
Logger& operator=(Logger&&) = delete;
inline void log(LogSeverity severity,
const std::string& message,
const std::string& file,
int line) {
_cb(severity, message, file, line);
}
inline void set_logging_callback(callback_type cb) {
_cb = std::move(cb);
}
private:
callback_type _cb;
};
inline void default_logging_callback(LogSeverity severity,
const std::string& message,
const std::string& file,
int line) {
std::clog << file << ": " << line << " [" << to_string(severity) << "] " << message
<< std::endl;
}
/// \brief Obtain a reference to the logger used by HighFive.
///
/// This uses a Meyers singleton, to ensure that the global logger is
/// initialized with a safe default logger, before it is used.
///
/// Note: You probably don't need to call this function explicitly.
///
inline Logger& get_global_logger() {
static Logger logger(&default_logging_callback);
return logger;
}
/// \brief Sets the callback that's used by the logger.
inline void register_logging_callback(Logger::callback_type cb) {
auto& logger = get_global_logger();
logger.set_logging_callback(std::move(cb));
}
namespace detail {
/// \brief Log a `message` with severity `severity`.
inline void log(LogSeverity severity,
const std::string& message,
const std::string& file,
int line) {
auto& logger = get_global_logger();
logger.log(severity, message, file, line);
}
} // namespace detail
#if HIGHFIVE_LOG_LEVEL <= HIGHFIVE_LOG_LEVEL_DEBUG
#define HIGHFIVE_LOG_DEBUG(message) \
::HighFive::detail::log(::HighFive::LogSeverity::Debug, (message), __FILE__, __LINE__);
// Useful, for the common pattern: if ...; then log something.
#define HIGHFIVE_LOG_DEBUG_IF(cond, message) \
if ((cond)) { \
HIGHFIVE_LOG_DEBUG((message)); \
}
#else
#define HIGHFIVE_LOG_DEBUG(message) ;
#define HIGHFIVE_LOG_DEBUG_IF(cond, message) ;
#endif
#if HIGHFIVE_LOG_LEVEL <= HIGHFIVE_LOG_LEVEL_INFO
#define HIGHFIVE_LOG_INFO(message) \
::HighFive::detail::log(::HighFive::LogSeverity::Info, (message), __FILE__, __LINE__);
// Useful, for the common pattern: if ...; then log something.
#define HIGHFIVE_LOG_INFO_IF(cond, message) \
if ((cond)) { \
HIGHFIVE_LOG_INFO((message)); \
}
#else
#define HIGHFIVE_LOG_INFO(message) ;
#define HIGHFIVE_LOG_INFO_IF(cond, message) ;
#endif
#if HIGHFIVE_LOG_LEVEL <= HIGHFIVE_LOG_LEVEL_WARN
#define HIGHFIVE_LOG_WARN(message) \
::HighFive::detail::log(::HighFive::LogSeverity::Warn, (message), __FILE__, __LINE__);
// Useful, for the common pattern: if ...; then log something.
#define HIGHFIVE_LOG_WARN_IF(cond, message) \
if ((cond)) { \
HIGHFIVE_LOG_WARN((message)); \
}
#else
#define HIGHFIVE_LOG_WARN(message) ;
#define HIGHFIVE_LOG_WARN_IF(cond, message) ;
#endif
#if HIGHFIVE_LOG_LEVEL <= HIGHFIVE_LOG_LEVEL_ERROR
#define HIGHFIVE_LOG_ERROR(message) \
::HighFive::detail::log(::HighFive::LogSeverity::Error, (message), __FILE__, __LINE__);
// Useful, for the common pattern: if ...; then log something.
#define HIGHFIVE_LOG_ERROR_IF(cond, message) \
if ((cond)) { \
HIGHFIVE_LOG_ERROR((message)); \
}
#else
#define HIGHFIVE_LOG_ERROR(message) ;
#define HIGHFIVE_LOG_ERROR_IF(cond, message) ;
#endif
} // namespace HighFive