summaryrefslogtreecommitdiffhomepage
path: root/cmap.h
diff options
context:
space:
mode:
authortylo <[email protected]>2020-03-11 11:50:00 +0100
committertylo <[email protected]>2020-03-11 11:50:00 +0100
commit4da2cdc45522626d005a0221a73064f0217b69fe (patch)
tree2d22ba16bd786f9f762af9cd9c7ad55be84acedf /cmap.h
parent7c326f3effd9977cb34e23d9cc9e9eb42ae3c789 (diff)
downloadSTC-modified-4da2cdc45522626d005a0221a73064f0217b69fe.tar.gz
STC-modified-4da2cdc45522626d005a0221a73064f0217b69fe.zip
New API: c_
Diffstat (limited to 'cmap.h')
-rw-r--r--cmap.h200
1 files changed, 100 insertions, 100 deletions
diff --git a/cmap.h b/cmap.h
index 542f7c87..20804882 100644
--- a/cmap.h
+++ b/cmap.h
@@ -20,122 +20,122 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
-#ifndef CMAP_H_
-#define CMAP_H_
+#ifndef C_HASHMAP_H_
+#define C_HASHMAP_H_
-#include "cvector.h"
+#include "c_vector.h"
-#define cmap_initializer {cvector_initializer, 0, 0.8f}
-#define cmap_size(cm) ((size_t) (cm)._size)
-#define cmap_buckets(cm) cvector_capacity((cm)._vec)
+#define c_hashmap_initializer {c_vector_initializer, 0, 0.8f}
+#define c_hashmap_size(cm) ((size_t) (cm)._size)
+#define c_hashmap_buckets(cm) c_vector_capacity((cm)._vec)
-// CMapEntry:
-enum { CMapEntry_VACANT = 0,
- CMapEntry_INUSE = 1,
- CMapEntry_ERASED = 2
+// c_HashmapEntry:
+enum { c_HashmapEntry_VACANT = 0,
+ c_HashmapEntry_INUSE = 1,
+ c_HashmapEntry_ERASED = 2
};
-#define declare_CMapEntry(tag, Key, Value, keyDestroy, valueDestroy) \
-struct CMapEntry_##tag { \
+#define c_declare_HashmapEntry(tag, Key, Value, keyDestroy, valueDestroy) \
+struct c_HashmapEntry_##tag { \
Key key; \
Value value; \
uint8_t state, changed; \
}; \
\
-static inline void cmapentry_##tag##_destroy(struct CMapEntry_##tag* e) { \
+static inline void cmapentry_##tag##_destroy(struct c_HashmapEntry_##tag* e) { \
keyDestroy(&e->key); \
valueDestroy(&e->value); \
- e->state = CMapEntry_VACANT; \
+ e->state = c_HashmapEntry_VACANT; \
} \
-typedef struct CMapEntry_##tag CMapEntry_##tag
+typedef struct c_HashmapEntry_##tag c_HashmapEntry_##tag
-// CMap:
-#define declare_CMap(...) cdefs_MACRO_OVERLOAD(declare_CMap, __VA_ARGS__)
+// c_Hashmap:
+#define c_declare_Hashmap(...) c_defs_MACRO_OVERLOAD(c_declare_Hashmap, __VA_ARGS__)
-#define declare_CMap_3(tag, Key, Value) \
- declare_CMap_4(tag, Key, Value, cdefs_destroy)
+#define c_declare_Hashmap_3(tag, Key, Value) \
+ c_declare_Hashmap_4(tag, Key, Value, c_defs_destroy)
-#define declare_CMap_4(tag, Key, Value, valueDestroy) \
- declare_CMap_10(tag, Key, Value, valueDestroy, Key, memcmp, cdefs_murmurHash, cdefs_initRaw, cdefs_getRaw, cdefs_destroy)
+#define c_declare_Hashmap_4(tag, Key, Value, valueDestroy) \
+ c_declare_Hashmap_10(tag, Key, Value, valueDestroy, Key, memcmp, c_defs_murmurHash, c_defs_initRaw, c_defs_getRaw, c_defs_destroy)
-// CMap<CString, Value>:
-#define declare_CMap_StringKey(...) cdefs_MACRO_OVERLOAD(declare_CMap_StringKey, __VA_ARGS__)
+// c_Hashmap<c_String, Value>:
+#define c_declare_Hashmap_stringkey(...) c_defs_MACRO_OVERLOAD(c_declare_Hashmap_stringkey, __VA_ARGS__)
-#define declare_CMap_StringKey_2(tag, Value) \
- declare_CMap_StringKey_3(tag, Value, cdefs_destroy)
+#define c_declare_Hashmap_stringkey_2(tag, Value) \
+ c_declare_Hashmap_stringkey_3(tag, Value, c_defs_destroy)
-#define declare_CMap_StringKey_3(tag, Value, valueDestroy) \
- declare_CMap_10(tag, CString, Value, valueDestroy, const char*, cstring_compareRaw, cstring_hashRaw, cstring_make, cstring_getRaw, cstring_destroy)
+#define c_declare_Hashmap_stringkey_3(tag, Value, valueDestroy) \
+ c_declare_Hashmap_10(tag, CString, Value, valueDestroy, const char*, cstring_compareRaw, cstring_hashRaw, cstring_make, cstring_getRaw, cstring_destroy)
-// CMap full:
-#define declare_CMap_10(tag, Key, Value, valueDestroy, KeyRaw, keyCompareRaw, keyHashRaw, keyInitRaw, keyGetRaw, keyDestroy) \
- declare_CMapEntry(tag, Key, Value, keyDestroy, valueDestroy); \
- declare_CVector_3(map_##tag, CMapEntry_##tag, cmapentry_##tag##_destroy); \
+// c_Hashmap full:
+#define c_declare_Hashmap_10(tag, Key, Value, valueDestroy, KeyRaw, keyCompareRaw, keyHashRaw, keyInitRaw, keyGetRaw, keyDestroy) \
+ c_declare_HashmapEntry(tag, Key, Value, keyDestroy, valueDestroy); \
+ c_declare_Vector_3(map_##tag, c_HashmapEntry_##tag, cmapentry_##tag##_destroy); \
\
-typedef struct CMap_##tag { \
- CVector_map_##tag _vec; \
+typedef struct c_Hashmap_##tag { \
+ c_Vector_map_##tag _vec; \
size_t _size; \
float maxLoadFactor; \
-} CMap_##tag; \
+} c_Hashmap_##tag; \
\
-typedef struct cmap_##tag##_iter_t { \
- CMapEntry_##tag *item, *_end; \
-} cmap_##tag##_iter_t; \
+typedef struct c_hashmap_##tag##_iter_t { \
+ c_HashmapEntry_##tag *item, *_end; \
+} c_hashmap_##tag##_iter_t; \
\
-static inline CMap_##tag cmap_##tag##_init(void) { \
- CMap_##tag map = cmap_initializer; \
+static inline c_Hashmap_##tag c_hashmap_##tag##_init(void) { \
+ c_Hashmap_##tag map = c_hashmap_initializer; \
return map; \
} \
\
-static inline void cmap_##tag##_destroy(CMap_##tag* self) { \
- if (cmap_size(*self)) { \
- size_t cap = _cvector_capacity(self->_vec); \
- CMapEntry_##tag* e = self->_vec.data, *end = e + cap; \
- for (; e != end; ++e) if (e->state == CMapEntry_INUSE) cmapentry_##tag##_destroy(e); \
+static inline void c_hashmap_##tag##_destroy(c_Hashmap_##tag* self) { \
+ if (c_hashmap_size(*self)) { \
+ size_t cap = _c_vector_capacity(self->_vec); \
+ c_HashmapEntry_##tag* e = self->_vec.data, *end = e + cap; \
+ for (; e != end; ++e) if (e->state == c_HashmapEntry_INUSE) cmapentry_##tag##_destroy(e); \
} \
- cvector_map_##tag##_destroy(&self->_vec); \
+ c_vector_map_##tag##_destroy(&self->_vec); \
} \
\
-static inline size_t cmap_##tag##_reserve(CMap_##tag* self, size_t size); /* predeclared */ \
+static inline size_t c_hashmap_##tag##_reserve(c_Hashmap_##tag* self, size_t size); /* predeclared */ \
\
-static inline void cmap_##tag##_clear(CMap_##tag* self) { \
- CMap_##tag cm = cmap_initializer; \
- cmap_##tag##_destroy(self); \
+static inline void c_hashmap_##tag##_clear(c_Hashmap_##tag* self) { \
+ c_Hashmap_##tag cm = c_hashmap_initializer; \
+ c_hashmap_##tag##_destroy(self); \
*self = cm; \
} \
\
-static inline void cmap_##tag##_swap(CMap_##tag* a, CMap_##tag* b) { \
- cvector_map_##tag##_swap(&a->_vec, &b->_vec); \
- cdefs_swap(size_t, a->_size, b->_size); \
+static inline void c_hashmap_##tag##_swap(c_Hashmap_##tag* a, c_Hashmap_##tag* b) { \
+ c_vector_map_##tag##_swap(&a->_vec, &b->_vec); \
+ c_defs_swap(size_t, a->_size, b->_size); \
} \
\
-static inline void cmap_##tag##_setMaxLoadFactor(CMap_##tag* self, float fac) { \
+static inline void c_hashmap_##tag##_setMaxLoadFactor(c_Hashmap_##tag* self, float fac) { \
self->maxLoadFactor = fac; \
- if (cmap_size(*self) > cmap_buckets(*self) * fac) \
- cmap_##tag##_reserve(self, 1 + (size_t) (cmap_size(*self) / fac)); \
+ if (c_hashmap_size(*self) > c_hashmap_buckets(*self) * fac) \
+ c_hashmap_##tag##_reserve(self, 1 + (size_t) (c_hashmap_size(*self) / fac)); \
} \
\
-static inline size_t cmap_##tag##_bucket(CMap_##tag cm, KeyRaw rawKey) { \
- size_t cap = cvector_capacity(cm._vec); \
- size_t idx = cmap_reduce(keyHashRaw(&rawKey, sizeof(Key)), cap); \
+static inline size_t c_hashmap_##tag##_bucket(c_Hashmap_##tag cm, KeyRaw rawKey) { \
+ size_t cap = c_vector_capacity(cm._vec); \
+ size_t idx = c_hashmap_reduce(keyHashRaw(&rawKey, sizeof(Key)), cap); \
size_t first = idx, erased_idx = cap; \
FIBONACCI_DECL; \
do { \
switch (cm._vec.data[idx].state) { \
- case CMapEntry_VACANT: \
+ case c_HashmapEntry_VACANT: \
return erased_idx != cap ? erased_idx : idx; \
- case CMapEntry_INUSE: \
+ case c_HashmapEntry_INUSE: \
if (keyCompareRaw(&cm._vec.data[idx].key, &rawKey, sizeof(Key)) != 0) \
break; \
if (erased_idx != cap) { \
- cdefs_swap(CMapEntry_##tag, cm._vec.data[erased_idx], cm._vec.data[idx]); \
+ c_defs_swap(c_HashmapEntry_##tag, cm._vec.data[erased_idx], cm._vec.data[idx]); \
return erased_idx; \
} \
return idx; \
- case CMapEntry_ERASED: \
+ case c_HashmapEntry_ERASED: \
if (erased_idx == cap) erased_idx = idx; \
break; \
} \
@@ -144,80 +144,80 @@ static inline size_t cmap_##tag##_bucket(CMap_##tag cm, KeyRaw rawKey) { \
} while (1); \
} \
\
-static inline CMapEntry_##tag* cmap_##tag##_get(CMap_##tag cm, KeyRaw rawKey) { \
- if (cmap_size(cm) == 0) return NULL; \
- size_t idx = cmap_##tag##_bucket(cm, rawKey); \
- return cm._vec.data[idx].state == CMapEntry_INUSE ? &cm._vec.data[idx] : NULL; \
+static inline c_HashmapEntry_##tag* c_hashmap_##tag##_get(c_Hashmap_##tag cm, KeyRaw rawKey) { \
+ if (c_hashmap_size(cm) == 0) return NULL; \
+ size_t idx = c_hashmap_##tag##_bucket(cm, rawKey); \
+ return cm._vec.data[idx].state == c_HashmapEntry_INUSE ? &cm._vec.data[idx] : NULL; \
} \
\
-static inline CMapEntry_##tag* cmap_##tag##_put(CMap_##tag* self, KeyRaw rawKey, Value value) { \
- size_t cap = cvector_capacity(self->_vec); \
- if (cmap_size(*self) >= cap * self->maxLoadFactor) \
- cap = cmap_##tag##_reserve(self, (size_t) (cap * 1.8)); \
- size_t idx = cmap_##tag##_bucket(*self, rawKey); \
- CMapEntry_##tag* e = &self->_vec.data[idx]; \
+static inline c_HashmapEntry_##tag* c_hashmap_##tag##_put(c_Hashmap_##tag* self, KeyRaw rawKey, Value value) { \
+ size_t cap = c_vector_capacity(self->_vec); \
+ if (c_hashmap_size(*self) >= cap * self->maxLoadFactor) \
+ cap = c_hashmap_##tag##_reserve(self, (size_t) (cap * 1.8)); \
+ size_t idx = c_hashmap_##tag##_bucket(*self, rawKey); \
+ c_HashmapEntry_##tag* e = &self->_vec.data[idx]; \
e->value = value; \
- e->changed = (e->state == CMapEntry_INUSE); \
- if (e->state != CMapEntry_INUSE) { \
+ e->changed = (e->state == c_HashmapEntry_INUSE); \
+ if (e->state != c_HashmapEntry_INUSE) { \
e->key = keyInitRaw(rawKey); \
- e->state = CMapEntry_INUSE; \
+ e->state = c_HashmapEntry_INUSE; \
++self->_size; \
} \
return e; \
} \
\
-static inline size_t cmap_##tag##_reserve(CMap_##tag* self, size_t size) { \
- size_t oldcap = cvector_capacity(self->_vec), newcap = (oldcap ? 1 : 7) + (size / 2) * 2; \
+static inline size_t c_hashmap_##tag##_reserve(c_Hashmap_##tag* self, size_t size) { \
+ size_t oldcap = c_vector_capacity(self->_vec), newcap = (oldcap ? 1 : 7) + (size / 2) * 2; \
if (oldcap >= newcap) return oldcap; \
- CVector_map_##tag vec = cvector_initializer; \
- cvector_map_##tag##_swap(&self->_vec, &vec); \
- cvector_map_##tag##_reserve(&self->_vec, newcap); \
+ c_Vector_map_##tag vec = c_vector_initializer; \
+ c_vector_map_##tag##_swap(&self->_vec, &vec); \
+ c_vector_map_##tag##_reserve(&self->_vec, newcap); \
self->_size = 0; \
- memset(self->_vec.data, 0, sizeof(CMapEntry_##tag) * newcap); \
- CMapEntry_##tag* e = vec.data; \
+ memset(self->_vec.data, 0, sizeof(c_HashmapEntry_##tag) * newcap); \
+ c_HashmapEntry_##tag* e = vec.data; \
for (size_t i = 0; i < oldcap; ++i, ++e) \
- if (e->state == CMapEntry_INUSE) cmap_##tag##_put(self, keyGetRaw(e->key), e->value); \
+ if (e->state == c_HashmapEntry_INUSE) c_hashmap_##tag##_put(self, keyGetRaw(e->key), e->value); \
return newcap; \
} \
\
-static inline bool cmap_##tag##_erase(CMap_##tag* self, KeyRaw rawKey) { \
- CMapEntry_##tag* e = cmap_##tag##_get(*self, rawKey); \
+static inline bool c_hashmap_##tag##_erase(c_Hashmap_##tag* self, KeyRaw rawKey) { \
+ c_HashmapEntry_##tag* e = c_hashmap_##tag##_get(*self, rawKey); \
if (e) { \
cmapentry_##tag##_destroy(e); \
- e->state = CMapEntry_ERASED; \
+ e->state = c_HashmapEntry_ERASED; \
--self->_size; \
return true; \
} \
return false; \
} \
\
-static inline cmap_##tag##_iter_t cmap_##tag##_begin(CMap_##tag map) { \
- cmap_##tag##_iter_t null = {NULL, NULL}; \
- if (cmap_size(map) == 0) return null; \
- CMapEntry_##tag* e = map._vec.data, *end = e + _cvector_capacity(map._vec); \
- while (e != end && e->state != CMapEntry_INUSE) ++e; \
- cmap_##tag##_iter_t it = {e, end}; return it; \
+static inline c_hashmap_##tag##_iter_t c_hashmap_##tag##_begin(c_Hashmap_##tag map) { \
+ c_hashmap_##tag##_iter_t null = {NULL, NULL}; \
+ if (c_hashmap_size(map) == 0) return null; \
+ c_HashmapEntry_##tag* e = map._vec.data, *end = e + _c_vector_capacity(map._vec); \
+ while (e != end && e->state != c_HashmapEntry_INUSE) ++e; \
+ c_hashmap_##tag##_iter_t it = {e, end}; return it; \
} \
\
-static inline cmap_##tag##_iter_t cmap_##tag##_next(cmap_##tag##_iter_t it) { \
- do { ++it.item; } while (it.item != it._end && it.item->state != CMapEntry_INUSE); \
+static inline c_hashmap_##tag##_iter_t c_hashmap_##tag##_next(c_hashmap_##tag##_iter_t it) { \
+ do { ++it.item; } while (it.item != it._end && it.item->state != c_HashmapEntry_INUSE); \
return it; \
} \
\
-static inline cmap_##tag##_iter_t cmap_##tag##_end(CMap_##tag map) { \
- CMapEntry_##tag* end = (cmap_size(map) == 0) ? NULL : map._vec.data + _cvector_capacity(map._vec); \
- cmap_##tag##_iter_t it = {end, end}; \
+static inline c_hashmap_##tag##_iter_t c_hashmap_##tag##_end(c_Hashmap_##tag map) { \
+ c_HashmapEntry_##tag* end = (c_hashmap_size(map) == 0) ? NULL : map._vec.data + _c_vector_capacity(map._vec); \
+ c_hashmap_##tag##_iter_t it = {end, end}; \
return it; \
} \
-typedef Key cmap_##tag##_key_t; \
-typedef Value cmap_##tag##_value_t
+typedef Key c_hashmap_##tag##_key_t; \
+typedef Value c_hashmap_##tag##_value_t
#define FIBONACCI_DECL size_t fib1 = 0, fib2 = 1, fibx
#define FIBONACCI_NEXT (fibx = fib1 + fib2, fib1 = fib2, fib2 = fibx)
// https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
-static inline uint32_t cmap_reduce(uint32_t x, uint32_t N) {
+static inline uint32_t c_hashmap_reduce(uint32_t x, uint32_t N) {
return ((uint64_t) x * (uint64_t) N) >> 32 ;
}