intial commit

This commit is contained in:
2023-05-29 14:51:44 +02:00
commit da781b87f2
38 changed files with 4842 additions and 0 deletions

View 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)

View 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)

View 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
View 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
View 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
View 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)

View 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)

View 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)

View 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
View 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)