diff --git a/src/reports.c b/src/reports.c index ad8a0fbc2..da4b2af45 100644 --- a/src/reports.c +++ b/src/reports.c @@ -2035,6 +2035,7 @@ void report_battle_start(battle * b) { bfaction *bf; char zText[32 * MAXSIDES]; + sbstring sbs; for (bf = b->factions; bf; bf = bf->next) { message *m; @@ -2042,18 +2043,17 @@ void report_battle_start(battle * b) const char *lastf = NULL; bool first = false; side *s; - char *bufp = zText; - size_t size = sizeof(zText) - 1; + sbs_init(&sbs, zText, sizeof(zText)); for (s = b->sides; s != b->sides + b->nsides; ++s) { fighter *df; for (df = s->fighters; df; df = df->next) { if (is_attacker(df)) { if (first) { - bufp += str_strlcpy(bufp, ", ", size); + sbs_strcpy(&sbs, ", "); } if (lastf) { - bufp += str_strlcpy(bufp, lastf, size); + sbs_strcpy(&sbs, lastf); first = true; } if (seematrix(f, s)) @@ -2065,12 +2065,12 @@ void report_battle_start(battle * b) } } if (first) { - bufp = STRLCPY(bufp, " ", size); - bufp = STRLCPY(bufp, LOC(f->locale, "and"), size); - bufp = STRLCPY(bufp, " ", size); + sbs_strcpy(&sbs, " "); + sbs_strcpy(&sbs, LOC(f->locale, "and")); + sbs_strcpy(&sbs, " "); } if (lastf) { - bufp = STRLCPY(bufp, lastf, size); + sbs_strcpy(&sbs, lastf); } m = msg_message("start_battle", "factions", zText); diff --git a/src/util/strings.c b/src/util/strings.c index 9350f4d5e..06bd43b3a 100644 --- a/src/util/strings.c +++ b/src/util/strings.c @@ -238,3 +238,28 @@ char *str_strdup(const char *s) { return strdup(s); #endif } + +void sbs_init(struct sbstring *sbs, char *buffer, size_t size) +{ + assert(sbs); + assert(size>0); + sbs->begin = buffer; + sbs->size = size; + sbs->end = buffer; + buffer[0] = '\0'; +} + +void sbs_strcat(struct sbstring *sbs, const char *str) +{ + size_t len; + assert(sbs); + len = sbs->size - (sbs->end - sbs->begin); + len = str_strlcpy(sbs->end, str, len); + sbs->end += len; +} + +void sbs_strcpy(struct sbstring *sbs, const char *str) +{ + size_t len = str_strlcpy(sbs->begin, str, sbs->size); + sbs->end += len; +} diff --git a/src/util/strings.h b/src/util/strings.h index bc1b48d7e..a9fa46d3a 100644 --- a/src/util/strings.h +++ b/src/util/strings.h @@ -37,6 +37,17 @@ extern "C" { unsigned int jenkins_hash(unsigned int a); unsigned int wang_hash(unsigned int a); + /* static buffered string */ + typedef struct sbstring { + size_t size; + char *begin; + char *end; + } sbstring; + + void sbs_init(struct sbstring *sbs, char *buffer, size_t size); + void sbs_strcat(struct sbstring *sbs, const char *str); + void sbs_strcpy(struct sbstring *sbs, const char *str); + /* benchmark for units: * JENKINS_HASH: 5.25 misses/hit (with good cache behavior) * WANG_HASH: 5.33 misses/hit (with good cache behavior) diff --git a/src/util/strings.test.c b/src/util/strings.test.c index 68a7fefe0..523d01dbd 100644 --- a/src/util/strings.test.c +++ b/src/util/strings.test.c @@ -91,6 +91,25 @@ static void test_str_strlcpy(CuTest * tc) errno = 0; } +static void test_sbstring(CuTest * tc) +{ + char buffer[16]; + sbstring sbs; + sbs_init(&sbs, buffer, sizeof(buffer)); + CuAssertStrEquals(tc, "", sbs.begin); + sbs_strcpy(&sbs, "Hodor"); + CuAssertStrEquals(tc, "Hodor", sbs.begin); + sbs_strcat(&sbs, "Hodor"); + CuAssertStrEquals(tc, "HodorHodor", sbs.begin); + sbs_strcpy(&sbs, "Hodor"); + CuAssertStrEquals(tc, "Hodor", sbs.begin); + sbs_strcpy(&sbs, "12345678901234567890"); + CuAssertStrEquals(tc, "123456789012345", sbs.begin); + sbs_strcat(&sbs, "12345678901234567890"); + CuAssertStrEquals(tc, "123456789012345", sbs.begin); + CuAssertStrEquals(tc, buffer, sbs.begin); +} + CuSuite *get_strings_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -100,5 +119,6 @@ CuSuite *get_strings_suite(void) SUITE_ADD_TEST(suite, test_str_slprintf); SUITE_ADD_TEST(suite, test_str_strlcat); SUITE_ADD_TEST(suite, test_str_strlcpy); + SUITE_ADD_TEST(suite, test_sbstring); return suite; }