#pragma once #include #include #include #include #include #include #include namespace ircolib { static inline std::vector IntegralToBuffer(const std::integral auto &val) { std::vector ret{}; ret.resize(sizeof(val)); memcpy(ret.data(), &val, sizeof(val)); return ret; } static inline constexpr bool IsInsideRange(const std::integral auto& addr, const std::integral auto& start, const std::integral auto& end) { return addr >= start && addr <= end; } template static constexpr inline T ReadAccess(const u8 *data, const u32 index); template static constexpr inline T ReadAccess(const std::vector &data, const u32 index); template static constexpr inline T ReadAccess(const std::array &data, const u32 index); template static constexpr inline void WriteAccess(u8 *data, const u32 index, const T val); template static constexpr inline void WriteAccess(std::vector &data, const u32 index, const T val); template static constexpr inline void WriteAccess(std::array &data, const u32 index, const T val); template <> constexpr inline u64 ReadAccess(const u8 *data, const u32 index) { u32 hi = *reinterpret_cast(&data[index + 0]); u32 lo = *reinterpret_cast(&data[index + 4]); const auto& result = static_cast(hi) << 32 | static_cast(lo); return result; } template static constexpr inline T ReadAccess(const u8 *data, const u32 index) { return *reinterpret_cast(&data[index]); } template <> constexpr inline u64 ReadAccess(const std::vector &data, const u32 index) { u32 hi = *reinterpret_cast(&data[index + 0]); u32 lo = *reinterpret_cast(&data[index + 4]); return (static_cast(hi) << 32) | static_cast(lo); } template static constexpr inline T ReadAccess(const std::vector &data, const u32 index) { return *reinterpret_cast(&data[index]); } template constexpr inline u64 ReadAccess(const std::array &data, const u32 index) { u32 hi = *reinterpret_cast(&data[index + 0]); u32 lo = *reinterpret_cast(&data[index + 4]); return static_cast(hi) << 32 | static_cast(lo); } template static constexpr inline T ReadAccess(const std::array &data, const u32 index) { return *reinterpret_cast(&data[index]); } template constexpr inline void WriteAccess(std::array &data, const u32 index, const u64 val) { const u32 hi = val >> 32; const u32 lo = val; *reinterpret_cast(&data[index + 0]) = hi; *reinterpret_cast(&data[index + 4]) = lo; } template static constexpr inline void WriteAccess(std::array &data, const u32 index, const T val) { *reinterpret_cast(&data[index]) = val; } template <> constexpr inline void WriteAccess(std::vector &data, const u32 index, const u64 val) { const u32 hi = val >> 32; const u32 lo = val; *reinterpret_cast(&data[index + 0]) = hi; *reinterpret_cast(&data[index + 4]) = lo; } template static constexpr inline void WriteAccess(std::vector &data, const u32 index, const T val) { *reinterpret_cast(&data[index]) = val; } template <> constexpr inline void WriteAccess(u8 *data, const u32 index, const u64 val) { const u32 hi = val >> 32; const u32 lo = val; *reinterpret_cast(&data[index + 0]) = hi; *reinterpret_cast(&data[index + 4]) = lo; } template static constexpr inline void WriteAccess(u8 *data, const u32 index, const T val) { *reinterpret_cast(&data[index]) = val; } template static constexpr inline void SwapBuffer(std::vector &data) { for (size_t i = 0; i < data.size(); i += sizeof(T)) { const T original = *reinterpret_cast(&data[i]); *reinterpret_cast(&data[i]) = std::byteswap(original); } } template static constexpr inline void SwapBuffer(std::array &data) { for (size_t i = 0; i < data.size(); i += sizeof(T)) { const T original = *reinterpret_cast(&data[i]); *reinterpret_cast(&data[i]) = std::byteswap(original); } } #ifdef _WIN32 inline void *aligned_alloc(const size_t alignment, const size_t size) { return _aligned_malloc(size, alignment); } inline void aligned_free(void *ptr) { _aligned_free(ptr); } #else inline void *aligned_alloc(const size_t alignment, const size_t size) { return std::aligned_alloc(alignment, size); } inline void aligned_free(void *ptr) { std::free(ptr); } #endif } // namespace Util