2018-06-03 15:25:50 +10:00
|
|
|
/*
|
2018-08-04 15:14:06 +10:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
2018-06-03 15:25:50 +10:00
|
|
|
*
|
2019-05-30 10:43:28 +10:00
|
|
|
* Copyright 2018-2019 Danny Robson <danny@nerdcruft.net>
|
2018-06-03 15:25:50 +10:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "../std.hpp"
|
2019-05-17 10:55:49 +10:00
|
|
|
#include "../debug/panic.hpp"
|
2019-05-30 10:43:28 +10:00
|
|
|
#include "../typeidx.hpp"
|
2018-06-03 15:25:50 +10:00
|
|
|
|
|
|
|
#include <cstddef>
|
|
|
|
#include <type_traits>
|
2019-03-16 18:19:12 +11:00
|
|
|
#include <functional>
|
|
|
|
#include <utility>
|
|
|
|
|
2018-06-03 15:25:50 +10:00
|
|
|
|
2018-08-05 14:42:02 +10:00
|
|
|
namespace cruft::types {
|
2019-05-09 10:32:39 +10:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/// Computes the number of elements of a scalar (ie, 1), or of statically
|
|
|
|
/// sized vector type
|
|
|
|
template <typename T, typename = void>
|
|
|
|
struct arity_trait { };
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// void arity is explicitly zero.
|
|
|
|
template <>
|
|
|
|
struct arity_trait<void, void> : public std::integer_sequence<std::size_t, 0> { };
|
|
|
|
|
|
|
|
|
2018-06-03 15:25:50 +10:00
|
|
|
//-------------------------------------------------------------------------
|
2019-05-09 10:32:39 +10:00
|
|
|
// All basic types are unit arity (except for void which is zero).
|
|
|
|
template <typename T>
|
|
|
|
struct arity_trait<
|
|
|
|
T,
|
|
|
|
std::enable_if_t<std::is_fundamental_v<T>>
|
|
|
|
> : public std::integral_constant<
|
|
|
|
std::size_t, 1u
|
|
|
|
> { };
|
|
|
|
|
|
|
|
|
2019-05-17 10:55:49 +10:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
// Punt the handling of any enum to the underlying type.
|
|
|
|
template <typename EnumT>
|
|
|
|
struct arity_trait<
|
|
|
|
EnumT,
|
|
|
|
std::enable_if_t<std::is_enum_v<EnumT>>
|
|
|
|
> : public arity_trait<
|
|
|
|
std::underlying_type_t<EnumT>
|
|
|
|
> { };
|
|
|
|
|
|
|
|
|
2019-05-09 10:32:39 +10:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
template <typename T>
|
|
|
|
constexpr auto arity_v = arity_trait<T>::value;
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2018-06-03 15:25:50 +10:00
|
|
|
enum class category {
|
|
|
|
NONE,
|
2019-05-30 10:43:28 +10:00
|
|
|
INTEGER,
|
2018-06-03 15:25:50 +10:00
|
|
|
REAL,
|
2019-05-14 13:01:23 +10:00
|
|
|
BOOL,
|
2019-05-30 10:43:28 +10:00
|
|
|
ENUM,
|
2018-06-03 15:25:50 +10:00
|
|
|
};
|
|
|
|
|
2019-05-09 10:32:39 +10:00
|
|
|
|
|
|
|
///------------------------------------------------------------------------
|
|
|
|
/// A description of the type that makes up a scalar or vector type.
|
|
|
|
///
|
|
|
|
/// A vector3f would be { REAL, sizeof(float), 3 };
|
2019-05-20 12:30:04 +10:00
|
|
|
///
|
|
|
|
/// DO NOT add a 'size' member function as it tends to be used in a way
|
|
|
|
/// that confuses total byte size, element byte size, and arity.
|
|
|
|
/// Instead: use the bytes member function, or the arity member variable.
|
2018-06-03 15:25:50 +10:00
|
|
|
struct description {
|
2019-05-30 10:43:28 +10:00
|
|
|
/// The fundamental nature of the type; is it integral, real, bool, etc.
|
2018-06-03 15:25:50 +10:00
|
|
|
enum category category;
|
2019-03-16 18:19:12 +11:00
|
|
|
|
2019-05-30 10:43:28 +10:00
|
|
|
/// Is the type considered to be signed?
|
|
|
|
///
|
|
|
|
/// For some types, like void, this does not make sense. In this case
|
|
|
|
/// the value must be false.
|
|
|
|
///
|
|
|
|
/// For other types this value will almost certainly be one value in a
|
|
|
|
/// realistic system; eg, signed floating point numbers.
|
|
|
|
bool signedness;
|
|
|
|
|
2019-03-16 18:19:12 +11:00
|
|
|
/// The number of bytes for an individual instance of this type.
|
2018-06-03 15:25:50 +10:00
|
|
|
std::size_t width;
|
2019-05-09 10:32:39 +10:00
|
|
|
|
|
|
|
/// The number of variables that make up an instance.
|
|
|
|
std::size_t arity;
|
|
|
|
|
|
|
|
std::size_t alignment;
|
|
|
|
|
2019-05-30 10:43:28 +10:00
|
|
|
/// The value from typeidx for the constructed type (if it is known
|
|
|
|
/// and has been registered), otherwise 0.
|
|
|
|
int index;
|
|
|
|
|
2019-05-09 10:32:39 +10:00
|
|
|
/// Returns the number of bytes required to store this type.
|
2019-05-20 12:30:04 +10:00
|
|
|
constexpr std::size_t
|
|
|
|
bytes (void) const noexcept
|
|
|
|
{
|
|
|
|
return width * arity;
|
|
|
|
}
|
2018-06-03 15:25:50 +10:00
|
|
|
};
|
|
|
|
|
2019-05-09 10:32:39 +10:00
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
2019-03-17 23:32:34 +11:00
|
|
|
constexpr bool
|
|
|
|
operator== (description const &a, description const &b) noexcept
|
|
|
|
{
|
2019-05-30 10:43:28 +10:00
|
|
|
return a.category == b.category &&
|
|
|
|
a.signedness == b.signedness &&
|
|
|
|
a.width == b.width &&
|
|
|
|
a.arity == b.arity &&
|
|
|
|
a.alignment == b.alignment &&
|
|
|
|
(a.index == 0 || b.index == 0 || a.index == b.index);
|
2019-03-17 23:32:34 +11:00
|
|
|
}
|
|
|
|
|
2018-06-03 15:25:50 +10:00
|
|
|
|
2019-05-15 13:03:25 +10:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
constexpr bool
|
|
|
|
operator!= (description const &a, description const &b) noexcept
|
|
|
|
{
|
|
|
|
return !(a == b);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-03 15:25:50 +10:00
|
|
|
//-------------------------------------------------------------------------
|
2019-05-17 10:55:49 +10:00
|
|
|
template <typename T, typename = void>
|
2018-06-03 15:25:50 +10:00
|
|
|
struct category_traits;
|
|
|
|
|
2019-05-30 10:43:28 +10:00
|
|
|
template <> struct category_traits<u08> : public std::integral_constant<category,category::INTEGER> {};
|
|
|
|
template <> struct category_traits<u16> : public std::integral_constant<category,category::INTEGER> {};
|
|
|
|
template <> struct category_traits<u32> : public std::integral_constant<category,category::INTEGER> {};
|
|
|
|
template <> struct category_traits<u64> : public std::integral_constant<category,category::INTEGER> {};
|
2018-06-03 15:25:50 +10:00
|
|
|
|
2019-05-30 10:43:28 +10:00
|
|
|
template <> struct category_traits<i08> : public std::integral_constant<category,category::INTEGER> {};
|
|
|
|
template <> struct category_traits<i16> : public std::integral_constant<category,category::INTEGER> {};
|
|
|
|
template <> struct category_traits<i32> : public std::integral_constant<category,category::INTEGER> {};
|
|
|
|
template <> struct category_traits<i64> : public std::integral_constant<category,category::INTEGER> {};
|
2018-06-03 15:25:50 +10:00
|
|
|
|
|
|
|
template <> struct category_traits<f32> : public std::integral_constant<category,category::REAL> {};
|
|
|
|
template <> struct category_traits<f64> : public std::integral_constant<category,category::REAL> {};
|
|
|
|
|
2019-05-14 13:01:23 +10:00
|
|
|
template <> struct category_traits<bool> : public std::integral_constant<category,category::BOOL> {};
|
|
|
|
|
2019-05-17 10:55:49 +10:00
|
|
|
|
|
|
|
template <typename EnumT>
|
|
|
|
struct category_traits<
|
|
|
|
EnumT,
|
|
|
|
std::enable_if_t<
|
|
|
|
std::is_enum_v<EnumT>
|
|
|
|
>
|
2019-05-30 10:43:28 +10:00
|
|
|
> : public std::integral_constant<category,category::ENUM>
|
2019-05-17 10:55:49 +10:00
|
|
|
{ };
|
|
|
|
|
|
|
|
|
2018-06-03 15:25:50 +10:00
|
|
|
template <typename T>
|
|
|
|
constexpr auto category_traits_v = category_traits<T>::value;
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
2019-05-30 10:43:28 +10:00
|
|
|
template <typename, typename = void>
|
|
|
|
struct signedness_traits;
|
|
|
|
|
|
|
|
template <> struct signedness_traits<u08> : public std::false_type {};
|
|
|
|
template <> struct signedness_traits<u16> : public std::false_type {};
|
|
|
|
template <> struct signedness_traits<u32> : public std::false_type {};
|
|
|
|
template <> struct signedness_traits<u64> : public std::false_type {};
|
|
|
|
|
|
|
|
template <> struct signedness_traits<i08> : public std::true_type {};
|
|
|
|
template <> struct signedness_traits<i16> : public std::true_type {};
|
|
|
|
template <> struct signedness_traits<i32> : public std::true_type {};
|
|
|
|
template <> struct signedness_traits<i64> : public std::true_type {};
|
|
|
|
|
|
|
|
template <> struct signedness_traits<f32> : public std::true_type {};
|
|
|
|
template <> struct signedness_traits<f64> : public std::true_type {};
|
|
|
|
|
|
|
|
template <> struct signedness_traits<bool> : public std::false_type {};
|
|
|
|
|
|
|
|
template <typename EnumT>
|
|
|
|
struct signedness_traits<
|
|
|
|
EnumT,
|
|
|
|
std::enable_if_t<
|
|
|
|
std::is_enum_v<EnumT>
|
|
|
|
>
|
|
|
|
>: public signedness_traits<std::underlying_type_t<EnumT>> {};
|
|
|
|
|
2018-06-03 15:25:50 +10:00
|
|
|
template <typename T>
|
2019-05-30 10:43:28 +10:00
|
|
|
constexpr auto signedness_traits_v = signedness_traits<T>::value;
|
|
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
template <typename T>
|
|
|
|
description
|
2018-06-03 15:25:50 +10:00
|
|
|
make_description (void) noexcept
|
|
|
|
{
|
2019-03-17 23:32:50 +11:00
|
|
|
if constexpr (std::is_void_v<T>) {
|
|
|
|
return {
|
2019-05-30 10:43:28 +10:00
|
|
|
.category = category::NONE,
|
|
|
|
.signedness = false,
|
|
|
|
.width = 0,
|
|
|
|
.arity = 1,
|
|
|
|
.alignment = 0,
|
|
|
|
.index = cruft::typeidx<T> (),
|
2019-03-17 23:32:50 +11:00
|
|
|
};
|
|
|
|
} else {
|
|
|
|
return {
|
|
|
|
.category = category_traits_v<T>,
|
2019-05-30 10:43:28 +10:00
|
|
|
.signedness = signedness_traits_v<T>,
|
2019-05-09 10:32:39 +10:00
|
|
|
.width = sizeof (T),
|
|
|
|
.arity = arity_v<T>,
|
2019-05-30 10:43:28 +10:00
|
|
|
.alignment = alignof (T),
|
|
|
|
.index = cruft::typeidx<T> (),
|
2019-03-17 23:32:50 +11:00
|
|
|
};
|
|
|
|
}
|
2018-06-03 15:25:50 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-30 10:43:28 +10:00
|
|
|
|
2018-06-03 15:25:50 +10:00
|
|
|
#include <iosfwd>
|
2018-08-05 14:42:02 +10:00
|
|
|
namespace cruft::types {
|
2018-06-03 15:25:50 +10:00
|
|
|
std::ostream& operator<< (std::ostream&, category);
|
|
|
|
std::ostream& operator<< (std::ostream&, description);
|
|
|
|
}
|