151 lines
3.8 KiB
C++
151 lines
3.8 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* Copyright 2012-2016 Danny Robson <danny@nerdcruft.net>
|
|
*/
|
|
|
|
#include "level.hpp"
|
|
|
|
#include "../parse/enum.hpp"
|
|
|
|
#include <iostream>
|
|
|
|
#include <cstring>
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/// convert a string representation of a log-level into an enumeration value.
|
|
///
|
|
/// conversion is case insensitive
|
|
/// throws std::range_error if unable to convert
|
|
cruft::log::level_t
|
|
cruft::log::to_level (std::string_view name)
|
|
{
|
|
if (std::empty (name))
|
|
return cruft::log::EMERGENCY;
|
|
|
|
std::string upper (name.size (), char{});
|
|
std::transform (
|
|
name.cbegin (),
|
|
name.cend (),
|
|
upper.begin (),
|
|
::toupper
|
|
);
|
|
|
|
#define ITEM(NAME) \
|
|
if (!strcmp (#NAME, upper.data ())) \
|
|
return NAME;
|
|
MAP_LEVEL_T(ITEM)
|
|
#undef ITEM
|
|
|
|
throw std::invalid_argument (std::string (name));
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
const std::string&
|
|
cruft::log::to_string (level_t l)
|
|
{
|
|
switch (l) {
|
|
#define CASE(L) \
|
|
case cruft::log::L: { \
|
|
static const std::string STR = #L; \
|
|
return STR; \
|
|
}
|
|
MAP_LEVEL_T(CASE)
|
|
#undef CASE
|
|
}
|
|
|
|
unreachable ();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
std::ostream&
|
|
cruft::log::operator<< (std::ostream& os, level_t l)
|
|
{
|
|
return os << to_string (l);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Determine what the value for LOG_LEVEL should be at the beginning of
|
|
// execution given the system environment.
|
|
//
|
|
// Note that the LOG macros _cannot_ be used from within this function as it
|
|
// will likely result in infinite recursion.
|
|
static cruft::log::level_t
|
|
initial_log_level (void)
|
|
{
|
|
const char *env = getenv ("LOG_LEVEL");
|
|
if (!env)
|
|
return cruft::log::DEFAULT_LOG_LEVEL;
|
|
|
|
try {
|
|
return cruft::log::to_level (env);
|
|
} catch (...) {
|
|
std::clog << "Invalid environment LOG_LEVEL: '" << env << "'\n";
|
|
return cruft::log::DEFAULT_LOG_LEVEL;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// We shouldn't ever actually get to use the default value, but we set it to
|
|
// the most verbose option just in case we've made a mistake elsewhere.
|
|
|
|
static bool s_log_level_done;
|
|
static cruft::log::level_t s_log_level_value;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
cruft::log::level_t
|
|
cruft::log::log_level (level_t _level)
|
|
{
|
|
s_log_level_value = _level;
|
|
s_log_level_done = true;
|
|
return s_log_level_value;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
cruft::log::level_t
|
|
cruft::log::log_level (void)
|
|
{
|
|
if (!s_log_level_done) {
|
|
s_log_level_value = initial_log_level ();
|
|
s_log_level_done = true;
|
|
}
|
|
|
|
return s_log_level_value;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
std::size_t
|
|
cruft::log::level_width (void)
|
|
{
|
|
return cruft::max (
|
|
#define ITEM(NAME) strlen(#NAME),
|
|
MAP_LEVEL_T(ITEM)
|
|
#undef ITEM
|
|
|
|
0u
|
|
);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
cruft::parse::enumeration::cookie
|
|
cruft::log::setup_level_reflection (void)
|
|
{
|
|
#define ITEM(NAME) { #NAME, NAME },
|
|
return parse::enumeration::setup (
|
|
std::map<std::string_view, level_t> {
|
|
MAP_LEVEL_T(ITEM)
|
|
}
|
|
);
|
|
#undef ITEM
|
|
}
|