From 94c816fbed2882f7dc0127f05f4ee74ffdccc21b Mon Sep 17 00:00:00 2001 From: Tyge Date: Thu, 23 Apr 2020 17:09:17 +0200 Subject: Fixed bugs with use of "Raw" types, and updated EXAMPLE.md accordingly. --- EXAMPLE.md | 53 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 15 deletions(-) (limited to 'EXAMPLE.md') diff --git a/EXAMPLE.md b/EXAMPLE.md index 45be0d02..e4fb8249 100644 --- a/EXAMPLE.md +++ b/EXAMPLE.md @@ -29,46 +29,69 @@ void person_destroy(struct Person* p) { cstring_destroy(&p->surname); } -int person_compare(struct Person* x, struct Person* y) { + +``` +In order to use it as a CMap key, provide a "view" of your class, that owns no resources (e.g. CStrings): +``` +struct PersonView +{ + const char* name; + const char* surname; + int age; +}; +struct PersonView person_getView(struct Person* p) { + return (struct PersonView) {p->name.str, p->surname.str, p->age}; +} +struct Person person_fromView(struct PersonView pv) { + return (struct Person) {cstring_make(pv.name), cstring_make(pv.surname), pv.age}; +} +int personview_compare(const struct PersonView* x, const struct PersonView* y) { int c; - c = strcmp(x->name.str, y->name.str); if (c != 0) return c; - c = strcmp(x->surname.str, y->surname.str); if (c != 0) return c; + c = strcmp(x->name, y->name); if (c != 0) return c; + c = strcmp(x->surname, y->surname); if (c != 0) return c; return memcmp(&x->age, &y->age, sizeof(x->age)); } ``` Here is a simple hash function that combines the three member's hashes: ``` -size_t person_hash(const struct Person* p, size_t ignore) { +size_t personview_hash(const struct PersonView* pv, size_t ignore) { // Compute individual hash values for name, surname and age // http://stackoverflow.com/a/1646913/126995 size_t res = 17; - res = res * 31 + c_defaultHash(p->name.str, cstring_size(p->name)); - res = res * 31 + c_defaultHash(p->surname.str, cstring_size(p->surname)); - res = res * 31 + c_defaultHash(&p->age, sizeof(p->age)); + res = res * 31 + c_defaultHash(pv->name, strlen(pv->name)); + res = res * 31 + c_defaultHash(pv->surname, strlen(pv->surname)); + res = res * 31 + c_defaultHash(&pv->age, sizeof(pv->age)); return res; } ``` -With this in place, you can instantiate a CMap with Person => CString: +With this in place, we can declare a CMap with Person => CString: ``` -#include -declare_CMap(ex, struct Person, CString, cstring_destroy, person_hash, person_compare, person_destroy); +#include +#include "stc/CMap.h" +declare_CMap(ex, struct Person, CString, cstring_destroy, + personview_hash, personview_compare, person_destroy, + struct PersonView, person_getView, person_fromView); +``` +Note we use struct PersonView to put keys in the map, but is stored as struct Person. +```` int main() { CMap_ex m6 = cmap_ex_init; - cmap_ex_put(&m6, person_make("John", "Doe", 12), cstring_make("example")); - cmap_ex_put(&m6, person_make("Mary", "Sue", 21), cstring_make("another")); - // ... + cmap_ex_put(&m6, (struct PersonView){"John", "Doe", 24}, cstring_make("dead")); + cmap_ex_put(&m6, (struct PersonView){"Jane", "Doe", 21}, cstring_make("another")); + cmap_ex_put(&m6, (struct PersonView){"John", "Travolta", 66}, cstring_make("actor")); + c_foreach (it, cmap_ex, m6) { if (cstring_equals(it.item->key.name, "John")) printf("%s %s %d -> %s\n", it.item->key.name.str, it.item->key.surname.str, it.item->key.age, it.item->value.str); } - + cmap_ex_destroy(&m6); } ``` -It will automatically use person_hash() as defined above for the hash value calculations, and the person_compare() for equality checks. +CMap will automatically use personview_hash() as defined above for the hash value calculations, and the personview_compare() for equality checks. The cmap_ex_destroy() function will free CStrings name, surname and the value for each item in the map, in addition to the CMap hash table itself. -- cgit v1.2.3