/* bele.h -- access memory in BigEndian and LittleEndian byte order This file is part of the UPX executable compressor. Copyright (C) 1996-2023 Markus Franz Xaver Johannes Oberhumer Copyright (C) 1996-2023 Laszlo Molnar All Rights Reserved. UPX and the UCL library are free software; you can redistribute them and/or modify them under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Markus F.X.J. Oberhumer Laszlo Molnar */ #pragma once // BE - Big Endian // LE - Little Endian // NE - Native Endianness (aka host endianness) // TE - Target Endianness (not used here, see various packers) #if 1 // some platforms may provide their own system bswapXX() functions, so rename #undef bswap16 #undef bswap32 #undef bswap64 #define bswap16 upx_bswap16 #define bswap32 upx_bswap32 #define bswap64 upx_bswap64 #endif /************************************************************************* // core - NE **************************************************************************/ static forceinline unsigned get_ne16(const void *p) noexcept { upx_uint16_t v = 0; upx_memcpy_inline(&v, p, sizeof(v)); return v; } static forceinline unsigned get_ne32(const void *p) noexcept { upx_uint32_t v = 0; upx_memcpy_inline(&v, p, sizeof(v)); return v; } static forceinline upx_uint64_t get_ne64(const void *p) noexcept { upx_uint64_t v = 0; upx_memcpy_inline(&v, p, sizeof(v)); return v; } static forceinline void set_ne16(void *p, unsigned vv) noexcept { upx_uint16_t v = (upx_uint16_t) (vv & 0xffff); upx_memcpy_inline(p, &v, sizeof(v)); } static forceinline void set_ne32(void *p, unsigned vv) noexcept { upx_uint32_t v = vv; upx_memcpy_inline(p, &v, sizeof(v)); } static forceinline void set_ne64(void *p, upx_uint64_t vv) noexcept { upx_uint64_t v = vv; upx_memcpy_inline(p, &v, sizeof(v)); } /************************************************************************* // core - bswap **************************************************************************/ #if (ACC_CC_MSC) ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) // unfortunately *not* constexpr with current MSVC static forceinline unsigned bswap16(unsigned v) noexcept { return (unsigned) _byteswap_ulong(v << 16); } static forceinline unsigned bswap32(unsigned v) noexcept { return (unsigned) _byteswap_ulong(v); } static forceinline upx_uint64_t bswap64(upx_uint64_t v) noexcept { return _byteswap_uint64(v); } #else static forceinline constexpr unsigned bswap16(unsigned v) noexcept { // return __builtin_bswap16((upx_uint16_t) (v & 0xffff)); // return (unsigned) __builtin_bswap64((upx_uint64_t) v << 48); return __builtin_bswap32(v << 16); } static forceinline constexpr unsigned bswap32(unsigned v) noexcept { // return (unsigned) __builtin_bswap64((upx_uint64_t) v << 32); return __builtin_bswap32(v); } static forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept { return __builtin_bswap64(v); } #endif static forceinline constexpr unsigned no_bswap16(unsigned v) noexcept { return v & 0xffff; // needed so that this is equivalent to bswap16() above } static forceinline constexpr unsigned no_bswap32(unsigned v) noexcept { return v; } static forceinline constexpr upx_uint64_t no_bswap64(upx_uint64_t v) noexcept { return v; } #if (ACC_ABI_BIG_ENDIAN) #define ne16_to_be16(v) no_bswap16(v) #define ne32_to_be32(v) no_bswap32(v) #define ne64_to_be64(v) no_bswap64(v) #define ne16_to_le16(v) bswap16(v) #define ne32_to_le32(v) bswap32(v) #define ne64_to_le64(v) bswap64(v) #else #define ne16_to_be16(v) bswap16(v) #define ne32_to_be32(v) bswap32(v) #define ne64_to_be64(v) bswap64(v) #define ne16_to_le16(v) no_bswap16(v) #define ne32_to_le32(v) no_bswap32(v) #define ne64_to_le64(v) no_bswap64(v) #endif /************************************************************************* // get/set 16/32/64 **************************************************************************/ inline unsigned get_be16(const void *p) noexcept { return ne16_to_be16(get_ne16(p)); } inline unsigned get_be32(const void *p) noexcept { return ne32_to_be32(get_ne32(p)); } inline upx_uint64_t get_be64(const void *p) noexcept { return ne64_to_be64(get_ne64(p)); } inline unsigned get_le16(const void *p) noexcept { return ne16_to_le16(get_ne16(p)); } inline unsigned get_le32(const void *p) noexcept { return ne32_to_le32(get_ne32(p)); } inline upx_uint64_t get_le64(const void *p) noexcept { return ne64_to_le64(get_ne64(p)); } inline void set_be16(void *p, unsigned v) noexcept { set_ne16(p, ne16_to_be16(v)); } inline void set_be32(void *p, unsigned v) noexcept { set_ne32(p, ne32_to_be32(v)); } inline void set_be64(void *p, upx_uint64_t v) noexcept { set_ne64(p, ne64_to_be64(v)); } inline void set_le16(void *p, unsigned v) noexcept { set_ne16(p, ne16_to_le16(v)); } inline void set_le32(void *p, unsigned v) noexcept { set_ne32(p, ne32_to_le32(v)); } inline void set_le64(void *p, upx_uint64_t v) noexcept { set_ne64(p, ne64_to_le64(v)); } /************************************************************************* // get/set 24/26 **************************************************************************/ inline unsigned get_be24(const void *p) noexcept { const byte *b = ACC_CCAST(const byte *, p); return (b[0] << 16) | (b[1] << 8) | (b[2] << 0); } inline unsigned get_le24(const void *p) noexcept { const byte *b = ACC_CCAST(const byte *, p); return (b[0] << 0) | (b[1] << 8) | (b[2] << 16); } inline void set_be24(void *p, unsigned v) noexcept { byte *b = ACC_PCAST(byte *, p); b[0] = ACC_ICONV(byte, (v >> 16) & 0xff); b[1] = ACC_ICONV(byte, (v >> 8) & 0xff); b[2] = ACC_ICONV(byte, (v >> 0) & 0xff); } inline void set_le24(void *p, unsigned v) noexcept { byte *b = ACC_PCAST(byte *, p); b[0] = ACC_ICONV(byte, (v >> 0) & 0xff); b[1] = ACC_ICONV(byte, (v >> 8) & 0xff); b[2] = ACC_ICONV(byte, (v >> 16) & 0xff); } inline unsigned get_le26(const void *p) noexcept { return get_le32(p) & 0x03ffffff; } inline unsigned get_le19_5(const void *p) noexcept { return (get_le32(p) >> 5) & 0x0007ffff; } inline unsigned get_le14_5(const void *p) noexcept { return (get_le32(p) >> 5) & 0x00003fff; } inline void set_le26(void *p, unsigned v) noexcept { // preserve the top 6 bits // set_le32(p, (get_le32(p) & 0xfc000000) | (v & 0x03ffffff)); // optimized version, saving a runtime bswap32 set_ne32(p, (get_ne32(p) & ne32_to_le32(0xfc000000)) | (ne32_to_le32(v) & ne32_to_le32(0x03ffffff))); } inline void set_le19_5(void *p, unsigned v) noexcept { set_le32(p, (get_le32(p) & 0xff00001f) | ((v & 0x0007ffff) << 5)); } inline void set_le14_5(void *p, unsigned v) noexcept { set_le32(p, (get_le32(p) & 0xfff8001f) | ((v & 0x00003fff) << 5)); } /************************************************************************* // get signed values **************************************************************************/ static forceinline int sign_extend(unsigned v, unsigned bits) noexcept { const unsigned sign_bit = 1u << (bits - 1); v &= sign_bit | (sign_bit - 1); v |= 0u - (v & sign_bit); return ACC_ICAST(int, v); } static forceinline upx_int64_t sign_extend(upx_uint64_t v, unsigned bits) noexcept { const upx_uint64_t sign_bit = 1ull << (bits - 1); v &= sign_bit | (sign_bit - 1); v |= 0ull - (v & sign_bit); return ACC_ICAST(upx_int64_t, v); } inline int get_be16_signed(const void *p) noexcept { unsigned v = get_be16(p); return sign_extend(v, 16); } inline int get_be24_signed(const void *p) noexcept { unsigned v = get_be24(p); return sign_extend(v, 24); } inline int get_be32_signed(const void *p) noexcept { unsigned v = get_be32(p); return sign_extend(v, 32); } inline upx_int64_t get_be64_signed(const void *p) noexcept { upx_uint64_t v = get_be64(p); return sign_extend(v, 64); } inline int get_le16_signed(const void *p) noexcept { unsigned v = get_le16(p); return sign_extend(v, 16); } inline int get_le24_signed(const void *p) noexcept { unsigned v = get_le24(p); return sign_extend(v, 24); } inline int get_le32_signed(const void *p) noexcept { unsigned v = get_le32(p); return sign_extend(v, 32); } inline upx_int64_t get_le64_signed(const void *p) noexcept { upx_uint64_t v = get_le64(p); return sign_extend(v, 64); } /************************************************************************* // classes for portable unaligned access // // Important: these classes must be PODs (Plain Old Data), i.e. no // constructor, no destructor, no virtual functions and no default // assignment operator, and all fields must be public(!). // // [Actually we _can_ use a safe non-POD subset, but for this we need // to have gcc bug 17519 fixed - see http://gcc.gnu.org/PR17519 ] **************************************************************************/ struct alignas(1) BE16 final { typedef unsigned integral_conversion_type; // automatic conversion to unsigned byte d[2]; forceinline operator unsigned() const noexcept { return get_be16(d); } forceinline BE16 &operator=(unsigned v) noexcept { set_be16(d, v); return *this; } BE16 &operator+=(unsigned v) noexcept { set_be16(d, get_be16(d) + v); return *this; } BE16 &operator-=(unsigned v) noexcept { set_be16(d, get_be16(d) - v); return *this; } BE16 &operator*=(unsigned v) noexcept { set_be16(d, get_be16(d) * v); return *this; } BE16 &operator/=(unsigned v) noexcept { set_be16(d, get_be16(d) / v); return *this; } BE16 &operator&=(unsigned v) noexcept { set_be16(d, get_be16(d) & v); return *this; } BE16 &operator|=(unsigned v) noexcept { set_be16(d, get_be16(d) | v); return *this; } BE16 &operator^=(unsigned v) noexcept { set_be16(d, get_be16(d) ^ v); return *this; } BE16 &operator<<=(unsigned v) noexcept { set_be16(d, get_be16(d) << v); return *this; } BE16 &operator>>=(unsigned v) noexcept { set_be16(d, get_be16(d) >> v); return *this; } bool operator==(const BE16 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } bool operator<(const BE16 &x) const noexcept { return unsigned(*this) < unsigned(x); } }; struct alignas(1) BE32 final { typedef unsigned integral_conversion_type; // automatic conversion to unsigned byte d[4]; forceinline operator unsigned() const noexcept { return get_be32(d); } forceinline BE32 &operator=(unsigned v) noexcept { set_be32(d, v); return *this; } BE32 &operator+=(unsigned v) noexcept { set_be32(d, get_be32(d) + v); return *this; } BE32 &operator-=(unsigned v) noexcept { set_be32(d, get_be32(d) - v); return *this; } BE32 &operator*=(unsigned v) noexcept { set_be32(d, get_be32(d) * v); return *this; } BE32 &operator/=(unsigned v) noexcept { set_be32(d, get_be32(d) / v); return *this; } BE32 &operator&=(unsigned v) noexcept { set_be32(d, get_be32(d) & v); return *this; } BE32 &operator|=(unsigned v) noexcept { set_be32(d, get_be32(d) | v); return *this; } BE32 &operator^=(unsigned v) noexcept { set_be32(d, get_be32(d) ^ v); return *this; } BE32 &operator<<=(unsigned v) noexcept { set_be32(d, get_be32(d) << v); return *this; } BE32 &operator>>=(unsigned v) noexcept { set_be32(d, get_be32(d) >> v); return *this; } bool operator==(const BE32 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } bool operator<(const BE32 &x) const noexcept { return unsigned(*this) < unsigned(x); } }; struct alignas(1) BE64 final { typedef upx_uint64_t integral_conversion_type; // automatic conversion to upx_uint64_t byte d[8]; forceinline operator upx_uint64_t() const noexcept { return get_be64(d); } forceinline BE64 &operator=(upx_uint64_t v) noexcept { set_be64(d, v); return *this; } BE64 &operator+=(upx_uint64_t v) noexcept { set_be64(d, get_be64(d) + v); return *this; } BE64 &operator-=(upx_uint64_t v) noexcept { set_be64(d, get_be64(d) - v); return *this; } BE64 &operator*=(upx_uint64_t v) noexcept { set_be64(d, get_be64(d) * v); return *this; } BE64 &operator/=(upx_uint64_t v) noexcept { set_be64(d, get_be64(d) / v); return *this; } BE64 &operator&=(upx_uint64_t v) noexcept { set_be64(d, get_be64(d) & v); return *this; } BE64 &operator|=(upx_uint64_t v) noexcept { set_be64(d, get_be64(d) | v); return *this; } BE64 &operator^=(upx_uint64_t v) noexcept { set_be64(d, get_be64(d) ^ v); return *this; } BE64 &operator<<=(unsigned v) noexcept { set_be64(d, get_be64(d) << v); return *this; } BE64 &operator>>=(unsigned v) noexcept { set_be64(d, get_be64(d) >> v); return *this; } bool operator==(const BE64 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } bool operator<(const BE64 &x) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(x); } }; struct alignas(1) LE16 final { typedef unsigned integral_conversion_type; // automatic conversion to unsigned byte d[2]; forceinline operator unsigned() const noexcept { return get_le16(d); } forceinline LE16 &operator=(unsigned v) noexcept { set_le16(d, v); return *this; } LE16 &operator+=(unsigned v) noexcept { set_le16(d, get_le16(d) + v); return *this; } LE16 &operator-=(unsigned v) noexcept { set_le16(d, get_le16(d) - v); return *this; } LE16 &operator*=(unsigned v) noexcept { set_le16(d, get_le16(d) * v); return *this; } LE16 &operator/=(unsigned v) noexcept { set_le16(d, get_le16(d) / v); return *this; } LE16 &operator&=(unsigned v) noexcept { set_le16(d, get_le16(d) & v); return *this; } LE16 &operator|=(unsigned v) noexcept { set_le16(d, get_le16(d) | v); return *this; } LE16 &operator^=(unsigned v) noexcept { set_le16(d, get_le16(d) ^ v); return *this; } LE16 &operator<<=(unsigned v) noexcept { set_le16(d, get_le16(d) << v); return *this; } LE16 &operator>>=(unsigned v) noexcept { set_le16(d, get_le16(d) >> v); return *this; } bool operator==(const LE16 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } bool operator<(const LE16 &x) const noexcept { return unsigned(*this) < unsigned(x); } }; struct alignas(1) LE32 final { typedef unsigned integral_conversion_type; // automatic conversion to unsigned byte d[4]; forceinline operator unsigned() const noexcept { return get_le32(d); } forceinline LE32 &operator=(unsigned v) noexcept { set_le32(d, v); return *this; } LE32 &operator+=(unsigned v) noexcept { set_le32(d, get_le32(d) + v); return *this; } LE32 &operator-=(unsigned v) noexcept { set_le32(d, get_le32(d) - v); return *this; } LE32 &operator*=(unsigned v) noexcept { set_le32(d, get_le32(d) * v); return *this; } LE32 &operator/=(unsigned v) noexcept { set_le32(d, get_le32(d) / v); return *this; } LE32 &operator&=(unsigned v) noexcept { set_le32(d, get_le32(d) & v); return *this; } LE32 &operator|=(unsigned v) noexcept { set_le32(d, get_le32(d) | v); return *this; } LE32 &operator^=(unsigned v) noexcept { set_le32(d, get_le32(d) ^ v); return *this; } LE32 &operator<<=(unsigned v) noexcept { set_le32(d, get_le32(d) << v); return *this; } LE32 &operator>>=(unsigned v) noexcept { set_le32(d, get_le32(d) >> v); return *this; } bool operator==(const LE32 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } bool operator<(const LE32 &x) const noexcept { return unsigned(*this) < unsigned(x); } }; struct alignas(1) LE64 final { typedef upx_uint64_t integral_conversion_type; // automatic conversion to upx_uint64_t byte d[8]; forceinline operator upx_uint64_t() const noexcept { return get_le64(d); } forceinline LE64 &operator=(upx_uint64_t v) noexcept { set_le64(d, v); return *this; } LE64 &operator+=(upx_uint64_t v) noexcept { set_le64(d, get_le64(d) + v); return *this; } LE64 &operator-=(upx_uint64_t v) noexcept { set_le64(d, get_le64(d) - v); return *this; } LE64 &operator*=(upx_uint64_t v) noexcept { set_le64(d, get_le64(d) * v); return *this; } LE64 &operator/=(upx_uint64_t v) noexcept { set_le64(d, get_le64(d) / v); return *this; } LE64 &operator&=(upx_uint64_t v) noexcept { set_le64(d, get_le64(d) & v); return *this; } LE64 &operator|=(upx_uint64_t v) noexcept { set_le64(d, get_le64(d) | v); return *this; } LE64 &operator^=(upx_uint64_t v) noexcept { set_le64(d, get_le64(d) ^ v); return *this; } LE64 &operator<<=(unsigned v) noexcept { set_le64(d, get_le64(d) << v); return *this; } LE64 &operator>>=(unsigned v) noexcept { set_le64(d, get_le64(d) >> v); return *this; } bool operator==(const LE64 &x) const noexcept { return memcmp(d, x.d, sizeof(d)) == 0; } bool operator<(const LE64 &x) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(x); } }; /************************************************************************* // global operators (pointer addition/subtraction) **************************************************************************/ template inline T *operator+(T *ptr, const BE16 &v) noexcept { return ptr + unsigned(v); } template inline T *operator-(T *ptr, const BE16 &v) noexcept { return ptr - unsigned(v); } template inline T *operator+(T *ptr, const BE32 &v) noexcept { return ptr + unsigned(v); } template inline T *operator-(T *ptr, const BE32 &v) noexcept { return ptr - unsigned(v); } template inline T *operator+(T *ptr, const LE16 &v) noexcept { return ptr + unsigned(v); } template inline T *operator-(T *ptr, const LE16 &v) noexcept { return ptr - unsigned(v); } template inline T *operator+(T *ptr, const LE32 &v) noexcept { return ptr + unsigned(v); } template inline T *operator-(T *ptr, const LE32 &v) noexcept { return ptr - unsigned(v); } // these are not implemented on purpose and will cause errors template T *operator+(T *ptr, const BE64 &v) noexcept DELETED_FUNCTION; template T *operator-(T *ptr, const BE64 &v) noexcept DELETED_FUNCTION; template T *operator+(T *ptr, const LE64 &v) noexcept DELETED_FUNCTION; template T *operator-(T *ptr, const LE64 &v) noexcept DELETED_FUNCTION; /************************************************************************* // global overloads **************************************************************************/ inline unsigned ALIGN_DOWN(unsigned a, const BE32 &b) { return ALIGN_DOWN(a, unsigned(b)); } inline unsigned ALIGN_DOWN(const BE32 &a, unsigned b) { return ALIGN_DOWN(unsigned(a), b); } inline unsigned ALIGN_UP(unsigned a, const BE32 &b) { return ALIGN_UP(a, unsigned(b)); } inline unsigned ALIGN_UP(const BE32 &a, unsigned b) { return ALIGN_UP(unsigned(a), b); } inline unsigned ALIGN_DOWN(unsigned a, const LE32 &b) { return ALIGN_DOWN(a, unsigned(b)); } inline unsigned ALIGN_DOWN(const LE32 &a, unsigned b) { return ALIGN_DOWN(unsigned(a), b); } inline unsigned ALIGN_UP(unsigned a, const LE32 &b) { return ALIGN_UP(a, unsigned(b)); } inline unsigned ALIGN_UP(const LE32 &a, unsigned b) { return ALIGN_UP(unsigned(a), b); } inline unsigned UPX_MAX(unsigned a, const BE16 &b) { return UPX_MAX(a, unsigned(b)); } inline unsigned UPX_MAX(const BE16 &a, unsigned b) { return UPX_MAX(unsigned(a), b); } inline unsigned UPX_MIN(unsigned a, const BE16 &b) { return UPX_MIN(a, unsigned(b)); } inline unsigned UPX_MIN(const BE16 &a, unsigned b) { return UPX_MIN(unsigned(a), b); } inline unsigned UPX_MAX(unsigned a, const BE32 &b) { return UPX_MAX(a, unsigned(b)); } inline unsigned UPX_MAX(const BE32 &a, unsigned b) { return UPX_MAX(unsigned(a), b); } inline unsigned UPX_MIN(unsigned a, const BE32 &b) { return UPX_MIN(a, unsigned(b)); } inline unsigned UPX_MIN(const BE32 &a, unsigned b) { return UPX_MIN(unsigned(a), b); } inline unsigned UPX_MAX(unsigned a, const LE16 &b) { return UPX_MAX(a, unsigned(b)); } inline unsigned UPX_MAX(const LE16 &a, unsigned b) { return UPX_MAX(unsigned(a), b); } inline unsigned UPX_MIN(unsigned a, const LE16 &b) { return UPX_MIN(a, unsigned(b)); } inline unsigned UPX_MIN(const LE16 &a, unsigned b) { return UPX_MIN(unsigned(a), b); } inline unsigned UPX_MAX(unsigned a, const LE32 &b) { return UPX_MAX(a, unsigned(b)); } inline unsigned UPX_MAX(const LE32 &a, unsigned b) { return UPX_MAX(unsigned(a), b); } inline unsigned UPX_MIN(unsigned a, const LE32 &b) { return UPX_MIN(a, unsigned(b)); } inline unsigned UPX_MIN(const LE32 &a, unsigned b) { return UPX_MIN(unsigned(a), b); } /************************************************************************* // misc support **************************************************************************/ // native types #if (ACC_ABI_BIG_ENDIAN) typedef BE16 NE16; typedef BE32 NE32; typedef BE64 NE64; #define ne16_compare be16_compare #define ne32_compare be32_compare #define ne64_compare be64_compare #define ne16_compare_signed be16_compare_signed #define ne32_compare_signed be32_compare_signed #define ne64_compare_signed be64_compare_signed #else typedef LE16 NE16; typedef LE32 NE32; typedef LE64 NE64; #define ne16_compare le16_compare #define ne32_compare le32_compare #define ne64_compare le64_compare #define ne16_compare_signed le16_compare_signed #define ne32_compare_signed le32_compare_signed #define ne64_compare_signed le64_compare_signed #endif // upx_is_integral #define TT_IS_INTEGRAL(T) \ template <> \ struct upx_is_integral : public std::true_type {}; \ template <> \ struct upx_is_integral : public std::true_type {}; \ template <> \ struct upx_is_integral : public std::true_type {}; \ template <> \ struct upx_is_integral : public std::true_type {} TT_IS_INTEGRAL(BE16); TT_IS_INTEGRAL(BE32); TT_IS_INTEGRAL(BE64); TT_IS_INTEGRAL(LE16); TT_IS_INTEGRAL(LE32); TT_IS_INTEGRAL(LE64); #undef TT_IS_INTEGRAL // for use with qsort() extern "C" { int __acc_cdecl_qsort be16_compare(const void *, const void *); int __acc_cdecl_qsort be24_compare(const void *, const void *); int __acc_cdecl_qsort be32_compare(const void *, const void *); int __acc_cdecl_qsort be64_compare(const void *, const void *); int __acc_cdecl_qsort le16_compare(const void *, const void *); int __acc_cdecl_qsort le24_compare(const void *, const void *); int __acc_cdecl_qsort le32_compare(const void *, const void *); int __acc_cdecl_qsort le64_compare(const void *, const void *); int __acc_cdecl_qsort be16_compare_signed(const void *, const void *); int __acc_cdecl_qsort be24_compare_signed(const void *, const void *); int __acc_cdecl_qsort be32_compare_signed(const void *, const void *); int __acc_cdecl_qsort be64_compare_signed(const void *, const void *); int __acc_cdecl_qsort le16_compare_signed(const void *, const void *); int __acc_cdecl_qsort le24_compare_signed(const void *, const void *); int __acc_cdecl_qsort le32_compare_signed(const void *, const void *); int __acc_cdecl_qsort le64_compare_signed(const void *, const void *); } // extern "C" /************************************************************************* // Provide namespaces and classes to abstract endianness policies. // // CTP - Compile-Time Polymorphism (templates) // RTP - Run-Time Polymorphism (virtual functions) **************************************************************************/ // forward declarations namespace N_BELE_CTP { struct BEPolicy; struct LEPolicy; extern const BEPolicy be_policy; extern const LEPolicy le_policy; } // namespace N_BELE_CTP namespace N_BELE_RTP { struct AbstractPolicy; struct BEPolicy; struct LEPolicy; extern const BEPolicy be_policy; extern const LEPolicy le_policy; } // namespace N_BELE_RTP // implementation namespace N_BELE_CTP { #define BELE_CTP 1 #include "bele_policy.h" #undef BELE_CTP } // namespace N_BELE_CTP namespace N_BELE_RTP { #define BELE_RTP 1 #include "bele_policy.h" #undef BELE_RTP } // namespace N_BELE_RTP // util namespace N_BELE_CTP { inline const N_BELE_RTP::AbstractPolicy *getRTP(const BEPolicy * /*dummy*/) noexcept { return &N_BELE_RTP::be_policy; } inline const N_BELE_RTP::AbstractPolicy *getRTP(const LEPolicy * /*dummy*/) noexcept { return &N_BELE_RTP::le_policy; } } // namespace N_BELE_CTP /* vim:set ts=4 sw=4 et: */