aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE2
-rw-r--r--liberty.c76
2 files changed, 60 insertions, 18 deletions
diff --git a/LICENSE b/LICENSE
index 0610bbd..d58be36 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2014 - 2023, Přemysl Eric Janouch <p@janouch.name>
+Copyright (c) 2014 - 2024, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
diff --git a/liberty.c b/liberty.c
index e438c34..390d40b 100644
--- a/liberty.c
+++ b/liberty.c
@@ -1,7 +1,7 @@
/*
* liberty.c: the ultimate C unlibrary
*
- * Copyright (c) 2014 - 2022, Přemysl Eric Janouch <p@janouch.name>
+ * Copyright (c) 2014 - 2024, Přemysl Eric Janouch <p@janouch.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
@@ -652,6 +652,60 @@ str_pack_u64 (struct str *self, uint64_t x)
#define str_pack_i32(self, x) str_pack_u32 ((self), (uint32_t) (x))
#define str_pack_i64(self, x) str_pack_u64 ((self), (uint64_t) (x))
+// --- Reading binary numbers --------------------------------------------------
+
+// Doing this byte by byte prevents unaligned memory access issues.
+
+static uint64_t
+peek_u64be (const uint8_t *p)
+{
+ return (uint64_t) p[0] << 56 | (uint64_t) p[1] << 48
+ | (uint64_t) p[2] << 40 | (uint64_t) p[3] << 32
+ | (uint64_t) p[4] << 24 | (uint64_t) p[5] << 16 | p[6] << 8 | p[7];
+}
+
+static uint32_t
+peek_u32be (const uint8_t *p)
+{
+ return (uint32_t) p[0] << 24 | (uint32_t) p[1] << 16 | p[2] << 8 | p[3];
+}
+
+static uint16_t
+peek_u16be (const uint8_t *p)
+{
+ return (uint16_t) p[0] << 8 | p[1];
+}
+
+static uint64_t
+peek_u64le (const uint8_t *p)
+{
+ return (uint64_t) p[7] << 56 | (uint64_t) p[6] << 48
+ | (uint64_t) p[5] << 40 | (uint64_t) p[4] << 32
+ | (uint64_t) p[3] << 24 | (uint64_t) p[2] << 16 | p[1] << 8 | p[0];
+}
+
+static uint32_t
+peek_u32le (const uint8_t *p)
+{
+ return (uint32_t) p[3] << 24 | (uint32_t) p[2] << 16 | p[1] << 8 | p[0];
+}
+
+static uint16_t
+peek_u16le (const uint8_t *p)
+{
+ return (uint16_t) p[1] << 8 | p[0];
+}
+
+struct peeker
+{
+ uint64_t (*u64) (const uint8_t *);
+ uint32_t (*u32) (const uint8_t *);
+ uint16_t (*u16) (const uint8_t *);
+};
+
+static const struct peeker peeker_be = {peek_u64be, peek_u32be, peek_u16be};
+static const struct peeker peeker_le = {peek_u64le, peek_u32le, peek_u16le};
+
// --- Errors ------------------------------------------------------------------
// Error reporting utilities. Inspired by GError, only much simpler.
@@ -2503,12 +2557,7 @@ msg_reader_get (struct msg_reader *self, size_t *len)
return NULL;
uint8_t *x = (uint8_t *) self->buf.str + self->offset;
- uint64_t msg_len
- = (uint64_t) x[0] << 56 | (uint64_t) x[1] << 48
- | (uint64_t) x[2] << 40 | (uint64_t) x[3] << 32
- | (uint64_t) x[4] << 24 | (uint64_t) x[5] << 16
- | (uint64_t) x[6] << 8 | (uint64_t) x[7];
-
+ uint64_t msg_len = peek_u64be (x);
if (msg_len < sizeof msg_len)
{
// The message is shorter than its header
@@ -2573,8 +2622,7 @@ static bool
msg_unpacker_u16 (struct msg_unpacker *self, uint16_t *value)
{
UNPACKER_INT_BEGIN
- *value
- = (uint16_t) x[0] << 8 | (uint16_t) x[1];
+ *value = peek_u16be (x);
return true;
}
@@ -2582,9 +2630,7 @@ static bool
msg_unpacker_u32 (struct msg_unpacker *self, uint32_t *value)
{
UNPACKER_INT_BEGIN
- *value
- = (uint32_t) x[0] << 24 | (uint32_t) x[1] << 16
- | (uint32_t) x[2] << 8 | (uint32_t) x[3];
+ *value = peek_u32be (x);
return true;
}
@@ -2592,11 +2638,7 @@ static bool
msg_unpacker_u64 (struct msg_unpacker *self, uint64_t *value)
{
UNPACKER_INT_BEGIN
- *value
- = (uint64_t) x[0] << 56 | (uint64_t) x[1] << 48
- | (uint64_t) x[2] << 40 | (uint64_t) x[3] << 32
- | (uint64_t) x[4] << 24 | (uint64_t) x[5] << 16
- | (uint64_t) x[6] << 8 | (uint64_t) x[7];
+ *value = peek_u64be (x);
return true;
}