/*
 * Copyright (C) 2020-2021 Aloysius Indrayanto
 *
 * This file is part of the eCxx library, see LICENSE file for the license details.
 */


#ifndef ECXX_CTL_RING_BUFFER_H
#define ECXX_CTL_RING_BUFFER_H


#include <eCxx/CTL/AlignedStorage.h>
#include <eCxx/CTL/MathUtility.h>


namespace eCxx {


//
// A simple ring buffer
//
template <typename ValueT, size_t MaxCapacity>
class RingBuffer : public Uncopyable {
    public:
        typedef       ValueT  ValueType;
        typedef       uint8_t SizeType;

        typedef       ValueT* Pointer;
        typedef const ValueT* ConstPointer;

        static constexpr SizeType ValueSize = sizeof(ValueType);
        static constexpr SizeType Capacity  = MaxCapacity;

    public:
        inline RingBuffer() noexcept;
        inline ~RingBuffer() noexcept;

        inline SizeType capacity() const noexcept;
        inline SizeType size() const noexcept;

        inline bool full() const noexcept;
        inline bool empty() const noexcept;
        inline void clear() noexcept;

        inline bool put(const ValueType& value) noexcept;
        inline bool get(      ValueType& value) noexcept;

        inline bool peek(ValueType& value) const noexcept;

        template <uint8_t N>
        inline bool peekMatchFirstN(const ValueType (&ref)[N]) const noexcept;

        template <uint8_t N>
        inline bool peekMatchLastN(const ValueType (&ref)[N]) const noexcept;

        inline ConstPointer data() const noexcept;

    public:
        // Special direct access functions to modify the buffer's content
        inline Pointer _writeableData() noexcept;
        inline void _setWrittenDataSize(SizeType size) noexcept;

    private:
        SizeType                            _rPos;
        SizeType                            _wPos;
        AlignedStorage<ValueType, Capacity> _buffer;
};


//
// Include the implementation file
//
#define INCLUDE_ECXX_CTL_RING_BUFFER_TPP
#include "RingBuffer.tpp"


} // namespace eCxx


#endif
