From 043280e6f915c0473670358bcb18113aa3f46c50 Mon Sep 17 00:00:00 2001 From: BrandonPacewic <92102436+BrandonPacewic@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:40:02 -0700 Subject: [PATCH] feat(cont): refactor container components --- cpl/inc/container.h | 89 ++++++++++++++++ cpl/inc/stdoutput.h | 108 -------------------- tests/cpl/container_debug_output/test.cpp | 68 ++++++++++++ tests/cpl/include_stdoutput_header/test.cpp | 8 -- 4 files changed, 157 insertions(+), 116 deletions(-) delete mode 100644 cpl/inc/stdoutput.h create mode 100644 tests/cpl/container_debug_output/test.cpp delete mode 100644 tests/cpl/include_stdoutput_header/test.cpp diff --git a/cpl/inc/container.h b/cpl/inc/container.h index 36ce3a6..9df9c98 100644 --- a/cpl/inc/container.h +++ b/cpl/inc/container.h @@ -11,11 +11,57 @@ #include #include #include +#include +#include #include +#include #include CPL_BEGIN +// ostream overloads for debugging output +template +std::ostream& operator<<(std::ostream& os, const std::pair& p) { + return os << '(' << p.first << ", " << p.second << ')'; +} + +template ::value, typename Cont::value_type>::type> +std::ostream& operator<<(std::ostream& os, const Cont& container) { + os << '{'; + auto it = container.begin(); + auto end = container.end(); + + if (it != end) { + os << *it; + ++it; + } + + for (; it != end; ++it) { + os << ", " << *it; + } + + return os << '}'; +} + +// macros for debugging output +#if DBG_MODE || CPL +template +void dbg_out() { + std::cerr << std::endl; +} + +template +void dbg_out(Head&& head, Tail&&... tail) { + std::cerr << ' ' << head; + dbg_out(std::forward(tail)...); +} + +#define test(...) std::cerr << "[" << #__VA_ARGS__ << "]:", dbg_out(__VA_ARGS__) +#else // ^^^ DBG_MODE || CPL ^^^ / vvv !DBG_MODE && !CPL +#define test(...) +#endif // DBG_MODE || CPL + template struct _Is_container_helper {}; @@ -33,6 +79,49 @@ constexpr bool is_container = _Is_container::value; #define CPL_IS_CONTAINER(T) static_assert(is_container, "Templated parameter is not a valid container.") +template +const void output_container(FwdIter first, FwdIter last, const bool& space = true, const bool& new_line = true) { + for (; first != last; ++first) { + std::cout << *first; + + if (space && first != last - 1) { + std::cout << ' '; + } + } + + std::cout << (new_line ? '\n' : ' '); +} + +template +const void output_container(const Cont& container, const bool& space = true, const bool& new_line = true) { +#if CPL + CPL_IS_CONTAINER(Cont); +#endif // CPL + output_container(container.begin(), container.end(), space, new_line); +} + +template +const void output_reverse_container( + FwdIter first, FwdIter last, const bool& space = true, const bool& new_line = true) { + for (; first != last; ++first) { + std::cout << *first; + + if (space && first != last - 1) { + std::cout << ' '; + } + } + + std::cout << (new_line ? '\n' : ' '); +} + +template +const void output_reverse_container(const Cont& container, const bool& space = true, const bool& new_line = true) { +#if CPL + CPL_IS_CONTAINER(Cont); +#endif // CPL + output_reverse_container(container.rbegin(), container.rend(), space, new_line); +} + template auto alternating_insertion(Args&&... args) { // 3-arg -> Treat arguments as containers, e.g. (input1, input2, output) diff --git a/cpl/inc/stdoutput.h b/cpl/inc/stdoutput.h deleted file mode 100644 index ff7b800..0000000 --- a/cpl/inc/stdoutput.h +++ /dev/null @@ -1,108 +0,0 @@ -// standard output library header - -// Copyright (c) Brandon Pacewic -// SPDX-License-Identifier: MIT - -#pragma once -#ifndef STD_OUTPUT_H_ -#define STD_OUTPUT_H_ -#include "xcore.h" - -#include - -#include "container.h" - -CPL_BEGIN - -template -const void output_container(FwdIter first, FwdIter last, const bool& space = true, const bool& new_line = true) { - for (; first != last; ++first) { - std::cout << *first; - - if (space && first != last - 1) { - std::cout << ' '; - } - } - - std::cout << (new_line ? '\n' : ' '); -} - -template -const void output_container(const Cont& container, const bool& space = true, const bool& new_line = true) { -#if CPL - CPL_IS_CONTAINER(Cont); -#endif // CPL - output_container(container.begin(), container.end(), space, new_line); -} - -template -const void output_reverse_container( - FwdIter first, FwdIter last, const bool& space = true, const bool& new_line = true) { - for (; first != last; ++first) { - std::cout << *first; - - if (space && first != last - 1) { - std::cout << ' '; - } - } - - std::cout << (new_line ? '\n' : ' '); -} - -template -const void output_reverse_container(const Cont& container, const bool& space = true, const bool& new_line = true) { -#if CPL - CPL_IS_CONTAINER(Cont); -#endif // CPL - output_reverse_container(container.rbegin(), container.rend(), space, new_line); -} - -// Special overloads for runtime test output. -namespace debug { - - template ::value, typename Cont::value_type>::type> - std::ostream& operator<<(std::ostream& os, const Cont& container) { - os << '{'; - auto it = container.begin(); - auto end = container.end(); - - if (it != end) { - os << *it; - ++it; - } - - for (; it != end; ++it) { - os << ", " << *it; - } - - return os << '}'; - } - - template - std::ostream& operator<<(std::ostream& os, const std::pair& pair) { - return os << '(' << pair.first << ", " << pair.second << ')'; - } - -#if DBG_MODE || CPL - template - void dbg_out() { - std::cerr << std::endl; - } - - template - void dbg_out(Head&& head, Tail&&... tail) { - std::cerr << ' ' << head; - dbg_out(std::forward(tail)...); - } - -#define test(...) std::cerr << "[" << #__VA_ARGS__ << "]:", dbg_out(__VA_ARGS__) -#else // ^^^ DBG_MODE || CPL ^^^ / vvv !DBG_MODE && !CPL -#define test(...) -#endif // DBG_MODE || CPL - -} // namespace debug - -CPL_END - -#endif // STD_OUTPUT_H_ diff --git a/tests/cpl/container_debug_output/test.cpp b/tests/cpl/container_debug_output/test.cpp new file mode 100644 index 0000000..e8bcdec --- /dev/null +++ b/tests/cpl/container_debug_output/test.cpp @@ -0,0 +1,68 @@ +// Copyright (c) Brandon Pacewic +// SPDX-License-Identifier: MIT + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "container.h" + +int main() { + using namespace std; + using namespace cpl; + { + vector v{1, 2, 3}; + stringstream ss; + ss << v; + assert(ss.str() == "{1, 2, 3}"); + } + { + list l{"foo", "bar"}; + stringstream ss; + ss << l; + assert(ss.str() == "{foo, bar}"); + } + { + set s{'a', 'b'}; + stringstream ss; + ss << s; + assert(ss.str() == "{a, b}"); + } + { + pair p{42, "answer"}; + stringstream ss; + ss << p; + assert(ss.str() == "(42, answer)"); + } + { + map m{{"x", 1}, {"y", 2}}; + stringstream ss; + ss << m; + // Note: map is ordered by key, so this will be {(x, 1), (y, 2)} + assert(ss.str() == "{(x, 1), (y, 2)}"); + } +#if DBG_MODE || CPL + { + stringstream errbuf; + auto old = cerr.rdbuf(errbuf.rdbuf()); + + int a = 10; + string b = "hi"; + test(a, b); + + cerr.rdbuf(old); + + auto out = errbuf.str(); + assert(out.find("[a, b]:") != string::npos); + assert(out.find("10") != string::npos); + assert(out.find("hi") != string::npos); + } +#endif + return 0; +} diff --git a/tests/cpl/include_stdoutput_header/test.cpp b/tests/cpl/include_stdoutput_header/test.cpp deleted file mode 100644 index b801620..0000000 --- a/tests/cpl/include_stdoutput_header/test.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Brandon Pacewic -// SPDX-License-Identifier: MIT - -#include "stdoutput.h" // Include macro target to verify syntax. - -int main() { // compile only - return 0; -}