From fbfe4772e04c2294a32bcec6341c96a2d6a05097 Mon Sep 17 00:00:00 2001 From: Tom Hicks Date: Sat, 6 May 2023 10:54:54 -0700 Subject: [PATCH] Adds PrettyPrint, PrettyPrintWithSeparator and EscapeForPrinting. --- BUILD | 15 ++ pretty_print.cpp | 13 ++ pretty_print.h | 331 ++++++++++++++++++++++++++++++++ pretty_print_test.cpp | 427 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 786 insertions(+) create mode 100644 pretty_print.cpp create mode 100644 pretty_print.h create mode 100644 pretty_print_test.cpp diff --git a/BUILD b/BUILD index c33c3e5..f23c256 100644 --- a/BUILD +++ b/BUILD @@ -20,3 +20,18 @@ cc_test( ], ) +cc_library( + name = "pretty_print", + srcs = ["pretty_print.cpp"], + hdrs = ["pretty_print.h"], + includes = ["pretty_print.h"], +) + +cc_test( + name = "pretty_print_test", + srcs = ["pretty_print_test.cpp"], + deps = [ + ":pretty_print", + "@tinytest", + ], +) diff --git a/pretty_print.cpp b/pretty_print.cpp new file mode 100644 index 0000000..b8ef9e8 --- /dev/null +++ b/pretty_print.cpp @@ -0,0 +1,13 @@ +/*************************************************************************************** + * @file pretty_print.cpp * + * * + * @brief Defines functions for printing objects in a frendlier manner. * + * @copyright * + * Copyright 2023 Tom Hicks * + * Licensed under the MIT license see the LICENSE file for details. * + ***************************************************************************************/ +#include "pretty_print.h" + +namespace CPPUtils { +// Nothing here. +} // namespace CPPUtils diff --git a/pretty_print.h b/pretty_print.h new file mode 100644 index 0000000..7fc74bb --- /dev/null +++ b/pretty_print.h @@ -0,0 +1,331 @@ +#ifndef CPP_UTILS_pretty_print_h__ +#define CPP_UTILS_pretty_print_h__ +/*************************************************************************************** + * @file pretty_print.cpp * + * * + * @brief Defines functions for printing objects in a frendlier manner. * + * @copyright * + * Copyright 2023 Tom Hicks * + * Licensed under the MIT license see the LICENSE file for details. * + ***************************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +/** \addtogroup Pretty Print + * @{ + */ +namespace CPPUtils { +//////////////////////////////////////////////////////////////////////////////// +// Helper templates - These are not directly tested. +template +struct StringTraits; + +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; } +}; + +template +struct is_container { + template + static constexpr bool test(decltype(std::begin(std::declval()))*) { + return true; + } + + 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); + +// std::string and std::wstring +template +std::basic_string EscapeForPrinting(const std::basic_string& text); + +// std::string_view and std::wstring_view +template +std::basic_string EscapeForPrinting(const std::basic_string_view& text); + +// pointers +template +auto& PrettyPrint(std::basic_ostream& os, const void* pointer); + +// const char* and const wchar_t* +template +auto& PrettyPrint(std::basic_ostream& os, const TChar* item); + +// std::string and std::wstring +template +auto& PrettyPrint(std::basic_ostream& os, const std::basic_string& item); + +// std::string_view and std::wstring_view +template +auto& PrettyPrint(std::basic_ostream& os, const std::basic_string_view& item); + +// std::tuple +template +auto& PrettyPrint(std::basic_ostream& os, const std::tuple& tuple); + +// Containers (anything with a begin and end iterator) +template +auto& PrettyPrint(std::basic_ostream& os, TContainer container); + +// Initializer Lists +template +auto& PrettyPrint(std::basic_ostream& os, std::initializer_list container); + +// queues +template +auto& PrettyPrint(std::basic_ostream& os, std::queue queue); + +// pairs +template +auto& PrettyPrint(std::basic_ostream& os, std::pair value); + +// Catch-all for everything else. Just print it and hope that works. +template ::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. +template +auto& PrettyPrintWithSeparator(std::basic_ostream& os, const TChar* separator, Args&&... args); + +// Prints varargs with a std::string or std::wstring separator. +template +auto& PrettyPrintWithSeparator(std::basic_ostream& os, + std::basic_string separator, + TArgs&&... args); + +// Prints varargs with a std::string_view or std::wstring_view separator. +template +auto& PrettyPrintWithSeparator(std::basic_ostream& os, + std::basic_string_view separator, + TArgs&&... args); + +//////////////////////////////////////////////////////////////////////////////// +// Actual implementations + +// const char* +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"); + return std::regex_replace(text, regex, replace); +} + +// std::string +template +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 +template +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"); + return std::regex_replace(text_as_string, regex, replace); +} + +// pointers +template +auto& PrettyPrint(std::basic_ostream& os, const void* pointer) { + if (pointer == nullptr) { + os << StringTraits::Literal("null", L"null"); + } else { + os << pointer; + } + return os; +} + +// const char*. +template +auto& PrettyPrint(std::basic_ostream& os, const TChar* item) { + os << StringTraits::Literal("\"", L"\"") << EscapeForPrinting(item) + << StringTraits::Literal("\"", L"\""); + return os; +} + +// std::string. +template +auto& PrettyPrint(std::basic_ostream& os, const std::basic_string& item) { + os << StringTraits::Literal("\"", L"\"") << EscapeForPrinting(item) + << StringTraits::Literal("\"", L"\""); + return os; +} + +// std::string_view. +template +auto& PrettyPrint(std::basic_ostream& os, const std::basic_string_view& item) { + os << StringTraits::Literal("\"", L"\"") << EscapeForPrinting(item) + << StringTraits::Literal("\"", L"\""); + return os; +} + +// std::tuple +template +auto& PrettyPrint(std::basic_ostream& os, const std::tuple& tuple) { + std::apply( + [&os](auto&&... args) { + if (sizeof...(TArgs) == 0) { + os << StringTraits::Literal("[]", L"[]]"); + return; + } + size_t n = 0; + os << StringTraits::Literal("[ ", L"[ "); + ((PrettyPrint(os, args) << (++n != sizeof...(TArgs) ? StringTraits::Literal(", ", L", ") + : StringTraits::Literal("", L""))), + ...); + os << StringTraits::Literal(" ]", L" ]"); + }, + tuple); + return os; +} + +// Containers +template ())), + typename = decltype(std::end(std::declval())), + typename = typename TContainer::value_type> +auto& PrettyPrint(std::basic_ostream& os, TContainer container) { + if (container.size() <= 0) { + os << StringTraits::Literal("[]", L"[]"); + } else { + os << StringTraits::Literal("[ ", L"[ "); + for (auto it = std::begin(container); it != std::end(container); it++) { + if (it != std::begin(container)) { + os << StringTraits::Literal(", ", L", "); + } + PrettyPrint(os, *it); + } + os << StringTraits::Literal(" ]", L" ]"); + } + return os; +} + +// initializer_lists +template +auto& PrettyPrint(std::basic_ostream& os, std::initializer_list container) { + if (container.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)) { + os << StringTraits::Literal(", ", L", "); + } + PrettyPrint(os, *it); + } + os << StringTraits::Literal(" ]", L" ]"); + return os; +} + +// queues +template +auto& PrettyPrint(std::basic_ostream& os, std::queue queue) { + if (queue.empty()) { + os << StringTraits::Literal("[]", L"[]"); + return os; + } + os << StringTraits::Literal("[ ", L"[ "); + PrettyPrint(os, queue.front()); + queue.pop(); + while (!queue.empty()) { + os << StringTraits::Literal(", ", L", "); + PrettyPrint(os, queue.front()); + queue.pop(); + } + os << StringTraits::Literal(" ]", L" ]"); + return os; +} + +// pairs +template +auto& PrettyPrint(std::basic_ostream& os, std::pair value) { + os << StringTraits::Literal("(", L"("); + PrettyPrint(os, value.first); + os << StringTraits::Literal(", ", L", "); + PrettyPrint(os, value.second); + os << StringTraits::Literal(")", L")"); + return os; +} + +// Catch-all for everything else. +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) { + if (sizeof...(TArgs) == 0) { + os << StringTraits::Literal("", L""); + return os; + } + size_t n = 0; + ((PrettyPrint(os, args) << (++n != sizeof...(TArgs) ? separator : StringTraits::Literal("", L""))), ...); + return os; +} + +// Prints args with separator between them. std::string separator. +template +auto& PrettyPrintWithSeparator(std::basic_ostream& os, + std::basic_string separator, + TArgs&&... args) { + if (sizeof...(TArgs) == 0) { + os << StringTraits::Literal("", L""); + return os; + } + size_t n = 0; + ((PrettyPrint(os, args) << (++n != sizeof...(TArgs) ? separator : StringTraits::Literal("", L""))), ...); + return os; +} + +// Prints args with separator between them. std::string_view separator. +template +auto& PrettyPrintWithSeparator(std::basic_ostream& os, + std::basic_string_view separator, + TArgs&&... args) { + if (sizeof...(TArgs) == 0) { + os << StringTraits::Literal("", L""); + return os; + } + size_t n = 0; + ((PrettyPrint(os, args) << (++n != sizeof...(TArgs) ? separator : StringTraits::Literal("", L""))), ...); + return os; +} + +} // End namespace CPPUtils + +/** @}*/ +#endif // End !defined CPP_UTILS_pretty_print_h__ diff --git a/pretty_print_test.cpp b/pretty_print_test.cpp new file mode 100644 index 0000000..3f97653 --- /dev/null +++ b/pretty_print_test.cpp @@ -0,0 +1,427 @@ +/*************************************************************************************** + * @file pretty_print_test.cpp * + * * + * @brief Defines tests for functions for printing objects in a frendlier manner. * + * @copyright * + * Copyright 2023 Tom Hicks * + * Licensed under the MIT license see the LICENSE file for details. * + ***************************************************************************************/ +// clang-format off +#include "pretty_print.h" +#include "tinytest.h" +// clang-format on +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { +using std::make_tuple; +using std::ostringstream; +using std::string; +using std::string_view; +using TinyTest::execute_suite; +using TinyTest::make_test; +using TinyTest::make_test_suite; +using TinyTest::TestResults; +using namespace CPPUtils; +using std::wstring; +} // End namespace + +TestResults test_EscapeForPrintingWithAConstCharPointer() { + TestResults results; + auto escape_const_char_pointer = [](const char* value) -> string { return EscapeForPrinting(value); }; + results += execute_suite(make_test_suite( + "CPPUtils::EscapeForPrinting(const char*)", + escape_const_char_pointer, + { + make_test("should escape an empty string", (string) "", make_tuple("")), + make_test("should esacpe a string with no special characters", + (string) "This is a normal string.", + make_tuple("This is a normal string.")), + make_test("should escape the escape character by itself", (string) "\\033", make_tuple("\033")), + make_test("should escape the escape character within a string", + (string) "This string has an \\033 in it.", + make_tuple("This string has an \033 in it.")), + })); + return results; +} + +TestResults test_EscapeForPrintingWithAString() { + TestResults results; + auto escape_string = [](const string& value) -> string { return EscapeForPrinting(value); }; + results += execute_suite(make_test_suite( + "CPPUtils::EscapeForPrinting(const std::string&)", + escape_string, + { + make_test("should escape an empty string", (string) "", make_tuple((string) "")), + make_test("should escape a string with no special characters", + (string) "This is a normal string.", + make_tuple((string) "This is a normal string.")), + make_test("should escape the escape character by itself", (string) "\\033", make_tuple((string) "\033")), + make_test("should escape the escape character within a string", + (string) "This string has an \\033 in it.", + make_tuple((string) "This string has an \033 in it.")), + })); + return results; +} + +TestResults test_EscapeForPrintingWithAStringView() { + auto escape_string_view = [](const string_view& value) -> string { return EscapeForPrinting(value); }; + return execute_suite(make_test_suite( + "CPPUtils::EscapeForPrinting(const std::string_view&)", + escape_string_view, + { + make_test("should escape an empty string", (string) "", make_tuple((string_view) "")), + make_test("should escape a string with no special characters", + (string) "This is a normal string.", + make_tuple((string_view) "This is a normal string.")), + make_test("should escape the escape character by itself", (string) "\\033", make_tuple((string_view) "\033")), + make_test("should escape the escape character within a string", + (string) "This string has an \\033 in it.", + make_tuple((string_view) "This string has an \033 in it.")), + })); +} + +TestResults test_PrettyPrintWithAConstCharPointer() { + auto pretty_print = [](const char* value) -> string { + ostringstream os; + PrettyPrint(os, value); + return os.str(); + }; + return execute_suite(make_test_suite( + "CPPUtils::PrettyPrint(std::ostream&, const char*)", + pretty_print, + { + make_test("should print \"\" for an empty string", (string) "\"\"", make_tuple("")), + make_test("should print \"hello world\"", (string) "\"hello world\"", make_tuple("hello world")), + })); +} + +TestResults test_PrettyPrintWithAString() { + auto pretty_print = [](const string& value) -> string { + ostringstream os; + PrettyPrint(os, value); + return os.str(); + }; + return execute_suite(make_test_suite( + "CPPUtils::PrettyPrint(std::ostream&, const std::string&)", + pretty_print, + { + make_test("should print \"\" for an empty string", (string) "\"\"", make_tuple((string) "")), + make_test("should print \"hello world\"", (string) "\"hello world\"", make_tuple((string) "hello world")), + })); +} + +TestResults test_PrettyPrintWithAStringView() { + auto pretty_print = [](const std::string_view& value) -> string { + ostringstream os; + PrettyPrint(os, value); + return os.str(); + }; + return execute_suite(make_test_suite( + "CPPUtils::PrettyPrint(std::ostream&, const std::string_view&)", + pretty_print, + { + make_test("should print \"\" for an empty string", (string) "\"\"", make_tuple((string_view) "")), + make_test( + "should print \"hello world\"", (string) "\"hello world\"", make_tuple((string_view) "hello world")), + })); +} + +TestResults test_PrettyPrintWithATuple() { + auto pretty_print = [](int i) -> string { + ostringstream os; + switch (i) { + case 1: + PrettyPrint(os, make_tuple(1, "hello", 9)); + break; + case 2: + PrettyPrint(os, make_tuple()); + break; + case 3: + PrettyPrint(os, make_tuple("one", "two", "three")); + break; + } + return os.str(); + }; + return execute_suite(make_test_suite( + "CPPUtils::PrettyPrint(std::ostream&, std::tuple)", + pretty_print, + { + make_test("should print a tuple of mixed types", (string) "[ 1, \"hello\", 9 ]", make_tuple(1)), + make_test("should print an empty tuple", (string) "[]", make_tuple(2)), + make_test("should print a tuple of strings", (string) "[ \"one\", \"two\", \"three\" ]", make_tuple(3)), + })); +} + +TestResults test_PrettyPrintWithAnInitializerList() { + auto pretty_print = [](int i) { + ostringstream os; + switch (i) { + case 1: + PrettyPrint(os, {"one", "two", "three"}); + break; + case 2: + PrettyPrint(os, (std::initializer_list){}); + break; + case 3: + PrettyPrint(os, {1, 2, 3}); + break; + case 4: + PrettyPrint(os, {"one", "two", "three", "four"}); + break; + case 5: + PrettyPrint(os, {1.1, 2.2, 3.3}); + break; + } + return os.str(); + }; + + return execute_suite(make_test_suite( + "CPPUtils::PrettyPrint(std::ostream&, std::initializer_list)", + pretty_print, + { + make_test( + "should print an initializer_list of strings", (string) "[ \"one\", \"two\", \"three\" ]", make_tuple(1)), + make_test("should print an empty initializer_list", (string) "[]", make_tuple(2)), + make_test("should print an initializer_list of integers", (string) "[ 1, 2, 3 ]", make_tuple(3)), + make_test("should print an initializer_list of strings with four elements", + (string) "[ \"one\", \"two\", \"three\", \"four\" ]", + make_tuple(4)), + make_test("should print an initializer_list of doubles", (string) "[ 1.1, 2.2, 3.3 ]", make_tuple(5)), + })); +} + +TestResults test_PrettyPrintWithDifferentContainerTypes() { + auto pretty_print = [](int i) { + ostringstream os; + switch (i) { + case 1: { + std::vector v = {1, 2, 3}; + PrettyPrint(os, v); + break; + } + case 2: { + std::queue q; + q.push(1); + q.push(2); + q.push(3); + PrettyPrint(os, q); + break; + } + case 3: { + std::vector v = {"one", "two", "three"}; + PrettyPrint(os, v); + break; + } + case 4: { + std::queue q; + q.push("one"); + q.push("two"); + q.push("three"); + PrettyPrint(os, q); + break; + } + } + return os.str(); + }; + + return execute_suite(make_test_suite( + "CPPUtils::PrettyPrint(std::ostream&, TContainer)", + pretty_print, + { + make_test("should print a vector of integers", (string) "[ 1, 2, 3 ]", make_tuple(1)), + make_test("should print a queue of integers", (string) "[ 1, 2, 3 ]", make_tuple(2)), + make_test("should print a vector of strings", (string) "[ \"one\", \"two\", \"three\" ]", make_tuple(3)), + make_test("should print a queue of strings", (string) "[ \"one\", \"two\", \"three\" ]", make_tuple(4)), + })); +} + +TestResults test_PrettyPrintWithSimpleTypes() { + TestResults results; + + auto pretty_print_int = [](int value) -> string { + ostringstream os; + PrettyPrint(os, value); + return os.str(); + }; + results += execute_suite(make_test_suite("CPPUtils::PrettyPrint(std::ostream&, const TItem&)", + pretty_print_int, + { + make_test("should print 42 for an int", (string) "42", make_tuple(42)), + })); + + auto pretty_print_float = [](float value) -> string { + ostringstream os; + PrettyPrint(os, value); + return os.str(); + }; + results += + execute_suite(make_test_suite("CPPUtils::PrettyPrint(std::ostream&, const TItem&)", + pretty_print_float, + { + make_test("should print 3.14 for a float", (string) "3.14", make_tuple(3.14f)), + })); + + auto pretty_print_string = [](const string& value) -> string { + ostringstream os; + PrettyPrint(os, value); + return os.str(); + }; + results += execute_suite(make_test_suite("CPPUtils::PrettyPrint(std::ostream&, const TItem&)", + pretty_print_string, + { + make_test("should print \"hello world\" for a string", + (string) "\"hello world\"", + make_tuple((string) "hello world")), + })); + return results; +} + +TestResults test_PrettyPrintWithAPair() { + auto pretty_print = [](int id) -> string { + ostringstream os; + switch (id) { + case 1: + PrettyPrint(os, std::make_pair(1, 2)); + break; + case 2: + PrettyPrint(os, std::make_pair(3.14f, 42)); + break; + case 3: + PrettyPrint(os, std::make_pair((string) "hello", (string) "world")); + break; + } + return os.str(); + }; + return execute_suite(make_test_suite( + "CPPUtils::PrettyPrint(std::ostream&, const std::pair&)", + pretty_print, + { + make_test("should print (1, 2) for a pair of ints", (string) "(1, 2)", make_tuple(1)), + make_test("should print (3.14, 42) for a pair of float and int", (string) "(3.14, 42)", make_tuple(2)), + make_test("should print (\"hello\", \"world\") for a pair of strings", + (string) "(\"hello\", \"world\")", + make_tuple(3)), + })); +} + +TestResults test_PrettyPrintWithSeparatorWithAConstCharPointer() { + auto pretty_print = [](const char* separator, int id) -> string { + ostringstream os; + switch (id) { + case 1: + PrettyPrintWithSeparator(os, separator, 1, 2, 3); + break; + case 2: + PrettyPrintWithSeparator(os, separator, 3.14f, 42, (string) "hello world"); + break; + case 3: + PrettyPrintWithSeparator(os, separator, (string) "hello", (string) "world"); + break; + } + return os.str(); + }; + return execute_suite( + make_test_suite("CPPUtils::PrettyPrintWithSeparator(std::ostream&, const TChar*, Args&&...)", + pretty_print, + { + make_test("should print 1, 2, 3 for a list of ints", (string) "1, 2, 3", make_tuple(", ", 1)), + make_test("should print 3.14; 42; \"hello world\" for a list of float, int and string", + (string) "3.14; 42; \"hello world\"", + make_tuple("; ", 2)), + make_test("should print \"hello\" \"world\" for a list of strings", + (string) "\"hello\" \"world\"", + make_tuple(" ", 3)), + })); +} + +TestResults test_PrettyPrintWithSeparatorWithAString() { + auto pretty_print = [](const string& separator, int id) -> string { + ostringstream os; + switch (id) { + case 1: + PrettyPrintWithSeparator(os, separator, 1, 2, 3); + break; + case 2: + PrettyPrintWithSeparator(os, separator, 3.14f, 42, (string) "hello world"); + break; + case 3: + PrettyPrintWithSeparator(os, separator, (string) "hello", (string) "world"); + break; + } + return os.str(); + }; + return execute_suite(make_test_suite( + "CPPUtils::PrettyPrintWithSeparator(std::ostream&, const TChar*, Args&&...)", + pretty_print, + { + make_test("should print 1 | 2 | 3 for a list of ints", (string) "1 | 2 | 3", make_tuple((string) " | ", 1)), + make_test("should print 3.14 / 42 / \"hello world\" for a list of float, int and string", + (string) "3.14 / 42 / \"hello world\"", + make_tuple((string) " / ", 2)), + make_test("should print \"hello\" - \"world\" for a list of strings", + (string) "\"hello\" - \"world\"", + make_tuple((string) " - ", 3)), + })); +} + +TestResults test_PrettyPrintWithSeparatorWithAStringView() { + auto pretty_print = [](const string_view& separator, int id) -> string { + ostringstream os; + switch (id) { + case 1: + PrettyPrintWithSeparator(os, separator, 1, 2, 3); + break; + case 2: + PrettyPrintWithSeparator(os, separator, 3.14f, 42, "hello world"); + break; + case 3: + PrettyPrintWithSeparator(os, separator, "hello", "world"); + break; + } + return os.str(); + }; + return execute_suite(make_test_suite( + "CPPUtils::PrettyPrintWithSeparator(std::ostream&, const TChar*, Args&&...)", + pretty_print, + { + make_test( + "should print 1 | 2 | 3 for a list of ints", (string) "1 | 2 | 3", make_tuple((string_view) " | ", 1)), + make_test("should print 3.14 / 42 / \"hello world\" for a list of float, int and string", + (string) "3.14 / 42 / \"hello world\"", + make_tuple((string_view) " / ", 2)), + make_test("should print \"hello\" - \"world\" for a list of strings", + (string) "\"hello\" - \"world\"", + make_tuple((string_view) " - ", 3)), + })); +} + +int main(int argc, char* argv[]) { + setlocale(LC_ALL, ""); + TestResults results; + + results += test_EscapeForPrintingWithAConstCharPointer(); + results += test_EscapeForPrintingWithAString(); + results += test_EscapeForPrintingWithAStringView(); + + results += test_PrettyPrintWithAConstCharPointer(); + results += test_PrettyPrintWithAString(); + results += test_PrettyPrintWithAStringView(); + results += test_PrettyPrintWithATuple(); + results += test_PrettyPrintWithAnInitializerList(); + results += test_PrettyPrintWithDifferentContainerTypes(); + results += test_PrettyPrintWithSimpleTypes(); + results += test_PrettyPrintWithAPair(); + + results += test_PrettyPrintWithSeparatorWithAConstCharPointer(); + results += test_PrettyPrintWithSeparatorWithAString(); + results += test_PrettyPrintWithSeparatorWithAStringView(); + + return results.failed() + results.errors(); +}