-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
392 additions
and
430 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
#pragma once | ||
|
||
#include <list> | ||
#include <optional> | ||
|
||
#include "detail/node.hpp" | ||
|
||
namespace efesx { | ||
namespace queue { | ||
namespace detail | ||
{ | ||
|
||
|
||
class list_storage { | ||
private: | ||
std::list<node> store; | ||
public: | ||
list_storage() = default; | ||
list_storage(const list_storage&) = delete; | ||
list_storage(list_storage&&) = delete; | ||
list_storage& operator=(list_storage&&) = delete; | ||
~list_storage() = default; | ||
|
||
template<typename...Args> | ||
void insert(Args...args){ | ||
store.emplace_back(args...); | ||
store.sort(); | ||
} | ||
|
||
template<typename T = bool> | ||
std::optional<T> extract(void* buf = nullptr){ | ||
if(store.size() == 0) { | ||
return std::optional<T>{}; | ||
} | ||
|
||
node& val = store.front(); | ||
|
||
if(!val.has_value() || val.size() == 0){ | ||
return std::optional<T>{}; | ||
} | ||
|
||
if (buf != nullptr){ | ||
val.blob_copy(buf); | ||
return std::optional<T>{}; | ||
} | ||
|
||
try{ | ||
return val.value_cast<T>(); | ||
} catch (std::runtime_error& e){ | ||
return std::optional<T>{}; | ||
} | ||
|
||
} | ||
|
||
void pop(){ | ||
store.pop_front(); | ||
} | ||
|
||
template<typename T> | ||
std::optional<T> extract_with_type(void* buf = nullptr){ | ||
throw std::runtime_error("Not Yet Implemented Error"); | ||
} | ||
|
||
|
||
|
||
}; | ||
|
||
|
||
|
||
}; // namespace detail | ||
}; // namespace queue | ||
}; // namespace efesxzc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,160 +1,124 @@ | ||
#pragma once | ||
|
||
#include <cstring> | ||
|
||
#include "types.hpp" | ||
#include "meta.hpp" | ||
|
||
namespace efesx { | ||
namespace queue { | ||
namespace detail { | ||
|
||
class node { | ||
struct node { | ||
private: | ||
union node_value | ||
{ | ||
int int_value; | ||
bool bool_value; | ||
char char_value; | ||
std::string* string_value; | ||
std::vector<node>* array_value; | ||
|
||
std::size_t v_size; | ||
|
||
node_value() = default; | ||
node_value(const node_value&) = default; | ||
node_value(node_value&& oth) = default; | ||
|
||
node_value(int v) : int_value(v) {} | ||
node_value(bool v) : bool_value(v) {} | ||
node_value(char v) : char_value(v) {} | ||
|
||
node_value(value_t t, std::size_t size) { | ||
switch (t) | ||
{ | ||
case value_t::container_t: { | ||
array_value = create<std::vector<node>>(); | ||
array_value->reserve(size); | ||
break; | ||
} | ||
|
||
default: break; | ||
} | ||
} | ||
|
||
node_value(const std::string& v) : string_value(create<std::string>(v)) {} | ||
node_value(const std::string&& v) : string_value(create<std::string>(std::move(v))) {} | ||
|
||
template<typename T, std::enable_if_t<std::is_pointer_v<T>, int> = 0> | ||
node_value(T arr, std::size_t size) { | ||
array_value = create<std::vector<node>>(); | ||
array_value->reserve(size); | ||
|
||
for (auto i = 0; i < size; i++){ | ||
array_value->emplace_back(arr[i]); | ||
} | ||
} | ||
const uint8_t m_priority = 0; | ||
const value_t m_type; | ||
const std::size_t m_size; | ||
void* m_data; | ||
|
||
template<typename T, typename... Args> | ||
static T* create(Args&& ... args){ | ||
T* create(Args&& ... args){ | ||
using allocator_traits = std::allocator_traits<std::allocator<T>>; | ||
|
||
std::allocator<T> alloc; | ||
|
||
|
||
auto deleter = [&](T* obj){ | ||
allocator_traits::deallocate(alloc, obj, 1); | ||
}; | ||
|
||
std::unique_ptr<T, decltype(deleter)> obj(allocator_traits::allocate(alloc, 1), deleter); | ||
allocator_traits::construct(alloc, obj.get(), std::forward<Args>(args)...); | ||
return obj.release(); | ||
} | ||
|
||
void destroy(value_t t) { | ||
switch (t) | ||
{ | ||
case value_t::string_t: { | ||
std::allocator<std::string> alloc; | ||
std::allocator_traits<decltype(alloc)>::destroy(alloc, string_value); | ||
std::allocator_traits<decltype(alloc)>::deallocate(alloc, string_value, 1); | ||
break; | ||
} | ||
case value_t::array_t: { | ||
std::allocator<std::vector<node>> alloc; | ||
std::allocator_traits<decltype(alloc)>::destroy(alloc, array_value); | ||
std::allocator_traits<decltype(alloc)>::deallocate(alloc, array_value, 1); | ||
break; | ||
} | ||
|
||
default: break; | ||
} | ||
template<typename T> | ||
void destroy(T* mem, std::size_t size){ | ||
std::allocator<T> alloc; | ||
std::allocator_traits<decltype(alloc)>::destroy(alloc, mem); | ||
std::allocator_traits<decltype(alloc)>::deallocate(alloc, mem, size); | ||
m_data = nullptr; | ||
} | ||
}; | ||
public: | ||
value_t m_type; | ||
value_t m_subtype; | ||
node() : m_type(value_t::null), m_size(0), m_data(nullptr) {} | ||
|
||
node(const node&) = delete; | ||
node(node&&) = delete; | ||
node& operator=(node&&) = delete; | ||
~node(){ | ||
if (m_type == value_t::blob) { | ||
std::free(m_data); | ||
return; | ||
} | ||
destroy<uint8_t>(static_cast<uint8_t*>(m_data), m_size); | ||
} | ||
|
||
node_value m_data; | ||
template<IsIntegral T, uint8_t Size = sizeof(T)> | ||
node(const T& val) : m_size(Size), m_type(value_t::integer), m_data(create<T>(val)) | ||
{} | ||
|
||
// ARRAY | ||
template<typename T, std::enable_if_t<std::is_pointer_v<T>, int> = 0> requires (!Container<T>) | ||
node(const T val, std::size_t size, std::size_t priority = 0) : | ||
m_data(val, size), | ||
m_type(value_t::array_t), | ||
m_subtype(detector<std::remove_const_t<std::remove_pointer_t<T>>>::type) | ||
template<IsFloating T, uint8_t Size = sizeof(T)> | ||
node(const T& val) : m_size(Size), m_type(value_t::floating), m_data(create<T>(val)) | ||
{} | ||
|
||
// ANOTHER ALL | ||
template<typename T, std::enable_if_t<std::is_fundamental_v<T> && !std::is_pointer_v<T>, int> = 0> | ||
node(T val, std::size_t priority = 0) : | ||
m_data(val), | ||
m_type(detector<T>::type) | ||
template<IsString T> | ||
node(const T& val) : m_size(val.size()), m_type(value_t::text), m_data(create<T>(val)) | ||
{} | ||
|
||
// STRING | ||
template<typename T, std::enable_if_t<std::is_same_v<std::string, std::remove_cv_t<T>>, int> = 0> | ||
node(T val, std::size_t priority = 0) : | ||
m_data(val), | ||
m_type(detector<T>::type) | ||
node(const char* val, std::size_t _size) : m_size(_size), m_type(value_t::text), m_data(create<std::string>(std::string(val, _size))) | ||
{} | ||
|
||
// CONTAINERS | ||
template<Container T> | ||
node(const T& container, std::size_t priority = 0) : | ||
m_data(value_t::container_t, container.size()), | ||
m_type(value_t::container_t) | ||
{ | ||
for (auto it = container.begin(); it != container.end(); it++){ | ||
m_data.array_value->emplace_back(*it, priority); | ||
node(const void* val, std::size_t _size) : m_size(_size), m_type(value_t::blob), m_data(std::malloc(_size)) { | ||
std::memcpy(m_data, val, _size); | ||
} | ||
|
||
template<typename T> | ||
T&& value_cast(){ | ||
if (m_data == nullptr){ | ||
throw std::runtime_error("Node Value Is Empty"); | ||
} | ||
|
||
if ((IsIntegral<T> && (m_type != value_t::integer)) || | ||
(IsFloating<T> && (m_type != value_t::floating))|| | ||
(IsString<T> && (m_type != value_t::text))) | ||
{ | ||
throw std::runtime_error("Bad Node Value Cast"); | ||
} | ||
|
||
return std::forward<T&&>(*static_cast<T*>(m_data)); | ||
} | ||
|
||
|
||
node(const node&) = default; | ||
node(node&& oth) = default; | ||
void blob_copy(void *dst){ | ||
std::memcpy(dst, m_data, m_size); | ||
} | ||
|
||
~node() { | ||
m_data.destroy(m_type); | ||
std::size_t size(){ | ||
return m_size; | ||
} | ||
|
||
// ANOTHER ALL | ||
template<typename T, std::enable_if_t<std::is_fundamental_v<T> && !std::is_pointer_v<T>, int> = 0> | ||
void restore(T& data){ | ||
data = m_data.int_value; | ||
bool has_value(){ | ||
return (m_data != nullptr); | ||
} | ||
|
||
// STRING | ||
template<typename T, std::enable_if_t<std::is_same_v<std::string, std::remove_cv_t<T>>, int> = 0> | ||
void restore(T& data){ | ||
data = *m_data.string_value; | ||
value_t value_type(){ | ||
return m_type; | ||
} | ||
|
||
// ARRAY | ||
template<typename T, std::enable_if_t<std::is_pointer_v<T>, int> = 0> requires (!Container<T>) | ||
void restore(T val) { | ||
std::size_t idx = 0; | ||
for (auto it = m_data.array_value->begin(); it != m_data.array_value->end(); it++){ | ||
it->restore(val[idx]); | ||
idx++; | ||
} | ||
uint8_t priority(){ | ||
return m_priority; | ||
} | ||
|
||
bool operator<(node& rhs){ | ||
return (m_priority > rhs.m_priority); | ||
} | ||
}; | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
}; // namespace detail | ||
}; // namespace queue | ||
}; // namespace efesx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.