src: more work on constexpr
This commit is contained in:
parent
e0633b89bb
commit
f65c8f8c6f
195
src/bele.h
195
src/bele.h
@ -32,7 +32,8 @@
|
||||
// NE - Native Endianness (aka Host Endianness aka CPU Endianness)
|
||||
// TE - Target Endianness (not used here, see various packers)
|
||||
|
||||
static_assert(std::is_same_v<unsigned, upx_uint32_t>);
|
||||
static_assert(std::is_same_v<upx_uint32_t, unsigned>);
|
||||
static_assert(std::is_same_v<byte, unsigned char>);
|
||||
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
#define bele_constexpr constexpr
|
||||
@ -109,14 +110,9 @@ using enable_if_xe64 = std::enable_if_t<is_xe64_type<T>, T>;
|
||||
|
||||
forceinline bele_constexpr unsigned get_ne16(const byte *p) noexcept {
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated()) {
|
||||
typedef unsigned U;
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
return (U(p[0]) << 8) | (U(p[1]) << 0);
|
||||
#else
|
||||
return (U(p[0]) << 0) | (U(p[1]) << 8);
|
||||
#endif
|
||||
} else
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::get_ne16(p);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
upx_uint16_t v = 0;
|
||||
@ -127,14 +123,9 @@ forceinline bele_constexpr unsigned get_ne16(const byte *p) noexcept {
|
||||
|
||||
forceinline bele_constexpr unsigned get_ne32(const byte *p) noexcept {
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated()) {
|
||||
typedef unsigned U;
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
return (U(p[0]) << 24) | (U(p[1]) << 16) | (U(p[2]) << 8) | (U(p[3]) << 0);
|
||||
#else
|
||||
return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16) | (U(p[3]) << 24);
|
||||
#endif
|
||||
} else
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::get_ne32(p);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
upx_uint32_t v = 0;
|
||||
@ -145,16 +136,9 @@ forceinline bele_constexpr unsigned get_ne32(const byte *p) noexcept {
|
||||
|
||||
forceinline bele_constexpr upx_uint64_t get_ne64(const byte *p) noexcept {
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated()) {
|
||||
typedef upx_uint64_t U;
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
return (U(p[0]) << 56) | (U(p[1]) << 48) | (U(p[2]) << 40) | (U(p[3]) << 32) |
|
||||
(U(p[4]) << 24) | (U(p[5]) << 16) | (U(p[6]) << 8) | (U(p[7]) << 0);
|
||||
#else
|
||||
return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16) | (U(p[3]) << 24) |
|
||||
(U(p[4]) << 32) | (U(p[5]) << 40) | (U(p[6]) << 48) | (U(p[7]) << 56);
|
||||
#endif
|
||||
} else
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::get_ne64(p);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
upx_uint64_t v = 0;
|
||||
@ -165,37 +149,21 @@ forceinline bele_constexpr upx_uint64_t get_ne64(const byte *p) noexcept {
|
||||
|
||||
forceinline bele_constexpr void set_ne16(byte *p, unsigned v) noexcept {
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated()) {
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
p[0] = byte((v >> 8) & 0xff);
|
||||
p[1] = byte((v >> 0) & 0xff);
|
||||
#else
|
||||
p[0] = byte((v >> 0) & 0xff);
|
||||
p[1] = byte((v >> 8) & 0xff);
|
||||
#endif
|
||||
} else
|
||||
if (upx_is_constant_evaluated())
|
||||
upx::compile_time::set_ne16(p, upx_uint16_t(v & 0xffff));
|
||||
else
|
||||
#endif
|
||||
{
|
||||
upx_uint16_t vv = (upx_uint16_t) (v & 0xffff);
|
||||
upx_uint16_t vv = upx_uint16_t(v & 0xffff);
|
||||
upx_memcpy_inline(p, &vv, sizeof(vv));
|
||||
}
|
||||
}
|
||||
|
||||
forceinline bele_constexpr void set_ne32(byte *p, unsigned v) noexcept {
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated()) {
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
p[0] = byte((v >> 24) & 0xff);
|
||||
p[1] = byte((v >> 16) & 0xff);
|
||||
p[2] = byte((v >> 8) & 0xff);
|
||||
p[3] = byte((v >> 0) & 0xff);
|
||||
#else
|
||||
p[0] = byte((v >> 0) & 0xff);
|
||||
p[1] = byte((v >> 8) & 0xff);
|
||||
p[2] = byte((v >> 16) & 0xff);
|
||||
p[3] = byte((v >> 24) & 0xff);
|
||||
#endif
|
||||
} else
|
||||
if (upx_is_constant_evaluated())
|
||||
upx::compile_time::set_ne32(p, v);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
upx_uint32_t vv = v;
|
||||
@ -205,27 +173,9 @@ forceinline bele_constexpr void set_ne32(byte *p, unsigned v) noexcept {
|
||||
|
||||
forceinline bele_constexpr void set_ne64(byte *p, upx_uint64_t v) noexcept {
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated()) {
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
p[0] = byte((v >> 56) & 0xff);
|
||||
p[1] = byte((v >> 48) & 0xff);
|
||||
p[2] = byte((v >> 40) & 0xff);
|
||||
p[3] = byte((v >> 32) & 0xff);
|
||||
p[4] = byte((v >> 24) & 0xff);
|
||||
p[5] = byte((v >> 16) & 0xff);
|
||||
p[6] = byte((v >> 8) & 0xff);
|
||||
p[7] = byte((v >> 0) & 0xff);
|
||||
#else
|
||||
p[0] = byte((v >> 0) & 0xff);
|
||||
p[1] = byte((v >> 8) & 0xff);
|
||||
p[2] = byte((v >> 16) & 0xff);
|
||||
p[3] = byte((v >> 24) & 0xff);
|
||||
p[4] = byte((v >> 32) & 0xff);
|
||||
p[5] = byte((v >> 40) & 0xff);
|
||||
p[6] = byte((v >> 48) & 0xff);
|
||||
p[7] = byte((v >> 56) & 0xff);
|
||||
#endif
|
||||
} else
|
||||
if (upx_is_constant_evaluated())
|
||||
upx::compile_time::set_ne64(p, v);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
upx_uint64_t vv = v;
|
||||
@ -274,7 +224,7 @@ forceinline bele_constexpr void set_ne64(XE64 *p, upx_uint64_t v) noexcept {
|
||||
#if __cpp_lib_byteswap >= 202110L
|
||||
|
||||
forceinline constexpr unsigned bswap16(unsigned v) noexcept {
|
||||
return std::byteswap((upx_uint16_t) (v & 0xffff));
|
||||
return std::byteswap(upx_uint16_t(v & 0xffff));
|
||||
}
|
||||
forceinline constexpr unsigned bswap32(unsigned v) noexcept { return std::byteswap(v); }
|
||||
forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept { return std::byteswap(v); }
|
||||
@ -283,30 +233,45 @@ forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept { return std
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4)
|
||||
|
||||
// unfortunately *not* constexpr with current MSVC
|
||||
forceinline /*constexpr*/ unsigned bswap16(unsigned v) noexcept {
|
||||
return (unsigned) _byteswap_ulong(v << 16);
|
||||
// _byteswap_XXX is unfortunately *not* constexpr with current MSVC
|
||||
forceinline bele_constexpr unsigned bswap16(unsigned v) noexcept {
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::bswap16(upx_uint16_t(v & 0xffff));
|
||||
else
|
||||
#endif
|
||||
return (unsigned) _byteswap_ulong(v << 16);
|
||||
}
|
||||
forceinline /*constexpr*/ unsigned bswap32(unsigned v) noexcept {
|
||||
return (unsigned) _byteswap_ulong(v);
|
||||
forceinline bele_constexpr unsigned bswap32(unsigned v) noexcept {
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::bswap32(v);
|
||||
else
|
||||
#endif
|
||||
return (unsigned) _byteswap_ulong(v);
|
||||
}
|
||||
forceinline /*constexpr*/ upx_uint64_t bswap64(upx_uint64_t v) noexcept {
|
||||
return _byteswap_uint64(v);
|
||||
forceinline bele_constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept {
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::bswap64(v);
|
||||
else
|
||||
#endif
|
||||
return _byteswap_uint64(v);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
forceinline constexpr unsigned bswap16(unsigned v) noexcept {
|
||||
#if defined(__riscv) && __riscv_xlen == 64
|
||||
return (unsigned) __builtin_bswap64((upx_uint64_t) v << 48);
|
||||
return (unsigned) __builtin_bswap64(upx_uint64_t(v) << 48);
|
||||
#else
|
||||
// return __builtin_bswap16((upx_uint16_t) (v & 0xffff));
|
||||
// return __builtin_bswap16(upx_uint16_t(v & 0xffff));
|
||||
return __builtin_bswap32(v << 16);
|
||||
#endif
|
||||
}
|
||||
forceinline constexpr unsigned bswap32(unsigned v) noexcept {
|
||||
#if defined(__riscv) && __riscv_xlen == 64
|
||||
return (unsigned) __builtin_bswap64((upx_uint64_t) v << 32);
|
||||
return (unsigned) __builtin_bswap64(upx_uint64_t(v) << 32);
|
||||
#else
|
||||
return __builtin_bswap32(v);
|
||||
#endif
|
||||
@ -389,42 +354,26 @@ inline bele_constexpr void set_le64(XE64 *p, upx_uint64_t v) noexcept {
|
||||
**************************************************************************/
|
||||
|
||||
inline constexpr unsigned get_be24(const byte *p) noexcept {
|
||||
typedef unsigned U;
|
||||
return (U(p[0]) << 16) | (U(p[1]) << 8) | (U(p[2]) << 0);
|
||||
return upx::compile_time::get_be24(p);
|
||||
}
|
||||
|
||||
inline constexpr unsigned get_le24(const byte *p) noexcept {
|
||||
typedef unsigned U;
|
||||
return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16);
|
||||
}
|
||||
|
||||
inline constexpr void set_be24(byte *p, unsigned v) noexcept {
|
||||
p[0] = byte((v >> 16) & 0xff);
|
||||
p[1] = byte((v >> 8) & 0xff);
|
||||
p[2] = byte((v >> 0) & 0xff);
|
||||
}
|
||||
|
||||
inline constexpr void set_le24(byte *p, unsigned v) noexcept {
|
||||
p[0] = byte((v >> 0) & 0xff);
|
||||
p[1] = byte((v >> 8) & 0xff);
|
||||
p[2] = byte((v >> 16) & 0xff);
|
||||
return upx::compile_time::get_le24(p);
|
||||
}
|
||||
inline constexpr void set_be24(byte *p, unsigned v) noexcept { upx::compile_time::set_be24(p, v); }
|
||||
inline constexpr void set_le24(byte *p, unsigned v) noexcept { upx::compile_time::set_le24(p, v); }
|
||||
|
||||
REQUIRE_XE24
|
||||
forceinline bele_constexpr unsigned get_be24(const XE24 *p) noexcept {
|
||||
return get_be24(upx::ptr_static_cast<const byte *>(p));
|
||||
}
|
||||
|
||||
REQUIRE_XE24
|
||||
forceinline bele_constexpr unsigned get_le24(const XE24 *p) noexcept {
|
||||
return get_le24(upx::ptr_static_cast<const byte *>(p));
|
||||
}
|
||||
|
||||
REQUIRE_XE24
|
||||
forceinline bele_constexpr void set_be24(XE24 *p, unsigned v) noexcept {
|
||||
set_be24(upx::ptr_static_cast<byte *>(p), v);
|
||||
}
|
||||
|
||||
REQUIRE_XE24
|
||||
forceinline bele_constexpr void set_le24(XE24 *p, unsigned v) noexcept {
|
||||
set_le24(upx::ptr_static_cast<byte *>(p), v);
|
||||
@ -594,7 +543,12 @@ struct alignas(1) BE16 final {
|
||||
}
|
||||
|
||||
bele_constexpr bool operator==(const BE16 &x) const noexcept {
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::mem_eq(d, x.d, sizeof(d));
|
||||
else
|
||||
#endif
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
}
|
||||
bele_constexpr bool operator<(const BE16 &x) const noexcept {
|
||||
return unsigned(*this) < unsigned(x);
|
||||
@ -656,7 +610,12 @@ struct alignas(1) BE32 final {
|
||||
}
|
||||
|
||||
bele_constexpr bool operator==(const BE32 &x) const noexcept {
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::mem_eq(d, x.d, sizeof(d));
|
||||
else
|
||||
#endif
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
}
|
||||
bele_constexpr bool operator<(const BE32 &x) const noexcept {
|
||||
return unsigned(*this) < unsigned(x);
|
||||
@ -718,7 +677,12 @@ struct alignas(1) BE64 final {
|
||||
}
|
||||
|
||||
bele_constexpr bool operator==(const BE64 &x) const noexcept {
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::mem_eq(d, x.d, sizeof(d));
|
||||
else
|
||||
#endif
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
}
|
||||
bele_constexpr bool operator<(const BE64 &x) const noexcept {
|
||||
return upx_uint64_t(*this) < upx_uint64_t(x);
|
||||
@ -780,7 +744,12 @@ struct alignas(1) LE16 final {
|
||||
}
|
||||
|
||||
bele_constexpr bool operator==(const LE16 &x) const noexcept {
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::mem_eq(d, x.d, sizeof(d));
|
||||
else
|
||||
#endif
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
}
|
||||
bele_constexpr bool operator<(const LE16 &x) const noexcept {
|
||||
return unsigned(*this) < unsigned(x);
|
||||
@ -842,7 +811,12 @@ struct alignas(1) LE32 final {
|
||||
}
|
||||
|
||||
bele_constexpr bool operator==(const LE32 &x) const noexcept {
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::mem_eq(d, x.d, sizeof(d));
|
||||
else
|
||||
#endif
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
}
|
||||
bele_constexpr bool operator<(const LE32 &x) const noexcept {
|
||||
return unsigned(*this) < unsigned(x);
|
||||
@ -904,7 +878,12 @@ struct alignas(1) LE64 final {
|
||||
}
|
||||
|
||||
bele_constexpr bool operator==(const LE64 &x) const noexcept {
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
if (upx_is_constant_evaluated())
|
||||
return upx::compile_time::mem_eq(d, x.d, sizeof(d));
|
||||
else
|
||||
#endif
|
||||
return upx_memcmp_inline(d, x.d, sizeof(d)) == 0;
|
||||
}
|
||||
bele_constexpr bool operator<(const LE64 &x) const noexcept {
|
||||
return upx_uint64_t(*this) < upx_uint64_t(x);
|
||||
|
||||
@ -96,51 +96,49 @@ int upx_doctest_check() { return upx_doctest_check(0, nullptr); }
|
||||
// compile-time checks
|
||||
**************************************************************************/
|
||||
|
||||
// need extra parenthesis because the C preprocessor does not understand C++ templates
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<short, upx_int16_t>::value))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<unsigned short, upx_uint16_t>::value))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<int, upx_int32_t>::value))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<unsigned, upx_uint32_t>::value))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<long long, upx_int64_t>::value))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same<unsigned long long, upx_uint64_t>::value))
|
||||
static_assert(std::is_same<short, upx_int16_t>::value);
|
||||
static_assert(std::is_same<unsigned short, upx_uint16_t>::value);
|
||||
static_assert(std::is_same<int, upx_int32_t>::value);
|
||||
static_assert(std::is_same<unsigned, upx_uint32_t>::value);
|
||||
static_assert(std::is_same<long long, upx_int64_t>::value);
|
||||
static_assert(std::is_same<unsigned long long, upx_uint64_t>::value);
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap16(0x04030201) == 0x0201)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap32(0x04030201) == 0x04030201)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap64(0x0807060504030201ull) == 0x0807060504030201ull)
|
||||
static_assert(no_bswap16(0x04030201) == 0x0201);
|
||||
static_assert(no_bswap32(0x04030201) == 0x04030201);
|
||||
static_assert(no_bswap64(0x0807060504030201ull) == 0x0807060504030201ull);
|
||||
#if !(ACC_CC_MSC) // unfortunately *not* constexpr with current MSVC
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(bswap16(0x04030201) == 0x0102)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(bswap32(0x04030201) == 0x01020304)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(bswap64(0x0807060504030201ull) == 0x0102030405060708ull)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(bswap16(bswap16(0xf4f3f2f1)) == no_bswap16(0xf4f3f2f1))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(bswap32(bswap32(0xf4f3f2f1)) == no_bswap32(0xf4f3f2f1))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(bswap64(bswap64(0xf8f7f6f5f4f3f2f1ull)) ==
|
||||
no_bswap64(0xf8f7f6f5f4f3f2f1ull))
|
||||
static_assert(bswap16(0x04030201) == 0x0102);
|
||||
static_assert(bswap32(0x04030201) == 0x01020304);
|
||||
static_assert(bswap64(0x0807060504030201ull) == 0x0102030405060708ull);
|
||||
static_assert(bswap16(bswap16(0xf4f3f2f1)) == no_bswap16(0xf4f3f2f1));
|
||||
static_assert(bswap32(bswap32(0xf4f3f2f1)) == no_bswap32(0xf4f3f2f1));
|
||||
static_assert(bswap64(bswap64(0xf8f7f6f5f4f3f2f1ull)) == no_bswap64(0xf8f7f6f5f4f3f2f1ull));
|
||||
#endif
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 0, 8) == 0)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 1, 8) == 1)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 127, 8) == 127)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 128, 8) == -128)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u - 1, 8) == -1)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 256, 8) == 0)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 257, 8) == 1)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 383, 8) == 127)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 384, 8) == -128)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 511, 8) == -1)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0ull + 0, 1) == 0)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0ull + 1, 1) == -1)
|
||||
static_assert(sign_extend(0u + 0, 8) == 0);
|
||||
static_assert(sign_extend(0u + 1, 8) == 1);
|
||||
static_assert(sign_extend(0u + 127, 8) == 127);
|
||||
static_assert(sign_extend(0u + 128, 8) == -128);
|
||||
static_assert(sign_extend(0u - 1, 8) == -1);
|
||||
static_assert(sign_extend(0u + 256, 8) == 0);
|
||||
static_assert(sign_extend(0u + 257, 8) == 1);
|
||||
static_assert(sign_extend(0u + 383, 8) == 127);
|
||||
static_assert(sign_extend(0u + 384, 8) == -128);
|
||||
static_assert(sign_extend(0u + 511, 8) == -1);
|
||||
static_assert(sign_extend(0ull + 0, 1) == 0);
|
||||
static_assert(sign_extend(0ull + 1, 1) == -1);
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_BIT == 8)
|
||||
static_assert(CHAR_BIT == 8);
|
||||
#if 0 // does not work with MSVC
|
||||
#if '\0' - 1 < 0
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 127)
|
||||
static_assert(CHAR_MAX == 127);
|
||||
#else
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 255)
|
||||
static_assert(CHAR_MAX == 255);
|
||||
#endif
|
||||
#if L'\0' - 1 < 0
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((wchar_t) -1 < 0)
|
||||
static_assert((wchar_t) -1 < 0);
|
||||
#else
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((wchar_t) -1 > 0)
|
||||
static_assert((wchar_t) -1 > 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -734,6 +732,14 @@ void upx_compiler_sanity_check(void) noexcept {
|
||||
0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0,
|
||||
0, 0, 0, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0, 0, 0, 0, 0};
|
||||
constexpr const byte *d = dd + 7;
|
||||
static_assert(upx::compile_time::get_be16(d) == 0xfffe);
|
||||
static_assert(upx::compile_time::get_be24(d) == 0xfffefd);
|
||||
static_assert(upx::compile_time::get_be32(d) == 0xfffefdfc);
|
||||
static_assert(upx::compile_time::get_be64(d) == 0xfffefdfcfbfaf9f8ULL);
|
||||
static_assert(upx::compile_time::get_le16(d) == 0xfeff);
|
||||
static_assert(upx::compile_time::get_le24(d) == 0xfdfeff);
|
||||
static_assert(upx::compile_time::get_le32(d) == 0xfcfdfeff);
|
||||
static_assert(upx::compile_time::get_le64(d) == 0xf8f9fafbfcfdfeffULL);
|
||||
const N_BELE_RTP::AbstractPolicy *bele;
|
||||
assert_noexcept(upx_adler32(d, 4) == 0x09f003f7);
|
||||
assert_noexcept(upx_adler32(d, 4, 0) == 0x09ec03f6);
|
||||
@ -762,19 +768,19 @@ void upx_compiler_sanity_check(void) noexcept {
|
||||
assert_noexcept(get_le32_signed(d) == -50462977);
|
||||
assert_noexcept(get_le64(d) == 0xf8f9fafbfcfdfeffULL);
|
||||
assert_noexcept(get_le64_signed(d) == -506097522914230529LL);
|
||||
static_assert(get_be24(d) == 0xfffefd);
|
||||
static_assert(get_le24(d) == 0xfdfeff);
|
||||
#if defined(upx_is_constant_evaluated)
|
||||
static_assert(get_be24_signed(d) == -259);
|
||||
static_assert(get_le24_signed(d) == -131329);
|
||||
static_assert(get_be16(d) == 0xfffe);
|
||||
static_assert(get_be16_signed(d) == -2);
|
||||
static_assert(get_be24(d) == 0xfffefd);
|
||||
static_assert(get_be24_signed(d) == -259);
|
||||
static_assert(get_be32(d) == 0xfffefdfc);
|
||||
static_assert(get_be32_signed(d) == -66052);
|
||||
static_assert(get_be64(d) == 0xfffefdfcfbfaf9f8ULL);
|
||||
static_assert(get_be64_signed(d) == -283686952306184LL);
|
||||
static_assert(get_le16(d) == 0xfeff);
|
||||
static_assert(get_le16_signed(d) == -257);
|
||||
static_assert(get_le24(d) == 0xfdfeff);
|
||||
static_assert(get_le24_signed(d) == -131329);
|
||||
static_assert(get_le32(d) == 0xfcfdfeff);
|
||||
static_assert(get_le32_signed(d) == -50462977);
|
||||
static_assert(get_le64(d) == 0xf8f9fafbfcfdfeffULL);
|
||||
|
||||
@ -35,82 +35,100 @@
|
||||
// compile-time checks
|
||||
**************************************************************************/
|
||||
|
||||
// need extra parenthesis because the C preprocessor does not understand C++ templates
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_all_v<int>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_all_v<int, int>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_all_v<int, int, int>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_all_v<int, char>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_all_v<int, char, int>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_all_v<int, int, char>) )
|
||||
static_assert(upx::is_same_all_v<int>);
|
||||
static_assert(upx::is_same_all_v<int, int>);
|
||||
static_assert(upx::is_same_all_v<int, int, int>);
|
||||
static_assert(!upx::is_same_all_v<int, char>);
|
||||
static_assert(!upx::is_same_all_v<int, char, int>);
|
||||
static_assert(!upx::is_same_all_v<int, int, char>);
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v<int>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v<int, int>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v<int, char, int>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v<int, int, char>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v<int, char>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v<int, char, char>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v<int, char, long>) )
|
||||
static_assert(!upx::is_same_any_v<int>);
|
||||
static_assert(upx::is_same_any_v<int, int>);
|
||||
static_assert(upx::is_same_any_v<int, char, int>);
|
||||
static_assert(upx::is_same_any_v<int, int, char>);
|
||||
static_assert(!upx::is_same_any_v<int, char>);
|
||||
static_assert(!upx::is_same_any_v<int, char, char>);
|
||||
static_assert(!upx::is_same_any_v<int, char, long>);
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v<ptrdiff_t, int, long, long long>) )
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(
|
||||
(upx::is_same_any_v<size_t, unsigned, unsigned long, unsigned long long>) )
|
||||
static_assert(upx::is_same_any_v<ptrdiff_t, int, long, long long>);
|
||||
static_assert(upx::is_same_any_v<size_t, unsigned, unsigned long, unsigned long long>);
|
||||
// TODO later: CHERI
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(
|
||||
(upx::is_same_any_v<upx_uintptr_t, unsigned, unsigned long, unsigned long long>) )
|
||||
static_assert(upx::is_same_any_v<upx_uintptr_t, unsigned, unsigned long, unsigned long long>);
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(int) == sizeof(int))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof('a') == sizeof(char))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof("") == 1)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof("a") == 2)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof("ab") == 3)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(L'a') == sizeof(wchar_t))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(L"") == 1 * sizeof(wchar_t))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(L"a") == 2 * sizeof(wchar_t))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(L"ab") == 3 * sizeof(wchar_t))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(0) == sizeof(int))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(0L) == sizeof(long))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(0LL) == sizeof(long long))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(nullptr) == sizeof(void *))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(sizeof(0)) == sizeof(size_t))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(usizeof(0)) == sizeof(unsigned))
|
||||
static_assert(usizeof(int) == sizeof(int));
|
||||
static_assert(usizeof('a') == sizeof(char));
|
||||
static_assert(usizeof("") == 1);
|
||||
static_assert(usizeof("a") == 2);
|
||||
static_assert(usizeof("ab") == 3);
|
||||
static_assert(usizeof(L'a') == sizeof(wchar_t));
|
||||
static_assert(usizeof(L"") == 1 * sizeof(wchar_t));
|
||||
static_assert(usizeof(L"a") == 2 * sizeof(wchar_t));
|
||||
static_assert(usizeof(L"ab") == 3 * sizeof(wchar_t));
|
||||
static_assert(usizeof(0) == sizeof(int));
|
||||
static_assert(usizeof(0L) == sizeof(long));
|
||||
static_assert(usizeof(0LL) == sizeof(long long));
|
||||
static_assert(usizeof(nullptr) == sizeof(void *));
|
||||
static_assert(usizeof(sizeof(0)) == sizeof(size_t));
|
||||
static_assert(usizeof(usizeof(0)) == sizeof(unsigned));
|
||||
#if 0
|
||||
// works, but may trigger clang/gcc warnings "-Wunused-value"
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof((1LL, 1)) == sizeof(int))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof((1, 1LL)) == sizeof(long long))
|
||||
static_assert(usizeof((1LL, 1)) == sizeof(int));
|
||||
static_assert(usizeof((1, 1LL)) == sizeof(long long));
|
||||
#endif
|
||||
|
||||
static_assert(upx::min<upx_int8_t>(1, 2) == 1);
|
||||
static_assert(upx::min<upx_int16_t>(1, 2) == 1);
|
||||
static_assert(upx::min(1, 2) == 1);
|
||||
static_assert(upx::min(1ll, 2ll) == 1);
|
||||
static_assert(upx::max<upx_int8_t>(1, 2) == 2);
|
||||
static_assert(upx::max<upx_int16_t>(1, 2) == 2);
|
||||
static_assert(upx::max(1, 2) == 2);
|
||||
static_assert(upx::max(1ll, 2ll) == 2);
|
||||
static_assert(upx::wrapping_add<upx_int8_t>(127, 2) == -127);
|
||||
static_assert(upx::wrapping_add<upx_int16_t>(32767, 2) == -32767);
|
||||
static_assert(upx::wrapping_add(2147483647, 2) == -2147483647);
|
||||
static_assert(upx::wrapping_add(9223372036854775807ll, 2ll) == -9223372036854775807ll);
|
||||
static_assert(upx::wrapping_sub<upx_int8_t>(-127, 2) == 127);
|
||||
static_assert(upx::wrapping_sub<upx_int16_t>(-32767, 2) == 32767);
|
||||
static_assert(upx::wrapping_sub(-2147483647, 2) == 2147483647);
|
||||
static_assert(upx::wrapping_sub(-9223372036854775807ll, 2ll) == 9223372036854775807ll);
|
||||
|
||||
namespace compile_time = upx::compile_time;
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_len("") == 0)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_len("a") == 1)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_len("ab") == 2)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_len("abc") == 3)
|
||||
static_assert(compile_time::string_len("") == 0);
|
||||
static_assert(compile_time::string_len("a") == 1);
|
||||
static_assert(compile_time::string_len("ab") == 2);
|
||||
static_assert(compile_time::string_len("abc") == 3);
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_eq("", ""))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("a", ""))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("", "a"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_eq("abc", "abc"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("ab", "abc"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("abc", "ab"))
|
||||
static_assert(compile_time::string_eq("", ""));
|
||||
static_assert(!compile_time::string_eq("a", ""));
|
||||
static_assert(!compile_time::string_eq("", "a"));
|
||||
static_assert(compile_time::string_eq("abc", "abc"));
|
||||
static_assert(!compile_time::string_eq("ab", "abc"));
|
||||
static_assert(!compile_time::string_eq("abc", "ab"));
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("", ""))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("a", ""))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_lt("", "a"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("abc", "abc"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_lt("ab", "abc"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("abc", "ab"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("abc", "aba"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_lt("abc", "abz"))
|
||||
static_assert(!compile_time::string_lt("", ""));
|
||||
static_assert(!compile_time::string_lt("a", ""));
|
||||
static_assert(compile_time::string_lt("", "a"));
|
||||
static_assert(!compile_time::string_lt("abc", "abc"));
|
||||
static_assert(compile_time::string_lt("ab", "abc"));
|
||||
static_assert(!compile_time::string_lt("abc", "ab"));
|
||||
static_assert(!compile_time::string_lt("abc", "aba"));
|
||||
static_assert(compile_time::string_lt("abc", "abz"));
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_ne("abc", "abz"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_gt("abc", "abz"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_ge("abc", "abz"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_le("abc", "abz"))
|
||||
static_assert(compile_time::string_ne("abc", "abz"));
|
||||
static_assert(!compile_time::string_gt("abc", "abz"));
|
||||
static_assert(!compile_time::string_ge("abc", "abz"));
|
||||
static_assert(compile_time::string_le("abc", "abz"));
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::mem_eq((const char *) nullptr, nullptr, 0))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::mem_eq((const byte *) nullptr, nullptr, 0))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::mem_eq("", "", 0))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::mem_eq("abc", "abc", 3))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::mem_eq("abc", "abz", 3))
|
||||
static_assert(compile_time::mem_eq((const char *) nullptr, nullptr, 0));
|
||||
static_assert(compile_time::mem_eq((const byte *) nullptr, nullptr, 0));
|
||||
static_assert(compile_time::mem_eq("", "", 0));
|
||||
static_assert(compile_time::mem_eq("abc", "abc", 3));
|
||||
static_assert(!compile_time::mem_eq("abc", "abz", 3));
|
||||
|
||||
static_assert(compile_time::bswap16(0x0102) == 0x0201);
|
||||
static_assert(compile_time::bswap32(0x01020304) == 0x04030201);
|
||||
static_assert(compile_time::bswap64(0x0102030405060708ull) == 0x0807060504030201ull);
|
||||
|
||||
/*************************************************************************
|
||||
//
|
||||
|
||||
36
src/conf.h
36
src/conf.h
@ -47,18 +47,18 @@
|
||||
// reserve name "upx" for namespace
|
||||
namespace upx {}
|
||||
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_BIT == 8)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(short) == 2)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(long long) == 8)
|
||||
static_assert(CHAR_BIT == 8);
|
||||
static_assert(sizeof(short) == 2);
|
||||
static_assert(sizeof(int) == 4);
|
||||
static_assert(sizeof(long long) == 8);
|
||||
// check sane compiler mandatory flags
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(-1 == ~0) // two's complement - see http://wg21.link/P0907R4
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(0u - 1 == ~0u) // two's complement - see http://wg21.link/P0907R4
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((1u << 31) << 1 == 0)
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(((int) (1u << 31)) >> 31 == -1) // arithmetic right shift
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((-1) >> 31 == -1) // arithmetic right shift
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 255) // -funsigned-char
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER((char) (-1) == 255)
|
||||
static_assert(-1 == ~0); // two's complement - see http://wg21.link/P0907R4
|
||||
static_assert(0u - 1 == ~0u); // two's complement - see http://wg21.link/P0907R4
|
||||
static_assert((1u << 31) << 1 == 0);
|
||||
static_assert(((int) (1u << 31)) >> 31 == -1); // arithmetic right shift
|
||||
static_assert((-1) >> 31 == -1); // arithmetic right shift
|
||||
static_assert(CHAR_MAX == 255); // -funsigned-char
|
||||
static_assert((char) (-1) == 255);
|
||||
|
||||
// enable some more strict warnings for Git developer builds
|
||||
#if defined(UPX_CONFIG_DISABLE_WSTRICT) && (UPX_CONFIG_DISABLE_WSTRICT + 0 == 0)
|
||||
@ -82,6 +82,12 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char) (-1) == 255)
|
||||
#endif // UPX_CONFIG_DISABLE_WERROR
|
||||
#endif // UPX_CONFIG_DISABLE_WSTRICT
|
||||
|
||||
#if __cplusplus >= 202002L // C++20
|
||||
#define upx_is_constant_evaluated std::is_constant_evaluated
|
||||
#elif __has_builtin(__builtin_is_constant_evaluated) // clang-9, gcc-9
|
||||
#define upx_is_constant_evaluated __builtin_is_constant_evaluated
|
||||
#endif
|
||||
|
||||
// multithreading (UPX currently does not use multithreading)
|
||||
#if (WITH_THREADS)
|
||||
#define upx_thread_local thread_local
|
||||
@ -121,12 +127,6 @@ inline constexpr bool upx_is_integral_v = upx_is_integral<T>::value;
|
||||
#define upx_alignas_max alignas(std::max_align_t)
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 202002L
|
||||
#define upx_is_constant_evaluated std::is_constant_evaluated
|
||||
#elif __has_builtin(__builtin_is_constant_evaluated)
|
||||
#define upx_is_constant_evaluated __builtin_is_constant_evaluated
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
// core
|
||||
**************************************************************************/
|
||||
@ -165,7 +165,7 @@ typedef unsigned char uchar;
|
||||
// upx_charptr_unit_type is some opaque type with sizeof(type) == 1
|
||||
//// typedef char upx_charptr_unit_type; // also works
|
||||
struct alignas(1) upx_charptr_unit_type final { char hidden__; };
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(upx_charptr_unit_type) == 1)
|
||||
static_assert(sizeof(upx_charptr_unit_type) == 1);
|
||||
|
||||
// using the system off_t was a bad idea even back in 199x...
|
||||
typedef upx_int64_t upx_off_t;
|
||||
|
||||
@ -220,6 +220,20 @@ forceinline constexpr T umax(const T &a, const T &b) noexcept {
|
||||
return a < b ? b : a;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
forceinline constexpr T wrapping_add(const T &a, const T &b) noexcept {
|
||||
static_assert(std::is_integral_v<T>);
|
||||
typedef std::make_unsigned_t<T> U;
|
||||
return T(U(a) + U(b));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
forceinline constexpr T wrapping_sub(const T &a, const T &b) noexcept {
|
||||
static_assert(std::is_integral_v<T>);
|
||||
typedef std::make_unsigned_t<T> U;
|
||||
return T(U(a) - U(b));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
// util
|
||||
**************************************************************************/
|
||||
@ -235,15 +249,19 @@ template <class Result, class From>
|
||||
forceinline constexpr Result ptr_static_cast(From *ptr) noexcept {
|
||||
static_assert(std::is_pointer_v<Result>);
|
||||
static_assert(!std::is_const_v<std::remove_pointer_t<Result> >); // enforce same constness
|
||||
// don't cast through "void *" if types already match
|
||||
typedef std::conditional_t<std::is_same_v<Result, decltype(ptr)>, Result, void *> VoidPtr;
|
||||
// NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
|
||||
return static_cast<Result>(static_cast<void *>(ptr));
|
||||
return static_cast<Result>(static_cast<VoidPtr>(ptr));
|
||||
}
|
||||
template <class Result, class From>
|
||||
forceinline constexpr Result ptr_static_cast(const From *ptr) noexcept {
|
||||
static_assert(std::is_pointer_v<Result>);
|
||||
static_assert(std::is_const_v<std::remove_pointer_t<Result> >); // required
|
||||
// don't cast through "void *" if types already match
|
||||
typedef std::conditional_t<std::is_same_v<Result, decltype(ptr)>, Result, const void *> VoidPtr;
|
||||
// NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
|
||||
return static_cast<Result>(static_cast<const void *>(ptr));
|
||||
return static_cast<Result>(static_cast<VoidPtr>(ptr));
|
||||
}
|
||||
|
||||
#if WITH_THREADS
|
||||
@ -335,25 +353,197 @@ protected:
|
||||
UPX_CXX_DISABLE_COPY_MOVE(noncopyable)
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
// compile_time
|
||||
**************************************************************************/
|
||||
|
||||
namespace compile_time {
|
||||
constexpr std::size_t string_len(const char *a) { return *a == '\0' ? 0 : 1 + string_len(a + 1); }
|
||||
constexpr bool string_eq(const char *a, const char *b) {
|
||||
|
||||
constexpr std::size_t string_len(const char *a) noexcept {
|
||||
return *a == '\0' ? 0 : 1 + string_len(a + 1);
|
||||
}
|
||||
constexpr bool string_eq(const char *a, const char *b) noexcept {
|
||||
return *a == *b && (*a == '\0' || string_eq(a + 1, b + 1));
|
||||
}
|
||||
constexpr bool string_lt(const char *a, const char *b) {
|
||||
constexpr bool string_lt(const char *a, const char *b) noexcept {
|
||||
return (uchar) *a < (uchar) *b || (*a != '\0' && *a == *b && string_lt(a + 1, b + 1));
|
||||
}
|
||||
constexpr bool string_ne(const char *a, const char *b) { return !string_eq(a, b); }
|
||||
constexpr bool string_gt(const char *a, const char *b) { return string_lt(b, a); }
|
||||
constexpr bool string_le(const char *a, const char *b) { return !string_lt(b, a); }
|
||||
constexpr bool string_ge(const char *a, const char *b) { return !string_lt(a, b); }
|
||||
forceinline constexpr bool string_ne(const char *a, const char *b) noexcept {
|
||||
return !string_eq(a, b);
|
||||
}
|
||||
forceinline constexpr bool string_gt(const char *a, const char *b) noexcept {
|
||||
return string_lt(b, a);
|
||||
}
|
||||
forceinline constexpr bool string_le(const char *a, const char *b) noexcept {
|
||||
return !string_lt(b, a);
|
||||
}
|
||||
forceinline constexpr bool string_ge(const char *a, const char *b) noexcept {
|
||||
return !string_lt(a, b);
|
||||
}
|
||||
|
||||
constexpr bool mem_eq(const char *a, const char *b, std::size_t n) {
|
||||
constexpr bool mem_eq(const char *a, const char *b, std::size_t n) noexcept {
|
||||
return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1));
|
||||
}
|
||||
constexpr bool mem_eq(const unsigned char *a, const unsigned char *b, std::size_t n) {
|
||||
constexpr bool mem_eq(const unsigned char *a, const unsigned char *b, std::size_t n) noexcept {
|
||||
return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1));
|
||||
}
|
||||
|
||||
forceinline constexpr upx_uint16_t bswap16(upx_uint16_t v) noexcept {
|
||||
return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
|
||||
}
|
||||
forceinline constexpr upx_uint32_t bswap32(upx_uint32_t v) noexcept {
|
||||
return ((v >> 24) & 0xff) | ((v >> 8) & 0xff00) | ((v & 0xff00) << 8) | ((v & 0xff) << 24);
|
||||
}
|
||||
forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept {
|
||||
return (upx_uint64_t(bswap32(upx_uint32_t(v))) << 32) | bswap32(upx_uint32_t(v >> 32));
|
||||
}
|
||||
|
||||
forceinline constexpr upx_uint16_t get_be16(const byte *p) noexcept {
|
||||
typedef upx_uint16_t U;
|
||||
return (U(p[0]) << 8) | (U(p[1]) << 0);
|
||||
}
|
||||
forceinline constexpr upx_uint32_t get_be24(const byte *p) noexcept {
|
||||
typedef upx_uint32_t U;
|
||||
return (U(p[0]) << 16) | (U(p[1]) << 8) | (U(p[2]) << 0);
|
||||
}
|
||||
forceinline constexpr upx_uint32_t get_be32(const byte *p) noexcept {
|
||||
typedef upx_uint32_t U;
|
||||
return (U(p[0]) << 24) | (U(p[1]) << 16) | (U(p[2]) << 8) | (U(p[3]) << 0);
|
||||
}
|
||||
forceinline constexpr upx_uint64_t get_be64(const byte *p) noexcept {
|
||||
typedef upx_uint64_t U;
|
||||
return (U(p[0]) << 56) | (U(p[1]) << 48) | (U(p[2]) << 40) | (U(p[3]) << 32) | (U(p[4]) << 24) |
|
||||
(U(p[5]) << 16) | (U(p[6]) << 8) | (U(p[7]) << 0);
|
||||
}
|
||||
|
||||
forceinline constexpr void set_be16(byte *p, upx_uint16_t v) noexcept {
|
||||
p[0] = byte((v >> 8) & 0xff);
|
||||
p[1] = byte((v >> 0) & 0xff);
|
||||
}
|
||||
forceinline constexpr void set_be24(byte *p, upx_uint32_t v) noexcept {
|
||||
p[0] = byte((v >> 16) & 0xff);
|
||||
p[1] = byte((v >> 8) & 0xff);
|
||||
p[2] = byte((v >> 0) & 0xff);
|
||||
}
|
||||
forceinline constexpr void set_be32(byte *p, upx_uint32_t v) noexcept {
|
||||
p[0] = byte((v >> 24) & 0xff);
|
||||
p[1] = byte((v >> 16) & 0xff);
|
||||
p[2] = byte((v >> 8) & 0xff);
|
||||
p[3] = byte((v >> 0) & 0xff);
|
||||
}
|
||||
forceinline constexpr void set_be64(byte *p, upx_uint64_t v) noexcept {
|
||||
p[0] = byte((v >> 56) & 0xff);
|
||||
p[1] = byte((v >> 48) & 0xff);
|
||||
p[2] = byte((v >> 40) & 0xff);
|
||||
p[3] = byte((v >> 32) & 0xff);
|
||||
p[4] = byte((v >> 24) & 0xff);
|
||||
p[5] = byte((v >> 16) & 0xff);
|
||||
p[6] = byte((v >> 8) & 0xff);
|
||||
p[7] = byte((v >> 0) & 0xff);
|
||||
}
|
||||
|
||||
forceinline constexpr upx_uint16_t get_le16(const byte *p) noexcept {
|
||||
typedef upx_uint16_t U;
|
||||
return (U(p[0]) << 0) | (U(p[1]) << 8);
|
||||
}
|
||||
forceinline constexpr upx_uint32_t get_le24(const byte *p) noexcept {
|
||||
typedef upx_uint32_t U;
|
||||
return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16);
|
||||
}
|
||||
forceinline constexpr upx_uint32_t get_le32(const byte *p) noexcept {
|
||||
typedef upx_uint32_t U;
|
||||
return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16) | (U(p[3]) << 24);
|
||||
}
|
||||
forceinline constexpr upx_uint64_t get_le64(const byte *p) noexcept {
|
||||
typedef upx_uint64_t U;
|
||||
return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16) | (U(p[3]) << 24) | (U(p[4]) << 32) |
|
||||
(U(p[5]) << 40) | (U(p[6]) << 48) | (U(p[7]) << 56);
|
||||
}
|
||||
|
||||
forceinline constexpr void set_le16(byte *p, upx_uint16_t v) noexcept {
|
||||
p[0] = byte((v >> 0) & 0xff);
|
||||
p[1] = byte((v >> 8) & 0xff);
|
||||
}
|
||||
forceinline constexpr void set_le32(byte *p, upx_uint32_t v) noexcept {
|
||||
p[0] = byte((v >> 0) & 0xff);
|
||||
p[1] = byte((v >> 8) & 0xff);
|
||||
p[2] = byte((v >> 16) & 0xff);
|
||||
p[3] = byte((v >> 24) & 0xff);
|
||||
}
|
||||
forceinline constexpr void set_le24(byte *p, upx_uint32_t v) noexcept {
|
||||
p[0] = byte((v >> 0) & 0xff);
|
||||
p[1] = byte((v >> 8) & 0xff);
|
||||
p[2] = byte((v >> 16) & 0xff);
|
||||
}
|
||||
forceinline constexpr void set_le64(byte *p, upx_uint64_t v) noexcept {
|
||||
p[0] = byte((v >> 0) & 0xff);
|
||||
p[1] = byte((v >> 8) & 0xff);
|
||||
p[2] = byte((v >> 16) & 0xff);
|
||||
p[3] = byte((v >> 24) & 0xff);
|
||||
p[4] = byte((v >> 32) & 0xff);
|
||||
p[5] = byte((v >> 40) & 0xff);
|
||||
p[6] = byte((v >> 48) & 0xff);
|
||||
p[7] = byte((v >> 56) & 0xff);
|
||||
}
|
||||
|
||||
forceinline constexpr upx_uint16_t get_ne16(const byte *p) noexcept {
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
return get_be16(p);
|
||||
#else
|
||||
return get_le16(p);
|
||||
#endif
|
||||
}
|
||||
forceinline constexpr upx_uint32_t get_ne24(const byte *p) noexcept {
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
return get_be24(p);
|
||||
#else
|
||||
return get_le24(p);
|
||||
#endif
|
||||
}
|
||||
forceinline constexpr upx_uint32_t get_ne32(const byte *p) noexcept {
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
return get_be32(p);
|
||||
#else
|
||||
return get_le32(p);
|
||||
#endif
|
||||
}
|
||||
forceinline constexpr upx_uint64_t get_ne64(const byte *p) noexcept {
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
return get_be64(p);
|
||||
#else
|
||||
return get_le64(p);
|
||||
#endif
|
||||
}
|
||||
|
||||
forceinline constexpr void set_ne16(byte *p, upx_uint16_t v) noexcept {
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
set_be16(p, v);
|
||||
#else
|
||||
set_le16(p, v);
|
||||
#endif
|
||||
}
|
||||
forceinline constexpr void set_ne24(byte *p, upx_uint32_t v) noexcept {
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
set_be24(p, v);
|
||||
#else
|
||||
set_le24(p, v);
|
||||
#endif
|
||||
}
|
||||
forceinline constexpr void set_ne32(byte *p, upx_uint32_t v) noexcept {
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
set_be32(p, v);
|
||||
#else
|
||||
set_le32(p, v);
|
||||
#endif
|
||||
}
|
||||
forceinline constexpr void set_ne64(byte *p, upx_uint64_t v) noexcept {
|
||||
#if (ACC_ABI_BIG_ENDIAN)
|
||||
set_be64(p, v);
|
||||
#else
|
||||
set_le64(p, v);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace compile_time
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
Loading…
Reference in New Issue
Block a user