#include <cassert>
#include <cinttypes>
#include <cstring>
#include <jau/test/catch2_ext.hpp>
extern "C" {
#ifndef BYTE_ORDER
#include <endian.h>
#endif
}
static constexpr inline bool VERBOSE =
false;
template<class Dummy_type>
return true;
}
template<class Dummy_type>
return false;
}
}
}
TEST_CASE(
"Endianess Test 00",
"[endian]" ) {
fprintf(stderr, "********************************************************************************\n");
fprintf(stderr, "********************************************************************************\n");
const bool cpp_is_little =
#if BYTE_ORDER == LITTLE_ENDIAN
true;
#else
false;
#endif
const bool cpp_is_big =
#if BYTE_ORDER == BIG_ENDIAN
true;
#else
false;
#endif
REQUIRE( cpp_is_little == is_little );
REQUIRE( cpp_is_big == is_big );
}
template<typename Value_type>
const uint8_t * pa = reinterpret_cast<const uint8_t *>(&a);
fprintf(stderr, "a[%zu] 0x%X, ", i, pa[i]);
}
}
template<typename Value_type>
const uint8_t * pa = reinterpret_cast<const uint8_t *>(&a);
const uint8_t * pb = reinterpret_cast<const uint8_t *>(&b);
bool res = true;
for(std::size_t i=0; i<
sizeof(
Value_type) && res; i++) {
res = pa[i] == pb[i];
if( !res ) {
fprintf(stderr, "pa[%zu] 0x%X != pb[%zu] 0x%X\n", i, pa[i], i, pb[i]);
}
}
return res;
}
template<typename Value_type>
{
fprintf(stderr, "\n");
}
{
REQUIRE( r1_le == v_le );
REQUIRE( r1_be == v_be );
}
{
#if BYTE_ORDER == LITTLE_ENDIAN
REQUIRE( r1_cpu == v_cpu );
#else
REQUIRE(
compare(v_be, v_cpu) ==
true );
REQUIRE( r1_cpu == v_cpu );
#endif
}
{
REQUIRE( r1_cpu == v_cpu );
REQUIRE( r2_cpu == v_cpu );
}
}
static uint16_t
composeU16(
const uint8_t n1,
const uint8_t n2) {
uint16_t dest;
uint8_t * p_dest = reinterpret_cast<uint8_t*>(&dest);
p_dest[0] = n1;
p_dest[1] = n2;
return dest;
}
static int16_t
composeI16(
const uint8_t n1,
const uint8_t n2) {
int16_t dest;
uint8_t * p_dest = reinterpret_cast<uint8_t*>(&dest);
p_dest[0] = n1;
p_dest[1] = n2;
return dest;
}
static uint32_t
composeU32(
const uint8_t n1,
const uint8_t n2,
const uint8_t n3,
const uint8_t n4) {
uint32_t dest;
uint8_t * p_dest = reinterpret_cast<uint8_t*>(&dest);
p_dest[0] = n1;
p_dest[1] = n2;
p_dest[2] = n3;
p_dest[3] = n4;
return dest;
}
static int32_t
composeI32(
const uint8_t n1,
const uint8_t n2,
const uint8_t n3,
const uint8_t n4) {
int32_t dest;
uint8_t * p_dest = reinterpret_cast<uint8_t*>(&dest);
p_dest[0] = n1;
p_dest[1] = n2;
p_dest[2] = n3;
p_dest[3] = n4;
return dest;
}
static uint64_t
composeU64(
const uint8_t n1,
const uint8_t n2,
const uint8_t n3,
const uint8_t n4,
const uint8_t n5, const uint8_t n6, const uint8_t n7, const uint8_t n8) {
uint64_t dest;
uint8_t * p_dest = reinterpret_cast<uint8_t*>(&dest);
p_dest[0] = n1;
p_dest[1] = n2;
p_dest[2] = n3;
p_dest[3] = n4;
p_dest[4] = n5;
p_dest[5] = n6;
p_dest[6] = n7;
p_dest[7] = n8;
return dest;
}
static int64_t
composeI64(
const uint8_t n1,
const uint8_t n2,
const uint8_t n3,
const uint8_t n4,
const uint8_t n5, const uint8_t n6, const uint8_t n7, const uint8_t n8) {
int64_t dest;
uint8_t * p_dest = reinterpret_cast<uint8_t*>(&dest);
p_dest[0] = n1;
p_dest[1] = n2;
p_dest[2] = n3;
p_dest[3] = n4;
p_dest[4] = n5;
p_dest[5] = n6;
p_dest[6] = n7;
p_dest[7] = n8;
return dest;
}
template<typename Value_type>
uint8_t * p_dest = reinterpret_cast<uint8_t*>(&dest);
uint8_t byte_value = lowest_value;
for(size_t i=0; i<sizeof(dest); i++, byte_value++) {
p_dest[i] = byte_value;
}
} else {
for(ssize_t i=sizeof(dest)-1; i>=0; i--, byte_value++) {
p_dest[i] = byte_value;
}
}
return dest;
}
template<typename Value_type>
}
TEST_CASE(
"Integer Type Byte Order Test 01",
"[byteorder][bswap]" ) {
{
constexpr uint16_t
cpu = 0x3210U;
}
{
constexpr uint16_t
cpu = 0xFEDCU;
}
{
constexpr int16_t
cpu = 0x3210;
}
{
constexpr int16_t
cpu = -292_i16;
}
{
constexpr uint32_t
cpu = 0x76543210U;
}
{
constexpr uint32_t
cpu = 0xFEDCBA98U;
}
{
constexpr int32_t
cpu = int32_t(0x76543210);
}
{
constexpr int32_t
cpu = -19088744_i32;
}
{
constexpr uint64_t
cpu = 0xfedcba9876543210ULL;
uint64_t le =
composeU64(0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe);
uint64_t be =
composeU64(0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10);
}
{
constexpr int64_t
cpu = -81985529216486896_i64;
int64_t le =
composeI64(0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe);
int64_t be =
composeI64(0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10);
}
{
}
{
}
{
}
}
template<typename Value_type>
REQUIRE( r1 == v1);
REQUIRE( r2 == v2);
REQUIRE( r3 == v3);
}
TEST_CASE(
"Integer Get/Put in CPU Byte Order Test 02",
"[byteorder][get][put]" ) {
{
constexpr uint8_t a = 0x01, b = 0x11, c = 0xff;
}
{
constexpr uint16_t a = 0x0123, b = 0x1122, c = 0xffee;
}
{
constexpr int16_t a = 0x0123, b = 0x1122, c = -18_i16;
}
{
constexpr uint32_t a = 0x01234567U, b = 0x11223344U, c = 0xffeeddccU;
}
{
constexpr int32_t a = 0x01234567, b = 0x11223344, c = -1122868_i32;
}
{
constexpr uint64_t a = 0x0123456789abcdefULL, b = 0x1122334455667788ULL, c = 0xffeeddcc99887766ULL;
}
{
constexpr int64_t a = 0x0123456789abcdefLL, b = 0x1122334455667788LL, c = -4822678761867418_i64;
}
{
}
{
}
{
}
}
template<typename Value_type>
fprintf(stderr, "\n");
}
REQUIRE( rle_raw == v_le);
REQUIRE( rle_cpu == v_cpu);
REQUIRE( rbe_raw == v_be);
REQUIRE( rbe_cpu == v_cpu);
}
TEST_CASE(
"Integer Get/Put in explicit Byte Order Test 03",
"[byteorder][get][put]" ) {
{
constexpr uint16_t
cpu = 0x3210U;
}
{
constexpr uint16_t
cpu = 0xFEDCU;
}
{
constexpr int16_t
cpu = 0x3210;
}
{
constexpr int16_t
cpu = -292_i16;
}
{
constexpr uint32_t
cpu = 0x76543210U;
}
{
constexpr uint32_t
cpu = 0xFEDCBA98U;
}
{
constexpr int32_t
cpu = int32_t(0x76543210);
}
{
constexpr int32_t
cpu = -19088744_i32;
}
{
constexpr uint64_t
cpu = 0xfedcba9876543210ULL;
uint64_t le =
composeU64(0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe);
uint64_t be =
composeU64(0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10);
}
{
constexpr int64_t
cpu = -81985529216486896_i64;
int64_t le =
composeI64(0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe);
int64_t be =
composeI64(0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10);
}
{
}
{
}
{
}
}
TEST_CASE(
"HexString from and to byte vector conversion - Test 04",
"[hexstring]" ) {
{
std::cout << "Little Endian Representation: " << std::endl;
const std::vector<uint8_t> lalaSink1 = { 0x1a, 0x1b, 0x2a, 0x2b, 0xff };
const uint64_t v0_be = 0x000000ff2b2a1b1aU;
const uint64_t v0_le = 0x0000001a1b2a2bffU;
const std::string value_s0 = "1a1b2a2bff";
std::vector<uint8_t> lalaSink2;
REQUIRE( value_s0 == value_s1 );
REQUIRE( value_s0 == value_s2 );
std::cout << "v0_le " << value_s1 << " (2) " << value_s2 << std::endl;
{
std::cout << "v0_be_s " << v0_be_s << std::endl;
std::cout << "v1_be_s " << v1_be_s << std::endl;
std::cout << "v2_be_s " << v2_be_s << std::endl;
std::cout << "v0_le_s " << v0_le_s << std::endl;
std::cout << "v1_le_s " << v1_le_s << std::endl;
std::cout << "v2_le_s " << v2_le_s << std::endl;
}
REQUIRE( v0_le == v1_le );
REQUIRE( v0_le == v2_le );
REQUIRE( v0_be == v1_be );
REQUIRE( v0_be == v2_be );
REQUIRE(lalaSink1 == lalaSink2);
std::cout << std::endl;
}
{
std::cout << "Big Endian Representation: " << std::endl;
const std::vector<uint8_t> lalaSink1 = { 0x1a, 0x1b, 0x2a, 0x2b, 0xff };
const uint64_t v0_be = 0x000000ff2b2a1b1aU;
const uint64_t v0_le = 0x0000001a1b2a2bffU;
const std::string value_s0 = "0xff2b2a1b1a";
std::vector<uint8_t> lalaSink2;
REQUIRE( value_s0 == value_s1 );
REQUIRE( value_s0 == value_s2 );
std::cout << "v0_be " << value_s1 << " (2) " << value_s2 << std::endl;
{
std::cout << "v0_be_s " << v0_be_s << std::endl;
std::cout << "v1_be_s " << v1_be_s << std::endl;
std::cout << "v2_be_s " << v2_be_s << std::endl;
std::cout << "v0_le_s " << v0_le_s << std::endl;
std::cout << "v1_le_s " << v1_le_s << std::endl;
std::cout << "v2_le_s " << v2_le_s << std::endl;
}
REQUIRE( v0_le == v1_le );
REQUIRE( v0_le == v2_le );
REQUIRE( v0_be == v1_be );
REQUIRE( v0_be == v2_be );
REQUIRE(lalaSink1 == lalaSink2);
std::cout << std::endl;
}
{
std::cout << "Even digits (1): " << std::endl;
const std::vector<uint8_t> v0_b = { 0x1a, 0x1b, 0x2a, 0x2b, 0xff };
const uint64_t v0 = 0xff2b2a1b1aU;
const std::string v0_s_msb = "0xff2b2a1b1a";
const std::string v0_s_lsb = "1a1b2a2bff";
std::cout << "v0_s (msb) " << v0_s_msb << std::endl;
std::cout << "v0_s (lsb) " << v0_s_lsb << std::endl;
std::vector<uint8_t> v1_b_msb_str;
std::vector<uint8_t> v1_b_lsb_str;
std::cout <<
"v1_b (msb str) " <<
jau::to_string(v1_b_msb_str) << std::endl;
std::cout << "v1_bs (msb str) " << v1_bs_msb_str << std::endl;
std::cout <<
"v1_b (lsb str) " <<
jau::to_string(v1_b_lsb_str) << std::endl;
std::cout << "v1_bs (lsb str) " << v1_bs_lsb_str << std::endl;
REQUIRE( v0 == v1_msb_str );
REQUIRE( v0 == v1_lsb_str );
REQUIRE( v0_b == v1_b_msb_str );
REQUIRE( v0_b == v1_b_lsb_str );
std::cout << std::endl;
}
{
std::cout << "Odd digits (1): " << std::endl;
const std::vector<uint8_t> v0_b_msb = { 0x1a, 0x1b, 0x2a, 0x2b, 0x0f };
const std::vector<uint8_t> v0_b_lsb = { 0x1a, 0x1b, 0x2a, 0x2b, 0xf0 };
const uint64_t v0_msb = 0x0f2b2a1b1aU;
const uint64_t v0_lsb = 0xf02b2a1b1aU;
const std::string v0_s_msb = "0xf2b2a1b1a";
const std::string v0_s_lsb = "1a1b2a2bf";
std::cout << "v0_s (msb) " << v0_s_msb << std::endl;
std::cout << "v0_s (lsb) " << v0_s_lsb << std::endl;
std::vector<uint8_t> v1_b_msb_str;
std::vector<uint8_t> v1_b_lsb_str;
std::cout <<
"v1_b (msb str) " <<
jau::to_string(v1_b_msb_str) << std::endl;
std::cout << "v1_bs (msb str) " << v1_bs_msb_str << std::endl;
std::cout <<
"v1_b (lsb str) " <<
jau::to_string(v1_b_lsb_str) << std::endl;
std::cout << "v1_bs (lsb str) " << v1_bs_lsb_str << std::endl;
REQUIRE( v0_msb == v1_msb_str );
REQUIRE( v0_lsb == v1_lsb_str );
REQUIRE( v0_b_msb == v1_b_msb_str );
REQUIRE( v0_b_lsb == v1_b_lsb_str );
std::cout << std::endl;
}
{
std::cout << "Even digits (2): " << std::endl;
const uint64_t v0 = 0x000000ff2b2a1b1aU;
std::cout << "v0_s " << v0_s << std::endl;
REQUIRE( v0 == v0_2 );
std::cout << std::endl;
}
{
std::cout << "Even digits (3): " << std::endl;
std::string v0_0s1 = "0xff2b2a1b1a";
const uint64_t v0_0 = 0xff2b2a1b1aU;
std::cout << "v0_0s " << v0_0s1 << std::endl;
std::cout << "v0_0s2 " << v0_0s2 << std::endl;
REQUIRE( v0_0 == i0_0s1 );
REQUIRE( v0_0 == i0_0s2 );
std::cout << std::endl;
}
{
std::cout << "Odd digits (3): " << std::endl;
std::string v0_0s1 = "0xf2b2a1b1a";
const uint64_t v0_0 = 0xf2b2a1b1aU;
std::cout << "v0_0s " << v0_0s1 << std::endl;
std::cout << "v0_0s2 " << v0_0s2 << std::endl;
REQUIRE( v0_0 == i0_0s1 );
REQUIRE( v0_0 == i0_0s2 );
std::cout << std::endl;
}
}
TEST_CASE(
"Integer Type Test Test 05",
"[integer][type]" ) {
REQUIRE( 3_i8 == (int8_t)3 );
REQUIRE( 3_u8 == (uint8_t)3 );
REQUIRE( 3_i16 == (int16_t)3 );
REQUIRE( 3_u16 == (uint16_t)3 );
REQUIRE( 3_i32 == (int32_t)3 );
REQUIRE( 3_u32 == (uint32_t)3 );
REQUIRE( 3_i64 == (int64_t)3 );
REQUIRE( 3_u64 == (uint64_t)3 );
REQUIRE( 3_iz == (ssize_t)3 );
REQUIRE( 3_uz == (size_t)3 );
}
constexpr bool is_little_endian() noexcept
Evaluates true if platform is running in little endian mode, i.e.
constexpr std::enable_if_t< std::is_standard_layout_v< T >, T > get_value(uint8_t const *buffer) noexcept
Returns a T value from the given byte address using packed_t to resolve a potential memory alignment ...
constexpr uint16_t bswap(uint16_t const source) noexcept
endian_t
Endian identifier, indicating endianess of all scalar types.
constexpr bool has_endian_little_v
Value access of little-endian type trait for convenience .
constexpr uint16_t le_to_cpu(uint16_t const l) noexcept
lb_endian_t
Simplified reduced endian type only covering little- and big-endian.
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
constexpr bool is_little_endian(const endian_t byte_order) noexcept
Returns true if given byte_order equals endian::little, otherwise false.
constexpr uint16_t be_to_cpu(uint16_t const n) noexcept
constexpr std::enable_if_t< std::is_standard_layout_v< T >, void > put_value(uint8_t *buffer, const T &v) noexcept
Put the given T value into the given byte address using packed_t to resolve a potential memory alignm...
constexpr lb_endian_t to_lb_endian(const endian_t v) noexcept
@ native
Identifier for native platform type, one of the above.
@ little
Identifier for little endian.
@ big
Identifier for big endian.
@ little
Identifier for little endian, equivalent to endian::little.
@ big
Identifier for big endian, equivalent to endian::big.
consteval_cxx20 bool has_builtin_bit_cast() noexcept
Query whether __builtin_bit_cast(Dest_type, arg) is available via __has_builtin(__builtin_bit_cast).
constexpr int compare(const T a, const T b) noexcept
Returns -1, 0 or 1 if a is less, equal or greater than b, disregarding epsilon but considering NaN,...
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
std::string to_hexstring(value_type const &v, const bool skipLeading0x=false) noexcept
Produce a lower-case hexadecimal string representation with leading 0x in MSB of the given pointer.
uint64_t from_hexstring(std::string const &s, const bool lsbFirst=!jau::is_little_endian(), const bool checkLeading0x=true) noexcept
Converts a given hexadecimal string representation into a uint64_t value according to hexStringBytes(...
std::string bytesHexString(const void *data, const nsize_t length, const bool lsbFirst, const bool lowerCase=true, const bool skipLeading0x=false) noexcept
Produce a hexadecimal string representation of the given byte values.
size_t hexStringBytes(std::vector< uint8_t > &out, const std::string &hexstr, const bool lsbFirst, const bool checkLeading0x) noexcept
Converts a given hexadecimal string representation into a byte vector.
Test private impl namespace.
constexpr bool isLittleEndian2_impl(std::enable_if_t< jau::has_endian_little_v< Dummy_type >, bool >=true) noexcept
A 128-bit packed uint8_t data array.
A 196-bit packed uint8_t data array.
A 256-bit packed uint8_t data array.
static void test_value_littlebig(const Value_type v_cpu, const Value_type v_le, const Value_type v_be)
static bool compare_values(const Value_type a, const Value_type b)
static int16_t composeI16(const uint8_t n1, const uint8_t n2)
static int64_t composeI64(const uint8_t n1, const uint8_t n2, const uint8_t n3, const uint8_t n4, const uint8_t n5, const uint8_t n6, const uint8_t n7, const uint8_t n8)
static void test_byteorder(const Value_type v_cpu, const Value_type v_le, const Value_type v_be)
static void test_value_cpu(const Value_type v1, const Value_type v2, const Value_type v3)
static uint16_t composeU16(const uint8_t n1, const uint8_t n2)
static int32_t composeI32(const uint8_t n1, const uint8_t n2, const uint8_t n3, const uint8_t n4)
static uint32_t composeU32(const uint8_t n1, const uint8_t n2, const uint8_t n3, const uint8_t n4)
static constexpr bool VERBOSE
static void print(const Value_type a)
static Value_type compose(const uint8_t lowest_value, const jau::lb_endian_t le_or_be)
static uint64_t composeU64(const uint8_t n1, const uint8_t n2, const uint8_t n3, const uint8_t n4, const uint8_t n5, const uint8_t n6, const uint8_t n7, const uint8_t n8)
TEST_CASE("Endianess Test 00", "[endian]")
constexpr bool isLittleEndian2() noexcept
Just demonstrating usage of our type-traits in a convenient API manner w/o requiring to add the dummy...