summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2025-01-19 15:14:39 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2025-01-19 15:43:56 -0700
commitabc16ce9b5ba132769e14b4b3d649d79a92effc3 (patch)
treeb7e24155458d33659fb0c2f4f1b0fcd716a86a6e
parent02188436a7cf4efcee88c7b5eed6a621abb19d6d (diff)
libmisc: endian.h: Add 64-bit versions
-rw-r--r--libmisc/include/libmisc/endian.h80
-rw-r--r--libmisc/tests/test_endian.c39
2 files changed, 103 insertions, 16 deletions
diff --git a/libmisc/include/libmisc/endian.h b/libmisc/include/libmisc/endian.h
index b1bc55c..665a8c8 100644
--- a/libmisc/include/libmisc/endian.h
+++ b/libmisc/include/libmisc/endian.h
@@ -1,6 +1,6 @@
/* libmisc/endian.h - Endian-conversion helpers
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -71,6 +71,45 @@ static inline uint32_t uint32be_unmarshal(uint32be_t in) {
return uint32be_decode(in.octets);
}
+typedef struct {
+ uint8_t octets[8];
+} uint64be_t;
+static_assert(sizeof(uint64be_t) == 8);
+
+static inline 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;
+}
+
+static inline 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)
+ ;
+}
+
+static inline uint64be_t uint64be_marshal(uint64_t in) {
+ uint64be_t out;
+ uint64be_encode(out.octets, in);
+ return out;
+}
+
+static inline uint64_t uint64be_unmarshal(uint64be_t in) {
+ return uint64be_decode(in.octets);
+}
+
/* Little endian **************************************************************/
typedef struct {
@@ -131,4 +170,43 @@ static inline uint32_t uint32le_unmarshal(uint32le_t in) {
return uint32le_decode(in.octets);
}
+typedef struct {
+ uint8_t octets[8];
+} uint64le_t;
+static_assert(sizeof(uint64le_t) == 8);
+
+static inline 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;
+}
+
+static inline 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)
+ ;
+}
+
+static inline uint64le_t uint64le_marshal(uint64_t in) {
+ uint64le_t out;
+ uint64le_encode(out.octets, in);
+ return out;
+}
+
+static inline uint64_t uint64le_unmarshal(uint64le_t in) {
+ return uint64le_decode(in.octets);
+}
+
#endif /* _LIBMISC_ENDIAN_H_ */
diff --git a/libmisc/tests/test_endian.c b/libmisc/tests/test_endian.c
index d0b547c..dcb3cc2 100644
--- a/libmisc/tests/test_endian.c
+++ b/libmisc/tests/test_endian.c
@@ -1,6 +1,6 @@
/* libmisc/tests/test_endian.c - Tests for <libmisc/endian.h>
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -11,22 +11,31 @@
#include "test.h"
int main() {
- uint8_t act[12] = {0};
- uint16be_encode(&act[0], UINT16_C(0x1234));
- uint32be_encode(&act[2], UINT32_C(0x56789ABC));
- uint16le_encode(&act[6], UINT16_C(0x1234));
- uint32le_encode(&act[8], UINT32_C(0x56789ABC));
+ uint8_t act[(2+4+8)*2] = {0};
+ size_t pos = 0;
+ pos += uint16be_encode(&act[pos], UINT16_C(0x1234));
+ pos += uint32be_encode(&act[pos], UINT32_C(0x56789ABC));
+ pos += uint64be_encode(&act[pos], UINT64_C(0xAC589A93278CB30A));
+ pos += uint16le_encode(&act[pos], UINT16_C(0x1234));
+ pos += uint32le_encode(&act[pos], UINT32_C(0x56789ABC));
+ pos += uint64le_encode(&act[pos], UINT64_C(0xAC589A93278CB30A));
- uint8_t exp[12] = { 0x12, 0x34,
- 0x56, 0x78, 0x9A, 0xBC,
- 0x34, 0x12,
- 0xBC, 0x9A, 0x78, 0x56 };
- test_assert(memcmp(act, exp, 12) == 0);
+ test_assert(pos == sizeof(act));
+ uint8_t exp[(2+4+8)*2] = { 0x12, 0x34,
+ 0x56, 0x78, 0x9A, 0xBC,
+ 0xAC, 0x58, 0x9A, 0x93, 0x27, 0x8C, 0xB3, 0x0A,
+ 0x34, 0x12,
+ 0xBC, 0x9A, 0x78, 0x56,
+ 0x0A, 0xB3, 0x8C, 0x27, 0x93, 0x9A, 0x58, 0xAC};
+ test_assert(memcmp(act, exp, sizeof(act)) == 0);
- test_assert(uint16be_decode(&act[0]) == UINT16_C(0x1234));
- test_assert(uint32be_decode(&act[2]) == UINT32_C(0x56789ABC));
- test_assert(uint16le_decode(&act[6]) == UINT16_C(0x1234));
- test_assert(uint32le_decode(&act[8]) == UINT32_C(0x56789ABC));
+ pos = 0;
+ test_assert(uint16be_decode(&act[pos]) == UINT16_C(0x1234)); pos += 2;
+ test_assert(uint32be_decode(&act[pos]) == UINT32_C(0x56789ABC)); pos += 4;
+ test_assert(uint64be_decode(&act[pos]) == UINT64_C(0xAC589A93278CB30A)); pos += 8;
+ test_assert(uint16le_decode(&act[pos]) == UINT16_C(0x1234)); pos += 2;
+ test_assert(uint32le_decode(&act[pos]) == UINT32_C(0x56789ABC)); pos += 4;
+ test_assert(uint64le_decode(&act[pos]) == UINT64_C(0xAC589A93278CB30A)); pos += 8;
return 0;
}