diff --git a/src/match_basic_types.cpp b/src/match_basic_types.cpp index 4808a18..600a4c7 100644 --- a/src/match_basic_types.cpp +++ b/src/match_basic_types.cpp @@ -289,10 +289,10 @@ void MemoryRegion::swap(MemoryRegion& other) { } void MemoryRegion::grow(std::size_t n) { if (n > size()) { - std::size_t nc = std::max(n, (size() * 3) >> 1); + std::size_t nc = std::max(n, (size() * 3 + 1) >> 1); void* t = std::realloc(beg_, nc); POTASSCO_CHECK(t, ENOMEM); - beg_ = t; end_ = static_cast(t)+n; + beg_ = t; end_ = static_cast(t)+nc; } } diff --git a/tests/test_aspif.cpp b/tests/test_aspif.cpp index 00762f8..0e86797 100644 --- a/tests/test_aspif.cpp +++ b/tests/test_aspif.cpp @@ -122,6 +122,35 @@ static int compareRead(std::stringstream& input, ReadObserver& observer, const R } return subset.second; } +TEST_CASE("Test MemoryRegion", "[rule]") { + SECTION("starts empty") { + MemoryRegion r; + REQUIRE(r.size() == 0); + REQUIRE(r.begin() == r.end()); + } + SECTION("supports initial size") { + MemoryRegion r(256); + REQUIRE(r.size() == 256); + REQUIRE(std::distance((char*) r.begin(), (char*) r.end()) == 256); + } + SECTION("grows geometrically") { + MemoryRegion r; + for (int i = 0; i != 10; ++i) { r.grow(r.size() + 1); } + REQUIRE(r.size() >= 50); + } + SECTION("copies data on grow") { + MemoryRegion r; + r.grow(12); + std::memset(r[0], 'A', 12); + r.grow(24); + std::memset(r[12], 'B', 12); + std::string exp(12, 'A'); + exp.append(12, 'B'); + r.grow(r.size() + 1); + *(char*) r[24] = 0; + REQUIRE(exp == (char*) r.begin()); + } +} TEST_CASE("Test RuleBuilder", "[rule]") { RuleBuilder rb; SECTION("simple rule") {