[ox/mc] Make VLI encode/decode constexpr
This commit is contained in:
parent
b33cd06031
commit
f191ade18b
34
deps/ox/src/ox/mc/intops.hpp
vendored
34
deps/ox/src/ox/mc/intops.hpp
vendored
@ -49,22 +49,18 @@ static_assert(highestBit(uint64_t(1) << 31) == 31);
|
||||
static_assert(highestBit(uint64_t(1) << 63) == 63);
|
||||
|
||||
struct McInt {
|
||||
uint8_t data[9];
|
||||
uint8_t data[9] = {0};
|
||||
// length of integer in bytes
|
||||
std::size_t length = 0;
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
#endif
|
||||
|
||||
template<typename I>
|
||||
[[nodiscard]] McInt encodeInteger(I input) noexcept {
|
||||
[[nodiscard]] constexpr McInt encodeInteger(I input) noexcept {
|
||||
McInt out;
|
||||
// move input to uint64_t to allow consistent bit manipulation, and to avoid
|
||||
// overflow concerns
|
||||
uint64_t val = *reinterpret_cast<Unsigned<I>*>(&input);
|
||||
uint64_t val = 0;
|
||||
ox_memcpy(&val, &input, sizeof(I));
|
||||
if (val) {
|
||||
// bits needed to represent number factoring in space possibly
|
||||
// needed for signed bit
|
||||
@ -83,19 +79,20 @@ template<typename I>
|
||||
// move sign bit
|
||||
if constexpr(ox::is_signed<I>) {
|
||||
if (val < 0) {
|
||||
*reinterpret_cast<uint64_t*>(&val) ^= uint64_t(1) << (sizeof(I) * 8 - 1);
|
||||
*reinterpret_cast<uint64_t*>(&val) |= uint64_t(1) << (bitsAvailable - 1);
|
||||
val ^= uint64_t(1) << (sizeof(I) * 8 - 1);
|
||||
val |= uint64_t(1) << (bitsAvailable - 1);
|
||||
}
|
||||
}
|
||||
// ensure we are copying from little endian represenstation
|
||||
LittleEndian<I> leVal = val;
|
||||
if (bytes == 9) {
|
||||
out.data[0] = bytesIndicator;
|
||||
*reinterpret_cast<I*>(&out.data[1]) = leVal.raw();
|
||||
ox_memcpy(&out.data[1], &leVal, sizeof(I));
|
||||
} else {
|
||||
*reinterpret_cast<uint64_t*>(&out.data[0]) =
|
||||
auto intermediate =
|
||||
static_cast<uint64_t>(leVal.raw()) << bytes |
|
||||
static_cast<uint64_t>(bytesIndicator);
|
||||
ox_memcpy(out.data, &intermediate, sizeof(intermediate));
|
||||
}
|
||||
out.length = bytes;
|
||||
}
|
||||
@ -123,11 +120,13 @@ static_assert(countBytes(0b01111111) == 8);
|
||||
static_assert(countBytes(0b11111111) == 9);
|
||||
|
||||
template<typename I>
|
||||
[[nodiscard]] ValErr<I> decodeInteger(uint8_t buff[9], std::size_t buffLen, std::size_t *bytesRead) noexcept {
|
||||
[[nodiscard]] constexpr ValErr<I> decodeInteger(uint8_t buff[9], std::size_t buffLen, std::size_t *bytesRead) noexcept {
|
||||
const auto bytes = countBytes(buff[0]);
|
||||
if (bytes == 9) {
|
||||
*bytesRead = bytes;
|
||||
return {LittleEndian<I>(*reinterpret_cast<I*>(&buff[1])), 0};
|
||||
I out;
|
||||
ox_memcpy(&out, &buff[1], sizeof(I));
|
||||
return {LittleEndian<I>(out), 0};
|
||||
} else if (buffLen >= bytes) {
|
||||
*bytesRead = bytes;
|
||||
uint64_t decoded = 0;
|
||||
@ -142,17 +141,14 @@ template<typename I>
|
||||
// remove sign
|
||||
decoded &= uint64_t(~0) ^ (uint64_t(1) << valBits);
|
||||
// set sign
|
||||
*reinterpret_cast<Unsigned<I>*>(&out) |= sign << (Bits<I> - 1);
|
||||
decoded |= sign << (Bits<I> - 1);
|
||||
ox_memcpy(&out, &decoded, sizeof(out));
|
||||
}
|
||||
return {out, 0};
|
||||
}
|
||||
return {0, OxError(1)};
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
template<typename I>
|
||||
[[nodiscard]] ValErr<I> decodeInteger(McInt m) noexcept {
|
||||
std::size_t bytesRead;
|
||||
|
17
deps/ox/src/ox/std/memops.cpp
vendored
17
deps/ox/src/ox/std/memops.cpp
vendored
@ -23,20 +23,3 @@ int ox_memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept {
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void *ox_memcpy(void *dest, const void *src, std::size_t size) noexcept {
|
||||
auto srcBuf = static_cast<const char*>(src);
|
||||
auto dstBuf = static_cast<char*>(dest);
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
dstBuf[i] = static_cast<char>(srcBuf[i]);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *ox_memset(void *ptr, int val, std::size_t size) noexcept {
|
||||
auto buf = static_cast<char*>(ptr);
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
buf[i] = val;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
17
deps/ox/src/ox/std/memops.hpp
vendored
17
deps/ox/src/ox/std/memops.hpp
vendored
@ -11,6 +11,19 @@
|
||||
|
||||
int ox_memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept;
|
||||
|
||||
void *ox_memcpy(void *dest, const void *src, std::size_t size) noexcept;
|
||||
constexpr void *ox_memcpy(void *dest, const void *src, std::size_t size) noexcept {
|
||||
auto srcBuf = static_cast<const char*>(src);
|
||||
auto dstBuf = static_cast<char*>(dest);
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
dstBuf[i] = static_cast<char>(srcBuf[i]);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *ox_memset(void *ptr, int val, std::size_t size) noexcept;
|
||||
constexpr void *ox_memset(void *ptr, int val, std::size_t size) noexcept {
|
||||
auto buf = static_cast<char*>(ptr);
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
buf[i] = val;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user