Skip to content

Commit

Permalink
Ensure tg_geom_copy copies collection indexes
Browse files Browse the repository at this point in the history
  • Loading branch information
tidwall committed Sep 30, 2023
1 parent a5f9cfb commit 5c505b9
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 12 deletions.
44 changes: 33 additions & 11 deletions tests/test_index.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,16 @@ struct tg_geom *test_index_multi_step(int npolys, double nsecs) {
assert(polys);
struct tg_geom *geom = tg_geom_new_multipolygon((void*)polys, npolys);
assert(geom);

for (int i = 0; i < npolys; i++) {
tg_poly_free(polys[i]);
}
free(polys);


struct tg_geom *geom2 = tg_geom_copy(geom);
assert(geom2);

double start = now();
struct tg_rect world_ext = {
{ world.min.x-10, world.min.y-10 },
Expand All @@ -546,19 +556,20 @@ struct tg_geom *test_index_multi_step(int npolys, double nsecs) {
tg_geom_search(geom, rect, icounter, &ctx0);
struct icounterctx ctx1 = { 0 };
for (int j = 0; j < npolys; j++) {
if (tg_geom_intersects_rect((struct tg_geom*)polys[j], rect)) {
struct tg_geom *poly = (struct tg_geom*)tg_geom_poly_at(geom, j);
if (tg_geom_intersects_rect(poly, rect)) {
ctx1.count++;
}
}
struct icounterctx ctx2 = { 0 };
tg_geom_search(geom2, rect, icounter, &ctx2);
assert(ctx0.count == ctx1.count);
assert(ctx0.count == ctx2.count);
steps++;
}
(void)steps;
// printf("%d\n", steps);
for (int i = 0; i < npolys; i++) {
tg_poly_free(polys[i]);
}
free(polys);
tg_geom_free(geom2);

return geom;
}

Expand All @@ -582,20 +593,31 @@ void test_index_chaos(void) {
struct tg_rect world = R(-180, -90, 180, 90);
struct tg_poly **polys;

npolys = 1000;
npolys = 65;
polys = gen_rand_polys(npolys, world, true);
assert(polys);


int failures = 0;
while (failures < 100) {
struct tg_geom *geom = tg_geom_new_multipolygon((void*)polys, npolys);
struct tg_geom *geom = NULL;
while (failures < 1000 || !geom) {
if (geom) {
tg_geom_free(geom);
}
geom = tg_geom_new_multipolygon((void*)polys, npolys);
if (!geom) {
failures++;
}
}
failures = 0;
while (failures < 300000) {
struct tg_geom *geom2 = tg_geom_copy(geom);
if (!geom2) {
failures++;
} else {
tg_geom_free(geom);
tg_geom_free(geom2);
}
}
tg_geom_free(geom);

for (int i = 0; i < npolys; i++) {
tg_poly_free(polys[i]);
Expand Down
26 changes: 25 additions & 1 deletion tg.c
Original file line number Diff line number Diff line change
Expand Up @@ -4802,6 +4802,12 @@ static size_t geom_memsize(const struct tg_geom *geom) {
for (int i = 0; i < geom->multi->ngeoms; i++) {
size += tg_geom_memsize(geom->multi->geoms[i]);
}
if (geom->multi->index) {
size += geom->multi->index->memsz;
}
if (geom->multi->ixgeoms) {
size += geom->multi->ngeoms*sizeof(int);
}
}
break;
}
Expand Down Expand Up @@ -14079,14 +14085,15 @@ static struct tg_geom *geom_copy(const struct tg_geom *geom) {
goto fail;
}
memset(geom2->multi, 0, sizeof(struct multi));
geom2->multi->rect = geom->multi->rect;
if (geom->multi->geoms) {
size_t gsize = sizeof(struct tg_geom*)*geom->multi->ngeoms;
geom2->multi->geoms = tg_malloc(gsize);
if (!geom2->multi->geoms) {
goto fail;
}
geom2->multi->ngeoms = geom->multi->ngeoms;
memset(geom2->multi->geoms, 0, gsize);
geom2->multi->ngeoms = geom->multi->ngeoms;
for (int i = 0; i < geom->multi->ngeoms; i++) {
const struct tg_geom *child = geom->multi->geoms[i];
geom2->multi->geoms[i] = tg_geom_copy(child);
Expand All @@ -14095,6 +14102,23 @@ static struct tg_geom *geom_copy(const struct tg_geom *geom) {
}
}
}
if (geom->multi->index) {
geom2->multi->index = tg_malloc(geom->multi->index->memsz);
if (!geom2->multi->index) {
goto fail;
}
memcpy(geom2->multi->index, geom->multi->index,
geom->multi->index->memsz);
}
if (geom->multi->ixgeoms) {
geom2->multi->ixgeoms = tg_malloc(
geom->multi->ngeoms*sizeof(int));
if (!geom2->multi->ixgeoms) {
goto fail;
}
memcpy(geom2->multi->ixgeoms, geom->multi->ixgeoms,
geom->multi->ngeoms*sizeof(int));
}
}
break;
}
Expand Down

0 comments on commit 5c505b9

Please sign in to comment.