Skip to content

Commit

Permalink
Mở rộng hmap cho phép tùy chỉnh hàm gán khóa và giá trị
Browse files Browse the repository at this point in the history
  • Loading branch information
bangoc committed Feb 2, 2025
1 parent 79b4459 commit a37139f
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 17 deletions.
11 changes: 7 additions & 4 deletions macro/demo/hmap_word_demo.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@

HMAP_DECL_IMPL(hmap, char *, int)

void str_assign(char **des, const char *src) {
*des = strdup(src);
}

int main() {
struct hmap *hm = hmap(0, hash_s, strcmp);
struct hmap *hm = hmap(hash_s, strcmp);
hmap_ak(hm, str_assign);
hmap_fk(hm, free);
char cmd[32], word[32];
while (scanf("%s", cmd) == 1) {
Expand All @@ -20,12 +25,10 @@ int main() {
}
scanf("%s", word);
if (strcmp(cmd, "insert") == 0) {
char *s = strdup(word);
struct hmap_elem *e = hmap_put(hm, s, 1);
struct hmap_elem *e = hmap_put(hm, word, 1);
if (e) {
++e->value;
printf("freq(%s) updated = %d\n", word, e->value);
free(s);
} else {
printf("Inserted %s\n", word);
}
Expand Down
54 changes: 43 additions & 11 deletions macro/hmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ const int prime_mod [] =
#define HMAP_DECL(hname, key_t, value_t) \
struct hname##_elem; \
struct hname; \
struct hname *hname(int cap, unsigned (*ha)(const key_t), \
struct hname *hname(unsigned (*ha)(const key_t), \
int (*cmp)(const key_t, const key_t)); \
struct hname *hname##_fk(struct hname* hm, void (*fk)()); \
struct hname *hname##_fv(struct hname* hm, void (*fv)()); \
struct hname *hname##_ak(struct hname *hm, void (*ak)(key_t *des, const key_t src)); \
struct hname *hname##_av(struct hname *hm, void (*av)(value_t *des, const value_t src)); \
void hname##_realloc(struct hname *hm, int ncap); \
struct hname##_elem *hname##_put(struct hname *hm, key_t k, value_t v); \
struct hname##_elem *hname##_get(struct hname *hm, const key_t k); \
int hname##_rem(struct hname *hm, const key_t k); \
Expand Down Expand Up @@ -90,6 +93,8 @@ struct hname { \
int (*cmp)(const key_t, const key_t); \
void (*fk)(); \
void (*fv)(); \
void (*ak)(key_t *des, const key_t src); \
void (*av)(value_t *des, const value_t src); \
}; \
static int closest_shift(int n) { \
int i = 0; \
Expand Down Expand Up @@ -154,9 +159,12 @@ static void relocate_map(struct hname *hm, unsigned ocap, \
} \
} \
} \
static void hname##_realloc(struct hname *hm) { \
void hname##_realloc(struct hname *hm, int ncap) { \
if (ncap == hm->cap || ncap < hm->used) { \
return; \
} \
int ocap = hm->cap; \
hname##_set_shift_from_cap(hm, hm->size * 1.333); \
hname##_set_shift_from_cap(hm, ncap); \
if (hm->cap > ocap) { \
hname##_realloc_arrays(hm); \
memset(hm->elems + ocap, 0, (hm->cap - ocap) * sizeof(struct hname##_elem)); \
Expand All @@ -171,10 +179,10 @@ static void hname##_realloc(struct hname *hm) { \
hm->used = hm->size; \
} \
static inline int hname##_maybe_realloc(struct hname *hm) { \
unsigned used = hm->used, cap = hm->cap; \
if ((cap > hm->size * 4 && cap > 1 << HASH_MIN_SHIFT) || \
(cap <= used + (used/16))) { \
hname##_realloc(hm); \
unsigned size = hm->size, cap = hm->cap; \
if (1.1 * size >= cap - 1 || \
(cap > 1024 && cap > 3 * size)) { \
hname##_realloc(hm, hm->size * 1.333); \
return 1; \
} \
return 0; \
Expand Down Expand Up @@ -219,7 +227,7 @@ static inline int hname##_lookup(struct hname *hm, const key_t key, \
} \
return idx; \
} \
struct hname *hname(int cap, unsigned (*ha)(const key_t), \
struct hname *hname(unsigned (*ha)(const key_t), \
int (*cmp)(const key_t, const key_t)) { \
struct hname *hm = malloc(sizeof(struct hname)); \
hm->size = 0; \
Expand All @@ -228,7 +236,9 @@ struct hname *hname(int cap, unsigned (*ha)(const key_t), \
hm->cmp = cmp; \
hm->fk = 0; \
hm->fv = 0; \
hname##_setup(hm, cap); \
hm->ak = 0; \
hm->av = 0; \
hname##_setup(hm, 0); \
return hm; \
} \
struct hname *hname##_fk(struct hname* hm, void (*fk)()) { \
Expand All @@ -245,6 +255,20 @@ struct hname *hname##_fv(struct hname* hm, void (*fv)()) { \
hm->fv = fv; \
return hm; \
} \
struct hname *hname##_ak(struct hname *hm, void (*ak)(key_t *des, const key_t src)) { \
if (!hm) { \
return hm; \
} \
hm->ak = ak; \
return hm; \
} \
struct hname *hname##_av(struct hname *hm, void (*av)(value_t *des, const value_t src)) { \
if (!hm) { \
return hm; \
} \
hm->av = av; \
return hm; \
} \
struct hname##_elem *hname##_put(struct hname *hm, key_t k, value_t v) { \
unsigned key_hash; \
int idx = hname##_lookup(hm, k, &key_hash); \
Expand All @@ -253,8 +277,16 @@ struct hname##_elem *hname##_put(struct hname *hm, key_t k, value_t v) { \
return n; \
} \
n->hash = key_hash; \
n->key = k; \
n->value = v; \
if (hm->ak) { \
hm->ak(&n->key, k); \
} else { \
n->key = k; \
} \
if (hm->av) { \
hm->av(&n->value, v); \
} else { \
n->value = v; \
} \
++hm->size; \
int new_usage = n->state == UNUSED; \
n->state = USING; \
Expand Down
2 changes: 1 addition & 1 deletion macro/tests/hmap_demo_ut.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ char *gens() {

int main() {
srand(time(NULL));
struct sihmap *hm = sihmap(0, hash_s, strcmp);
struct sihmap *hm = sihmap(hash_s, strcmp);
sihmap_fk(hm, free);
for (int i = 0; i < 100000; ++i) {
char *key = strdup(gens());
Expand Down
2 changes: 1 addition & 1 deletion macro/tests/hmap_trav_demo_ut.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void elem_print(struct simap_elem *n, void *u) {
}

int main() {
struct simap *si = simap(10, hash_s, strcmp);
struct simap *si = simap(hash_s, strcmp);
simap_put(si, "abc", 12);
simap_put(si, "def", 35);
simap_put(si, "ace", 28);
Expand Down

0 comments on commit a37139f

Please sign in to comment.