Vinicius Teshima 4 сар өмнө
parent
commit
5a42106aa9
2 өөрчлөгдсөн 587 нэмэгдсэн , 6 устгасан
  1. 112 1
      first.c
  2. 475 5
      src/lib.h

+ 112 - 1
first.c

@@ -1,16 +1,19 @@
 #include <stdio.h>
 #include <stdbool.h>
 
-#define STR_SIZE_LIMIT 65536
+/* #define STR_SIZE_LIMIT 65536 */
+#define STR_SIZE_LIMIT 5458264
 
 #define IMP
 #define WANT_BUILD
 #define WANT_CSTR
 #define WANT_STR
+#define WANT_MAP
 #define WANT_TOKENIZER
 #define WANT_DYN_ARR
 #define WANT_PATH
 #define WANT_ENV
+#define WANT_SLOP
 #include "./src/lib.h"
 
 #include <stdlib.h>
@@ -30,6 +33,14 @@ bool tkn_parse_pp_directive(struct tokenizer *tkn, struct token *out_tk,
 bool tkn_parse_decl(struct tokenizer *tkn, struct token *out_tk,
                     enum err *out_err);
 
+bool is_space(char c);
+bool
+is_space(char c)
+{
+    return (c == ' ') || (c == '\r') || (c == '\n')
+           || (c == '\t') || (c == '\v');
+}
+
 enum c_token_type {
     _TT = TK_LAST,
     TK_PP_DEF,
@@ -53,10 +64,110 @@ struct token_pp_def {
     struct str val;
 };
 
+struct token_var_decl {
+    enum token_type type;
+    u64 loc_start;
+    u64 loc_end;
+
+    struct str _type;
+    struct str name;
+    struct str init;
+};
+
+struct token_func_decl {
+    enum token_type type;
+    u64 loc_start;
+    u64 loc_end;
+
+    struct str _type;
+    struct str name;
+};
+
+struct ctx {
+    void *t;
+};
+
 bool skip_token(struct tokenizer *tkn, char c);
 
+# define DIE(f, e) \
+    (f); \
+    if ( (e) != ERR_OK ) {\
+        fprintf(stderr, \
+                "Error while running `" #f "`: %s\n", \
+                err_to_name[(e)]); \
+        goto exit_err; \
+    }
+
 int
 main(int argc, char *argv[])
+{
+    enum err err = ERR_OK;
+
+    u8 *file = NULL;
+    u64 file_size = 0;
+    struct str s = {0};
+    struct str ss = {0};
+    struct str_tokenizer stkn = {0};
+
+    u64 *index = NULL;
+    u64 i = 0;
+    u64 counter = 0;
+
+    void *tmp = NULL;
+
+    struct map m = {0};
+
+    m = DIE(map_create(sizeof(u64), 32, &err), err);
+
+    file = DIE(slop_file_slurp("./t8.shakespeare.txt", &file_size, &err), err);
+
+    s = DIE(str_from_cstr((char*)file, file_size, &err), err);
+
+    stkn = str_tokenize_func(s, is_space);
+
+    ss = str_tokenizer_next(&stkn);
+    while ( ss.size != ((u64) -1) ) {
+        if ( i > 10 ) {
+            break;
+        }
+
+        tmp = map_get(&m, (void*)ss.data, ss.size, &err);
+        if ( err == ERR_NOT_FOUND ) {
+            err = ERR_OK;
+            DIE(map_add(&m, (void*)ss.data, ss.size, (void*)1, &err), err);
+            continue;
+        }
+        counter = (u64) tmp;
+
+        DIE(map_set(&m, (void*)ss.data, ss.size, (void*)(counter+1), &err), err);
+
+        printf("-> `%.*s` | `%ld`\n", (int)ss.size, ss.data, counter);
+
+        ss = str_tokenizer_next(&stkn);
+        ++i;
+    }
+
+    MAP_FOR_EACH_USED(&m, index) {
+        struct map_item mi = m.data[*index];
+        printf("%ld -> Value: %ld\n", *index, (u64)mi.item);
+    }
+
+    DIE(map_destroy(&m, &err), err);
+
+    free(file);
+
+    UNUSED(argc);
+    UNUSED(argv);
+    return 0;
+exit_err:
+    if ( file != NULL ) free(file);
+    map_destroy(&m, NULL);
+    return 1;
+}
+
+int main2(int argc, char *argv[]);
+int
+main2(int argc, char *argv[])
 {
     enum err err = ERR_OK;
     struct path src_path = {0};

+ 475 - 5
src/lib.h

@@ -1,3 +1,4 @@
+/* vim: set filetype=c : */
 #ifndef LIB_H
 # define LIB_H
 
@@ -59,7 +60,9 @@ enum err {
     ERR_FAILED_WRITE,
     ERR_WROTE_WRONG_AMOUNT,
     ERR_FAILED_ALLOC,
+    ERR_FAILED_REALLOC,
     ERR_MKDIR_FAILED,
+    ERR_FAILED_HASHING,
     ERR_STR_EMPTY,
     ERR_PATH_EMPTY,
     ERR_PATH_INVALID,
@@ -82,7 +85,9 @@ const char *err_to_name[] = {
     "ERR_FAILED_WRITE",
     "ERR_WROTE_WRONG_AMOUNT",
     "ERR_FAILED_ALLOC",
+    "ERR_FAILED_REALLOC",
     "ERR_MKDIR_FAILED",
+    "ERR_FAILED_HASHING",
     "ERR_PATH_EMPTY",
     "ERR_PATH_INVALID",
     "ERR_PATH_FILE_EMPTY",
@@ -173,6 +178,7 @@ void abort(void);
         return ret_val; \
     }
 
+#define _r_ __restrict__
 
 /* ------------------------------ END LIB DEF ------------------------------ */
 
@@ -237,6 +243,7 @@ struct str_tokenizer {
     struct str str;
     u64 cur;
     char c;
+    bool (*f)(char c);
 };
 
 struct str str_from_cstr(const char *cstr, u64 cstr_size,
@@ -259,6 +266,7 @@ u64 str_lindex(struct str str, char c);
 u64 str_rindex(struct str str, char c);
 
 struct str_tokenizer str_tokenize(struct str str, char c);
+struct str_tokenizer str_tokenize_func(struct str str, bool (*f)(char c));
 struct str str_tokenizer_next(struct str_tokenizer *st);
 
 struct str str_slice(struct str str, u64 from, u64 to);
@@ -508,6 +516,406 @@ dyn_arr_destroy(struct dyn_arr *da, enum err *out_err)
 
 /* --------------------------- END DYN ARR DEF ----------------------------- */
 
+/* ---------------------------- START DA DEF ------------------------------- */
+
+# define DA_APPEND(da, val, err_var) \
+    do { \
+        if ( err_var != NULL ) { \
+            if ( *err_var != ERR_OK ) { \
+                break; \
+            } \
+        } \
+        if ( (da).size + 1 >= (da).cap ) { \
+            (da).cap *= 2; \
+            (da).data = realloc((da).data, (da).cap); \
+            if ( (da).data == NULL ) { \
+                LIB_SET_IF_NOT_NULL((err_var), ERR_FAILED_REALLOC); \
+                break; \
+            } \
+        } \
+        if ( (da).data == NULL ) { \
+            if ( (da).cap == 0 ) { \
+                (da).cap = 32; \
+                (da).size = 0; \
+            } \
+            (da).data = malloc(sizeof(*(da).data) * (da).cap); \
+            if ( (da).data == NULL ) { \
+                LIB_SET_IF_NOT_NULL((err_var), ERR_FAILED_ALLOC); \
+                break; \
+            } \
+        } \
+        (da).data[(da).size++] = (val); \
+        LIB_SET_IF_NOT_NULL((err_var), ERR_OK); \
+    } while(0);
+
+/* ----------------------------- END DA DEF -------------------------------- */
+
+/* ---------------------------- START MAP DEF ------------------------------ */
+
+# if defined(WANT_MAP) || defined(WANT_ALL)
+
+#  define MAP_FOR_EACH_USED(Map, Var) \
+    for ( Var = (Map)->used.data; \
+          Var < ((Map)->used.data + (Map)->used.size); \
+          ++Var )
+
+struct map_item {
+    u64 key[4];
+    u8 item[1];
+};
+
+struct map {
+    struct map_item *data;
+    u64 size;
+    struct {
+        u64 *data;
+        u64 size;
+        u64 cap;
+    } used;
+    u64 _cap;
+    u64 _size_bytes;
+    u64 _item_size;
+    u64 _elem_size;
+    u64 *(*hash)(void *key, u64 key_size);
+};
+
+struct map map_create(u64 elem_size, u64 cap, enum err *_r_ out_err);
+
+enum err map_inc_cap(struct map *_r_ m, enum err *_r_ out_err);
+
+enum err map_add_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
+                            enum err *_r_ out_err);
+enum err map_add(struct map *_r_ m, void *_r_ key, u64 key_size, void *_r_ elem,
+                 enum err *_r_ out_err);
+
+void *map_get(struct map *_r_ m, void *_r_ key, u64 key_size, enum err *_r_ out_err);
+
+enum err map_set_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
+                            enum err *_r_ out_err);
+enum err map_set(struct map *_r_ m, void *_r_ key, u64 key_size,
+                 void *_r_ elem, enum err *_r_ out_err);
+
+void *map_pop(struct map *_r_ m, void *_r_ key, u64 key_size, enum err *_r_ out_err);
+
+enum err map_destroy(struct map *_r_ m, enum err *_r_ out_err);
+
+u64 *map_default_hasher(void *key, u64 key_size);
+
+#  if defined(IMP) || defined(IMP_MAP)
+
+struct map
+map_create(u64 elem_size, u64 cap, enum err *out_err)
+{
+    struct map empty = {0};
+    struct map m = {0};
+
+    LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
+
+    m._cap = cap;
+    m._item_size = sizeof(struct map_item) + (elem_size-1);
+    m._size_bytes = m._item_size * m._cap;
+    m.data = malloc(m._size_bytes);
+    if ( m.data == NULL ) {
+        LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
+        return empty;
+    }
+
+    m.used.cap = 32;
+    m.used.data = malloc(m.used.cap);
+    if ( m.used.data == NULL ) {
+        free(m.data);
+        LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
+        return empty;
+    }
+
+    m.hash = map_default_hasher;
+
+    LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
+    return m;
+}
+
+enum err
+map_inc_cap(struct map *_r_ m, enum err *_r_ out_err)
+{
+    enum err err = ERR_OK;
+    enum err *perr = &err;
+
+    struct map nm = {0};
+    u64 *index = 0;
+
+    LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
+
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m      , out_err);
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
+
+    if ( out_err != NULL ) {
+        perr = out_err;
+    }
+
+    nm = map_create(m->_elem_size, (m->_cap * 2), perr);
+    if ( *perr != ERR_OK ) {
+        goto err_exit;
+    }
+
+    MAP_FOR_EACH_USED(m, index) {
+        struct map_item mi = m->data[*index];
+        map_add_hashed_key(&nm, mi.key, mi.item, perr);
+        if ( *perr != ERR_OK ) {
+            goto err_exit;
+        }
+    }
+
+    LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
+    return ERR_OK;
+err_exit:
+    map_destroy(&nm, NULL);
+    return *perr;
+}
+
+enum err
+map_add_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
+                   enum err *_r_ out_err)
+{
+    enum err err = ERR_OK;
+    enum err *perr = &err;
+
+    u64 i = 0;
+    struct map_item *it = NULL;
+    LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
+
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
+
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
+
+    if ( out_err != NULL ) {
+        perr = out_err;
+    }
+
+    i = (key[0] + key[1] + key[2] + key[3]) % m->_cap;
+
+    do {
+        if ( i >= m->_cap ) {
+            map_inc_cap(m, perr);
+            if ( *perr != ERR_OK ) {
+                return *perr;
+            }
+        }
+        it = (m->data + (m->_item_size * (i++)));
+    } while (it->key[0] != 0 || it->key[1] != 0
+             || it->key[2] != 0 || it->key[3] != 0);
+
+    memcpy(it->key, key, sizeof(u64) * 4);
+    memcpy(it->item, elem, m->_elem_size);
+
+    DA_APPEND(m->used, i-1, perr);
+    if ( *perr != ERR_OK ) {
+        memset(it->key, 0, sizeof(u64) * 4);
+        memset(it->item, 0, m->_elem_size);
+        return *perr;
+    }
+
+    *perr = ERR_OK;
+    return ERR_OK;
+}
+
+enum err
+map_add(struct map *m, void *key, u64 key_size, void *elem, enum err *out_err)
+{
+    enum err err = ERR_OK;
+    enum err *perr = &err;
+
+    u64 *hash = NULL;
+
+    LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
+
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
+
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
+
+    if ( out_err != NULL ) {
+        perr = out_err;
+    }
+
+    hash = m->hash(key, key_size);
+    if ( hash == NULL ) {
+        *perr = ERR_FAILED_HASHING;
+        return *perr;
+    }
+
+    map_add_hashed_key(m, hash, elem, perr);
+    if ( *perr != ERR_OK ) {
+        free(hash);
+        return *perr;
+    }
+
+    free(hash);
+
+    *perr = ERR_OK;
+    return ERR_OK;
+}
+
+void *
+map_get(struct map *m, void *key, u64 key_size, enum err *out_err)
+{
+    u64 i = 0;
+    struct map_item *it = NULL;
+    u64 *hash = NULL;
+
+    LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, NULL);
+
+    LIB_ARG_MUST_NOT_BE_NULL(m      , out_err, NULL);
+    LIB_ARG_MUST_NOT_BE_NULL(m->data, out_err, NULL);
+
+    LIB_ARG_MUST_NOT_BE_NULL(key , out_err, NULL);
+
+    hash = m->hash(key, key_size);
+    i = (hash[0] + hash[1] + hash[2] + hash[3]) % m->_cap;
+
+    do {
+        if ( i >= m->_cap ) {
+            LIB_SET_IF_NOT_NULL(out_err, ERR_NOT_FOUND);
+            free(hash);
+            return NULL;
+        }
+        it = (m->data + (m->_item_size * (i++)));
+    } while (it->key[0] != hash[0] || it->key[1] != hash[1]
+             || it->key[2] != hash[2] || it->key[3] != hash[3]);
+
+    free(hash);
+
+    LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
+    return it->item;
+}
+
+enum err
+map_set_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
+                   enum err *_r_ out_err)
+{
+    enum err err = ERR_OK;
+    enum err *perr = &err;
+
+    u64 i = 0;
+    struct map_item *it = NULL;
+    LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
+
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
+
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
+
+    if ( out_err != NULL ) {
+        perr = out_err;
+    }
+
+    i = (key[0] + key[1] + key[2] + key[3]) % m->_cap;
+
+    do {
+        if ( i >= m->_cap ) {
+            *perr = ERR_NOT_FOUND;
+            return *perr;
+        }
+        it = (m->data + (m->_item_size * (i++)));
+    } while (it->key[0] != key[0] || it->key[1] != key[1]
+             || it->key[2] != key[2] || it->key[3] != key[3]);
+
+    memcpy(it->item, elem, m->_elem_size);
+
+    *perr = ERR_OK;
+    return ERR_OK;
+}
+
+enum err
+map_set(struct map *_r_ m, void *_r_ key, u64 key_size, void *_r_ elem,
+        enum err *_r_ out_err)
+{
+    enum err err = ERR_OK;
+    enum err *perr = &err;
+
+    u64 *hash = NULL;
+
+    LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
+
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m->data, out_err);
+
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(key, out_err);
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(elem, out_err);
+
+    if ( out_err != NULL ) {
+        perr = out_err;
+    }
+
+    hash = m->hash(key, key_size);
+    if ( hash == NULL ) {
+        *perr = ERR_FAILED_HASHING;
+        return *perr;
+    }
+
+    map_set_hashed_key(m, hash, elem, perr);
+    if ( *perr != ERR_OK ) {
+        free(hash);
+        return *perr;
+    }
+
+    free(hash);
+
+    *perr = ERR_OK;
+    return ERR_OK;
+}
+
+void *map_pop(struct map *m, void *key, u64 key_size, enum err *out_err);
+
+enum err
+map_destroy(struct map *m, enum err *out_err)
+{
+    LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
+
+    LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(m, out_err);
+
+    if ( m->data      != NULL ) free(m->data);
+    if ( m->used.data != NULL ) free(m->used.data);
+
+    LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
+    return ERR_OK;
+}
+
+u64 *
+map_default_hasher(void *key, u64 key_size)
+{
+    u64 i = 0;
+    u64 *k = NULL;
+
+    k = malloc(sizeof(u64) * 4);
+    if ( k == NULL ) {
+        return NULL;
+    }
+
+    k[0] = 0;
+    k[1] = 0;
+    k[2] = 0;
+    k[3] = 0;
+
+    for ( i = 0; i < key_size; ++i ) {
+        k[0] += ((u8*)key)[i] * 31;
+        k[1] += ((u8*)key)[i] * 127;
+        k[2] += ((u8*)key)[i] * 233;
+        k[3] += ((u8*)key)[i] * 353;
+    }
+
+    return k;
+}
+
+#  endif /* defined(IMP) || defined(IMP_MAP) */
+
+# endif /* defined(WANT_MAP) || defined(WANT_ALL) */
+
+/* ----------------------------- END MAP DEF ------------------------------- */
+
 /* ---------------------------- START ENV DEF ------------------------------ */
 
 # if defined(WANT_ENV) || defined(WANT_ALL)
@@ -1489,6 +1897,52 @@ gui_close_window(struct gui *gui, enum err *out_err)
 
 /* ----------------------------- END GUI DEF ------------------------------- */
 
+/* ---------------------------- START SLOP DEF ----------------------------- */
+
+# if defined(WANT_SLOP) || defined(WANT_ALL)
+
+u8 *slop_file_slurp(const char *_r_ path, u64 *_r_ out_size,
+                    enum err *_r_ out_err);
+enum err slop_file_save(const char *_r_ path, u8 *_r_ data, u64 size,
+                        enum err *_r_ out_err);
+
+#  if defined(IMP) || defined(IMP_SLOP)
+
+u8 *
+slop_file_slurp(const char *_r_ path, u64 *_r_ out_size, enum err *_r_ out_err)
+{
+    enum err err = ERR_OK;
+    enum err *perr = &err;
+
+    struct path p = {0};
+    struct file f = {0};
+
+    LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, NULL);
+
+    LIB_ARG_MUST_NOT_BE_NULL(path, out_err, NULL);
+
+    if ( out_err != NULL ) {
+        perr = out_err;
+    }
+
+    p = path_from_cstr_ns(path, perr);
+    f = path_file_read_all(&p, perr);
+    if ( out_size != NULL ) {
+        *out_size = f.size;
+    }
+
+    return f.data;
+}
+
+enum err slop_file_save(const char *_r_ path, u8 *_r_ data, u64 size,
+                        enum err *_r_ out_err);
+
+#  endif /* defined(IMP) || defined(IMP_SLOP) */
+
+# endif /* defined(WANT_SLOP) || defined(WANT_ALL) */
+
+/* ----------------------------- END SLOP DEF ------------------------------ */
+
 # if defined(IMP) || defined(IMP_STR)
 
 #  define _SET_IF_NOT_NULL(var, err) \
@@ -1742,7 +2196,6 @@ str_from_i64_temp(i64 num)
     return ret;
 }
 
-
 struct str
 str_dup(struct str str)
 {
@@ -1856,6 +2309,15 @@ str_tokenize(struct str str, char c)
     return st;
 }
 
+struct str_tokenizer
+str_tokenize_func(struct str str, bool (*f)(char c))
+{
+    struct str_tokenizer st = {0};
+    st.str = str;
+    st.f = f;
+    return st;
+}
+
 struct str
 str_tokenizer_next(struct str_tokenizer *st)
 {
@@ -1877,10 +2339,18 @@ str_tokenizer_next(struct str_tokenizer *st)
     str.data += st->cur;
     str.size = 0;
 
-    while ( str.data[str.size] != st->c
-        && st->cur < st->str.size ) {
-        ++str.size;
-        ++st->cur;
+    if ( st->f != NULL ) {
+        while ( (! st->f(str.data[str.size]))
+                && st->cur < st->str.size ) {
+            ++str.size;
+            ++st->cur;
+        }
+    } else {
+        while ( str.data[str.size] != st->c
+                && st->cur < st->str.size ) {
+            ++str.size;
+            ++st->cur;
+        }
     }
     ++st->cur;