summaryrefslogtreecommitdiffstats
path: root/usr.sbin/nscd/hashtable.h
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/nscd/hashtable.h')
-rw-r--r--usr.sbin/nscd/hashtable.h218
1 files changed, 218 insertions, 0 deletions
diff --git a/usr.sbin/nscd/hashtable.h b/usr.sbin/nscd/hashtable.h
new file mode 100644
index 0000000..86dad9f
--- /dev/null
+++ b/usr.sbin/nscd/hashtable.h
@@ -0,0 +1,218 @@
+/*-
+ * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __CACHELIB_HASHTABLE_H__
+#define __CACHELIB_HASHTABLE_H__
+
+#include <search.h>
+#include <string.h>
+
+#define HASHTABLE_INITIAL_ENTRIES_CAPACITY 8
+typedef int hashtable_index_t;
+
+/*
+ * This file contains queue.h-like macro definitions for hash tables.
+ * Hash table is organized as an array of the specified size of the user
+ * defined (with HASTABLE_ENTRY_HEAD) structures. Each hash table
+ * entry (user defined structure) stores its elements in the sorted array.
+ * You can place elements into the hash table, retrieve elements with
+ * specified key, traverse through all elements, and delete them.
+ * New elements are placed into the hash table by using the compare and
+ * hashing functions, provided by the user.
+ */
+
+/*
+ * Defines the hash table entry structure, that uses specified type of
+ * elements.
+ */
+#define HASHTABLE_ENTRY_HEAD(name, type) struct name { \
+ type *values; \
+ size_t capacity; \
+ size_t size; \
+}
+
+/*
+ * Defines the hash table structure, which uses the specified type of entries.
+ * The only restriction for entries is that is that they should have the field,
+ * defined with HASHTABLE_ENTRY_HEAD macro.
+ */
+#define HASHTABLE_HEAD(name, entry) struct name { \
+ struct entry *entries; \
+ size_t entries_size; \
+}
+
+#define HASHTABLE_ENTRIES_COUNT(table) ((table)->entries_size)
+
+/*
+ * Unlike most of queue.h data types, hash tables can not be initialized
+ * statically - so there is no HASHTABLE_HEAD_INITIALIZED macro.
+ */
+#define HASHTABLE_INIT(table, type, field, _entries_size) \
+ do { \
+ hashtable_index_t var; \
+ (table)->entries = (void *)malloc( \
+ sizeof(*(table)->entries) * (_entries_size)); \
+ memset((table)->entries, 0, \
+ sizeof(*(table)->entries) * (_entries_size)); \
+ (table)->entries_size = (_entries_size); \
+ for (var = 0; var < HASHTABLE_ENTRIES_COUNT(table); ++var) {\
+ (table)->entries[var].field.capacity = \
+ HASHTABLE_INITIAL_ENTRIES_CAPACITY; \
+ (table)->entries[var].field.size = 0; \
+ (table)->entries[var].field.values = (type *)malloc(\
+ sizeof(type) * \
+ HASHTABLE_INITIAL_ENTRIES_CAPACITY); \
+ assert((table)->entries[var].field.values != NULL);\
+ } \
+ } while (0)
+
+/*
+ * All initialized hashtables should be destroyed with this macro.
+ */
+#define HASHTABLE_DESTROY(table, field) \
+ do { \
+ hashtable_index_t var; \
+ for (var = 0; var < HASHTABLE_ENTRIES_COUNT(table); ++var) {\
+ free((table)->entries[var].field.values); \
+ } \
+ } while (0)
+
+#define HASHTABLE_GET_ENTRY(table, hash) (&((table)->entries[hash]))
+
+/*
+ * Traverses through all hash table entries
+ */
+#define HASHTABLE_FOREACH(table, var) \
+ for ((var) = &((table)->entries[0]); \
+ (var) < &((table)->entries[HASHTABLE_ENTRIES_COUNT(table)]);\
+ ++(var))
+
+/*
+ * Traverses through all elements of the specified hash table entry
+ */
+#define HASHTABLE_ENTRY_FOREACH(entry, field, var) \
+ for ((var) = &((entry)->field.values[0]); \
+ (var) < &((entry)->field.values[(entry)->field.size]); \
+ ++(var))
+
+#define HASHTABLE_ENTRY_CLEAR(entry, field) \
+ ((entry)->field.size = 0)
+
+#define HASHTABLE_ENTRY_SIZE(entry, field) \
+ ((entry)->field.size)
+
+#define HASHTABLE_ENTRY_CAPACITY(entry, field) \
+ ((entry)->field.capacity)
+
+#define HASHTABLE_ENTRY_CAPACITY_INCREASE(entry, field, type) \
+ (entry)->field.capacity *= 2; \
+ (entry)->field.values = (type *)realloc((entry)->field.values, \
+ (entry)->field.capacity * sizeof(type));
+
+#define HASHTABLE_ENTRY_CAPACITY_DECREASE(entry, field, type) \
+ (entry)->field.capacity /= 2; \
+ (entry)->field.values = (type *)realloc((entry)->field.values, \
+ (entry)->field.capacity * sizeof(type));
+
+/*
+ * Generates prototypes for the hash table functions
+ */
+#define HASHTABLE_PROTOTYPE(name, entry_, type) \
+hashtable_index_t name##_CALCULATE_HASH(struct name *, type *); \
+void name##_ENTRY_STORE(struct entry_*, type *); \
+type *name##_ENTRY_FIND(struct entry_*, type *); \
+type *name##_ENTRY_FIND_SPECIAL(struct entry_ *, type *, \
+ int (*) (const void *, const void *)); \
+void name##_ENTRY_REMOVE(struct entry_*, type *);
+
+/*
+ * Generates implementations of the hash table functions
+ */
+#define HASHTABLE_GENERATE(name, entry_, type, field, HASH, CMP) \
+hashtable_index_t name##_CALCULATE_HASH(struct name *table, type *data) \
+{ \
+ \
+ return HASH(data, table->entries_size); \
+} \
+ \
+void name##_ENTRY_STORE(struct entry_ *the_entry, type *data) \
+{ \
+ \
+ if (the_entry->field.size == the_entry->field.capacity) \
+ HASHTABLE_ENTRY_CAPACITY_INCREASE(the_entry, field, type);\
+ \
+ memcpy(&(the_entry->field.values[the_entry->field.size++]), \
+ data, \
+ sizeof(type)); \
+ qsort(the_entry->field.values, the_entry->field.size, \
+ sizeof(type), CMP); \
+} \
+ \
+type *name##_ENTRY_FIND(struct entry_ *the_entry, type *key) \
+{ \
+ \
+ return ((type *)bsearch(key, the_entry->field.values, \
+ the_entry->field.size, sizeof(type), CMP)); \
+} \
+ \
+type *name##_ENTRY_FIND_SPECIAL(struct entry_ *the_entry, type *key, \
+ int (*compar) (const void *, const void *)) \
+{ \
+ return ((type *)bsearch(key, the_entry->field.values, \
+ the_entry->field.size, sizeof(type), compar)); \
+} \
+ \
+void name##_ENTRY_REMOVE(struct entry_ *the_entry, type *del_elm) \
+{ \
+ \
+ memmove(del_elm, del_elm + 1, \
+ (&the_entry->field.values[--the_entry->field.size] - del_elm) *\
+ sizeof(type)); \
+}
+
+/*
+ * Macro definitions below wrap the functions, generaed with
+ * HASHTABLE_GENERATE macro. You should use them and avoid using generated
+ * functions directly.
+ */
+#define HASHTABLE_CALCULATE_HASH(name, table, data) \
+ (name##_CALCULATE_HASH((table), data))
+
+#define HASHTABLE_ENTRY_STORE(name, entry, data) \
+ name##_ENTRY_STORE((entry), data)
+
+#define HASHTABLE_ENTRY_FIND(name, entry, key) \
+ (name##_ENTRY_FIND((entry), (key)))
+
+#define HASHTABLE_ENTRY_FIND_SPECIAL(name, entry, key, cmp) \
+ (name##_ENTRY_FIND_SPECIAL((entry), (key), (cmp)))
+
+#define HASHTABLE_ENTRY_REMOVE(name, entry, del_elm) \
+ name##_ENTRY_REMOVE((entry), (del_elm))
+
+#endif
OpenPOWER on IntegriCloud