Freeciv21
Develop your civilization from humble roots to a global empire
genhash.cpp File Reference

A general-purpose generic hash table implementation. More...

#include "genhash.h"
#include "log.h"
#include "shared.h"
#include "support.h"
#include <cstring>
+ Include dependency graph for genhash.cpp:

Go to the source code of this file.

Classes

struct  genhash_entry
 
struct  genhash
 
struct  genhash_iter
 

Macros

#define FULL_RATIO   0.75
 
#define MIN_RATIO   0.24
 
#define GENHASH_ITER(p)   ((struct genhash_iter *) (p))
 
#define MIN_BUCKETS   29
 Calculate a "reasonable" number of buckets for a given number of entries. More...
 
#define genhash_maybe_expand(htab)   genhash_maybe_resize((htab), true)
 Call this when an entry might be added or deleted: resizes the genhash table if seems like a good idea. More...
 
#define genhash_maybe_shrink(htab)   genhash_maybe_resize((htab), false)
 

Functions

genhash_val_t genhash_str_val_func (const char *vkey)
 A supplied genhash function appropriate to nul-terminated strings. More...
 
bool genhash_str_comp_func (const char *vkey1, const char *vkey2)
 A supplied function for comparison of nul-terminated strings: More...
 
char * genhash_str_copy_func (const char *vkey)
 Copy function for string allocation. More...
 
void genhash_str_free_func (char *vkey)
 Free function for string allocation. More...
 
static size_t genhash_calc_num_buckets (size_t num_entries)
 
static struct genhashgenhash_new_nbuckets (genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func, genhash_copy_fn_t key_copy_func, genhash_free_fn_t key_free_func, genhash_copy_fn_t data_copy_func, genhash_free_fn_t data_free_func, size_t num_buckets)
 Internal constructor, specifying exact number of buckets. More...
 
struct genhashgenhash_new_nentries_full (genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func, genhash_copy_fn_t key_copy_func, genhash_free_fn_t key_free_func, genhash_copy_fn_t data_copy_func, genhash_free_fn_t data_free_func, size_t nentries)
 Constructor specifying number of entries. More...
 
struct genhashgenhash_new_nentries (genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func, size_t nentries)
 Constructor specifying number of entries. More...
 
struct genhashgenhash_new_full (genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func, genhash_copy_fn_t key_copy_func, genhash_free_fn_t key_free_func, genhash_copy_fn_t data_copy_func, genhash_free_fn_t data_free_func)
 Constructor with unspecified number of entries. More...
 
struct genhashgenhash_new (genhash_val_fn_t key_val_func, genhash_comp_fn_t key_comp_func)
 Constructor with unspecified number of entries. More...
 
void genhash_destroy (struct genhash *pgenhash)
 Destructor: free internal memory. More...
 
static void genhash_resize_table (struct genhash *pgenhash, size_t new_nbuckets)
 Resize the genhash table: relink entries. More...
 
static bool genhash_maybe_resize (struct genhash *pgenhash, bool expandingp)
 
static genhash_val_t genhash_val_calc (const struct genhash *pgenhash, const void *key)
 Calculate genhash value given hash table and key. More...
 
static struct genhash_entry ** genhash_slot_lookup (const struct genhash *pgenhash, const void *key, genhash_val_t hash_val)
 Return slot (entry pointer) in genhash table where key resides, or where it should go if it is to be a new key. More...
 
static void genhash_default_get (void **pkey, void **data)
 Function to store from invalid data. More...
 
static void genhash_slot_get (struct genhash_entry *const *slot, void **pkey, void **data)
 Function to store data. More...
 
static void genhash_slot_create (struct genhash *pgenhash, struct genhash_entry **slot, const void *key, const void *data, genhash_val_t hash_val)
 Create the entry and call the copy callbacks. More...
 
static void genhash_slot_free (struct genhash *pgenhash, struct genhash_entry **slot)
 Free the entry slot and call the free callbacks. More...
 
static void genhash_slot_set (struct genhash *pgenhash, struct genhash_entry **slot, const void *key, const void *data)
 Clear previous values (with free callback) and call the copy callbacks. More...
 
bool genhash_set_no_shrink (struct genhash *pgenhash, bool no_shrink)
 Prevent or allow the genhash table automatically shrinking. More...
 
size_t genhash_size (const struct genhash *pgenhash)
 Returns the number of entries in the genhash table. More...
 
size_t genhash_capacity (const struct genhash *pgenhash)
 Returns the number of buckets in the genhash table. More...
 
struct genhashgenhash_copy (const struct genhash *pgenhash)
 Returns a newly allocated mostly deep copy of the given genhash table. More...
 
void genhash_clear (struct genhash *pgenhash)
 Remove all entries of the genhash table. More...
 
bool genhash_insert (struct genhash *pgenhash, const void *key, const void *data)
 Insert entry: returns TRUE if inserted, or FALSE if there was already an entry with the same key, in which case the entry was not inserted. More...
 
bool genhash_replace (struct genhash *pgenhash, const void *key, const void *data)
 Insert entry, replacing any existing entry which has the same key. More...
 
bool genhash_replace_full (struct genhash *pgenhash, const void *key, const void *data, void **old_pkey, void **old_pdata)
 Insert entry, replacing any existing entry which has the same key. More...
 
bool genhash_lookup (const struct genhash *pgenhash, const void *key, void **pdata)
 Lookup data. More...
 
bool genhash_remove (struct genhash *pgenhash, const void *key)
 Delete an entry from the genhash table. More...
 
bool genhash_remove_full (struct genhash *pgenhash, const void *key, void **deleted_pkey, void **deleted_pdata)
 Delete an entry from the genhash table. More...
 
bool genhashs_are_equal (const struct genhash *pgenhash1, const struct genhash *pgenhash2)
 Returns TRUE iff the hash tables contains the same pairs of key/data. More...
 
bool genhashs_are_equal_full (const struct genhash *pgenhash1, const struct genhash *pgenhash2, genhash_comp_fn_t data_comp_func)
 Returns TRUE iff the hash tables contains the same pairs of key/data. More...
 
size_t genhash_iter_sizeof ()
 "Sizeof" function implementation for generic_iterate genhash iterators. More...
 
void * genhash_iter_key (const struct iterator *genhash_iter)
 Helper function for genhash (key, value) pair iteration. More...
 
void * genhash_iter_value (const struct iterator *genhash_iter)
 Helper function for genhash (key, value) pair iteration. More...
 
static void genhash_iter_next (struct iterator *genhash_iter)
 Iterator interface 'next' function implementation. More...
 
static void * genhash_iter_get (const struct iterator *genhash_iter)
 Iterator interface 'get' function implementation. More...
 
static bool genhash_iter_valid (const struct iterator *genhash_iter)
 Iterator interface 'valid' function implementation. More...
 
static struct iteratorgenhash_iter_init_common (struct genhash_iter *iter, const struct genhash *pgenhash, void *(*get)(const struct iterator *))
 Common genhash iterator initializer. More...
 
struct iteratorgenhash_iter_init (struct genhash_iter *iter, const struct genhash *pgenhash)
 Returns an iterator that iterates over both keys and values of the genhash table. More...
 
struct iteratorgenhash_key_iter_init (struct genhash_iter *iter, const struct genhash *pgenhash)
 Returns an iterator over the genhash table's k genhashgenhashenhashys. More...
 
struct iteratorgenhash_value_iter_init (struct genhash_iter *iter, const struct genhash *pgenhash)
 Returns an iterator over the hash table's values. More...
 

Detailed Description

A general-purpose generic hash table implementation.

Based on implementation previous included in registry.c, but separated out so that can be used more generally. Maybe we should just use glib?

Original author: David Pfitzner dwp@m.nosp@m.so.a.nosp@m.nu.ed.nosp@m.u.au

A hash table maps keys to user data values, using a user-supplied hash function to do this efficiently. Here both keys and values are general data represented by (void*) pointers. Memory management of both keys and data is the responsibility of the caller: that is, the caller must ensure that the memory (especially for keys) remains valid (allocated) for as long as required (typically, the life of the genhash table). (Otherwise, to allocate keys internally would either have to restrict key type (e.g., strings), or have user-supplied function to duplicate a key type. See further comments below.)

User-supplied functions required are: key_val_func: map key to bucket number given number of buckets; should map keys fairly evenly to range 0 to (num_buckets - 1) inclusive.

key_comp_func: compare keys for equality, necessary for lookups for keys which map to the same genhash value. Keys which compare equal should map to the same hash value. Returns 0 for equality, so can use qsort-type comparison function (but the hash table does not make use of the ordering information if the return value is non-zero).

Some constructors also accept following functions to be registered: key_copy_func: This is called when assigning a new value to a bucket. key_free_func: This is called when genhash no longer needs key construct. Note that one key construct gets freed even when it is replaced with another that is considered identical by key_comp_func(). data_copy_func: same as 'key_copy_func', but for data. data_free_func: same as 'key_free_func', but for data.

Implementation uses open hashing. Collision resolution is done by separate chaining with linked lists. Resize hash table when deemed necessary by making and populating a new table.

Definition in file genhash.cpp.

Macro Definition Documentation

◆ FULL_RATIO

#define FULL_RATIO   0.75

Definition at line 68 of file genhash.cpp.

◆ GENHASH_ITER

#define GENHASH_ITER (   p)    ((struct genhash_iter *) (p))

Definition at line 98 of file genhash.cpp.

◆ genhash_maybe_expand

#define genhash_maybe_expand (   htab)    genhash_maybe_resize((htab), true)

Call this when an entry might be added or deleted: resizes the genhash table if seems like a good idea.

Count deleted entries in check because efficiency may be degraded if there are too many deleted entries. But for determining new size, ignore deleted entries, since they'll be removed by rehashing.

Definition at line 329 of file genhash.cpp.

◆ genhash_maybe_shrink

#define genhash_maybe_shrink (   htab)    genhash_maybe_resize((htab), false)

Definition at line 330 of file genhash.cpp.

◆ MIN_BUCKETS

#define MIN_BUCKETS   29

Calculate a "reasonable" number of buckets for a given number of entries.

Gives a prime number far from powers of 2, allowing at least a factor of 2 from the given number of entries for breathing room.

Generalized restrictions on the behavior of this function: MIN_BUCKETS <= genhash_calc_num_buckets(x) genhash_calc_num_buckets(x) * MIN_RATIO < x whenever x > MIN_BUCKETS * MIN_RATIO. genhash_calc_num_buckets(x) * FULL_RATIO > x. This one is more of a recommendation, to ensure enough free space: genhash_calc_num_buckets(x) >= 2 * x.

Definition at line 156 of file genhash.cpp.

◆ MIN_RATIO

#define MIN_RATIO   0.24

Definition at line 69 of file genhash.cpp.

Function Documentation

◆ genhash_calc_num_buckets()

static size_t genhash_calc_num_buckets ( size_t  num_entries)
static

◆ genhash_capacity()

size_t genhash_capacity ( const struct genhash pgenhash)

Returns the number of buckets in the genhash table.

Definition at line 528 of file genhash.cpp.

◆ genhash_clear()

void genhash_clear ( struct genhash pgenhash)

Remove all entries of the genhash table.

Definition at line 575 of file genhash.cpp.

Referenced by conn_reset_delta_state(), and genhash_destroy().

◆ genhash_copy()

struct genhash* genhash_copy ( const struct genhash pgenhash)

Returns a newly allocated mostly deep copy of the given genhash table.

Definition at line 537 of file genhash.cpp.

◆ genhash_default_get()

static void genhash_default_get ( void **  pkey,
void **  data 
)
inlinestatic

Function to store from invalid data.

Definition at line 414 of file genhash.cpp.

Referenced by genhash_lookup(), genhash_remove_full(), and genhash_replace_full().

◆ genhash_destroy()

void genhash_destroy ( struct genhash pgenhash)

Destructor: free internal memory.

Definition at line 284 of file genhash.cpp.

Referenced by free_packet_hashes().

◆ genhash_insert()

bool genhash_insert ( struct genhash pgenhash,
const void *  key,
const void *  data 
)

Insert entry: returns TRUE if inserted, or FALSE if there was already an entry with the same key, in which case the entry was not inserted.

Definition at line 597 of file genhash.cpp.

◆ genhash_iter_get()

static void* genhash_iter_get ( const struct iterator genhash_iter)
static

Iterator interface 'get' function implementation.

This just returns the iterator itself, so you would need to use genhash_iter_get_key/value to get the actual keys and values.

Definition at line 832 of file genhash.cpp.

Referenced by genhash_iter_init().

◆ genhash_iter_init()

struct iterator* genhash_iter_init ( struct genhash_iter iter,
const struct genhash pgenhash 
)

Returns an iterator that iterates over both keys and values of the genhash table.

NB: iterator_get() returns an iterator pointer, so use the helper functions genhash_iter_get_{key,value} to access the key and value.

Definition at line 880 of file genhash.cpp.

◆ genhash_iter_init_common()

static struct iterator* genhash_iter_init_common ( struct genhash_iter iter,
const struct genhash pgenhash,
void *(*)(const struct iterator *)  get 
)
inlinestatic

Common genhash iterator initializer.

Definition at line 850 of file genhash.cpp.

Referenced by genhash_iter_init(), genhash_key_iter_init(), and genhash_value_iter_init().

◆ genhash_iter_key()

void* genhash_iter_key ( const struct iterator genhash_iter)

Helper function for genhash (key, value) pair iteration.

Definition at line 792 of file genhash.cpp.

Referenced by genhash_key_iter_init().

◆ genhash_iter_next()

static void genhash_iter_next ( struct iterator genhash_iter)
static

Iterator interface 'next' function implementation.

Definition at line 810 of file genhash.cpp.

Referenced by genhash_iter_init_common().

◆ genhash_iter_sizeof()

size_t genhash_iter_sizeof ( )

"Sizeof" function implementation for generic_iterate genhash iterators.

Definition at line 787 of file genhash.cpp.

◆ genhash_iter_valid()

static bool genhash_iter_valid ( const struct iterator genhash_iter)
static

Iterator interface 'valid' function implementation.

Definition at line 840 of file genhash.cpp.

Referenced by genhash_iter_init_common().

◆ genhash_iter_value()

void* genhash_iter_value ( const struct iterator genhash_iter)

Helper function for genhash (key, value) pair iteration.

Definition at line 801 of file genhash.cpp.

Referenced by genhash_value_iter_init().

◆ genhash_key_iter_init()

struct iterator* genhash_key_iter_init ( struct genhash_iter iter,
const struct genhash pgenhash 
)

Returns an iterator over the genhash table's k genhashgenhashenhashys.

Definition at line 889 of file genhash.cpp.

◆ genhash_lookup()

bool genhash_lookup ( const struct genhash pgenhash,
const void *  key,
void **  pdata 
)

Lookup data.

Return TRUE on success, then pdata - if not nullptr will be set to the data value.

Definition at line 675 of file genhash.cpp.

◆ genhash_maybe_resize()

static bool genhash_maybe_resize ( struct genhash pgenhash,
bool  expandingp 
)
static

Definition at line 331 of file genhash.cpp.

◆ genhash_new()

struct genhash* genhash_new ( genhash_val_fn_t  key_val_func,
genhash_comp_fn_t  key_comp_func 
)

Constructor with unspecified number of entries.

Definition at line 274 of file genhash.cpp.

◆ genhash_new_full()

struct genhash* genhash_new_full ( genhash_val_fn_t  key_val_func,
genhash_comp_fn_t  key_comp_func,
genhash_copy_fn_t  key_copy_func,
genhash_free_fn_t  key_free_func,
genhash_copy_fn_t  data_copy_func,
genhash_free_fn_t  data_free_func 
)

Constructor with unspecified number of entries.

Allows to specify functions to free the memory allocated for the key and user-data that get called when removing the bucket from the hash table or changing key/user-data values.

Definition at line 259 of file genhash.cpp.

◆ genhash_new_nbuckets()

static struct genhash* genhash_new_nbuckets ( genhash_val_fn_t  key_val_func,
genhash_comp_fn_t  key_comp_func,
genhash_copy_fn_t  key_copy_func,
genhash_free_fn_t  key_free_func,
genhash_copy_fn_t  data_copy_func,
genhash_free_fn_t  data_free_func,
size_t  num_buckets 
)
static

Internal constructor, specifying exact number of buckets.

Allows to specify functions to free the memory allocated for the key and user-data that get called when removing the bucket from the hash table or changing key/user-data values.

NB: Be sure to check the "copy constructor" genhash_copy() if you change this function significantly.

Definition at line 195 of file genhash.cpp.

Referenced by genhash_new(), genhash_new_full(), genhash_new_nentries(), and genhash_new_nentries_full().

◆ genhash_new_nentries()

struct genhash* genhash_new_nentries ( genhash_val_fn_t  key_val_func,
genhash_comp_fn_t  key_comp_func,
size_t  nentries 
)

Constructor specifying number of entries.

Definition at line 244 of file genhash.cpp.

◆ genhash_new_nentries_full()

struct genhash* genhash_new_nentries_full ( genhash_val_fn_t  key_val_func,
genhash_comp_fn_t  key_comp_func,
genhash_copy_fn_t  key_copy_func,
genhash_free_fn_t  key_free_func,
genhash_copy_fn_t  data_copy_func,
genhash_free_fn_t  data_free_func,
size_t  nentries 
)

Constructor specifying number of entries.

Allows to specify functions to free the memory allocated for the key and user-data that get called when removing the bucket from the hash table or changing key/user-data values.

Definition at line 228 of file genhash.cpp.

◆ genhash_remove()

bool genhash_remove ( struct genhash pgenhash,
const void *  key 
)

Delete an entry from the genhash table.

Returns TRUE on success.

Definition at line 696 of file genhash.cpp.

◆ genhash_remove_full()

bool genhash_remove_full ( struct genhash pgenhash,
const void *  key,
void **  deleted_pkey,
void **  deleted_pdata 
)

Delete an entry from the genhash table.

Returns TRUE on success.

Returns in 'deleted_pkey' and 'deleted_pdata' the old contents of the deleted entry if not nullptr. NB: It can returns freed pointers if free functions were supplied to the genhash table.

Definition at line 708 of file genhash.cpp.

Referenced by genhash_remove().

◆ genhash_replace()

bool genhash_replace ( struct genhash pgenhash,
const void *  key,
const void *  data 
)

Insert entry, replacing any existing entry which has the same key.

Returns TRUE if a data have been replaced, FALSE if it was a simple insertion.

Definition at line 625 of file genhash.cpp.

◆ genhash_replace_full()

bool genhash_replace_full ( struct genhash pgenhash,
const void *  key,
const void *  data,
void **  old_pkey,
void **  old_pdata 
)

Insert entry, replacing any existing entry which has the same key.

Returns TRUE if a data have been replaced, FALSE if it was a simple insertion.

Returns in 'old_pkey' and 'old_pdata' the old content of the bucket if they are not nullptr. NB: It can returns freed pointers if free functions were supplied to the genhash table.

Definition at line 640 of file genhash.cpp.

Referenced by genhash_replace().

◆ genhash_resize_table()

static void genhash_resize_table ( struct genhash pgenhash,
size_t  new_nbuckets 
)
static

Resize the genhash table: relink entries.

Definition at line 297 of file genhash.cpp.

Referenced by genhash_maybe_resize().

◆ genhash_set_no_shrink()

bool genhash_set_no_shrink ( struct genhash pgenhash,
bool  no_shrink 
)

Prevent or allow the genhash table automatically shrinking.

Returns the old value of the setting.

Definition at line 506 of file genhash.cpp.

◆ genhash_size()

size_t genhash_size ( const struct genhash pgenhash)

Returns the number of entries in the genhash table.

Definition at line 519 of file genhash.cpp.

◆ genhash_slot_create()

static void genhash_slot_create ( struct genhash pgenhash,
struct genhash_entry **  slot,
const void *  key,
const void *  data,
genhash_val_t  hash_val 
)
inlinestatic

Create the entry and call the copy callbacks.

Definition at line 443 of file genhash.cpp.

Referenced by genhash_copy(), genhash_insert(), and genhash_replace_full().

◆ genhash_slot_free()

static void genhash_slot_free ( struct genhash pgenhash,
struct genhash_entry **  slot 
)
inlinestatic

Free the entry slot and call the free callbacks.

Definition at line 464 of file genhash.cpp.

Referenced by genhash_clear(), and genhash_remove_full().

◆ genhash_slot_get()

static void genhash_slot_get ( struct genhash_entry *const *  slot,
void **  pkey,
void **  data 
)
inlinestatic

Function to store data.

Definition at line 427 of file genhash.cpp.

Referenced by genhash_lookup(), genhash_remove_full(), and genhash_replace_full().

◆ genhash_slot_lookup()

static struct genhash_entry** genhash_slot_lookup ( const struct genhash pgenhash,
const void *  key,
genhash_val_t  hash_val 
)
inlinestatic

Return slot (entry pointer) in genhash table where key resides, or where it should go if it is to be a new key.

Definition at line 387 of file genhash.cpp.

Referenced by genhash_insert(), genhash_lookup(), genhash_remove_full(), genhash_replace_full(), and genhashs_are_equal_full().

◆ genhash_slot_set()

static void genhash_slot_set ( struct genhash pgenhash,
struct genhash_entry **  slot,
const void *  key,
const void *  data 
)
inlinestatic

Clear previous values (with free callback) and call the copy callbacks.

Definition at line 482 of file genhash.cpp.

Referenced by genhash_replace_full().

◆ genhash_str_comp_func()

bool genhash_str_comp_func ( const char *  vkey1,
const char *  vkey2 
)

A supplied function for comparison of nul-terminated strings:

Definition at line 119 of file genhash.cpp.

◆ genhash_str_copy_func()

char* genhash_str_copy_func ( const char *  vkey)

Copy function for string allocation.

Definition at line 127 of file genhash.cpp.

◆ genhash_str_free_func()

void genhash_str_free_func ( char *  vkey)

Free function for string allocation.

Definition at line 135 of file genhash.cpp.

◆ genhash_str_val_func()

genhash_val_t genhash_str_val_func ( const char *  vkey)

A supplied genhash function appropriate to nul-terminated strings.

Prefers table sizes that are prime numbers.

Definition at line 104 of file genhash.cpp.

◆ genhash_val_calc()

static genhash_val_t genhash_val_calc ( const struct genhash pgenhash,
const void *  key 
)
inlinestatic

Calculate genhash value given hash table and key.

Definition at line 372 of file genhash.cpp.

Referenced by genhash_insert(), genhash_lookup(), genhash_remove_full(), and genhash_replace_full().

◆ genhash_value_iter_init()

struct iterator* genhash_value_iter_init ( struct genhash_iter iter,
const struct genhash pgenhash 
)

Returns an iterator over the hash table's values.

Definition at line 898 of file genhash.cpp.

◆ genhashs_are_equal()

bool genhashs_are_equal ( const struct genhash pgenhash1,
const struct genhash pgenhash2 
)

Returns TRUE iff the hash tables contains the same pairs of key/data.

Definition at line 734 of file genhash.cpp.

◆ genhashs_are_equal_full()

bool genhashs_are_equal_full ( const struct genhash pgenhash1,
const struct genhash pgenhash2,
genhash_comp_fn_t  data_comp_func 
)

Returns TRUE iff the hash tables contains the same pairs of key/data.

Definition at line 743 of file genhash.cpp.

Referenced by genhashs_are_equal().