Adds doxygen comments.

This commit is contained in:
2023-05-09 22:34:39 -07:00
parent 6b1d1b2d2b
commit dbf2e04e2a
4 changed files with 862 additions and 317 deletions

View File

@@ -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__

View File

@@ -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
View File

@@ -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__)

View File

@@ -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__