/* libmisc/endian.c - Endian-conversion helpers * * Copyright (C) 2024-2025 Luke T. Shumaker * SPDX-License-Identifier: AGPL-3.0-or-later */ #include /* for LM_FORCE_SEMICOLON */ #include #define endian_declare_wrappers(NBIT, ENDIAN) \ uint##NBIT##ENDIAN##_t uint##NBIT##ENDIAN##_marshal(uint##NBIT##_t in) { \ uint##NBIT##ENDIAN##_t out; \ uint##NBIT##ENDIAN##_encode(out.octets, in); \ return out; \ } \ uint##NBIT##_t uint##NBIT##ENDIAN##_unmarshal(uint##NBIT##ENDIAN##_t in) { \ return uint##NBIT##ENDIAN##_decode(in.octets); \ } \ LM_FORCE_SEMICOLON /* Big endian *****************************************************************/ size_t uint16be_encode(uint8_t *out, uint16_t in) { out[0] = (uint8_t)((in >> 8) & 0xFF); out[1] = (uint8_t)((in >> 0) & 0xFF); return 2; } uint16_t uint16be_decode(uint8_t *in) { return (((uint16_t)(in[0])) << 8) | (((uint16_t)(in[1])) << 0) ; } size_t uint32be_encode(uint8_t *out, uint32_t in) { out[0] = (uint8_t)((in >> 24) & 0xFF); out[1] = (uint8_t)((in >> 16) & 0xFF); out[2] = (uint8_t)((in >> 8) & 0xFF); out[3] = (uint8_t)((in >> 0) & 0xFF); return 4; } uint32_t uint32be_decode(uint8_t *in) { return (((uint32_t)(in[0])) << 24) | (((uint32_t)(in[1])) << 16) | (((uint32_t)(in[2])) << 8) | (((uint32_t)(in[3])) << 0) ; } size_t uint64be_encode(uint8_t *out, uint64_t in) { out[0] = (uint8_t)((in >> 56) & 0xFF); out[1] = (uint8_t)((in >> 48) & 0xFF); out[2] = (uint8_t)((in >> 40) & 0xFF); out[3] = (uint8_t)((in >> 32) & 0xFF); out[4] = (uint8_t)((in >> 24) & 0xFF); out[5] = (uint8_t)((in >> 16) & 0xFF); out[6] = (uint8_t)((in >> 8) & 0xFF); out[7] = (uint8_t)((in >> 0) & 0xFF); return 8; } uint64_t uint64be_decode(uint8_t *in) { return (((uint64_t)(in[0])) << 56) | (((uint64_t)(in[1])) << 48) | (((uint64_t)(in[2])) << 40) | (((uint64_t)(in[3])) << 32) | (((uint64_t)(in[4])) << 24) | (((uint64_t)(in[5])) << 16) | (((uint64_t)(in[6])) << 8) | (((uint64_t)(in[7])) << 0) ; } endian_declare_wrappers(16, be); endian_declare_wrappers(32, be); endian_declare_wrappers(64, be); /* Little endian **************************************************************/ size_t uint16le_encode(uint8_t *out, uint16_t in) { out[0] = (uint8_t)((in >> 0) & 0xFF); out[1] = (uint8_t)((in >> 8) & 0xFF); return 2; } uint16_t uint16le_decode(uint8_t *in) { return (((uint16_t)(in[0])) << 0) | (((uint16_t)(in[1])) << 8) ; } size_t uint32le_encode(uint8_t *out, uint32_t in) { out[0] = (uint8_t)((in >> 0) & 0xFF); out[1] = (uint8_t)((in >> 8) & 0xFF); out[2] = (uint8_t)((in >> 16) & 0xFF); out[3] = (uint8_t)((in >> 24) & 0xFF); return 4; } uint32_t uint32le_decode(uint8_t *in) { return (((uint32_t)(in[0])) << 0) | (((uint32_t)(in[1])) << 8) | (((uint32_t)(in[2])) << 16) | (((uint32_t)(in[3])) << 24) ; } size_t uint64le_encode(uint8_t *out, uint64_t in) { out[0] = (uint8_t)((in >> 0) & 0xFF); out[1] = (uint8_t)((in >> 8) & 0xFF); out[2] = (uint8_t)((in >> 16) & 0xFF); out[3] = (uint8_t)((in >> 24) & 0xFF); out[4] = (uint8_t)((in >> 32) & 0xFF); out[5] = (uint8_t)((in >> 40) & 0xFF); out[6] = (uint8_t)((in >> 48) & 0xFF); out[7] = (uint8_t)((in >> 56) & 0xFF); return 8; } uint64_t uint64le_decode(uint8_t *in) { return (((uint64_t)(in[0])) << 0) | (((uint64_t)(in[1])) << 8) | (((uint64_t)(in[2])) << 16) | (((uint64_t)(in[3])) << 24) | (((uint64_t)(in[4])) << 32) | (((uint64_t)(in[5])) << 40) | (((uint64_t)(in[6])) << 48) | (((uint64_t)(in[7])) << 56) ; } endian_declare_wrappers(16, le); endian_declare_wrappers(32, le); endian_declare_wrappers(64, le);