diff --git a/ansi_escapes.h b/ansi_escapes.h index ff587b5..8eb8d18 100644 --- a/ansi_escapes.h +++ b/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 * - * * - * Licensed under the MIT license see below for details. * - * * - * MIT License * - * * - * Copyright (c) 2023 Tom Hicks * - * * - * 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 + * + * 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 + * + * 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 #include #include -/** \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 -auto& Escape(std::basic_ostream& os, const std::basic_string& 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 -auto& Escape(std::basic_ostream& os, const std::basic_string_view& escape_code) { - return os << "\033[" << escape_code << "m"; +auto &Escape(std::basic_ostream &os, const std::basic_string &escape_code) { + return os << StringTraits::Literal("\033[", L"\033[") << escape_code + << StringTraits::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 -auto& Escape(std::basic_ostream& os, const TChar* escape_code) { - return os << "\033[" << escape_code << "m"; +auto &Escape(std::basic_ostream &os, const std::basic_string_view &escape_code) { + return os << StringTraits::Literal("\033[", L"\033[") << escape_code + << StringTraits::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 -auto& ForegroundColor8Bit(std::basic_ostream& os, uint8_t color) { - return Escape(os, "38;5;" + std::to_string(color)); +auto &Escape(std::basic_ostream &os, const TChar *escape_code) { + return os << StringTraits::Literal("\033[", L"\033[") << escape_code + << StringTraits::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 -auto& BackgroundColor8Bit(std::basic_ostream& os, uint8_t color) { - return Escape(os, "48;5;" + std::to_string(color)); +auto &ForegroundColor8Bit(std::basic_ostream &os, uint8_t color) { + return Escape(os, + StringTraits::Literal("38;5;", L"38;5;") + + StringTraits::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 -auto& ForegroundTrueColor(std::basic_ostream& 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 &os, uint8_t color) { + return Escape(os, + StringTraits::Literal("48;5;", L"48;5;") + + StringTraits::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 -auto& ForegroundTrueColor(std::basic_ostream& os, uint32_t color) { +auto &ForegroundTrueColor(std::basic_ostream &os, uint8_t red, uint8_t green, uint8_t blue) { + std::basic_ostringstream str; + str << StringTraits::Literal("38;2;", L"38;2;") << (uint16_t)red << StringTraits::Literal(";", L";") + << (uint16_t)green << StringTraits::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 +auto &ForegroundTrueColor(std::basic_ostream &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 -auto& BackgroundTrueColor(std::basic_ostream& 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 &os, uint8_t red, uint8_t green, uint8_t blue) { + std::basic_ostringstream str; + str << StringTraits::Literal("48;2;", L"48;2;") << (uint16_t)red << StringTraits::Literal(";", L";") + << (uint16_t)green << StringTraits::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 -auto& BackgroundTrueColor(std::basic_ostream& os, uint32_t color) { +auto &BackgroundTrueColor(std::basic_ostream &os, uint32_t color) { return BackgroundTrueColor(os, GetRedComponent(color), GetGreenComponent(color), GetBlueComponent(color)); } -template -auto& Reset(std::basic_ostream& 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 auto &Reset(std::basic_ostream &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__ diff --git a/console_logger.h b/console_logger.h index c022abc..70155e3 100644 --- a/console_logger.h +++ b/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 * - * * - * Licensed under the MIT license see below for details. * - * * - * MIT License * - * * - * Copyright (c) 2023 Tom Hicks * - * * - * 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 + * + * Licensed under the MIT license see below for details. + * **********************************************************************************************************************/ -#ifndef CONSOLE_LOGGER_H__ -#define CONSOLE_LOGGER_H__ +/* + * MIT License + * + * Copyright (c) 2023 Tom Hicks + * + * 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 #include #include @@ -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 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__ diff --git a/logger.h b/logger.h index a50c11f..714ade6 100644 --- a/logger.h +++ b/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 * - * * - * Licensed under the MIT license see below for details. * - * * - * MIT License * - * * - * Copyright (c) 2023 Tom Hicks * - * * - * 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 + * + * Licensed under the MIT license. + * **********************************************************************************************************************/ -#ifndef CPPUtils__Logger_h__ -#define CPPUtils__Logger_h__ +/* + * MIT License + * + * Copyright (c) 2023 Tom Hicks + * + * 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 #include @@ -36,78 +40,303 @@ #include 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 GetShared(); - static std::shared_ptr GetUnique(); - virtual void AddDestination(std::shared_ptr 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 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 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 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> 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__) diff --git a/pretty_print.h b/pretty_print.h index 6154363..5bb965a 100644 --- a/pretty_print.h +++ b/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 * - * * - * Licensed under the MIT license see below for details. * - * * - * MIT License * - * * - * Copyright (c) 2023 Tom Hicks * - * * - * 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 + * + * 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 + * + * 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 #include #include @@ -38,136 +42,257 @@ #include #include -/** \addtogroup Pretty Print - * @{ - */ namespace CPPUtils { -//////////////////////////////////////////////////////////////////////////////// -// Helper templates - These are not directly tested. -template -struct StringTraits; +/// @addtogroup pretty_print Pretty Print +/// @{ -template <> -struct StringTraits { - 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 struct StringTraits; + +/// @brief This SFINAE struct is use to select a narrow string. +template <> struct StringTraits { + static constexpr const char *Literal(const char *narrow, const wchar_t *wide) { return narrow; } }; -template <> -struct StringTraits { - 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 { + static constexpr const wchar_t *Literal(const char *narrow, const wchar_t *wide) { return wide; } }; -template -struct is_container { - template - static constexpr bool test(decltype(std::begin(std::declval()))*) { - return true; - } +/// @brief This SFINAE struct is used to help select container like types. +/// @tparam T The potential container type. +template struct is_container { + template static constexpr bool test(decltype(std::begin(std::declval())) *) { return true; } - template - static constexpr bool test(...) { - return false; - } + template static constexpr bool test(...) { return false; } static constexpr bool value = test(nullptr); }; -//////////////////////////////////////////////////////////////////////////////// -// Forward Declarations +/// @} -// const char* and const wchar_t* -template -std::basic_string 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 std::basic_string 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 -std::basic_string EscapeForPrinting(const std::basic_string& text); +std::basic_string EscapeForPrinting(const std::basic_string &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 -std::basic_string EscapeForPrinting(const std::basic_string_view& text); +std::basic_string EscapeForPrinting(const std::basic_string_view &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 -auto& PrettyPrint(std::basic_ostream& os, const void* pointer); +auto &PrettyPrint(std::basic_ostream &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 -auto& PrettyPrint(std::basic_ostream& os, const TChar* item); +auto &PrettyPrint(std::basic_ostream &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 -auto& PrettyPrint(std::basic_ostream& os, const std::basic_string& item); +auto &PrettyPrint(std::basic_ostream &os, const std::basic_string &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 -auto& PrettyPrint(std::basic_ostream& os, const std::basic_string_view& item); +auto &PrettyPrint(std::basic_ostream &os, const std::basic_string_view &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 -auto& PrettyPrint(std::basic_ostream& os, const std::tuple& tuple); +auto &PrettyPrint(std::basic_ostream &os, const std::tuple &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){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 -auto& PrettyPrint(std::basic_ostream& os, TContainer container); +auto &PrettyPrint(std::basic_ostream &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 -auto& PrettyPrint(std::basic_ostream& os, std::initializer_list container); +auto &PrettyPrint(std::basic_ostream &os, std::initializer_list 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 -auto& PrettyPrint(std::basic_ostream& os, std::queue queue); +auto &PrettyPrint(std::basic_ostream &os, std::queue 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 -auto& PrettyPrint(std::basic_ostream& os, std::pair value); +auto &PrettyPrint(std::basic_ostream &os, std::pair 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 ::value>::type* = nullptr> -auto& PrettyPrint(std::basic_ostream& os, TItem item); + typename std::enable_if::value>::type * = nullptr> +auto &PrettyPrint(std::basic_ostream &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 -auto& PrettyPrintWithSeparator(std::basic_ostream& os, const TChar* separator, Args&&... args); +auto &PrettyPrintWithSeparator(std::basic_ostream &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 -auto& PrettyPrintWithSeparator(std::basic_ostream& os, +auto &PrettyPrintWithSeparator(std::basic_ostream &os, std::basic_string 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 -auto& PrettyPrintWithSeparator(std::basic_ostream& os, +auto &PrettyPrintWithSeparator(std::basic_ostream &os, std::basic_string_view separator, - TArgs&&... args); + TArgs &&...args); -//////////////////////////////////////////////////////////////////////////////// -// Actual implementations +/// @} -// const char* -template -std::basic_string EscapeForPrinting(const TChar* text) { +// const char* and const wchar_t* +template std::basic_string EscapeForPrinting(const TChar *text) { std::regex regex = std::regex(StringTraits::Literal("\033", L"\033")); - const TChar* replace = StringTraits::Literal("\\033", L"\\033"); + const TChar *replace = StringTraits::Literal("\\033", L"\\033"); return std::regex_replace(text, regex, replace); } -// std::string +// std::string and std::wstring template -std::basic_string EscapeForPrinting(const std::basic_string& text) { +std::basic_string EscapeForPrinting(const std::basic_string &text) { std::regex regex = std::regex(StringTraits::Literal("\033", L"\033")); std::basic_string replace = StringTraits::Literal("\\033", L"\\033"); return std::regex_replace(text, regex, replace); } -// std::string_view +// std::string_view and std::wstring_view template -std::basic_string EscapeForPrinting(const std::basic_string_view& text) { +std::basic_string EscapeForPrinting(const std::basic_string_view &text) { std::basic_string text_as_string = std::basic_string(text); std::regex regex = std::regex(StringTraits::Literal("\033", L"\033")); std::basic_string replace = StringTraits::Literal("\\033", L"\\033"); @@ -176,7 +301,7 @@ std::basic_string EscapeForPrinting(const std::basic_string_view // pointers template -auto& PrettyPrint(std::basic_ostream& os, const void* pointer) { +auto &PrettyPrint(std::basic_ostream &os, const void *pointer) { if (pointer == nullptr) { os << StringTraits::Literal("null", L"null"); } else { @@ -185,35 +310,35 @@ auto& PrettyPrint(std::basic_ostream& os, const void* pointer) { return os; } -// const char*. +// const char* and const wchar_t* template -auto& PrettyPrint(std::basic_ostream& os, const TChar* item) { +auto &PrettyPrint(std::basic_ostream &os, const TChar *item) { os << StringTraits::Literal("\"", L"\"") << EscapeForPrinting(item) << StringTraits::Literal("\"", L"\""); return os; } -// std::string. +// std::string and std::wstring template -auto& PrettyPrint(std::basic_ostream& os, const std::basic_string& item) { - os << StringTraits::Literal("\"", L"\"") << EscapeForPrinting(item) +auto &PrettyPrint(std::basic_ostream &os, const std::basic_string &text) { + os << StringTraits::Literal("\"", L"\"") << EscapeForPrinting(text) << StringTraits::Literal("\"", L"\""); return os; } -// std::string_view. +// std::string_view and std::wstring_view template -auto& PrettyPrint(std::basic_ostream& os, const std::basic_string_view& item) { - os << StringTraits::Literal("\"", L"\"") << EscapeForPrinting(item) +auto &PrettyPrint(std::basic_ostream &os, const std::basic_string_view &text) { + os << StringTraits::Literal("\"", L"\"") << EscapeForPrinting(text) << StringTraits::Literal("\"", L"\""); return os; } // std::tuple template -auto& PrettyPrint(std::basic_ostream& os, const std::tuple& tuple) { +auto &PrettyPrint(std::basic_ostream &os, const std::tuple &tuple) { std::apply( - [&os](auto&&... args) { + [&os](auto &&...args) { if (sizeof...(TArgs) == 0) { os << StringTraits::Literal("[]", L"[]]"); return; @@ -229,14 +354,14 @@ auto& PrettyPrint(std::basic_ostream& os, const std::tuple())), typename = decltype(std::end(std::declval())), typename = typename TContainer::value_type> -auto& PrettyPrint(std::basic_ostream& os, TContainer container) { +auto &PrettyPrint(std::basic_ostream &os, TContainer container) { if (container.size() <= 0) { os << StringTraits::Literal("[]", L"[]"); } else { @@ -252,16 +377,16 @@ auto& PrettyPrint(std::basic_ostream& os, TContainer container) return os; } -// initializer_lists +// std::initializer_list template -auto& PrettyPrint(std::basic_ostream& os, std::initializer_list container) { - if (container.size() <= 0) { +auto &PrettyPrint(std::basic_ostream &os, std::initializer_list list) { + if (list.size() <= 0) { os << StringTraits::Literal("[]", L"[]"); return os; } os << StringTraits::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::Literal(", ", L", "); } PrettyPrint(os, *it); @@ -270,9 +395,9 @@ auto& PrettyPrint(std::basic_ostream& os, std::initializer_list< return os; } -// queues +// std::queue template -auto& PrettyPrint(std::basic_ostream& os, std::queue queue) { +auto &PrettyPrint(std::basic_ostream &os, std::queue queue) { if (queue.empty()) { os << StringTraits::Literal("[]", L"[]"); return os; @@ -289,9 +414,9 @@ auto& PrettyPrint(std::basic_ostream& os, std::queue queu return os; } -// pairs +// std::pair template -auto& PrettyPrint(std::basic_ostream& os, std::pair value) { +auto &PrettyPrint(std::basic_ostream &os, std::pair value) { os << StringTraits::Literal("(", L"("); PrettyPrint(os, value.first); os << StringTraits::Literal(", ", L", "); @@ -301,15 +426,18 @@ auto& PrettyPrint(std::basic_ostream& os, std::pair::value>::type*> -auto& PrettyPrint(std::basic_ostream& os, TItem item) { +template ::value>::type *> +auto &PrettyPrint(std::basic_ostream &os, TItem item) { os << item; return os; } // Prints args with separator between them. const char* separator. template -auto& PrettyPrintWithSeparator(std::basic_ostream& os, const TChar* separator, TArgs&&... args) { +auto &PrettyPrintWithSeparator(std::basic_ostream &os, const TChar *separator, TArgs &&...args) { if (sizeof...(TArgs) == 0) { os << StringTraits::Literal("", L""); return os; @@ -321,9 +449,9 @@ auto& PrettyPrintWithSeparator(std::basic_ostream& os, const TCh // Prints args with separator between them. std::string separator. template -auto& PrettyPrintWithSeparator(std::basic_ostream& os, +auto &PrettyPrintWithSeparator(std::basic_ostream &os, std::basic_string separator, - TArgs&&... args) { + TArgs &&...args) { if (sizeof...(TArgs) == 0) { os << StringTraits::Literal("", L""); return os; @@ -335,9 +463,9 @@ auto& PrettyPrintWithSeparator(std::basic_ostream& os, // Prints args with separator between them. std::string_view separator. template -auto& PrettyPrintWithSeparator(std::basic_ostream& os, +auto &PrettyPrintWithSeparator(std::basic_ostream &os, std::basic_string_view separator, - TArgs&&... args) { + TArgs &&...args) { if (sizeof...(TArgs) == 0) { os << StringTraits::Literal("", L""); return os; @@ -347,7 +475,7 @@ auto& PrettyPrintWithSeparator(std::basic_ostream& os, return os; } -} // End namespace CPPUtils +/// @} +} // End namespace CPPUtils -/** @}*/ -#endif // End !defined CPP_UTILS_pretty_print_h__ +#endif // End !defined CPPUtils__pretty_print_h__