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

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