From 1ec05ef6583722b4c8df5d93f4de8cd5122b5b17 Mon Sep 17 00:00:00 2001 From: KingToolbox Date: Tue, 28 Jul 2020 01:38:01 +0800 Subject: [PATCH] Add a quick circular buffer class. --- src/CircularBuffer.h | 90 ++++++++++++++++++++++++++++++++++++++++++++ src/README.md | 4 ++ 2 files changed, 94 insertions(+) create mode 100644 src/CircularBuffer.h diff --git a/src/CircularBuffer.h b/src/CircularBuffer.h new file mode 100644 index 0000000..1cc5a6a --- /dev/null +++ b/src/CircularBuffer.h @@ -0,0 +1,90 @@ + /* + * Copyright 2020, WindTerm. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CIRCULARBUFFER_H +#define CIRCULARBUFFER_H + +#pragma once + +#include +#include + +#define ROUND_UP_POW2(value) { (1 << (32 - qCountLeadingZeroBits(value))) } + +template +class CircularBuffer { +public: + CircularBuffer(quint32 capacity) + : m_currentIndex(0) { + Q_ASSERT(capacity < (1 << 31)); + + m_capacity = ROUND_UP_POW2(capacity); + m_mask = m_capacity - 1; + m_buffer = static_cast(calloc(m_capacity, sizeof(qint64))); + + clear(); + } + + ~CircularBuffer() { + free(m_buffer); + m_buffer = nullptr; + } + + void append(const T &value) { + m_buffer[++m_currentIndex & m_mask] = value; + } + + const T &at(qint64 index) const { + Q_ASSERT(index >= std::max(0, m_currentIndex + 1 - m_capacity) && index <= m_currentIndex); + return m_buffer[index & m_mask]; + } + + int capacity() const { return m_capacity; } + void clear() { + m_currentIndex = -1; + memset(m_buffer, 0xFF, m_capacity * sizeof(qint64)); + +#ifdef _DEBUG + for (int i = 0; i < m_capacity; i++) { + Q_ASSERT(m_buffer[i] == -1); + } +#endif // _DEBUG + } + + qint64 currentIndex() const { return m_currentIndex; } + qint64 minIndex() const { return std::max(0, m_currentIndex + 1 - m_capacity); } + + const T &operator [](qint64 index) const { + Q_ASSERT(index >= std::max(0, m_currentIndex + 1 - m_capacity) && index <= m_currentIndex); + return m_buffer[index & m_mask]; + } + +private: + T *m_buffer; + qint64 m_currentIndex; + + int m_capacity; + int m_mask; +}; + +class Int64CircularBuffer : public CircularBuffer { +public: + Int64CircularBuffer(quint32 capacity) + : CircularBuffer(capacity) + {} +}; + +#endif // CIRCULARBUFFER_H \ No newline at end of file diff --git a/src/README.md b/src/README.md index 8cbea08..38a3f55 100644 --- a/src/README.md +++ b/src/README.md @@ -4,6 +4,10 @@ Below is a list of (some) WindTerm components in alphabetical order, along with a brief description of each. +## CircularBuffer.h + +A quick circular buffer template class. + ## Onigmo An improved version based on Onigmo 5.13.5. In particular, **the addition of iterator makes it possible to match gap buffer or nonadjacent memory blocks.** Please refer to the sample files for how to use. \ No newline at end of file