pull/363/merge
Benichou 9 years ago committed by GitHub
commit 97af76cf0f

@ -23,6 +23,7 @@ Very fast, header only, C++ logging library. [![Build Status](https://travis-ci.
* Windows (vc 2013+, cygwin/mingw)
* Mac OSX (clang 3.5+)
* Android
* VxWorks 7
##Features
* Very fast - performance is the primary goal (see [benchmarks](#benchmarks) below).
@ -37,6 +38,7 @@ Very fast, header only, C++ logging library. [![Build Status](https://travis-ci.
* Console logging (colors supported).
* syslog.
* Windows debugger (```OutputDebugString(..)```)
* Android output (```__android_log_write(..)```)
* Easily extendable with custom log targets (just implement a single function in the [sink](include/spdlog/sinks/sink.h) interface).
* Severity based filtering - threshold levels can be modified in runtime as well as in compile time.

@ -197,8 +197,43 @@ inline void spdlog::logger::critical(const T& msg)
log(level::critical, msg);
}
inline spdlog::ostream spdlog::logger::log(level::level_enum lvl)
{
if (!should_log(lvl))
return ostream();
return ostream(this, lvl);
}
inline spdlog::ostream spdlog::logger::trace()
{
return log(level::trace);
}
inline spdlog::ostream spdlog::logger::debug()
{
return log(level::debug);
}
inline spdlog::ostream spdlog::logger::info()
{
return log(level::info);
}
inline spdlog::ostream spdlog::logger::warn()
{
return log(level::warn);
}
inline spdlog::ostream spdlog::logger::error()
{
return log(level::err);
}
inline spdlog::ostream spdlog::logger::critical()
{
return log(level::critical);
}
//
// name and level
@ -215,7 +250,15 @@ inline void spdlog::logger::set_level(spdlog::level::level_enum log_level)
inline void spdlog::logger::set_error_handler(spdlog::log_err_handler err_handler)
{
_err_handler = err_handler;
if (!err_handler)
{
_err_handler = [this](const std::string &msg)
{
this->_default_err_handler(msg);
};
}
else
_err_handler = err_handler;
}
inline spdlog::log_err_handler spdlog::logger::error_handler()

@ -306,8 +306,12 @@ inline int utc_minutes_offset(const std::tm& tm = details::os::localtime())
};
long int offset_seconds = helper::calculate_gmt_offset(tm);
#else
#ifdef __VXWORKS__
long int offset_seconds = 0;
#else
long int offset_seconds = tm.tm_gmtoff;
#endif
#endif
return static_cast<int>(offset_seconds / 60);
@ -377,7 +381,7 @@ inline std::string errno_str(int err_num)
else
return "Unkown error";
#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || defined(__SUNPRO_CC) || \
#elif defined(__FreeBSD__) || defined(__APPLE__) || defined(ANDROID) || defined(__SUNPRO_CC) || defined(__VXWORKS__) || \
((_POSIX_C_SOURCE >= 200112L) && ! defined(_GNU_SOURCE)) // posix version
if (strerror_r(err_num, buf, buf_size) == 0)

@ -0,0 +1,76 @@
//
// Copyright(c) 2017 Benoit Leforestier.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#pragma once
template <class CharT, class Traits>
spdlog::basic_streambuf<CharT, Traits>::basic_streambuf(spdlog::logger* plogger, spdlog::level::level_enum lvl) :
m_plogger(plogger),
m_log_msg(nullptr, lvl)
{
if (m_plogger)
{
const std::string& name = m_plogger->name();
m_log_msg.logger_name = &name;
}
}
template <class CharT, class Traits>
spdlog::basic_streambuf<CharT, Traits>::basic_streambuf(basic_streambuf&& rhs) :
m_plogger(std::move(rhs.m_plogger)),
m_log_msg(nullptr, rhs.m_log_msg.level)
{
rhs.m_plogger = nullptr;
if (m_plogger)
{
m_log_msg.logger_name = std::move(rhs.m_log_msg.logger_name);
m_log_msg.time = std::move(rhs.m_log_msg.time);
m_log_msg.thread_id = std::move(rhs.m_log_msg.thread_id);
m_log_msg.raw = std::move(rhs.m_log_msg.raw);
m_log_msg.formatted = std::move(rhs.m_log_msg.formatted);
}
}
template <class CharT, class Traits>
spdlog::basic_streambuf<CharT, Traits>::~basic_streambuf()
{
if (!m_plogger)
return;
try
{
m_plogger->_sink_it(m_log_msg);
}
catch (const std::exception &ex)
{
m_plogger->error_handler()(ex.what());
}
catch (...)
{
m_plogger->error_handler()("Unknown exception");
}
}
template <class CharT, class Traits>
std::streamsize spdlog::basic_streambuf<CharT, Traits>::xsputn(const char_type* __s, std::streamsize __n)
{
if (!m_plogger)
return 0;
try
{
m_log_msg.raw << fmt::BasicStringRef<char_type>(__s, __n);
}
catch (const std::exception &ex)
{
m_plogger->error_handler()(ex.what());
}
catch (...)
{
m_plogger->error_handler()("Unknown exception");
}
return __n;
}

@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cmath>
#include <cstdarg>
#include <cstddef> // for std::ptrdiff_t
#include <stdio.h>
#if defined(_WIN32) && defined(__MINGW32__)
# include <cstring>
@ -444,12 +445,12 @@ namespace fmt {
typedef internal::NamedArg<Char> NamedArg;
const NamedArg *named_arg = FMT_NULL;
bool use_values =
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE_ARG;
if (use_values) {
for (unsigned i = 0;/*nothing*/; ++i) {
internal::Arg::Type arg_type = args.type(i);
switch (arg_type) {
case internal::Arg::NONE:
case internal::Arg::NONE_ARG:
return;
case internal::Arg::NAMED_ARG:
named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
@ -470,7 +471,7 @@ namespace fmt {
}
for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
switch (args.args_[i].type) {
case internal::Arg::NONE:
case internal::Arg::NONE_ARG:
return;
case internal::Arg::NAMED_ARG:
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
@ -493,7 +494,7 @@ namespace fmt {
{
Arg arg = args_[arg_index];
switch (arg.type) {
case Arg::NONE:
case Arg::NONE_ARG:
error = "argument index out of range";
break;
case Arg::NAMED_ARG:

@ -1285,7 +1285,7 @@ struct Value
enum Type
{
NONE, NAMED_ARG,
NONE_ARG, NAMED_ARG,
// Integer types should go first,
INT, UINT, LONG_LONG, ULONG_LONG, BOOL, CHAR, LAST_INTEGER_TYPE = CHAR,
// followed by floating-point types.
@ -1684,7 +1684,7 @@ class MakeArg: public Arg
public:
MakeArg()
{
type = Arg::NONE;
type = Arg::NONE_ARG;
}
template <typename T>
@ -1781,12 +1781,12 @@ public:
{
using internal::Arg;
Arg arg;
bool use_values = type(MAX_PACKED_ARGS - 1) == Arg::NONE;
bool use_values = type(MAX_PACKED_ARGS - 1) == Arg::NONE_ARG;
if (index < MAX_PACKED_ARGS)
{
Arg::Type arg_type = type(index);
internal::Value &val = arg;
if (arg_type != Arg::NONE)
if (arg_type != Arg::NONE_ARG)
val = use_values ? values_[index] : args_[index];
arg.type = arg_type;
return arg;
@ -1795,12 +1795,12 @@ public:
{
// The index is greater than the number of arguments that can be stored
// in values, so return a "none" argument.
arg.type = Arg::NONE;
arg.type = Arg::NONE_ARG;
return arg;
}
for (unsigned i = MAX_PACKED_ARGS; i <= index; ++i)
{
if (args_[i].type == Arg::NONE)
if (args_[i].type == Arg::NONE_ARG)
return args_[i];
}
return args_[index];
@ -1961,7 +1961,7 @@ public:
{
switch (arg.type)
{
case Arg::NONE:
case Arg::NONE_ARG:
case Arg::NAMED_ARG:
FMT_ASSERT(false, "invalid argument type");
break;
@ -2672,7 +2672,7 @@ static Value make(const T &value)
template <unsigned N>
struct ArgArray<N, false/*IsPacked*/>
{
typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE
typedef Arg Type[N + 1]; // +1 for the list end Arg::NONE_ARG
template <typename Formatter, typename T>
static Arg make(const T &value)

@ -14,6 +14,7 @@
#include <spdlog/sinks/base_sink.h>
#include <spdlog/common.h>
#include <spdlog/stream.h>
#include <vector>
#include <memory>
@ -52,6 +53,14 @@ public:
template <typename T> void error(const T&);
template <typename T> void critical(const T&);
ostream log(level::level_enum lvl);
ostream trace();
ostream debug();
ostream info();
ostream warn();
ostream error();
ostream critical();
bool should_log(level::level_enum) const;
void set_level(level::level_enum);
level::level_enum level() const;
@ -71,6 +80,9 @@ public:
const std::vector<sink_ptr>& sinks() const;
protected:
template <class CharT, class Traits>
friend class basic_streambuf;
virtual void _sink_it(details::log_msg&);
virtual void _set_pattern(const std::string&);
virtual void _set_formatter(formatter_ptr);
@ -92,3 +104,4 @@ protected:
}
#include <spdlog/details/logger_impl.h>
#include <spdlog/details/stream_impl.h>

@ -0,0 +1,80 @@
//
// Copyright(c) 2017 Benoit Leforestier.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//
#pragma once
#include <ostream>
namespace spdlog
{
class logger;
template <class CharT, class Traits = std::char_traits<CharT>>
class basic_streambuf : public std::basic_streambuf<CharT, Traits>
{
public:
typedef std::basic_streambuf<CharT, Traits> _Mysb;
typedef CharT char_type;
typedef Traits traits_type;
typedef typename Traits::int_type int_type;
typedef typename Traits::pos_type pos_type;
typedef typename Traits::off_type off_type;
basic_streambuf(logger* plogger, level::level_enum lvl);
basic_streambuf(basic_streambuf&& rhs);
virtual ~basic_streambuf();
basic_streambuf(const basic_streambuf&) = delete;
basic_streambuf& operator=(const basic_streambuf&) = delete;
basic_streambuf& operator=(basic_streambuf&&) = delete;
protected:
virtual std::streamsize xsputn(const char_type* __s, std::streamsize __n) override;
private:
logger* m_plogger;
details::log_msg m_log_msg;
};
template <class CharT, class Traits = std::char_traits<CharT>>
class basic_ostream : public std::basic_ostream < CharT, Traits >
{
public:
typedef std::basic_ostream<CharT, Traits> _Mybase;
typedef CharT char_type;
typedef Traits traits_type;
typedef typename Traits::int_type int_type;
typedef typename Traits::pos_type pos_type;
typedef typename Traits::off_type off_type;
basic_ostream() : _Mybase(&m_rdbuf), m_rdbuf(nullptr, level::critical) {}
basic_ostream(spdlog::logger* plogger, level::level_enum lvl) : _Mybase(&m_rdbuf), m_rdbuf(plogger, lvl) {}
basic_ostream(basic_ostream&& rhs_stream) : _Mybase(&m_rdbuf), m_rdbuf(std::move(rhs_stream.m_rdbuf)) {}
virtual ~basic_ostream() = default;
basic_ostream(const basic_ostream&) = delete;
basic_ostream& operator=(const basic_ostream&) = delete;
basic_ostream& operator=(basic_ostream&& rhs_stream) { swap(rhs_stream); return *this; }
basic_streambuf<char_type>* rdbuf() const
{
basic_streambuf<char_type>* pBuf = _Mybase::rdbuf();
if (!pBuf)
return const_cast<basic_streambuf<char_type>*>(&m_rdbuf);
return reinterpret_cast<basic_streambuf<char_type>*>(pBuf);
}
private:
basic_streambuf<char_type> m_rdbuf;
};
typedef basic_streambuf<char> streambuf;
typedef basic_streambuf<wchar_t> wstreambuf;
typedef basic_ostream<char> ostream;
typedef basic_ostream<wchar_t> wostream;
}
Loading…
Cancel
Save