f070e484cd
d611a21e5 imma stop using size_t git-subtree-dir: external/ircolib git-subtree-split: d611a21e50fcfdfb5f34a7f79c4c690c50d85c5f
161 lines
5.5 KiB
C++
161 lines
5.5 KiB
C++
#pragma once
|
|
#include "types.hpp"
|
|
#include <cstddef>
|
|
#include <cstring>
|
|
#include <functional>
|
|
#include <bit>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <concepts>
|
|
|
|
namespace ircolib {
|
|
static inline std::vector<u8> integral_to_buffer(const std::integral auto &val) {
|
|
std::vector<u8> ret{};
|
|
ret.resize(sizeof(val));
|
|
|
|
memcpy(ret.data(), &val, sizeof(val));
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline auto integral_to_slice(const std::integral auto &val) -> std::array<u8, sizeof(val)> {
|
|
std::array<u8, sizeof(val)> ret{};
|
|
|
|
memcpy(ret.data(), &val, sizeof(val));
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline constexpr bool is_inside_range(const std::integral auto &addr, const std::integral auto &start,
|
|
const std::integral auto &end) {
|
|
return addr >= start && addr <= end;
|
|
}
|
|
|
|
template <typename T>
|
|
static constexpr inline T read_access(const u8 *data, const u32 index);
|
|
template <typename T>
|
|
static constexpr inline T read_access(const std::vector<u8> &data, const u32 index);
|
|
template <typename T, u32 Size>
|
|
static constexpr inline T read_access(const std::array<u8, Size> &data, const u32 index);
|
|
|
|
template <typename T>
|
|
static constexpr inline void write_access(u8 *data, const u32 index, const T val);
|
|
template <typename T>
|
|
static constexpr inline void write_access(std::vector<u8> &data, const u32 index, const T val);
|
|
template <typename T, u32 Size>
|
|
static constexpr inline void write_access(std::array<u8, Size> &data, const u32 index, const T val);
|
|
|
|
template <>
|
|
constexpr inline u64 read_access(const u8 *data, const u32 index) {
|
|
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
|
|
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
|
|
const auto &result = static_cast<u64>(hi) << 32 | static_cast<u64>(lo);
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
static constexpr inline T read_access(const u8 *data, const u32 index) {
|
|
return *reinterpret_cast<const T *>(&data[index]);
|
|
}
|
|
|
|
template <>
|
|
constexpr inline u64 read_access(const std::vector<u8> &data, const u32 index) {
|
|
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
|
|
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
|
|
return (static_cast<u64>(hi) << 32) | static_cast<u64>(lo);
|
|
}
|
|
|
|
template <typename T>
|
|
static constexpr inline T read_access(const std::vector<u8> &data, const u32 index) {
|
|
return *reinterpret_cast<const T *>(&data[index]);
|
|
}
|
|
|
|
template <u32 Size>
|
|
constexpr inline u64 read_access(const std::array<u8, Size> &data, const u32 index) {
|
|
u32 hi = *reinterpret_cast<const u32 *>(&data[index + 0]);
|
|
u32 lo = *reinterpret_cast<const u32 *>(&data[index + 4]);
|
|
return static_cast<u64>(hi) << 32 | static_cast<u64>(lo);
|
|
}
|
|
|
|
template <typename T, u32 Size>
|
|
static constexpr inline T read_access(const std::array<u8, Size> &data, const u32 index) {
|
|
return *reinterpret_cast<const T *>(&data[index]);
|
|
}
|
|
|
|
template <u32 Size>
|
|
constexpr inline void write_access(std::array<u8, Size> &data, const u32 index, const u64 val) {
|
|
const u32 hi = val >> 32;
|
|
const u32 lo = val;
|
|
|
|
*reinterpret_cast<u32 *>(&data[index + 0]) = hi;
|
|
*reinterpret_cast<u32 *>(&data[index + 4]) = lo;
|
|
}
|
|
|
|
template <typename T, u32 Size>
|
|
static constexpr inline void write_access(std::array<u8, Size> &data, const u32 index, const T val) {
|
|
*reinterpret_cast<T *>(&data[index]) = val;
|
|
}
|
|
|
|
template <>
|
|
constexpr inline void write_access(std::vector<u8> &data, const u32 index, const u64 val) {
|
|
const u32 hi = val >> 32;
|
|
const u32 lo = val;
|
|
|
|
*reinterpret_cast<u32 *>(&data[index + 0]) = hi;
|
|
*reinterpret_cast<u32 *>(&data[index + 4]) = lo;
|
|
}
|
|
|
|
template <typename T>
|
|
static constexpr inline void write_access(std::vector<u8> &data, const u32 index, const T val) {
|
|
*reinterpret_cast<T *>(&data[index]) = val;
|
|
}
|
|
|
|
template <>
|
|
constexpr inline void write_access(u8 *data, const u32 index, const u64 val) {
|
|
const u32 hi = val >> 32;
|
|
const u32 lo = val;
|
|
|
|
*reinterpret_cast<u32 *>(&data[index + 0]) = hi;
|
|
*reinterpret_cast<u32 *>(&data[index + 4]) = lo;
|
|
}
|
|
|
|
template <typename T>
|
|
static constexpr inline void write_access(u8 *data, const u32 index, const T val) {
|
|
*reinterpret_cast<T *>(&data[index]) = val;
|
|
}
|
|
|
|
template <typename T>
|
|
static constexpr inline void swap_buffer(std::vector<u8> &data) {
|
|
for (u32 i = 0; i < data.size(); i += sizeof(T)) {
|
|
const T original = *reinterpret_cast<T *>(&data[i]);
|
|
*reinterpret_cast<T *>(&data[i]) = std::byteswap(original);
|
|
}
|
|
}
|
|
|
|
template <typename T, u32 Size>
|
|
static constexpr inline void swap_buffer(std::array<u8, Size> &data) {
|
|
for (u32 i = 0; i < data.size(); i += sizeof(T)) {
|
|
const T original = *reinterpret_cast<T *>(&data[i]);
|
|
*reinterpret_cast<T *>(&data[i]) = std::byteswap(original);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
static constexpr inline void swap_buffer(u8 *data, u32 size) {
|
|
for (u32 i = 0; i < size; i += sizeof(T)) {
|
|
const T original = *reinterpret_cast<T *>(&data[i]);
|
|
*reinterpret_cast<T *>(&data[i]) = std::byteswap(original);
|
|
}
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
inline void *aligned_alloc(const u32 alignment, const u32 size) { return _aligned_malloc(size, alignment); }
|
|
|
|
inline void aligned_free(void *ptr) { _aligned_free(ptr); }
|
|
#else
|
|
inline void *aligned_alloc(const u32 alignment, const u32 size) { return std::aligned_alloc(alignment, size); }
|
|
|
|
inline void aligned_free(void *ptr) { std::free(ptr); }
|
|
#endif
|
|
} // namespace ircolib
|