diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 646c99687..ac2e917a7 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -291,6 +291,17 @@ attrib_type at_curse = { #define MAXCTHASH 128 static quicklist *cursetypes[MAXCTHASH]; +static int ct_changes = 1; + +bool ct_changed(int *cache) +{ + assert(cache); + if (*cache != ct_changes) { + *cache = ct_changes; + return true; + } + return false; +} void ct_register(const curse_type * ct) { @@ -298,6 +309,27 @@ void ct_register(const curse_type * ct) quicklist **ctlp = cursetypes + hash; ql_set_insert(ctlp, (void *)ct); + ++ct_changes; +} + +void ct_remove(const char *c) +{ + unsigned int hash = tolower(c[0]); + quicklist *ctl = cursetypes[hash]; + + if (ctl) { + int qi; + + for (qi = 0; ctl; ql_advance(&ctl, &qi, 1)) { + curse_type *type = (curse_type *)ql_get(ctl, qi); + + if (strcmp(c, type->cname) == 0) { + ql_delete(&ctl, qi); + ++ct_changes; + break; + } + } + } } const curse_type *ct_find(const char *c) @@ -798,5 +830,7 @@ void curses_done(void) { int i; for (i = 0; i != MAXCTHASH; ++i) { ql_free(cursetypes[i]); + cursetypes[i] = 0; } + ++ct_changes; } diff --git a/src/kernel/curse.h b/src/kernel/curse.h index 9013a1df5..a1518bbdd 100644 --- a/src/kernel/curse.h +++ b/src/kernel/curse.h @@ -282,7 +282,9 @@ extern "C" { int find_cursebyname(const char *c); const curse_type *ct_find(const char *c); + bool ct_changed(int *cache); void ct_register(const curse_type *); + void ct_remove(const char *c); void ct_checknames(void); curse *findcurse(int curseid); diff --git a/src/kernel/curse.test.c b/src/kernel/curse.test.c index 6514b2f3e..d7c86b9b0 100644 --- a/src/kernel/curse.test.c +++ b/src/kernel/curse.test.c @@ -157,10 +157,29 @@ static void test_write_flag(CuTest *tc) { cleanup_curse(&fix); } +static void test_curse_cache(CuTest *tc) +{ + int cache = 0; + const curse_type ct_dummy = { "dummy", CURSETYP_NORM, 0, M_SUMEFFECT, NULL }; + test_setup(); + CuAssertIntEquals(tc, true, ct_changed(&cache)); + CuAssertIntEquals(tc, false, ct_changed(&cache)); + CuAssertPtrEquals(tc, NULL, (void *)ct_find(ct_dummy.cname)); + ct_register(&ct_dummy); + CuAssertIntEquals(tc, true, ct_changed(&cache)); + CuAssertPtrEquals(tc, (void *)&ct_dummy, (void *)ct_find(ct_dummy.cname)); + ct_remove(ct_dummy.cname); + CuAssertIntEquals(tc, true, ct_changed(&cache)); + CuAssertIntEquals(tc, false, ct_changed(&cache)); + CuAssertPtrEquals(tc, NULL, (void *)ct_find(ct_dummy.cname)); + test_cleanup(); +} + CuSuite *get_curse_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_curse); + SUITE_ADD_TEST(suite, test_curse_cache); SUITE_ADD_TEST(suite, test_magicstreet); SUITE_ADD_TEST(suite, test_magicstreet_warning); SUITE_ADD_TEST(suite, test_good_dreams);