/* SPDX-License-Identifier: BSL-1.0 OR BSD-3-Clause */ #ifndef MPT_ENDIAN_INT24_HPP #define MPT_ENDIAN_INT24_HPP #include "mpt/base/bit.hpp" #include "mpt/base/macros.hpp" #include "mpt/base/memory.hpp" #include "mpt/base/namespace.hpp" #include #include #include #include namespace mpt { inline namespace MPT_INLINE_NS { struct uint24 { std::array bytes; uint24() = default; template ::value, bool>::type = true> explicit uint24(T other) noexcept { using Tunsigned = typename std::make_unsigned::type; MPT_MAYBE_CONSTANT_IF (mpt::endian_is_big()) { bytes[0] = mpt::byte_cast(static_cast((static_cast(other) >> 16) & 0xff)); bytes[1] = mpt::byte_cast(static_cast((static_cast(other) >> 8) & 0xff)); bytes[2] = mpt::byte_cast(static_cast((static_cast(other) >> 0) & 0xff)); } else { bytes[0] = mpt::byte_cast(static_cast((static_cast(other) >> 0) & 0xff)); bytes[1] = mpt::byte_cast(static_cast((static_cast(other) >> 8) & 0xff)); bytes[2] = mpt::byte_cast(static_cast((static_cast(other) >> 16) & 0xff)); } } operator int() const noexcept { MPT_MAYBE_CONSTANT_IF (mpt::endian_is_big()) { return (mpt::byte_cast(bytes[0]) * 65536) + (mpt::byte_cast(bytes[1]) * 256) + mpt::byte_cast(bytes[2]); } else { return (mpt::byte_cast(bytes[2]) * 65536) + (mpt::byte_cast(bytes[1]) * 256) + mpt::byte_cast(bytes[0]); } } }; static_assert(sizeof(uint24) == 3); struct int24 { std::array bytes; int24() = default; template ::value, bool>::type = true> explicit int24(T other) noexcept { using Tunsigned = typename std::make_unsigned::type; MPT_MAYBE_CONSTANT_IF (mpt::endian_is_big()) { bytes[0] = mpt::byte_cast(static_cast((static_cast(other) >> 16) & 0xff)); bytes[1] = mpt::byte_cast(static_cast((static_cast(other) >> 8) & 0xff)); bytes[2] = mpt::byte_cast(static_cast((static_cast(other) >> 0) & 0xff)); } else { bytes[0] = mpt::byte_cast(static_cast((static_cast(other) >> 0) & 0xff)); bytes[1] = mpt::byte_cast(static_cast((static_cast(other) >> 8) & 0xff)); bytes[2] = mpt::byte_cast(static_cast((static_cast(other) >> 16) & 0xff)); } } operator int() const noexcept { MPT_MAYBE_CONSTANT_IF (mpt::endian_is_big()) { return (static_cast(mpt::byte_cast(bytes[0])) * 65536) + (mpt::byte_cast(bytes[1]) * 256) + mpt::byte_cast(bytes[2]); } else { return (static_cast(mpt::byte_cast(bytes[2])) * 65536) + (mpt::byte_cast(bytes[1]) * 256) + mpt::byte_cast(bytes[0]); } } }; static_assert(sizeof(int24) == 3); } // namespace MPT_INLINE_NS } // namespace mpt #if !defined(CPPCHECK) // work-around crash in cppcheck 2.4.1 namespace std { template <> class numeric_limits : public std::numeric_limits { public: static constexpr mpt::uint32 min() noexcept { return 0; } static constexpr mpt::uint32 lowest() noexcept { return 0; } static constexpr mpt::uint32 max() noexcept { return 0x00ffffff; } }; template <> class numeric_limits : public std::numeric_limits { public: static constexpr mpt::int32 min() noexcept { return 0 - 0x00800000; } static constexpr mpt::int32 lowest() noexcept { return 0 - 0x00800000; } static constexpr mpt::int32 max() noexcept { return 0 + 0x007fffff; } }; } // namespace std #endif // !CPPCHECK #endif // MPT_ENDIAN_INT24_HPP