diff options
| author | Tyge Løvset <[email protected]> | 2021-12-19 12:21:44 +0100 |
|---|---|---|
| committer | Tyge Løvset <[email protected]> | 2021-12-19 12:21:44 +0100 |
| commit | 92b950333c6c7002bdbf1b60af44a249dc0cef9c (patch) | |
| tree | 4b1acfcdba0bd940f829c53910587e27b5e0af90 /docs/cmap_api.md | |
| parent | 183a89859ba9914ee0546e4482b40be199e52292 (diff) | |
| download | STC-modified-92b950333c6c7002bdbf1b60af44a249dc0cef9c.tar.gz STC-modified-92b950333c6c7002bdbf1b60af44a249dc0cef9c.zip | |
First commit for Version 3 of STC. Main changes are consistent rename of '_del' to '_drop' and '_compare' to '_cmp'.
Also i_key_ref (earlier i_key_sptr) and i_val_ref replaced by more general i_key_bind/i_val_bind.
Diffstat (limited to 'docs/cmap_api.md')
| -rw-r--r-- | docs/cmap_api.md | 161 |
1 files changed, 86 insertions, 75 deletions
diff --git a/docs/cmap_api.md b/docs/cmap_api.md index 0fec365c..e2cb668f 100644 --- a/docs/cmap_api.md +++ b/docs/cmap_api.md @@ -21,13 +21,13 @@ See the c++ class [std::unordered_map](https://en.cppreference.com/w/cpp/contain #define i_val // value: REQUIRED #define i_cmp // three-way compare two i_keyraw*: REQUIRED IF i_keyraw is non-integral type #define i_equ // equality comparison two i_keyraw*: ALTERNATIVE to i_cmp -#define i_keydel // destroy key func - defaults to empty destruct +#define i_keydrop // destroy key func - defaults to empty destruct #define i_keyraw // convertion "raw" type - defaults to i_key -#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy +#define i_keyfrom // convertion func i_keyraw => i_key - defaults to plain copy #define i_keyto // convertion func i_key* => i_keyraw - defaults to plain copy -#define i_valdel // destroy value func - defaults to empty destruct +#define i_valdrop // destroy value func - defaults to empty destruct #define i_valraw // convertion "raw" type - defaults to i_val -#define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy +#define i_valfrom // convertion func i_valraw => i_val - defaults to plain copy #define i_valto // convertion func i_val* => i_valraw - defaults to plain copy #define i_tag // defaults to i_key #include <stc/cmap.h> @@ -47,7 +47,7 @@ void cmap_X_max_load_factor(cmap_X* self, float max_load); bool cmap_X_reserve(cmap_X* self, size_t size); void cmap_X_shrink_to_fit(cmap_X* self); void cmap_X_swap(cmap_X* a, cmap_X* b); -void cmap_X_del(cmap_X* self); // destructor +void cmap_X_drop(cmap_X* self); // destructor size_t cmap_X_size(cmap_X map); size_t cmap_X_capacity(cmap_X map); // buckets * max_load_factor @@ -207,15 +207,15 @@ typedef struct { int x, y, z; } Vec3i; int main() { // Define map with defered destruct - c_autovar (cmap_vi vecs = cmap_vi_init(), cmap_vi_del(&vecs)) + c_autovar (cmap_vi vecs = cmap_vi_init(), cmap_vi_drop(&vecs)) { cmap_vi_insert(&vecs, (Vec3i){100, 0, 0}, 1); cmap_vi_insert(&vecs, (Vec3i){ 0, 100, 0}, 2); cmap_vi_insert(&vecs, (Vec3i){ 0, 0, 100}, 3); cmap_vi_insert(&vecs, (Vec3i){100, 100, 100}, 4); - c_foreach (i, cmap_vi, vecs) - printf("{ %3d, %3d, %3d }: %d\n", i.ref->first.x, i.ref->first.y, i.ref->first.z, i.ref->second); + c_forpair (vec, num, cmap_vi, vecs) + printf("{ %3d, %3d, %3d }: %d\n", _.vec.x, _.vec.y, _.vec.z, _.num); } } ``` @@ -240,15 +240,15 @@ typedef struct { int x, y, z; } Vec3i; int main() { - c_autovar (cmap_iv vecs = cmap_iv_init(), cmap_iv_del(&vecs)) + c_auto (cmap_iv, vecs) // shorthand for c_autovar with _init(), _drop(). { cmap_iv_insert(&vecs, 1, (Vec3i){100, 0, 0}); cmap_iv_insert(&vecs, 2, (Vec3i){ 0, 100, 0}); cmap_iv_insert(&vecs, 3, (Vec3i){ 0, 0, 100}); cmap_iv_insert(&vecs, 4, (Vec3i){100, 100, 100}); - c_foreach (i, cmap_iv, vecs) - printf("%d: { %3d, %3d, %3d }\n", i.ref->first, i.ref->second.x, i.ref->second.y, i.ref->second.z); + c_forpair (num, vec, cmap_iv, vecs) + printf("%d: { %3d, %3d, %3d }\n", _.num_, _.vec.x, _.vec.y, _.vec.z); } } ``` @@ -270,45 +270,56 @@ typedef struct { cstr country; } Viking; -static bool Viking_equalto(const Viking* a, const Viking* b) { +#define Viking_init() ((Viking){cstr_null, cstr_null}) + +static inline bool RViking_equalto(const Viking* a, const Viking* b) { return cstr_equals_s(a->name, b->name) && cstr_equals_s(a->country, b->country); } -static uint32_t Viking_hash(const Viking* a, int ignored) { +static inline uint32_t RViking_hash(const Viking* a, int ignored) { return c_strhash(a->name.str) ^ (c_strhash(a->country.str) >> 15); } -static void Viking_del(Viking* v) { - c_del(cstr, &v->name, &v->country); +static inline Viking Viking_clone(Viking v) { + v.name = cstr_clone(v.name); + v.country = cstr_clone(v.country); +} + +void inline Viking_drop(Viking* vk) { + cstr_drop(&vk->name); + cstr_drop(&vk->country); } -#define i_key Viking +#define i_type Vikings +#define i_key_bind Viking #define i_val int -#define i_equ Viking_equalto -#define i_hash Viking_hash -#define i_del Viking_del -#define i_tag vk +// i_key_bind auto-binds: +// #define i_equ RViking_equalto +// #define i_hash RViking_hash +// #define i_keyfrom Viking_clone +// #define i_drop Viking_drop #include <stc/cmap.h> int main() { // Use a HashMap to store the vikings' health points. - cmap_vk vikings = cmap_vk_init(); - - cmap_vk_insert(&vikings, (Viking){cstr_new("Einar"), cstr_new("Norway")}, 25); - cmap_vk_insert(&vikings, (Viking){cstr_new("Olaf"), cstr_new("Denmark")}, 24); - cmap_vk_insert(&vikings, (Viking){cstr_new("Harald"), cstr_new("Iceland")}, 12); - cmap_vk_insert(&vikings, (Viking){cstr_new("Einar"), cstr_new("Denmark")}, 21); - - Viking lookup = (Viking){cstr_new("Einar"), cstr_new("Norway")}; - printf("Lookup: Einar of Norway has %d hp\n\n", *cmap_vk_at(&vikings, lookup)); - Viking_del(&lookup); - - // Print the status of the vikings. - c_foreach (i, cmap_vk, vikings) { - printf("%s of %s has %d hp\n", i.ref->first.name.str, i.ref->first.country.str, i.ref->second); + c_auto (Vikings, vikings) // uses Vikings_init(), Vikings_drop() + { + Vikings_insert(&vikings, (Viking){cstr_new("Einar"), cstr_new("Norway")}, 25); + Vikings_insert(&vikings, (Viking){cstr_new("Olaf"), cstr_new("Denmark")}, 24); + Vikings_insert(&vikings, (Viking){cstr_new("Harald"), cstr_new("Iceland")}, 12); + Vikings_insert(&vikings, (Viking){cstr_new("Einar"), cstr_new("Denmark")}, 21); + + c_auto (Viking, lookup) { + lookup = (Viking){cstr_new("Einar"), cstr_new("Norway")}; + printf("Lookup: Einar of Norway has %d hp\n\n", *Vikings_at(&vikings, lookup)); + } + + // Print the status of the vikings. + c_forpair (viking, hp, Vikings, vikings) { + printf("%s of %s has %d hp\n", _.viking.name.str, _.viking.country.str, _.hp); + } } - cmap_vk_del(&vikings); } ``` Output: @@ -326,65 +337,65 @@ to add "raw" type entries (otherwise compile error): ```c #include <stc/cstr.h> -typedef struct { +typedef struct Viking { cstr name; cstr country; } Viking; -static void Viking_del(Viking* v) { - c_del(cstr, &v->name, &v->country); +static inline void Viking_drop(Viking* v) { + c_drop(cstr, &v->name, &v->country); } -// Define a "raw" type that does not need allocations. -// Define equals, hash, fromraw, toraw functions: +// Define Viking raw struct with hash, equalto, and convertion functions between Viking and RViking structs: -typedef struct { +typedef struct RViking { const char* name; const char* country; } RViking; -static bool RViking_equalto(const RViking* r1, const RViking* r2) - { return !strcmp(r1->name, r2->name) && !strcmp(r1->country, r2->country); } - -static uint32_t RViking_hash(const RViking* r, int ignored) - { return c_strhash(r->name) ^ (c_strhash(r->country) >> 15); } - -static Viking Viking_fromR(RViking r) - { return (Viking){cstr_from(r.name), cstr_from(r.country)}; } +static inline uint64_t RViking_hash(const RViking* raw, size_t ignore) { + uint64_t hash = c_strhash(raw->name) ^ (c_strhash(raw->country) >> 15); + return hash; +} +static inline bool RViking_equalto(const RViking* rx, const RViking* ry) { + return strcmp(rx->name, ry->name) == 0 && strcmp(rx->country, ry->country) == 0; +} -static RViking Viking_toR(const Viking* v) - { return (RViking){v->name.str, v->country.str}; } +static inline Viking Viking_from(RViking raw) { + return (Viking){cstr_from(raw.name), cstr_from(raw.country)}; +} +static inline RViking Viking_toraw(const Viking* vk) { + return (RViking){vk->name.str, vk->country.str}; +} -#define i_key Viking -#define i_val int -#define i_keydel Viking_del -#define i_keyraw RViking -#define i_equ RViking_equalto -#define i_hash RViking_hash -#define i_keyfrom Viking_fromR -#define i_keyto Viking_toR -#define i_tag vk +// With this in place, we define the Viking => int hash map type: +#define i_type Vikings +#define i_key_bind Viking +#define i_val int +#define i_keyraw RViking +// i_key_bind macro will make these functions auto-bind: +// #define i_hash RViking_hash +// #define i_equ RViking_equalto +// #define i_keyfrom Viking_from // uses _from because i_keyraw is defined +// #define i_keyto Viking_toraw +// #define i_keydrop Viking_drop #include <stc/cmap.h> int main() { - c_auto (cmap_vk, vikings) // RAII - { - // Insert works as before, takes a constructed Viking object - cmap_vk_insert(&vikings, (Viking){cstr_new("Einar"), cstr_new("Norway")}, 25); - cmap_vk_insert(&vikings, (Viking){cstr_new("Olaf"), cstr_new("Denmark")}, 24); - - // Emplace is simpler to use now - takes rawkey argument - cmap_vk_emplace(&vikings, (RViking){"Harald", "Iceland"}, 12); - cmap_vk_emplace(&vikings, (RViking){"Einar", "Denmark"}, 21); + c_auto (Vikings, vikings) { + c_apply_pair(Vikings, emplace, &vikings, { + {{"Einar", "Norway"}, 20}, + {{"Olaf", "Denmark"}, 24}, + {{"Harald", "Iceland"}, 12}, + }); + Vikings_emplace_or_assign(&vikings, (RViking){"Bjorn", "Sweden"}, 10); - // Lookup also uses rawkey args, no need construct/destruct key: - printf("Lookup: Einar of Norway has %d hp\n\n", *cmap_vk_at(&vikings, (RViking){"Einar", "Norway"})); + Vikings_value *einar = Vikings_find(&vikings, (RViking){"Einar", "Norway"}).ref; + if (einar) einar->second += 3; // add 3 hp points to Einar - // Print the status of the vikings. - c_foreach (i, cmap_vk, vikings) { - printf("%s of %s has %d hp\n", i.ref->first.name.str, - i.ref->first.country.str, i.ref->second); + c_forpair (viking, health, Vikings, vikings) { + printf("%s of %s has %d hp\n", _.viking.name.str, _.viking.country.str, _.health); } } } |
