diff --git a/src/report.c b/src/report.c index fd642d10f..fdb670b5e 100644 --- a/src/report.c +++ b/src/report.c @@ -1550,7 +1550,7 @@ void pump_paragraph(sbstring *sbp, stream *out, size_t maxlen, bool isfinal) return; } else if (next > begin + maxlen) { - size_t len = pos - begin; + ptrdiff_t len = pos - begin; swrite(begin, 1, len, out); newline(out); @@ -1558,8 +1558,8 @@ void pump_paragraph(sbstring *sbp, stream *out, size_t maxlen, bool isfinal) ++pos; ++len; } - assert(len <= INT_MAX); - sbs_cut(sbp, (int)len); + assert(len <= SIZE_MAX); + sbs_substr(sbp, len, SIZE_MAX); break; } pos = next; diff --git a/src/util/strings.c b/src/util/strings.c index b227e5cc8..bd513fda4 100644 --- a/src/util/strings.c +++ b/src/util/strings.c @@ -298,19 +298,24 @@ void sbs_strcpy(struct sbstring *sbs, const char *str) assert(sbs->begin + sbs->size >= sbs->end); } -void sbs_cut(sbstring *sbs, int bytes) +void sbs_substr(sbstring *sbs, ptrdiff_t pos, size_t len) { - if (bytes > 0) { - size_t len = sbs_length(sbs) - bytes; - memmove(sbs->begin, sbs->begin + bytes, len + 1); - sbs->end = sbs->begin + len; + if (pos > sbs->end - sbs->begin) { + /* starting past end of string, do nothing */ + sbs->end = sbs->begin; } - else if (bytes < 0) { - size_t len = sbs_length(sbs) + bytes; + if (pos >= 0) { + size_t sz = sbs->end - (sbs->begin + pos); + if (len > sz) len = sz; + if (len - pos > 0) { + memmove(sbs->begin, sbs->begin + pos, len); + } + else { + memcpy(sbs->begin, sbs->begin + pos, len); + } sbs->end = sbs->begin + len; + sbs->end[0] = '\0'; } - assert(sbs->begin + sbs->size >= sbs->end); - assert(sbs->end[0] == '\0'); } size_t sbs_length(const struct sbstring *sbs) diff --git a/src/util/strings.h b/src/util/strings.h index d7b18a1a7..afcb477e4 100644 --- a/src/util/strings.h +++ b/src/util/strings.h @@ -52,7 +52,7 @@ extern "C" { void sbs_strcat(struct sbstring *sbs, const char *str); void sbs_strncat(struct sbstring *sbs, const char *str, size_t size); void sbs_strcpy(struct sbstring *sbs, const char *str); - void sbs_cut(struct sbstring *sbp, int bytes); + void sbs_substr(struct sbstring *sbp, ptrdiff_t pos, size_t len); size_t sbs_length(const struct sbstring *sbs); /* benchmark for units: diff --git a/src/util/strings.test.c b/src/util/strings.test.c index bcf1c54c2..23816a72d 100644 --- a/src/util/strings.test.c +++ b/src/util/strings.test.c @@ -191,6 +191,45 @@ static void test_sbs_strcat(CuTest * tc) CuAssertStrEquals(tc, "1234123", sbs.begin); } +static void test_sbs_substr(CuTest * tc) +{ + char buffer[10]; + sbstring sbs; + + buffer[9] = 'A'; + sbs_init(&sbs, buffer, sizeof(buffer)); + sbs_strcpy(&sbs, "12345678"); + CuAssertStrEquals(tc, "12345678", buffer); + sbs_substr(&sbs, 0, 4); + CuAssertStrEquals(tc, "1234", buffer); + CuAssertIntEquals(tc, 4, (int)sbs_length(&sbs)); + + sbs_strcpy(&sbs, "12345678"); + CuAssertStrEquals(tc, "12345678", buffer); + sbs_substr(&sbs, 4, 4); + CuAssertStrEquals(tc, "5678", buffer); + CuAssertIntEquals(tc, 4, (int)sbs_length(&sbs)); + + sbs_strcpy(&sbs, "12345678"); + CuAssertStrEquals(tc, "12345678", buffer); + sbs_substr(&sbs, 2, 4); + CuAssertStrEquals(tc, "3456", buffer); + CuAssertIntEquals(tc, 4, (int)sbs_length(&sbs)); + + sbs_strcpy(&sbs, "12345678"); + CuAssertStrEquals(tc, "12345678", buffer); + sbs_substr(&sbs, 4, 4); + CuAssertStrEquals(tc, "5678", buffer); + CuAssertIntEquals(tc, 4, (int)sbs_length(&sbs)); + + sbs_strcpy(&sbs, "12345678"); + CuAssertStrEquals(tc, "12345678", buffer); + sbs_substr(&sbs, 4, 8); + CuAssertStrEquals(tc, "5678", buffer); + CuAssertIntEquals(tc, 4, (int)sbs_length(&sbs)); + CuAssertIntEquals(tc, 'A', buffer[9]); +} + CuSuite *get_strings_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -205,5 +244,6 @@ CuSuite *get_strings_suite(void) SUITE_ADD_TEST(suite, test_str_itoa); SUITE_ADD_TEST(suite, test_sbstring); SUITE_ADD_TEST(suite, test_sbs_strcat); + SUITE_ADD_TEST(suite, test_sbs_substr); return suite; }