xserver-multidpi/test/hashtabletest.c
Erkki Seppälä ccb3e78124 Xext: add a generic hashtable implementation
The generic hashtable implementation adds a key-value container, that
keeps the key and value inside the hashtable structure and manages
their memory by itself. This data structure is best suited for
fixed-length keys and values.

One creates a new hash table with ht_create and disposes it with
ht_destroy. ht_create accepts the key and value sizes (in bytes) in
addition to the hashing and comparison functions to use. When adding
keys with ht_add, they will be copied into the hash and a pointer to
the value will be returned: data may be put into this structure (or if
the hash table is to be used as a set, one can just not put anything
in).

The hash table comes also with one generic hashing function plus a
comparison function to facilitate ease of use. It also has a custom
hashing and comparison functions for hashing resource IDs with
HashXID.

Reviewed-by: Rami Ylimäki <rami.ylimaki@vincit.fi>
Signed-off-by: Erkki Seppälä <erkki.seppala@vincit.fi>
2012-04-18 12:49:06 +03:00

163 lines
2.9 KiB
C

#include <misc.h>
#include <stdlib.h>
#include <stdio.h>
#include "hashtable.h"
#include "resource.h"
static void
print_xid(void* ptr, void* v)
{
XID *x = v;
printf("%ld", *x);
}
static void
print_int(void* ptr, void* v)
{
int *x = v;
printf("%d", *x);
}
static int
test1(void)
{
HashTable h;
XID id;
int c;
int ok = 1;
const int numKeys = 420;
printf("test1\n");
h = ht_create(sizeof(XID), sizeof(int), ht_resourceid_hash, ht_resourceid_compare, NULL);
for (c = 0; c < numKeys; ++c) {
int *dest;
id = c;
dest = ht_add(h, &id);
if (dest) {
*dest = 2 * c;
}
}
printf("Distribution after insertion\n");
ht_dump_distribution(h);
ht_dump_contents(h, print_xid, print_int, NULL);
for (c = 0; c < numKeys; ++c) {
XID id = c;
int* v = ht_find(h, &id);
if (v) {
if (*v == 2 * c) {
// ok
} else {
printf("Key %d doesn't have expected value %d but has %d instead\n",
c, 2 * c, *v);
ok = 0;
}
} else {
ok = 0;
printf("Cannot find key %d\n", c);
}
}
if (ok) {
printf("%d keys inserted and found\n", c);
for (c = 0; c < numKeys; ++c) {
XID id = c;
ht_remove(h, &id);
}
printf("Distribution after deletion\n");
ht_dump_distribution(h);
}
ht_destroy(h);
return ok;
}
static int
test2(void)
{
HashTable h;
XID id;
int c;
int ok = 1;
const int numKeys = 420;
printf("test2\n");
h = ht_create(sizeof(XID), 0, ht_resourceid_hash, ht_resourceid_compare, NULL);
for (c = 0; c < numKeys; ++c) {
id = c;
ht_add(h, &id);
}
for (c = 0; c < numKeys; ++c) {
XID id = c;
if (!ht_find(h, &id)) {
ok = 0;
printf("Cannot find key %d\n", c);
}
}
{
XID id = c + 1;
if (ht_find(h, &id)) {
ok = 0;
printf("Could find a key that shouldn't be there\n");
}
}
ht_destroy(h);
if (ok) {
printf("Test with empty keys OK\n");
} else {
printf("Test with empty keys FAILED\n");
}
return ok;
}
static int
test3(void)
{
int ok = 1;
HtGenericHashSetupRec hashSetup = {
.keySize = 4
};
HashTable h;
printf("test3\n");
h = ht_create(4, 0, ht_generic_hash, ht_generic_compare, &hashSetup);
if (!ht_add(h, "helo") ||
!ht_add(h, "wrld")) {
printf("Could not insert keys\n");
}
if (!ht_find(h, "helo") ||
!ht_find(h, "wrld")) {
ok = 0;
printf("Could not find inserted keys\n");
}
printf("Hash distribution with two strings\n");
ht_dump_distribution(h);
ht_destroy(h);
return ok;
}
int
main(void)
{
int ok = test1();
ok = ok && test2();
ok = ok && test3();
return ok ? 0 : 1;
}