mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[includes] Move enum_bitfields.h to base includes
Pull this widely-useful header out of kutil, so more things can use it. Also replace its dependency on <type_traits> by defining our own custom basic_types.h which contains a subset of the standard's types.
This commit is contained in:
56
src/include/basic_types.h
Normal file
56
src/include/basic_types.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
/// file basic_types.h
|
||||||
|
/// Type properties that would normally come from <type_traits>
|
||||||
|
|
||||||
|
namespace types {
|
||||||
|
|
||||||
|
template <bool B, typename T = void> struct enable_if {};
|
||||||
|
template <typename T> struct enable_if<true, T> { using type = T; };
|
||||||
|
|
||||||
|
template <typename T> struct is_integral { static constexpr bool value = false; };
|
||||||
|
template <> struct is_integral<char> { static constexpr bool value = true; };
|
||||||
|
template <> struct is_integral<unsigned char> { static constexpr bool value = true; };
|
||||||
|
template <> struct is_integral<short> { static constexpr bool value = true; };
|
||||||
|
template <> struct is_integral<unsigned short> { static constexpr bool value = true; };
|
||||||
|
template <> struct is_integral<int> { static constexpr bool value = true; };
|
||||||
|
template <> struct is_integral<unsigned int> { static constexpr bool value = true; };
|
||||||
|
template <> struct is_integral<long> { static constexpr bool value = true; };
|
||||||
|
template <> struct is_integral<unsigned long> { static constexpr bool value = true; };
|
||||||
|
template <> struct is_integral<long long> { static constexpr bool value = true; };
|
||||||
|
template <> struct is_integral<unsigned long long> { static constexpr bool value = true; };
|
||||||
|
|
||||||
|
template <typename E> struct integral { using type = unsigned long long; };
|
||||||
|
template <> struct integral<char> { using type = char; };
|
||||||
|
template <> struct integral<unsigned char> { using type = unsigned char; };
|
||||||
|
template <> struct integral<short> { using type = short; };
|
||||||
|
template <> struct integral<unsigned short> { using type = unsigned short; };
|
||||||
|
template <> struct integral<int> { using type = int; };
|
||||||
|
template <> struct integral<unsigned int> { using type = unsigned int; };
|
||||||
|
template <> struct integral<long> { using type = long; };
|
||||||
|
template <> struct integral<unsigned long> { using type = unsigned long; };
|
||||||
|
template <> struct integral<long long> { using type = long long; };
|
||||||
|
template <> struct integral<unsigned long long> { using type = unsigned long long; };
|
||||||
|
|
||||||
|
template <typename T, T v>
|
||||||
|
struct integral_constant
|
||||||
|
{
|
||||||
|
using value_type = T;
|
||||||
|
using type = integral_constant;
|
||||||
|
static constexpr value_type value = v;
|
||||||
|
constexpr operator value_type() const noexcept { return value; }
|
||||||
|
constexpr value_type operator()() const noexcept { return value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
using true_type = integral_constant<bool, true>;
|
||||||
|
using false_type = integral_constant<bool, false>;
|
||||||
|
|
||||||
|
template <bool B, typename T, typename F> struct conditional { using type = T; };
|
||||||
|
template <typename T, typename F> struct conditional<false, T, F> { using type = F; };
|
||||||
|
|
||||||
|
template<typename...> struct conjunction : true_type {};
|
||||||
|
template<typename B1> struct conjunction<B1> : B1 {};
|
||||||
|
template<typename B1, typename... Bn>
|
||||||
|
struct conjunction<B1, Bn...> : conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace types
|
||||||
89
src/include/enum_bitfields.h
Normal file
89
src/include/enum_bitfields.h
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "basic_types.h"
|
||||||
|
|
||||||
|
namespace bitfields {
|
||||||
|
|
||||||
|
template <typename E>
|
||||||
|
constexpr bool is_enum_bitfield(E) { return false; }
|
||||||
|
|
||||||
|
template <typename E>
|
||||||
|
struct enum_or_int {
|
||||||
|
static constexpr bool value =
|
||||||
|
is_enum_bitfield(E{}) || types::is_integral<E>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename E, typename F>
|
||||||
|
struct both_enum_or_int {
|
||||||
|
static constexpr bool value =
|
||||||
|
types::conjunction< enum_or_int<E>, enum_or_int<F> >::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename E, typename F>
|
||||||
|
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
||||||
|
operator |= (E &lhs, F rhs)
|
||||||
|
{
|
||||||
|
return lhs = static_cast<E>(
|
||||||
|
static_cast<typename types::integral<E>::type>(lhs) |
|
||||||
|
static_cast<typename types::integral<F>::type>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename E, typename F>
|
||||||
|
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
||||||
|
operator &= (E &lhs, F rhs)
|
||||||
|
{
|
||||||
|
return lhs = static_cast<E>(
|
||||||
|
static_cast<typename types::integral<E>::type>(lhs) &
|
||||||
|
static_cast<typename types::integral<F>::type>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename E, typename F>
|
||||||
|
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
||||||
|
operator ^= (E &lhs, F rhs)
|
||||||
|
{
|
||||||
|
return lhs = static_cast<E>(
|
||||||
|
static_cast<typename types::integral<E>::type>(lhs) ^
|
||||||
|
static_cast<typename types::integral<F>::type>(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename E, typename F>
|
||||||
|
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type
|
||||||
|
operator & (E lhs, F rhs) { return lhs &= rhs; }
|
||||||
|
|
||||||
|
template <typename E, typename F>
|
||||||
|
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type
|
||||||
|
operator | (E lhs, F rhs) { return lhs |= rhs; }
|
||||||
|
|
||||||
|
template <typename E, typename F>
|
||||||
|
constexpr typename types::enable_if<both_enum_or_int<E, F>::value,E>::type
|
||||||
|
operator ^ (E lhs, F rhs) { return lhs ^= rhs; }
|
||||||
|
|
||||||
|
template <typename E>
|
||||||
|
constexpr typename types::enable_if<is_enum_bitfield(E{}),E>::type
|
||||||
|
operator ~ (E rhs) { return static_cast<E>(~static_cast<typename types::integral<E>::type>(rhs)); }
|
||||||
|
|
||||||
|
template <typename E>
|
||||||
|
constexpr typename types::enable_if<is_enum_bitfield(E{}),bool>::type
|
||||||
|
operator ! (E rhs) { return static_cast<typename types::integral<E>::type>(rhs) == 0; }
|
||||||
|
|
||||||
|
/// Override logical-and to mean 'rhs contains all bits in lhs'
|
||||||
|
template <typename E>
|
||||||
|
constexpr typename types::enable_if<is_enum_bitfield(E{}),bool>::type
|
||||||
|
operator && (E rhs, E lhs) { return (rhs & lhs) == lhs; }
|
||||||
|
|
||||||
|
/// Generic 'has' for non-marked bitfields
|
||||||
|
template <typename E, typename F>
|
||||||
|
constexpr bool has(E set, F flags)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(static_cast<typename types::integral<E>::type>(set) &
|
||||||
|
static_cast<typename types::integral<F>::type>(flags)) ==
|
||||||
|
static_cast<typename types::integral<F>::type>(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace bitfields
|
||||||
|
|
||||||
|
#define is_bitfield(name) \
|
||||||
|
constexpr bool is_enum_bitfield(name) { return true; } \
|
||||||
|
using namespace ::bitfields;
|
||||||
|
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "enum_bitfields.h"
|
||||||
#include "kutil/coord.h"
|
#include "kutil/coord.h"
|
||||||
#include "kutil/enum_bitfields.h"
|
|
||||||
#include "kutil/misc.h"
|
#include "kutil/misc.h"
|
||||||
|
|
||||||
struct acpi_table_header
|
struct acpi_table_header
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/// Classes to control both local and I/O APICs.
|
/// Classes to control both local and I/O APICs.
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "kutil/enum_bitfields.h"
|
#include "enum_bitfields.h"
|
||||||
|
|
||||||
enum class isr : uint8_t;
|
enum class isr : uint8_t;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/// Definitions relating to a CPU's GDT table
|
/// Definitions relating to a CPU's GDT table
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "kutil/enum_bitfields.h"
|
#include "enum_bitfields.h"
|
||||||
|
|
||||||
class TSS;
|
class TSS;
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
#include "kernel_args.h"
|
#include "kernel_args.h"
|
||||||
#include "j6/init.h"
|
#include "j6/init.h"
|
||||||
|
|
||||||
|
#include "enum_bitfields.h"
|
||||||
#include "kutil/assert.h"
|
#include "kutil/assert.h"
|
||||||
#include "kutil/enum_bitfields.h"
|
|
||||||
#include "kutil/heap_allocator.h"
|
#include "kutil/heap_allocator.h"
|
||||||
#include "kutil/no_construct.h"
|
#include "kutil/no_construct.h"
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "enum_bitfields.h"
|
||||||
#include "j6/signals.h"
|
#include "j6/signals.h"
|
||||||
#include "kutil/enum_bitfields.h"
|
|
||||||
#include "kutil/vector.h"
|
#include "kutil/vector.h"
|
||||||
|
|
||||||
#include "kernel_memory.h"
|
#include "kernel_memory.h"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/// Helper structures for dealing with page tables.
|
/// Helper structures for dealing with page tables.
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "kutil/enum_bitfields.h"
|
#include "enum_bitfields.h"
|
||||||
#include "kernel_memory.h"
|
#include "kernel_memory.h"
|
||||||
|
|
||||||
struct free_page_header;
|
struct free_page_header;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
/// Structure for tracking a range of virtual memory addresses
|
/// Structure for tracking a range of virtual memory addresses
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "kutil/enum_bitfields.h"
|
#include "enum_bitfields.h"
|
||||||
#include "kutil/spinlock.h"
|
#include "kutil/spinlock.h"
|
||||||
#include "kutil/vector.h"
|
#include "kutil/vector.h"
|
||||||
#include "page_table.h"
|
#include "page_table.h"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "kutil/enum_bitfields.h"
|
#include "enum_bitfields.h"
|
||||||
|
|
||||||
namespace elf {
|
namespace elf {
|
||||||
|
|
||||||
@@ -95,4 +95,4 @@ struct section_header
|
|||||||
|
|
||||||
} // namespace elf
|
} // namespace elf
|
||||||
|
|
||||||
IS_BITFIELD(elf::section_flags);
|
is_bitfield(elf::section_flags);
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace kutil {
|
|
||||||
namespace bitfields {
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
constexpr bool is_enum_bitfield(E) { return false; }
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
struct enum_or_int {
|
|
||||||
static constexpr bool value =
|
|
||||||
is_enum_bitfield(E{}) || std::is_integral<E>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
struct both_enum_or_int {
|
|
||||||
static constexpr bool value =
|
|
||||||
std::conjunction< enum_or_int<E>, enum_or_int<F> >::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
struct integral { using type = typename std::underlying_type<E>::type; };
|
|
||||||
|
|
||||||
template <> struct integral<char> { using type = char; };
|
|
||||||
template <> struct integral<unsigned char> { using type = unsigned char; };
|
|
||||||
template <> struct integral<short> { using type = short; };
|
|
||||||
template <> struct integral<unsigned short> { using type = unsigned short; };
|
|
||||||
template <> struct integral<int> { using type = int; };
|
|
||||||
template <> struct integral<unsigned int> { using type = unsigned int; };
|
|
||||||
template <> struct integral<long> { using type = long; };
|
|
||||||
template <> struct integral<unsigned long> { using type = unsigned long; };
|
|
||||||
template <> struct integral<long long> { using type = long long; };
|
|
||||||
template <> struct integral<unsigned long long> { using type = unsigned long long; };
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
|
||||||
operator |= (E &lhs, F rhs)
|
|
||||||
{
|
|
||||||
return lhs = static_cast<E>(
|
|
||||||
static_cast<typename integral<E>::type>(lhs) |
|
|
||||||
static_cast<typename integral<F>::type>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
|
||||||
operator &= (E &lhs, F rhs)
|
|
||||||
{
|
|
||||||
return lhs = static_cast<E>(
|
|
||||||
static_cast<typename integral<E>::type>(lhs) &
|
|
||||||
static_cast<typename integral<F>::type>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type&
|
|
||||||
operator ^= (E &lhs, F rhs)
|
|
||||||
{
|
|
||||||
return lhs = static_cast<E>(
|
|
||||||
static_cast<typename integral<E>::type>(lhs) ^
|
|
||||||
static_cast<typename integral<F>::type>(rhs));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type
|
|
||||||
operator & (E lhs, F rhs) { return lhs &= rhs; }
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type
|
|
||||||
operator | (E lhs, F rhs) { return lhs |= rhs; }
|
|
||||||
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr typename std::enable_if<both_enum_or_int<E, F>::value,E>::type
|
|
||||||
operator ^ (E lhs, F rhs) { return lhs ^= rhs; }
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
constexpr typename std::enable_if<is_enum_bitfield(E{}),E>::type
|
|
||||||
operator ~ (E rhs) { return static_cast<E>(~static_cast<typename std::underlying_type<E>::type>(rhs)); }
|
|
||||||
|
|
||||||
template <typename E>
|
|
||||||
constexpr typename std::enable_if<is_enum_bitfield(E{}),bool>::type
|
|
||||||
operator ! (E rhs) { return static_cast<typename std::underlying_type<E>::type>(rhs) == 0; }
|
|
||||||
|
|
||||||
/// Override logical-and to mean 'rhs contains all bits in lhs'
|
|
||||||
template <typename E>
|
|
||||||
constexpr typename std::enable_if<is_enum_bitfield(E{}),bool>::type
|
|
||||||
operator && (E rhs, E lhs) { return (rhs & lhs) == lhs; }
|
|
||||||
|
|
||||||
/// Generic 'has' for non-marked bitfields
|
|
||||||
template <typename E, typename F>
|
|
||||||
constexpr bool has(E set, F flags)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
(static_cast<typename integral<E>::type>(set) &
|
|
||||||
static_cast<typename integral<F>::type>(flags)) ==
|
|
||||||
static_cast<typename integral<F>::type>(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace bitfields
|
|
||||||
} // namespace kutil
|
|
||||||
|
|
||||||
#define is_bitfield(name) \
|
|
||||||
constexpr bool is_enum_bitfield(name) { return true; } \
|
|
||||||
using namespace kutil::bitfields;
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user