aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.util/capture_stream.ccm
diff options
context:
space:
mode:
authorLexi Winter <lexi@le-fay.org>2025-06-29 00:42:31 +0100
committerLexi Winter <lexi@le-fay.org>2025-06-29 00:42:31 +0100
commitd24315268c11d435bb9accbce87b7f46dda6ed3e (patch)
tree66589cb6a15fa74d4b09683105c583e4a5c222b4 /nihil.util/capture_stream.ccm
parent7741a9698d29f79aca3e47495dcdf87c7a712f42 (diff)
downloadnihil-d24315268c11d435bb9accbce87b7f46dda6ed3e.tar.gz
nihil-d24315268c11d435bb9accbce87b7f46dda6ed3e.tar.bz2
cli: improve command dispatch a bit
Diffstat (limited to 'nihil.util/capture_stream.ccm')
-rw-r--r--nihil.util/capture_stream.ccm61
1 files changed, 61 insertions, 0 deletions
diff --git a/nihil.util/capture_stream.ccm b/nihil.util/capture_stream.ccm
new file mode 100644
index 0000000..3333505
--- /dev/null
+++ b/nihil.util/capture_stream.ccm
@@ -0,0 +1,61 @@
+/*
+ * This source code is released into the public domain.
+ */
+
+module;
+
+#include <iostream>
+
+export module nihil.util:capture_stream;
+
+namespace nihil {
+
+/*
+ * Capture output written to a stream and redirect it to an internal string
+ * buffer. Call .str() to get the data written. Call .release() to stop
+ * capturing (or simply delete the capture_stream object).
+ */
+export template<typename Char, typename Traits>
+struct capture_stream {
+ capture_stream(std::basic_ostream<Char, Traits> &stream)
+ : m_stream(&stream)
+ {
+ m_old_streambuf = m_stream->rdbuf();
+ m_stream->rdbuf(m_buffer.rdbuf());
+ }
+
+ ~capture_stream() {
+ if (m_old_streambuf == nullptr)
+ return;
+ release();
+ }
+
+ /*
+ * Release this capture, returning the stream to its previous state.
+ */
+ auto release(this capture_stream &self) -> void
+ {
+ if (self.m_old_streambuf == nullptr)
+ throw std::logic_error(
+ "release() called on empty capture_stream");
+
+ self.m_stream->rdbuf(self.m_old_streambuf);
+ self.m_old_streambuf = nullptr;
+ }
+
+ /*
+ * Get the data which has been written to the stream.
+ */
+ [[nodiscard]] auto str(this capture_stream const &self)
+ -> std::basic_string_view<Char, Traits>
+ {
+ return self.m_buffer.view();
+ }
+
+private:
+ std::basic_ostringstream<Char, Traits> m_buffer;
+ std::basic_ostream<Char, Traits> *m_stream;
+ std::streambuf *m_old_streambuf;
+};
+
+} // namespace nihil