Hey, I have been coding a 30 minutes logging library for my applications, I would appreciate some comments about it .
Thank You!
Code:
#include <iostream>
#include <string>
#include <cassert>
#include <fstream>
#include <functional>
namespace log_level {
enum type
{
ok,
info,
warning,
error
};
const char* get_string(type level)
{
switch (level)
{
case ok: return "OK";
case info: return "INFO";
case warning: return "WARNING";
case error: return "ERROR";
}
assert(false);
return "";
}
};
template<class Char, class Traits = std::char_traits<Char> >
class basic_log_message
{
typedef Char char_t;
const char_t* m_message;
log_level::type m_level;
public:
const char_t* get_message() const { return m_message; }
log_level::type get_level() const { return m_level; }
basic_log_message(const char_t* message, log_level::type level = log_level::ok)
: m_message(message)
, m_level(level)
{
}
};
typedef basic_log_message<wchar_t, std::char_traits<wchar_t> > wlog_message;
typedef basic_log_message<char, std::char_traits<char> > log_message;
template<class Char>
struct basic_formatter;
template<class Char, class Traits = std::char_traits<Char>, class Formatter = basic_formatter<Char> >
class basic_logger
{
typedef Char char_t;
typedef basic_logger<Char, Traits, Formatter> my_type;
typedef basic_log_message<Char, Traits> message_t;
// we use reference_wrapper so that we can reassign the output reference
std::tr1::reference_wrapper<std::basic_ostream<Char, Traits> > m_output;
protected:
// unformatted logging
template<class T>
my_type& operator<<(const T& value)
{
m_output.get() << value;
return *this;
}
public:
basic_logger(std::basic_ostream<Char, Traits>& output)
: m_output(std::tr1::ref(output))
{
}
void redirect(std::basic_ostream<Char, Traits>& output)
{
m_output = std::tr1::ref(output);
}
void put(const message_t& message)
{
Formatter::append_message(*this, message);
}
void put(const char_t* message)
{
put(log_message(message));
}
friend typename Formatter;
};
typedef basic_logger<wchar_t, std::char_traits<wchar_t> > wlogger;
typedef basic_logger<char, std::char_traits<char> > logger;
extern wlogger wlog(std::wcout);
extern logger log(std::cout );
template<class Char, class Traits>
basic_logger<Char, Traits>& operator<<(basic_logger<Char, Traits>& other_logger, const basic_log_message<Char, Traits>& message)
{
other_logger.put(message);
return other_logger;
}
template<class Char>
struct basic_formatter
{
};
template<>
struct basic_formatter<char>
{
template<class Traits>
static void append_message(basic_logger<char, Traits, basic_formatter<char> >& logger, const basic_log_message<char, Traits>& message)
{
logger << '[' << log_level::get_string(message.get_level()) << "] " << message.get_message() << "\n";
}
};
template<>
struct basic_formatter<wchar_t>
{
template<class Traits>
static void append_message(basic_logger<wchar_t, Traits, basic_formatter<wchar_t> >& logger, const basic_log_message<wchar_t, Traits>& message)
{
logger << L'[' << log_level::get_string(message.get_level()) << L"] " << message.get_message() << L"\n";
}
};
void main()
{
std::ofstream file("log.txt");
log.redirect(file);
log << log_message("teste") << log_message("kk", log_level::error);
wlog << wlog_message(L"teste2");
}