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 ***/
|
/*** Hash map implementation ***/
|
||||||
|
struct PageMap {
|
||||||
|
struct Page **pages;
|
||||||
|
int capacity;
|
||||||
|
int size;
|
||||||
|
};
|
||||||
|
|
||||||
int helper_hash_polynomial(
|
int helper_hash_polynomial(
|
||||||
char string[],
|
char string[],
|
||||||
int i,
|
int i,
|
||||||
|
@ -65,33 +71,69 @@ int helper_hash_polynomial(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int hash_polynomial(int mapSize, char key[]) {
|
int hash_polynomial(int capacity, char key[]) {
|
||||||
return helper_hash_polynomial(key, 0, strlen(key), mapSize, 0);
|
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;
|
int i = 0;
|
||||||
for (; str[i] != '\0'; i++) {
|
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) {
|
struct PageMap * map(int capacity) {
|
||||||
char lowercased[80];
|
struct PageMap *map = malloc(sizeof(struct PageMap));
|
||||||
to_lower_case(lowercased, title);
|
map->pages = calloc(capacity, sizeof(struct Page *));
|
||||||
|
map->capacity = capacity;
|
||||||
int index = hash_polynomial(mapSize, lowercased);
|
map->size = 0;
|
||||||
map[index] = page;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Page * map_get(struct Page **map, int mapSize, char title[]) {
|
void map_free(struct PageMap *map) {
|
||||||
char lowercased[80];
|
free(map->pages);
|
||||||
to_lower_case(lowercased, title);
|
free(map);
|
||||||
|
}
|
||||||
|
|
||||||
int index = hash_polynomial(mapSize, lowercased);
|
void map_put(struct PageMap *map, char title[], struct Page *page) {
|
||||||
struct Page *page = map[index];
|
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;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +218,6 @@ char * substitute_string(char dest[], char sub[], char *start, char *end) {
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
char pagesLocation[256] = "./pages";
|
char pagesLocation[256] = "./pages";
|
||||||
int mapSize = 1000;
|
|
||||||
int initialInboundCapacity = 2;
|
int initialInboundCapacity = 2;
|
||||||
char templateFileName[256] = "./template.html";
|
char templateFileName[256] = "./template.html";
|
||||||
char outputDirectoryName[256] = "./build";
|
char outputDirectoryName[256] = "./build";
|
||||||
|
@ -189,11 +230,6 @@ int main(int argc, char *argv[]) {
|
||||||
i++;
|
i++;
|
||||||
strcpy(pagesLocation, 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) {
|
} else if (strcmp(argv[i], "--template") == 0) {
|
||||||
if (i + 1 < argc) {
|
if (i + 1 < argc) {
|
||||||
i++;
|
i++;
|
||||||
|
@ -230,8 +266,7 @@ int main(int argc, char *argv[]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Page ** pageMap = malloc(mapSize * sizeof(struct Page *));
|
struct PageMap *pageMap = map(100);
|
||||||
memset(pageMap, 0, mapSize * sizeof(struct Page *));
|
|
||||||
|
|
||||||
// Contains some information about the current file picked from pagesDir
|
// Contains some information about the current file picked from pagesDir
|
||||||
struct dirent *fileEntry = readdir(pagesDir);
|
struct dirent *fileEntry = readdir(pagesDir);
|
||||||
|
@ -310,7 +345,7 @@ int main(int argc, char *argv[]) {
|
||||||
currentPage->title[min(titleLength, 80)] = 0;
|
currentPage->title[min(titleLength, 80)] = 0;
|
||||||
|
|
||||||
// Insert it into the hash map for lookup later
|
// 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
|
// Get ready to process the next page
|
||||||
fileEntry = readdir(pagesDir);
|
fileEntry = readdir(pagesDir);
|
||||||
|
@ -360,14 +395,13 @@ int main(int argc, char *argv[]) {
|
||||||
strncpy(linkTitle, nextLinkStart + 2, (nextVerticalBar - 1) - (nextLinkStart + 1));
|
strncpy(linkTitle, nextLinkStart + 2, (nextVerticalBar - 1) - (nextLinkStart + 1));
|
||||||
linkPageTitle = calloc((nextLinkEnd - 2) - nextVerticalBar, sizeof(char));
|
linkPageTitle = calloc((nextLinkEnd - 2) - nextVerticalBar, sizeof(char));
|
||||||
strncpy(linkPageTitle, nextVerticalBar + 1, (nextLinkEnd - 1) - nextVerticalBar);
|
strncpy(linkPageTitle, nextVerticalBar + 1, (nextLinkEnd - 1) - nextVerticalBar);
|
||||||
puts(linkPageTitle);
|
|
||||||
} else {
|
} else {
|
||||||
// The link is of the form [[page title]]
|
// The link is of the form [[page title]]
|
||||||
linkPageTitle = linkTitle;
|
linkPageTitle = linkTitle;
|
||||||
strncpy(linkTitle, nextLinkStart + 2, (linkLength - 2)*sizeof(char));
|
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;
|
char *compiledLink = NULL;
|
||||||
|
|
||||||
|
@ -499,6 +533,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
closedir(pagesDir);
|
closedir(pagesDir);
|
||||||
free(templateContent);
|
free(templateContent);
|
||||||
|
map_free(pageMap);
|
||||||
|
|
||||||
// Deallocate all the pages
|
// Deallocate all the pages
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue