From 0e71af11a27631e45c0160842e4498507420eff0 Mon Sep 17 00:00:00 2001 From: stkhan Date: Fri, 31 Mar 2023 19:42:29 -0500 Subject: bar and blocks --- wm/somebar/src/line_buffer.hpp | 71 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 wm/somebar/src/line_buffer.hpp (limited to 'wm/somebar/src/line_buffer.hpp') diff --git a/wm/somebar/src/line_buffer.hpp b/wm/somebar/src/line_buffer.hpp new file mode 100644 index 0000000..a5497bf --- /dev/null +++ b/wm/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