glib-aux: add NM_HASH_SEED_16_U64() macro

c_siphash_init() requires a 16 bytes array. That is cumbersome to use.
We have NM_HASH_SEED_16() macro for helping with that. It's still
cumbersome.

Most of the time, the caller just wants to pick an arbitrarily chosen,
fixed number. Add NM_HASH_SEED_16_U64() which takes a number and gives
a 16 seed array. The argument is in host endianness, but the resulting
seed array has it encoded in big endianness, to be architecture
independent.
This commit is contained in:
Thomas Haller 2023-11-03 10:41:50 +01:00
parent 832065b6e6
commit 0d6885c087
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
2 changed files with 40 additions and 1 deletions

View file

@ -557,6 +557,21 @@ test_nm_hash(void)
#endif
NM_STATIC_ASSERT_EXPR_VOID(NM_HASH_COMBINE_BOOLS(int, 1, 0, 1) == 5);
g_assert_cmpmem(NM_HASH_SEED_16(55, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
16,
((guint8[16]){55, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}),
16);
g_assert_cmpmem(NM_HASH_SEED_16_U64(1), 16, ((guint8[16]){0, 0, 0, 0, 0, 0, 0, 1, 0}), 16);
g_assert_cmpmem(NM_HASH_SEED_16_U64(0x1234567890ABCDEFu),
16,
((guint8[16]){0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0}),
16);
g_assert_cmpint(c_siphash_hash(NM_HASH_SEED_16_U64(0x780E21E45489CC6Fu), (guint8 *) "foo", 3),
==,
0XA5A41E5C1B4153BFu);
}
/*****************************************************************************/

View file

@ -14,6 +14,30 @@
#define NM_HASH_SEED_16(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af) \
((const guint8[16]){a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af})
struct _nm_packed _nm_hash_seed_16_u64_data {
guint64 s1;
guint64 s2;
};
G_STATIC_ASSERT(sizeof(struct _nm_hash_seed_16_u64_data) == 16);
G_STATIC_ASSERT(sizeof(struct _nm_hash_seed_16_u64_data) == sizeof(guint64) * 2);
/* c_siphash_init() has a seed of 16 bytes (NM_HASH_SEED_16()). That is
* cumbersome to use, because we usually just hardcode an arbitrarily chosen,
* fixed number.
*
* This macro takes a u64 (in host-endianness) and returns a 16 byte seed
* buffer. The number will be big endian encoded, to be architecture
* independent. */
#define NM_HASH_SEED_16_U64(u64) \
((const guint8 *) ((gpointer) \
& ((struct _nm_hash_seed_16_u64_data){ \
.s1 = htobe64((u64)), \
.s2 = 0, \
})))
/*****************************************************************************/
void nm_hash_siphash42_init(CSipHash *h, guint static_seed);
/* Siphash24 of binary buffer @arr and @len, using the randomized seed from
@ -22,7 +46,7 @@ void nm_hash_siphash42_init(CSipHash *h, guint static_seed);
* Note, that this is guaranteed to use siphash42 under the hood (contrary to
* all other NMHash API, which leave this undefined). That matters at the point,
* where the caller needs to be sure that a reasonably strong hashing algorithm
* is used. (Yes, NMHash is all about siphash24, but otherwise that is not promised
* is used. (Yes, NMHash is all about siphash42, but otherwise that is not promised
* anywhere).
*
* Another difference is, that this returns guint64 (not guint like other NMHash functions).