mirror of
https://github.com/wiiu-env/wut.git
synced 2024-12-13 11:12:37 +01:00
397 lines
12 KiB
C++
397 lines
12 KiB
C++
#pragma once
|
|
#include "utils.h"
|
|
#include "type_traits.h"
|
|
#include <utility>
|
|
|
|
template<typename Type>
|
|
class be_val
|
|
{
|
|
public:
|
|
static_assert(!std::is_array<Type>::value,
|
|
"be_val invalid type: array");
|
|
|
|
static_assert(!std::is_pointer<Type>::value,
|
|
"be_val invalid type: pointer");
|
|
|
|
static_assert(sizeof(Type) == 1 || sizeof(Type) == 2 || sizeof(Type) == 4 || sizeof(Type) == 8,
|
|
"be_val invalid type size");
|
|
|
|
using value_type = Type;
|
|
|
|
be_val() = default;
|
|
|
|
be_val(const value_type &value) :
|
|
mStorage(byte_swap(value))
|
|
{
|
|
}
|
|
|
|
value_type value() const
|
|
{
|
|
return byte_swap(mStorage);
|
|
}
|
|
|
|
void setValue(value_type value)
|
|
{
|
|
mStorage = byte_swap(value);
|
|
}
|
|
|
|
operator value_type() const
|
|
{
|
|
return value();
|
|
}
|
|
|
|
template<typename T = Type,
|
|
typename = typename std::enable_if<std::is_convertible<T, bool>::value ||
|
|
std::is_constructible<bool, T>::value
|
|
>::type>
|
|
explicit operator bool() const
|
|
{
|
|
return static_cast<bool>(value());
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = typename std::enable_if<std::is_convertible<Type, OtherType>::value ||
|
|
std::is_constructible<OtherType, Type>::value ||
|
|
std::is_convertible<Type, typename safe_underlying_type<OtherType>::type>::value
|
|
>::type>
|
|
explicit operator OtherType() const
|
|
{
|
|
return static_cast<OtherType>(value());
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = typename std::enable_if<std::is_constructible<value_type, const OtherType &>::value ||
|
|
std::is_convertible<const OtherType &, value_type>::value>::type>
|
|
be_val & operator =(const OtherType &other)
|
|
{
|
|
if constexpr (std::is_constructible<value_type, const OtherType &>::value) {
|
|
setValue(value_type { other });
|
|
} else {
|
|
setValue(static_cast<value_type>(other));
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = typename std::enable_if<std::is_constructible<value_type, const OtherType &>::value ||
|
|
std::is_convertible<const OtherType &, value_type>::value>::type>
|
|
be_val & operator =(OtherType &&other)
|
|
{
|
|
if constexpr (std::is_constructible<value_type, const OtherType &>::value) {
|
|
setValue(value_type { std::forward<OtherType>(other) });
|
|
} else {
|
|
setValue(static_cast<value_type>(std::forward<OtherType>(other)));
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = typename std::enable_if<std::is_convertible<const OtherType &, value_type>::value ||
|
|
std::is_constructible<value_type, const OtherType &>::value>::type>
|
|
be_val & operator =(const be_val<OtherType> &other)
|
|
{
|
|
if constexpr (std::is_constructible<value_type, const OtherType &>::value) {
|
|
setValue(value_type { other.value() });
|
|
} else {
|
|
setValue(static_cast<value_type>(other.value()));
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = typename std::enable_if<std::is_convertible<const OtherType &, value_type>::value ||
|
|
std::is_constructible<value_type, const OtherType &>::value>::type>
|
|
be_val & operator =(be_val<OtherType> &&other)
|
|
{
|
|
if constexpr (std::is_constructible<value_type, const OtherType &>::value) {
|
|
setValue(value_type { other.value() });
|
|
} else {
|
|
setValue(static_cast<value_type>(other.value()));
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator ==(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator ==(std::declval<const OtherType>())) const
|
|
{
|
|
return value() == other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator !=(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator !=(std::declval<const OtherType>())) const
|
|
{
|
|
return value() != other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator >=(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator >=(std::declval<const OtherType>())) const
|
|
{
|
|
return value() >= other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator <=(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator <=(std::declval<const OtherType>())) const
|
|
{
|
|
return value() <= other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator >(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator >(std::declval<const OtherType>())) const
|
|
{
|
|
return value() > other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator <(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator <(std::declval<const OtherType>())) const
|
|
{
|
|
return value() < other;
|
|
}
|
|
|
|
template<typename K = value_type>
|
|
auto operator +()
|
|
-> decltype(std::declval<const K>(). operator+()) const
|
|
{
|
|
return +value();
|
|
}
|
|
|
|
template<typename K = value_type>
|
|
auto operator -()
|
|
-> decltype(std::declval<const K>(). operator-()) const
|
|
{
|
|
return -value();
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator +(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator +(std::declval<const OtherType>())) const
|
|
{
|
|
return value() + other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator -(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator -(std::declval<const OtherType>())) const
|
|
{
|
|
return value() - other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator *(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator *(std::declval<const OtherType>())) const
|
|
{
|
|
return value() * other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator /(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator /(std::declval<const OtherType>())) const
|
|
{
|
|
return value() / other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator %(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator %(std::declval<const OtherType>())) const
|
|
{
|
|
return value() % other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator |(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator |(std::declval<const OtherType>())) const
|
|
{
|
|
return value() | other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator &(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator &(std::declval<const OtherType>())) const
|
|
{
|
|
return value() & other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator ^(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator ^(std::declval<const OtherType>())) const
|
|
{
|
|
return value() ^ other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator <<(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator <<(std::declval<const OtherType>())) const
|
|
{
|
|
return value() << other;
|
|
}
|
|
|
|
template<typename OtherType, typename K = value_type>
|
|
auto operator >>(const OtherType &other)
|
|
-> decltype(std::declval<const K>().operator >>(std::declval<const OtherType>())) const
|
|
{
|
|
return value() >> other;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = decltype(std::declval<const value_type>() + std::declval<const OtherType>())>
|
|
be_val &operator +=(const OtherType &other)
|
|
{
|
|
*this = value() + other;
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = decltype(std::declval<const value_type>() - std::declval<const OtherType>())>
|
|
be_val &operator -=(const OtherType &other)
|
|
{
|
|
*this = value() - other;
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = decltype(std::declval<const value_type>() * std::declval<const OtherType>())>
|
|
be_val &operator *=(const OtherType &other)
|
|
{
|
|
*this = value() * other;
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = decltype(std::declval<const value_type>() / std::declval<const OtherType>())>
|
|
be_val &operator /=(const OtherType &other)
|
|
{
|
|
*this = value() / other;
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = decltype(std::declval<const value_type>() % std::declval<const OtherType>())>
|
|
be_val &operator %=(const OtherType &other)
|
|
{
|
|
*this = value() % other;
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = decltype(std::declval<const value_type>() | std::declval<const OtherType>())>
|
|
be_val &operator |=(const OtherType &other)
|
|
{
|
|
*this = static_cast<Type>(value() | other);
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = decltype(std::declval<const value_type>() & std::declval<const OtherType>())>
|
|
be_val &operator &=(const OtherType &other)
|
|
{
|
|
*this = static_cast<Type>(value() & other);
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = decltype(std::declval<const value_type>() ^ std::declval<const OtherType>())>
|
|
be_val &operator ^=(const OtherType &other)
|
|
{
|
|
*this = static_cast<Type>(value() ^ other);
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = decltype(std::declval<const value_type>() << std::declval<const OtherType>())>
|
|
be_val &operator <<=(const OtherType &other)
|
|
{
|
|
*this = value() << other;
|
|
return *this;
|
|
}
|
|
|
|
template<typename OtherType,
|
|
typename = decltype(std::declval<const value_type>() >> std::declval<const OtherType>())>
|
|
be_val &operator >>=(const OtherType &other)
|
|
{
|
|
*this = value() >> other;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T = Type,
|
|
typename = decltype(std::declval<const T>() + 1)>
|
|
be_val &operator ++()
|
|
{
|
|
setValue(value() + 1);
|
|
return *this;
|
|
}
|
|
|
|
template<typename T = Type,
|
|
typename = decltype(std::declval<const T>() + 1)>
|
|
be_val operator ++(int)
|
|
{
|
|
auto before = *this;
|
|
setValue(value() + 1);
|
|
return before;
|
|
}
|
|
|
|
template<typename T = Type,
|
|
typename = decltype(std::declval<const T>() - 1)>
|
|
be_val &operator --()
|
|
{
|
|
setValue(value() - 1);
|
|
return *this;
|
|
}
|
|
|
|
template<typename T = Type,
|
|
typename = decltype(std::declval<const T>() - 1)>
|
|
be_val operator --(int)
|
|
{
|
|
auto before = *this;
|
|
setValue(value() - 1);
|
|
return before;
|
|
}
|
|
|
|
template<typename IndexType,
|
|
typename K = value_type>
|
|
auto operator [](const IndexType &index)
|
|
-> decltype(std::declval<K>().operator [](std::declval<IndexType>()))
|
|
{
|
|
return value().operator [](index);
|
|
}
|
|
|
|
template<typename K = value_type>
|
|
auto operator ->()
|
|
-> decltype(std::declval<K>().operator ->())
|
|
{
|
|
return value().operator ->();
|
|
}
|
|
|
|
template<typename K = value_type>
|
|
auto operator ->() const
|
|
-> decltype(std::declval<const K>().operator ->())
|
|
{
|
|
return value().operator ->();
|
|
}
|
|
|
|
template<typename K = value_type>
|
|
auto operator *()
|
|
-> decltype(std::declval<K>().operator *())
|
|
{
|
|
return value().operator *();
|
|
}
|
|
|
|
template<typename K = value_type>
|
|
auto operator *() const
|
|
-> decltype(std::declval<const K>().operator *())
|
|
{
|
|
return value().operator ->();
|
|
}
|
|
|
|
private:
|
|
value_type mStorage;
|
|
};
|