Added LogStream class for uniform color output handling.

This commit is contained in:
Patrick Lühne 2016-06-14 15:53:53 +02:00
parent 57e9de6b05
commit b599670572
3 changed files with 294 additions and 71 deletions

View File

@ -3,7 +3,7 @@
#include <iostream> #include <iostream>
#include <unistd.h> #include <plasp/utils/LogStream.h>
namespace plasp namespace plasp
{ {
@ -41,23 +41,27 @@ enum class FontWeight
struct Format struct Format
{ {
Format(Color color, FontWeight fontWeight = FontWeight::Normal) Format(Color color, FontWeight fontWeight = FontWeight::Normal)
: color{color}, : m_color{color},
fontWeight{fontWeight} m_fontWeight{fontWeight}
{ {
} }
Color color; Color m_color;
FontWeight fontWeight; FontWeight m_fontWeight;
}; };
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
std::ostream &operator<<(std::ostream &ostream, const Format &format) template<StandardStream StandardStream>
LogStream<StandardStream> &operator<<(LogStream<StandardStream> &stream, const Format &format)
{ {
const auto fontWeightCode = static_cast<size_t>(format.fontWeight); if (!stream.supportsColor())
const auto colorCode = 30 + static_cast<size_t>(format.color); return stream;
return (ostream << "\033[" << fontWeightCode << ";" << colorCode << "m"); const auto fontWeightCode = static_cast<size_t>(format.m_fontWeight);
const auto colorCode = 30 + static_cast<size_t>(format.m_color);
return (stream << "\033[" << fontWeightCode << ";" << colorCode << "m");
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -68,9 +72,13 @@ class ResetFormat
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
std::ostream &operator<<(std::ostream &ostream, const ResetFormat &) template<StandardStream StandardStream>
LogStream<StandardStream> &operator<<(LogStream<StandardStream> &stream, const ResetFormat &)
{ {
return (ostream << "\033[0m"); if (!stream.supportsColor())
return stream;
return (stream << "\033[0m");
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,247 @@
#ifndef __PLASP__UTILS__LOG_STREAM_H
#define __PLASP__UTILS__LOG_STREAM_H
#include <iostream>
#include <unistd.h>
namespace plasp
{
namespace utils
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// LogStream
//
////////////////////////////////////////////////////////////////////////////////////////////////////
enum class StandardStream
{
Out,
Err
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
class LogStream
{
private:
using CharacterType = std::ostream::char_type;
using TraitsType = std::ostream::traits_type;
public:
bool supportsColor() const
{
const auto fileDescriptor =
(StandardStream == StandardStream::Out)
? STDOUT_FILENO
: STDERR_FILENO;
return isatty(fileDescriptor);
}
std::ostream &ostream()
{
return (StandardStream == StandardStream::Out)
? std::cout
: std::cerr;
}
LogStream &operator<<(short value);
LogStream &operator<<(unsigned short value);
LogStream &operator<<(int value);
LogStream &operator<<(unsigned int value);
LogStream &operator<<(long value);
LogStream &operator<<(unsigned long value);
LogStream &operator<<(long long value);
LogStream &operator<<(unsigned long long value);
LogStream &operator<<(float value);
LogStream &operator<<(double value);
LogStream &operator<<(long double value);
LogStream &operator<<(bool value);
LogStream &operator<<(const void *value);
LogStream &operator<<(const char *value);
LogStream &operator<<(std::basic_streambuf<CharacterType, TraitsType> *sb);
LogStream &operator<<(std::ios_base &(*func)(std::ios_base &));
LogStream &operator<<(std::basic_ios<CharacterType, TraitsType> &(*func)(std::basic_ios<CharacterType, TraitsType> &));
LogStream &operator<<(std::basic_ostream<CharacterType, TraitsType> &(*func)(std::basic_ostream<CharacterType, TraitsType> &));
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(short value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(unsigned short value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(int value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(unsigned int value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(long value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(unsigned long value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(long long value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(unsigned long long value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(float value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(double value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(long double value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(bool value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(const void *value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(const char *value)
{
ostream() << value;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(std::basic_streambuf<CharacterType, TraitsType>* sb)
{
ostream() << sb;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(std::ios_base &(*func)(std::ios_base &))
{
ostream() << func;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(std::basic_ios<CharacterType, TraitsType> &(*func)(std::basic_ios<CharacterType, TraitsType> &))
{
ostream() << func;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream>
LogStream<StandardStream> &LogStream<StandardStream>::operator<<(std::basic_ostream<CharacterType, TraitsType> &(*func)(std::basic_ostream<CharacterType, TraitsType> &))
{
ostream() << func;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<StandardStream StandardStream, class CharacterType, class Traits, class Allocator>
LogStream<StandardStream> &operator<<(LogStream<StandardStream> &stream, const std::basic_string<CharacterType, Traits, Allocator> &string)
{
stream.ostream() << string;
return stream;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,6 +1,7 @@
#include <plasp/utils/Logger.h> #include <plasp/utils/Logger.h>
#include <plasp/utils/Formatting.h> #include <plasp/utils/Formatting.h>
#include <plasp/utils/LogStream.h>
namespace plasp namespace plasp
{ {
@ -63,50 +64,29 @@ void Logger::setWarningLevel(WarningLevel warningLevel)
void Logger::logError(const std::string &message) void Logger::logError(const std::string &message)
{ {
if (isatty(STDERR_FILENO)) LogStream<StandardStream::Err> stream;
{
std::cerr stream
<< Format(Color::Red, FontWeight::Bold) << "error:" << Format(Color::Red, FontWeight::Bold) << "error:"
<< ResetFormat() << " " << ResetFormat() << " "
<< Format(Color::White, FontWeight::Bold) << message << Format(Color::White, FontWeight::Bold) << message
<< ResetFormat() << std::endl; << ResetFormat() << std::endl;
}
else
{
std::cerr
<< "error:"
<< " "
<< message
<< std::endl;
}
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
void Logger::logError(const Parser::Coordinate &coordinate, const std::string &message) void Logger::logError(const Parser::Coordinate &coordinate, const std::string &message)
{ {
if (isatty(STDERR_FILENO)) LogStream<StandardStream::Err> stream;
{
std::cerr stream
<< Format(Color::White, FontWeight::Bold) << coordinate.sectionName << ":" << Format(Color::White, FontWeight::Bold) << coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":" << std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":"
<< ResetFormat() << " " << ResetFormat() << " "
<< Format(Color::Red, FontWeight::Bold) << "error:" << Format(Color::Red, FontWeight::Bold) << "error:"
<< ResetFormat() << " " << ResetFormat() << " "
<< Format(Color::White, FontWeight::Bold) << message << Format(Color::White, FontWeight::Bold) << message
<< ResetFormat() << std::endl; << ResetFormat() << std::endl;
}
else
{
std::cerr
<< coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":"
<< " "
<< "error:"
<< " "
<< message
<< std::endl;
}
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
@ -121,28 +101,16 @@ void Logger::logWarning(const Parser &parser, const std::string &message)
const auto coordinate = parser.coordinate(); const auto coordinate = parser.coordinate();
if (isatty(STDERR_FILENO)) LogStream<StandardStream::Err> stream;
{
std::cerr stream
<< Format(Color::White, FontWeight::Bold) << coordinate.sectionName << ":" << Format(Color::White, FontWeight::Bold) << coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":" << std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":"
<< ResetFormat() << " " << ResetFormat() << " "
<< Format(Color::Magenta, FontWeight::Bold) << "warning:" << Format(Color::Magenta, FontWeight::Bold) << "warning:"
<< ResetFormat() << " " << ResetFormat() << " "
<< Format(Color::White, FontWeight::Bold) << message << Format(Color::White, FontWeight::Bold) << message
<< ResetFormat() << std::endl; << ResetFormat() << std::endl;
}
else
{
std::cerr
<< coordinate.sectionName << ":"
<< std::to_string(coordinate.row) + ":" + std::to_string(coordinate.column) << ":"
<< " "
<< "warning:"
<< " "
<< message
<< std::endl;
}
} }
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////