HTable.xcc

Benoit Dupont de Dinechin (Benoit.Dupont-de-Dinechin@st.com)

Copyright 2007 STMicroelectronics. Copyright 1995 - 1998 Commissariat a l'Energie Atomique.

This program is free software; you can redistribute it and/or modify it under the terms of either (at your option): the GNU General Public License (GPL) version 2; the GNU Lesser General Public License (LGPL) version 2.1; any later version of these licences as published by the Free Software Foundation.

HTable_Hash— Multiplicative hash using the golden ratio (Knuth).

The input number interpreted as Q0.32 fractional is multiplied by the Q0.32 fractional representation of the golden ratio (sqrt(5) - 1)/2. Actually, the constant used is 2654435761, a prime close enough to (sqrt(5) - 1)/2 * 2*32. As a final step, we apply a pseudo modular reduction by the prime 2*31 - 1.

static inline uint32_t
HTable_Hash(uint32_t number)
{
  uint64_t result = number*(uint64_t)2654435761U;
  uint32_t hash = result + (result >> 31);
  return hash + (hash >> 31);
}

The HTableEntry_ structure implements the HTable entries. This structure is published for use in HTable_FOREACH.

struct HTableEntry_ {
  //@args       HTableKey key, size_t valueSize, struct HTableEntry_ *link
  HTableKey KEY;                // The key, which holds a pointer.
  struct HTableEntry_ *LINK;    // Link to the next HTableEntry in bucket.
  //@access VALUE       ((HTableValue)((HTableEntry_ *)(this) + 1))
};
HTable— Hash table implementation with chaining.
memory
Where the HTable entries are allocated.
estimate
Estimate of maximum number of entries in the hash table.
struct HTable_ {
  //@args       Memory memory, uint32_t estimate
  Memory MEMORY;
  uint32_t MASK;                // Mask for modulo clp2.
  int32_t COUNT;                // Count this HTable ENTRIES.
  HTableEntry *BUCKETS;         // This HTable buckets.
};
HTable_resize— Resize this HTable for the given estimated count.
void
HTable_resize(HTable this, uint32_t estimate);
HTable_empty— Empty this HTable.
void
HTable_empty(HTable this, HTableValueRelease release);
HTable_memory— This HTable Memory.
static inline Memory
HTable_memory(const_HTable this)
{
  return HTable_MEMORY(this);
}
HTable_isEmpty— True iff this HTable is empty.
#define HTable_isEmpty(this)    (HTable_count(this) == 0)
HTable_isSingle— True iff this HTable has a single entry.
#define HTable_isSingle(this)   (HTable_count(this) == 1)
HTable_count— Count entries in the HTable.
Return
The count of entries in the HTable.
static inline int32_t
HTable_count(const_HTable this)
{
  return HTable_COUNT(this);
}
HTable_mask— For use by HTable_FOREACH.
static inline uint32_t
HTable_mask(const_HTable this)
{
  return HTable_MASK(this);
}
HTable_buckets— For use by HTable_FOREACH.
Return
This HTable_ENTRIES.
static inline HTableEntry *
HTable_buckets(const_HTable this)
{
  return HTable_BUCKETS(this);
}
HTable_FOREACH— Iterates over the HTable entries.
key
Variable set for each key in this HTable.
Type
the value type.
iter
Pointer set to each value associated to key.

Exiting HTable_FOREACH with break or return is allowed.

Calling HTable_remove on the current entry is allowed.

#define HTable_FOREACH(this, key, Type, iter) { \
  HTableEntry *HTable_BUCKETS = HTable_buckets(this); \
  int32_t HTable_MASK = HTable_mask(this), HTable_INDEX; \
  for (HTable_INDEX = 0; HTable_INDEX <= HTable_MASK; HTable_INDEX++) { \
    HTableEntry HTable_ENTRY = HTable_BUCKETS[HTable_INDEX], HTableEntry_LINK; \
    for (; HTable_ENTRY != NULL; HTable_ENTRY = HTableEntry_LINK) { \
      HTableKey key = HTableEntry_key(HTable_ENTRY); \
      Type *(iter) = (Type *)HTableEntry_value(HTable_ENTRY); \
      HTableEntry_LINK = HTableEntry_link(HTable_ENTRY);
#define HTable_ENDEACH \
    } \
    if (HTable_ENTRY != NULL) break; \
  } \
}
HTable_search— Search the value associated to key.
Return
The associated value if key is in HTable, else NULL.
HTableValue
HTable_search(const_HTable this, HTableKey key);
HTable_lookup_— Lookup key and insert if not found.
Return
Pointer to the associated value (never return NULL).

In case of insertion, the new value is left uninitialized.

HTableValue
HTable_lookup_(HTable this, HTableKey key, size_t valueSize);
HTable_lookup— Lookup key and insert if not found.
Return
Pointer to the associated value (never return NULL).

In case of insertion, the new value is cleared.

static inline HTableValue
HTable_lookup(HTable this, HTableKey key, size_t valueSize)
{
  int32_t count = HTable_count(this);
  HTableValue value = HTable_lookup_(this, key, valueSize);
  if (count != HTable_count(this)) memset(value, 0, valueSize);
  return value;
}
HTable_insert— Insert key and return the associated value.
Return
Pointer to the associated value if key was inserted in HTable, NULL if key is already in HTable.
HTableValue
HTable_insert(HTable this, HTableKey key, size_t valueSize);
HTable_remove_— Specialized HTable_remove that does not release the HTableEntry.
HTableEntry
HTable_remove_(HTable this, HTableKey key);
HTable_remove— Remove key and the associated value.
Return
true if key was in HTable, else false.
static inline bool
HTable_remove(HTable this, HTableKey key, HTableValueRelease release)
{
  Memory memory = HTable_MEMORY(this);
  HTableEntry entry = HTable_remove_(this, key);
  if (entry != NULL) {
    HTableValue value = HTableEntry_VALUE(entry);
    if (release != NULL) (*release)(value);
    Memory_free_(memory, entry);
    return true;
  }
  return false;
}
HTable_map— Map the HTable_map entries using the supplied map function.
map
The function that will be called for each entry in the HTable. First argument of (map) is the current key. Second argument of (map) is the void value associated to the current key. Third argument of (map) is the va_list corresponding to the ... arguments of HTable_map.
...
The other arguments if any to be passed to (*map) as va_list.
void
HTable_map(HTable this, void (*map)(HTableKey, HTableValue, va_list), ...);