Files
gsmartcontrol/src/libdebug/dout.cpp
T

160 lines
3.1 KiB
C++

/******************************************************************************
License: Zlib
Copyright:
(C) 2008 - 2021 Alexander Shaduri <ashaduri@gmail.com>
******************************************************************************/
/// \file
/// \author Alexander Shaduri
/// \ingroup libdebug
/// \weakgroup libdebug
/// @{
#include <string>
#include <iosfwd> // std::ostream definition
#include <sstream>
#include <cstdarg> // std::va_start, va_list macro and friends
#include "hz/string_sprintf.h" // string_vsprintf()
#include "dout.h"
#include "dflags.h"
#include "dstate.h"
#include "dexcept.h"
// This may throw for invalid domain or level.
std::ostream& debug_out(debug_level::flag level, const std::string& domain)
{
auto& dm = debug_internal::get_debug_state_ref().get_domain_map_ref();
auto level_map = dm.find(domain);
if (level_map == dm.end()) { // no such domain
// this is an internal error
std::string msg = "debug_out(): Debug state doesn't contain the requested domain: \"" + domain + "\".";
throw debug_internal_error(msg.c_str());
}
auto os = level_map->second.find(level);
if (level_map == dm.end()) {
std::string msg = std::string("debug_out(): Debug state doesn't contain the requested level ") +
debug_level::get_name(level) + " in domain: \"" + domain + "\".";
// this is an internal error
throw debug_internal_error(msg.c_str());
}
return *(os->second);
}
void debug_print(debug_level::flag level, const std::string& domain, const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
std::string s = hz::string_vsprintf(format, ap);
va_end(ap);
debug_out(level, domain) << s;
}
// Start / stop prefix printing. Useful for large dumps
void debug_begin()
{
debug_internal::get_debug_state_ref().push_inside_begin();
}
void debug_end()
{
debug_internal::get_debug_state_ref().pop_inside_begin();
// this is needed because else the contents won't be written until next write.
debug_internal::get_debug_state_ref().force_output();
}
namespace debug_internal {
std::string DebugSourcePos::str() const
{
std::ostringstream os;
os << "(";
if (enabled_types.test(debug_pos::func_name)) {
os << "function: " << func_name;
} else if (enabled_types.test(debug_pos::func)) {
os << "function: " << func << "()";
}
if (enabled_types.test(debug_pos::file)) {
if (os.str() != "(")
os << ", ";
os << "file: " << file;
}
if (enabled_types.test(debug_pos::line)) {
if (os.str() != "(")
os << ", ";
os << "line: " << line;
}
os << ")";
return os.str();
}
}
// ------------------ Indentation and manipulators
// increase indentation level for all debug levels
void debug_indent_inc(int by)
{
int curr = debug_internal::get_debug_state_ref().get_indent_level();
debug_internal::get_debug_state_ref().set_indent_level(curr + by);
}
void debug_indent_dec(int by)
{
int curr = debug_internal::get_debug_state_ref().get_indent_level();
curr -= by;
if (curr < 0)
curr = 0;
debug_internal::get_debug_state_ref().set_indent_level(curr);
}
void debug_indent_reset()
{
debug_internal::get_debug_state_ref().set_indent_level(0);
}
/// @}