diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ac937c..7148537 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 2.7) project(liblex) -add_library(lex STATIC src/pattern.c) +add_library(lex STATIC src/pattern.c src/pairmap.c) add_executable(liblex src/main.c) add_subdirectory(external/libds) diff --git a/include/pairmap.h b/include/pairmap.h new file mode 100644 index 0000000..628dc2b --- /dev/null +++ b/include/pairmap.h @@ -0,0 +1,59 @@ +#ifndef LIBLEX_PAIRMAP_H +#define LIBLEX_PAIRMAP_H + +#define LIBLEX_PAIRMAP_SIZE 64 +/** + * Since libds's hash table requires a pointer to a key object, it's necessary to modify a single + * key object (tmp) with the two values for the pair, and then pass it into the ht_xxx functions + * to be copied. This requires at least 3 things - set the x value, set the y value, call the + * hash table function the requires the key. These macros take care of these three things. + */ +#define PAIRMAP_PUT(map, tmp, newx, newy, data) do { (tmp)->x = newx; (tmp)->y = newy; ht_put(map, tmp, data); } while(0) +#define PAIRMAP_GET(map, tmp, newx, newy) ((tmp)->x = newx, (tmp)->y = newy, ht_get(map, tmp)) + +#include "ht.h" + +/** + * A key object used for hash tables that take a pair of integers + * instead of a single pointer. + */ +struct pairmap_key_s { + int x; + int y; +}; + +typedef struct pairmap_key_s pairmap_key; + +/** + * Hashes pairmap_key instead of the default string. + * This takes the lower 16 bits, and bit shifts them + * into a single integer. + * + * Why 16 bits? Well, the hash map implementation takes an unsigned long, + * which is only guaranteed to contain 32 bits. Therefore, assuming it + * has to be unique for any two equal-sized integers, it has to + * be twice the size. Hence, the largest the integers can be is 16. + * @param key the key for the hash table. + * @return the resulting hash. + */ +unsigned long pairmap_hash_func(void* key); +/** + * Compares two pairmap_key's. + * @param a the first pairmap_key + * @param b the second pairmap_key + * @return + */ +int pairmap_cmp_func(void* a, void* b); +/** + * Copies a pairmap_key. + * @param key the key to copy. + * @return the copy of the key. + */ +void* pairmap_copy_func(void* key); +/** + * Initializes a hash table with functions used for pair maps. + * @param ht the hash table to initialize. + */ +void pairmap_init_ht(ht* ht); + +#endif diff --git a/src/pairmap.c b/src/pairmap.c new file mode 100644 index 0000000..2745573 --- /dev/null +++ b/src/pairmap.c @@ -0,0 +1,29 @@ +#include "pairmap.h" +#include + +unsigned long pairmap_hash_func(void* key){ + pairmap_key* new_key = key; + unsigned int hash = 0; + hash |= ((new_key->x & 0xffff) << 8) + (new_key->y & 0xffff); + return hash; +} +int pairmap_cmp_func(void* a, void* b){ + pairmap_key* new_key_a = a; + pairmap_key* new_key_b = b; + return (new_key_a->x == new_key_b->x) && (new_key_a->y == new_key_b->y); +} +void* pairmap_copy_func(void* key){ + pairmap_key* copy_from = key; + pairmap_key* new_key = malloc(sizeof(*new_key)); + if(new_key){ + new_key->x = copy_from->x; + new_key->y = copy_from->y; + } + return new_key; +} +void pairmap_init_ht(ht* ht){ + ht_init(ht); + ht->hash_func = pairmap_hash_func; + ht->cmp_func = pairmap_cmp_func; + ht->copy_func = pairmap_copy_func; +}