zhash(3)
CZMQ Manual - CZMQ/1.4.1
Name
zhash - generic type-free hash container
Synopsis
// Callback function for zhash_foreach method
typedef int (zhash_foreach_fn) (const char *key, void *item, void *argument);
// Callback function for zhash_freefn method
typedef void (zhash_free_fn) (void *data);
// Create a new, empty hash container
CZMQ_EXPORT zhash_t *
zhash_new (void);
// Destroy a hash container and all items in it
CZMQ_EXPORT void
zhash_destroy (zhash_t **self_p);
// Insert item into hash table with specified key and item.
// If key is already present returns -1 and leaves existing item unchanged
// Returns 0 on success.
CZMQ_EXPORT int
zhash_insert (zhash_t *self, const char *key, void *item);
// Update item into hash table with specified key and item.
// If key is already present, destroys old item and inserts new one.
// Use free_fn method to ensure deallocator is properly called on item.
CZMQ_EXPORT void
zhash_update (zhash_t *self, const char *key, void *item);
// Remove an item specified by key from the hash table. If there was no such
// item, this function does nothing.
CZMQ_EXPORT void
zhash_delete (zhash_t *self, const char *key);
// Return the item at the specified key, or null
CZMQ_EXPORT void *
zhash_lookup (zhash_t *self, const char *key);
// Reindexes an item from an old key to a new key. If there was no such
// item, does nothing. Returns 0 if successful, else -1.
CZMQ_EXPORT int
zhash_rename (zhash_t *self, const char *old_key, const char *new_key);
// Set a free function for the specified hash table item. When the item is
// destroyed, the free function, if any, is called on that item.
// Use this when hash items are dynamically allocated, to ensure that
// you don't have memory leaks. You can pass 'free' or NULL as a free_fn.
// Returns the item, or NULL if there is no such item.
CZMQ_EXPORT void *
zhash_freefn (zhash_t *self, const char *key, zhash_free_fn *free_fn);
// Return the number of keys/items in the hash table
CZMQ_EXPORT size_t
zhash_size (zhash_t *self);
// Make copy of hash table
CZMQ_EXPORT zhash_t *
zhash_dup (zhash_t *self);
// Return keys for items in table
CZMQ_EXPORT zlist_t *
zhash_keys (zhash_t *self);
// Apply function to each item in the hash table. Items are iterated in no
// defined order. Stops if callback function returns non-zero and returns
// final return code from callback function (zero = success).
CZMQ_EXPORT int
zhash_foreach (zhash_t *self, zhash_foreach_fn *callback, void *argument);
// Save hash table to a text file in name=value format. Hash values must be
// printable strings; keys may not contain '=' character. Returns 0 if OK,
// else -1 if a file error occurred.
CZMQ_EXPORT int
zhash_save (zhash_t *self, char *filename);
// Load hash table from a text file in name=value format; hash table must
// already exist. Hash values must printable strings; keys may not contain
// '=' character. Returns 0 if OK, else -1 if a file was not readable.
CZMQ_EXPORT int
zhash_load (zhash_t *self, char *filename);
// Set hash for automatic value destruction
CZMQ_EXPORT void
zhash_autofree (zhash_t *self);
// Self test of this class
CZMQ_EXPORT void
zhash_test (int verbose);
Description
Expandable hash table container
Note that it's relatively slow (<subscript>50k insertions/deletes per second), so don't do inserts/updates on the critical path for message I/O. It can do </subscript>2.5M lookups per second for 16-char keys. Timed on a 1.6GHz CPU.
Example
From zhash_test method
zhash_t *hash = zhash_new ();
assert (hash);
assert (zhash_size (hash) == 0);
// Insert some items
int rc;
rc = zhash_insert (hash, "DEADBEEF", "dead beef");
assert (rc == 0);
rc = zhash_insert (hash, "ABADCAFE", "a bad cafe");
assert (rc == 0);
rc = zhash_insert (hash, "C0DEDBAD", "coded bad");
assert (rc == 0);
rc = zhash_insert (hash, "DEADF00D", "dead food");
assert (rc == 0);
assert (zhash_size (hash) == 4);
// Look for existing items
char *item;
item = (char *) zhash_lookup (hash, "DEADBEEF");
assert (streq (item, "dead beef"));
item = (char *) zhash_lookup (hash, "ABADCAFE");
assert (streq (item, "a bad cafe"));
item = (char *) zhash_lookup (hash, "C0DEDBAD");
assert (streq (item, "coded bad"));
item = (char *) zhash_lookup (hash, "DEADF00D");
assert (streq (item, "dead food"));
// Look for non-existent items
item = (char *) zhash_lookup (hash, "foo");
assert (item == NULL);
// Try to insert duplicate items
rc = zhash_insert (hash, "DEADBEEF", "foo");
assert (rc == -1);
item = (char *) zhash_lookup (hash, "DEADBEEF");
assert (streq (item, "dead beef"));
// Rename an item
rc = zhash_rename (hash, "DEADBEEF", "LIVEBEEF");
assert (rc == 0);
rc = zhash_rename (hash, "WHATBEEF", "LIVEBEEF");
assert (rc == -1);
// Test keys method
zlist_t *keys = zhash_keys (hash);
assert (zlist_size (keys) == 4);
zlist_destroy (&keys);
// Test dup method
zhash_t *copy = zhash_dup (hash);
assert (zhash_size (copy) == 4);
item = (char *) zhash_lookup (copy, "LIVEBEEF");
assert (item);
assert (streq (item, "dead beef"));
zhash_destroy (©);
// Test foreach
assert (0 == zhash_foreach (hash, test_foreach, hash));
assert (-1 == zhash_foreach (hash, test_foreach_error, hash));
// Test save and load
zhash_save (hash, ".cache");
copy = zhash_new ();
zhash_load (copy, ".cache");
item = (char *) zhash_lookup (copy, "LIVEBEEF");
assert (item);
assert (streq (item, "dead beef"));
zhash_destroy (©);
#if (defined (WIN32))
DeleteFile (".cache");
#else
unlink (".cache");
#endif
// Delete a item
zhash_delete (hash, "LIVEBEEF");
item = (char *) zhash_lookup (hash, "LIVEBEEF");
assert (item == NULL);
assert (zhash_size (hash) == 3);
// Check that the queue is robust against random usage
struct {
char name [100];
bool exists;
} testset [200];
memset (testset, 0, sizeof (testset));
int testmax = 200, testnbr, iteration;
srandom ((unsigned) time (NULL));
for (iteration = 0; iteration < 25000; iteration++) {
testnbr = randof (testmax);
if (testset [testnbr].exists) {
item = (char *) zhash_lookup (hash, testset [testnbr].name);
assert (item);
zhash_delete (hash, testset [testnbr].name);
testset [testnbr].exists = false;
}
else {
sprintf (testset [testnbr].name, "%x-%x", rand (), rand ());
if (zhash_insert (hash, testset [testnbr].name, "") == 0)
testset [testnbr].exists = true;
}
}
// Test 10K lookups
for (iteration = 0; iteration < 10000; iteration++)
item = (char *) zhash_lookup (hash, "DEADBEEFABADCAFE");
// Destructor should be safe to call twice
zhash_destroy (&hash);
zhash_destroy (&hash); assert (hash == NULL);
See also
Authors
The CZMQ manual was written by Pieter Hintjens<moc.xitami|hp#moc.xitami|hp>.
Resources
Main web site: http://czmq.zeromq.org/
Report bugs to the ØMQ development mailing list: <gro.qmorez.stsil|ved-qmorez#gro.qmorez.stsil|ved-qmorez>
Copyright
Copyright (c) 1991-2010 iMatix Corporation and contributors. License LGPLv3+: GNU LGPL 3 or later <http://gnu.org/licenses/lgpl.html>. This is free software: you are free to change it and redistribute it. There is NO WARRANTY, to the extent permitted by law. For details see the files COPYING and COPYING.LESSER included with the CZMQ distribution.