123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- #pragma once
- #include <memory>
- #include <stdint.h>
- #include <stdio.h>
- #include <types/allocator.hpp>
- namespace types {
- template <typename Allocator>
- class basic_buffer {
- public:
- using alloc_traits = std::allocator_traits<Allocator>;
- private:
- char* const start;
- char* const end;
- char* base;
- char* head;
- size_t count;
- Allocator alloc{};
- private:
- constexpr char _get_char(char* ptr) {
- --count;
- return *ptr;
- }
- constexpr void _put_char(char c) {
- *head = c;
- ++count;
- }
- constexpr char* _forward(char* ptr) {
- if (ptr == end)
- return start;
- else
- return ptr + 1;
- }
- constexpr char* _backward(char* ptr) {
- if (ptr == start)
- return end;
- else
- return ptr - 1;
- }
- public:
- constexpr basic_buffer(size_t size)
- : start{alloc_traits::allocate(alloc, size)}
- , end{start + size - 1}
- , base{start}
- , head{start}
- , count{0} {}
- constexpr basic_buffer(const basic_buffer& buf)
- : start{alloc_traits::allocate(alloc, buf.end + 1 - buf.start)}
- , end{(uint32_t)start + (uint32_t)buf.end - (uint32_t)buf.start}
- , base{(uint32_t)start + (uint32_t)buf.base - (uint32_t)buf.start}
- , head{(uint32_t)start + (uint32_t)buf.base - (uint32_t)buf.start}
- , count{buf.count} {}
- constexpr basic_buffer(basic_buffer&& buf)
- : start{buf.start}
- , end{buf.end}
- , base{buf.base}
- , head{buf.head}
- , count{buf.count} {}
- constexpr ~basic_buffer() {
- if (start)
- alloc_traits::deallocate(alloc, start, end - start);
- }
- constexpr bool empty(void) const { return count == 0; }
- constexpr bool full(void) const {
- return count == static_cast<size_t>(end - start + 1);
- }
- constexpr int front(void) {
- if (empty())
- return EOF;
- return *base;
- }
- constexpr int back(void) {
- if (empty())
- return EOF;
- return *_backward(head);
- }
- constexpr int get(void) {
- if (empty())
- return EOF;
- char c = _get_char(base);
- base = _forward(base);
- return c;
- }
- constexpr int pop(void) {
- if (empty())
- return EOF;
- char c = _get_char(_backward(head));
- head = _backward(head);
- return c;
- }
- constexpr int put(char c) {
- if (full())
- return EOF;
- _put_char(c);
- head = _forward(head);
- return c;
- }
- constexpr size_t size(void) const { return count; }
- constexpr size_t avail(void) const { return end - start + 1 - count; }
- constexpr void clear(void) {
- count = 0;
- head = base;
- }
- };
- using buffer = basic_buffer<std::allocator<char>>;
- } // namespace types
|