From 5b5086084b4f8451afb097a471f905c2cb2ad634 Mon Sep 17 00:00:00 2001 From: stkhan Date: Tue, 26 Dec 2023 13:42:41 -0600 Subject: Init commit --- somebar/src/line_buffer.hpp | 71 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 somebar/src/line_buffer.hpp (limited to 'somebar/src/line_buffer.hpp') diff --git a/somebar/src/line_buffer.hpp b/somebar/src/line_buffer.hpp new file mode 100644 index 0000000..a5497bf --- /dev/null +++ b/somebar/src/line_buffer.hpp @@ -0,0 +1,71 @@ +// somebar - dwl bar +// See LICENSE file for copyright and license details. + +#pragma once +#include +#include +#include + +// reads data from Reader, and passes complete lines to Consumer. +template +class LineBuffer { + using Iterator = typename std::array::iterator; + std::array _buffer; + Iterator _bufferedTo; + Iterator _consumedTo; + bool _discardLine {false}; +public: + LineBuffer() + : _bufferedTo {_buffer.begin()} + , _consumedTo {_buffer.begin()} + { + } + + template + ssize_t readLines(const Reader& reader, const Consumer& consumer) + { + while (true) { + auto bytesRead = reader(_bufferedTo, _buffer.end() - _bufferedTo); + if (bytesRead <= 0) { + return bytesRead; + } + _bufferedTo += bytesRead; + dispatchLines(consumer); + resetBuffer(); + } + } +private: + template + void dispatchLines(const Consumer& consumer) + { + while (true) { + auto separator = std::find(_consumedTo, _bufferedTo, '\n'); + if (separator == _bufferedTo) { + break; + } + size_t lineLength = separator - _consumedTo; + if (!_discardLine) { + consumer(_consumedTo, lineLength); + } + _consumedTo = separator + 1; + _discardLine = false; + } + } + + void resetBuffer() + { + size_t bytesRemaining = _bufferedTo - _consumedTo; + if (bytesRemaining == _buffer.size()) { + // line too long + _discardLine = true; + _consumedTo = _buffer.begin(); + _bufferedTo = _buffer.begin(); + } else { + // move the last partial message to the front of the buffer, so a full-sized + // message will fit + std::copy(_consumedTo, _bufferedTo, _buffer.begin()); + _consumedTo = _buffer.begin(); + _bufferedTo = _consumedTo + bytesRemaining; + } + } +}; -- cgit v1.2.3