From 3635797e39dbf4d4811b02411658c2b9bd61e14a Mon Sep 17 00:00:00 2001 From: Tyge Løvset <60263450+tylo-work@users.noreply.github.com> Date: Thu, 12 Mar 2020 13:28:20 +0100 Subject: Reverted to original API --- README.md | 239 ++++++++++++++++++++++++++++++---------------------------- benchmark.cpp | 40 +++++----- c_defs.h | 36 ++++----- c_hashmap.h | 210 ++++++++++++++++++++++++++------------------------- c_string.h | 182 ++++++++++++++++++++++---------------------- c_vector.h | 128 +++++++++++++++---------------- cmap_test.c | 98 ++++++++++++------------ 7 files changed, 473 insertions(+), 460 deletions(-) diff --git a/README.md b/README.md index 12cca576..db2398ef 100644 --- a/README.md +++ b/README.md @@ -1,114 +1,125 @@ -# c_Lib - -Introduction ------------- -A modern, typesafe, very efficient, generic C99 container library: String, Vector and Hashmap - -Headers only library with the most used data structures: string, dynamic vector/stack, and map/assosiative array. The library has an intuitive and API. It uses overloadable macros to simplify usage. - -Usage ------ -c_String demo: -``` -#include "c_string.h" - -int main() { - c_String cs = c_string_make("one-nine-three-seven-five"); - printf("%s.\n", cs.str); - c_string_insert(&cs, 3, "-two"); - printf("%s.\n", cs.str); - c_string_erase(&cs, 7, 5); // -nine - printf("%s.\n", cs.str); - c_string_replace(&cs, 0, "seven", "four"); - printf("%s.\n", cs.str); - printf("find: %s\n", cs.str + c_string_find(cs, 0, "four")); - // reassign: - c_string_assign(&cs, "one two three four five six seven"); - c_string_append(&cs, " eight"); - printf("append: %s\n", cs.str); -} -``` -Simple c_Vector of 64bit ints: -``` -#include "c_vector.h" -c_declare_Vector(ix, int64_t); // ix is just an example tag name, use anything without underscore. - -int main() { - c_Vector_ix bignums = c_vector_initializer; // use c_vector_ix_init(); if initializing after declaration. - c_vector_ix_reserve(&bignums, 100); - for (size_t i = 0; i<100; ++i) - c_vector_ix_push(&bignums, i * i * i); - c_vector_ix_pop(&bignums); // erase the last - - uint64_t value; - for (size_t i = 0; i < c_vector_size(bignums); ++i) - value = bignums.data[i]; - c_vector_ix_destroy(&bignums); -} -``` -CVector of CString: -``` -#include "c_string.h" -#include "c_vector.h" -c_declare_Vector(cs, c_String, c_string_destroy); // supply inline destructor of values - -int main() { - c_Vector_cs names = c_vector_initializer; - c_vector_cs_push(&names, c_string_make("Mary")); - c_vector_cs_push(&names, c_string_make("Joe")); - c_string_assign(&names.data[1], c_string_make("Jake")); // replace Joe - printf("%s\n", names.data[1].str); // Access the string char* - c_vector_cs_destroy(&names); -} -``` -Simple c_Hashmap, int -> int: -``` -#include "c_hashmap.h" -c_declare_Hashmap(ii, int, int); - -int main() { - c_Hashmap_ii nums = c_hashmap_initializer; - c_hashmap_ii_put(&nums, 8, 64); - c_hashmap_ii_put(&nums, 11, 121); - printf("%d\n", c_hashmap_ii_get(nums, 8)->value); - c_hashmap_ii_destroy(&nums); -} -``` -Simple c_Hashmap, c_String -> int: -``` -#include "c_string.h" -#include "c_hashmap.h" -c_declare_Hashmap_stringkey(si, int); // Shorthand macro for the general c_declare_Hashmap expansion. -// c_String keys are "magically" managed internally, although c_Hashmap is ignorant of c_String. - -int main() { - c_Hashmap_si nums = c_hashmap_initializer; - c_hashmap_si_put(&nums, "Hello", 64); - c_hashmap_si_put(&nums, "Groovy", 121); - c_hashmap_si_put(&nums, "Groovy", 200); // overwrite previous - // iterate the map: - for (c_hashmap_si_iter_t i = c_hashmap_si_begin(nums); i.item != c_hashmap_si_end(nums).item; i = c_hashmap_si_next(i)) - printf("%s: %d\n", i.item->key.str, i.item->value); - // or rather use the short form: - c_foreach (i, c_hashmap_si, nums) - printf("%s: %d, changed: %s\n", i.item->key.str, i.item->value, i.item->changed ? "yes" : "no"); - - c_hashmap_si_destroy(&nums); -} -``` -c_Hashmap, with c_String -> c_String. Temporary c_String values are created by "make", and moved to the container. -``` -#include "c_string.h" -#include "c_hashmap.h" -c_declare_Hashmap_stringkey(ss, c_String, c_string_destroy); - -int main() { - c_Hashmap_ss table = c_hashmap_initializer; - c_hashmap_ss_put(&table, "Make", c_string_make("my")); - c_hashmap_ss_put(&table, "Sunny", c_string_make("day")); - printf("Sunny: %s\n", c_hashmap_ss_get(table, "Sunny")->value.str); - c_hashmap_ss_erase(&table, "Make"); - printf("size %d\n", c_hashmap_size(table)); - c_hashmap_ss_destroy(&table); // frees key and value c_Strings, and hash table (c_Vector). -} -``` +# c_Lib + +Introduction +------------ +A modern, typesafe, very efficient, generic C99 container library: String, Vector and Hashmap + +Headers only library with the most used data structures: string, dynamic vector/stack, and map/assosiative array. The library has an intuitive and API. It uses overloadable macros to simplify usage. + +Usage +----- +CString demo: +``` +#include + +int main() { + CString cs = cstring_make("one-nine-three-seven-five"); + printf("%s.\n", cs.str); + + cstring_insert(&cs, 3, "-two"); + printf("%s.\n", cs.str); + + cstring_erase(&cs, 7, 5); // -nine + printf("%s.\n", cs.str); + + cstring_replace(&cs, 0, "seven", "four"); + printf("%s.\n", cs.str); + printf("find: %s\n", cs.str + cstring_find(cs, 0, "four")); + + // reassign: + cstring_assign(&cs, "one two three four five six seven"); + cstring_append(&cs, " eight"); + printf("append: %s\n", cs.str); + + cstring_destroy(&cs); +} +``` +Simple CVector of 64bit ints: +``` +#include +declare_CVector(ix, int64_t); // ix is just an example tag name, use anything without underscore. + +int main() { + CVector_ix bignums = cvector_initializer; // use cvector_ix_init(); if initializing after declaration. + cvector_ix_reserve(&bignums, 100); + for (size_t i = 0; i<100; ++i) + cvector_ix_push(&bignums, i * i * i); + cvector_ix_pop(&bignums); // erase the last + + uint64_t value; + for (size_t i = 0; i < cvector_size(bignums); ++i) + value = bignums.data[i]; + cvector_ix_destroy(&bignums); +} +``` +CVector of CString: +``` +#include +#include +declare_CVector(cs, CString, cstring_destroy); // supply inline destructor of values + +int main() { + CVector_cs names = cvector_initializer; + cvector_cs_push(&names, cstring_make("Mary")); + cvector_cs_push(&names, cstring_make("Joe")); + cstring_assign(&names.data[1], cstring_make("Jake")); // replace Joe + + printf("%s\n", names.data[1].str); // Access the string char* + cvector_cs_destroy(&names); +} +``` +Simple CMap, int -> int: +``` +#include +declare_CMap(ii, int, int); + +int main() { + CMap_ii nums = cmap_initializer; + cmap_ii_put(&nums, 8, 64); + cmap_ii_put(&nums, 11, 121); + + printf("%d\n", cmap_ii_get(nums, 8)->value); + cmap_ii_destroy(&nums); +} +``` +Simple CMap, CString -> int: +``` +#include +#include +declare_CMap_stringkey(si, int); // Shorthand macro for the general declare_CMap expansion. +// CString keys are "magically" managed internally, although CMap is ignorant of CString. + +int main() { + CMap_si nums = cmap_initializer; + cmap_si_put(&nums, "Hello", 64); + cmap_si_put(&nums, "Groovy", 121); + cmap_si_put(&nums, "Groovy", 200); // overwrite previous + + // iterate the map: + for (cmap_si_iter_t i = cmap_si_begin(nums); i.item != cmap_si_end(nums).item; i = cmap_si_next(i)) + printf("%s: %d\n", i.item->key.str, i.item->value); + + // or rather use the short form: + c_foreach (i, cmap_si, nums) + printf("%s: %d\n", i.item->key.str, i.item->value); + + cmap_si_destroy(&nums); +} +``` +CMap, with CString -> CString. Temporary CString values are created by "make", and moved to the container. +``` +#include +#include +declare_CMap_stringkey(ss, CString, cstring_destroy); + +int main() { + CMap_ss table = cmap_initializer; + cmap_ss_put(&table, "Make", cstring_make("my")); + cmap_ss_put(&table, "Sunny", cstring_make("day")); + printf("Sunny: %s\n", cmap_ss_get(table, "Sunny")->value.str); + cmap_ss_erase(&table, "Make"); + + printf("size %d\n", cmap_size(table)); + cmap_ss_destroy(&table); // frees key and value CStrings, and hash table (CVector). +} +``` diff --git a/benchmark.cpp b/benchmark.cpp index 3f11703d..2cf1929b 100644 --- a/benchmark.cpp +++ b/benchmark.cpp @@ -6,65 +6,65 @@ #include -c_declare_Hashmap(ii, int, int); -c_declare_Vector_string(s); +declare_CMap(ii, int, int); +declare_CVector_string(s); int main() { - c_Hashmap_ii map = c_hashmap_initializer; + CMap_ii map = cmap_initializer; int K = 300000; printf("BEGIN\n"); - //c_hashmap_ii_reserve(&map, 50); + //cmap_ii_reserve(&map, 50); /* - c_hashmap_ii_setMaxLoadFactor(&map, 0.8); + cmap_ii_setMaxLoadFactor(&map, 0.8); for (size_t i = 0; i < K; ++i) { - c_hashmap_ii_put(&map, i*i, i); + cmap_ii_put(&map, i*i, i); } for (size_t i = 0; i < K/2; ++i) { - c_hashmap_ii_erase(&map, i*i); + cmap_ii_erase(&map, i*i); } - c_foreach (i, c_hashmap_ii, map) c_hashmap_ii_bucket(map, i.item->key); + c_foreach (i, cmap_ii, map) cmap_ii_bucket(map, i.item->key); for (size_t i = 0; i < K/2; ++i) { - c_hashmap_ii_put(&map, i, i*i); + cmap_ii_put(&map, i, i*i); } - c_foreach (i, c_hashmap_ii, map) c_hashmap_ii_bucket(map, i.item->key); + c_foreach (i, cmap_ii, map) cmap_ii_bucket(map, i.item->key); */ uint64_t checksum = 0; clock_t before, difference; size_t fib1, fib2, fibx; - const size_t N = 10000000; + const size_t N = 20000000; printf("Starting %llu\n", N); - //c_hashmap_ii_reserve(&map, N * 1.25); + //cmap_ii_reserve(&map, N * 1.25); before = clock(); fib1 = 0, fib2 = 1; checksum = 0; for (size_t i = 0; i < N; ++i) { - checksum += ++c_hashmap_ii_put(&map, FIBONACCI_NEXT, i)->value; + checksum += ++cmap_ii_put(&map, FIBONACCI_NEXT, i)->value; } difference = clock() - before; - printf("c_Hashmap_ii added: size: %llu, time: %f, check: %llu\n", c_hashmap_size(map), 1.0 * difference / CLOCKS_PER_SEC, checksum); + printf("CMap_ii added: size: %llu, time: %f, check: %llu\n", cmap_size(map), 1.0 * difference / CLOCKS_PER_SEC, checksum); before = clock(); fib1 = 0, fib2 = 1; for (size_t i = 0; i < N*2/3; ++i) { - c_hashmap_ii_erase(&map, FIBONACCI_NEXT); + cmap_ii_erase(&map, FIBONACCI_NEXT); } difference = clock() - before; - printf("c_Hashmap_ii removed: size: %llu, time: %f, check: %llu\n", c_hashmap_size(map), 1.0 * difference / CLOCKS_PER_SEC, checksum); + printf("CMap_ii removed: size: %llu, time: %f, check: %llu\n", cmap_size(map), 1.0 * difference / CLOCKS_PER_SEC, checksum); before = clock(); fib1 = 0, fib2 = 1; checksum = 0; for (size_t i = 0; i < N; ++i) { - checksum += ++c_hashmap_ii_put(&map, i, i)->value; + checksum += ++cmap_ii_put(&map, i, i)->value; } difference = clock() - before; - printf("c_Hashmap_ii re-add: size: %llu, time: %f, check: %llu\n", c_hashmap_size(map), 1.0 * difference / CLOCKS_PER_SEC, checksum); + printf("CMap_ii re-add: size: %llu, time: %f, check: %llu\n", cmap_size(map), 1.0 * difference / CLOCKS_PER_SEC, checksum); size_t sum = 0; - c_foreach (i, c_hashmap_ii, map) sum += c_hashmap_ii_get(map, i.item->key)->value; + c_foreach (i, cmap_ii, map) sum += cmap_ii_get(map, i.item->key)->value; - c_hashmap_ii_destroy(&map); + cmap_ii_destroy(&map); std::unordered_map map2; diff --git a/c_defs.h b/c_defs.h index 4ebd21c7..0d25c916 100644 --- a/c_defs.h +++ b/c_defs.h @@ -20,38 +20,38 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#ifndef C_DEFS__H__ -#define C_DEFS__H__ +#ifndef CDEFS__H__ +#define CDEFS__H__ #include #include // Macro overloading feature support: https://rextester.com/ONP80107 -#define c_defs_CAT( A, B ) A ## B -#define c_defs_EXPAND(...) __VA_ARGS__ -#define c_defs_VA_ARG_SIZE(...) c_defs_EXPAND(c_defs_APPLY_ARG_N((__VA_ARGS__, c_defs_RSEQ_N))) -#define c_defs_APPLY_ARG_N(ARGS) c_defs_EXPAND(c_defs_ARG_N ARGS) -#define c_defs_ARG_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N,...) N -#define c_defs_RSEQ_N 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 -#define c_defs_OVERLOAD_SELECT(NAME, NUM) c_defs_CAT( NAME ## _, NUM) +#define c_CAT( A, B ) A ## B +#define c_EXPAND(...) __VA_ARGS__ +#define c_VA_ARG_SIZE(...) c_EXPAND(c_APPLY_ARG_N((__VA_ARGS__, c_RSEQ_N))) +#define c_APPLY_ARG_N(ARGS) c_EXPAND(c_ARG_N ARGS) +#define c_ARG_N(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N,...) N +#define c_RSEQ_N 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +#define c_OVERLOAD_SELECT(NAME, NUM) c_CAT( NAME ## _, NUM) -#define c_defs_MACRO_OVERLOAD(NAME, ...) c_defs_OVERLOAD_SELECT(NAME, c_defs_VA_ARG_SIZE(__VA_ARGS__))(__VA_ARGS__) -// #define foo(...) c_defs_MACRO_OVERLOAD(foo, __VA_ARGS__) +#define c_MACRO_OVERLOAD(NAME, ...) c_OVERLOAD_SELECT(NAME, c_VA_ARG_SIZE(__VA_ARGS__))(__VA_ARGS__) +// #define foo(...) c_MACRO_OVERLOAD(foo, __VA_ARGS__) // #define foo_1(X) foo_2(X, 100) // #define foo_2(X, Y) X + Y -#define c_defs_npos ((size_t) -1) -#define c_defs_max_alloca (1000) -#define c_defs_swap(T, x, y) { T __t = x; x = y; y = __t; } +#define c_npos ((size_t) -1) +#define c_max_alloca (1000) +#define c_swap(T, x, y) { T __t = x; x = y; y = __t; } -#define c_defs_initRaw(x) (x) -#define c_defs_getRaw(x) (x) -static inline void c_defs_destroy(void* value) {} +#define c_defaultInitRaw(x) (x) +#define c_defaultGetRaw(x) (x) +static inline void c_defaultDestroy(void* value) {} #define c_foreach(it, ctag, con) \ for (ctag##_iter_t it = ctag##_begin(con); it.item != ctag##_end(con).item; it = ctag##_next(it)) -static inline uint32_t c_defs_murmurHash(const void *data, size_t len) { // One-at-a-time 32bit +static inline uint32_t c_murmurHash(const void *data, size_t len) { // One-at-a-time 32bit const unsigned char *key = (const unsigned char *) data; uint32_t h = 0xC613FC15; // ‭0x749E3E6989DF617‬; 64bit while (len--) { diff --git a/c_hashmap.h b/c_hashmap.h index 1f81ff70..1011d363 100644 --- a/c_hashmap.h +++ b/c_hashmap.h @@ -20,125 +20,127 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#ifndef C_HASHMAP_H_ -#define C_HASHMAP_H_ +#ifndef CHASHMAP_H_ +#define CHASHMAP_H_ #include "c_vector.h" -#define c_hashmap_initializer {c_vector_initializer, 0, 0.8f} -#define c_hashmap_size(map) ((size_t) (map)._size) -#define c_hashmap_buckets(map) c_vector_capacity((map)._vec) +#define cmap_initializer {cvector_initializer, 0, 0.8f} +#define cmap_size(map) ((size_t) (map)._size) +#define cmap_buckets(map) cvector_capacity((map)._vec) -// c_HashmapEntry: -enum { c_HashmapEntry_VACANT = 0, - c_HashmapEntry_INUSE = 1, - c_HashmapEntry_ERASED = 2 +// CMapEntry: +enum { CMapEntry_VACANT = 0, + CMapEntry_INUSE = 1, + CMapEntry_ERASED = 2 }; -#define c_declare_HashmapEntry(tag, Key, Value, valueDestroy, keyDestroy) \ -struct c_HashmapEntry_##tag { \ +#define declare_CMapEntry(tag, Key, Value, valueDestroy, keyDestroy) \ +struct CMapEntry_##tag { \ Key key; \ Value value; \ uint8_t state, changed; \ }; \ \ -static inline void c_hashmapentry_##tag##_destroy(struct c_HashmapEntry_##tag* e) { \ +static inline void chmapentry_##tag##_destroy(struct CMapEntry_##tag* e) { \ keyDestroy(&e->key); \ valueDestroy(&e->value); \ - e->state = c_HashmapEntry_VACANT; \ + e->state = CMapEntry_VACANT; \ } \ -typedef struct c_HashmapEntry_##tag c_HashmapEntry_##tag +typedef struct CMapEntry_##tag CMapEntry_##tag -// c_Hashmap: -#define c_declare_Hashmap(...) c_defs_MACRO_OVERLOAD(c_declare_Hashmap, __VA_ARGS__) +// CMap: +#define declare_CMap(...) c_MACRO_OVERLOAD(declare_CMap, __VA_ARGS__) -#define c_declare_Hashmap_3(tag, Key, Value) \ - c_declare_Hashmap_4(tag, Key, Value, c_defs_destroy) +#define declare_CMap_3(tag, Key, Value) \ + declare_CMap_4(tag, Key, Value, c_defaultDestroy) -#define c_declare_Hashmap_4(tag, Key, Value, valueDestroy) \ - c_declare_Hashmap_6(tag, Key, Value, valueDestroy, memcmp, c_defs_murmurHash) +#define declare_CMap_4(tag, Key, Value, valueDestroy) \ + declare_CMap_6(tag, Key, Value, valueDestroy, memcmp, c_murmurHash) -#define c_declare_Hashmap_6(tag, Key, Value, valueDestroy, keyCompare, keyHash) \ - c_declare_Hashmap_10(tag, Key, Value, valueDestroy, keyCompare, keyHash, c_defs_destroy, Key, c_defs_getRaw, c_defs_initRaw) +#define declare_CMap_6(tag, Key, Value, valueDestroy, keyCompare, keyHash) \ + declare_CMap_10(tag, Key, Value, valueDestroy, keyCompare, keyHash, c_defaultDestroy, Key, c_defaultGetRaw, c_defaultInitRaw) -// c_Hashmap: -#define c_declare_Hashmap_stringkey(...) c_defs_MACRO_OVERLOAD(c_declare_Hashmap_stringkey, __VA_ARGS__) +// CMap: +#define declare_CMap_stringkey(...) c_MACRO_OVERLOAD(declare_CMap_stringkey, __VA_ARGS__) -#define c_declare_Hashmap_stringkey_2(tag, Value) \ - c_declare_Hashmap_stringkey_3(tag, Value, c_defs_destroy) +#define declare_CMap_stringkey_2(tag, Value) \ + declare_CMap_stringkey_3(tag, Value, c_defaultDestroy) -#define c_declare_Hashmap_stringkey_3(tag, Value, valueDestroy) \ - c_declare_Hashmap_10(tag, c_String, Value, valueDestroy, c_string_compareRaw, c_string_hashRaw, c_string_destroy, const char*, c_string_getRaw, c_string_make) +#define declare_CMap_stringkey_3(tag, Value, valueDestroy) \ + declare_CMap_10(tag, CString, Value, valueDestroy, cstring_compareRaw, cstring_hashRaw, cstring_destroy, \ + const char*, cstring_getRaw, cstring_make) -// c_Hashmap full: -#define c_declare_Hashmap_10(tag, Key, Value, valueDestroy, keyCompareRaw, keyHashRaw, keyDestroy, KeyRaw, keyGetRaw, keyInitRaw) \ - c_declare_HashmapEntry(tag, Key, Value, valueDestroy, keyDestroy); \ - c_declare_Vector_3(map_##tag, c_HashmapEntry_##tag, c_hashmapentry_##tag##_destroy); \ +// CMap full: +#define declare_CMap_10(tag, Key, Value, valueDestroy, keyCompareRaw, keyHashRaw, keyDestroy, \ + KeyRaw, keyGetRaw, keyInitRaw) \ + declare_CMapEntry(tag, Key, Value, valueDestroy, keyDestroy); \ + declare_CVector_3(map_##tag, CMapEntry_##tag, chmapentry_##tag##_destroy); \ \ -typedef struct c_Hashmap_##tag { \ - c_Vector_map_##tag _vec; \ +typedef struct CMap_##tag { \ + CVector_map_##tag _vec; \ size_t _size; \ float maxLoadFactor; \ -} c_Hashmap_##tag; \ +} CMap_##tag; \ \ -typedef struct c_hashmap_##tag##_iter_t { \ - c_HashmapEntry_##tag *item, *_end; \ -} c_hashmap_##tag##_iter_t; \ +typedef struct cmap_##tag##_iter_t { \ + CMapEntry_##tag *item, *_end; \ +} cmap_##tag##_iter_t; \ \ -static inline c_Hashmap_##tag c_hashmap_##tag##_init(void) { \ - c_Hashmap_##tag map = c_hashmap_initializer; \ +static inline CMap_##tag cmap_##tag##_init(void) { \ + CMap_##tag map = cmap_initializer; \ return map; \ } \ \ -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) c_hashmapentry_##tag##_destroy(e); \ +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) chmapentry_##tag##_destroy(e); \ } \ - c_vector_map_##tag##_destroy(&self->_vec); \ + cvector_map_##tag##_destroy(&self->_vec); \ } \ \ -static inline size_t c_hashmap_##tag##_reserve(c_Hashmap_##tag* self, size_t size); /* predeclared */ \ +static inline size_t cmap_##tag##_reserve(CMap_##tag* self, size_t size); /* predeclared */ \ \ -static inline void c_hashmap_##tag##_clear(c_Hashmap_##tag* self) { \ - c_Hashmap_##tag map = c_hashmap_initializer; \ - c_hashmap_##tag##_destroy(self); \ +static inline void cmap_##tag##_clear(CMap_##tag* self) { \ + CMap_##tag map = cmap_initializer; \ + cmap_##tag##_destroy(self); \ *self = map; \ } \ \ -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##_swap(CMap_##tag* a, CMap_##tag* b) { \ + cvector_map_##tag##_swap(&a->_vec, &b->_vec); \ + c_swap(size_t, a->_size, b->_size); \ } \ \ -static inline void c_hashmap_##tag##_setMaxLoadFactor(c_Hashmap_##tag* self, float fac) { \ +static inline void cmap_##tag##_setMaxLoadFactor(CMap_##tag* self, float fac) { \ self->maxLoadFactor = fac; \ - if (c_hashmap_size(*self) > c_hashmap_buckets(*self) * fac) \ - c_hashmap_##tag##_reserve(self, 1 + (size_t) (c_hashmap_size(*self) / fac)); \ + if (cmap_size(*self) > cmap_buckets(*self) * fac) \ + cmap_##tag##_reserve(self, 1 + (size_t) (cmap_size(*self) / fac)); \ } \ \ -static inline size_t c_hashmap_##tag##_bucket(c_Hashmap_##tag map, KeyRaw rawKey) { \ - size_t cap = c_vector_capacity(map._vec); \ - size_t idx = c_hashmap_reduce(keyHashRaw(&rawKey, sizeof(Key)), cap); \ +static inline size_t cmap_##tag##_bucket(CMap_##tag map, KeyRaw rawKey) { \ + size_t cap = cvector_capacity(map._vec); \ + size_t idx = cmap_reduce(keyHashRaw(&rawKey, sizeof(Key)), cap); \ size_t first = idx, erased_idx = cap; \ FIBONACCI_DECL; \ do { \ switch (map._vec.data[idx].state) { \ - case c_HashmapEntry_VACANT: \ + case CMapEntry_VACANT: \ return erased_idx != cap ? erased_idx : idx; \ - case c_HashmapEntry_INUSE: \ + case CMapEntry_INUSE: \ if (keyCompareRaw(&map._vec.data[idx].key, &rawKey, sizeof(Key)) != 0) \ break; \ if (erased_idx != cap) { \ - c_defs_swap(c_HashmapEntry_##tag, map._vec.data[erased_idx], map._vec.data[idx]); \ + c_swap(CMapEntry_##tag, map._vec.data[erased_idx], map._vec.data[idx]); \ return erased_idx; \ } \ return idx; \ - case c_HashmapEntry_ERASED: \ + case CMapEntry_ERASED: \ if (erased_idx == cap) erased_idx = idx; \ break; \ } \ @@ -147,81 +149,81 @@ static inline size_t c_hashmap_##tag##_bucket(c_Hashmap_##tag map, KeyRaw rawKey } while (1); \ } \ \ -static inline c_HashmapEntry_##tag* c_hashmap_##tag##_get(c_Hashmap_##tag map, KeyRaw rawKey) { \ - if (c_hashmap_size(map) == 0) return NULL; \ - size_t idx = c_hashmap_##tag##_bucket(map, rawKey); \ - return map._vec.data[idx].state == c_HashmapEntry_INUSE ? &map._vec.data[idx] : NULL; \ +static inline CMapEntry_##tag* cmap_##tag##_get(CMap_##tag map, KeyRaw rawKey) { \ + if (cmap_size(map) == 0) return NULL; \ + size_t idx = cmap_##tag##_bucket(map, rawKey); \ + return map._vec.data[idx].state == CMapEntry_INUSE ? &map._vec.data[idx] : NULL; \ } \ \ -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) 7 + (cap * 1.8)); \ - size_t idx = c_hashmap_##tag##_bucket(*self, rawKey); \ - c_HashmapEntry_##tag* e = &self->_vec.data[idx]; \ +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) 7 + (cap * 1.8)); \ + size_t idx = cmap_##tag##_bucket(*self, rawKey); \ + CMapEntry_##tag* e = &self->_vec.data[idx]; \ e->value = value; \ - e->changed = (e->state == c_HashmapEntry_INUSE); \ - if (e->state != c_HashmapEntry_INUSE) { \ + e->changed = (e->state == CMapEntry_INUSE); \ + if (e->state != CMapEntry_INUSE) { \ e->key = keyInitRaw(rawKey); \ - e->state = c_HashmapEntry_INUSE; \ + e->state = CMapEntry_INUSE; \ ++self->_size; \ } \ return e; \ } \ \ -static inline size_t c_hashmap_##tag##_reserve(c_Hashmap_##tag* self, size_t size) { \ - size_t oldcap = c_vector_capacity(self->_vec), newcap = 1 + (size / 2) * 2; \ +static inline size_t cmap_##tag##_reserve(CMap_##tag* self, size_t size) { \ + size_t oldcap = cvector_capacity(self->_vec), newcap = 1 + (size / 2) * 2; \ if (oldcap >= newcap) return oldcap; \ - c_Vector_map_##tag vec = c_vector_initializer; \ - c_vector_map_##tag##_swap(&self->_vec, &vec); \ - c_vector_map_##tag##_reserve(&self->_vec, newcap); \ + CVector_map_##tag vec = cvector_initializer; \ + cvector_map_##tag##_swap(&self->_vec, &vec); \ + cvector_map_##tag##_reserve(&self->_vec, newcap); \ self->_size = 0; \ - memset(self->_vec.data, 0, sizeof(c_HashmapEntry_##tag) * newcap); \ - c_HashmapEntry_##tag* e = vec.data; \ + memset(self->_vec.data, 0, sizeof(CMapEntry_##tag) * newcap); \ + CMapEntry_##tag* e = vec.data; \ for (size_t i = 0; i < oldcap; ++i, ++e) \ - if (e->state == c_HashmapEntry_INUSE) c_hashmap_##tag##_put(self, keyGetRaw(e->key), e->value); \ + if (e->state == CMapEntry_INUSE) cmap_##tag##_put(self, keyGetRaw(e->key), e->value); \ return newcap; \ } \ \ -static inline bool c_hashmap_##tag##_erase(c_Hashmap_##tag* self, KeyRaw rawKey) { \ - size_t idx = c_hashmap_##tag##_bucket(*self, rawKey); \ - c_HashmapEntry_##tag* e = &self->_vec.data[idx]; \ - if (e->state == c_HashmapEntry_INUSE) { \ - c_hashmapentry_##tag##_destroy(e); \ - e->state = c_HashmapEntry_ERASED; \ +static inline bool cmap_##tag##_erase(CMap_##tag* self, KeyRaw rawKey) { \ + size_t idx = cmap_##tag##_bucket(*self, rawKey); \ + CMapEntry_##tag* e = &self->_vec.data[idx]; \ + if (e->state == CMapEntry_INUSE) { \ + chmapentry_##tag##_destroy(e); \ + e->state = CMapEntry_ERASED; \ --self->_size; \ return true; \ } \ return false; \ } \ \ -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##_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##_next(c_hashmap_##tag##_iter_t it) { \ - do { ++it.item; } while (it.item != it._end && it.item->state != c_HashmapEntry_INUSE); \ +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); \ return it; \ } \ \ -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}; \ +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}; \ return it; \ } \ -typedef Key c_hashmap_##tag##_key_t; \ -typedef Value c_hashmap_##tag##_value_t +typedef Key cmap_##tag##_key_t; \ +typedef Value cmap_##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 c_hashmap_reduce(uint32_t x, uint32_t N) { +static inline uint32_t cmap_reduce(uint32_t x, uint32_t N) { return ((uint64_t) x * (uint64_t) N) >> 32 ; } diff --git a/c_string.h b/c_string.h index 9732ce0c..b659066d 100644 --- a/c_string.h +++ b/c_string.h @@ -20,8 +20,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#ifndef C_STRING__H__ -#define C_STRING__H__ +#ifndef CSTRING__H__ +#define CSTRING__H__ #include #include @@ -30,177 +30,177 @@ #include "c_defs.h" -typedef struct c_String { +typedef struct CString { char* str; -} c_String; +} CString; -static size_t _c_string_null_rep[] = {0, 0, 0}; -#define _c_string_rep(cs) (((size_t *) (cs).str) - 2) +static size_t _cstring_null_rep[] = {0, 0, 0}; +#define _cstring_rep(cs) (((size_t *) (cs).str) - 2) -#define c_string_initializer {(char* ) (_c_string_null_rep + 2)} -#define c_string_size(cs) ((size_t) _c_string_rep(cs)[0]) -#define c_string_capacity(cs) ((size_t) _c_string_rep(cs)[1]) -#define c_string_npos c_defs_npos +#define cstring_initializer {(char* ) (_cstring_null_rep + 2)} +#define cstring_size(cs) ((size_t) _cstring_rep(cs)[0]) +#define cstring_capacity(cs) ((size_t) _cstring_rep(cs)[1]) +#define cstring_npos c_npos -static inline void c_string_reserve(c_String* self, size_t cap) { - size_t len = c_string_size(*self), oldcap = c_string_capacity(*self); +static inline void cstring_reserve(CString* self, size_t cap) { + size_t len = cstring_size(*self), oldcap = cstring_capacity(*self); if (cap > oldcap) { - size_t* rep = (size_t *) realloc(oldcap ? _c_string_rep(*self) : NULL, sizeof(size_t) * 2 + cap + 1); + size_t* rep = (size_t *) realloc(oldcap ? _cstring_rep(*self) : NULL, sizeof(size_t) * 2 + cap + 1); self->str = (char* ) (rep + 2); self->str[ rep[0] = len ] = '\0'; rep[1] = cap; } } -static inline void c_string_destroy(c_String* self) { - if (c_string_capacity(*self)) { - free(_c_string_rep(*self)); +static inline void cstring_destroy(CString* self) { + if (cstring_capacity(*self)) { + free(_cstring_rep(*self)); } } -static inline c_String c_string_init(void) { - c_String cs = c_string_initializer; +static inline CString cstring_init(void) { + CString cs = cstring_initializer; return cs; } -static inline c_String c_string_makeN(const char* str, size_t len) { - c_String cs = c_string_initializer; +static inline CString cstring_makeN(const char* str, size_t len) { + CString cs = cstring_initializer; if (len) { - c_string_reserve(&cs, len); + cstring_reserve(&cs, len); memcpy(cs.str, str, len); - cs.str[ _c_string_rep(cs)[0] = len ] = '\0'; + cs.str[ _cstring_rep(cs)[0] = len ] = '\0'; } return cs; } -static inline c_String c_string_make(const char* str) { - return c_string_makeN(str, strlen(str)); +static inline CString cstring_make(const char* str) { + return cstring_makeN(str, strlen(str)); } -static inline c_String c_string_makeCopy(c_String cs) { - return c_string_makeN(cs.str, c_string_size(cs)); +static inline CString cstring_makeCopy(CString cs) { + return cstring_makeN(cs.str, cstring_size(cs)); } -static inline void c_string_clear(c_String* self) { - c_String cs = c_string_initializer; - c_string_destroy(self); +static inline void cstring_clear(CString* self) { + CString cs = cstring_initializer; + cstring_destroy(self); *self = cs; } -static inline c_String* c_string_assignN(c_String* self, const char* str, size_t len) { +static inline CString* cstring_assignN(CString* self, const char* str, size_t len) { if (len) { - c_string_reserve(self, len); + cstring_reserve(self, len); memmove(self->str, str, len); - self->str[_c_string_rep(*self)[0] = len] = '\0'; + self->str[_cstring_rep(*self)[0] = len] = '\0'; } return self; } -static inline c_String* c_string_assign(c_String* self, const char* str) { - return c_string_assignN(self, str, strlen(str)); +static inline CString* cstring_assign(CString* self, const char* str) { + return cstring_assignN(self, str, strlen(str)); } -static inline c_String* c_string_copy(c_String* self, c_String cs2) { - return c_string_assignN(self, cs2.str, c_string_size(cs2)); +static inline CString* cstring_copy(CString* self, CString cs2) { + return cstring_assignN(self, cs2.str, cstring_size(cs2)); } -static inline c_String* c_string_appendN(c_String* self, const char* str, size_t len) { +static inline CString* cstring_appendN(CString* self, const char* str, size_t len) { if (len) { - size_t oldlen = c_string_size(*self), newlen = oldlen + len; - if (newlen > c_string_capacity(*self)) - c_string_reserve(self, newlen * 5 / 3); + size_t oldlen = cstring_size(*self), newlen = oldlen + len; + if (newlen > cstring_capacity(*self)) + cstring_reserve(self, newlen * 5 / 3); memmove(&self->str[oldlen], str, len); - self->str[_c_string_rep(*self)[0] = newlen] = '\0'; + self->str[_cstring_rep(*self)[0] = newlen] = '\0'; } return self; } -static inline c_String* c_string_append(c_String* self, const char* str) { - return c_string_appendN(self, str, strlen(str)); +static inline CString* cstring_append(CString* self, const char* str) { + return cstring_appendN(self, str, strlen(str)); } -static inline c_String* c_string_appendS(c_String* self, c_String cs2) { - return c_string_appendN(self, cs2.str, c_string_size(cs2)); +static inline CString* cstring_appendS(CString* self, CString cs2) { + return cstring_appendN(self, cs2.str, cstring_size(cs2)); } -static inline void _c_string_internalMove(c_String* self, size_t pos1, size_t pos2) { +static inline void _cstring_internalMove(CString* self, size_t pos1, size_t pos2) { if (pos1 == pos2) return; - size_t len = c_string_size(*self), newlen = len + pos2 - pos1; - if (newlen > c_string_capacity(*self)) - c_string_reserve(self, newlen * 5 / 3); + size_t len = cstring_size(*self), newlen = len + pos2 - pos1; + if (newlen > cstring_capacity(*self)) + cstring_reserve(self, newlen * 5 / 3); memmove(&self->str[pos2], &self->str[pos1], len - pos1); - self->str[_c_string_rep(*self)[0] = newlen] = '\0'; + self->str[_cstring_rep(*self)[0] = newlen] = '\0'; } -static inline void c_string_insertN(c_String* self, size_t pos, const char* str, size_t n) { - char* xstr = (char *) memcpy(n > c_defs_max_alloca ? malloc(n) : alloca(n), str, n); - _c_string_internalMove(self, pos, pos + n); +static inline void cstring_insertN(CString* self, size_t pos, const char* str, size_t n) { + char* xstr = (char *) memcpy(n > c_max_alloca ? malloc(n) : alloca(n), str, n); + _cstring_internalMove(self, pos, pos + n); memcpy(&self->str[pos], xstr, n); - if (n > c_defs_max_alloca) free(xstr); + if (n > c_max_alloca) free(xstr); } -static inline void c_string_insert(c_String* self, size_t pos, const char* str) { - c_string_insertN(self, pos, str, strlen(str)); +static inline void cstring_insert(CString* self, size_t pos, const char* str) { + cstring_insertN(self, pos, str, strlen(str)); } -static inline void c_string_erase(c_String* self, size_t pos, size_t n) { - size_t len = c_string_size(*self); +static inline void cstring_erase(CString* self, size_t pos, size_t n) { + size_t len = cstring_size(*self); if (len) { memmove(&self->str[pos], &self->str[pos + n], len - (pos + n)); - self->str[_c_string_rep(*self)[0] -= n] = '\0'; + self->str[_cstring_rep(*self)[0] -= n] = '\0'; } } -static inline size_t c_string_findN(c_String cs, size_t pos, const char* needle, size_t n); +static inline size_t cstring_findN(CString cs, size_t pos, const char* needle, size_t n); -static inline size_t c_string_replaceN(c_String* self, size_t pos, const char* s1, size_t n1, const char* s2, size_t n2) { - size_t pos2 = c_string_findN(*self, pos, s1, n1); - if (pos2 == c_string_npos) return c_string_npos; - char* xs2 = (char *) memcpy(n2 > c_defs_max_alloca ? malloc(n2) : alloca(n2), s2, n2); - _c_string_internalMove(self, pos2 + n1, pos2 + n2); +static inline size_t cstring_replaceN(CString* self, size_t pos, const char* s1, size_t n1, const char* s2, size_t n2) { + size_t pos2 = cstring_findN(*self, pos, s1, n1); + if (pos2 == cstring_npos) return cstring_npos; + char* xs2 = (char *) memcpy(n2 > c_max_alloca ? malloc(n2) : alloca(n2), s2, n2); + _cstring_internalMove(self, pos2 + n1, pos2 + n2); memcpy(&self->str[pos2], xs2, n2); - if (n2 > c_defs_max_alloca) free(xs2); + if (n2 > c_max_alloca) free(xs2); return pos2; } -static inline size_t c_string_replace(c_String* self, size_t pos, const char* s1, const char* s2) { - return c_string_replaceN(self, pos, s1, strlen(s1), s2, strlen(s2)); +static inline size_t cstring_replace(CString* self, size_t pos, const char* s1, const char* s2) { + return cstring_replaceN(self, pos, s1, strlen(s1), s2, strlen(s2)); } -static inline char c_string_back(c_String cs) { - return cs.str[c_string_size(cs) - 1]; +static inline char cstring_back(CString cs) { + return cs.str[cstring_size(cs) - 1]; } -static inline c_String* c_string_push(c_String* self, char value) { - return c_string_appendN(self, &value, 1); +static inline CString* cstring_push(CString* self, char value) { + return cstring_appendN(self, &value, 1); } -static inline void c_string_pop(c_String* self) { - --_c_string_rep(*self)[0]; +static inline void cstring_pop(CString* self) { + --_cstring_rep(*self)[0]; } /* readonly */ -static inline bool c_string_empty(c_String cs) { - return c_string_size(cs) == 0; +static inline bool cstring_empty(CString cs) { + return cstring_size(cs) == 0; } -static inline bool c_string_equals(c_String cs1, const char* str) { +static inline bool cstring_equals(CString cs1, const char* str) { return strcmp(cs1.str, str) == 0; } -static inline bool c_string_equalsS(c_String cs1, c_String cs2) { +static inline bool cstring_equalsS(CString cs1, CString cs2) { return strcmp(cs1.str, cs2.str) == 0; } -static inline char* c_string_strnstr(c_String cs, size_t pos, const char* needle, size_t n) { +static inline char* cstring_strnstr(CString cs, size_t pos, const char* needle, size_t n) { char *x = cs.str + pos, // haystack - *z = cs.str + c_string_size(cs) - n + 1; + *z = cs.str + cstring_size(cs) - n + 1; if (x >= z) return NULL; ptrdiff_t sum = 0; @@ -215,30 +215,30 @@ static inline char* c_string_strnstr(c_String cs, size_t pos, const char* needle return NULL; } -static inline size_t c_string_findN(c_String cs, size_t pos, const char* needle, size_t n) { - char* res = c_string_strnstr(cs, pos, needle, n); - return res ? res - cs.str : c_string_npos; +static inline size_t cstring_findN(CString cs, size_t pos, const char* needle, size_t n) { + char* res = cstring_strnstr(cs, pos, needle, n); + return res ? res - cs.str : cstring_npos; } -static inline size_t c_string_find(c_String cs, size_t pos, const char* needle) { +static inline size_t cstring_find(CString cs, size_t pos, const char* needle) { char* res = strstr(cs.str + pos, needle); - return res ? res - cs.str : c_string_npos; + return res ? res - cs.str : cstring_npos; } -static inline char* c_string_splitFirst(const char* delimiters, c_String cs) { +static inline char* cstring_splitFirst(const char* delimiters, CString cs) { return strtok(cs.str, delimiters); } -static inline char* c_string_splitNext(const char* delimiters) { +static inline char* cstring_splitNext(const char* delimiters) { return strtok(NULL, delimiters); } -// c_Vector / c_Hashmap API functions: +// CVector / CMap API functions: -#define c_string_getRaw(x) ((x).str) -static inline uint32_t c_string_hashRaw(const char** str, size_t sz_ignored) { return c_defs_murmurHash(*str, strlen(*str)); } -static inline int c_string_compareRaw(c_String* self, const char** str, size_t sz_ignored) { return strcmp(self->str, *str); } +#define cstring_getRaw(x) ((x).str) +static inline uint32_t cstring_hashRaw(const char** str, size_t sz_ignored) { return c_murmurHash(*str, strlen(*str)); } +static inline int cstring_compareRaw(CString* self, const char** str, size_t sz_ignored) { return strcmp(self->str, *str); } #endif diff --git a/c_vector.h b/c_vector.h index cd05f3bd..ff70483f 100644 --- a/c_vector.h +++ b/c_vector.h @@ -20,141 +20,141 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -#ifndef C_VECTOR__H__ -#define C_VECTOR__H__ +#ifndef CVECTOR__H__ +#define CVECTOR__H__ #include #include #include "c_defs.h" -#define c_vector_initializer {NULL} -#define c_vector_size(cv) _c_vector_safe_size((cv).data) -#define c_vector_capacity(cv) _c_vector_safe_capacity((cv).data) -#define c_vector_empty(cv) (_c_vector_safe_size((cv).data) == 0) +#define cvector_initializer {NULL} +#define cvector_size(cv) _cvector_safe_size((cv).data) +#define cvector_capacity(cv) _cvector_safe_capacity((cv).data) +#define cvector_empty(cv) (_cvector_safe_size((cv).data) == 0) -#define c_declare_Vector(...) c_defs_MACRO_OVERLOAD(c_declare_Vector, __VA_ARGS__) -#define c_declare_Vector_2(tag, Value) \ - c_declare_Vector_3(tag, Value, c_defs_destroy) -#define c_declare_Vector_3(tag, Value, valueDestroy) \ - c_declare_Vector_5(tag, Value, valueDestroy, memcmp, Value) -#define c_declare_Vector_4(tag, Value, valueDestroy, valueCompare) \ - c_declare_Vector_5(tag, Value, valueDestroy, valueCompare, Value) -#define c_declare_Vector_string(tag) \ - c_declare_Vector_5(tag, c_String, c_string_destroy, c_string_compareRaw, const char*) +#define declare_CVector(...) c_MACRO_OVERLOAD(declare_CVector, __VA_ARGS__) +#define declare_CVector_2(tag, Value) \ + declare_CVector_3(tag, Value, c_defaultDestroy) +#define declare_CVector_3(tag, Value, valueDestroy) \ + declare_CVector_5(tag, Value, valueDestroy, memcmp, Value) +#define declare_CVector_4(tag, Value, valueDestroy, valueCompare) \ + declare_CVector_5(tag, Value, valueDestroy, valueCompare, Value) +#define declare_CVector_string(tag) \ + declare_CVector_5(tag, CString, cstring_destroy, cstring_compareRaw, const char*) -#define c_declare_Vector_5(tag, Value, valueDestroy, valueCompareRaw, ValueRaw) \ -typedef struct c_Vector_##tag { \ +#define declare_CVector_5(tag, Value, valueDestroy, valueCompareRaw, ValueRaw) \ +typedef struct CVector_##tag { \ Value* data; \ -} c_Vector_##tag; \ +} CVector_##tag; \ \ -typedef struct c_vector_##tag##_iter_t { \ +typedef struct cvector_##tag##_iter_t { \ Value* item; \ -} c_vector_##tag##_iter_t; \ +} cvector_##tag##_iter_t; \ \ -static inline c_Vector_##tag c_vector_##tag##_init(void) { \ - c_Vector_##tag cv = c_vector_initializer; \ +static inline CVector_##tag cvector_##tag##_init(void) { \ + CVector_##tag cv = cvector_initializer; \ return cv; \ } \ \ -static inline void c_vector_##tag##_swap(c_Vector_##tag* a, c_Vector_##tag* b) { \ +static inline void cvector_##tag##_swap(CVector_##tag* a, CVector_##tag* b) { \ Value* data = a->data; a->data = b->data; b->data = data; \ } \ \ -static inline void c_vector_##tag##_destroy(c_Vector_##tag* self) { \ +static inline void cvector_##tag##_destroy(CVector_##tag* self) { \ Value* p = self->data; \ - size_t i = 0, n = c_vector_size(*self); \ + size_t i = 0, n = cvector_size(*self); \ for (; i < n; ++p, ++i) valueDestroy(p); \ - free(_c_vector_alloced(self->data)); \ + free(_cvector_alloced(self->data)); \ } \ \ -static inline void c_vector_##tag##_reserve(c_Vector_##tag* self, size_t cap) { \ - if (cap > c_vector_capacity(*self)) { \ - size_t len = c_vector_size(*self); \ - size_t* rep = (size_t *) realloc(_c_vector_alloced(self->data), 2 * sizeof(size_t) + cap * sizeof(Value)); \ +static inline void cvector_##tag##_reserve(CVector_##tag* self, size_t cap) { \ + if (cap > cvector_capacity(*self)) { \ + size_t len = cvector_size(*self); \ + size_t* rep = (size_t *) realloc(_cvector_alloced(self->data), 2 * sizeof(size_t) + cap * sizeof(Value)); \ self->data = (Value *) (rep + 2); \ rep[0] = len; \ rep[1] = cap; \ } \ } \ \ -static inline void c_vector_##tag##_clear(c_Vector_##tag* self) { \ - c_Vector_##tag cv = c_vector_initializer; \ - c_vector_##tag##_destroy(self); \ +static inline void cvector_##tag##_clear(CVector_##tag* self) { \ + CVector_##tag cv = cvector_initializer; \ + cvector_##tag##_destroy(self); \ *self = cv; \ } \ \ \ -static inline void c_vector_##tag##_push(c_Vector_##tag* self, Value value) { \ - size_t newsize = c_vector_size(*self) + 1; \ - if (newsize > c_vector_capacity(*self)) \ - c_vector_##tag##_reserve(self, 7 + newsize * 5 / 3); \ - self->data[c_vector_size(*self)] = value; \ - _c_vector_size(*self) = newsize; \ +static inline void cvector_##tag##_push(CVector_##tag* self, Value value) { \ + size_t newsize = cvector_size(*self) + 1; \ + if (newsize > cvector_capacity(*self)) \ + cvector_##tag##_reserve(self, 7 + newsize * 5 / 3); \ + self->data[cvector_size(*self)] = value; \ + _cvector_size(*self) = newsize; \ } \ \ -static inline void c_vector_##tag##_insert(c_Vector_##tag* self, size_t pos, Value value) { \ - c_vector_##tag##_push(self, value); \ - size_t len = c_vector_size(*self); \ +static inline void cvector_##tag##_insert(CVector_##tag* self, size_t pos, Value value) { \ + cvector_##tag##_push(self, value); \ + size_t len = cvector_size(*self); \ memmove(&self->data[pos + 1], &self->data[pos], (len - pos - 1) * sizeof(Value)); \ self->data[pos] = value; \ } \ \ -static inline void c_vector_##tag##_erase(c_Vector_##tag* self, size_t pos, size_t size) { \ - size_t len = c_vector_size(*self); \ +static inline void cvector_##tag##_erase(CVector_##tag* self, size_t pos, size_t size) { \ + size_t len = cvector_size(*self); \ if (len) { \ Value* p = &self->data[pos], *start = p, *end = p + size; \ while (p != end) valueDestroy(p++); \ memmove(start, end, (len - pos - size) * sizeof(Value)); \ - _c_vector_size(*self) -= size; \ + _cvector_size(*self) -= size; \ } \ } \ \ \ -static inline size_t c_vector_##tag##_find(c_Vector_##tag cv, ValueRaw rawValue) { \ - size_t n = c_vector_size(cv); \ +static inline size_t cvector_##tag##_find(CVector_##tag cv, ValueRaw rawValue) { \ + size_t n = cvector_size(cv); \ for (size_t i = 0; i < n; ++i) \ if (valueCompareRaw(&cv.data[i], &rawValue, sizeof(Value)) == 0) return i; \ - return c_defs_npos; \ + return c_npos; \ } \ \ \ -static inline Value c_vector_##tag##_back(c_Vector_##tag cv) { \ - return cv.data[_c_vector_size(cv) - 1]; \ +static inline Value cvector_##tag##_back(CVector_##tag cv) { \ + return cv.data[_cvector_size(cv) - 1]; \ } \ \ -static inline void c_vector_##tag##_pop(c_Vector_##tag* self) { \ - valueDestroy(&self->data[_c_vector_size(*self) - 1]); \ - --_c_vector_size(*self); \ +static inline void cvector_##tag##_pop(CVector_##tag* self) { \ + valueDestroy(&self->data[_cvector_size(*self) - 1]); \ + --_cvector_size(*self); \ } \ \ -static inline c_vector_##tag##_iter_t c_vector_##tag##_begin(c_Vector_##tag vec) { \ - c_vector_##tag##_iter_t it = {vec.data}; \ +static inline cvector_##tag##_iter_t cvector_##tag##_begin(CVector_##tag vec) { \ + cvector_##tag##_iter_t it = {vec.data}; \ return it; \ } \ \ -static inline c_vector_##tag##_iter_t c_vector_##tag##_next(c_vector_##tag##_iter_t it) { \ +static inline cvector_##tag##_iter_t cvector_##tag##_next(cvector_##tag##_iter_t it) { \ ++it.item; \ return it; \ } \ \ -static inline c_vector_##tag##_iter_t c_vector_##tag##_end(c_Vector_##tag vec) { \ - c_vector_##tag##_iter_t it = {vec.data + c_vector_size(vec)}; \ +static inline cvector_##tag##_iter_t cvector_##tag##_end(CVector_##tag vec) { \ + cvector_##tag##_iter_t it = {vec.data + cvector_size(vec)}; \ return it; \ } \ -typedef Value c_vector_##tag##_value_t +typedef Value cvector_##tag##_value_t -#define _c_vector_size(cv) ((size_t *)(cv).data)[-2] -#define _c_vector_capacity(cv) ((size_t *)(cv).data)[-1] +#define _cvector_size(cv) ((size_t *)(cv).data)[-2] +#define _cvector_capacity(cv) ((size_t *)(cv).data)[-1] -static inline size_t* _c_vector_alloced(void* data) { +static inline size_t* _cvector_alloced(void* data) { return data ? ((size_t *) data) - 2 : NULL; } -static inline size_t _c_vector_safe_size(const void* data) { +static inline size_t _cvector_safe_size(const void* data) { return data ? ((const size_t *) data)[-2] : 0; } -static inline size_t _c_vector_safe_capacity(const void* data) { +static inline size_t _cvector_safe_capacity(const void* data) { return data ? ((const size_t *) data)[-1] : 0; } diff --git a/cmap_test.c b/cmap_test.c index c02b25cd..d96c173c 100644 --- a/cmap_test.c +++ b/cmap_test.c @@ -24,14 +24,14 @@ #include #include -#include "c_hashmap.h" -#include "c_string.h" +#include "cmap.h" +#include "cstring.h" -c_declare_Vector_string(s); -c_declare_Hashmap_stringkey(ss, c_String, c_string_destroy); -c_declare_Hashmap_stringkey(si, int); -c_declare_Hashmap(id, uint64_t, double); +declare_CVector_string(s); +declare_CMap_stringkey(ss, CString, cstring_destroy); +declare_CMap_stringkey(si, int); +declare_CMap(id, uint64_t, double); // like fgets, but removes any newline @@ -46,7 +46,7 @@ char *fgetstr(char *string, int n, FILE *stream) return string; } -int read_words(c_Hashmap_si* map) +int read_words(CMap_si* map) { FILE * fp; # define bufferLength 1024 @@ -61,7 +61,7 @@ int read_words(c_Hashmap_si* map) while (fgetstr(line, bufferLength, fp)) { ++i; if (i < 10) printf("%zu: %s\n", i, line); - c_hashmap_si_put(map, line, i); + cmap_si_put(map, line, i); } fclose(fp); @@ -69,20 +69,20 @@ int read_words(c_Hashmap_si* map) } void stringSpeed(int limit) { - c_String s = c_string_initializer; + CString s = cstring_initializer; char ch[2] = {0, 0}; size_t x = 0; size_t p = 0; - for (int n = 0; n < limit; ++n) { ch[0] = 'A' + (rand() % 26); c_string_append(&s, ch); } + for (int n = 0; n < limit; ++n) { ch[0] = 'A' + (rand() % 26); cstring_append(&s, ch); } const char* search = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"; - c_string_append(&s, search); + cstring_append(&s, search); clock_t before = clock(); for (int n = 0; n < limit; ++n) { - p = c_string_find(s, 0, search + (n % 100)); - if (p != c_string_npos) x += p; + p = cstring_find(s, 0, search + (n % 100)); + if (p != cstring_npos) x += p; } clock_t diff = clock() - before; - printf("string length = %llu / %llu, sum %llu speed: %f\n", c_string_size(s), c_string_capacity(s), x, 1.0 * diff / CLOCKS_PER_SEC); + printf("string length = %llu / %llu, sum %llu speed: %f\n", cstring_size(s), cstring_capacity(s), x, 1.0 * diff / CLOCKS_PER_SEC); } int main() @@ -91,73 +91,73 @@ int main() stringSpeed(20000); - c_String cs = c_string_make("one-nine-three-seven-five"); + CString cs = cstring_make("one-nine-three-seven-five"); printf("%s.\n", cs.str); - c_string_insert(&cs, 3, "-two"); + cstring_insert(&cs, 3, "-two"); printf("%s.\n", cs.str); - c_string_erase(&cs, 7, 5); // -nine + cstring_erase(&cs, 7, 5); // -nine printf("%s.\n", cs.str); - c_string_replace(&cs, 0, "seven", "four"); + cstring_replace(&cs, 0, "seven", "four"); printf("%s.\n", cs.str); - printf("found: %s\n", cs.str + c_string_find(cs, 0, "four")); - c_string_assign(&cs, "one two three four five six seven"); - c_string_replace(&cs, 0, "four", "F-O-U-R"); + printf("found: %s\n", cs.str + cstring_find(cs, 0, "four")); + cstring_assign(&cs, "one two three four five six seven"); + cstring_replace(&cs, 0, "four", "F-O-U-R"); printf("replace: %s\n", cs.str); - c_Hashmap_si words = c_hashmap_initializer; + CMap_si words = cmap_initializer; printf("read words\n"); read_words(&words); - c_HashmapEntry_si* num = NULL; - num = c_hashmap_si_get(words, "hello"); + CMapEntry_si* num = NULL; + num = cmap_si_get(words, "hello"); if (num) printf("%s: %d\n", num->key.str, num->value); - num = c_hashmap_si_get(words, "funny"); + num = cmap_si_get(words, "funny"); if (num) printf("%s: %d\n", num->key.str, num->value); - printf("words size: %llu, capacity %llu\n", c_hashmap_size(words), c_hashmap_buckets(words)); - c_hashmap_si_clear(&words); + printf("words size: %llu, capacity %llu\n", cmap_size(words), cmap_buckets(words)); + cmap_si_clear(&words); - c_Vector_s strv = c_vector_initializer; - c_String myday = c_string_make("my day"); - c_string_assign(&myday, "great"); + CVector_s strv = cvector_initializer; + CString myday = cstring_make("my day"); + cstring_assign(&myday, "great"); - c_vector_s_push(&strv, c_string_make("E0")); - c_vector_s_push(&strv, c_string_make("E1")); - c_vector_s_push(&strv, c_string_make("E2")); + cvector_s_push(&strv, cstring_make("E0")); + cvector_s_push(&strv, cstring_make("E1")); + cvector_s_push(&strv, cstring_make("E2")); printf(" element %d: %s\n", 1, strv.data[1].str); - c_foreach (i, c_vector_s, strv) { + c_foreach (i, cvector_s, strv) { printf(" %s\n", i.item->str); } - for (i = 0; i < c_vector_size(strv); ++i) { + for (i = 0; i < cvector_size(strv); ++i) { printf(" %s\n", strv.data[i].str); } - c_vector_s_destroy(&strv); + cvector_s_destroy(&strv); - c_Hashmap_ss smap = c_hashmap_initializer; - c_hashmap_ss_put(&smap, "KEY1", c_string_make("VAL1")); - c_hashmap_ss_put(&smap, "KEY2", c_string_make("VAL2")); - c_hashmap_ss_put(&smap, "hello", c_string_makeCopy(myday)); - c_string_destroy(&myday); + CMap_ss smap = cmap_initializer; + cmap_ss_put(&smap, "KEY1", cstring_make("VAL1")); + cmap_ss_put(&smap, "KEY2", cstring_make("VAL2")); + cmap_ss_put(&smap, "hello", cstring_makeCopy(myday)); + cstring_destroy(&myday); - c_foreach (i, c_hashmap_ss, smap) + c_foreach (i, cmap_ss, smap) printf(" %s: %s\n", i.item->key.str, i.item->value.str); - c_hashmap_ss_destroy(&smap); + cmap_ss_destroy(&smap); - c_Hashmap_id mymap = c_hashmap_initializer; + CMap_id mymap = cmap_initializer; for (i = 0; i < 600000; ++i) - c_hashmap_id_put(&mymap, i*i, i); + cmap_id_put(&mymap, i*i, i); for (i = 1000; i < 1010; ++i) - printf("lookup %d: %f\n", i*i, c_hashmap_id_get(mymap, i*i)->value); + printf("lookup %d: %f\n", i*i, cmap_id_get(mymap, i*i)->value); - c_HashmapEntry_id* me = c_hashmap_id_get(mymap, 10000); + CMapEntry_id* me = cmap_id_get(mymap, 10000); printf("changed: %d %f\n", me->changed, me->value); - c_hashmap_id_put(&mymap, 10000, 101.2); + cmap_id_put(&mymap, 10000, 101.2); printf("changed: %d %f\n", me->changed, me->value); - c_hashmap_id_destroy(&mymap); + cmap_id_destroy(&mymap); } -- cgit v1.2.3