db read and write

This commit is contained in:
ari melody 2026-03-13 04:22:02 +00:00
parent e34fc0ca7f
commit c774e08eb1
Signed by: ari
GPG key ID: 60B5F0386E3DDB7E
4 changed files with 146 additions and 18 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
hashmap hashmap
*.db

View file

@ -20,7 +20,7 @@ long long hash(const char *s) {
return value; return value;
} }
void *get(HashMap *map, char *key) { void *map_get(HashMap *map, char *key) {
Bucket *bucket = &map->buckets[hash(key) % HASHMAP_BUCKETS]; Bucket *bucket = &map->buckets[hash(key) % HASHMAP_BUCKETS];
Entry *entry = NULL; Entry *entry = NULL;
@ -32,7 +32,7 @@ void *get(HashMap *map, char *key) {
return NULL; return NULL;
} }
Entry *set(HashMap *map, char *key, void *data, size_t data_size) { Entry *map_set(HashMap *map, char *key, void *data, size_t data_size) {
Bucket *bucket = &map->buckets[hash(key) % HASHMAP_BUCKETS]; Bucket *bucket = &map->buckets[hash(key) % HASHMAP_BUCKETS];
Entry *entry = NULL; Entry *entry = NULL;

View file

@ -22,7 +22,7 @@ typedef struct HashMap {
} HashMap; } HashMap;
void init_map(HashMap *map); void init_map(HashMap *map);
void *get(HashMap *map, char *key); void *map_get(HashMap *map, char *key);
Entry *set(HashMap *map, char *key, void *data, size_t data_size); Entry *map_set(HashMap *map, char *key, void *data, size_t data_size);
#endif // _HASHMAP_H #endif // _HASHMAP_H

155
main.c
View file

@ -1,23 +1,140 @@
#include "hashmap.h" #include "hashmap.h"
#include <errno.h> #include <errno.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#define INPUT_BUF_SIZE 1024 #define INPUT_BUF_SIZE 1024
const char HASHMAPP_MAGIC[] = "HSMP";
typedef struct AppState {
char running;
HashMap map;
} AppState;
void open_file(HashMap *map, const char *filename) {
FILE *file = fopen(filename, "r");
if (file == NULL) {
fprintf(stderr, "failed to open file: %s\n", strerror(errno));
return;
}
fseek(file, 0, SEEK_END);
long filesize = ftell(file);
fseek(file, 0, SEEK_SET);
if (filesize < 4) {
fprintf(stderr, "invalid file: %s\n", filename);
return;
}
int magic_len = strlen(HASHMAPP_MAGIC);
char magic[magic_len + 1];
unsigned long cur = ftell(file);
fread(magic, magic_len, 1, file);
magic[magic_len] = 0;
if (strcmp(HASHMAPP_MAGIC, magic) != 0) {
fprintf(stderr, "invalid file: %s\n", filename);
return;
}
while (cur < filesize) {
uint16_t key_len = 0;
fread(&key_len, sizeof(uint16_t), 1, file);
char key[key_len + 1];
fread(key, key_len, 1, file);
key[key_len] = 0;
uint16_t data_size = 0;
fread(&data_size, sizeof(uint16_t), 1, file);
char *data = malloc(data_size);
fread(data, data_size, 1, file);
data[data_size] = 0;
map_set(map, key, data, data_size);
cur = ftell(file);
}
if (fclose(file) != 0) {
fprintf(stderr, "failed to close file: %s\n", strerror(errno));
return;
}
printf("opened db: %s\n", filename);
}
void write_file(HashMap *map, const char *filename) {
FILE *file = fopen(filename, "w+");
if (file == NULL) {
fprintf(stderr, "failed to open file: %s\n", strerror(errno));
return;
}
int fd = fileno(file);
if (fd == -1) {
fprintf(stderr, "failed to get descriptor: %s\n", strerror(errno));
fclose(file);
return;
}
unsigned long offset = 0;
offset += fwrite(HASHMAPP_MAGIC, strlen(HASHMAPP_MAGIC), 1, file);
for (uint16_t bucket_i = 0; bucket_i < HASHMAP_BUCKETS; bucket_i++) {
Bucket *bucket = &map->buckets[bucket_i];
for (uint16_t i = 0; i < bucket->n_entries; i++) {
Entry *entry = &bucket->entries[i];
uint16_t key_len = strlen(entry->key);
uint16_t data_len = strlen(entry->data);
offset += fwrite(&key_len, sizeof(uint16_t), 1, file);
offset += fwrite(entry->key, strlen(entry->key), 1, file);
offset += fwrite(&data_len, sizeof(uint16_t), 1, file);
offset += fwrite(entry->data, strlen(entry->data), 1, file);
}
}
if (ftruncate(fd, offset) != 0) {
fprintf(stderr, "failed to truncate file: %s\n", strerror(errno));
fclose(file);
return;
}
if (fclose(file) != 0) {
fprintf(stderr, "failed to close file: %s\n", strerror(errno));
return;
}
printf("written db to \"%s\" successfully.\n", filename);
}
void handle_command(AppState *app, char *buf, size_t buf_len) {
if (!strcmp(buf, "q"))
app->running = 0;
else if (strcmp(buf, "w ") > 0)
write_file(&app->map, buf + 2);
else if (strcmp(buf, "o ") > 0)
open_file(&app->map, buf + 2);
else
printf("?\n");
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
printf("hashmapp. the map to app all hashes. wait-\n" printf("hashmapp. the map to app all hashes. wait-\n"
"\":q\" to exit\n\n"); "\":q\" to exit\n"
"\":w <file>\" to save\n"
"\":o <file>\" to load\n\n");
HashMap map; AppState app = { 0 };
init_map(&map); init_map(&app.map);
char buf[INPUT_BUF_SIZE];
app.running = 1;
while (app.running) {
memset(buf, 0, INPUT_BUF_SIZE);
char running = 1;
while (running) {
printf("> "); printf("> ");
char buf[INPUT_BUF_SIZE];
if (fgets(buf, INPUT_BUF_SIZE, stdin) == NULL) { if (fgets(buf, INPUT_BUF_SIZE, stdin) == NULL) {
fprintf(stderr, "failed to read stdin: %u\n", errno); fprintf(stderr, "failed to read stdin: %u\n", errno);
return EXIT_FAILURE; return EXIT_FAILURE;
@ -25,12 +142,22 @@ int main(int argc, char *argv[]) {
size_t buf_len = strnlen(buf, INPUT_BUF_SIZE); size_t buf_len = strnlen(buf, INPUT_BUF_SIZE);
buf[buf_len - 1] = 0; buf[buf_len - 1] = 0;
if (!strcmp(buf, ":q")) if (buf_len == 0)
break; continue;
if (buf[0] == ':') {
if (buf_len < 2) {
printf("?\n");
continue;
}
handle_command(&app, buf + 1, buf_len - 1);
continue;
}
char *eq = strchr(buf, '='); char *eq = strchr(buf, '=');
if (eq == NULL) { if (eq == NULL) {
void *data = get(&map, buf); void *data = map_get(&app.map, buf);
if (data == NULL) if (data == NULL)
printf("\n"); printf("\n");
else else
@ -39,21 +166,21 @@ int main(int argc, char *argv[]) {
continue; continue;
} }
size_t key_len = eq - buf + 1; uint16_t key_len = eq - buf + 1;
char key[key_len]; char key[key_len];
strncpy(key, buf, key_len); strncpy(key, buf, key_len);
key[key_len - 1] = 0; key[key_len - 1] = 0;
size_t value_len = strlen(buf + key_len); uint16_t value_len = strlen(buf + key_len);
char *value = malloc(sizeof(char) * value_len); char *value = malloc(sizeof(char) * value_len);
strncpy(value, buf + key_len, value_len); strncpy(value, buf + key_len, value_len);
value[value_len] = 0; value[value_len] = 0;
set(&map, key, value, value_len); map_set(&app.map, key, value, value_len);
} }
for (size_t bucket_i = 0; bucket_i < HASHMAP_BUCKETS; bucket_i++) { for (size_t bucket_i = 0; bucket_i < HASHMAP_BUCKETS; bucket_i++) {
Bucket *bucket = &map.buckets[bucket_i]; Bucket *bucket = &app.map.buckets[bucket_i];
for (size_t i = 0; i < bucket->n_entries; i++) { for (size_t i = 0; i < bucket->n_entries; i++) {
free(bucket->entries[i].key); free(bucket->entries[i].key);
free(bucket->entries[i].data); free(bucket->entries[i].data);