Vinicius Teshima 3 ヶ月 前
コミット
22205989d9
2 ファイル変更218 行追加35 行削除
  1. 38 10
      first.c
  2. 180 25
      src/lib.h

+ 38 - 10
first.c

@@ -98,6 +98,11 @@ bool skip_token(struct tokenizer *tkn, char c);
         goto exit_err; \
     }
 
+# define PPP(f) \
+    printf("PRE: `" #f "`\n"); \
+    f; \
+    printf("POST: `" #f "`\n");
+
 int
 main(int argc, char *argv[])
 {
@@ -114,10 +119,11 @@ main(int argc, char *argv[])
     u64 counter = 0;
 
     void *tmp = NULL;
+    struct key_bytes *kb = NULL;
 
     struct map m = {0};
 
-    m = DIE(map_create(sizeof(u64), 32, &err), err);
+    m = DIE(map_create(sizeof(u64), 64, &err), err);
 
     file = DIE(slop_file_slurp("./t8.shakespeare.txt", &file_size, &err), err);
 
@@ -126,31 +132,53 @@ main(int argc, char *argv[])
     stkn = str_tokenize_func(s, is_space);
 
     ss = str_tokenizer_next(&stkn);
-    while ( ss.size != ((u64) -1) ) {
+    for ( ; ss.size != ((u64) -1); (ss = str_tokenizer_next(&stkn), ++i)) {
+        /*
         if ( i > 10 ) {
             break;
         }
+        */
 
+        /* printf("i -> %ld\n", i); */
         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);
+            counter = 1;
+            /* printf("-> `%.*s` | `%ld`\n", (int)ss.size, ss.data, counter); */
+            DIE(map_add(&m, (void*)ss.data, ss.size, &counter, &err), err);
             continue;
         }
-        counter = (u64) tmp;
+        counter = *(u64*) tmp;
+
+        ++counter;
+        DIE(map_set(&m, (void*)ss.data, ss.size, &counter, &err), err);
+
+        /* printf("-> `%.*s` | `%ld`\n", (int)ss.size, ss.data, counter); */
+    }
 
-        DIE(map_set(&m, (void*)ss.data, ss.size, (void*)(counter+1), &err), err);
+    i = 0;
+    MAP_FOR_EACH(&m, index, kb) {
+        struct map_item *mi = MAP_GET_INDEX(&m, *index);
 
-        printf("-> `%.*s` | `%ld`\n", (int)ss.size, ss.data, counter);
+        if ( i > 10 ) break;
+
+        printf("%.*s -> %ld\n", (int) kb->size, kb->key , *(u64*)mi->item);
 
-        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);
+    /*
+    MAP_FOR_EACH_INDEXS(&m, index) {
+        struct map_item *mi = MAP_GET_INDEX(&m, *index);
+        printf("%ld -> Value: %ld\n", *index, *(u64*)mi->item);
+    }
+
+    kb = m.keys.data;
+    while ( kb->size > 0 ) {
+        printf("-->> %.*s\n", (int) kb->size, kb->key);
+        kb = CAST(struct key_bytes *, CAST(u8*, kb->key) + kb->size);
     }
+    */
 
     DIE(map_destroy(&m, &err), err);
 

+ 180 - 25
src/lib.h

@@ -178,7 +178,11 @@ void abort(void);
         return ret_val; \
     }
 
-#define _r_ __restrict__
+# define _r_ __restrict__
+
+# define SIZEOF_MEMBER(Struct, Member) sizeof(((Struct *)0)->Member)
+
+# define CAST(Type, Var) ((Type) (Var))
 
 /* ------------------------------ END LIB DEF ------------------------------ */
 
@@ -546,7 +550,41 @@ dyn_arr_destroy(struct dyn_arr *da, enum err *out_err)
         } \
         (da).data[(da).size++] = (val); \
         LIB_SET_IF_NOT_NULL((err_var), ERR_OK); \
-    } while(0);
+    } while(0)
+
+# define DAV_APPEND(Da, Val, ValSize, ErrVar) \
+    do { \
+        if ( ErrVar != NULL ) { \
+            if ( *ErrVar != ERR_OK ) { \
+                break; \
+            } \
+        } \
+        /* printf("ValSize -> %5ld\tused_bytes -> %5ld\tcap_bytes -> %5ld\n", (ValSize), (Da).used_bytes, (Da).cap_bytes); */ \
+        if ( (Da).used_bytes + (ValSize) >= (Da).cap_bytes ) { \
+            (Da).cap_bytes *= 2; \
+            (Da).data = realloc((Da).data, (Da).cap_bytes); \
+            if ( (Da).data == NULL ) { \
+                LIB_SET_IF_NOT_NULL((ErrVar), ERR_FAILED_REALLOC); \
+                break; \
+            } \
+        } \
+        if ( (Da).data == NULL ) { \
+            if ( (Da).cap_bytes == 0 ) { \
+                (Da).cap_bytes = 32; \
+                (Da).size = 0; \
+                (Da).used_bytes = 0; \
+            } \
+            (Da).data = malloc(sizeof(u64) * (Da).cap_bytes); \
+            if ( (Da).data == NULL ) { \
+                LIB_SET_IF_NOT_NULL((ErrVar), ERR_FAILED_ALLOC); \
+                break; \
+            } \
+        } \
+        memcpy(CAST(u8*, (Da).data) + (Da).used_bytes, (Val), (ValSize)); \
+        (Da).used_bytes += (ValSize); \
+        ++(Da).size; \
+        LIB_SET_IF_NOT_NULL((ErrVar), ERR_OK); \
+    } while(0)
 
 /* ----------------------------- END DA DEF -------------------------------- */
 
@@ -554,14 +592,27 @@ dyn_arr_destroy(struct dyn_arr *da, enum err *out_err)
 
 # 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); \
+#  define MAP_FOR_EACH(Map, VIndex, VKey) \
+    for ( (VIndex = (Map)->indexs.data, VKey = (Map)->keys.data); \
+          VIndex < ((Map)->indexs.data + (Map)->indexs.size); \
+          (++VIndex, VKey = CAST(struct key_bytes *, CAST(u8*, VKey->key) + VKey->size)) )
+
+#  define MAP_FOR_EACH_INDEXS(Map, Var) \
+    for ( Var = (Map)->indexs.data; \
+          Var < ((Map)->indexs.data + (Map)->indexs.size); \
           ++Var )
 
+#  define MAP_GET_INDEX(Map, Index) \
+    ((struct map_item *)(((u8*)(Map)->data) + ((Map)->_item_size * (Index))))
+
+struct key_bytes {
+    u64 size;
+    u8 key[1];
+};
+
 struct map_item {
     u64 key[4];
-    u8 item[1];
+    u8  item[1];
 };
 
 struct map {
@@ -571,7 +622,13 @@ struct map {
         u64 *data;
         u64 size;
         u64 cap;
-    } used;
+    } indexs;
+    struct {
+        struct key_bytes *data;
+        u64 size;
+        u64 used_bytes;
+        u64 cap_bytes;
+    } keys;
     u64 _cap;
     u64 _size_bytes;
     u64 _item_size;
@@ -612,26 +669,41 @@ map_create(u64 elem_size, u64 cap, enum err *out_err)
     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._elem_size = elem_size;
+    m._item_size = SIZEOF_MEMBER(struct map_item, key) + m._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;
+        goto err_exit;
     }
+    memset(m.data, 0, m._size_bytes);
 
-    m.used.cap = 32;
-    m.used.data = malloc(m.used.cap);
-    if ( m.used.data == NULL ) {
-        free(m.data);
+    m.indexs.cap = m._cap;
+    m.indexs.data = malloc(sizeof(*m.indexs.data) * m.indexs.cap);
+    if ( m.indexs.data == NULL ) {
         LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
-        return empty;
+        goto err_exit;
     }
+    memset(m.indexs.data, 0, sizeof(*m.indexs.data) * m.indexs.cap);
+
+    m.keys.cap_bytes = m._cap;
+    m.keys.data = malloc(sizeof(u64) * m.keys.cap_bytes);
+    if ( m.keys.data == NULL ) {
+        LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
+        goto err_exit;
+    }
+    memset(m.keys.data, 0, m.keys.cap_bytes);
 
     m.hash = map_default_hasher;
 
     LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
     return m;
+err_exit:
+    if ( m.data        != NULL ) free(m.data);
+    if ( m.indexs.data != NULL ) free(m.indexs.data);
+    if ( m.keys.data   != NULL ) free(m.keys.data);
+    return empty;
 }
 
 enum err
@@ -640,6 +712,7 @@ map_inc_cap(struct map *_r_ m, enum err *_r_ out_err)
     enum err err = ERR_OK;
     enum err *perr = &err;
 
+    struct map old = {0};
     struct map nm = {0};
     u64 *index = 0;
 
@@ -657,14 +730,28 @@ map_inc_cap(struct map *_r_ m, enum err *_r_ out_err)
         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);
+    MAP_FOR_EACH_INDEXS(m, index) {
+        struct map_item *mi = MAP_GET_INDEX(m, (*index));
+        map_add_hashed_key(&nm, mi->key, mi->item, perr);
         if ( *perr != ERR_OK ) {
             goto err_exit;
         }
     }
 
+    old = *m;
+
+    m->data        = nm.data;
+    m->size        = nm.size;
+    m->indexs      = nm.indexs;
+    m->keys        = nm.keys;
+    m->_cap        = nm._cap;
+    m->_size_bytes = nm._size_bytes;
+    m->_item_size  = nm._item_size;
+    m->_elem_size  = nm._elem_size;
+    m->hash        = nm.hash;
+
+    map_destroy(&old, NULL);
+
     LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
     return ERR_OK;
 err_exit:
@@ -681,6 +768,7 @@ map_add_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
 
     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);
@@ -702,14 +790,18 @@ map_add_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
                 return *perr;
             }
         }
-        it = (m->data + (m->_item_size * (i++)));
+        it = MAP_GET_INDEX(m, i++);
     } while (it->key[0] != 0 || it->key[1] != 0
              || it->key[2] != 0 || it->key[3] != 0);
+    /*
+    printf("cap=%-5ld\telem_size=%-5ld\tsize_bytes=%-5ld\n",
+           m->_cap, m->_elem_size, m->_size_bytes);
+    */
 
     memcpy(it->key, key, sizeof(u64) * 4);
     memcpy(it->item, elem, m->_elem_size);
 
-    DA_APPEND(m->used, i-1, perr);
+    DA_APPEND(m->indexs, i-1, perr);
     if ( *perr != ERR_OK ) {
         memset(it->key, 0, sizeof(u64) * 4);
         memset(it->item, 0, m->_elem_size);
@@ -726,6 +818,8 @@ 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;
 
+    struct key_bytes *sb = NULL;
+
     u64 *hash = NULL;
 
     LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
@@ -747,12 +841,72 @@ map_add(struct map *m, void *key, u64 key_size, void *elem, enum err *out_err)
     }
 
     map_add_hashed_key(m, hash, elem, perr);
+    free(hash);
+
     if ( *perr != ERR_OK ) {
-        free(hash);
         return *perr;
     }
 
-    free(hash);
+    sb = malloc(SIZEOF_MEMBER(struct key_bytes, size) + key_size);
+    if ( sb == NULL ) {
+        *perr = ERR_FAILED_ALLOC;
+        return *perr;
+    }
+    memset(sb, 0, SIZEOF_MEMBER(struct key_bytes, size) + key_size);
+
+    sb->size = key_size;
+    memcpy(sb->key, key, key_size);
+
+
+    DAV_APPEND(
+        m->keys, sb,
+        SIZEOF_MEMBER(struct key_bytes, size) + key_size,
+        perr
+    );
+
+    /*
+    do {
+        if (perr != ((void * ) 0)) {
+            if ( * perr != ERR_OK) {
+                break;
+            }
+        }
+        if ((m -> keys).used_bytes + (sizeof(((struct key_bytes * ) 0) -> size) + key_size) >= (m -> keys).cap_bytes) {
+            (m -> keys).cap_bytes *= 2;
+            (m -> keys).data = realloc((m -> keys).data, (m -> keys).cap_bytes);
+            if ((m -> keys).data == ((void * ) 0)) {
+                if ((perr) != ((void * ) 0)) {
+                    *(perr) = ERR_FAILED_REALLOC;
+                };
+                break;
+            }
+        }
+        if ((m -> keys).data == ((void * ) 0)) {
+            if ((m -> keys).cap_bytes == 0) {
+                (m -> keys).cap_bytes = 32;
+                (m -> keys).size = 0;
+                (m -> keys).used_bytes = 0;
+            }(m -> keys).data = malloc(sizeof(u64) * (m -> keys).cap_bytes);
+            if ((m -> keys).data == ((void * ) 0)) {
+                if ((perr) != ((void * ) 0)) {
+                    *(perr) = ERR_FAILED_ALLOC;
+                };
+                break;
+            }
+        }
+        memcpy(((u8 * )((m -> keys).data)) + (m -> keys).used_bytes, (sb), (sizeof(((struct key_bytes * ) 0) -> size) + key_size));
+        (m -> keys).used_bytes += (sizeof(((struct key_bytes * ) 0) -> size) + key_size);
+        ++(m -> keys).size;
+        if ((perr) != ((void * ) 0)) {
+            *(perr) = ERR_OK;
+        };
+    } while (0);
+    */
+
+    free(sb);
+    if ( *perr != ERR_OK ) {
+        return *perr;
+    }
 
     *perr = ERR_OK;
     return ERR_OK;
@@ -781,7 +935,7 @@ map_get(struct map *m, void *key, u64 key_size, enum err *out_err)
             free(hash);
             return NULL;
         }
-        it = (m->data + (m->_item_size * (i++)));
+        it = MAP_GET_INDEX(m, i++);
     } while (it->key[0] != hash[0] || it->key[1] != hash[1]
              || it->key[2] != hash[2] || it->key[3] != hash[3]);
 
@@ -819,7 +973,7 @@ map_set_hashed_key(struct map *_r_ m, u64 *_r_ key, void *_r_ elem,
             *perr = ERR_NOT_FOUND;
             return *perr;
         }
-        it = (m->data + (m->_item_size * (i++)));
+        it = MAP_GET_INDEX(m, i++);
     } while (it->key[0] != key[0] || it->key[1] != key[1]
              || it->key[2] != key[2] || it->key[3] != key[3]);
 
@@ -877,8 +1031,9 @@ map_destroy(struct map *m, enum err *out_err)
 
     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);
+    if ( m->data        != NULL ) free(m->data);
+    if ( m->indexs.data != NULL ) free(m->indexs.data);
+    if ( m->keys.data   != NULL ) free(m->keys.data);
 
     LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
     return ERR_OK;