Expand the hash table implementation
Our implementation now resizes automatically and supports hashing by open addressing.
This commit is contained in:
parent
f4e04b0dfd
commit
02c7492f74
89
calathea.c
89
calathea.c
|
@ -50,6 +50,12 @@ char * read_file(char *filename) {
|
|||
}
|
||||
|
||||
/*** Hash map implementation ***/
|
||||
struct PageMap {
|
||||
struct Page **pages;
|
||||
int capacity;
|
||||
int size;
|
||||
};
|
||||
|
||||
int helper_hash_polynomial(
|
||||
char string[],
|
||||
int i,
|
||||
|
@ -65,33 +71,69 @@ int helper_hash_polynomial(
|
|||
}
|
||||
}
|
||||
|
||||
int hash_polynomial(int mapSize, char key[]) {
|
||||
return helper_hash_polynomial(key, 0, strlen(key), mapSize, 0);
|
||||
int hash_polynomial(int capacity, char key[]) {
|
||||
return helper_hash_polynomial(key, 0, strlen(key), capacity, 0);
|
||||
}
|
||||
|
||||
void to_lower_case(char dest[], char str[]) {
|
||||
char * to_lower_case(char str[]) {
|
||||
char * lower = malloc((strlen(str) + 1) * sizeof(char));
|
||||
int i = 0;
|
||||
for (; str[i] != '\0'; i++) {
|
||||
dest[i] = tolower(str[i]);
|
||||
lower[i] = tolower(str[i]);
|
||||
}
|
||||
dest[i] = 0;
|
||||
lower[i] = 0;
|
||||
|
||||
return lower;
|
||||
}
|
||||
|
||||
void map_put(struct Page **map, int mapSize, char title[], struct Page *page) {
|
||||
char lowercased[80];
|
||||
to_lower_case(lowercased, title);
|
||||
|
||||
int index = hash_polynomial(mapSize, lowercased);
|
||||
map[index] = page;
|
||||
struct PageMap * map(int capacity) {
|
||||
struct PageMap *map = malloc(sizeof(struct PageMap));
|
||||
map->pages = calloc(capacity, sizeof(struct Page *));
|
||||
map->capacity = capacity;
|
||||
map->size = 0;
|
||||
return map;
|
||||
}
|
||||
|
||||
struct Page * map_get(struct Page **map, int mapSize, char title[]) {
|
||||
char lowercased[80];
|
||||
to_lower_case(lowercased, title);
|
||||
void map_free(struct PageMap *map) {
|
||||
free(map->pages);
|
||||
free(map);
|
||||
}
|
||||
|
||||
int index = hash_polynomial(mapSize, lowercased);
|
||||
struct Page *page = map[index];
|
||||
void map_put(struct PageMap *map, char title[], struct Page *page) {
|
||||
char *lowercased = to_lower_case(title);
|
||||
|
||||
int index = hash_polynomial(map->capacity, lowercased);
|
||||
while (map->pages[index] != NULL) index++;
|
||||
map->pages[index] = page;
|
||||
map->size++;
|
||||
|
||||
// Resize the map if we're running low on space
|
||||
if (map->size/map->capacity > 0.75) {
|
||||
map->pages = realloc(map->pages, map->capacity * 2);
|
||||
for (int i = map->capacity; i < map->capacity * 2; i++) {
|
||||
map->pages[i] = 0;
|
||||
}
|
||||
map->capacity *= 2;
|
||||
}
|
||||
|
||||
free(lowercased);
|
||||
}
|
||||
|
||||
struct Page * map_get(struct PageMap *map, char title[]) {
|
||||
char *lowercased = to_lower_case(title);
|
||||
|
||||
int index = hash_polynomial(map->capacity, lowercased);
|
||||
struct Page *page = map->pages[index];
|
||||
|
||||
char *lowercasedFoundTitle = to_lower_case(page->title);
|
||||
while (strcmp(lowercasedFoundTitle, lowercased) != 0) {
|
||||
page = map->pages[++index];
|
||||
free(lowercasedFoundTitle);
|
||||
lowercasedFoundTitle = to_lower_case(page->title);
|
||||
}
|
||||
|
||||
free(lowercased);
|
||||
free(lowercasedFoundTitle);
|
||||
return page;
|
||||
}
|
||||
|
||||
|
@ -176,7 +218,6 @@ char * substitute_string(char dest[], char sub[], char *start, char *end) {
|
|||
|
||||
int main(int argc, char *argv[]) {
|
||||
char pagesLocation[256] = "./pages";
|
||||
int mapSize = 1000;
|
||||
int initialInboundCapacity = 2;
|
||||
char templateFileName[256] = "./template.html";
|
||||
char outputDirectoryName[256] = "./build";
|
||||
|
@ -189,11 +230,6 @@ int main(int argc, char *argv[]) {
|
|||
i++;
|
||||
strcpy(pagesLocation, argv[i]);
|
||||
}
|
||||
} else if (strcmp(argv[i], "--table-size") == 0) {
|
||||
if (i + 1 < argc) {
|
||||
i++;
|
||||
mapSize = atoi(argv[i]);
|
||||
}
|
||||
} else if (strcmp(argv[i], "--template") == 0) {
|
||||
if (i + 1 < argc) {
|
||||
i++;
|
||||
|
@ -230,8 +266,7 @@ int main(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
struct Page ** pageMap = malloc(mapSize * sizeof(struct Page *));
|
||||
memset(pageMap, 0, mapSize * sizeof(struct Page *));
|
||||
struct PageMap *pageMap = map(100);
|
||||
|
||||
// Contains some information about the current file picked from pagesDir
|
||||
struct dirent *fileEntry = readdir(pagesDir);
|
||||
|
@ -310,7 +345,7 @@ int main(int argc, char *argv[]) {
|
|||
currentPage->title[min(titleLength, 80)] = 0;
|
||||
|
||||
// Insert it into the hash map for lookup later
|
||||
map_put(pageMap, mapSize, currentPage->title, currentPage);
|
||||
map_put(pageMap, currentPage->title, currentPage);
|
||||
|
||||
// Get ready to process the next page
|
||||
fileEntry = readdir(pagesDir);
|
||||
|
@ -360,14 +395,13 @@ int main(int argc, char *argv[]) {
|
|||
strncpy(linkTitle, nextLinkStart + 2, (nextVerticalBar - 1) - (nextLinkStart + 1));
|
||||
linkPageTitle = calloc((nextLinkEnd - 2) - nextVerticalBar, sizeof(char));
|
||||
strncpy(linkPageTitle, nextVerticalBar + 1, (nextLinkEnd - 1) - nextVerticalBar);
|
||||
puts(linkPageTitle);
|
||||
} else {
|
||||
// The link is of the form [[page title]]
|
||||
linkPageTitle = linkTitle;
|
||||
strncpy(linkTitle, nextLinkStart + 2, (linkLength - 2)*sizeof(char));
|
||||
}
|
||||
|
||||
struct Page *linkedPage = map_get(pageMap, mapSize, linkPageTitle);
|
||||
struct Page *linkedPage = map_get(pageMap, linkPageTitle);
|
||||
|
||||
char *compiledLink = NULL;
|
||||
|
||||
|
@ -499,6 +533,7 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
closedir(pagesDir);
|
||||
free(templateContent);
|
||||
map_free(pageMap);
|
||||
|
||||
// Deallocate all the pages
|
||||
|
||||
|
|
Loading…
Reference in New Issue