Blame shared/nm-glib-aux/nm-hash-utils.h

Packit Service b23acc
// SPDX-License-Identifier: LGPL-2.1+
Packit Service b23acc
/*
Packit Service b23acc
 * Copyright (C) 2017 Red Hat, Inc.
Packit Service b23acc
 */
Packit Service b23acc
Packit Service b23acc
#ifndef __NM_HASH_UTILS_H__
Packit Service b23acc
#define __NM_HASH_UTILS_H__
Packit Service b23acc
Packit Service b23acc
#include "c-siphash/src/c-siphash.h"
Packit Service b23acc
#include "nm-macros-internal.h"
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
#define NM_HASH_SEED_16(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af) \
Packit Service b23acc
	((const guint8[16]) { a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af })
Packit Service b23acc
Packit Service b23acc
void nm_hash_siphash42_init (CSipHash *h, guint static_seed);
Packit Service b23acc
Packit Service b23acc
/* Siphash24 of binary buffer @arr and @len, using the randomized seed from
Packit Service b23acc
 * other NMHash functions.
Packit Service b23acc
 *
Packit Service b23acc
 * Note, that this is guaranteed to use siphash42 under the hood (contrary to
Packit Service b23acc
 * all other NMHash API, which leave this undefined). That matters at the point,
Packit Service b23acc
 * where the caller needs to be sure that a reasonably strong hashing algorithm
Packit Service b23acc
 * is used.  (Yes, NMHash is all about siphash24, but otherwise that is not promised
Packit Service b23acc
 * anywhere).
Packit Service b23acc
 *
Packit Service b23acc
 * Another difference is, that this returns guint64 (not guint like other NMHash functions).
Packit Service b23acc
 *
Packit Service b23acc
 * Another difference is, that this may also return zero (not like nm_hash_complete()).
Packit Service b23acc
 *
Packit Service b23acc
 * Then, why not use c_siphash_hash() directly? Because this also uses the randomized,
Packit Service b23acc
 * per-run hash-seed like nm_hash_init(). So, you get siphash24 with a random
Packit Service b23acc
 * seed (which is cached for the current run of the program).
Packit Service b23acc
 */
Packit Service b23acc
static inline guint64
Packit Service b23acc
nm_hash_siphash42 (guint static_seed, const void *ptr, gsize n)
Packit Service b23acc
{
Packit Service b23acc
	CSipHash h;
Packit Service b23acc
Packit Service b23acc
	nm_hash_siphash42_init (&h, static_seed);
Packit Service b23acc
	c_siphash_append (&h, ptr, n);
Packit Service b23acc
	return c_siphash_finalize (&h);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
struct _NMHashState {
Packit Service b23acc
	CSipHash _state;
Packit Service b23acc
};
Packit Service b23acc
Packit Service b23acc
typedef struct _NMHashState NMHashState;
Packit Service b23acc
Packit Service b23acc
guint nm_hash_static (guint static_seed);
Packit Service b23acc
Packit Service b23acc
static inline void
Packit Service b23acc
nm_hash_init (NMHashState *state, guint static_seed)
Packit Service b23acc
{
Packit Service b23acc
	nm_assert (state);
Packit Service b23acc
Packit Service b23acc
	nm_hash_siphash42_init (&state->_state, static_seed);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static inline guint64
Packit Service b23acc
nm_hash_complete_u64 (NMHashState *state)
Packit Service b23acc
{
Packit Service b23acc
	nm_assert (state);
Packit Service b23acc
Packit Service b23acc
	/* this returns the native u64 hash value. Note that this differs
Packit Service b23acc
	 * from nm_hash_complete() in two ways:
Packit Service b23acc
	 *
Packit Service b23acc
	 * - the type, guint64 vs. guint.
Packit Service b23acc
	 * - nm_hash_complete() never returns zero.
Packit Service b23acc
	 *
Packit Service b23acc
	 * In practice, nm_hash*() API is implemented via siphash24, so this returns
Packit Service b23acc
	 * the siphash24 value. But that is not guaranteed by the API, and if you need
Packit Service b23acc
	 * siphash24 directly, use c_siphash_*() and nm_hash_siphash42*() API. */
Packit Service b23acc
	return c_siphash_finalize (&state->_state);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static inline guint
Packit Service b23acc
nm_hash_complete (NMHashState *state)
Packit Service b23acc
{
Packit Service b23acc
	guint64 h;
Packit Service b23acc
Packit Service b23acc
	h = nm_hash_complete_u64 (state);
Packit Service b23acc
Packit Service b23acc
	/* we don't ever want to return a zero hash.
Packit Service b23acc
	 *
Packit Service b23acc
	 * NMPObject requires that in _idx_obj_part(), and it's just a good idea. */
Packit Service b23acc
	return    (((guint) (h >> 32)) ^ ((guint) h))
Packit Service b23acc
	       ?: 1396707757u;
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static inline void
Packit Service b23acc
nm_hash_update (NMHashState *state, const void *ptr, gsize n)
Packit Service b23acc
{
Packit Service b23acc
	nm_assert (state);
Packit Service b23acc
	nm_assert (n == 0 || ptr);
Packit Service b23acc
Packit Service b23acc
	/* Note: the data passed in here might be sensitive data (secrets),
Packit Service b23acc
	 * that we should nm_explicty_zero() afterwards. However, since
Packit Service b23acc
	 * we are using siphash24 with a random key, that is not really
Packit Service b23acc
	 * necessary. Something to keep in mind, if we ever move away from
Packit Service b23acc
	 * this hash implementation. */
Packit Service b23acc
	c_siphash_append (&state->_state, ptr, n);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
#define nm_hash_update_val(state, val) \
Packit Service b23acc
	G_STMT_START { \
Packit Service b23acc
		typeof (val) _val = (val); \
Packit Service b23acc
		\
Packit Service b23acc
		nm_hash_update ((state), &_val, sizeof (_val)); \
Packit Service b23acc
	} G_STMT_END
Packit Service b23acc
Packit Service b23acc
#define nm_hash_update_valp(state, val) \
Packit Service b23acc
	nm_hash_update ((state), (val), sizeof (*(val))) \
Packit Service b23acc
Packit Service b23acc
static inline void
Packit Service b23acc
nm_hash_update_bool (NMHashState *state, bool val)
Packit Service b23acc
{
Packit Service b23acc
	nm_hash_update (state, &val, sizeof (val));
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_x_1( t, y)      ((y) ? ((t) (1ull <<  0)) : ((t) 0ull))
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_x_2( t, y, ...) ((y) ? ((t) (1ull <<  1)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_1  (t, __VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_x_3( t, y, ...) ((y) ? ((t) (1ull <<  2)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_2  (t, __VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_x_4( t, y, ...) ((y) ? ((t) (1ull <<  3)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_3  (t, __VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_x_5( t, y, ...) ((y) ? ((t) (1ull <<  4)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_4  (t, __VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_x_6( t, y, ...) ((y) ? ((t) (1ull <<  5)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_5  (t, __VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_x_7( t, y, ...) ((y) ? ((t) (1ull <<  6)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_6  (t, __VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_x_8( t, y, ...) ((y) ? ((t) (1ull <<  7)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_7  (t, __VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_x_9( t, y, ...) ((y) ? ((t) (1ull <<  8)) : ((t) 0ull)) | (G_STATIC_ASSERT_EXPR (sizeof (t) >= 2), (_NM_HASH_COMBINE_BOOLS_x_8  (t, __VA_ARGS__)))
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_x_10(t, y, ...) ((y) ? ((t) (1ull <<  9)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_9  (t, __VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_x_11(t, y, ...) ((y) ? ((t) (1ull << 10)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_10 (t, __VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_n2(t, n, ...) _NM_HASH_COMBINE_BOOLS_x_##n (t, __VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_BOOLS_n(t, n, ...) _NM_HASH_COMBINE_BOOLS_n2(t, n, __VA_ARGS__)
Packit Service b23acc
Packit Service b23acc
#define NM_HASH_COMBINE_BOOLS(type, ...) ((type) (_NM_HASH_COMBINE_BOOLS_n(type, NM_NARG (__VA_ARGS__), __VA_ARGS__)))
Packit Service b23acc
Packit Service b23acc
#define nm_hash_update_bools(state, ...) \
Packit Service b23acc
	nm_hash_update_val (state, NM_HASH_COMBINE_BOOLS (guint8, __VA_ARGS__))
Packit Service b23acc
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_1( y)       typeof (y) _v1;
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_2( y, ...)  typeof (y) _v2;  _NM_HASH_COMBINE_VALS_typ_x_1  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_3( y, ...)  typeof (y) _v3;  _NM_HASH_COMBINE_VALS_typ_x_2  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_4( y, ...)  typeof (y) _v4;  _NM_HASH_COMBINE_VALS_typ_x_3  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_5( y, ...)  typeof (y) _v5;  _NM_HASH_COMBINE_VALS_typ_x_4  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_6( y, ...)  typeof (y) _v6;  _NM_HASH_COMBINE_VALS_typ_x_5  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_7( y, ...)  typeof (y) _v7;  _NM_HASH_COMBINE_VALS_typ_x_6  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_8( y, ...)  typeof (y) _v8;  _NM_HASH_COMBINE_VALS_typ_x_7  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_9( y, ...)  typeof (y) _v9;  _NM_HASH_COMBINE_VALS_typ_x_8  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_10(y, ...)  typeof (y) _v10; _NM_HASH_COMBINE_VALS_typ_x_9  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_11(y, ...)  typeof (y) _v11; _NM_HASH_COMBINE_VALS_typ_x_10  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_12(y, ...)  typeof (y) _v12; _NM_HASH_COMBINE_VALS_typ_x_11 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_13(y, ...)  typeof (y) _v13; _NM_HASH_COMBINE_VALS_typ_x_12 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_14(y, ...)  typeof (y) _v14; _NM_HASH_COMBINE_VALS_typ_x_13 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_15(y, ...)  typeof (y) _v15; _NM_HASH_COMBINE_VALS_typ_x_14 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_16(y, ...)  typeof (y) _v16; _NM_HASH_COMBINE_VALS_typ_x_15 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_17(y, ...)  typeof (y) _v17; _NM_HASH_COMBINE_VALS_typ_x_16 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_18(y, ...)  typeof (y) _v18; _NM_HASH_COMBINE_VALS_typ_x_17 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_19(y, ...)  typeof (y) _v19; _NM_HASH_COMBINE_VALS_typ_x_18 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_x_20(y, ...)  typeof (y) _v20; _NM_HASH_COMBINE_VALS_typ_x_19 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_n2(n, ...) _NM_HASH_COMBINE_VALS_typ_x_##n (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_typ_n(n, ...) _NM_HASH_COMBINE_VALS_typ_n2(n, __VA_ARGS__)
Packit Service b23acc
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_1( y)       ._v1  = (y),
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_2( y, ...)  ._v2  = (y), _NM_HASH_COMBINE_VALS_val_x_1  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_3( y, ...)  ._v3  = (y), _NM_HASH_COMBINE_VALS_val_x_2  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_4( y, ...)  ._v4  = (y), _NM_HASH_COMBINE_VALS_val_x_3  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_5( y, ...)  ._v5  = (y), _NM_HASH_COMBINE_VALS_val_x_4  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_6( y, ...)  ._v6  = (y), _NM_HASH_COMBINE_VALS_val_x_5  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_7( y, ...)  ._v7  = (y), _NM_HASH_COMBINE_VALS_val_x_6  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_8( y, ...)  ._v8  = (y), _NM_HASH_COMBINE_VALS_val_x_7  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_9( y, ...)  ._v9  = (y), _NM_HASH_COMBINE_VALS_val_x_8  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_10(y, ...)  ._v10 = (y), _NM_HASH_COMBINE_VALS_val_x_9  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_11(y, ...)  ._v11 = (y), _NM_HASH_COMBINE_VALS_val_x_10  (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_12(y, ...)  ._v12 = (y), _NM_HASH_COMBINE_VALS_val_x_11 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_13(y, ...)  ._v13 = (y), _NM_HASH_COMBINE_VALS_val_x_12 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_14(y, ...)  ._v14 = (y), _NM_HASH_COMBINE_VALS_val_x_13 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_15(y, ...)  ._v15 = (y), _NM_HASH_COMBINE_VALS_val_x_14 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_16(y, ...)  ._v16 = (y), _NM_HASH_COMBINE_VALS_val_x_15 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_17(y, ...)  ._v17 = (y), _NM_HASH_COMBINE_VALS_val_x_16 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_18(y, ...)  ._v18 = (y), _NM_HASH_COMBINE_VALS_val_x_17 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_19(y, ...)  ._v19 = (y), _NM_HASH_COMBINE_VALS_val_x_18 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_x_20(y, ...)  ._v20 = (y), _NM_HASH_COMBINE_VALS_val_x_19 (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_n2(n, ...) _NM_HASH_COMBINE_VALS_val_x_##n (__VA_ARGS__)
Packit Service b23acc
#define _NM_HASH_COMBINE_VALS_val_n(n, ...) _NM_HASH_COMBINE_VALS_val_n2(n, __VA_ARGS__)
Packit Service b23acc
Packit Service b23acc
/* NM_HASH_COMBINE_VALS() is faster then nm_hash_update_val() as it combines multiple
Packit Service b23acc
 * calls to nm_hash_update() using a packed structure. */
Packit Service b23acc
#define NM_HASH_COMBINE_VALS(var, ...) \
Packit Service b23acc
	const struct _nm_packed { \
Packit Service b23acc
		_NM_HASH_COMBINE_VALS_typ_n (NM_NARG (__VA_ARGS__), __VA_ARGS__) \
Packit Service b23acc
	} var _nm_alignas (guint64) = { \
Packit Service b23acc
		_NM_HASH_COMBINE_VALS_val_n (NM_NARG (__VA_ARGS__), __VA_ARGS__) \
Packit Service b23acc
	}
Packit Service b23acc
Packit Service b23acc
/* nm_hash_update_vals() is faster then nm_hash_update_val() as it combines multiple
Packit Service b23acc
 * calls to nm_hash_update() using a packed structure. */
Packit Service b23acc
#define nm_hash_update_vals(state, ...) \
Packit Service b23acc
	G_STMT_START { \
Packit Service b23acc
		NM_HASH_COMBINE_VALS (_val, __VA_ARGS__); \
Packit Service b23acc
		\
Packit Service b23acc
		nm_hash_update ((state), &_val, sizeof (_val)); \
Packit Service b23acc
	} G_STMT_END
Packit Service b23acc
Packit Service b23acc
static inline void
Packit Service b23acc
nm_hash_update_mem (NMHashState *state, const void *ptr, gsize n)
Packit Service b23acc
{
Packit Service b23acc
	/* This also hashes the length of the data. That means,
Packit Service b23acc
	 * hashing two consecutive binary fields (of arbitrary
Packit Service b23acc
	 * length), will hash differently. That is,
Packit Service b23acc
	 * [[1,1], []] differs from [[1],[1]].
Packit Service b23acc
	 *
Packit Service b23acc
	 * If you have a constant length (sizeof), use nm_hash_update()
Packit Service b23acc
	 * instead. */
Packit Service b23acc
	nm_hash_update (state, &n, sizeof (n));
Packit Service b23acc
	if (n > 0)
Packit Service b23acc
		nm_hash_update (state, ptr, n);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static inline void
Packit Service b23acc
nm_hash_update_str0 (NMHashState *state, const char *str)
Packit Service b23acc
{
Packit Service b23acc
	if (str)
Packit Service b23acc
		nm_hash_update_mem (state, str, strlen (str));
Packit Service b23acc
	else {
Packit Service b23acc
		gsize n = G_MAXSIZE;
Packit Service b23acc
Packit Service b23acc
		nm_hash_update (state, &n, sizeof (n));
Packit Service b23acc
	}
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
static inline void
Packit Service b23acc
nm_hash_update_str (NMHashState *state, const char *str)
Packit Service b23acc
{
Packit Service b23acc
	nm_assert (str);
Packit Service b23acc
	nm_hash_update (state, str, strlen (str) + 1);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
#if _NM_CC_SUPPORT_GENERIC
Packit Service b23acc
/* Like nm_hash_update_str(), but restricted to arrays only. nm_hash_update_str() only works
Packit Service b23acc
 * with a @str argument that cannot be NULL. If you have a string pointer, that is never NULL, use
Packit Service b23acc
 * nm_hash_update() instead. */
Packit Service b23acc
#define nm_hash_update_strarr(state, str) \
Packit Service b23acc
	(_Generic (&(str), \
Packit Service b23acc
		const char (*) [sizeof (str)]: nm_hash_update_str ((state), (str)), \
Packit Service b23acc
		char (*) [sizeof (str)]:       nm_hash_update_str ((state), (str))) \
Packit Service b23acc
	)
Packit Service b23acc
#else
Packit Service b23acc
#define nm_hash_update_strarr(state, str) nm_hash_update_str ((state), (str))
Packit Service b23acc
#endif
Packit Service b23acc
Packit Service b23acc
guint nm_hash_ptr (gconstpointer ptr);
Packit Service b23acc
guint nm_direct_hash (gconstpointer str);
Packit Service b23acc
Packit Service b23acc
guint nm_hash_str (const char *str);
Packit Service b23acc
guint nm_str_hash (gconstpointer str);
Packit Service b23acc
Packit Service b23acc
#define nm_hash_val(static_seed, val) \
Packit Service b23acc
	({ \
Packit Service b23acc
		NMHashState _h; \
Packit Service b23acc
		\
Packit Service b23acc
		nm_hash_init (&_h, (static_seed)); \
Packit Service b23acc
		nm_hash_update_val (&_h, (val)); \
Packit Service b23acc
		nm_hash_complete (&_h); \
Packit Service b23acc
	})
Packit Service b23acc
Packit Service b23acc
static inline guint
Packit Service b23acc
nm_hash_mem (guint static_seed, const void *ptr, gsize n)
Packit Service b23acc
{
Packit Service b23acc
	NMHashState h;
Packit Service b23acc
Packit Service b23acc
	if (n == 0)
Packit Service b23acc
		return nm_hash_static (static_seed);
Packit Service b23acc
	nm_hash_init (&h, static_seed);
Packit Service b23acc
	nm_hash_update (&h, ptr, n);
Packit Service b23acc
	return nm_hash_complete (&h);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
/* nm_pstr_*() are for hashing keys that are pointers to strings,
Packit Service b23acc
 * that is, "const char *const*" types, using strcmp(). */
Packit Service b23acc
Packit Service b23acc
guint nm_pstr_hash (gconstpointer p);
Packit Service b23acc
Packit Service b23acc
gboolean nm_pstr_equal (gconstpointer a, gconstpointer b);
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
/* nm_pint_*() are for hashing keys that are pointers to int values,
Packit Service b23acc
 * that is, "const int *" types. */
Packit Service b23acc
Packit Service b23acc
guint nm_pint_hash (gconstpointer p);
Packit Service b23acc
gboolean nm_pint_equals (gconstpointer a, gconstpointer b);
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
/* this hashes/compares the pointer value that we point to. Basically,
Packit Service b23acc
 * (*((const void *const*) a) == *((const void *const*) b)). */
Packit Service b23acc
Packit Service b23acc
guint nm_pdirect_hash (gconstpointer p);
Packit Service b23acc
Packit Service b23acc
gboolean nm_pdirect_equal (gconstpointer a, gconstpointer b);
Packit Service b23acc
Packit Service b23acc
/* this hashes/compares the direct pointer value by following pointers to
Packit Service b23acc
 * pointers 2 times.
Packit Service b23acc
 * (**((const void *const*const*) a) == **((const void *const*const*) b)). */
Packit Service b23acc
Packit Service b23acc
guint nm_ppdirect_hash (gconstpointer p);
Packit Service b23acc
Packit Service b23acc
gboolean nm_ppdirect_equal (gconstpointer a, gconstpointer b);
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
guint nm_gbytes_hash (gconstpointer p);
Packit Service b23acc
#define nm_gbytes_equal g_bytes_equal
Packit Service b23acc
Packit Service b23acc
guint nm_pgbytes_hash (gconstpointer p);
Packit Service b23acc
gboolean nm_pgbytes_equal (gconstpointer a, gconstpointer b);
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
#define NM_HASH_OBFUSCATE_PTR_FMT "%016" G_GINT64_MODIFIER "x"
Packit Service b23acc
Packit Service b23acc
/* sometimes we want to log a pointer directly, for providing context/information about
Packit Service b23acc
 * the message that get logged. Logging pointer values directly defeats ASLR, so we should
Packit Service b23acc
 * not do that. This returns a "unsigned long long" value that can be used
Packit Service b23acc
 * instead.
Packit Service b23acc
 *
Packit Service b23acc
 * Note that there is a chance that two different pointer values hash to the same obfuscated
Packit Service b23acc
 * value. So beware of that when reviewing logs. However, such a collision is very unlikely. */
Packit Service b23acc
static inline guint64
Packit Service b23acc
nm_hash_obfuscate_ptr (guint static_seed, gconstpointer val)
Packit Service b23acc
{
Packit Service b23acc
	NMHashState h;
Packit Service b23acc
Packit Service b23acc
	nm_hash_init (&h, static_seed);
Packit Service b23acc
	nm_hash_update_val (&h, val);
Packit Service b23acc
	return nm_hash_complete_u64 (&h);
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
/* if you want to log obfuscated pointer for a certain context (like, NMPRuleManager
Packit Service b23acc
 * logging user-tags), then you are advised to use nm_hash_obfuscate_ptr() with your
Packit Service b23acc
 * own, unique static-seed.
Packit Service b23acc
 *
Packit Service b23acc
 * However, for example the singleton constructors log the obfuscated pointer values
Packit Service b23acc
 * for all singletons, so they must all be obfuscated with the same seed. So, this
Packit Service b23acc
 * macro uses a particular static seed that should be used by when comparing pointer
Packit Service b23acc
 * values in a global context. */
Packit Service b23acc
#define NM_HASH_OBFUSCATE_PTR(ptr) (nm_hash_obfuscate_ptr (1678382159u, ptr))
Packit Service b23acc
Packit Service b23acc
/*****************************************************************************/
Packit Service b23acc
Packit Service b23acc
#endif /* __NM_HASH_UTILS_H__ */