diff --git a/lib/cunit/cu_pc_patch.c b/lib/cunit/cu_pc_patch.c index 67238397..74f5364f 100644 --- a/lib/cunit/cu_pc_patch.c +++ b/lib/cunit/cu_pc_patch.c @@ -379,6 +379,57 @@ test_patch_dimensional_compression() if ( pds ) pc_dimstats_free(pds); } +static void +test_patch_compression_stats_leak() +{ + PCPOINT *pt; + int i; + int npts = 400; + PCPOINTLIST *pl1, *pl2; + PCPATCH *pch1, *pch2; + PCDIMSTATS *pds = NULL; + + pl1 = pc_pointlist_make(npts); + + for ( i = 0; i < npts; i++ ) + { + pt = pc_point_make(simpleschema); + pc_point_set_double_by_name(pt, "x", i*2.0); + pc_point_set_double_by_name(pt, "y", i*1.9); + pc_point_set_double_by_name(pt, "Z", i*0.34); + pc_point_set_double_by_name(pt, "intensity", 10); + pc_pointlist_add_point(pl1, pt); + } + + pch1 = pc_patch_from_pointlist(pl1); + + pch2 = pc_patch_compress(pch1, pds); + + pl2 = pc_pointlist_from_patch(pch2); + + for ( i = 0; i < npts; i++ ) + { + pt = pc_pointlist_get_point(pl2, i); + double v1, v2, v3, v4; + pc_point_get_double_by_name(pt, "x", &v1); + pc_point_get_double_by_name(pt, "y", &v2); + pc_point_get_double_by_name(pt, "Z", &v3); + pc_point_get_double_by_name(pt, "intensity", &v4); + + CU_ASSERT_DOUBLE_EQUAL(v1, i*2.0, 0.001); + CU_ASSERT_DOUBLE_EQUAL(v2, i*1.9, 0.001); + CU_ASSERT_DOUBLE_EQUAL(v3, i*0.34, 0.001); + CU_ASSERT_DOUBLE_EQUAL(v4, 10, 0.001); + } + + pc_patch_free((PCPATCH*)pch1); + pc_patch_free((PCPATCH*)pch2); + pc_pointlist_free(pl1); + pc_pointlist_free(pl2); + if ( pds ) pc_dimstats_free(pds); +} + + static void test_patch_dimensional_extent() { @@ -1394,6 +1445,7 @@ CU_TestInfo patch_tests[] = { PC_TEST(test_schema_xy), PC_TEST(test_patch_dimensional), PC_TEST(test_patch_dimensional_compression), + PC_TEST(test_patch_compression_stats_leak), PC_TEST(test_patch_dimensional_extent), PC_TEST(test_patch_union), PC_TEST(test_patch_wkb), diff --git a/lib/pc_api_internal.h b/lib/pc_api_internal.h index f23dacc6..54d8a526 100644 --- a/lib/pc_api_internal.h +++ b/lib/pc_api_internal.h @@ -166,6 +166,7 @@ char* pc_dimstats_to_string(const PCDIMSTATS *pds); /** Returns newly allocated patch that only contains the points fitting the filter condition */ PCPATCH* pc_patch_filter(const PCPATCH *pa, uint32_t dimnum, PC_FILTERTYPE filter, double val1, double val2); +void pc_patch_free_stats(PCPATCH *pa); /* DIMENSIONAL PATCHES */ char* pc_patch_dimensional_to_string(const PCPATCH_DIMENSIONAL *pa); diff --git a/lib/pc_patch.c b/lib/pc_patch.c index b52dabfd..1800d2a5 100644 --- a/lib/pc_patch.c +++ b/lib/pc_patch.c @@ -80,14 +80,18 @@ pc_patch_compute_stats(PCPATCH *pa) } void -pc_patch_free(PCPATCH *patch) +pc_patch_free_stats(PCPATCH *patch) { if ( patch->stats ) { pc_stats_free( patch->stats ); patch->stats = NULL; } +} +void +pc_patch_free(PCPATCH *patch) +{ switch( patch->type ) { case PC_NONE: diff --git a/lib/pc_patch_dimensional.c b/lib/pc_patch_dimensional.c index 01ac1cb1..786dbb0b 100644 --- a/lib/pc_patch_dimensional.c +++ b/lib/pc_patch_dimensional.c @@ -148,6 +148,7 @@ pc_patch_dimensional_decompress(const PCPATCH_DIMENSIONAL *pdl) pdl_decompressed = pcalloc(sizeof(PCPATCH_DIMENSIONAL)); memcpy(pdl_decompressed, pdl, sizeof(PCPATCH_DIMENSIONAL)); pdl_decompressed->bytes = pcalloc(ndims*sizeof(PCBYTES)); + pdl_decompressed->stats = pc_stats_clone(pdl->stats); /* Compress each dimension as dictated by stats */ for ( i = 0; i < ndims; i++ ) @@ -165,6 +166,8 @@ pc_patch_dimensional_free(PCPATCH_DIMENSIONAL *pdl) assert(pdl); assert(pdl->schema); + pc_patch_free_stats((PCPATCH*) pdl); + if ( pdl->bytes ) { for ( i = 0; i < pdl->schema->ndims; i++ ) @@ -282,6 +285,7 @@ pc_patch_dimensional_from_wkb(const PCSCHEMA *schema, const uint8_t *wkb, size_t patch->schema = schema; patch->npoints = npoints; patch->bytes = pcalloc(ndims*sizeof(PCBYTES)); + patch->stats = NULL; buf = wkb+hdrsz; for ( i = 0; i < ndims; i++ ) diff --git a/lib/pc_patch_ght.c b/lib/pc_patch_ght.c index 4ac595f4..5970aec9 100644 --- a/lib/pc_patch_ght.c +++ b/lib/pc_patch_ght.c @@ -233,6 +233,8 @@ pc_patch_ght_free(PCPATCH_GHT *paght) assert(paght); assert(paght->schema); + pc_patch_free_stats((PCPATCH*) paght); + /* A readonly tree won't own it's ght buffer, */ /* so only free a readwrite tree */ if ( ! paght->readonly ) @@ -363,6 +365,7 @@ pc_patch_ght_from_wkb(const PCSCHEMA *schema, const uint8_t *wkb, size_t wkbsize patch->readonly = PC_FALSE; patch->schema = schema; patch->npoints = npoints; + patch->stats = NULL; /* Start on the GHT */ buf = wkb+hdrsz; @@ -533,6 +536,7 @@ pc_patch_ght_filter(const PCPATCH_GHT *patch, uint32_t dimnum, PC_FILTERTYPE fil paght->readonly = PC_FALSE; paght->schema = patch->schema; paght->npoints = npoints; + paght->stats = NULL; /* No points, not much to do... */ if ( ! npoints ) diff --git a/lib/pc_patch_lazperf.c b/lib/pc_patch_lazperf.c index 1db64746..2686faf0 100644 --- a/lib/pc_patch_lazperf.c +++ b/lib/pc_patch_lazperf.c @@ -16,6 +16,8 @@ void pc_patch_lazperf_free(PCPATCH_LAZPERF *pal) { assert(pal); + assert(pal->schema); + pc_patch_free_stats((PCPATCH*) pal); pcfree(pal->lazperf); pcfree(pal); } @@ -206,6 +208,7 @@ pc_patch_lazperf_from_wkb(const PCSCHEMA *schema, const uint8_t *wkb, size_t wkb patch->readonly = PC_FALSE; patch->schema = schema; patch->npoints = npoints; + patch->stats = NULL; /* Start on the LAZPERF */ buf = wkb+hdrsz; diff --git a/lib/pc_patch_uncompressed.c b/lib/pc_patch_uncompressed.c index 7d19f5f6..0d21fd94 100644 --- a/lib/pc_patch_uncompressed.c +++ b/lib/pc_patch_uncompressed.c @@ -10,6 +10,7 @@ * ***********************************************************************/ +#include #include "pc_api_internal.h" #include "stringbuffer.h" @@ -140,6 +141,7 @@ pc_patch_uncompressed_from_wkb(const PCSCHEMA *s, const uint8_t *wkb, size_t wkb patch->maxpoints = npoints; patch->datasize = (wkbsize - hdrsz); patch->data = data; + patch->stats = NULL; return (PCPATCH*)patch; } @@ -215,6 +217,11 @@ pc_patch_uncompressed_compute_extent(PCPATCH_UNCOMPRESSED *patch) void pc_patch_uncompressed_free(PCPATCH_UNCOMPRESSED *patch) { + assert(patch); + assert(patch->schema); + + pc_patch_free_stats((PCPATCH*) patch); + if ( patch->data && ! patch->readonly ) { pcfree(patch->data); @@ -279,6 +286,7 @@ pc_patch_uncompressed_from_pointlist(const PCPOINTLIST *pl) pch = pcalloc(sizeof(PCPATCH_UNCOMPRESSED)); pch->datasize = s->size * numpts; pch->data = pcalloc(pch->datasize); + pch->stats = NULL; ptr = pch->data; /* Initialize bounds */