Skip to content

Commit

Permalink
Merge pull request #14 from wx257osn2/refactor-puller
Browse files Browse the repository at this point in the history
Refactor puller
  • Loading branch information
wx257osn2 authored Dec 6, 2022
2 parents fdb27ef + 8d47d2b commit eac3b33
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 39 deletions.
58 changes: 19 additions & 39 deletions include/qoixx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@ namespace qoixx{

namespace detail{

template<typename T>
requires(sizeof(T) == 1 && !std::same_as<T, bool>)
struct contiguous_puller{
static constexpr bool is_contiguous = true;
const T* t;
inline std::uint8_t pull()noexcept{
return static_cast<std::uint8_t>(*t++);
}
inline const std::uint8_t* raw_pointer()noexcept{
return reinterpret_cast<const std::uint8_t*>(t);
}
inline void advance(std::size_t n)noexcept{
t += n;
}
};

template<typename T>
struct default_container_operator;

Expand Down Expand Up @@ -64,19 +80,7 @@ struct default_container_operator<std::vector<T, A>>{
static constexpr pusher create_pusher(target_type& t)noexcept{
return {&t};
}
struct puller{
static constexpr bool is_contiguous = true;
const T* t;
inline std::uint8_t pull()noexcept{
return static_cast<std::uint8_t>(*t++);
}
inline const std::uint8_t* raw_pointer()noexcept{
return reinterpret_cast<const std::uint8_t*>(t);
}
inline void advance(std::size_t n)noexcept{
t += n;
}
};
using puller = contiguous_puller<T>;
static constexpr puller create_puller(const target_type& t)noexcept{
return {t.data()};
}
Expand Down Expand Up @@ -119,19 +123,7 @@ struct default_container_operator<std::pair<std::unique_ptr<T[]>, std::size_t>>{
static constexpr pusher create_pusher(target_type& t)noexcept{
return {&t};
}
struct puller{
static constexpr bool is_contiguous = true;
const T* t;
inline std::uint8_t pull()noexcept{
return static_cast<std::uint8_t>(*t++);
}
inline const std::uint8_t* raw_pointer()noexcept{
return reinterpret_cast<const std::uint8_t*>(t);
}
inline void advance(std::size_t n)noexcept{
t += n;
}
};
using puller = contiguous_puller<T>;
static constexpr puller create_puller(const target_type& t)noexcept{
return {t.first.get()};
}
Expand All @@ -147,19 +139,7 @@ template<typename T>
requires(sizeof(T) == 1)
struct default_container_operator<std::pair<T*, std::size_t>>{
using target_type = std::pair<T*, std::size_t>;
struct puller{
static constexpr bool is_contiguous = true;
const T* ptr;
inline std::uint8_t pull()noexcept{
return static_cast<std::uint8_t>(*ptr++);
}
inline const std::uint8_t* raw_pointer()noexcept{
return reinterpret_cast<const std::uint8_t*>(ptr);
}
inline void advance(std::size_t n)noexcept{
ptr += n;
}
};
using puller = contiguous_puller<T>;
static constexpr puller create_puller(const target_type& t)noexcept{
return {t.first};
}
Expand Down
76 changes: 76 additions & 0 deletions src/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"

template<typename T, typename U>
static bool equals(const T& t, const U& u){
const auto t_size = qoixx::container_operator<T>::size(t);
{
const auto u_size = qoixx::container_operator<U>::size(u);
if(t_size != u_size)
return false;
}
auto t_puller = qoixx::container_operator<T>::create_puller(t);
auto u_puller = qoixx::container_operator<U>::create_puller(u);
for(std::size_t i = 0; i < t_size; ++i)
if(t_puller.pull() != u_puller.pull())
return false;
return true;
}

TEST_CASE("3-channel image"){
constexpr qoixx::qoi::desc d{
.width = 8,
Expand Down Expand Up @@ -34,11 +50,41 @@ TEST_CASE("3-channel image"){
const auto actual = qoixx::qoi::encode<std::vector<std::uint8_t>>(image, d);
CHECK(actual == expected);
}
SUBCASE("encode std::vector<std::uint8_t>, output as std::pair<std::unique_ptr<std::uint8_t[]>, std::size_t>>"){
const auto actual = qoixx::qoi::encode<std::pair<std::unique_ptr<std::uint8_t[]>, std::size_t>>(image, d);
CHECK(equals(actual, expected));
}
SUBCASE("encode std::pair<std::unique_ptr<std::uint8_t[]>, std::size_t>, output as std::vector<std::uint8_t>"){
auto ptr = std::make_unique<std::uint8_t[]>(image.size());
std::ranges::copy(image, ptr.get());
const auto actual = qoixx::qoi::encode<std::vector<std::uint8_t>>(std::make_pair(std::move(ptr), image.size()), d);
CHECK(equals(actual, expected));
}
SUBCASE("encode std::uint8_t*, output as std::vector<std::byte>"){
const auto actual = qoixx::qoi::encode<std::vector<std::byte>>(image.data(), image.size(), d);
CHECK(equals(actual, expected));
}
SUBCASE("decode std::vector<std::uint8_t>, output as std::vector<std::uint8_t>"){
const auto [actual, desc] = qoixx::qoi::decode<std::vector<std::uint8_t>>(expected);
CHECK(d == desc);
CHECK(actual == image);
}
SUBCASE("decode std::vector<std::uint8_t>, output as std::pair<std::unique_ptr<std::uint8_t[], std::size_t>>"){
const auto [actual, desc] = qoixx::qoi::decode<std::pair<std::unique_ptr<std::uint8_t[]>, std::size_t>>(expected);
CHECK(d == desc);
CHECK(equals(actual, image));
}
SUBCASE("decode std::pair<std::unique_ptr<std::uint8_t[]>, std::size_t>, output as std::vector<std::uint8_t>"){
auto ptr = std::make_unique<std::uint8_t[]>(expected.size());
std::ranges::copy(expected, ptr.get());
const auto [actual, desc] = qoixx::qoi::decode<std::vector<std::uint8_t>>(std::make_pair(std::move(ptr), expected.size()));
CHECK(d == desc);
CHECK(equals(actual, image));
}
SUBCASE("decode std::uint8_t*, output as std::vector<std::byte>"){
const auto [actual, desc] = qoixx::qoi::decode<std::vector<std::byte>>(expected.data(), expected.size());
CHECK(equals(actual, image));
}
}

TEST_CASE("4-channel image"){
Expand Down Expand Up @@ -77,9 +123,39 @@ TEST_CASE("4-channel image"){
const auto actual = qoixx::qoi::encode<std::vector<std::uint8_t>>(image, d);
CHECK(actual == expected);
}
SUBCASE("encode std::vector<std::uint8_t>, output as std::pair<std::unique_ptr<std::uint8_t[]>, std::size_t>>"){
const auto actual = qoixx::qoi::encode<std::pair<std::unique_ptr<std::uint8_t[]>, std::size_t>>(image, d);
CHECK(equals(actual, expected));
}
SUBCASE("encode std::pair<std::unique_ptr<std::uint8_t[]>, std::size_t>, output as std::vector<std::uint8_t>"){
auto ptr = std::make_unique<std::uint8_t[]>(image.size());
std::ranges::copy(image, ptr.get());
const auto actual = qoixx::qoi::encode<std::vector<std::uint8_t>>(std::make_pair(std::move(ptr), image.size()), d);
CHECK(equals(actual, expected));
}
SUBCASE("encode std::uint8_t*, output as std::vector<std::byte>"){
const auto actual = qoixx::qoi::encode<std::vector<std::byte>>(image.data(), image.size(), d);
CHECK(equals(actual, expected));
}
SUBCASE("decode std::vector<std::uint8_t>, output as std::vector<std::uint8_t>"){
const auto [actual, desc] = qoixx::qoi::decode<std::vector<std::uint8_t>>(expected);
CHECK(d == desc);
CHECK(actual == image);
}
SUBCASE("decode std::vector<std::uint8_t>, output as std::pair<std::unique_ptr<std::uint8_t[], std::size_t>>"){
const auto [actual, desc] = qoixx::qoi::decode<std::pair<std::unique_ptr<std::uint8_t[]>, std::size_t>>(expected);
CHECK(d == desc);
CHECK(equals(actual, image));
}
SUBCASE("decode std::pair<std::unique_ptr<std::uint8_t[]>, std::size_t>, output as std::vector<std::uint8_t>"){
auto ptr = std::make_unique<std::uint8_t[]>(expected.size());
std::ranges::copy(expected, ptr.get());
const auto [actual, desc] = qoixx::qoi::decode<std::vector<std::uint8_t>>(std::make_pair(std::move(ptr), expected.size()));
CHECK(d == desc);
CHECK(equals(actual, image));
}
SUBCASE("decode std::uint8_t*, output as std::vector<std::byte>"){
const auto [actual, desc] = qoixx::qoi::decode<std::vector<std::byte>>(expected.data(), expected.size());
CHECK(equals(actual, image));
}
}

0 comments on commit eac3b33

Please sign in to comment.