mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-05 08:49:03 +00:00
Put everything back.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @file binary_utils.h
|
||||
* @brief Declaration of inlines and classes for literal bit manipulation and other low-level operations.
|
||||
* @author Jack (jakcron)
|
||||
* @version 0.1
|
||||
* @date 2020/12/20
|
||||
*/
|
||||
#pragma once
|
||||
#include <tc/types.h>
|
||||
|
||||
namespace tc { namespace bn {
|
||||
|
||||
/**
|
||||
* @brief Generate struct magic 32bit number.
|
||||
* @details This generates a little endian 32bit integer from char[4].
|
||||
*
|
||||
* @param[in] magic Pointer to array of magic bytes.
|
||||
*
|
||||
* @return Little endian magic uint32_t.
|
||||
*/
|
||||
constexpr uint32_t make_struct_magic_uint32(const char magic[4])
|
||||
{
|
||||
return uint32_t((uint32_t)(magic[3]) << 24 | (uint32_t)(magic[2]) << 16 | (uint32_t)(magic[1]) << 8 | (uint32_t)(magic[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate struct magic 64bit number.
|
||||
* @details This generates a little endian 64bit integer from char[8].
|
||||
*
|
||||
* @param[in] magic Pointer to array of magic bytes.
|
||||
*
|
||||
* @return Little endian magic uint64_t.
|
||||
*/
|
||||
constexpr uint64_t make_struct_magic_uint64(const char magic[8])
|
||||
{
|
||||
return uint64_t((uint64_t)(magic[7]) << 56 | (uint64_t)(magic[6]) << 48 | (uint64_t)(magic[5]) << 40 | (uint64_t)(magic[4]) << 32 | (uint64_t)(magic[3]) << 24 | (uint64_t)(magic[2]) << 16 | (uint64_t)(magic[1]) << 8 | (uint64_t)(magic[0]));
|
||||
}
|
||||
|
||||
}} // namespace tc::bn
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @file bitarray.h
|
||||
* @brief Declaration of tc::bn::bitarray
|
||||
* @author Jack (jakcron)
|
||||
* @version 0.2
|
||||
* @date 2021/02/27
|
||||
*/
|
||||
#pragma once
|
||||
#include <tc/types.h>
|
||||
|
||||
namespace tc { namespace bn {
|
||||
|
||||
/**
|
||||
* @struct bitarray
|
||||
* @brief This struct is a literal bitarray, with configurable byte and bit endianness.
|
||||
*
|
||||
* @tparam T size in bytes of the bitarray.
|
||||
* @tparam byte_order_le Boolean, true: byte order is little endian, false: byte order is big endian.
|
||||
* @tparam bit_order_le Boolean, true: bit order is little endian, false: bit order is big endian.
|
||||
*
|
||||
* @details
|
||||
* This struct is meant to be used when defining written-to-disk structures, like file headers.
|
||||
*/
|
||||
template <size_t T, bool byte_order_le = true, bool bit_order_le = true>
|
||||
struct bitarray
|
||||
{
|
||||
public:
|
||||
#define __BITARRAY_BYTE_INDEX_MATH(x) (byte_order_le? (x / 8) : (T - 1 - (x / 8)))
|
||||
#define __BITARRAY_BIT_INDEX_MATH(x) (bit_order_le? (1 << (x % 8)) : (1 << (7 - (x % 8))))
|
||||
|
||||
/// Returns the size in bits of this bitarray
|
||||
size_t bit_size() const { return T * 8; }
|
||||
|
||||
/// Sets a given bit in this bitarray
|
||||
void set(size_t bit)
|
||||
{
|
||||
bit %= (T*8);
|
||||
mArray[__BITARRAY_BYTE_INDEX_MATH(bit)] |= __BITARRAY_BIT_INDEX_MATH(bit);
|
||||
}
|
||||
|
||||
/// Clears a given bit in this bitarray
|
||||
void reset(size_t bit)
|
||||
{
|
||||
bit %= (T*8);
|
||||
mArray[__BITARRAY_BYTE_INDEX_MATH(bit)] &= ~(uint8_t(__BITARRAY_BIT_INDEX_MATH(bit)));
|
||||
}
|
||||
|
||||
/// Flips a given bit in this bitarray
|
||||
void flip(size_t bit)
|
||||
{
|
||||
bit %= (T*8);
|
||||
test(bit) ? reset(bit) : set(bit);
|
||||
}
|
||||
|
||||
/// Checks a given bit in this bitarray
|
||||
bool test(size_t bit) const
|
||||
{
|
||||
bit %= (T*8);
|
||||
return (mArray[__BITARRAY_BYTE_INDEX_MATH(bit)] & (__BITARRAY_BIT_INDEX_MATH(bit))) != 0;
|
||||
}
|
||||
|
||||
#undef __BITARRAY_BYTE_INDEX_MATH
|
||||
#undef __BITARRAY_BIT_INDEX_MATH
|
||||
|
||||
private:
|
||||
std::array<uint8_t, T> mArray;
|
||||
};
|
||||
|
||||
}} // namespace tc::bn
|
||||
@@ -0,0 +1,233 @@
|
||||
/**
|
||||
* @file endian_types.h
|
||||
* @brief Declaration of macros and classes to unwrap primatives in an endian agnostic way.
|
||||
* @author Jack (jakcron)
|
||||
* @version 0.1
|
||||
* @date 2020/12/05
|
||||
**/
|
||||
#pragma once
|
||||
#include <cinttypes>
|
||||
#include <type_traits>
|
||||
|
||||
namespace tc { namespace bn { namespace detail {
|
||||
|
||||
static inline uint16_t __local_bswap16(uint16_t x) {
|
||||
return ((x << 8) & 0xff00) | ((x >> 8) & 0x00ff);
|
||||
}
|
||||
|
||||
static inline void __local_bswap16(void* x) {
|
||||
uint16_t tmp = *((uint16_t*)x);
|
||||
*((uint16_t*)x) = ((tmp << 8) & 0xff00) | ((tmp >> 8) & 0x00ff);
|
||||
}
|
||||
|
||||
static inline uint32_t __local_bswap32(uint32_t x) {
|
||||
return ((x << 24) & 0xff000000 ) |
|
||||
((x << 8) & 0x00ff0000 ) |
|
||||
((x >> 8) & 0x0000ff00 ) |
|
||||
((x >> 24) & 0x000000ff );
|
||||
}
|
||||
|
||||
static inline void __local_bswap32(void* x) {
|
||||
uint32_t tmp = *((uint32_t*)x);
|
||||
*((uint32_t*)x) = ((tmp << 24) & 0xff000000 ) |
|
||||
((tmp << 8) & 0x00ff0000 ) |
|
||||
((tmp >> 8) & 0x0000ff00 ) |
|
||||
((tmp >> 24) & 0x000000ff );
|
||||
}
|
||||
|
||||
static inline uint64_t __local_bswap64(uint64_t x)
|
||||
{
|
||||
return (uint64_t)__local_bswap32(x>>32) |
|
||||
((uint64_t)__local_bswap32(x&0xFFFFFFFF) << 32);
|
||||
}
|
||||
|
||||
static inline void __local_bswap64(void* x) {
|
||||
uint64_t tmp = *((uint64_t*)x);
|
||||
*((uint64_t*)x) = ((uint64_t)(tmp << 56) & (uint64_t)0xff00000000000000ULL ) |
|
||||
((uint64_t)(tmp << 40) & (uint64_t)0x00ff000000000000ULL ) |
|
||||
((uint64_t)(tmp << 24) & (uint64_t)0x0000ff0000000000ULL ) |
|
||||
((uint64_t)(tmp << 8) & (uint64_t)0x000000ff00000000ULL ) |
|
||||
((uint64_t)(tmp >> 8) & (uint64_t)0x00000000ff000000ULL ) |
|
||||
((uint64_t)(tmp >> 24) & (uint64_t)0x0000000000ff0000ULL ) |
|
||||
((uint64_t)(tmp >> 40) & (uint64_t)0x000000000000ff00ULL ) |
|
||||
((uint64_t)(tmp >> 56) & (uint64_t)0x00000000000000ffULL );
|
||||
}
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
static inline uint64_t __be_uint64(uint64_t a) { return __local_bswap64(a); }
|
||||
static inline uint32_t __be_uint32(uint32_t a) { return __local_bswap32(a); }
|
||||
static inline uint16_t __be_uint16(uint16_t a) { return __local_bswap16(a); }
|
||||
static inline uint64_t __le_uint64(uint64_t a) { return a; }
|
||||
static inline uint32_t __le_uint32(uint32_t a) { return a; }
|
||||
static inline uint16_t __le_uint16(uint16_t a) { return a; }
|
||||
|
||||
static inline void __be_swap64(void* a) { __local_bswap64(a); }
|
||||
static inline void __be_swap32(void* a) { __local_bswap32(a); }
|
||||
static inline void __be_swap16(void* a) { __local_bswap16(a); }
|
||||
static inline void __le_swap64(void* a) { return; }
|
||||
static inline void __le_swap32(void* a) { return; }
|
||||
static inline void __le_swap16(void* a) { return; }
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
static inline uint64_t __be_uint64(uint64_t a) { return a; }
|
||||
static inline uint32_t __be_uint32(uint32_t a) { return a; }
|
||||
static inline uint16_t __be_uint16(uint16_t a) { return a; }
|
||||
static inline uint64_t __le_uint64(uint64_t a) { return __local_bswap64(a); }
|
||||
static inline uint32_t __le_uint32(uint32_t a) { return __local_bswap32(a); }
|
||||
static inline uint16_t __le_uint16(uint16_t a) { return __local_bswap16(a); }
|
||||
|
||||
static inline void __be_swap64(void* a) { return; }
|
||||
static inline void __be_swap32(void* a) { return; }
|
||||
static inline void __be_swap16(void* a) { return; }
|
||||
static inline void __le_swap64(void* a) { __local_bswap64(a); }
|
||||
static inline void __le_swap32(void* a) { __local_bswap32(a); }
|
||||
static inline void __le_swap16(void* a) { __local_bswap16(a); }
|
||||
#endif
|
||||
|
||||
}}} // namespace tc::bn::detail
|
||||
|
||||
namespace tc { namespace bn {
|
||||
|
||||
/**
|
||||
* @struct le16
|
||||
* @brief Wrapper that allows accessing a little-endian 16-bit POD regardless of processor endianness
|
||||
**/
|
||||
template <typename T>
|
||||
struct le16 {
|
||||
public:
|
||||
static_assert(sizeof(T) == sizeof(uint16_t), "le16 requires T to be 16 bit.");
|
||||
static_assert(std::is_pod<T>::value, "le16 requires T to be a POD.");
|
||||
|
||||
/// Unwrap value (Implicit)
|
||||
operator T() const { return unwrap(); }
|
||||
/// Wrap value (Implicit)
|
||||
le16& operator=(const T& var) { wrap(var); return *this; }
|
||||
|
||||
/// Unwrap value
|
||||
inline T unwrap() const { T tmp = mVar; detail::__le_swap16(&tmp); return tmp; }
|
||||
/// Wrap value
|
||||
inline void wrap(const T& var) { mVar = var; detail::__le_swap16(&mVar); }
|
||||
private:
|
||||
T mVar;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct be16
|
||||
* @brief Wrapper that allows accessing a big-endian 16-bit POD regardless of processor endianness
|
||||
**/
|
||||
template <typename T>
|
||||
struct be16 {
|
||||
public:
|
||||
static_assert(sizeof(T) == sizeof(uint16_t), "be16 requires T to be 16 bit.");
|
||||
static_assert(std::is_pod<T>::value, "be16 requires T to be a POD.");
|
||||
|
||||
/// Unwrap value (Implicit)
|
||||
operator T() const { return unwrap(); }
|
||||
/// Wrap value (Implicit)
|
||||
be16& operator=(const T& var) { wrap(var); return *this; }
|
||||
|
||||
/// Unwrap value
|
||||
inline T unwrap() const { T tmp = mVar; detail::__be_swap16(&tmp); return tmp; }
|
||||
/// Wrap value
|
||||
inline void wrap(const T& var) { mVar = var; detail::__be_swap16(&mVar); }
|
||||
private:
|
||||
T mVar;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct le32
|
||||
* @brief Wrapper that allows accessing a little-endian 32-bit POD regardless of processor endianness
|
||||
**/
|
||||
template <typename T>
|
||||
struct le32 {
|
||||
public:
|
||||
static_assert(sizeof(T) == sizeof(uint32_t), "le32 requires T to be 32 bit.");
|
||||
static_assert(std::is_pod<T>::value, "le32 requires T to be a POD.");
|
||||
|
||||
/// Unwrap value (Implicit)
|
||||
operator T() const { return unwrap(); }
|
||||
/// Wrap value (Implicit)
|
||||
le32& operator=(const T& var) { wrap(var); return *this; }
|
||||
|
||||
/// Unwrap value
|
||||
inline T unwrap() const { T tmp = mVar; detail::__le_swap32(&tmp); return tmp; }
|
||||
/// Wrap value
|
||||
inline void wrap(const T& var) { mVar = var; detail::__le_swap32(&mVar); }
|
||||
private:
|
||||
T mVar;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct be32
|
||||
* @brief Wrapper that allows accessing a big-endian 32-bit POD regardless of processor endianness
|
||||
**/
|
||||
template <typename T>
|
||||
struct be32 {
|
||||
public:
|
||||
static_assert(sizeof(T) == sizeof(uint32_t), "be32 requires T to be 32 bit.");
|
||||
static_assert(std::is_pod<T>::value, "be32 requires T to be a POD.");
|
||||
|
||||
/// Unwrap value (Implicit)
|
||||
operator T() const { return unwrap(); }
|
||||
/// Wrap value (Implicit)
|
||||
be32& operator=(const T& var) { wrap(var); return *this; }
|
||||
|
||||
/// Unwrap value
|
||||
inline T unwrap() const { T tmp = mVar; detail::__be_swap32(&tmp); return tmp; }
|
||||
/// Wrap value
|
||||
inline void wrap(const T& var) { mVar = var; detail::__be_swap32(&mVar); }
|
||||
private:
|
||||
T mVar;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct le64
|
||||
* @brief Wrapper that allows accessing a little-endian 64-bit POD regardless of processor endianness
|
||||
**/
|
||||
template <typename T>
|
||||
struct le64 {
|
||||
public:
|
||||
static_assert(sizeof(T) == sizeof(uint64_t), "le64 requires T to be 64 bit.");
|
||||
static_assert(std::is_pod<T>::value, "le64 requires T to be a POD.");
|
||||
|
||||
/// Unwrap value (Implicit)
|
||||
operator T() const { return unwrap(); }
|
||||
/// Wrap value (Implicit)
|
||||
le64& operator=(const T& var) { wrap(var); return *this; }
|
||||
|
||||
/// Unwrap value
|
||||
inline T unwrap() const { T tmp = mVar; detail::__le_swap64(&tmp); return tmp; }
|
||||
/// Wrap value
|
||||
inline void wrap(const T& var) { mVar = var; detail::__le_swap64(&mVar); }
|
||||
private:
|
||||
T mVar;
|
||||
};
|
||||
|
||||
/**
|
||||
* @struct be64
|
||||
* @brief Wrapper that allows accessing a big-endian 64-bit POD regardless of processor endianness
|
||||
**/
|
||||
template <typename T>
|
||||
struct be64 {
|
||||
public:
|
||||
static_assert(sizeof(T) == sizeof(uint64_t), "be64 requires T to be 64 bit.");
|
||||
static_assert(std::is_pod<T>::value, "be64 requires T to be a POD.");
|
||||
|
||||
/// Unwrap value (Implicit)
|
||||
operator T() const { return unwrap(); }
|
||||
/// Wrap value (Implicit)
|
||||
be64& operator=(const T& var) { wrap(var); return *this; }
|
||||
|
||||
/// Unwrap value
|
||||
inline T unwrap() const { T tmp = mVar; detail::__be_swap64(&tmp); return tmp; }
|
||||
/// Wrap value
|
||||
inline void wrap(const T& var) { mVar = var; detail::__be_swap64(&mVar); }
|
||||
private:
|
||||
T mVar;
|
||||
};
|
||||
|
||||
}} // namespace tc::bn
|
||||
|
||||
namespace tc { namespace bn {
|
||||
|
||||
|
||||
}} // namespace tc::bn
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @file pad.h
|
||||
* @brief Declaration of tc::bn::pad
|
||||
* @author Jack (jakcron)
|
||||
* @version 0.2
|
||||
* @date 2022/02/05
|
||||
*/
|
||||
#pragma once
|
||||
#include <tc/types.h>
|
||||
|
||||
namespace tc { namespace bn {
|
||||
|
||||
/**
|
||||
* @class pad
|
||||
* @brief This class creates padding.
|
||||
*
|
||||
* @tparam T size in bytes of the padding.
|
||||
*/
|
||||
template <size_t T>
|
||||
class pad
|
||||
{
|
||||
public:
|
||||
/// Returns size of padding in bytes
|
||||
size_t size() const { return mArray.size(); }
|
||||
private:
|
||||
std::array<uint8_t, T> mArray;
|
||||
};
|
||||
|
||||
}} // namespace tc::bn
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* @file string.h
|
||||
* @brief Declaration of tc::bn::string
|
||||
* @author Jack (jakcron)
|
||||
* @version 0.3
|
||||
* @date 2022/02/05
|
||||
*/
|
||||
#pragma once
|
||||
#include <tc/types.h>
|
||||
|
||||
namespace tc { namespace bn {
|
||||
|
||||
/**
|
||||
* @class string
|
||||
* @brief This class represents a literal char array.
|
||||
*
|
||||
* @tparam ENCODED_SIZE Literal size of the string structure. sizeof() will return this size.
|
||||
* @tparam LOGICAL_SIZE Logical maximum size of the string, LOGICAL_SIZE <= ENCODED_SIZE.
|
||||
*
|
||||
* @details The intended for use is for defining structures read from files.
|
||||
*
|
||||
* Consider this structure read from a file with some comments from the spec:
|
||||
* @code
|
||||
* struct MyStruct
|
||||
* {
|
||||
* uint32_t version;
|
||||
* char product_sku[16]; // ASCII but not NULL terminated, so 16 usable characters
|
||||
* char product_title[32]; // ASCII but must be NULL terminated, so only 31 usable chars
|
||||
* uint32_t product_version;
|
||||
* };
|
||||
* @endcode
|
||||
* The member @c product_sku according to specification can have all 16 chars populated, and if all 16 chars
|
||||
* are populated it isn't guarenteed to be null terminated. The member @c product_title according to specification
|
||||
* must be null terminated, reserving one byte for the null byte. This isn't the same behaviour as @c product_sku,
|
||||
* requiring different string logic specific to this one struct. But these constraints can be enforced into the
|
||||
* defintion of MyStruct using @ref tc::bn::string.
|
||||
*
|
||||
* Consider this revised struct using tc::bn::string :
|
||||
* @code
|
||||
* struct MyStruct
|
||||
* {
|
||||
* uint32_t version;
|
||||
* tc::bn::string<16> product_sku; // this has a ENCODED_SIZE & LOGICAL_SIZE of 16 bytes which mean's the size on disk is 16 bytes and there are 16 usable characters
|
||||
* tc::bn::string<32,31> product_title; // this has a ENCODED_SIZE of 32 bytes & LOGICAL_SIZE of 31 bytes which mean's the size on disk is 32 bytes and there are 31 usable characters
|
||||
* uint32_t product_version;
|
||||
* };
|
||||
* @endcode
|
||||
* In the above struct the correct size of @c product_sku and @c product_title are preserved while also enforcing the logical size of the string.
|
||||
*
|
||||
* To get the maximum length a string can be for a given tc::bn::string, use @ref max_size():
|
||||
* @code
|
||||
* MyStruct st;
|
||||
* size_t product_sku_max_size = st.product_sku.max_size(); // 16
|
||||
* size_t product_title_max_size = st.product_title.max_size(); // 31
|
||||
* @endcode
|
||||
*
|
||||
* To get the current string length for a given tc::bn::string, use @ref size():
|
||||
* @code
|
||||
* MyStruct st;
|
||||
* size_t product_sku_str_size = st.product_sku.size();
|
||||
* size_t product_title_str_size = st.product_title.size();
|
||||
* @endcode
|
||||
*
|
||||
* To decode the data in a tc::bn::string to a std::string, use @ref decode():
|
||||
* @code
|
||||
* MyStruct st;
|
||||
* std::string product_sku = st.product_sku.decode();
|
||||
* std::string product_title = st.product_title.decode();
|
||||
* @endcode
|
||||
*
|
||||
* To encode a std::string into a tc::bn::string, use @ref encode():
|
||||
* @code
|
||||
* MyStruct st;
|
||||
* st.product_sku.encode("SKU-1234-X");
|
||||
* st.product_title.encode("MyProductTitle");
|
||||
* @endcode
|
||||
*/
|
||||
template <size_t ENCODED_SIZE, size_t LOGICAL_SIZE = ENCODED_SIZE>
|
||||
class string
|
||||
{
|
||||
public:
|
||||
static_assert(ENCODED_SIZE >= LOGICAL_SIZE, "literal string had a logical size greater than the encoded size.");
|
||||
|
||||
/// Access specific element
|
||||
const char& operator[](size_t index) const { return mRawString[index]; }
|
||||
|
||||
/// Access specific element
|
||||
char& operator[](size_t index) { return mRawString[index]; }
|
||||
|
||||
/// Direct access to the underlying array
|
||||
const char* data() const { return mRawString.data(); }
|
||||
|
||||
/// Direct access to the underlying array
|
||||
char* data() { return mRawString.data(); }
|
||||
|
||||
/// Returns maximum possible length for this string
|
||||
size_t max_size() const { return LOGICAL_SIZE; }
|
||||
|
||||
/// Returns length of string
|
||||
size_t size() const
|
||||
{
|
||||
size_t chr_count = 0;
|
||||
|
||||
for (; chr_count < LOGICAL_SIZE; chr_count++)
|
||||
{
|
||||
if (mRawString[chr_count] == 0) break;
|
||||
}
|
||||
|
||||
return chr_count;
|
||||
}
|
||||
|
||||
/// Returns a std::string created from the underlying char array
|
||||
std::string decode() const { return std::string(this->data(), this->size()); }
|
||||
|
||||
/// Encode the underlying char array from a std::string
|
||||
void encode(const std::string& source_str)
|
||||
{
|
||||
size_t chr_count = 0;
|
||||
|
||||
// copy chars from source_str
|
||||
for (; chr_count < LOGICAL_SIZE; chr_count++)
|
||||
{
|
||||
// skip if chr count exceeds the size of the string, or the string char is null byte
|
||||
if (chr_count >= source_str.size()) break;
|
||||
if (source_str[chr_count] == 0) break;
|
||||
|
||||
mRawString[chr_count] = source_str[chr_count];
|
||||
}
|
||||
|
||||
// clear remaining chars
|
||||
for (; chr_count < LOGICAL_SIZE; chr_count++)
|
||||
{
|
||||
mRawString[chr_count] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<char, ENCODED_SIZE> mRawString;
|
||||
};
|
||||
|
||||
}} // namespace tc::bn
|
||||
Reference in New Issue
Block a user