@ -0,0 +1,29 @@ | |||
#pragma once | |||
namespace gp{ | |||
template<typename T, typename U, typename ...rest> | |||
constexpr T max(T first, U second, rest... args) | |||
{ | |||
if constexpr (sizeof...(args) == 0) | |||
{ | |||
return first > second ? first : second; | |||
} | |||
else | |||
{ | |||
return max(first > second ? first : second, args...); | |||
} | |||
} | |||
template<typename T, typename U, typename ...rest> | |||
constexpr T min(T first, U second, rest... args) | |||
{ | |||
if constexpr (sizeof...(args) == 0) | |||
{ | |||
return first < second ? first : second; | |||
} | |||
else | |||
{ | |||
return min(first < second ? first : second, args...); | |||
} | |||
} | |||
} |
@ -0,0 +1,64 @@ | |||
#pragma once | |||
#include "gp/algorithm/tmp_manip.hpp" | |||
#include "gp/range.hpp" | |||
namespace gp{ | |||
template<typename T> | |||
typename gp::remove_reference<T>::type&& move(T&& value) | |||
{ | |||
return (typename gp::remove_reference<T>::type&&)value; | |||
} | |||
template<typename T> | |||
constexpr T&& forward(typename gp::remove_reference<T>::type& t) noexcept | |||
{ | |||
return static_cast<T&&>(t); | |||
} | |||
template<typename T> | |||
constexpr T&& forward(typename gp::remove_reference<T>::type&& t) noexcept | |||
{ | |||
static_assert(!std::is_lvalue_reference_v<T>,"bad forward of rvalue as lvalue"); | |||
return static_cast<T&&>(t); | |||
} | |||
template<typename T> | |||
constexpr void swap( | |||
T& lhs, | |||
T& rhs | |||
) | |||
{ | |||
auto tmp = lhs; | |||
lhs = rhs; | |||
rhs = tmp; | |||
} | |||
template<typename range_in, typename range_out> | |||
nameless_range<typename range_out::associated_iterator> move(range_in src, range_out dest) | |||
{ | |||
if(src.size()>dest.size()) | |||
return nameless_range<typename range_out::associated_iterator>(dest.begin(), dest.end()); | |||
auto in = src.begin(); | |||
auto in_close = src.end(); | |||
auto out = dest.begin(); | |||
while(in != in_close) | |||
{ | |||
*(out++) = gp::move(*(in++)); | |||
} | |||
return nameless_range<typename range_out::associated_iterator>{out, dest.end()}; | |||
} | |||
template<typename T, typename range_in, typename range_out> | |||
nameless_range<typename range_out::associated_iterator> move_uninitialized(range_in src, range_out dest) | |||
{ | |||
if(src.size()>dest.size()) | |||
return nameless_range<typename range_out::associated_iterator>(dest.begin(), dest.end()); | |||
auto in = src.begin(); | |||
auto in_close = src.end(); | |||
auto out = dest.begin(); | |||
while(in != in_close) | |||
{ | |||
new(&*(out++)) T{gp::move(*(in++))}; | |||
} | |||
return nameless_range<typename range_out::associated_iterator>{out, dest.end()}; | |||
} | |||
} |
@ -0,0 +1,234 @@ | |||
#pragma once | |||
#include <type_traits> | |||
#include <typeinfo> | |||
#include <cstddef> | |||
#include <limits> | |||
#include "gp/algorithm/min_max.hpp" | |||
namespace gp{ | |||
template<bool cond, typename T, typename U> | |||
struct either | |||
{ | |||
}; | |||
template<typename T, typename U> | |||
struct either<true,T,U> | |||
{ | |||
typedef T type; | |||
}; | |||
template<typename T, typename U> | |||
struct either<false,T,U> | |||
{ | |||
typedef U type; | |||
}; | |||
template<bool first, bool ...list> | |||
struct constexpr_all_of | |||
{ | |||
static constexpr bool value = first && constexpr_all_of<list...>::value; | |||
}; | |||
template<bool first> | |||
struct constexpr_all_of<first> | |||
{ | |||
static constexpr bool value = first; | |||
}; | |||
template<bool first, bool ...list> | |||
struct constexpr_any_of | |||
{ | |||
static constexpr bool value = first || constexpr_any_of<list...>::value; | |||
}; | |||
template<bool first> | |||
struct constexpr_any_of<first> | |||
{ | |||
static constexpr bool value = first; | |||
}; | |||
template<typename T> | |||
constexpr bool is_fixed_size() | |||
{ | |||
return std::is_final<T>::value | |||
|| std::is_fundamental<T>::value; | |||
} | |||
template<typename T, typename ...rest> | |||
struct all_of_fixed_size | |||
{ | |||
static constexpr bool value = is_fixed_size<T>() && all_of_fixed_size<rest...>::value; | |||
}; | |||
template<typename T> | |||
struct all_of_fixed_size<T> | |||
{ | |||
static constexpr bool value = is_fixed_size<T>(); | |||
}; | |||
template<typename Univ, typename T, typename ...rest> | |||
struct list_contains_class | |||
{ | |||
static constexpr bool value = ( | |||
std::is_same<T, Univ>::value | |||
) || list_contains_class<Univ, rest...>::value; | |||
}; | |||
template<typename Univ, typename T> | |||
struct list_contains_class<Univ, T> | |||
{ | |||
static constexpr bool value = std::is_same<T, Univ>::value; | |||
}; | |||
template<typename Univ, typename T, typename ...rest> | |||
struct r_index_of | |||
{ | |||
static constexpr std::size_t value = std::is_same<T, Univ>::value ? sizeof...(rest) : r_index_of<Univ, rest...>::value; | |||
}; | |||
template<typename Univ, typename T> | |||
struct r_index_of<Univ, T> | |||
{ | |||
static constexpr std::size_t value = std::is_same<T, Univ>::value ? 0 : std::numeric_limits<std::size_t>::max(); | |||
}; | |||
template<size_t idx, typename T, typename ...rest> | |||
struct r_index_at | |||
{ | |||
using type = typename either<idx==sizeof...(rest),T,typename r_index_at<idx,rest...>::type>::type; | |||
}; | |||
template<typename T, typename U, typename ...rest> | |||
constexpr std::size_t max_size() | |||
{ | |||
if constexpr (sizeof...(rest) == 0) | |||
{ | |||
return gp::max(sizeof(T),sizeof(U)); | |||
} | |||
else | |||
{ | |||
return max_size< | |||
either< | |||
( sizeof(T) > sizeof(U) ), | |||
T, | |||
U | |||
>::type, | |||
rest...>(); | |||
} | |||
} | |||
template<typename T> | |||
struct remove_reference | |||
{ | |||
using type = T; | |||
}; | |||
template<typename T> | |||
struct remove_reference<T&> | |||
{ | |||
using type = T; | |||
}; | |||
template<typename T> | |||
struct remove_reference<T&&> | |||
{ | |||
using type = T; | |||
}; | |||
template<typename T> | |||
struct has_size_interface | |||
{ | |||
private: | |||
typedef std::true_type yes; | |||
typedef std::false_type no; | |||
template<typename U, size_t (U::*f)() const> struct SFINAE{}; | |||
template<class C> static yes test(SFINAE<C,&C::size>*); | |||
template<class C> static no test(...); | |||
public: | |||
static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value; | |||
}; | |||
template<typename T> | |||
struct has_begin_interface | |||
{ | |||
private: | |||
typedef std::true_type yes; | |||
typedef std::false_type no; | |||
template<typename U, auto (U::*f)() const> struct SFINAE{}; | |||
template<class C> static yes test(SFINAE<C,&C::begin>*); | |||
template<class C> static no test(...); | |||
public: | |||
static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value; | |||
}; | |||
template<typename T> | |||
struct has_end_interface | |||
{ | |||
private: | |||
typedef std::true_type yes; | |||
typedef std::false_type no; | |||
template<typename U, auto (U::*f)() const> struct SFINAE{}; | |||
template<class C> static yes test(SFINAE<C,&C::end>*); | |||
template<class C> static no test(...); | |||
public: | |||
static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value; | |||
}; | |||
template<typename T> | |||
using has_range_interface = constexpr_all_of<has_begin_interface<T>::value,has_end_interface<T>::value>; | |||
template<typename T> | |||
using has_measurable_range_interface = constexpr_all_of<has_range_interface<T>::value,has_size_interface<T>::value>; | |||
template<typename T> | |||
struct has_allocate_interface | |||
{ | |||
private: | |||
typedef std::true_type yes; | |||
typedef std::false_type no; | |||
template<typename U, void* (U::*f)(size_t) const> struct SFINAE{}; | |||
template<class C> static yes test(SFINAE<C,&C::allocate>*); | |||
template<class C> static no test(...); | |||
public: | |||
static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value; | |||
}; | |||
template<typename T> | |||
struct has_deallocate_interface | |||
{ | |||
private: | |||
typedef std::true_type yes; | |||
typedef std::false_type no; | |||
template<typename U, void (U::*f)(void*) const> struct SFINAE{}; | |||
template<class C> static yes test(SFINAE<C,&C::deallocate>*); | |||
template<class C> static no test(...); | |||
public: | |||
static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value; | |||
}; | |||
template<typename T> | |||
using has_allocator_interface = constexpr_all_of<has_allocate_interface<T>::value,has_deallocate_interface<T>::value>; | |||
} |
@ -0,0 +1,95 @@ | |||
#pragma once | |||
#include "gp_config.hpp" | |||
#include "gp/buffer.hpp" | |||
#include <type_traits> | |||
#include <gp/algorithm/tmp_manip.hpp> | |||
namespace gp{ | |||
template<typename page_allocator, size_t align = 1> | |||
class arena{ | |||
page_allocator allocator; | |||
fel::buffer<char> data; | |||
size_t last; | |||
size_t count; | |||
public: | |||
arena() | |||
:last(0) | |||
,count(0) | |||
,data(fel::buffer<char>(nullptr,nullptr)) | |||
{} | |||
template<typename T = typename std::enable_if<fel::has_allocator_interface<page_allocator>::value,int>::type> | |||
arena(size_t sz) | |||
:last(0) | |||
,count(0) | |||
,data(nullptr,nullptr) | |||
{ | |||
if(sz!=0) | |||
{ | |||
auto v=allocator.allocate(sz); | |||
if(v!=nullptr) | |||
{ | |||
data=fel::buffer<char>(reinterpret_cast<char*>(v),reinterpret_cast<char*>(v)+sz); | |||
} | |||
} | |||
} | |||
arena(char* pos,size_t sz) | |||
:last(0) | |||
,count(0) | |||
,data(pos,pos+sz) | |||
{ | |||
} | |||
void* allocate(size_t sz) | |||
{ | |||
[[maybe_unused]] | |||
size_t mod = 0; | |||
if constexpr (align != 1) | |||
{ | |||
mod = align - ((intptr_t)data.begin())%align; | |||
} | |||
auto ret=data.begin()+last+mod; | |||
if(data.contains(ret)) | |||
{ | |||
count++; | |||
last+=sz+mod; | |||
return &*(ret); | |||
} | |||
else | |||
{ | |||
return nullptr; | |||
} | |||
} | |||
bool deallocate(void* ptr) | |||
{ | |||
if(data.contains((char*)ptr)) | |||
{ | |||
count--; | |||
if(count==0) | |||
{ | |||
for(auto& i : data) | |||
{ | |||
i=0; | |||
} | |||
last=0; | |||
} | |||
return true; | |||
} | |||
return false; | |||
} | |||
~arena() | |||
{ | |||
if constexpr(fel::has_allocator_interface<page_allocator>::value) | |||
{ | |||
allocator.deallocate(&data[0]); | |||
} | |||
} | |||
}; | |||
} |
@ -0,0 +1,48 @@ | |||
#pragma once | |||
#include <gp/buffer.hpp> | |||
namespace gp{ | |||
template<typename T, std::size_t sz> | |||
class array{ | |||
T ary[sz]; | |||
public: | |||
using associated_iterator = typename buffer<T>::associated_iterator; | |||
constexpr T& operator[] (size_t off) | |||
{ | |||
return ary[off]; | |||
} | |||
constexpr size_t size() const | |||
{ | |||
return sz; | |||
} | |||
constexpr associated_iterator begin() const | |||
{ | |||
return gp::buffer<T>{(T*)ary, (T*)ary+sz}.begin(); | |||
} | |||
constexpr associated_iterator end() const | |||
{ | |||
return gp::buffer<T>{(T*)ary, (T*)ary+sz}.end(); | |||
} | |||
constexpr bool operator==(const array& oth) const | |||
{ | |||
for(size_t idx = 0; idx<sz; idx++) | |||
{ | |||
if(ary[idx] != oth.ary[idx]) | |||
{ | |||
return false; | |||
} | |||
} | |||
return true; | |||
} | |||
gp::buffer<T> as_buffer() | |||
{ | |||
return gp::buffer<T>{(T*)ary, (T*)ary+sz}; | |||
} | |||
}; | |||
} |
@ -0,0 +1,49 @@ | |||
#pragma once | |||
#include <stdint.h> | |||
#include <atomic> | |||
#include <gp/array.hpp> | |||
#include <gp/algorithm/tmp_manip.hpp> | |||
namespace gp { | |||
template<typename hash_type = uint64_t, uint8_t magnitude = 19, bool threading = false> | |||
class bloomfilter { | |||
constexpr static size_t phys_size = (1 << magnitude) / 32; | |||
gp::array< | |||
typename gp::either< threading, | |||
std::atomic_uint32_t, | |||
uint32_t | |||
>::type, | |||
phys_size | |||
> data; | |||
template<typename T> | |||
static void set_bit(T* value, const int v_pos) { | |||
*value |= (1 << v_pos); | |||
} | |||
template<typename T> | |||
static bool get_bit(T* value, const int v_pos) { | |||
return (*value >> v_pos) & 1; | |||
} | |||
public: | |||
void set_hash(hash_type v) | |||
{ | |||
const size_t modulo = v & ((1 << magnitude)-1); | |||
const size_t p_pos = modulo / 32; | |||
const size_t v_pos = modulo % 32; | |||
set_bit(&data[p_pos], v_pos); | |||
} | |||
bool test_hash(hash_type v) | |||
{ | |||
const size_t modulo = v & ((1 << magnitude)-1); | |||
const size_t p_pos = modulo / 32; | |||
const size_t v_pos = modulo % 32; | |||
return get_bit(&data[p_pos], v_pos); | |||
} | |||
}; | |||
} |
@ -0,0 +1,205 @@ | |||
#pragma once | |||
#include <cstddef> | |||
#include <cstdint> | |||
#include <gp/optional.hpp> | |||
#include <gp/iterator.hpp> | |||
#include <gp/function.hpp> | |||
#include <gp/exception.hpp> | |||
#include <gp/algorithm/move.hpp> | |||
namespace gp{ | |||
template<typename T> | |||
class buffer final{ | |||
public: | |||
struct buffer_iterator final | |||
{ | |||
T* data; | |||
typedef T value_type; | |||
typedef std::size_t difference_type; | |||
static constexpr iterator_type_t iterator_type = iterator_type_t::contiguous_iterator; | |||
constexpr buffer_iterator(const buffer_iterator& oth) | |||
: data{oth.data} | |||
{} | |||
constexpr buffer_iterator(T* ptr) | |||
: data{ptr} | |||
{} | |||
constexpr operator T&() | |||
{ | |||
return *data; | |||
} | |||
constexpr T& operator*(){ | |||
return *data; | |||
} | |||
constexpr buffer_iterator operator++() | |||
{ | |||
return buffer_iterator{++data}; | |||
} | |||
constexpr buffer_iterator operator++(int) | |||
{ | |||
return buffer_iterator{data++}; | |||
} | |||
constexpr buffer_iterator operator--() | |||
{ | |||
return buffer_iterator{--data}; | |||
} | |||
constexpr buffer_iterator operator--(int) | |||
{ | |||
return buffer_iterator{data--}; | |||
} | |||
constexpr buffer_iterator operator+(const std::size_t offset) | |||
{ | |||
return buffer_iterator{data+offset}; | |||
} | |||
constexpr buffer_iterator operator+(const int offset) | |||
{ | |||
return buffer_iterator{data+offset}; | |||
} | |||
constexpr buffer_iterator operator-(const std::size_t offset) | |||
{ | |||
return buffer_iterator{data-offset}; | |||
} | |||
constexpr buffer_iterator operator-(const int offset) | |||
{ | |||
return buffer_iterator{data-offset}; | |||
} | |||
constexpr difference_type operator-(const buffer_iterator& oth) const | |||
{ | |||
return (T*)data-(T*)oth.data; | |||
} | |||
constexpr bool operator==(const buffer_iterator& oth) | |||
{ | |||
return data==oth.data; | |||
} | |||
constexpr bool operator!=(buffer_iterator& oth) | |||
{ | |||
return data!=oth.data; | |||
} | |||
constexpr bool before_or_equal(const buffer_iterator& oth) | |||
{ | |||
return reinterpret_cast<std::intptr_t>(data) <= reinterpret_cast<std::intptr_t>(oth.data); | |||
} | |||
constexpr bool operator<=(const buffer_iterator& oth) | |||
{ | |||
return before_or_equal(oth); | |||
} | |||
}; | |||
private: | |||
buffer_iterator begin_elem; | |||
buffer_iterator end_elem; | |||
public: | |||
using associated_iterator = buffer_iterator; | |||
constexpr buffer(T* beg_ptr, T* end_ptr) | |||
: begin_elem{beg_ptr} | |||
, end_elem{end_ptr} | |||
{} | |||
constexpr buffer(T* beg_ptr, std::size_t sz) | |||
: begin_elem{beg_ptr} | |||
, end_elem{beg_ptr+sz} | |||
{} | |||
constexpr typename buffer_iterator::difference_type size() const | |||
{ | |||
return end_elem - begin_elem; | |||
} | |||
constexpr associated_iterator begin() const | |||
{ | |||
return begin_elem; | |||
} | |||
constexpr associated_iterator end() const | |||
{ | |||
return end_elem; | |||
} | |||
constexpr T& operator[](std::size_t offset) | |||
{ | |||
return *(begin_elem+offset); | |||
} | |||
optional<buffer_iterator> at(std::size_t offset) | |||
{ | |||
auto elem = begin()+offset; | |||
if(!contains(elem)) | |||
{ | |||
return nullopt; | |||
} | |||
return elem; | |||
} | |||
constexpr bool contains(buffer_iterator ptr) | |||
{ | |||
return | |||
ptr.data < end_elem.data | |||
&& ptr.data >= begin_elem.data; | |||
} | |||
template<typename U> | |||
buffer<U> cast() | |||
{ | |||
if constexpr(sizeof(T)%sizeof(U) == 0) | |||
{ | |||
return buffer<U>(reinterpret_cast<U*>(&*begin_elem), size()*(sizeof(T)/sizeof(U))); | |||
} | |||
else | |||
{ | |||
if(size()*sizeof(T)/sizeof(U)) | |||
{ | |||
return buffer<U>(reinterpret_cast<U*>(&*begin_elem), size()*sizeof(T)/sizeof(U)); | |||
} | |||
else if constexpr (gp_config::has_exceptions) | |||
{ | |||
throw bad_buffer_cast<T, U>{}; | |||
} | |||
else | |||
{ | |||
return buffer<U>(reinterpret_cast<U*>(nullptr), 0); | |||
} | |||
} | |||
} | |||
buffer slice_start(size_t new_sz) | |||
{ | |||
if(new_sz<=size()) | |||
{ | |||
return buffer{&*begin(), &*(begin()+new_sz)}; | |||
} | |||
else | |||
{ | |||
return buffer{(T*)nullptr,(size_t)0}; | |||
} | |||
} | |||
buffer slice_end(size_t new_sz) | |||
{ | |||
if(new_sz<=size()) | |||
{ | |||
return buffer{&*(end()-(1+new_sz)), &*end()}; | |||
} | |||
else | |||
{ | |||
return buffer{(T*)nullptr,(size_t)0}; | |||
} | |||
} | |||
}; | |||
} |
@ -0,0 +1,117 @@ | |||
#pragma once | |||
#include "gp_config.hpp" | |||
#include <new> | |||
namespace gp{ | |||
class runtime_error{ | |||
protected: | |||
const char* what_str; | |||
public: | |||
runtime_error(const char* what) | |||
: what_str{what} | |||
{} | |||
runtime_error() | |||
{ | |||
what_str = "an unknown error has occured"; | |||
} | |||
const char* what() | |||
{ | |||
return what_str; | |||
} | |||
}; | |||
class out_of_range : public runtime_error{ | |||
public: | |||
out_of_range(const char* what) | |||
: runtime_error{what} | |||
{} | |||
out_of_range() | |||
: runtime_error{} | |||
{ | |||
what_str = "out_of_range error has occured"; | |||
} | |||
}; | |||
class bad_optional : public runtime_error{ | |||
public: | |||
bad_optional(const char* what) | |||
: runtime_error{what} | |||
{} | |||
bad_optional() | |||
: runtime_error{} | |||
{ | |||
what_str = "bad_optional error has occured"; | |||
} | |||
}; | |||
template<typename orig, typename target> | |||
class bad_buffer_cast : public runtime_error{ | |||
public: | |||
bad_buffer_cast(const char* what) | |||
: runtime_error{what} | |||
{} | |||
bad_buffer_cast() | |||
: runtime_error{} | |||
{ | |||
what_str = "bad_buffer_cast error has occured"; | |||
} | |||
}; | |||
template<typename Expected> | |||
class bad_variant_access : public runtime_error{ | |||
public: | |||
bad_variant_access(const char* what) | |||
: runtime_error{what} | |||
{} | |||
bad_variant_access() | |||
: runtime_error{} | |||
{ | |||
what_str = "bad_variant_access error has occured"; | |||
} | |||
}; | |||
class bad_hashmap_access : public runtime_error{ | |||
public: | |||
bad_hashmap_access(const char* what) | |||
: runtime_error{what} | |||
{} | |||
bad_hashmap_access() | |||
: runtime_error{} | |||
{ | |||
what_str = "bad_hashmap_access error has occured"; | |||
} | |||
}; | |||
class bad_alloc : public runtime_error{ | |||
public: | |||
bad_alloc(const char* what) | |||
: runtime_error{what} | |||
{} | |||
bad_alloc() | |||
: runtime_error{} | |||
{ | |||
what_str = "bad_alloc error has occured"; | |||
} | |||
}; | |||
class bad_functor : public runtime_error{ | |||
public: | |||
bad_functor(const char* what) | |||
: runtime_error{what} | |||
{} | |||
bad_functor() | |||
: runtime_error{} | |||
{ | |||
what_str = "bad_functor error has occured"; | |||
} | |||
}; | |||
} |
@ -0,0 +1,140 @@ | |||
#pragma once | |||
#include "gp/memory.hpp" | |||
#include "gp/exception.hpp" | |||
namespace gp{ | |||
template <typename> | |||
class function; | |||
template <typename ret, typename ...args> | |||
class function<ret(args...)>{ | |||
struct virtual_callable | |||
{ | |||
virtual ~virtual_callable() = default; | |||
virtual ret operator() (args...) = 0; | |||
}; | |||
template<typename fn> | |||
class callable : virtual_callable{ | |||
fn internal_representation; | |||
public: | |||
callable(const fn& func) | |||
: internal_representation{func} | |||
{} | |||
virtual ~callable() override = default; | |||
ret operator() (args... arg_list) | |||
{ | |||
return internal_representation(arg_list...); | |||
} | |||
}; | |||
enum state_t : uint8_t{ | |||
INACTIVE = 0, | |||
ACTIVE = 1, | |||
NO_SOO = 0, | |||
SOO = 2 | |||
}; | |||
state_t state = 0; | |||
union{ | |||
virtual_callable* functor = nullptr; | |||
char inplace[12]; | |||
} self; | |||
public: | |||
template <typename T> | |||
function& operator=(T& t) | |||
{ | |||
if(state & ACTIVE) | |||
{ | |||
if(state & SOO) | |||
{ | |||
((virtual_callable*)&self)->~virtual_callable(); | |||
} | |||
else | |||
{ | |||
delete self.functor; | |||
} | |||
} | |||
if constexpr (sizeof(callable<T>) <= sizeof(self)) | |||
{ | |||
new((void*)&self) callable(t); | |||
state = ACTIVE | SOO; | |||
} | |||
else | |||
{ | |||
self = new callable(t); | |||
state = ACTIVE | NO_SOO; | |||
} | |||
} | |||
template <typename T> | |||
function(T t) | |||
{ | |||
if constexpr (sizeof(callable<T>) <= sizeof(self)) | |||
{ | |||
new((void*)&self) callable(t); | |||
state = ACTIVE | SOO; | |||
} | |||
else | |||
{ | |||
self = new callable(t); | |||
state = ACTIVE | NO_SOO; | |||
} | |||
} | |||
template <typename T> | |||
function(T& t) | |||
{ | |||
if constexpr (sizeof(callable<T>) <= sizeof(self)) | |||
{ | |||
new((void*)&self) callable(t); | |||
state = ACTIVE | SOO; | |||
} | |||
else | |||
{ | |||
self = new callable(t); | |||
state = ACTIVE | NO_SOO; | |||
} | |||
} | |||
ret operator()(args... arg_list) const { | |||
if constexpr (gp_config::has_exceptions) | |||
{ | |||
if(!(state & ACTIVE)) | |||
{ | |||
throw bad_functor{}; | |||
} | |||
} | |||
if(state & SOO) | |||
{ | |||
return (*(virtual_callable*)&self)(arg_list...); | |||
} | |||
else | |||
{ | |||
return (*(self.functor))(arg_list...); | |||
} | |||
} | |||
~function() | |||
{ | |||
if(state & ACTIVE) | |||
{ | |||
if(state & SOO) | |||
{ | |||
((virtual_callable*)&self)->~virtual_callable(); | |||
} | |||
else | |||
{ | |||
delete self.functor; | |||
} | |||
} | |||
} | |||
}; | |||
} |
@ -0,0 +1,7 @@ | |||
#pragma once | |||
enum class iterator_type_t{ | |||
contiguous_iterator, | |||
non_contiguous_iterator, | |||
lazy_iterator | |||
}; |
@ -0,0 +1,56 @@ | |||
#pragma once | |||
#include "gp_config.hpp" | |||
#include "gp/exception.hpp" | |||
#include <type_traits> | |||
namespace gp{ | |||
template<class T, typename I = std::enable_if_t<gp_config::memory_module::is_ok,int>> | |||
class default_memory_allocator | |||
{ | |||
public: | |||
using pointer_type = T*; | |||
using reference_type = T&; | |||
using const_pointer_type = const T*; | |||
using const_reference_type = const T&; | |||
pointer_type allocate(size_t sz) | |||
{ | |||
return reinterpret_cast <pointer_type> (gp_config::memory_module::memory_allocator<gp_config::memory_module::memory_mode>(sizeof(T) * sz)); | |||
} | |||
void deallocate(pointer_type ptr) | |||
{ | |||
gp_config::memory_module::memory_deallocator<gp_config::memory_module::memory_mode>(ptr); | |||
} | |||
template<typename ...params> | |||
pointer_type construct(pointer_type ptr, params... args) | |||
{ | |||
new(ptr) T(args...); | |||
return ptr; | |||
} | |||
void destroy(pointer_type v) | |||
{ | |||
v->~T(); | |||
} | |||
}; | |||
} | |||
void* operator new(size_t sz) | |||
{ | |||
auto ptr = gp_config::memory_module::memory_allocator<gp_config::memory_module::memory_mode>(sz); | |||
if constexpr (gp_config::has_exceptions) | |||
{ | |||
if(!ptr) | |||
{ | |||
throw gp::bad_alloc{}; | |||
} | |||
} | |||
return ptr; | |||
} | |||
void operator delete (void* ptr) noexcept | |||
{ | |||
gp_config::memory_module::memory_deallocator<gp_config::memory_module::memory_mode>(ptr); | |||
} |
@ -0,0 +1,100 @@ | |||
#pragma once | |||
#include <type_traits> | |||
#include "gp_config.hpp" | |||
#include "gp/exception.hpp" | |||
#include "gp/memory.hpp" | |||
namespace gp{ | |||
struct nullopt_t{}; | |||
constexpr nullopt_t nullopt; | |||
template<typename T, bool B = std::is_final<T>::value || std::is_fundamental<T>::value> | |||
class optional; | |||
template<typename T> | |||
class optional<T,true>{ | |||
bool ready = false; | |||
char buffer[sizeof(T)]; | |||
public: | |||
constexpr optional() | |||
: ready{false} | |||
{} | |||
constexpr optional(nullopt_t) | |||
: ready{false} | |||
{} | |||
constexpr optional(T& value) | |||
: ready{true} | |||
{ | |||
new(buffer) T(value); | |||
} | |||
constexpr optional(T&& value) | |||
: ready{true} | |||
{ | |||
new(buffer) T(std::move(value)); | |||
} | |||
constexpr bool has_value() | |||
{ | |||
return ready; | |||
} | |||
constexpr T& value() | |||
{ | |||
if constexpr (gp_config::has_exceptions) | |||
{ | |||
if(!ready) | |||
{ | |||
throw bad_optional{}; | |||
} | |||
} | |||
return *reinterpret_cast<T*>(buffer); | |||
} | |||
}; | |||
template<typename T> | |||
class optional<T,false>{ | |||
bool ready = false; | |||
void* ptr; | |||
public: | |||
constexpr optional() | |||
: ready{false} | |||
{} | |||
constexpr optional(nullopt_t) | |||
: ready{false} | |||
{} | |||
constexpr optional(T& value) | |||
: ready{true} | |||
{ | |||
ptr = (void*)new T(value); | |||
} | |||
constexpr optional(T&& value) | |||
: ready{true} | |||
{ | |||
ptr = (void*)new T(std::move(value)); | |||
} | |||
constexpr bool has_value() | |||
{ | |||
return ready; | |||
} | |||
constexpr T& value() | |||
{ | |||
if constexpr (gp_config::has_exceptions) | |||
{ | |||
if(!ready) | |||
{ | |||
throw bad_optional{}; | |||
} | |||
} | |||
return *reinterpret_cast<T*>(ptr); | |||
} | |||
}; | |||
} |
@ -0,0 +1,65 @@ | |||
#pragma once | |||
#include "gp/algorithm/tmp_manip.hpp" | |||
namespace gp{ | |||
template<typename it, bool Enable = std::is_same<typename it::difference_type,std::size_t>::value> | |||
class nameless_range; | |||
template<typename it> | |||
class nameless_range<it, false> | |||
{ | |||
it _begin; | |||
it _end; | |||
friend nameless_range<it, true>; | |||
public: | |||
using associated_iterator = it; | |||
nameless_range() = delete; | |||
template<typename othT> | |||
nameless_range(const nameless_range<othT>& oth) | |||
: _begin(oth._begin) | |||
, _end(oth._end) | |||
{} | |||
nameless_range(it sbegin, it send) | |||
: _begin(sbegin) | |||
, _end(send) | |||
{} | |||
it begin() const | |||
{ | |||
return _begin; | |||
} | |||
it end() const | |||
{ | |||
return _end; | |||
} | |||
}; | |||
template<typename it> | |||
class nameless_range<it, true> : public nameless_range<it, false> | |||
{ | |||
public: | |||
nameless_range() = delete; | |||
template<typename othT> | |||
nameless_range(const nameless_range<othT>& oth) | |||
: nameless_range<it,false>(oth._begin,oth._end) | |||
{} | |||
nameless_range(it sbegin, it send) | |||
: nameless_range<it,false>(sbegin, send) | |||
{} | |||
std::size_t size() const | |||
{ | |||
return this->_end-this->_begin; | |||
} | |||
}; | |||
} | |||
@ -0,0 +1,182 @@ | |||
#pragma once | |||
#include <gp/algorithm/tmp_manip.hpp> | |||
#include <type_traits> | |||
#include <new> | |||
#include "gp_config.hpp" | |||
#include "gp/exception.hpp" | |||
#include "gp/memory.hpp" | |||
#include "gp/function.hpp" | |||
namespace gp{ | |||
template< typename Enable, typename ...T> | |||
class variant; | |||
template<typename ...T> | |||
class variant<typename std::enable_if<!gp_config::memory_module::is_ok && all_of_fixed_size<T...>::value,int>::type, T...>{ | |||
std::size_t index = std::numeric_limits<std::size_t>::max(); | |||
char buffer[max_size<T...>]; | |||
gp::function<void(void*)> dtor = [](void*){}; | |||
public: | |||
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type> | |||
constexpr variant(U& value) | |||
: index{r_index_of<U, T...>::value} | |||
{ | |||
new(buffer) U(value); | |||
dtor = gp::function([](void* thing){((U*)thing)->~U();}); | |||
} | |||
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type> | |||
constexpr variant(U&& value) | |||
: index{r_index_of<U, T...>::value} | |||
{ | |||
new(buffer) U(std::move(value)); | |||
dtor = gp::function([](void* thing){((U*)thing)->~U();}); | |||
} | |||
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type> | |||
void operator=(U& value) | |||
{ | |||
if(index != std::numeric_limits<std::size_t>::max()) | |||
{ | |||
dtor((void*)buffer); | |||
} | |||
index = r_index_of<U, T...>::value; | |||
new(buffer) U(value); | |||
dtor = gp::function([](void* thing){((U*)thing)->~U();}); | |||
} | |||
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type> | |||
void operator=(U&& value) | |||
{ | |||
if(index != std::numeric_limits<std::size_t>::max()) | |||
{ | |||
dtor((void*)buffer); | |||
} | |||
index = r_index_of<U, T...>::value; | |||
new(buffer) U(std::move(value)); | |||
dtor = gp::function([](void* thing){((U*)thing)->~U();}); | |||
} | |||
~variant() | |||
{ | |||
if(index != std::numeric_limits<std::size_t>::max()) | |||
{ | |||
dtor((void*)buffer); | |||
} | |||
} | |||
template<typename U> | |||
constexpr U& value() | |||
{ | |||
if constexpr (gp_config::has_exceptions) | |||
{ | |||
if(r_index_of<U, T...>::value != index) | |||
{ | |||
throw bad_variant_access<U>{}; | |||
} | |||
} | |||
return *reinterpret_cast<U*>(buffer); | |||
} | |||
template<typename U> | |||
constexpr U& is_a() | |||
{ | |||
if(r_index_of<U, T...>::value == index) | |||
{ | |||
return true; | |||
} | |||
else | |||
{ | |||
return false; | |||
} | |||
} | |||
}; | |||
template<typename ...T> | |||
class variant<typename std::enable_if<gp_config::memory_module::is_ok,default_memory_allocator<>>::type, T...>{ | |||
std::size_t index = std::numeric_limits<std::size_t>::max(); | |||
void* ptr; | |||
gp::function<void(void*)> dtor = [](void*){}; | |||
public: | |||
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type> | |||
constexpr variant(U& value) | |||
: index{r_index_of<U, T...>::value} | |||
{ | |||
ptr = (void*)new(default_memory_allocator<>{}.allocate(sizeof(U))) U(value); | |||
dtor = gp::function([](void* thing){((U*)thing)->~U();}); | |||
} | |||
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type> | |||
constexpr variant(U&& value) | |||
: index{r_index_of<U, T...>::value} | |||
{ | |||
ptr = (void*)new(default_memory_allocator<>{}.allocate(sizeof(U))) U(std::move(value)); | |||
dtor = gp::function([](void* thing){((U*)thing)->~U();}); | |||
} | |||
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type> | |||
void operator=(U& value) | |||
{ | |||
if(index != std::numeric_limits<std::size_t>::max()) | |||
{ | |||
dtor(ptr); | |||
default_memory_allocator<>{}.deallocate(ptr); | |||
} | |||
index = r_index_of<U, T...>::value; | |||
ptr = (void*)new(default_memory_allocator<>{}.allocate(sizeof(U))) U(value); | |||
dtor = gp::function([](void* thing){((U*)thing)->~U();}); | |||
} | |||
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type> | |||
void operator=(U&& value) | |||
{ | |||
if(index != std::numeric_limits<std::size_t>::max()) | |||
{ | |||
dtor(ptr); | |||
default_memory_allocator<>{}.deallocate(ptr); | |||
} | |||
index = r_index_of<U, T...>::value; | |||
ptr = (void*)new(default_memory_allocator<>{}.allocate(sizeof(U))) U(std::move(value)); | |||
dtor = gp::function([](void* thing){((U*)thing)->~U();}); | |||
} | |||
~variant() | |||
{ | |||
if(index != std::numeric_limits<std::size_t>::max()) | |||
{ | |||
dtor(ptr); | |||
default_memory_allocator<>{}.deallocate(ptr); | |||
} | |||
} | |||
template<typename U> | |||
constexpr U& value() | |||
{ | |||
if constexpr (gp_config::has_exceptions) | |||
{ | |||
if(r_index_of<U, T...>::value != index) | |||
{ | |||
throw bad_variant_access<U>{}; | |||
} | |||
} | |||
return *reinterpret_cast<U*>(ptr); | |||
} | |||
template<typename U> | |||
constexpr U& is_a() | |||
{ | |||
if(r_index_of<U, T...>::value == index) | |||
{ | |||
return true; | |||
} | |||
else | |||
{ | |||
return false; | |||
} | |||
} | |||
}; | |||
} |
@ -0,0 +1,64 @@ | |||
#pragma once | |||
#include <cstdint> | |||
#include <cstddef> | |||
#include <cstdlib> | |||
#include <type_traits> | |||
namespace gp_config{ | |||
namespace memory_module{ | |||
enum class memory_mode_t{ | |||
other, | |||
clib, | |||
buffer, | |||
arena_buffer | |||
}; | |||
constexpr memory_mode_t memory_mode = memory_mode_t::clib; | |||
template<memory_mode_t T = memory_mode_t::other> | |||
constexpr void*(*memory_allocator)(std::size_t)=nullptr; | |||
template<memory_mode_t T = memory_mode_t::other> | |||
constexpr void(*memory_deallocator)(void*)=nullptr; | |||
// C Standard library memory usage | |||
template<> | |||
constexpr void*(*memory_allocator<memory_mode_t::clib>)(std::size_t) = malloc; | |||
template<> | |||
constexpr void(*memory_deallocator<memory_mode_t::clib>)(void*) = free; | |||
// Buffer memory usage only | |||
template<> | |||
constexpr void*(*memory_allocator<memory_mode_t::buffer>)(std::size_t) = nullptr; | |||
template<> | |||
constexpr void(*memory_deallocator<memory_mode_t::buffer>)(void*) = nullptr; | |||
// Buffer of arena memory usage | |||
template<> | |||
constexpr void*(*memory_allocator<memory_mode_t::arena_buffer>)(std::size_t) = nullptr; | |||
template<> | |||
constexpr void(*memory_deallocator<memory_mode_t::arena_buffer>)(void*) = nullptr; | |||
constexpr bool is_ok = | |||
( memory_allocator<memory_mode> != nullptr ) | |||
&& ( memory_deallocator<memory_mode> != nullptr ); | |||
} | |||
constexpr bool has_exceptions = true; | |||
// Value of 8 is considered not cryptographically secure | |||
// Value of 12 offers a good compromise of performance and robustness | |||
// Value of 20 offers maximum robustness | |||
constexpr size_t arc4random_strength = 20; | |||
constexpr size_t assert_buffer_size = 0; | |||
constexpr auto assert = [](bool, const char*) -> void{}; | |||
/** Simple exit assert | |||
constexpr auto assert = [](bool pred, const char*) -> void | |||
{ | |||
if(pred) | |||
return; | |||
else | |||
std::exit(-1);}; | |||
*/ | |||
} |
@ -0,0 +1,132 @@ | |||
#pragma once | |||
#include <stdint.h> | |||
#include <stddef.h> | |||
#include <algorithm> | |||
#include <array> | |||
template<typename word_t> | |||
size_t lg(word_t v); | |||
/** | |||
Sean Eron Anderson | |||
seander@cs.stanford.edu | |||
**/ | |||
template<> | |||
size_t lg<uint32_t>(uint32_t v) | |||
{ | |||
static const int MultiplyDeBruijnBitPosition[32] = | |||
{ | |||
0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, | |||
8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 | |||
}; | |||
v |= v >> 1; | |||
v |= v >> 2; | |||
v |= v >> 4; | |||
v |= v >> 8; | |||
v |= v >> 16; | |||
return MultiplyDeBruijnBitPosition[(uint32_t)(v * 0x07C4ACDDU) >> 27]; | |||
} | |||
template<> | |||
size_t lg<uint64_t>(uint64_t v) | |||
{ | |||
static const int MultiplyDeBruijnBitPosition[64] = | |||
{ | |||
0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61, | |||
51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62, | |||
57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56, | |||
45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63 | |||
}; | |||
v |= v >> 1; | |||
v |= v >> 2; | |||
v |= v >> 4; | |||
v |= v >> 8; | |||
v |= v >> 16; | |||
v |= v >> 32; | |||
return MultiplyDeBruijnBitPosition[(uint64_t)(v * 0x03f6eaf2cd271461) >> 58]; | |||
} | |||
template<typename word_t = uint32_t, size_t r = 20, size_t b = 128, word_t P = 0xB7E15163, word_t Q = 0x9E3779B9> | |||
class RC6 { | |||
static word_t r_l(const word_t& w, size_t v) { | |||
return (w << v) | ( w >> (sizeof(w)-v)); | |||
} | |||
static word_t r_r(const word_t& w, size_t v) { | |||
return (w >> v) | ( w << (sizeof(w)-v)); | |||
} | |||
class RC6_KeySched { | |||
public: | |||
static constexpr size_t c = b/sizeof(word_t)/8; | |||
static constexpr size_t v_3 = std::max(c, 2*r+4); | |||
static constexpr size_t v = v_3*3; | |||
private: | |||
std::array<word_t, v_3> S; | |||
public: | |||
RC6_KeySched(std::array<word_t, c> L) | |||
{ | |||
S[0] = P; | |||
for(size_t i = 1; i < 2*r+3; ++i) | |||
{ | |||
S[i] = S[i - 1] + Q; | |||
} | |||
word_t A = 0; | |||
word_t B = 0; | |||
word_t i = 0; | |||
word_t j = 0; | |||
for(size_t s = 1; s < v; ++s) | |||
{ | |||
A = S[i] = r_l( S[i] + A + B, 3 ); | |||
B = L[j] = r_l( L[j] + A + B, (A + B)%(8*sizeof(word_t))); | |||
i = (i + 1) % (2*r+4); | |||
j = (j + 1) % c; | |||
} | |||
} | |||
const word_t& operator[](const size_t pos) { | |||
return S[pos]; | |||
} | |||
}; | |||
RC6_KeySched S; | |||
public: | |||
typedef std::array<word_t, RC6_KeySched::c> key_type; | |||
typedef std::array<word_t, 4> block_type; | |||
RC6(const key_type& key) | |||
: S(key) | |||
{} | |||
void encrypt(block_type& plaintext) { | |||
auto& A = plaintext[0]; | |||
auto& B = plaintext[1]; | |||
auto& C = plaintext[2]; | |||
auto& D = plaintext[3]; | |||
B += S[0]; | |||
D += S[1]; | |||
for(size_t i = 1; i < r; ++i) | |||
{ | |||
auto t = r_l( B * ( 2 * B + 1 ), 5); | |||
auto u = r_l( D * ( 2 * D + 1 ), 5); | |||
A = ((A ^ t) << u%(8*sizeof(word_t))) + S[2*i]; | |||
C = ((C ^ u) << t%(8*sizeof(word_t))) + S[2*i+1]; | |||
std::rotate(plaintext.begin(), plaintext.begin()+1, plaintext.end()); | |||
} | |||
A += S[2*r+3]; | |||
C += S[2*r+2]; | |||
} | |||
}; |
@ -0,0 +1,111 @@ | |||
#include "test_scaffold.h" | |||
#include <random> | |||
#include <string> | |||
#include "gp/bloomfilter.hpp" | |||
typedef std::linear_congruential_engine<uint_fast64_t, 128273, 13, 2147483647> cheap_rand; | |||
typedef std::linear_congruential_engine<uint_fast64_t, 69857, 87541, 2147483647> cheap_rand_bis; | |||
struct bfilter_test : public test_scaffold { | |||
uint32_t seed; | |||
bfilter_test() { | |||
seed = std::random_device{}(); | |||
name = __FILE__ ":1_seed"; | |||
name += std::to_string(seed); | |||
} | |||
virtual int run() { | |||
cheap_rand setter(seed); | |||
cheap_rand getter(seed); | |||
gp::bloomfilter test_filter; | |||
for(int a = 0 ; a < 100; a++) | |||
{ | |||
test_filter.set_hash(setter()); | |||
} | |||
bool result = true; | |||
for(int a = 0 ; a < 100; a++) | |||
{ | |||
result *= test_filter.test_hash(getter()); | |||
} | |||
return !result; | |||
} | |||
}; | |||
append_test dummy_r21fg6r43(new bfilter_test{}); | |||
struct bfilter2_test : public test_scaffold { | |||
uint32_t seedA; | |||
uint32_t seedB; | |||
bfilter2_test() { | |||
seedA = std::random_device{}(); | |||
seedB = std::random_device{}(); | |||
name = __FILE__ ":2_seedA"; | |||
name += std::to_string(seedA); | |||
name += "&seedB"; | |||
name += std::to_string(seedB); | |||
} | |||
virtual int run() { | |||
cheap_rand setter(seedA); | |||
cheap_rand_bis getter(seedB); | |||
gp::bloomfilter test_filter; | |||
for(int a = 0 ; a < 10000; a++) | |||
{ | |||
test_filter.set_hash(setter()); | |||
} | |||
int interference = 0; | |||
for(int a = 0 ; a < 10000; a++) | |||
{ | |||
interference += test_filter.test_hash(getter()); | |||
} | |||
return interference >= 550; | |||
} | |||
}; | |||
append_test dummy_r2gflu3(new bfilter2_test{}); | |||
struct bfilter3_test : public test_scaffold { | |||
uint32_t seed; | |||
bfilter3_test() { | |||
seed = std::random_device{}(); | |||
name = __FILE__ ":3_seed"; | |||
name += std::to_string(seed); | |||
} | |||
virtual int run() { | |||
cheap_rand setter(seed); | |||
cheap_rand getter(seed); | |||
gp::bloomfilter<uint32_t, 19, true> test_filter; | |||
for(int a = 0 ; a < 1000; a++) | |||
{ | |||
test_filter.set_hash(setter()); | |||
} | |||
bool result = true; | |||
for(int a = 0 ; a < 1000; a++) | |||
{ | |||
result *= test_filter.test_hash(getter()); | |||
} | |||
return !result; | |||
} | |||
}; | |||
append_test dummy_56489flu3(new bfilter3_test{}); |
@ -0,0 +1,78 @@ | |||
#include "test_scaffold.h" | |||
#include "gp/array.hpp" | |||
#include <thread> | |||
#include <chrono> | |||
#include <numeric> | |||
#include <iomanip> | |||
#include <fstream> | |||
struct arraysum_test : public test_scaffold { | |||
arraysum_test() { | |||
name = __FILE__ ":1"; | |||
} | |||
virtual int run() { | |||
gp::array<uint32_t, 16> test; | |||
for(auto& elem : test) | |||
{ | |||
elem = 12; | |||
} | |||
return std::accumulate(test.begin(), test.end(), 0) != 12*test.size(); | |||
} | |||
}; | |||
append_test dummy_sd45uisd3(new arraysum_test{}); | |||
struct optional_test : public test_scaffold { | |||
optional_test() { | |||
name = __FILE__ ":1"; | |||
} | |||
virtual int run() { | |||
int res = 0; | |||
{ | |||
gp::optional<uint32_t> test; | |||
if(test.has_value()) | |||
{ | |||
res++; | |||
} | |||
test = 12; | |||
if(test.has_value()) | |||
{ | |||
if(test.value()!=12) | |||
{ | |||
res++; | |||
} | |||
} | |||
else | |||
{ | |||
res++; | |||
} | |||
} | |||
{ | |||
gp::optional<std::ifstream> test; | |||
if(test.has_value()) | |||
{ | |||
res++; | |||
} | |||
test = std::ifstream("/proc/cpuinfo"); | |||
if(!test.has_value()) | |||
{ | |||
res++; | |||
} | |||
} | |||
return res; | |||
} | |||
}; | |||
append_test dummy_mlyusisd3(new optional_test{}); |
@ -0,0 +1,43 @@ | |||
#include "rc6_generic.hpp" | |||
#include "test_scaffold.h" | |||
#include <iostream> | |||
#include <ios> | |||
struct RC6test : public test_scaffold { | |||
RC6test() { | |||
name = __FILE__ ":1"; | |||
} | |||
virtual int run() { | |||
using rc = RC6<uint32_t, 20, 128>; | |||
rc::key_type key = {0,0,0,0}; | |||
rc::block_type plaintext = {0,0,0,0}; | |||
rc::block_type expected{0x8fc3a536,0x56b1f778,0xc129df4e,0x9848a41e}; | |||
std::cout<<"plain:"; | |||
for(auto a : plaintext) | |||
std::cout << std::hex << a; | |||
auto cipher = rc(key); | |||
cipher.encrypt(plaintext); | |||
std::cout<<"\nkey__:"; | |||
for(auto a : key) | |||
std::cout << std::hex << a; | |||
std::cout<<"\nciphe:"; | |||
for(auto a : plaintext) | |||
std::cout << std::hex << a; | |||
std::cout<<"\nexpec:"; | |||
for(auto a : expected) | |||
std::cout << std::hex << a; | |||
std::cout << std::endl; | |||
return plaintext != expected; | |||
} | |||
}; | |||
append_test dummy_szfhu5463(new RC6test{}); |