diff --git a/libraries/libvapours/include/vapours/defines.hpp b/libraries/libvapours/include/vapours/defines.hpp index 9d0982a8b..629b3723f 100644 --- a/libraries/libvapours/include/vapours/defines.hpp +++ b/libraries/libvapours/include/vapours/defines.hpp @@ -42,6 +42,8 @@ #define CONCATENATE_IMPL(S1, s2) s1##s2 #define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2) +#define BITSIZEOF(x) (sizeof(x) * CHAR_BIT) + #ifdef __COUNTER__ #define ANONYMOUS_VARIABLE(pref) CONCATENATE(pref, __COUNTER__) #else @@ -55,8 +57,8 @@ probability; \ })) -#define AMS_PREDICT_TRUE(expr, probability) AMS_PREDICT(!!expr, 1, probability) -#define AMS_PREDICT_FALSE(expr, probability) AMS_PREDICT(!!expr, 0, probability) +#define AMS_PREDICT_TRUE(expr, probability) AMS_PREDICT(!!(expr), 1, probability) +#define AMS_PREDICT_FALSE(expr, probability) AMS_PREDICT(!!(expr), 0, probability) #define AMS_LIKELY(expr) AMS_PREDICT_TRUE(expr, 1.0) #define AMS_UNLIKELY(expr) AMS_PREDICT_FALSE(expr, 1.0) diff --git a/libraries/libvapours/include/vapours/util.hpp b/libraries/libvapours/include/vapours/util.hpp index c35192e45..a3562c93a 100644 --- a/libraries/libvapours/include/vapours/util.hpp +++ b/libraries/libvapours/include/vapours/util.hpp @@ -20,6 +20,7 @@ #include "util/util_alignment.hpp" #include "util/util_size.hpp" #include "util/util_fourcc.hpp" +#include "util/util_bitpack.hpp" #include "util/util_scope_guard.hpp" #include "util/util_typed_storage.hpp" #include "util/util_intrusive_list.hpp" diff --git a/libraries/libvapours/include/vapours/util/util_bitpack.hpp b/libraries/libvapours/include/vapours/util/util_bitpack.hpp new file mode 100644 index 000000000..ccec50e98 --- /dev/null +++ b/libraries/libvapours/include/vapours/util/util_bitpack.hpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018-2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include "../defines.hpp" + +namespace ams::util { + + namespace impl { + + template + class BitPack { + private: + static_assert(std::is_integral::value); + static_assert(std::is_unsigned::value); + + template + static constexpr inline IntegralStorageType Mask = [] { + static_assert(Index < BITSIZEOF(IntegralStorageType)); + static_assert(0 < Count && Count <= BITSIZEOF(IntegralStorageType)); + static_assert(Index + Count <= BITSIZEOF(IntegralStorageType)); + + return ((IntegralStorageType(1) << Count) - 1) << Index; + }(); + public: + template + struct Field { + using Type = T; + static constexpr size_t Index = _Index; + static constexpr size_t Count = _Count; + static constexpr size_t Next = Index + Count; + + using BitPackType = BitPack; + + static_assert(Mask != 0); + static_assert(std::is_integral::value); + static_assert(!std::is_same::value || Count == 1); + }; + private: + IntegralStorageType value; + public: + constexpr ALWAYS_INLINE void Clear() { + constexpr IntegralStorageType Zero = IntegralStorageType(0); + this->value = Zero; + } + + template + constexpr ALWAYS_INLINE typename FieldType::Type Get() const { + static_assert(std::is_same>::value); + return static_cast((this->value & Mask) >> FieldType::Index); + } + + template + constexpr ALWAYS_INLINE void Set(typename FieldType::Type field_value) { + static_assert(std::is_same>::value); + constexpr IntegralStorageType FieldMask = Mask; + this->value &= ~FieldMask; + this->value |= (static_cast(field_value) << FieldType::Index) & FieldMask; + } + }; + + } + + using BitPack8 = impl::BitPack; + using BitPack16 = impl::BitPack; + using BitPack32 = impl::BitPack; + using BitPack64 = impl::BitPack; + + static_assert(std::is_pod::value); + static_assert(std::is_pod::value); + static_assert(std::is_pod::value); + static_assert(std::is_pod::value); + +}