intial commit
This commit is contained in:
75
source/mijin/util/bitarray.hpp
Normal file
75
source/mijin/util/bitarray.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_UTIL_BITARRAY_HPP_INCLUDED)
|
||||
#define MIJIN_UTIL_BITARRAY_HPP_INCLUDED 1
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
|
||||
template<std::size_t numBits, bool threadSafe = false>
|
||||
struct BitArray
|
||||
{
|
||||
private:
|
||||
using byte_type = std::conditional_t<threadSafe, std::atomic_uint8_t, std::uint8_t>;
|
||||
std::array<byte_type, (numBits + 7) / 8> bytes;
|
||||
public:
|
||||
[[nodiscard]] bool get(std::size_t index) const {
|
||||
assert(index < numBits);
|
||||
return (bytes[index / 8] & (1 << (index % 8)));
|
||||
}
|
||||
void set(std::size_t index, bool value)
|
||||
{
|
||||
byte_type& byte = bytes[index / 8];
|
||||
const std::uint8_t mask = (1 << (index % 8));
|
||||
if constexpr (threadSafe)
|
||||
{
|
||||
std::uint8_t oldByte = byte.load(std::memory_order_relaxed);
|
||||
std::uint8_t newByte = 0;
|
||||
do
|
||||
{
|
||||
if (value) {
|
||||
newByte = oldByte | mask;
|
||||
}
|
||||
else {
|
||||
newByte = oldByte & ~mask;
|
||||
}
|
||||
} while (!byte.compare_exchange_weak(oldByte, newByte, std::memory_order_release, std::memory_order_relaxed));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value) {
|
||||
byte |= mask;
|
||||
}
|
||||
else {
|
||||
byte &= ~mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_UTIL_BITARRAY_HPP_INCLUDED)
|
||||
92
source/mijin/util/bitflags.hpp
Normal file
92
source/mijin/util/bitflags.hpp
Normal file
@@ -0,0 +1,92 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_UTIL_BITFLAGS_HPP_INCLUDED)
|
||||
#define MIJIN_UTIL_BITFLAGS_HPP_INCLUDED 1
|
||||
|
||||
#include <bit>
|
||||
#include <cstddef>
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
template<typename TBits>
|
||||
struct BitFlags
|
||||
{
|
||||
constexpr TBits& operator |=(const BitFlags& other) {
|
||||
for (std::size_t idx = 0; idx < sizeof(TBits); ++idx) {
|
||||
*(std::bit_cast<std::byte*>(asBits()) + idx) |= *(std::bit_cast<const std::byte*>(other.asBits()) + idx);
|
||||
}
|
||||
return *asBits();
|
||||
}
|
||||
constexpr TBits& operator &=(const BitFlags& other) {
|
||||
for (std::size_t idx = 0; idx < sizeof(TBits); ++idx) {
|
||||
*(std::bit_cast<std::byte*>(asBits()) + idx) &= *(std::bit_cast<const std::byte*>(other.asBits()) + idx);
|
||||
}
|
||||
return *asBits();
|
||||
}
|
||||
|
||||
constexpr TBits& operator ^=(const BitFlags& other) {
|
||||
for (std::size_t idx = 0; idx < sizeof(TBits); ++idx) {
|
||||
*(std::bit_cast<std::byte*>(asBits()) + idx) ^= *(std::bit_cast<const std::byte*>(other.asBits()) + idx);
|
||||
}
|
||||
return *asBits();
|
||||
}
|
||||
|
||||
constexpr TBits operator& (const BitFlags& other) const
|
||||
{
|
||||
TBits copy(*asBits());
|
||||
copy &= other;
|
||||
return copy;
|
||||
}
|
||||
|
||||
constexpr TBits operator| (const BitFlags& other) const
|
||||
{
|
||||
TBits copy(*asBits());
|
||||
copy |= other;
|
||||
return copy;
|
||||
}
|
||||
|
||||
constexpr TBits operator^ (const BitFlags& other) const
|
||||
{
|
||||
TBits copy(*asBits());
|
||||
copy ^= other;
|
||||
return copy;
|
||||
}
|
||||
|
||||
constexpr operator bool() const {
|
||||
for (std::size_t idx = 0; idx < sizeof(TBits); ++idx) {
|
||||
if (*(std::bit_cast<const std::byte*>(asBits()) + idx) != std::byte(0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr bool operator!() const {
|
||||
return !static_cast<bool>(*this);
|
||||
}
|
||||
private:
|
||||
constexpr TBits* asBits() { return static_cast<TBits*>(this); }
|
||||
constexpr const TBits* asBits() const { return static_cast<const TBits*>(this); }
|
||||
};
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_UTIL_BITFLAGS_HPP_INCLUDED)
|
||||
48
source/mijin/util/concepts.hpp
Normal file
48
source/mijin/util/concepts.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_UTIL_CONCEPTS_HPP_INCLUDED)
|
||||
#define MIJIN_UTIL_CONCEPTS_HPP_INCLUDED 1
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
template<typename T>
|
||||
concept standard_type = std::is_standard_layout_v<T>;
|
||||
|
||||
template<typename T>
|
||||
concept trivial_type = std::is_trivial_v<T>;
|
||||
|
||||
template<typename T>
|
||||
concept enum_type = std::is_enum_v<T>;
|
||||
|
||||
template<typename T>
|
||||
concept arithmetic_type = std::is_arithmetic_v<T>;
|
||||
|
||||
template<typename T>
|
||||
concept pointer_type = std::is_pointer_v<T>;
|
||||
|
||||
template<typename T>
|
||||
concept reference_type = std::is_reference_v<T>;
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_UTIL_CONCEPTS_HPP_INCLUDED)
|
||||
161
source/mijin/util/flag.hpp
Normal file
161
source/mijin/util/flag.hpp
Normal file
@@ -0,0 +1,161 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_UTIL_FLAG_HPP_INCLUDED)
|
||||
#define MIJIN_UTIL_FLAG_HPP_INCLUDED 1
|
||||
|
||||
#include <cstdint>
|
||||
#include "./traits.hpp"
|
||||
#include "./types.hpp"
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
#define MIJIN_DEFINE_FLAG(name) \
|
||||
struct name : Flag \
|
||||
{ \
|
||||
private: \
|
||||
struct Proxy_ { \
|
||||
uint8_t value; \
|
||||
}; \
|
||||
public: \
|
||||
constexpr name() = default; \
|
||||
constexpr name(const name&) = default; \
|
||||
constexpr name(Proxy_ proxy) \
|
||||
: Flag(proxy.value) {} \
|
||||
constexpr explicit name(bool value) noexcept \
|
||||
: Flag(value) {} \
|
||||
name& operator=(const name&) = default; \
|
||||
static constexpr Proxy_ YES{1}; \
|
||||
static constexpr Proxy_ NO{0}; \
|
||||
}
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
struct Flag
|
||||
{
|
||||
std::uint8_t value;
|
||||
|
||||
Flag() = default;
|
||||
Flag(const Flag&) = default;
|
||||
explicit constexpr Flag(uint8_t value) noexcept : value(value) {}
|
||||
|
||||
Flag& operator=(const Flag&) = default;
|
||||
|
||||
constexpr bool operator ==(const Flag& other) const noexcept
|
||||
{
|
||||
return value == other.value;
|
||||
}
|
||||
constexpr bool operator !=(const Flag& other) const noexcept
|
||||
{
|
||||
return value != other.value;
|
||||
}
|
||||
constexpr bool operator !() const noexcept
|
||||
{
|
||||
return !value;
|
||||
}
|
||||
constexpr operator bool() const noexcept
|
||||
{
|
||||
return value != 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
concept FlagType = requires (T& value)
|
||||
{
|
||||
value = T::YES;
|
||||
value = T::NO;
|
||||
};
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template<std::size_t offset, FlagType... TFlags>
|
||||
class FlagSetStorage;
|
||||
|
||||
template<std::size_t offset, FlagType TFirst, FlagType... TMore>
|
||||
class FlagSetStorage<offset, TFirst, TMore...> : public FlagSetStorage<offset + 1, TMore...>
|
||||
{
|
||||
private:
|
||||
using base_t = FlagSetStorage<offset + 1, TMore...>;
|
||||
static constexpr typename base_t::data_t BIT = (1 << offset);
|
||||
public:
|
||||
constexpr void set(TFirst value) noexcept
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
base_t::data_ |= BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
base_t::data_ &= ~BIT;
|
||||
}
|
||||
}
|
||||
constexpr bool get(TFirst) noexcept
|
||||
{
|
||||
return (base_t::data_ & BIT) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<std::size_t offset>
|
||||
class FlagSetStorage<offset>
|
||||
{
|
||||
protected:
|
||||
using data_t = uint_next_t<offset>;
|
||||
protected:
|
||||
data_t data_ = data_t(0);
|
||||
};
|
||||
} // namespace impl
|
||||
|
||||
template<FlagType... TFlags>
|
||||
class FlagSet
|
||||
{
|
||||
private:
|
||||
using storage_t = impl::FlagSetStorage<0, TFlags...>;
|
||||
private:
|
||||
storage_t storage_;
|
||||
public:
|
||||
FlagSet() = default;
|
||||
FlagSet(const FlagSet&) = default;
|
||||
template<FlagType... TFlags2>
|
||||
constexpr FlagSet(TFlags2... flags)
|
||||
{
|
||||
(set(flags), ...);
|
||||
}
|
||||
public:
|
||||
FlagSet& operator=(const FlagSet&) = default;
|
||||
template<FlagType T> requires is_any_type_v<T, TFlags...>
|
||||
FlagSet& operator=(T flag) noexcept
|
||||
{
|
||||
reset(flag);
|
||||
return *this;
|
||||
}
|
||||
template<FlagType T> requires is_any_type_v<T, TFlags...>
|
||||
FlagSet& operator|=(T flag) noexcept
|
||||
{
|
||||
set(flag);
|
||||
return *this;
|
||||
}
|
||||
template<FlagType T> requires is_any_type_v<T, TFlags...>
|
||||
FlagSet& operator&=(T flag) noexcept
|
||||
{
|
||||
unset(flag);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_UTIL_FLAG_HPP_INCLUDED)
|
||||
47
source/mijin/util/os.cpp
Normal file
47
source/mijin/util/os.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
#include "os.hpp"
|
||||
|
||||
#include "../detect.hpp"
|
||||
|
||||
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
|
||||
#include <pthread.h>
|
||||
#elif MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
|
||||
// TODO
|
||||
#endif
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// internal defines
|
||||
//
|
||||
|
||||
//
|
||||
// internal constants
|
||||
//
|
||||
|
||||
//
|
||||
// internal types
|
||||
//
|
||||
|
||||
//
|
||||
// internal variables
|
||||
//
|
||||
|
||||
//
|
||||
// internal functions
|
||||
//
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
void setCurrentThreadName(const char* threadName)
|
||||
{
|
||||
#if MIJIN_TARGET_OS == MIJIN_OS_LINUX
|
||||
pthread_setname_np(pthread_self(), threadName);
|
||||
#elif MIJIN_TARGET_OS == MIJIN_OS_WINDOWS
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace mijin
|
||||
30
source/mijin/util/os.hpp
Normal file
30
source/mijin/util/os.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_UTIL_OS_HPP_INCLUDED)
|
||||
#define MIJIN_UTIL_OS_HPP_INCLUDED 1
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
void setCurrentThreadName(const char* threadName);
|
||||
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_UTIL_OS_HPP_INCLUDED)
|
||||
52
source/mijin/util/string.hpp
Normal file
52
source/mijin/util/string.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_UTIL_STRING_HPP_INCLUDED)
|
||||
#define MIJIN_UTIL_STRING_HPP_INCLUDED 1
|
||||
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
template <typename TRange, typename TValue = typename TRange::value_type>
|
||||
std::string join(const TRange& elements, const char* const delimiter)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
auto first = std::begin(elements);
|
||||
auto last = std::end(elements);
|
||||
|
||||
if (first != last)
|
||||
{
|
||||
std::copy(first, std::prev(last), std::ostream_iterator<TValue>(oss, delimiter));
|
||||
first = prev(last);
|
||||
}
|
||||
if (first != last)
|
||||
{
|
||||
oss << *first;
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_UTIL_STRING_HPP_INCLUDED)
|
||||
126
source/mijin/util/template_string.hpp
Normal file
126
source/mijin/util/template_string.hpp
Normal file
@@ -0,0 +1,126 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_UTIL_TEMPLATE_STRING_HPP_INCLUDED)
|
||||
#define MIJIN_UTIL_TEMPLATE_STRING_HPP_INCLUDED 1
|
||||
|
||||
#include <utility>
|
||||
#include "../detect.hpp"
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
// #define MIJIN_MAKE_TEMPLATE_STRING(str) decltype(str ## _mijin_template_string)
|
||||
#define MIJIN_MAKE_TEMPLATE_STRING(str) \
|
||||
mijin::impl::template_string_builder< \
|
||||
mijin::impl::charAt<0>(str), \
|
||||
mijin::impl::charAt<1>(str), \
|
||||
mijin::impl::charAt<2>(str), \
|
||||
mijin::impl::charAt<3>(str), \
|
||||
mijin::impl::charAt<4>(str), \
|
||||
mijin::impl::charAt<5>(str), \
|
||||
mijin::impl::charAt<6>(str), \
|
||||
mijin::impl::charAt<7>(str), \
|
||||
mijin::impl::charAt<8>(str), \
|
||||
mijin::impl::charAt<9>(str), \
|
||||
mijin::impl::charAt<10>(str), \
|
||||
mijin::impl::charAt<11>(str), \
|
||||
mijin::impl::charAt<12>(str), \
|
||||
mijin::impl::charAt<13>(str), \
|
||||
mijin::impl::charAt<14>(str), \
|
||||
mijin::impl::charAt<15>(str), \
|
||||
mijin::impl::charAt<16>(str), \
|
||||
mijin::impl::charAt<17>(str), \
|
||||
mijin::impl::charAt<18>(str), \
|
||||
mijin::impl::charAt<19>(str), \
|
||||
mijin::impl::charAt<20>(str), \
|
||||
mijin::impl::charAt<21>(str), \
|
||||
mijin::impl::charAt<22>(str), \
|
||||
mijin::impl::charAt<23>(str), \
|
||||
mijin::impl::charAt<24>(str), \
|
||||
mijin::impl::charAt<25>(str), \
|
||||
mijin::impl::charAt<26>(str), \
|
||||
mijin::impl::charAt<27>(str), \
|
||||
mijin::impl::charAt<28>(str), \
|
||||
mijin::impl::charAt<29>(str) \
|
||||
>
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
template<char... chars>
|
||||
using template_string = std::integer_sequence<char, chars...>;
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template<typename T>
|
||||
struct TemplateStringHelper;
|
||||
|
||||
template<char... chars>
|
||||
struct TemplateStringHelper<template_string<chars...>>
|
||||
{
|
||||
static constexpr const char value[sizeof...(chars) + 1] = {chars..., '\0'}; // NOLINT
|
||||
};
|
||||
|
||||
template<char chr, char... chars>
|
||||
constexpr template_string<chr, chars...> prependToString(template_string<chars...>)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template<char... chars>
|
||||
struct TemplateStringBuilder {};
|
||||
|
||||
template<char firstChar, char... chars>
|
||||
struct TemplateStringBuilder<firstChar, chars...>
|
||||
{
|
||||
using previous_seq_t = typename TemplateStringBuilder<chars...>::seq_t;
|
||||
using seq_t = decltype(prependToString<firstChar>(previous_seq_t()));
|
||||
};
|
||||
|
||||
template<char... chars>
|
||||
struct TemplateStringBuilder<'\0', chars...>
|
||||
{
|
||||
using seq_t = template_string<>;
|
||||
};
|
||||
|
||||
template<std::size_t pos, std::size_t len>
|
||||
constexpr char charAt(const char (&text)[len])
|
||||
{
|
||||
if constexpr (pos < len) {
|
||||
return text[pos];
|
||||
}
|
||||
else {
|
||||
return '\0';
|
||||
}
|
||||
}
|
||||
|
||||
template<char... chars>
|
||||
typename TemplateStringBuilder<chars...>::seq_t buildTemplateString()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
template<char... chars>
|
||||
using template_string_builder = typename TemplateStringBuilder<chars...>::seq_t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline constexpr auto template_string_v = impl::TemplateStringHelper<T>::value;
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_UTIL_TEMPLATE_STRING_HPP_INCLUDED)
|
||||
118
source/mijin/util/traits.hpp
Normal file
118
source/mijin/util/traits.hpp
Normal file
@@ -0,0 +1,118 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_UTIL_TRAITS_HPP_INCLUDED)
|
||||
#define MIJIN_UTIL_TRAITS_HPP_INCLUDED 1
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
template<typename T>
|
||||
struct always_false
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr bool always_false_v = always_false<T>::value;
|
||||
|
||||
template<auto V>
|
||||
struct always_false_val
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template<auto V>
|
||||
inline constexpr bool always_false_val_v = always_false_val<V>::value;
|
||||
|
||||
|
||||
|
||||
template<template<typename> typename TFilter, typename... TArgs>
|
||||
struct TypeFilter;
|
||||
|
||||
template<template<typename> typename TFilter>
|
||||
struct TypeFilter<TFilter>
|
||||
{
|
||||
using type_t = std::tuple<>;
|
||||
};
|
||||
|
||||
template<template<typename> typename TFilter, typename TFirst, typename... TArgs>
|
||||
struct TypeFilter<TFilter, TFirst, TArgs...>
|
||||
{
|
||||
static consteval auto makeTypeHelper()
|
||||
{
|
||||
using base_t = typename TypeFilter<TFilter, TArgs...>::type_t;
|
||||
|
||||
// note: not using decltype, as the compiler might think it is being evaluated
|
||||
if constexpr (!TFilter<TFirst>::value) {
|
||||
return static_cast<base_t*>(nullptr);
|
||||
}
|
||||
else {
|
||||
auto wrapper = []<typename... TArgsInner>(std::tuple<TArgsInner...>*)
|
||||
{
|
||||
return static_cast<std::tuple<TFirst, TArgsInner...>*>(nullptr);
|
||||
};
|
||||
return wrapper(static_cast<base_t*>(nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
using type_t = std::remove_pointer_t<decltype(makeTypeHelper())>;
|
||||
};
|
||||
|
||||
template<template<typename> typename TFilter, typename... TArgs>
|
||||
auto typeFilterHelper(std::tuple<TArgs...>*)
|
||||
{
|
||||
return static_cast<typename TypeFilter<TFilter, TArgs...>::type_t*>(nullptr);
|
||||
}
|
||||
|
||||
template<template<typename> typename TFilter, typename TTuple>
|
||||
using filter_types_t = std::remove_pointer_t<decltype(typeFilterHelper<TFilter>(static_cast<TTuple*>(nullptr)))>;
|
||||
|
||||
template<template<typename> typename TPredicate, typename... TArgs>
|
||||
auto mapTypesHelper(std::tuple<TArgs...>)
|
||||
{
|
||||
return static_cast<std::tuple<TPredicate<TArgs>...>*>(nullptr);
|
||||
}
|
||||
|
||||
template<template<typename> typename TPredicate, typename TTuple>
|
||||
using map_types_t = std::remove_pointer_t<decltype(mapTypesHelper<TPredicate>(std::declval<TTuple>()))>;
|
||||
|
||||
template<template<typename> typename TPredicate, template<typename> typename TTemplate>
|
||||
struct map_template {
|
||||
template<typename T>
|
||||
using type_t = TTemplate<TPredicate<T>>;
|
||||
};
|
||||
|
||||
template<typename T, typename... Types>
|
||||
struct is_any_type : std::disjunction<std::is_same<T, Types>...> {};
|
||||
|
||||
template<typename T, typename... Types>
|
||||
static constexpr bool is_any_type_v = is_any_type<T, Types...>::value;
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
template<typename THelper, typename TType>
|
||||
decltype(auto) delayEvaluation(TType&& value)
|
||||
{
|
||||
return static_cast<TType&&>(value);
|
||||
}
|
||||
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_UTIL_TRAITS_HPP_INCLUDED)
|
||||
127
source/mijin/util/types.hpp
Normal file
127
source/mijin/util/types.hpp
Normal file
@@ -0,0 +1,127 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(MIJIN_UTIL_TYPES_HPP_INCLUDED)
|
||||
#define MIJIN_UTIL_TYPES_HPP_INCLUDED 1
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include "./traits.hpp"
|
||||
|
||||
namespace mijin
|
||||
{
|
||||
|
||||
//
|
||||
// public defines
|
||||
//
|
||||
|
||||
//
|
||||
// public constants
|
||||
//
|
||||
|
||||
//
|
||||
// public types
|
||||
//
|
||||
|
||||
namespace impl
|
||||
{
|
||||
template<std::size_t numBits>
|
||||
consteval auto getUintType()
|
||||
{
|
||||
if constexpr (numBits == 8) {
|
||||
return std::uint8_t{};
|
||||
}
|
||||
else if constexpr (numBits == 16) {
|
||||
return std::uint16_t{};
|
||||
}
|
||||
else if constexpr (numBits == 32) {
|
||||
return std::uint32_t{};
|
||||
}
|
||||
else if constexpr (numBits == 64) {
|
||||
return std::uint64_t{};
|
||||
}
|
||||
else {
|
||||
static_assert(always_false_val_v<numBits>, "No uint type with this bit count.");
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t numBits>
|
||||
consteval auto getNextUintType()
|
||||
{
|
||||
if constexpr (numBits <= 8) {
|
||||
return std::uint8_t{};
|
||||
}
|
||||
else if constexpr (numBits <= 16) {
|
||||
return std::uint16_t{};
|
||||
}
|
||||
else if constexpr (numBits <= 32) {
|
||||
return std::uint32_t{};
|
||||
}
|
||||
else if constexpr (numBits <= 64) {
|
||||
return std::uint64_t{};
|
||||
}
|
||||
else {
|
||||
static_assert(always_false_val_v<numBits>, "No uint type with this bit count.");
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t numBits>
|
||||
consteval auto getIntType()
|
||||
{
|
||||
if constexpr (numBits == 8) {
|
||||
return std::int8_t{};
|
||||
}
|
||||
else if constexpr (numBits == 16) {
|
||||
return std::int16_t{};
|
||||
}
|
||||
else if constexpr (numBits == 32) {
|
||||
return std::int32_t{};
|
||||
}
|
||||
else if constexpr (numBits == 64) {
|
||||
return std::int64_t{};
|
||||
}
|
||||
else {
|
||||
static_assert(always_false_val_v<numBits>, "No int type with this bit count.");
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t numBits>
|
||||
consteval auto getNextIntType()
|
||||
{
|
||||
if constexpr (numBits <= 8) {
|
||||
return std::int8_t{};
|
||||
}
|
||||
else if constexpr (numBits <= 16) {
|
||||
return std::int16_t{};
|
||||
}
|
||||
else if constexpr (numBits <= 32) {
|
||||
return std::int32_t{};
|
||||
}
|
||||
else if constexpr (numBits <= 64) {
|
||||
return std::int64_t{};
|
||||
}
|
||||
else {
|
||||
static_assert(always_false_val_v<numBits>, "No int type with this bit count.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t numBits>
|
||||
using uintx_t = decltype(impl::getUintType<numBits>());
|
||||
|
||||
template<std::size_t numBits>
|
||||
using uint_next_t = decltype(impl::getNextUintType<numBits>());
|
||||
|
||||
template<std::size_t numBits>
|
||||
using intx_t = decltype(impl::getIntType<numBits>());
|
||||
|
||||
template<std::size_t numBits>
|
||||
using int_next_t = decltype(impl::getNextIntType<numBits>());
|
||||
|
||||
//
|
||||
// public functions
|
||||
//
|
||||
|
||||
} // namespace mijin
|
||||
|
||||
#endif // !defined(MIJIN_UTIL_TYPES_HPP_INCLUDED)
|
||||
Reference in New Issue
Block a user