From 2b01a75679a03bd6557cf11c20b1588f436d6b94 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 9 Jun 2025 22:26:34 -0700 Subject: [PATCH] io/process: add StdioCollector data stream parser --- src/io/datastream.cpp | 24 ++++++++++++++++++++++++ src/io/datastream.hpp | 43 +++++++++++++++++++++++++++++++++++++++++-- src/io/process.hpp | 4 ++-- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/io/datastream.cpp b/src/io/datastream.cpp index b30b0ac3..393f3330 100644 --- a/src/io/datastream.cpp +++ b/src/io/datastream.cpp @@ -111,3 +111,27 @@ void SplitParser::setSplitMarker(QString marker) { this->mSplitMarkerChanged = true; emit this->splitMarkerChanged(); } + +void StdioCollector::parseBytes(QByteArray& incoming, QByteArray& buffer) { + buffer.append(incoming); + + if (!this->mWaitForEnd) { + this->mData = buffer; + emit this->dataChanged(); + } +} + +void StdioCollector::streamEnded(QByteArray& buffer) { + if (this->mWaitForEnd) { + this->mData = buffer; + emit this->dataChanged(); + } + + emit this->streamFinished(); +} + +void StdioCollector::setWaitForEnd(bool waitForEnd) { + if (waitForEnd == this->mWaitForEnd) return; + this->mWaitForEnd = waitForEnd; + emit this->waitForEndChanged(); +} diff --git a/src/io/datastream.hpp b/src/io/datastream.hpp index 57ddd658..d83e571e 100644 --- a/src/io/datastream.hpp +++ b/src/io/datastream.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -61,8 +62,8 @@ signals: void read(QString data); }; -///! Parser for delimited data streams. -/// Parser for delimited data streams. @@read() is emitted once per delimited chunk of the stream. +///! DataStreamParser for delimited data streams. +/// DataStreamParser for delimited data streams. @@read() is emitted once per delimited chunk of the stream. class SplitParser: public DataStreamParser { Q_OBJECT; /// The delimiter for parsed data. May be multiple characters. Defaults to `\n`. @@ -88,3 +89,41 @@ private: QString mSplitMarker = "\n"; bool mSplitMarkerChanged = false; }; + +///! DataStreamParser that collects all output into a buffer +/// StdioCollector collects all process output into a buffer exposed as @@text or @@data. +class StdioCollector: public DataStreamParser { + Q_OBJECT; + QML_ELEMENT; + /// The stdio buffer exposed as text. if @@waitForEnd is true, this will not change + /// until the stream ends. + Q_PROPERTY(QString text READ text NOTIFY dataChanged); + /// The stdio buffer exposed as an [ArrayBuffer]. if @@waitForEnd is true, this will not change + /// until the stream ends. + /// + /// [ArrayBuffer]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer + Q_PROPERTY(QByteArray data READ data NOTIFY dataChanged); + /// If true, @@text and @@data will not be updated until the stream ends. Defaults to true. + Q_PROPERTY(bool waitForEnd READ waitForEnd WRITE setWaitForEnd NOTIFY waitForEndChanged); + +public: + explicit StdioCollector(QObject* parent = nullptr): DataStreamParser(parent) {} + + void parseBytes(QByteArray& incoming, QByteArray& buffer) override; + void streamEnded(QByteArray& buffer) override; + + [[nodiscard]] QString text() const { return this->mData; } + [[nodiscard]] QByteArray data() const { return this->mData; } + + [[nodiscard]] bool waitForEnd() const { return this->mWaitForEnd; } + void setWaitForEnd(bool waitForEnd); + +signals: + void waitForEndChanged(); + void dataChanged(); + void streamFinished(); + +private: + bool mWaitForEnd = true; + QByteArray mData; +}; diff --git a/src/io/process.hpp b/src/io/process.hpp index 7f448c4e..e93004f1 100644 --- a/src/io/process.hpp +++ b/src/io/process.hpp @@ -22,8 +22,8 @@ /// Process { /// running: true /// command: [ "some-command", "arg" ] -/// stdout: SplitParser { -/// onRead: data => console.log(`line read: ${data}`) +/// stdout: @@StdioCollector { +/// onStreamFinished: console.log(`line read: ${this.text}`) /// } /// } /// ```