Adds doxygen comments.
This commit is contained in:
279
ansi_escapes.h
279
ansi_escapes.h
@@ -1,106 +1,271 @@
|
||||
/**********************************************************************************************************************
|
||||
* *
|
||||
* @file ansi_escapes.h *
|
||||
* *
|
||||
* @brief Defines constants and functions for working with screen colors. *
|
||||
* @copyright Copyright (C) 2023 by Tom Hicks <headhunter3@gmail.com> *
|
||||
* *
|
||||
* Licensed under the MIT license see below for details. *
|
||||
* *
|
||||
* MIT License *
|
||||
* *
|
||||
* Copyright (c) 2023 Tom Hicks <headhunter3@gmail.com> *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated *
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation *
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and *
|
||||
* to permit persons to whom the Software is furnished to do so, subject to the following conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of *
|
||||
* the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO *
|
||||
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
|
||||
* IN THE SOFTWARE. *
|
||||
* *
|
||||
*
|
||||
* @file ansi_escapes.h
|
||||
*
|
||||
* @brief Defines constants and functions for working with screen colors.
|
||||
*
|
||||
* @copyright Copyright (C) 2023 by Tom Hicks <headhunter3@gmail.com>
|
||||
*
|
||||
* Licensed under the MIT license see below for details.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
#ifndef CPP_Utils__ansi_escapes_h__
|
||||
#define CPP_Utils__ansi_escapes_h__
|
||||
/*
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Tom Hicks <headhunter3@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
||||
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
||||
* the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
#ifndef CPPUtils__ansi_escapes_h__
|
||||
#define CPPUtils__ansi_escapes_h__
|
||||
#include "pretty_print.h"
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
/** \addtogroup Ansi Escape Sequences
|
||||
* @{
|
||||
*/
|
||||
namespace CPPUtils {
|
||||
/// @addtogroup ansi_escape_sequences Ansi Escape Sequences
|
||||
/// @{
|
||||
|
||||
/// @brief Gets the red component of a 32bit ARGB color value.
|
||||
/// @param color The color to split.
|
||||
/// @return The red component as an 8-bit unsigned int.
|
||||
constexpr uint8_t GetRedComponent(uint32_t color) {
|
||||
return (color & 0x00FF0000) >> 16;
|
||||
}
|
||||
|
||||
/// @brief Gets the green component of a 32bit ARGB color value.
|
||||
/// @param color The color to split.
|
||||
/// @return The green component as an 8-bit unsigned int.
|
||||
constexpr uint8_t GetGreenComponent(uint32_t color) {
|
||||
return (color & 0x0000FF00) >> 8;
|
||||
}
|
||||
|
||||
/// @brief Gets the blue component of a 32bit ARGB color value.
|
||||
/// @param color The color to split.
|
||||
/// @return The blue component as an 8-bit unsigned int.
|
||||
constexpr uint8_t GetBlueComponent(uint32_t color) {
|
||||
return (color & 0x000000FF);
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& Escape(std::basic_ostream<TChar, TTraits>& os, const std::basic_string<TChar, TTraits>& escape_code) {
|
||||
return os << "\033[" << escape_code << "m";
|
||||
/// @brief Gets the alpha component of a 32bit ARGB color value.
|
||||
///
|
||||
/// This function is included for completeness. You cannot set a transparent color via these ansi escape sequences.
|
||||
/// @param color The color to split.
|
||||
/// @return The alpha component as an 8-bit unsigned int.
|
||||
constexpr uint8_t GetAlphaComponent(uint32_t color) {
|
||||
return (color & 0xFF000000);
|
||||
}
|
||||
|
||||
/// @brief Writes the escape_code string provided as an ansi escape sequence.
|
||||
///
|
||||
/// For example to set the foreground to 24bit red you would pass "38;2;255;0;0" as escape_code and this would print
|
||||
/// "\033" + "38;2;255;0;0" + "m".
|
||||
/// @tparam TChar The type of character in the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @tparam TTraits The char_traits of the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param escape_code The ansi sequence to escape.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& Escape(std::basic_ostream<TChar, TTraits>& os, const std::basic_string_view<TChar, TTraits>& escape_code) {
|
||||
return os << "\033[" << escape_code << "m";
|
||||
auto &Escape(std::basic_ostream<TChar, TTraits> &os, const std::basic_string<TChar, TTraits> &escape_code) {
|
||||
return os << StringTraits<TChar>::Literal("\033[", L"\033[") << escape_code
|
||||
<< StringTraits<TChar>::Literal("m", L"m");
|
||||
}
|
||||
|
||||
/// @brief Writes the escape_code string provided as an ansi escape sequence.
|
||||
///
|
||||
/// For example to set the foreground to 24bit red you would pass "38;2;255;0;0" as escape_code and this would print
|
||||
/// "\033" + "38;2;255;0;0" + "m".
|
||||
/// @tparam TChar The type of character in the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @tparam TTraits The char_traits of the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param escape_code The ansi sequence to escape.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& Escape(std::basic_ostream<TChar, TTraits>& os, const TChar* escape_code) {
|
||||
return os << "\033[" << escape_code << "m";
|
||||
auto &Escape(std::basic_ostream<TChar, TTraits> &os, const std::basic_string_view<TChar, TTraits> &escape_code) {
|
||||
return os << StringTraits<TChar>::Literal("\033[", L"\033[") << escape_code
|
||||
<< StringTraits<TChar>::Literal("m", L"m");
|
||||
}
|
||||
|
||||
/// @brief Writes the escape_code string provided as an ansi escape sequence.
|
||||
///
|
||||
/// For example to set the foreground to 24bit red you would pass "38;2;255;0;0" as escape_code and this would print
|
||||
/// "\033" + "38;2;255;0;0" + "m".
|
||||
/// @tparam TChar The type of character in the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @tparam TTraits The char_traits of the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param escape_code The ansi sequence to escape.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& ForegroundColor8Bit(std::basic_ostream<TChar, TTraits>& os, uint8_t color) {
|
||||
return Escape(os, "38;5;" + std::to_string(color));
|
||||
auto &Escape(std::basic_ostream<TChar, TTraits> &os, const TChar *escape_code) {
|
||||
return os << StringTraits<TChar>::Literal("\033[", L"\033[") << escape_code
|
||||
<< StringTraits<TChar>::Literal("m", L"m");
|
||||
}
|
||||
|
||||
/// @brief Writes an ansi escape sequence that sets the foreground color to one of the 8-bit pallete colors.
|
||||
/// @tparam TChar The type of character in the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @tparam TTraits The char_traits of the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param color The color value to set.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& BackgroundColor8Bit(std::basic_ostream<TChar, TTraits>& os, uint8_t color) {
|
||||
return Escape(os, "48;5;" + std::to_string(color));
|
||||
auto &ForegroundColor8Bit(std::basic_ostream<TChar, TTraits> &os, uint8_t color) {
|
||||
return Escape(os,
|
||||
StringTraits<TChar>::Literal("38;5;", L"38;5;")
|
||||
+ StringTraits<TChar>::Literal(std::to_string(color), std::to_wstring(color)));
|
||||
}
|
||||
|
||||
/// @brief Writes an ansi escape sequence that sets the background color to one of the 8-bit pallete colors.
|
||||
/// @tparam TChar The type of character in the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @tparam TTraits The char_traits of the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param color The color value to set.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& ForegroundTrueColor(std::basic_ostream<TChar, TTraits>& os, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
return os << "\033["
|
||||
<< "38;2;" << (uint16_t)red << ";" << (uint16_t)green << ";" << (uint16_t)blue << "m";
|
||||
auto &BackgroundColor8Bit(std::basic_ostream<TChar, TTraits> &os, uint8_t color) {
|
||||
return Escape(os,
|
||||
StringTraits<TChar>::Literal("48;5;", L"48;5;")
|
||||
+ StringTraits<TChar>::Literal(std::to_string(color), std::to_wstring(color)));
|
||||
}
|
||||
|
||||
/// @brief Writes an ansi escape sequence that sets the foreground color to one of the 24-bit pallete colors.
|
||||
/// @tparam TChar The type of character in the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @tparam TTraits The char_traits of the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param red The red value to set.
|
||||
/// @param green The green value to set.
|
||||
/// @param blue The blue value to set.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& ForegroundTrueColor(std::basic_ostream<TChar, TTraits>& os, uint32_t color) {
|
||||
auto &ForegroundTrueColor(std::basic_ostream<TChar, TTraits> &os, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
std::basic_ostringstream<TChar> str;
|
||||
str << StringTraits<TChar>::Literal("38;2;", L"38;2;") << (uint16_t)red << StringTraits<TChar>::Literal(";", L";")
|
||||
<< (uint16_t)green << StringTraits<TChar>::Literal(";", L";") << (uint16_t)blue;
|
||||
return Escape(os, str.str());
|
||||
}
|
||||
|
||||
/// @brief Writes an ansi escape sequence that sets the foreground color to one of the 24-bit pallete colors.
|
||||
/// @tparam TChar The type of character in the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @tparam TTraits The char_traits of the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param color The encoded ARGB value to set.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto &ForegroundTrueColor(std::basic_ostream<TChar, TTraits> &os, uint32_t color) {
|
||||
return ForegroundTrueColor(os, GetRedComponent(color), GetGreenComponent(color), GetBlueComponent(color));
|
||||
}
|
||||
|
||||
/// @brief Writes an ansi escape sequence that sets the background color to one of the 24-bit pallete colors.
|
||||
/// @tparam TChar The type of character in the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @tparam TTraits The char_traits of the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param red The red value to set.
|
||||
/// @param green The green value to set.
|
||||
/// @param blue The blue value to set.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& BackgroundTrueColor(std::basic_ostream<TChar, TTraits>& os, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
return os << "\033["
|
||||
<< "48;2;" << (uint16_t)red << ";" << (uint16_t)green << ";" << (uint16_t)blue << "m";
|
||||
auto &BackgroundTrueColor(std::basic_ostream<TChar, TTraits> &os, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
std::basic_ostringstream<TChar> str;
|
||||
str << StringTraits<TChar>::Literal("48;2;", L"48;2;") << (uint16_t)red << StringTraits<TChar>::Literal(";", L";")
|
||||
<< (uint16_t)green << StringTraits<TChar>::Literal(";", L";") << (uint16_t)blue;
|
||||
return Escape(os, str.str());
|
||||
}
|
||||
|
||||
/// @brief Writes an ansi escape sequence that sets the background color to one of the 24-bit pallete colors.
|
||||
/// @tparam TChar The type of character in the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @tparam TTraits The char_traits of the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param color The encoded ARGB value to set.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& BackgroundTrueColor(std::basic_ostream<TChar, TTraits>& os, uint32_t color) {
|
||||
auto &BackgroundTrueColor(std::basic_ostream<TChar, TTraits> &os, uint32_t color) {
|
||||
return BackgroundTrueColor(os, GetRedComponent(color), GetGreenComponent(color), GetBlueComponent(color));
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& Reset(std::basic_ostream<TChar, TTraits>& os) {
|
||||
return os << "\033["
|
||||
<< "m";
|
||||
/// @brief Writes an empty escape sequence to reset the output stream.
|
||||
/// @tparam TChar The type of character in the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @tparam TTraits The char_traits of the std::basic_ostream you are writing to.
|
||||
///
|
||||
/// Usually this will be automatically detected from the stream and string you pass in so you shouldn't need to specify
|
||||
/// it.
|
||||
/// @param os The output stream to write to.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits> auto &Reset(std::basic_ostream<TChar, TTraits> &os) {
|
||||
return Escape(os, "");
|
||||
}
|
||||
} // End namespace CPPUtils
|
||||
|
||||
/** @}*/
|
||||
#endif // End !defined CPP_Utils__ansi_escapes_h__
|
||||
/// @}
|
||||
} // End namespace CPPUtils
|
||||
|
||||
#endif // End !defined CPPUtils__ansi_escapes_h__
|
||||
|
||||
129
console_logger.h
129
console_logger.h
@@ -1,33 +1,36 @@
|
||||
/**********************************************************************************************************************
|
||||
* *
|
||||
* @file console_logger.h *
|
||||
* *
|
||||
* @brief Declares the ConsoleLogger class that is a logging destination for the Logger class declared in logger.h *
|
||||
* @copyright Copyright (C) 2023 by Tom Hicks <headhunter3@gmail.com> *
|
||||
* *
|
||||
* Licensed under the MIT license see below for details. *
|
||||
* *
|
||||
* MIT License *
|
||||
* *
|
||||
* Copyright (c) 2023 Tom Hicks <headhunter3@gmail.com> *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated *
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation *
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and *
|
||||
* to permit persons to whom the Software is furnished to do so, subject to the following conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of *
|
||||
* the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO *
|
||||
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
|
||||
* IN THE SOFTWARE. *
|
||||
* *
|
||||
*
|
||||
* @file console_logger.h
|
||||
*
|
||||
* @brief Declares the ConsoleLogger class that is a logging destination for the Logger class declared in logger.h
|
||||
*
|
||||
* @copyright Copyright (C) 2023 by Tom Hicks <headhunter3@gmail.com>
|
||||
*
|
||||
* Licensed under the MIT license see below for details.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
#ifndef CONSOLE_LOGGER_H__
|
||||
#define CONSOLE_LOGGER_H__
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Tom Hicks <headhunter3@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
||||
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
||||
* the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
#ifndef CPPUtils__console_logger_h__
|
||||
#define CPPUtils__console_logger_h__
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <ostream>
|
||||
@@ -36,32 +39,52 @@
|
||||
#include "logger.h"
|
||||
|
||||
namespace CPPUtils {
|
||||
class ConsoleLogger : public Logger::Destination {
|
||||
public:
|
||||
ConsoleLogger();
|
||||
virtual ~ConsoleLogger();
|
||||
virtual void LogMessage(const Logger::MessageType& type, const std::string& message) const;
|
||||
virtual void LogError(const Logger::MessageType& type, const std::exception& ex) const;
|
||||
virtual void LogError(const Logger::MessageType& type, const std::string& message, const std::exception& ex) const;
|
||||
virtual void SetOutputStream(std::ostream& os);
|
||||
virtual std::ostream& GetOutputStream();
|
||||
/// @addtogroup logger Logger
|
||||
/// @{
|
||||
|
||||
/// @brief A @link Logger::Destination @endlink that logs by writing to an std::ostream. By default this stream is
|
||||
/// std::cout.
|
||||
class ConsoleLogger : public Logger::Destination {
|
||||
public:
|
||||
/// @brief Allocates any resources used by this destination. This sets the underlying output stream to std::cout.
|
||||
ConsoleLogger();
|
||||
|
||||
/// @brief Frees any resources used by this destination. This is currently empty.
|
||||
virtual ~ConsoleLogger();
|
||||
|
||||
/// @brief Logs a string message with a specific type.
|
||||
/// @param type The type of message to log.
|
||||
/// @param message The message to log.
|
||||
virtual void LogMessage(const Logger::MessageType &type, const std::string &message) const;
|
||||
|
||||
/// @brief Logs an exception.
|
||||
/// @param type The type of message to log the exception as.
|
||||
/// @param ex The exception to log.
|
||||
virtual void LogError(const Logger::MessageType &type, const std::exception &ex) const;
|
||||
|
||||
/// @brief Logs an exception with a message.
|
||||
/// @param type The type of message to log.
|
||||
/// @param message The message to log.
|
||||
/// @param ex The exception to log.
|
||||
virtual void LogError(const Logger::MessageType &type, const std::string &message, const std::exception &ex) const;
|
||||
|
||||
/// @brief Sets the output stream used for logging.
|
||||
/// @param os The std::ostream to use for logging.
|
||||
virtual void SetOutputStream(std::ostream &os);
|
||||
|
||||
/// @brief Gets the current output stream.
|
||||
/// @return The std::ostream used for logging.
|
||||
virtual std::ostream &GetOutputStream();
|
||||
|
||||
private:
|
||||
/// @brief Gets the title to be used based on the @link MessageType @endlink.
|
||||
/// @param type The @link Logger::MessageType @endlink to get the title for.
|
||||
/// @return The title to be used for this @link MessageType @endlink.
|
||||
std::string GetTitle(const Logger::MessageType &type) const;
|
||||
|
||||
private:
|
||||
std::string GetTitle(const Logger::MessageType& type) const;
|
||||
std::reference_wrapper<std::ostream> os_;
|
||||
};
|
||||
} // namespace CPPUtils
|
||||
|
||||
#endif // CONSOLE_LOGGER_H__
|
||||
|
||||
/*
|
||||
Destination();
|
||||
virtual ~Destination();
|
||||
virtual void LogMessage(const MessageType& type, const std::string& message) const = 0;
|
||||
virtual void LogError(const MessageType& type, const std::exception& ex) const = 0;
|
||||
virtual void LogError(const MessageType& type, const std::string& message, const std::exception& ex) const = 0;
|
||||
virtual void SetMinType(const MessageType& type);
|
||||
virtual void SetMaxType(const MessageType& type);
|
||||
virtual MessageType GetMinType() const;
|
||||
virtual MessageType GetMaxType() const;
|
||||
*/
|
||||
/// @}
|
||||
} // namespace CPPUtils
|
||||
#endif // CPPUtils__console_logger_h__
|
||||
|
||||
381
logger.h
381
logger.h
@@ -1,34 +1,38 @@
|
||||
/**********************************************************************************************************************
|
||||
* *
|
||||
* @file logger.h *
|
||||
* *
|
||||
* @brief Declares the Logger class used as a generic interface to log to logging destinations. *
|
||||
* Multiple logging destinations can be registered with different thresholds. *
|
||||
* @copyright Copyright (C) 2023 by Tom Hicks <headhunter3@gmail.com> *
|
||||
* *
|
||||
* Licensed under the MIT license see below for details. *
|
||||
* *
|
||||
* MIT License *
|
||||
* *
|
||||
* Copyright (c) 2023 Tom Hicks <headhunter3@gmail.com> *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated *
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation *
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and *
|
||||
* to permit persons to whom the Software is furnished to do so, subject to the following conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of *
|
||||
* the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO *
|
||||
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
|
||||
* IN THE SOFTWARE. *
|
||||
* *
|
||||
*
|
||||
* @file logger.h
|
||||
*
|
||||
* @brief Declares the Logger class used as a generic interface to log to logging destinations.
|
||||
*
|
||||
* Multiple logging destinations can be registered with different thresholds.
|
||||
*
|
||||
* @copyright Copyright (C) 2023 by Tom Hicks <headhunter3@gmail.com>
|
||||
*
|
||||
* Licensed under the MIT license.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
#ifndef CPPUtils__Logger_h__
|
||||
#define CPPUtils__Logger_h__
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Tom Hicks <headhunter3@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
||||
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
||||
* the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
#ifndef CPPUtils__logger_h__
|
||||
#define CPPUtils__logger_h__
|
||||
|
||||
#include <exception>
|
||||
#include <memory>
|
||||
@@ -36,78 +40,303 @@
|
||||
#include <vector>
|
||||
|
||||
namespace CPPUtils {
|
||||
class Logger {
|
||||
public:
|
||||
enum MessageType { Unknown = 0, Debug, Verbose, Info, Warning, Error, Wtf };
|
||||
/// @addtogroup logger Logger
|
||||
/// @{
|
||||
|
||||
/// @brief The Logger class can be used as a general purpose logging system.
|
||||
/// It allows the user to register one or more destinations for log requests. Each destination can be configured to
|
||||
/// respond to different levels of messages. Logger also provides some utility methods to log specific debug conditions.
|
||||
/// LogUnimplementedMethod, LogUnhandledError, LogUnimplementedFeature, and LogToDo.
|
||||
///
|
||||
/// * @link LogUnimplementedMethod @endlink logs a debug message that the calling method has not been implemented. When
|
||||
/// compiled with c++20 or higher it is a normal function, but for earlier c++ versions there is a #define
|
||||
/// LogUnimplementedMethod that calls @link LogUnimplementedMethodReal @endlink with the calling function name.
|
||||
///
|
||||
/// * @link LogUnhandledError @endlink logs a debug message that some exception was caught the calling code doesn't know
|
||||
/// what to do with it, but wants to try to continue.
|
||||
///
|
||||
/// * @link LogUnimplementedFeature @endlink logs a debug message that some feature has not been implemented yet. This
|
||||
/// is useful for when a branch of code hasn't been implemented but the rest of the function has.
|
||||
///
|
||||
/// * @link LogToDo @endlink logs a debug message that something needs to be done.
|
||||
class Logger {
|
||||
public:
|
||||
/// @brief The type of a message.
|
||||
enum MessageType {
|
||||
/// The lowest level. Anything that logs with this level is likely a mistake.
|
||||
Unknown = 0,
|
||||
/// The second lowest level. This message type is debugging information. The convenience methods all log at this
|
||||
/// level.
|
||||
Debug,
|
||||
/// This is the third lowest level. Logs at this level should be useful to an end user. It is good for detailed
|
||||
/// diagnostic messages.
|
||||
Verbose,
|
||||
/// This is the middle level. It is useful for standard logging such as application configuration or state changes.
|
||||
Info,
|
||||
/// This is the third highest level. It is useful for when something may be wrong, but it likely recoverable or the
|
||||
/// action can be retried. This level is also good for things are not an error, but may produce unexpected results.
|
||||
Warning,
|
||||
/// This is the second highest level. This is for common errors like failed connections and files not being
|
||||
/// writable. At this level something is definitely wrong, but may be recoverable.
|
||||
Error,
|
||||
/// This is the highest level. Conditions that log at this level are almost always fatal. Use it when something
|
||||
/// happens that should be impossible. It is useful for when you have unimplemented code paths that are skipped
|
||||
/// because data should never let them be called. It can help track down why something else is crashing or incorrect
|
||||
/// because of data model changes.
|
||||
Wtf,
|
||||
};
|
||||
|
||||
/// @brief This is an abstract class used to represent a logging destination.
|
||||
/// Users should subclass Destination and implement LogMessage and both LogError methods to create a new logging
|
||||
/// destination.
|
||||
///
|
||||
/// @see ConsoleLogger for an example destination that logs to cout.
|
||||
class Destination {
|
||||
public:
|
||||
public:
|
||||
/// @brief Allocates resources used by this destination. This is currently empty.
|
||||
Destination();
|
||||
/// @brief Releases any resources allocated by this destination. This is currently empty.
|
||||
virtual ~Destination();
|
||||
virtual void LogMessage(const MessageType& type, const std::string& message) const = 0;
|
||||
virtual void LogError(const MessageType& type, const std::exception& ex) const = 0;
|
||||
virtual void LogError(const MessageType& type, const std::string& message, const std::exception& ex) const = 0;
|
||||
virtual void SetMinType(const MessageType& type);
|
||||
virtual void SetMaxType(const MessageType& type);
|
||||
/// @brief Logs a string message with a specific type.
|
||||
/// @param type The type of message to log.
|
||||
/// @param message The message to log.
|
||||
virtual void LogMessage(const MessageType &type, const std::string &message) const = 0;
|
||||
/// @brief Logs an exception.
|
||||
/// @param type The type of message to log the exception as.
|
||||
/// @param ex The exception to log.
|
||||
virtual void LogError(const MessageType &type, const std::exception &ex) const = 0;
|
||||
/// @brief Logs an exception with a message.
|
||||
/// @param type The type of message to log.
|
||||
/// @param message The message to log.
|
||||
/// @param ex The exception to log.
|
||||
virtual void LogError(const MessageType &type, const std::string &message, const std::exception &ex) const = 0;
|
||||
/// @brief Sets the minimum message type that this logger logs. Requests to log messages lower than this type will
|
||||
/// be ignored.
|
||||
/// @param type The message type to set.
|
||||
virtual void SetMinType(const MessageType &type);
|
||||
/// @brief Sets the maximum message type that this logger logs. Requests to log messages higher than this type will
|
||||
/// be ignored.
|
||||
/// @param type The message type to set.
|
||||
virtual void SetMaxType(const MessageType &type);
|
||||
/// @brief Gets the maximum message type that this logger logs.
|
||||
/// @return The message type.
|
||||
virtual MessageType GetMinType() const;
|
||||
/// @brief Gets the minimum message type that this logger logs.
|
||||
/// @return The message type.
|
||||
virtual MessageType GetMaxType() const;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
MessageType min_type_;
|
||||
MessageType max_type_;
|
||||
};
|
||||
|
||||
virtual ~Logger();
|
||||
static std::shared_ptr<Logger> GetShared();
|
||||
static std::shared_ptr<Logger> GetUnique();
|
||||
virtual void AddDestination(std::shared_ptr<Logger::Destination> destination);
|
||||
virtual void ClearDestinations();
|
||||
/// If you want to create an instance of Logger you should use @link GetShared() @endlink or @link GetUnique()
|
||||
/// @endlink.
|
||||
/// @name Constructors and Destructors
|
||||
/// @{
|
||||
|
||||
// This one is special and annoying because it requires macros until the minimum standard is c++20.
|
||||
/// @brief Gets the shared Logger instance. Treat this like a singleton.
|
||||
/// @return The same instance each time it is called.
|
||||
static std::shared_ptr<Logger> GetShared();
|
||||
|
||||
/// @brief Gets a unique Logger instance. If you want to separate loggers then use this.
|
||||
/// @return A different instance each time it is called.
|
||||
static std::shared_ptr<Logger> GetUnique();
|
||||
|
||||
/// @brief Frees resources used by the logger. This currently does nothing.
|
||||
virtual ~Logger();
|
||||
|
||||
protected:
|
||||
/// @brief Allocates resources used by the logger. This currently does nothing.
|
||||
Logger();
|
||||
|
||||
public:
|
||||
/// @}
|
||||
|
||||
/// Methods for manipulation the @link Destinations @endlink of this Logger.
|
||||
/// @name Destinations
|
||||
/// @{
|
||||
|
||||
/// @brief Adds a destination to this logger.
|
||||
/// @param destination The destination to add.
|
||||
virtual void AddDestination(std::shared_ptr<Logger::Destination> destination);
|
||||
|
||||
/// @brief Removes all destinations from this logger.
|
||||
virtual void ClearDestinations();
|
||||
/// @}
|
||||
|
||||
/// These methods log debug messages for specific cases.
|
||||
/// @name Convenience Methods
|
||||
/// @{
|
||||
|
||||
// This one is special and annoying because it requires macros until the minimum standard is c++20.
|
||||
#if __cplusplus >= 202002L
|
||||
/// @brief Logs the calling method as not implemented.
|
||||
/// @param The source location this was called from.
|
||||
void LogUnimplementedMethod(std::source_location = std::source_location::current());
|
||||
#else
|
||||
/// @brief Logs method_name as not implemented. Don't call this directly use LogUnimplementedMethod instead
|
||||
/// @param method_name The name of the method that is not implemented.
|
||||
void LogUnimplementedMethodReal(std::string method_name);
|
||||
#endif
|
||||
|
||||
void LogUnhandledError(const std::exception& ex);
|
||||
void LogUnimplementedFeature(const std::string& feature);
|
||||
void LogWtf(const std::string& message);
|
||||
void LogWtf(const std::exception& ex);
|
||||
void LogWtf(const std::string& message, const std::exception& ex);
|
||||
void LogError(const std::string& message);
|
||||
void LogError(const std::exception& ex);
|
||||
void LogError(const std::string& message, const std::exception& ex);
|
||||
void LogWarning(const std::string& message);
|
||||
void LogWarning(const std::exception& ex);
|
||||
void LogWarning(const std::string& message, const std::exception& ex);
|
||||
void LogInfo(const std::string& message);
|
||||
void LogInfo(const std::exception& ex);
|
||||
void LogInfo(const std::string& message, const std::exception& ex);
|
||||
void LogDebug(const std::string& message);
|
||||
void LogDebug(const std::exception& ex);
|
||||
void LogDebug(const std::string& message, const std::exception& ex);
|
||||
void LogVerbose(const std::string& message);
|
||||
void LogVerbose(const std::exception& ex);
|
||||
void LogVerbose(const std::string& message, const std::exception& ex);
|
||||
void Log(const MessageType& type, const std::string& message);
|
||||
void Log(const MessageType& type, const std::exception& ex);
|
||||
void Log(const MessageType& type, const std::string& message, const std::exception& ex);
|
||||
void LogToDo(const std::string& message);
|
||||
/// @brief Logs an exception as unhandled.
|
||||
/// @param ex The exception to log.
|
||||
void LogUnhandledError(const std::exception &ex);
|
||||
|
||||
protected:
|
||||
Logger();
|
||||
/// @brief Logs a feature as not implemented.
|
||||
/// @param feature The name of the unimplemented feature.
|
||||
void LogUnimplementedFeature(const std::string &feature);
|
||||
|
||||
private:
|
||||
/// @brief Logs a TODO message.
|
||||
/// @param message The message to log.
|
||||
void LogToDo(const std::string &message);
|
||||
/// @}
|
||||
|
||||
/// These methods let you pass the @link MessageType @endlink instead of calling the specifically named methods.
|
||||
/// @name General Logging Methods
|
||||
/// @{
|
||||
|
||||
/// @brief Logs a message with a specific message type.
|
||||
/// @param type The type of message to log.
|
||||
/// @param message The message to log.
|
||||
void Log(const MessageType &type, const std::string &message);
|
||||
|
||||
/// @brief Logs an exception with a specific message type.
|
||||
/// @param type The type of message to log.
|
||||
/// @param ex The exception to log.
|
||||
void Log(const MessageType &type, const std::exception &ex);
|
||||
|
||||
/// @brief Logs an exception with a message as a specific message type.
|
||||
/// @param type The type of message to log.
|
||||
/// @param message The message to log.
|
||||
/// @param ex The exception to log.
|
||||
void Log(const MessageType &type, const std::string &message, const std::exception &ex);
|
||||
/// @}
|
||||
|
||||
/// These methods log at the @link Debug @endlink level.
|
||||
/// @name Debug
|
||||
/// @{
|
||||
|
||||
/// @brief Logs a message as a debug.
|
||||
/// @param message The message to log.
|
||||
void LogDebug(const std::string &message);
|
||||
/// @brief Logs an exception as a debug.
|
||||
/// @param ex The exception to log.
|
||||
void LogDebug(const std::exception &ex);
|
||||
/// @brief Logs an exception with a message as a debug.
|
||||
/// @param message The message to log.
|
||||
/// @param ex The exception to log.
|
||||
void LogDebug(const std::string &message, const std::exception &ex);
|
||||
/// @}
|
||||
|
||||
/// These methods log at the @link Verbose @endlink level.
|
||||
/// @name Verbose
|
||||
/// @{
|
||||
|
||||
/// @brief Logs a message as a verbose.
|
||||
/// @param message The message to log.
|
||||
void LogVerbose(const std::string &message);
|
||||
|
||||
/// @brief Logs an exception as a verbose.
|
||||
/// @param ex The exception to log.
|
||||
void LogVerbose(const std::exception &ex);
|
||||
|
||||
/// @brief Logs an exception with a message as a verbose.
|
||||
/// @param message The message to log.
|
||||
/// @param ex The exception to log.
|
||||
void LogVerbose(const std::string &message, const std::exception &ex);
|
||||
/// @}
|
||||
|
||||
/// These methods log at the @link Info @endlink level.
|
||||
/// @name Info
|
||||
/// @{
|
||||
|
||||
/// @brief Logs a message as an Info.
|
||||
/// @param message The message to log.
|
||||
void LogInfo(const std::string &message);
|
||||
|
||||
/// @brief Logs an exception as an Info.
|
||||
/// @param ex The exception to log.
|
||||
void LogInfo(const std::exception &ex);
|
||||
|
||||
/// @brief Logs an exception with a message as an Info.
|
||||
/// @param message The message to log.
|
||||
/// @param ex The exception to log.
|
||||
void LogInfo(const std::string &message, const std::exception &ex);
|
||||
/// @}
|
||||
|
||||
/// These methods log at the @link Warning @endlink level.
|
||||
/// @name Warning
|
||||
/// @{
|
||||
|
||||
/// @brief Logs a message as a warning.
|
||||
/// @param message The message to log.
|
||||
void LogWarning(const std::string &message);
|
||||
|
||||
/// @brief Logs an exception as a warning.
|
||||
/// @param ex The exception to log.
|
||||
void LogWarning(const std::exception &ex);
|
||||
|
||||
/// @brief Logs an exception with a message as a warning.
|
||||
/// @param message The message to log.
|
||||
/// @param ex The exception to log.
|
||||
void LogWarning(const std::string &message, const std::exception &ex);
|
||||
/// @}
|
||||
|
||||
/// These methods log at the @link Error @endlink level.
|
||||
/// @name Error
|
||||
/// @{
|
||||
|
||||
/// @brief Logs a message as an error.
|
||||
/// @param message The message to log.
|
||||
void LogError(const std::string &message);
|
||||
|
||||
/// @brief Logs an exception as an error.
|
||||
/// @param ex The exception to log.
|
||||
void LogError(const std::exception &ex);
|
||||
|
||||
/// @brief Logs an exception with a message as an error.
|
||||
/// @param message The message to log.
|
||||
/// @param ex The exception to log.
|
||||
void LogError(const std::string &message, const std::exception &ex);
|
||||
/// @}
|
||||
|
||||
/// These methods log at the @link Wtf @endlink level.
|
||||
/// @name Wtf (What a Terrible Failure)
|
||||
/// @{
|
||||
|
||||
/// @brief Logs a message as a terrible failure. This is something that the user expects to never happen.
|
||||
/// @param message The message to log.
|
||||
void LogWtf(const std::string &message);
|
||||
/// @brief Logs an exception as a terrible failure. This is something that the user expects to never happen.
|
||||
/// @param ex The exception to log.
|
||||
void LogWtf(const std::exception &ex);
|
||||
/// @brief Logs an exception with a message as a terrible failure. This is something that user expects to never
|
||||
/// happen.
|
||||
/// @param message The message to log.
|
||||
/// @param ex The exception to log.
|
||||
void LogWtf(const std::string &message, const std::exception &ex);
|
||||
/// @}
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<Logger::Destination>> destinations_;
|
||||
};
|
||||
} // End namespace CPPUtils
|
||||
|
||||
/// @}
|
||||
} // End namespace CPPUtils
|
||||
|
||||
/// @addtogropu Logger
|
||||
/// @{
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
#elif defined __GNUC__
|
||||
#define LogUnimplementedMethod Logger::LogUnimplementedMethodReal(__PRETTY_FUNCTION__);
|
||||
/// @brief Logs a debug message saying the calling method is not implemented.
|
||||
#define LogUnimplementedMethod Logger::LogUnimplementedMethodReal(__PRETTY_FUNCTION__)
|
||||
#else
|
||||
#define LogUnimplementedMethod Logger::LogUnimplementedMethodReal(__FUNCTION__);
|
||||
/// @brief Logs a debug message saying the calling method is not implemented.
|
||||
#define LogUnimplementedMethod Logger::LogUnimplementedMethodReal(__FUNCTION__)
|
||||
#endif
|
||||
|
||||
#endif // End !defined(CPPUtils__Logger_h__)
|
||||
/// @}
|
||||
#endif // End !defined(CPPUtils__logger_h__)
|
||||
|
||||
390
pretty_print.h
390
pretty_print.h
@@ -1,35 +1,39 @@
|
||||
/**********************************************************************************************************************
|
||||
* *
|
||||
* @file pretty_print.h *
|
||||
* *
|
||||
* @brief Declares function templates for printing objects in a friendlier manner. *
|
||||
* This specifically helps for printing stl containers, tuples, pairs, and queues as well as quoting strings *
|
||||
* contained within them. *
|
||||
* @copyright Copyright (C) 2023 by Tom Hicks <headhunter3@gmail.com> *
|
||||
* *
|
||||
* Licensed under the MIT license see below for details. *
|
||||
* *
|
||||
* MIT License *
|
||||
* *
|
||||
* Copyright (c) 2023 Tom Hicks <headhunter3@gmail.com> *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated *
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation *
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and *
|
||||
* to permit persons to whom the Software is furnished to do so, subject to the following conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of *
|
||||
* the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO *
|
||||
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS *
|
||||
* IN THE SOFTWARE. *
|
||||
* *
|
||||
*
|
||||
* @file pretty_print.h
|
||||
*
|
||||
* @brief Declares function templates for printing objects in a friendlier manner.
|
||||
*
|
||||
* This specifically helps for printing stl containers, tuples, pairs, and queues as well as quoting strings
|
||||
* contained within them.
|
||||
*
|
||||
* @copyright Copyright (C) 2023 by Tom Hicks <headhunter3@gmail.com>
|
||||
*
|
||||
* Licensed under the MIT license see below for details.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
#ifndef CPP_UTILS_pretty_print_h__
|
||||
#define CPP_UTILS_pretty_print_h__
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Tom Hicks <headhunter3@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
||||
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
||||
* the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
**********************************************************************************************************************/
|
||||
#ifndef CPPUtils__pretty_print_h__
|
||||
#define CPPUtils__pretty_print_h__
|
||||
#include <initializer_list>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
@@ -38,136 +42,257 @@
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
/** \addtogroup Pretty Print
|
||||
* @{
|
||||
*/
|
||||
namespace CPPUtils {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Helper templates - These are not directly tested.
|
||||
template <typename TChar>
|
||||
struct StringTraits;
|
||||
/// @addtogroup pretty_print Pretty Print
|
||||
/// @{
|
||||
|
||||
template <>
|
||||
struct StringTraits<char> {
|
||||
static constexpr const char* Literal(const char* narrow, const wchar_t* wide) { return narrow; }
|
||||
/// @name Helper Templates
|
||||
/// These are not directly tested.
|
||||
/// @{
|
||||
|
||||
/// @brief This SFINAE struct is used to select the correct wide or narrow string based the TChar.
|
||||
/// @tparam TChar The character type of the string we want. This should either be char or wchar_t.
|
||||
template <typename TChar> struct StringTraits;
|
||||
|
||||
/// @brief This SFINAE struct is use to select a narrow string.
|
||||
template <> struct StringTraits<char> {
|
||||
static constexpr const char *Literal(const char *narrow, const wchar_t *wide) { return narrow; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct StringTraits<wchar_t> {
|
||||
static constexpr const wchar_t* Literal(const char* narrow, const wchar_t* wide) { return wide; }
|
||||
/// @brief This SFINAE struct is used to select a wide string.
|
||||
template <> struct StringTraits<wchar_t> {
|
||||
static constexpr const wchar_t *Literal(const char *narrow, const wchar_t *wide) { return wide; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_container {
|
||||
template <typename U>
|
||||
static constexpr bool test(decltype(std::begin(std::declval<U>()))*) {
|
||||
return true;
|
||||
}
|
||||
/// @brief This SFINAE struct is used to help select container like types.
|
||||
/// @tparam T The potential container type.
|
||||
template <typename T> struct is_container {
|
||||
template <typename U> static constexpr bool test(decltype(std::begin(std::declval<U>())) *) { return true; }
|
||||
|
||||
template <typename U>
|
||||
static constexpr bool test(...) {
|
||||
return false;
|
||||
}
|
||||
template <typename U> static constexpr bool test(...) { return false; }
|
||||
|
||||
static constexpr bool value = test<T>(nullptr);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Forward Declarations
|
||||
/// @}
|
||||
|
||||
// const char* and const wchar_t*
|
||||
template <typename TChar>
|
||||
std::basic_string<TChar> EscapeForPrinting(const TChar* text);
|
||||
/// @name Escape for Printing
|
||||
/// These methods all escape different kinds of strings for printing. Currently they replace the ansi escape character
|
||||
/// with a printable version of its code "\033".
|
||||
/// @{
|
||||
|
||||
/// @brief This function escapes a char* or wchar_t* for printing to cout or wcout.
|
||||
///
|
||||
/// It replaces the escape character with a its code.
|
||||
/// @tparam TChar The type of character of our string. This should be dertermined automatically based on the input type.
|
||||
/// @param text The text to escape.
|
||||
/// @return The escaped string.
|
||||
template <typename TChar> std::basic_string<TChar> EscapeForPrinting(const TChar *text);
|
||||
|
||||
// std::string and std::wstring
|
||||
/// @brief This function escapes a std::string or std::wstring for printing to cout or wcout.
|
||||
/// @tparam TChar The type of character of our string. This should be dertermined automatically based on the input type.
|
||||
/// @tparam TTraits The char_traits type of our string. This should be determined automatically based on the input type.
|
||||
/// @param text The text to escape.
|
||||
/// @return The escaped string.
|
||||
template <typename TChar, typename TTraits>
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string<TChar, TTraits>& text);
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string<TChar, TTraits> &text);
|
||||
|
||||
// std::string_view and std::wstring_view
|
||||
/// @brief This function escapes a std::string_view or std::wstring_view for printing to cout or wcout.
|
||||
/// @tparam TChar The type of character of our string. This should be dertermined automatically based on the input type.
|
||||
/// @tparam TTraits The char_traits type of our string. This should be determined automatically based on the input type.
|
||||
/// @param text The text to escape.
|
||||
/// @return The escaped string.
|
||||
template <typename TChar, typename TTraits>
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string_view<TChar, TTraits>& text);
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string_view<TChar, TTraits> &text);
|
||||
/// @}
|
||||
|
||||
// pointers
|
||||
/// @name Pretty Print
|
||||
/// These functions attempt to print friendlier versions of strings and objects that don't have operator<< defined for
|
||||
/// them.
|
||||
/// @{
|
||||
|
||||
/// @brief This function prints a pointer.
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param pointer The pointer to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const void* pointer);
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, const void *pointer);
|
||||
|
||||
// const char* and const wchar_t*
|
||||
/// @brief This function prints a const char* or const wchar_t* to the output stream.
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param text The text to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const TChar* item);
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, const TChar *text);
|
||||
|
||||
// std::string and std::wstring
|
||||
/// @brief This function prints a std::string or std::wstring to the output stream.
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param text The text to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::basic_string<TChar, TTraits>& item);
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, const std::basic_string<TChar, TTraits> &text);
|
||||
|
||||
// std::string_view and std::wstring_view
|
||||
/// @brief This function prints a std::string_view or std::wstring_view to the output stream.
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param text The text to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::basic_string_view<TChar, TTraits>& item);
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, const std::basic_string_view<TChar, TTraits> &text);
|
||||
|
||||
// std::tuple
|
||||
/// @brief This function prints a std::tuple to the output stream.
|
||||
///
|
||||
/// The output format for an empty tuple is "[]". For a tuple of (1, "two", 3.0) the output format is "[ 1, "two", 3.0
|
||||
/// ]".
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @tparam ...TArgs The types of the tuple.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param tuple The tuple to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::tuple<TArgs...>& tuple);
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, const std::tuple<TArgs...> &tuple);
|
||||
|
||||
// Containers (anything with a begin and end iterator)
|
||||
/// @brief This function prints any stl-like container to the output stream.
|
||||
///
|
||||
/// It works with any class that has begin and end methods that return iterators.
|
||||
///
|
||||
/// The output format for an empty container is "[]". For a (vector<int>){1, 2, 3} the output format is "[ 1, 2, 3 ]".
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @tparam TContainer The type of the container to print.
|
||||
/// @tparam Ignore this parameter it has a default value.
|
||||
/// @tparam Ignore this parameter it has a default value.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param container The container to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits, typename TContainer, typename, typename>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, TContainer container);
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, TContainer container);
|
||||
|
||||
// Initializer Lists
|
||||
/// @brief This function prints an initializer list to the output stream.
|
||||
///
|
||||
/// The output format for a list {"hello", "world"} is "[ "hello", "world" ]". Unfortunately empty initializer lists are
|
||||
/// treated as null pointers and will either print "null" or however your platform prints pointers.
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @tparam TItem The type of the item in the initializer list.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param list The initializer_list to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits, typename TItem>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::initializer_list<TItem> container);
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, std::initializer_list<TItem> list);
|
||||
|
||||
// queues
|
||||
/// @brief This function prints STL queues to the output stream.
|
||||
///
|
||||
/// The output format for an empty queue is "[]". The output format for a queue of 5,1,3 is "[ 5, 1, 3 ]".
|
||||
///
|
||||
/// The queue is copied and the copy is emptied.
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @tparam TItem The type of the item in the initializer list.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param queue The queue to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits, typename TItem>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::queue<TItem> queue);
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, std::queue<TItem> queue);
|
||||
|
||||
// pairs
|
||||
/// @brief This function prints STL pairs to the output stream.
|
||||
///
|
||||
/// The output format for a pair of (3, "Kansas") is "(3, "Kansas")".
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @tparam TFirst The type of the first item in the pair.
|
||||
/// @tparam TSecond The type of the second item in the pair.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param value The pair to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits, typename TFirst, typename TSecond>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::pair<TFirst, TSecond> value);
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, std::pair<TFirst, TSecond> value);
|
||||
|
||||
// Catch-all for everything else. Just print it and hope that works.
|
||||
/// @brief This function prints other items. It just pipes the item to the output stream.
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @tparam TItem The type of the item to print.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param item The item to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar,
|
||||
typename TTraits,
|
||||
typename TItem,
|
||||
typename std::enable_if<!is_container<TItem>::value>::type* = nullptr>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, TItem item);
|
||||
typename std::enable_if<!is_container<TItem>::value>::type * = nullptr>
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, TItem item);
|
||||
/// @}
|
||||
|
||||
// Prints varargs with a const char* or const wchar_t* separator between each pair.
|
||||
/// @name Pretty Print with Separator
|
||||
/// These functions pretty print items with a separator.
|
||||
/// @{
|
||||
|
||||
/// @brief This function prints varargs with a const char* or const wchar_t* separator between each pair.
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @tparam ...Args The types of the arguments to print.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param separator The separator to use between the items.
|
||||
/// @param ...args The items to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits, typename... Args>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os, const TChar* separator, Args&&... args);
|
||||
auto &PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits> &os, const TChar *separator, Args &&...args);
|
||||
|
||||
// Prints varargs with a std::string or std::wstring separator.
|
||||
/// @brief This function prints varargs with a std::string or std::wstring separator between each pair.
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @tparam ...Args The types of the arguments to print.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param separator The separator to use between the items.
|
||||
/// @param ...args The items to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os,
|
||||
auto &PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits> &os,
|
||||
std::basic_string<TChar, TTraits> separator,
|
||||
TArgs&&... args);
|
||||
TArgs &&...args);
|
||||
|
||||
// Prints varargs with a std::string_view or std::wstring_view separator.
|
||||
/// @brief This function prints varargs with a std::string_view or std::wstring_view separator between each pair.
|
||||
/// @tparam TChar The character type of our stream.
|
||||
/// @tparam TTraits The character_traits type of our stream.
|
||||
/// @tparam ...Args The types of the arguments to print.
|
||||
/// @param os The output stream to write to.
|
||||
/// @param separator The separator to use between the items.
|
||||
/// @param ...args The items to print.
|
||||
/// @return The output stream for chaining.
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os,
|
||||
auto &PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits> &os,
|
||||
std::basic_string_view<TChar, TTraits> separator,
|
||||
TArgs&&... args);
|
||||
TArgs &&...args);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Actual implementations
|
||||
/// @}
|
||||
|
||||
// const char*
|
||||
template <typename TChar>
|
||||
std::basic_string<TChar> EscapeForPrinting(const TChar* text) {
|
||||
// const char* and const wchar_t*
|
||||
template <typename TChar> std::basic_string<TChar> EscapeForPrinting(const TChar *text) {
|
||||
std::regex regex = std::regex(StringTraits<TChar>::Literal("\033", L"\033"));
|
||||
const TChar* replace = StringTraits<TChar>::Literal("\\033", L"\\033");
|
||||
const TChar *replace = StringTraits<TChar>::Literal("\\033", L"\\033");
|
||||
return std::regex_replace(text, regex, replace);
|
||||
}
|
||||
|
||||
// std::string
|
||||
// std::string and std::wstring
|
||||
template <typename TChar, typename TTraits>
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string<TChar, TTraits>& text) {
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string<TChar, TTraits> &text) {
|
||||
std::regex regex = std::regex(StringTraits<TChar>::Literal("\033", L"\033"));
|
||||
std::basic_string<TChar, TTraits> replace = StringTraits<TChar>::Literal("\\033", L"\\033");
|
||||
return std::regex_replace(text, regex, replace);
|
||||
}
|
||||
|
||||
// std::string_view
|
||||
// std::string_view and std::wstring_view
|
||||
template <typename TChar, typename TTraits>
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string_view<TChar, TTraits>& text) {
|
||||
std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string_view<TChar, TTraits> &text) {
|
||||
std::basic_string<TChar, TTraits> text_as_string = std::basic_string<TChar, TTraits>(text);
|
||||
std::regex regex = std::regex(StringTraits<TChar>::Literal("\033", L"\033"));
|
||||
std::basic_string<TChar, TTraits> replace = StringTraits<TChar>::Literal("\\033", L"\\033");
|
||||
@@ -176,7 +301,7 @@ std::basic_string<TChar, TTraits> EscapeForPrinting(const std::basic_string_view
|
||||
|
||||
// pointers
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const void* pointer) {
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, const void *pointer) {
|
||||
if (pointer == nullptr) {
|
||||
os << StringTraits<TChar>::Literal("null", L"null");
|
||||
} else {
|
||||
@@ -185,35 +310,35 @@ auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const void* pointer) {
|
||||
return os;
|
||||
}
|
||||
|
||||
// const char*.
|
||||
// const char* and const wchar_t*
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const TChar* item) {
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, const TChar *item) {
|
||||
os << StringTraits<TChar>::Literal("\"", L"\"") << EscapeForPrinting(item)
|
||||
<< StringTraits<TChar>::Literal("\"", L"\"");
|
||||
return os;
|
||||
}
|
||||
|
||||
// std::string.
|
||||
// std::string and std::wstring
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::basic_string<TChar, TTraits>& item) {
|
||||
os << StringTraits<TChar>::Literal("\"", L"\"") << EscapeForPrinting(item)
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, const std::basic_string<TChar, TTraits> &text) {
|
||||
os << StringTraits<TChar>::Literal("\"", L"\"") << EscapeForPrinting(text)
|
||||
<< StringTraits<TChar>::Literal("\"", L"\"");
|
||||
return os;
|
||||
}
|
||||
|
||||
// std::string_view.
|
||||
// std::string_view and std::wstring_view
|
||||
template <typename TChar, typename TTraits>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::basic_string_view<TChar, TTraits>& item) {
|
||||
os << StringTraits<TChar>::Literal("\"", L"\"") << EscapeForPrinting(item)
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, const std::basic_string_view<TChar, TTraits> &text) {
|
||||
os << StringTraits<TChar>::Literal("\"", L"\"") << EscapeForPrinting(text)
|
||||
<< StringTraits<TChar>::Literal("\"", L"\"");
|
||||
return os;
|
||||
}
|
||||
|
||||
// std::tuple
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::tuple<TArgs...>& tuple) {
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, const std::tuple<TArgs...> &tuple) {
|
||||
std::apply(
|
||||
[&os](auto&&... args) {
|
||||
[&os](auto &&...args) {
|
||||
if (sizeof...(TArgs) == 0) {
|
||||
os << StringTraits<TChar>::Literal("[]", L"[]]");
|
||||
return;
|
||||
@@ -229,14 +354,14 @@ auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, const std::tuple<TArgs
|
||||
return os;
|
||||
}
|
||||
|
||||
// Containers
|
||||
// STL containers
|
||||
template <typename TChar,
|
||||
typename TTraits,
|
||||
typename TContainer,
|
||||
typename = decltype(std::begin(std::declval<TContainer>())),
|
||||
typename = decltype(std::end(std::declval<TContainer>())),
|
||||
typename = typename TContainer::value_type>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, TContainer container) {
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, TContainer container) {
|
||||
if (container.size() <= 0) {
|
||||
os << StringTraits<TChar>::Literal("[]", L"[]");
|
||||
} else {
|
||||
@@ -252,16 +377,16 @@ auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, TContainer container)
|
||||
return os;
|
||||
}
|
||||
|
||||
// initializer_lists
|
||||
// std::initializer_list
|
||||
template <typename TChar, typename TTraits, typename TItem>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::initializer_list<TItem> container) {
|
||||
if (container.size() <= 0) {
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, std::initializer_list<TItem> list) {
|
||||
if (list.size() <= 0) {
|
||||
os << StringTraits<TChar>::Literal("[]", L"[]");
|
||||
return os;
|
||||
}
|
||||
os << StringTraits<TChar>::Literal("[ ", L"[ ");
|
||||
for (auto it = std::begin(container); it != std::end(container); it++) {
|
||||
if (it != std::begin(container)) {
|
||||
for (auto it = std::begin(list); it != std::end(list); it++) {
|
||||
if (it != std::begin(list)) {
|
||||
os << StringTraits<TChar>::Literal(", ", L", ");
|
||||
}
|
||||
PrettyPrint(os, *it);
|
||||
@@ -270,9 +395,9 @@ auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::initializer_list<
|
||||
return os;
|
||||
}
|
||||
|
||||
// queues
|
||||
// std::queue
|
||||
template <typename TChar, typename TTraits, typename TItem>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::queue<TItem> queue) {
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, std::queue<TItem> queue) {
|
||||
if (queue.empty()) {
|
||||
os << StringTraits<TChar>::Literal("[]", L"[]");
|
||||
return os;
|
||||
@@ -289,9 +414,9 @@ auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::queue<TItem> queu
|
||||
return os;
|
||||
}
|
||||
|
||||
// pairs
|
||||
// std::pair
|
||||
template <typename TChar, typename TTraits, typename TFirst, typename TSecond>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::pair<TFirst, TSecond> value) {
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, std::pair<TFirst, TSecond> value) {
|
||||
os << StringTraits<TChar>::Literal("(", L"(");
|
||||
PrettyPrint(os, value.first);
|
||||
os << StringTraits<TChar>::Literal(", ", L", ");
|
||||
@@ -301,15 +426,18 @@ auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, std::pair<TFirst, TSec
|
||||
}
|
||||
|
||||
// Catch-all for everything else.
|
||||
template <typename TChar, typename TTraits, typename TItem, typename std::enable_if<!is_container<TItem>::value>::type*>
|
||||
auto& PrettyPrint(std::basic_ostream<TChar, TTraits>& os, TItem item) {
|
||||
template <typename TChar,
|
||||
typename TTraits,
|
||||
typename TItem,
|
||||
typename std::enable_if<!is_container<TItem>::value>::type *>
|
||||
auto &PrettyPrint(std::basic_ostream<TChar, TTraits> &os, TItem item) {
|
||||
os << item;
|
||||
return os;
|
||||
}
|
||||
|
||||
// Prints args with separator between them. const char* separator.
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os, const TChar* separator, TArgs&&... args) {
|
||||
auto &PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits> &os, const TChar *separator, TArgs &&...args) {
|
||||
if (sizeof...(TArgs) == 0) {
|
||||
os << StringTraits<TChar>::Literal("", L"");
|
||||
return os;
|
||||
@@ -321,9 +449,9 @@ auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os, const TCh
|
||||
|
||||
// Prints args with separator between them. std::string separator.
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os,
|
||||
auto &PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits> &os,
|
||||
std::basic_string<TChar, TTraits> separator,
|
||||
TArgs&&... args) {
|
||||
TArgs &&...args) {
|
||||
if (sizeof...(TArgs) == 0) {
|
||||
os << StringTraits<TChar>::Literal("", L"");
|
||||
return os;
|
||||
@@ -335,9 +463,9 @@ auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os,
|
||||
|
||||
// Prints args with separator between them. std::string_view separator.
|
||||
template <typename TChar, typename TTraits, typename... TArgs>
|
||||
auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os,
|
||||
auto &PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits> &os,
|
||||
std::basic_string_view<TChar, TTraits> separator,
|
||||
TArgs&&... args) {
|
||||
TArgs &&...args) {
|
||||
if (sizeof...(TArgs) == 0) {
|
||||
os << StringTraits<TChar>::Literal("", L"");
|
||||
return os;
|
||||
@@ -347,7 +475,7 @@ auto& PrettyPrintWithSeparator(std::basic_ostream<TChar, TTraits>& os,
|
||||
return os;
|
||||
}
|
||||
|
||||
} // End namespace CPPUtils
|
||||
/// @}
|
||||
} // End namespace CPPUtils
|
||||
|
||||
/** @}*/
|
||||
#endif // End !defined CPP_UTILS_pretty_print_h__
|
||||
#endif // End !defined CPPUtils__pretty_print_h__
|
||||
|
||||
Reference in New Issue
Block a user