Compare commits
No commits in common. "b4949a6f0789f02184c851ddf10b25c7f9c8fb43" and "6662bbde927572c9ddf5fd48765eca050f59a258" have entirely different histories.
b4949a6f07
...
6662bbde92
15
.drone.yml
15
.drone.yml
@ -1,15 +0,0 @@
|
|||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: default
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: build and test
|
|
||||||
pull: never
|
|
||||||
image: erki/cpp-ubuntu:latest
|
|
||||||
commands:
|
|
||||||
- mkdir -p build
|
|
||||||
- cd build
|
|
||||||
- conan install .. --build=missing
|
|
||||||
- cmake .. -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=ON
|
|
||||||
- ninja
|
|
||||||
- ctest . --output-on-failure
|
|
||||||
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,10 +1,3 @@
|
|||||||
# ---> Clion
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
# ---> Build files and folders
|
|
||||||
[Bb]uild/
|
|
||||||
cmake-build-*/
|
|
||||||
|
|
||||||
# ---> Eclipse
|
# ---> Eclipse
|
||||||
.metadata
|
.metadata
|
||||||
bin/
|
bin/
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
|
|
||||||
project(SkullC)
|
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
|
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
|
||||||
|
|
||||||
option(WITH_TESTS "Enable unit testing." OFF)
|
|
||||||
|
|
||||||
if(WITH_TESTS)
|
|
||||||
enable_testing()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_subdirectory(Utility)
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
|
|
||||||
|
|
||||||
add_library(utility STATIC
|
|
||||||
Src/utility_logger.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(skullc::utility ALIAS utility)
|
|
||||||
|
|
||||||
target_include_directories(utility
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/Inc
|
|
||||||
)
|
|
||||||
|
|
||||||
if(WITH_TESTS)
|
|
||||||
|
|
||||||
find_package(Catch2 REQUIRED)
|
|
||||||
|
|
||||||
add_executable(utility-tests
|
|
||||||
Tests/main.cpp
|
|
||||||
Tests/ringbuffer.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(utility-tests
|
|
||||||
PUBLIC
|
|
||||||
skullc::utility
|
|
||||||
Catch2::Catch2
|
|
||||||
)
|
|
||||||
|
|
||||||
include(CTest)
|
|
||||||
include(Catch)
|
|
||||||
catch_discover_tests(utility-tests)
|
|
||||||
|
|
||||||
endif()
|
|
||||||
@ -1,230 +0,0 @@
|
|||||||
/*
|
|
||||||
* utility_ringbuffer.hpp
|
|
||||||
*
|
|
||||||
* Created on: Mar 12, 2021
|
|
||||||
* Author: erki
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UTILITY_RINGBUFFER_HPP_
|
|
||||||
#define UTILITY_RINGBUFFER_HPP_
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <iterator>
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
namespace Utility
|
|
||||||
{
|
|
||||||
|
|
||||||
template<typename T, size_t N>
|
|
||||||
class Ringbuffer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using value_type = T;
|
|
||||||
using size_type = std::size_t;
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
using reference = value_type&;
|
|
||||||
using const_reference = const value_type&;
|
|
||||||
using pointer = value_type*;
|
|
||||||
using const_pointer = const value_type*;
|
|
||||||
|
|
||||||
struct iterator
|
|
||||||
{
|
|
||||||
using iterator_category = std::forward_iterator_tag;
|
|
||||||
using difference_type = std::ptrdiff_t;
|
|
||||||
using value_type = T;
|
|
||||||
using pointer = value_type*;
|
|
||||||
using reference = value_type&;
|
|
||||||
|
|
||||||
iterator(const pointer ptr, const pointer begin, const pointer end)
|
|
||||||
: _ptr(ptr)
|
|
||||||
, _arr_begin(begin)
|
|
||||||
, _arr_end(end)
|
|
||||||
{ }
|
|
||||||
iterator(const iterator&) = default;
|
|
||||||
iterator(iterator&&) noexcept = default;
|
|
||||||
|
|
||||||
iterator& operator=(const iterator&) = default;
|
|
||||||
|
|
||||||
reference operator*() const
|
|
||||||
{
|
|
||||||
return *_ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer operator->()
|
|
||||||
{
|
|
||||||
return _ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator& operator++()
|
|
||||||
{
|
|
||||||
_ptr++;
|
|
||||||
if (_ptr == _arr_end)
|
|
||||||
_ptr = _arr_begin;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator operator++(int)
|
|
||||||
{
|
|
||||||
iterator tmp = *this;
|
|
||||||
++(*this);
|
|
||||||
return tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator operator+(const difference_type n) const
|
|
||||||
{
|
|
||||||
const pointer naive = _ptr + n;
|
|
||||||
if (naive < _arr_end)
|
|
||||||
{
|
|
||||||
return iterator(naive, _arr_begin, _arr_end);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const pointer remainder = pointer(naive - _arr_end);
|
|
||||||
return iterator(_arr_begin + difference_type(remainder), _arr_begin, _arr_end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator operator-(const difference_type n) const
|
|
||||||
{
|
|
||||||
const pointer naive = _ptr - n;
|
|
||||||
if (naive >= _arr_begin)
|
|
||||||
{
|
|
||||||
return iterator(naive, _arr_begin, _arr_end);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const pointer remainder = pointer(_arr_begin - naive);
|
|
||||||
return iterator(_arr_end - difference_type(remainder), _arr_begin, _arr_end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator==(const iterator& a, const iterator& b)
|
|
||||||
{
|
|
||||||
return a._ptr == b._ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator!=(const iterator& a, const iterator& b)
|
|
||||||
{
|
|
||||||
return a._ptr != b._ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend difference_type operator-(const iterator& a, const iterator& b)
|
|
||||||
{
|
|
||||||
return a._ptr - b._ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend difference_type operator+(const iterator& a, const iterator& b)
|
|
||||||
{
|
|
||||||
return a._ptr + b._ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
pointer _ptr;
|
|
||||||
pointer _arr_begin;
|
|
||||||
pointer _arr_end;
|
|
||||||
};
|
|
||||||
|
|
||||||
Ringbuffer()
|
|
||||||
: _head(&_data[0], &_data[0], &_data[N])
|
|
||||||
, _tail(_head)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
Ringbuffer(const Ringbuffer&) = delete;
|
|
||||||
Ringbuffer(Ringbuffer&&) noexcept = default;
|
|
||||||
|
|
||||||
iterator begin()
|
|
||||||
{
|
|
||||||
return _head;
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator end()
|
|
||||||
{
|
|
||||||
return _tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
_head = _tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
void push_back(const T& value)
|
|
||||||
{
|
|
||||||
if (size() == N)
|
|
||||||
return;
|
|
||||||
|
|
||||||
*_tail = value;
|
|
||||||
++_tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
void emplace_back(Args&&... args)
|
|
||||||
{
|
|
||||||
if (size() == N)
|
|
||||||
return;
|
|
||||||
|
|
||||||
new (&*_tail)T(std::forward<Args>(args)...);
|
|
||||||
return *(_tail++);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop_front()
|
|
||||||
{
|
|
||||||
if (empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
++_head;
|
|
||||||
}
|
|
||||||
|
|
||||||
reference front()
|
|
||||||
{
|
|
||||||
return *_head;
|
|
||||||
}
|
|
||||||
|
|
||||||
const_reference front() const
|
|
||||||
{
|
|
||||||
return *_head;
|
|
||||||
}
|
|
||||||
|
|
||||||
reference back()
|
|
||||||
{
|
|
||||||
return *(_tail - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const_reference back() const
|
|
||||||
{
|
|
||||||
return *(_tail - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_type size() const
|
|
||||||
{
|
|
||||||
if (_head == _tail)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const typename Ringbuffer<T, N>::iterator::difference_type distance = _tail - _head;
|
|
||||||
|
|
||||||
if (distance > 0)
|
|
||||||
{
|
|
||||||
return distance;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return _head - _tail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty() const
|
|
||||||
{
|
|
||||||
return size() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::array<T, N> _data;
|
|
||||||
|
|
||||||
iterator _head;
|
|
||||||
iterator _tail;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* UTILITY_RINGBUFFER_HPP_ */
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
/*
|
|
||||||
* utility_logger.cpp
|
|
||||||
*
|
|
||||||
* Created on: Mar 13, 2021
|
|
||||||
* Author: erki
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by erki on 13.03.21.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
|
|
||||||
#include <catch2/catch.hpp>
|
|
||||||
@ -1,250 +0,0 @@
|
|||||||
//
|
|
||||||
// Created by erki on 13.03.21.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <catch2/catch.hpp>
|
|
||||||
|
|
||||||
#include "utility_ringbuffer.hpp"
|
|
||||||
|
|
||||||
template<size_t N>
|
|
||||||
using Ringbuffer = Utility::Ringbuffer<int, N>;
|
|
||||||
|
|
||||||
TEST_CASE("Ringbuffer iterator", "[ringbuffer],[iterator]")
|
|
||||||
{
|
|
||||||
using iterator = Ringbuffer<10>::iterator;
|
|
||||||
const auto begin = iterator::pointer(10);
|
|
||||||
const auto end = iterator::pointer(21);
|
|
||||||
iterator it = iterator(iterator::pointer(15), begin, end);
|
|
||||||
|
|
||||||
SECTION("Incrementing postfix increases its pointer and returns initial.")
|
|
||||||
{
|
|
||||||
iterator it_second = it++;
|
|
||||||
REQUIRE(it - it_second == iterator::difference_type(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Incrementing prefix increases its pointer and returns new.")
|
|
||||||
{
|
|
||||||
const iterator original = it;
|
|
||||||
iterator it_second = ++it;
|
|
||||||
REQUIRE(it_second == it);
|
|
||||||
REQUIRE(it - original == iterator::difference_type(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Subtracting 1 decreases its pointer.")
|
|
||||||
{
|
|
||||||
iterator it_second = it - 1;
|
|
||||||
REQUIRE(it - it_second == iterator::difference_type(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Adding 1 increases its pointer.")
|
|
||||||
{
|
|
||||||
iterator it_second = it + 1;
|
|
||||||
REQUIRE(it_second - it == iterator::difference_type(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Ringbuffer iterator at the end", "[ringbuffer],[iterator]")
|
|
||||||
{
|
|
||||||
using iterator = Ringbuffer<10>::iterator;
|
|
||||||
const auto begin = iterator::pointer(10);
|
|
||||||
const auto end = iterator::pointer(21);
|
|
||||||
iterator it = iterator(end - 1, begin, end);
|
|
||||||
|
|
||||||
const auto it_begin = iterator(begin, begin, end);
|
|
||||||
|
|
||||||
SECTION("Incrementing postfix sets the pointer to begin().")
|
|
||||||
{
|
|
||||||
it++;
|
|
||||||
REQUIRE(it == it_begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Incrementing prefix sets the pointer to begin().")
|
|
||||||
{
|
|
||||||
++it;
|
|
||||||
REQUIRE(it == it_begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Adding 1 sets the pointer to begin().")
|
|
||||||
{
|
|
||||||
const iterator it_second = it + 1;
|
|
||||||
REQUIRE(it_second == it_begin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Ringbuffer iterator at the beginning", "[ringbuffer],[iterator]")
|
|
||||||
{
|
|
||||||
using iterator = Ringbuffer<10>::iterator;
|
|
||||||
const auto begin = iterator::pointer(10);
|
|
||||||
const auto end = iterator::pointer(21);
|
|
||||||
iterator it = iterator(begin, begin, end);
|
|
||||||
|
|
||||||
const auto it_last = iterator(end - 1, begin, end);
|
|
||||||
|
|
||||||
SECTION("Subtracting 1 sets the pointer to last element.")
|
|
||||||
{
|
|
||||||
const iterator it_second = it - 1;
|
|
||||||
REQUIRE(it_last == it_second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Constructed buffer is empty.", "[ringbuffer]")
|
|
||||||
{
|
|
||||||
Ringbuffer<10> buffer;
|
|
||||||
|
|
||||||
REQUIRE(buffer.begin() == buffer.end());
|
|
||||||
REQUIRE(buffer.size() == 0);
|
|
||||||
REQUIRE(buffer.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Adding single element.", "[ringbuffer]")
|
|
||||||
{
|
|
||||||
Ringbuffer<10> buffer;
|
|
||||||
const auto old_end = buffer.end();
|
|
||||||
const auto old_begin = buffer.begin();
|
|
||||||
|
|
||||||
buffer.push_back(1);
|
|
||||||
|
|
||||||
SECTION("Increases size and empty appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.size() == 1);
|
|
||||||
REQUIRE(!buffer.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Updates end() appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(old_end != buffer.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("begin() remains the same.")
|
|
||||||
{
|
|
||||||
REQUIRE(old_begin == buffer.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Makes begin() refer to the inserted member.")
|
|
||||||
{
|
|
||||||
REQUIRE(*old_begin == 1);
|
|
||||||
REQUIRE(*buffer.begin() == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Distance between begin and end is 1.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.end() - buffer.begin() == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Makes back() refer to the first element.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.back() == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Makes front() refer to the first element.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.front() == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Makes front() and back() refer to the same memory address.")
|
|
||||||
{
|
|
||||||
REQUIRE(&buffer.front() == &buffer.back());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Adding multiple elements.", "[ringbuffer]")
|
|
||||||
{
|
|
||||||
Ringbuffer<10> buffer;
|
|
||||||
const auto old_begin = buffer.begin();
|
|
||||||
|
|
||||||
buffer.push_back(1);
|
|
||||||
buffer.push_back(2);
|
|
||||||
buffer.push_back(3);
|
|
||||||
|
|
||||||
SECTION("Increases size and empty appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.size() == 3);
|
|
||||||
REQUIRE(!buffer.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Makes front() refer to the first element.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.front() == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Makes back() refer to the last element.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.back() == 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Updates begin() and end() appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(old_begin == buffer.begin());
|
|
||||||
REQUIRE(buffer.end() - buffer.begin() == 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Removing elements from the ringbuffer.", "[ringbuffer]")
|
|
||||||
{
|
|
||||||
Ringbuffer<10> buffer;
|
|
||||||
const auto old_begin = buffer.begin();
|
|
||||||
|
|
||||||
buffer.push_back(1);
|
|
||||||
buffer.push_back(2);
|
|
||||||
buffer.push_back(3);
|
|
||||||
|
|
||||||
buffer.pop_front();
|
|
||||||
|
|
||||||
SECTION("Updates the front() appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.front() == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Updates begin() appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.begin() - old_begin == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Updates size() appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.size() == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Erasing remaining elements")
|
|
||||||
{
|
|
||||||
buffer.pop_front();
|
|
||||||
buffer.pop_front();
|
|
||||||
|
|
||||||
SECTION("Updates empty() appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Updates begin() and end() appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.begin() == buffer.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Updates size() appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.size() == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Clearing a ringbuffer works.", "[ringbuffer]")
|
|
||||||
{
|
|
||||||
Ringbuffer<10> buffer;
|
|
||||||
|
|
||||||
buffer.push_back(1);
|
|
||||||
buffer.push_back(2);
|
|
||||||
buffer.push_back(3);
|
|
||||||
|
|
||||||
buffer.clear();
|
|
||||||
|
|
||||||
SECTION("Updates size() and empty() appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.empty());
|
|
||||||
REQUIRE(buffer.size() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Sets begin() and end() pointers appropriately.")
|
|
||||||
{
|
|
||||||
REQUIRE(buffer.begin() == buffer.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
[requires]
|
|
||||||
catch2/[>=2.0.0,<3.0.0]
|
|
||||||
|
|
||||||
[generators]
|
|
||||||
cmake_find_package
|
|
||||||
Loading…
x
Reference in New Issue
Block a user