summaryrefslogtreecommitdiff
path: root/app/platform/stm32f0-gcc/ring_buffer.h
blob: ae4d99dcd64fb736cff01781cc0397a7e79e4930 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#pragma once
#include <cassert>
#include <cstring>

template <typename T>
class RingBuffer
{
public:
    using UnitType = T;
    constexpr explicit RingBuffer(UnitType* buffer, size_t buffer_size)
        : _buffer_size(buffer_size), _buffer(buffer)
    {
        assert(buffer_size);
        assert(buffer);
    }
    constexpr void Push(UnitType item)
    {
        _buffer[_head] = item;
        _head = (_head + 1) % _buffer_size;
    }
    constexpr void Push(const UnitType *items, size_t nitems)
    {
        if (items) {
            for (size_t i = 0; i < nitems; i++) {
                Push(items[i]);
            }
        }
    }
    constexpr UnitType Pop()
    {
        const auto item = _buffer[_tail];
        _tail = (_tail + 1) % _buffer_size;
        return item;
    }
    constexpr void Pop(UnitType* buf, size_t nitems)
    {
        if (buf) {
            for (size_t i = 0; i < nitems; i++) {
                buf[i] = Pop();
            }
        }
    }
    constexpr size_t Free()
    {
        return Size() - Occupied();
    }
    constexpr size_t Occupied()
    {
        return _head - _tail + (_head >= _tail) ? 0 : _buffer_size;
    }
    constexpr bool IsEmpty() { return _head == _tail; }
    constexpr bool IsFull() { return _tail + 1 == _head; }
    constexpr size_t Size() { return _buffer_size - 1; }
private:
    size_t _buffer_size{};
    UnitType *_buffer{};
    size_t _head{}, _tail{};
};