hashmapp.
This commit is contained in:
commit
e34fc0ca7f
5 changed files with 161 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
hashmap
|
||||||
7
Makefile
Normal file
7
Makefile
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
.PHONY: hashmap
|
||||||
|
|
||||||
|
hashmap: main.c
|
||||||
|
$(CC) -o hashmap -g main.c hashmap.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf hashmap
|
||||||
61
hashmap.c
Normal file
61
hashmap.c
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include "hashmap.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void init_map(HashMap *map) {
|
||||||
|
memset(map, 0, sizeof(HashMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
long long hash(const char *s) {
|
||||||
|
const int p = 100;
|
||||||
|
const int m = 1e9 + 9;
|
||||||
|
long p_pow = 1;
|
||||||
|
long value = 0;
|
||||||
|
const unsigned long len = strlen(s);
|
||||||
|
for (unsigned long i = 0; i < len; i++) {
|
||||||
|
unsigned char c = s[i];
|
||||||
|
value = (value + (c - 'a' + 1) * p_pow) % m;
|
||||||
|
p_pow = (p_pow * p) % m;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *get(HashMap *map, char *key) {
|
||||||
|
Bucket *bucket = &map->buckets[hash(key) % HASHMAP_BUCKETS];
|
||||||
|
Entry *entry = NULL;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < bucket->n_entries; i++) {
|
||||||
|
if (!strcmp(bucket->entries[i].key, key))
|
||||||
|
return bucket->entries[i].data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry *set(HashMap *map, char *key, void *data, size_t data_size) {
|
||||||
|
Bucket *bucket = &map->buckets[hash(key) % HASHMAP_BUCKETS];
|
||||||
|
Entry *entry = NULL;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for (; i < bucket->n_entries; i++) {
|
||||||
|
entry = &bucket->entries[i];
|
||||||
|
if (!strcmp(entry->key, key)) {
|
||||||
|
// entry exists; replace data
|
||||||
|
entry->data = data;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// entry doesn't exist; insert data
|
||||||
|
if (i >= BUCKET_ENTRIES) {
|
||||||
|
fprintf(stderr, "set \"%s\": bucket is full\n", key);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = &bucket->entries[i];
|
||||||
|
entry->key = strdup(key);
|
||||||
|
entry->data = data;
|
||||||
|
entry->data_size = data_size;
|
||||||
|
bucket->n_entries++;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
28
hashmap.h
Normal file
28
hashmap.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef _HASHMAP_H
|
||||||
|
#define _HASHMAP_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define BUCKET_ENTRIES 20
|
||||||
|
#define HASHMAP_BUCKETS 2048
|
||||||
|
|
||||||
|
typedef struct Entry {
|
||||||
|
char *key;
|
||||||
|
void *data;
|
||||||
|
size_t data_size;
|
||||||
|
} Entry;
|
||||||
|
|
||||||
|
typedef struct Bucket {
|
||||||
|
size_t n_entries;
|
||||||
|
Entry entries[BUCKET_ENTRIES];
|
||||||
|
} Bucket;
|
||||||
|
|
||||||
|
typedef struct HashMap {
|
||||||
|
Bucket buckets[HASHMAP_BUCKETS];
|
||||||
|
} HashMap;
|
||||||
|
|
||||||
|
void init_map(HashMap *map);
|
||||||
|
void *get(HashMap *map, char *key);
|
||||||
|
Entry *set(HashMap *map, char *key, void *data, size_t data_size);
|
||||||
|
|
||||||
|
#endif // _HASHMAP_H
|
||||||
64
main.c
Normal file
64
main.c
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
#include "hashmap.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define INPUT_BUF_SIZE 1024
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
printf("hashmapp. the map to app all hashes. wait-\n"
|
||||||
|
"\":q\" to exit\n\n");
|
||||||
|
|
||||||
|
HashMap map;
|
||||||
|
init_map(&map);
|
||||||
|
|
||||||
|
char running = 1;
|
||||||
|
while (running) {
|
||||||
|
printf("> ");
|
||||||
|
|
||||||
|
char buf[INPUT_BUF_SIZE];
|
||||||
|
if (fgets(buf, INPUT_BUF_SIZE, stdin) == NULL) {
|
||||||
|
fprintf(stderr, "failed to read stdin: %u\n", errno);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
size_t buf_len = strnlen(buf, INPUT_BUF_SIZE);
|
||||||
|
buf[buf_len - 1] = 0;
|
||||||
|
|
||||||
|
if (!strcmp(buf, ":q"))
|
||||||
|
break;
|
||||||
|
|
||||||
|
char *eq = strchr(buf, '=');
|
||||||
|
if (eq == NULL) {
|
||||||
|
void *data = get(&map, buf);
|
||||||
|
if (data == NULL)
|
||||||
|
printf("\n");
|
||||||
|
else
|
||||||
|
printf("%s\n", (char*)data);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t key_len = eq - buf + 1;
|
||||||
|
char key[key_len];
|
||||||
|
strncpy(key, buf, key_len);
|
||||||
|
key[key_len - 1] = 0;
|
||||||
|
|
||||||
|
size_t value_len = strlen(buf + key_len);
|
||||||
|
char *value = malloc(sizeof(char) * value_len);
|
||||||
|
strncpy(value, buf + key_len, value_len);
|
||||||
|
value[value_len] = 0;
|
||||||
|
|
||||||
|
set(&map, key, value, value_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t bucket_i = 0; bucket_i < HASHMAP_BUCKETS; bucket_i++) {
|
||||||
|
Bucket *bucket = &map.buckets[bucket_i];
|
||||||
|
for (size_t i = 0; i < bucket->n_entries; i++) {
|
||||||
|
free(bucket->entries[i].key);
|
||||||
|
free(bucket->entries[i].data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue