diff options
| author | kartofen <mladenovnasko0@gmail.com> | 2024-01-03 00:08:27 +0200 | 
|---|---|---|
| committer | kartofen <mladenovnasko0@gmail.com> | 2024-01-03 00:08:27 +0200 | 
| commit | fad8df848092d7f35e95c3b70b5917593df84952 (patch) | |
| tree | 7300189cfd953b2571237e8e2a0fd556e1921633 | |
| parent | c837b2bb4ea71cedb434260b11c9f356e8b34e2d (diff) | |
| -rw-r--r-- | src/eval.h | 27 | ||||
| -rw-r--r-- | src/hashtbl.c | 135 | ||||
| -rw-r--r-- | src/hashtbl.h | 23 | 
3 files changed, 182 insertions, 3 deletions
| @@ -2,17 +2,38 @@  #define EVAL_H  #include "parser.h" +#include "hashtbl.h"  typedef struct eval *eval_t; +// struct symdata { +//     enum symbol_type { +//         SYMBOL_VALUE, +//         SYMBOL_FUNC, +//         SYMBOL_FUNC_BUILTIN +//     } type; +// +//     union { +//         value_t value; +//         ast_t   func; +//         builtin_func_t builtin; +//     }; +// }; +// +// struct symtbl { +//     hashtbl_t table; +//     struct symtbl *parent; +// }; +  struct eval { -    // symtbl_t root; -    // symtbl_t *cur; +    // struct symtbl root; +    // struct symtbl *cur; +    // ...  };  // TODO: add options for the evaluation  eval_t eval_create();  void eval_destroy(eval_t eval); -int eval_ast(eval_t eval, parser_t ast); +int eval_ast(eval_t eval, ast_t *ast);  #endif diff --git a/src/hashtbl.c b/src/hashtbl.c new file mode 100644 index 0000000..02f2118 --- /dev/null +++ b/src/hashtbl.c @@ -0,0 +1,135 @@ +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "common.h" +#include "hashtbl.h" + +static struct hash_item *hash_item_alloc(); +static void hash_item_reset_rec(struct hash_item *item, bool should_free); + +static struct hash_item *hash_item_find(struct hash_item *item, char *key, bool create); + +static size_t hash(char *str) +{ +    size_t hash = 5381; +    char c; +    while ((c = *str++) != 0) +        hash = ((hash << 5) + hash) + (size_t)c; + +    // return hash; +    return 0; +} + +// ---------- Exported Functions ---------- // + +hashtbl_t hashtbl_create(size_t cap) +{ +    hashtbl_t hashtbl = xmalloc(sizeof(*hashtbl)); + +    hashtbl->cap = cap; +    hashtbl->items = xcalloc(hashtbl->cap, sizeof(*hashtbl->items)); + +    for(size_t i = 0; i < hashtbl->cap; i++) { +        hashtbl->items[i] = hash_item_alloc(); +    } +     +    return hashtbl; +} +       +void hashtbl_destroy(hashtbl_t hashtbl) +{ +    if(hashtbl == NULL) return; +     +    for(int i = 0; i < hashtbl->cap; i++) { +        hash_item_reset_rec(hashtbl->items[i], true); +    } +     +    free(hashtbl->items); +    free(hashtbl); +} + +void hashtbl_reset(hashtbl_t hashtbl) +{ +    for(int i = 0; i < hashtbl->cap; i++) { +        hash_item_reset_rec(hashtbl->items[i]->next, true); +        hash_item_reset_rec(hashtbl->items[i]->next, false); +    } +} + +#define HEAD_ITEM (hashtbl->items[hash(key) % hashtbl->cap]) + +int hashtbl_insert(hashtbl_t hashtbl, char *key, void *data, size_t data_sz) +{ +    struct hash_item *item = hash_item_find(HEAD_ITEM, key, true); + +    if(item->data) free(item->data); +     +    item->data = xmalloc(data_sz); +    memcpy(item->data, data, data_sz); + +    return 0; +} + +int hashtbl_query(hashtbl_t hashtbl, char *key, void **dest) +{ +    struct hash_item *item = hash_item_find(HEAD_ITEM, key, false); +     +    if(item == NULL) return 1; +    if(dest != NULL) *dest = item->data; +    return 0; +} + +// ---------- Helper Functions ---------- // + +static struct hash_item *hash_item_alloc() +{ +    struct hash_item *item = xmalloc(sizeof(struct hash_item)); +     +    item->next = NULL; +    item->key = NULL; +    item->data = NULL; +     +    return item; +} + +static void hash_item_reset_rec(struct hash_item *item, bool should_free) +{ +    if(item == NULL) return; +     +    if(item->key) free(item->key); +    if(item->data) free(item->data); +     +    hash_item_reset_rec(item->next, should_free); +     +    if(should_free) free(item); +} + +static struct hash_item *hash_item_find(struct hash_item *item, char *key, bool create) +{ +    if(item-> key == NULL) { +        if(!create) return NULL; +         +        item->key = xmalloc(strlen(key) + 1); +        strcpy(item->key, key); +        return item; +    }  +         +    if(strcmp(key, item->key) == 0) { +        return item; +    } + +    if(item->next == NULL) { +        if(!create) return NULL; +         +        struct hash_item *next = hash_item_alloc(); +         +        next->key = xmalloc(strlen(key) + 1); +        strcpy(next->key, key); +         +        item->next = next; +        return item->next; +    } +     +    return hash_item_find(item->next, key, create); +} diff --git a/src/hashtbl.h b/src/hashtbl.h new file mode 100644 index 0000000..a6cfa10 --- /dev/null +++ b/src/hashtbl.h @@ -0,0 +1,23 @@ +#ifndef HASHTBL_H +#define HASHTBL_H + +typedef struct hash_table *hashtbl_t; + +struct hash_table {     +    struct hash_item { +        struct hash_item *next; +        char *key; +        void *data; +    } **items; +     +    size_t cap; +}; + +hashtbl_t hashtbl_create(size_t cap); +void hashtbl_destroy(hashtbl_t hashtbl); +void hashtbl_reset(hashtbl_t hashtbl); + +int hashtbl_insert(hashtbl_t hashtbl, char *key, void *data, size_t data_sz); +int hashtbl_query(hashtbl_t hashtbl, char *key, void **dest); + +#endif | 
