diff --git a/include/uitsl/utility/SeparatedStream.hpp b/include/uitsl/utility/SeparatedStream.hpp new file mode 100644 index 000000000..c267fa05b --- /dev/null +++ b/include/uitsl/utility/SeparatedStream.hpp @@ -0,0 +1,40 @@ +#pragma once +#ifndef UITSL_UTILITY_SEPARATEDSTREAM_HPP_INCLUDE +#define UITSL_UTILITY_SEPARATEDSTREAM_HPP_INCLUDE + +#include +#include +#include + +namespace uitsl { + +// adapted from https://stackoverflow.com/a/30073885 +class SeparatedStream { + + std::ostream& _stream; + std::string _sep; + bool _first; + +public: + + SeparatedStream(std::ostream &stream, std::string sep) + : _stream(stream), _sep(std::move(sep)), _first(true) {} + + template + SeparatedStream &operator <<(Rhs &&rhs) { + if (_first) _first = false; + else _stream << _sep; + _stream << std::forward(rhs); + return *this; + } + + SeparatedStream& operator<<(std::ostream &(*manip)(std::ostream&)) { + manip(_stream); + return *this; + } + +}; + +} // namespace uitsl + +#endif // #ifndef UITSL_UTILITY_SEPARATEDSTREAM_HPP_INCLUDE diff --git a/include/uitsl/utility/SetSeparator.hpp b/include/uitsl/utility/SetSeparator.hpp new file mode 100644 index 000000000..8074c710c --- /dev/null +++ b/include/uitsl/utility/SetSeparator.hpp @@ -0,0 +1,31 @@ +#pragma once +#ifndef UITSL_UTILITY_SETSEPARATOR_HPP_INCLUDE +#define UITSL_UTILITY_SETSEPARATOR_HPP_INCLUDE + +#include +#include +#include + +#include "SeparatedStream.hpp" + +namespace uitsl { + +// adapted from https://stackoverflow.com/a/30073885 +struct SetSeparator { + + std::string sep; + + SetSeparator(const std::string& sep) : sep(sep) {} + +}; + +uitsl::SeparatedStream operator<<( + std::ostream& stream, + uitsl::SetSeparator wsep +) { + return uitsl::SeparatedStream(stream, std::move(wsep.sep)); +} + +} // namespace uitsl + +#endif // #ifndef UITSL_UTILITY_SETSEPARATOR_HPP_INCLUDE diff --git a/tests/uitsl/utility/Makefile b/tests/uitsl/utility/Makefile index 580abbf90..805711c1a 100644 --- a/tests/uitsl/utility/Makefile +++ b/tests/uitsl/utility/Makefile @@ -2,6 +2,7 @@ TARGET_NAMES += get_exec_instance_uuid TARGET_NAMES += get_proc_instance_uuid TARGET_NAMES += get_thread_instance_uuid TARGET_NAMES += NamedArrayElement +TARGET_NAMES += SetSeparator TO_ROOT := $(shell git rev-parse --show-cdup) diff --git a/tests/uitsl/utility/SetSeparator.cpp b/tests/uitsl/utility/SetSeparator.cpp new file mode 100644 index 000000000..316cddcad --- /dev/null +++ b/tests/uitsl/utility/SetSeparator.cpp @@ -0,0 +1,24 @@ +#include + +#include "Catch/single_include/catch2/catch.hpp" +#include "stduuid/include/uuid.h" + +#include "uitsl/utility/SetSeparator.hpp" + +TEST_CASE("SetSeparator no items", "[nproc:1]") { + std::stringstream ss; + ss << uitsl::SetSeparator(", "); + REQUIRE(ss.str() == ""); +} + +TEST_CASE("SetSeparator one item", "[nproc:1]") { + std::stringstream ss; + ss << uitsl::SetSeparator(", ") << "hello"; + REQUIRE(ss.str() == "hello"); +} + +TEST_CASE("SetSeparator two items", "[nproc:1]") { + std::stringstream ss; + ss << uitsl::SetSeparator(", ") << "hello" << "friend"; + REQUIRE(ss.str() == "hello, friend"); +}