/* SPDX-License-Identifier: LGPL-2.1-only */
/*
 * Copyright (c) 2012 Cumulus Networks, Inc
 */

#include "nl-default.h"

#include <netlink/object.h>
#include <netlink/hash.h>
#include <netlink/hashtable.h>

#include "nl-aux-core/nl-core.h"

/**
 * @ingroup core_types
 * @defgroup hashtable Hashtable
 * @{
 */

/**
 * Allocate hashtable
 * @arg size		Size of hashtable in number of elements
 *
 * @return Allocated hashtable or NULL.
 */
nl_hash_table_t *nl_hash_table_alloc(int size)
{
	nl_hash_table_t *ht;

	ht = calloc(1, sizeof (*ht));
	if (!ht)
		goto errout;

	ht->nodes = calloc(size, sizeof (*ht->nodes));
	if (!ht->nodes) {
		free(ht);
		goto errout;
	}

	ht->size = size;

	return ht;
errout:
	return NULL;
}

/**
 * Free hashtable including all nodes
 * @arg ht		Hashtable
 *
 * @note Reference counter of all objects in the hashtable will be decremented.
 */
void nl_hash_table_free(nl_hash_table_t *ht)
{
	int i;

	for(i = 0; i < ht->size; i++) {
		nl_hash_node_t *node = ht->nodes[i];
		nl_hash_node_t *saved_node;

		while (node) {
			saved_node = node;
			node = node->next;
			nl_object_put(saved_node->obj);
			free(saved_node);
		}
	}

	free(ht->nodes);
	free(ht);
}

/**
 * Lookup identical object in hashtable
 * @arg ht		Hashtable
 * @arg	obj		Object to lookup
 *
 * Generates hashkey for `obj` and traverses the corresponding chain calling
 * `nl_object_identical()` on each trying to find a match.
 *
 * @return Pointer to object if match was found or NULL.
 */
struct nl_object* nl_hash_table_lookup(nl_hash_table_t *ht,
				       struct nl_object *obj)
{
	nl_hash_node_t *node;
	uint32_t key_hash;

	nl_object_keygen(obj, &key_hash, ht->size);
	node = ht->nodes[key_hash];

	while (node) {
		if (nl_object_identical(node->obj, obj))
			return node->obj;
		node = node->next;
	}

	return NULL;
}

/**
 * Add object to hashtable
 * @arg ht		Hashtable
 * @arg obj		Object to add
 *
 * Adds `obj` to the hashtable. Object type must support hashing, otherwise all
 * objects will be added to the chain `0`.
 *
 * @note The reference counter of the object is incremented.
 *
 * @return 0 on success or a negative error code
 * @retval -NLE_EXIST Identical object already present in hashtable
 */
int nl_hash_table_add(nl_hash_table_t *ht, struct nl_object *obj)
{
	nl_hash_node_t *node;
	uint32_t key_hash;

	nl_object_keygen(obj, &key_hash, ht->size);
	node = ht->nodes[key_hash];

	while (node) {
		if (nl_object_identical(node->obj, obj)) {
			NL_DBG(2, "Warning: Add to hashtable found duplicate...\n");
			return -NLE_EXIST;
		}
		node = node->next;
	}

	NL_DBG (5, "adding cache entry of obj %p in table %p, with hash 0x%x\n",
		obj, ht, key_hash);

	node = malloc(sizeof(nl_hash_node_t));
	if (!node)
		return -NLE_NOMEM;
	nl_object_get(obj);
	node->obj = obj;
	node->key = key_hash;
	node->key_size = sizeof(uint32_t);
	node->next = ht->nodes[key_hash];
	ht->nodes[key_hash] = node;

	return 0;
}

/**
 * Remove object from hashtable
 * @arg ht		Hashtable
 * @arg obj		Object to remove
 *
 * Remove `obj` from hashtable if it exists.
 *
 * @note Reference counter of object will be decremented.
 *
 * @return 0 on success or a negative error code.
 * @retval -NLE_OBJ_NOTFOUND Object not present in hashtable.
 */
int nl_hash_table_del(nl_hash_table_t *ht, struct nl_object *obj)
{
	nl_hash_node_t *node, *prev;
	uint32_t key_hash;

	nl_object_keygen(obj, &key_hash, ht->size);
	prev = node = ht->nodes[key_hash];

	while (node) {
		if (nl_object_identical(node->obj, obj)) {
			nl_object_put(obj);

			NL_DBG (5, "deleting cache entry of obj %p in table %p, with"
			        " hash 0x%x\n", obj, ht, key_hash);

			if (node == ht->nodes[key_hash])
				ht->nodes[key_hash] = node->next;
			else
				prev->next = node->next;

			free(node);

			return 0;
		}
		prev = node;
		node = node->next;
	}

	return -NLE_OBJ_NOTFOUND;
}

uint32_t nl_hash(void *k, size_t length, uint32_t initval)
{
	return(__nl_hash((char *) k, length, initval));
}

/** @} */
