diff --git a/lib/pc_api.h b/lib/pc_api.h index f204c85..39eb63a 100644 --- a/lib/pc_api.h +++ b/lib/pc_api.h @@ -376,7 +376,7 @@ int pc_bytes_serialize(const PCBYTES *pcb, uint8_t *buf, size_t *size); int pc_bytes_deserialize(const uint8_t *buf, const PCDIMENSION *dim, PCBYTES *pcb, int readonly, int flip_endian); /** Wrap serialized stats in a new stats objects */ -PCSTATS* pc_stats_new_from_data(const PCSCHEMA *schema, uint8_t *mindata, uint8_t *maxdata, uint8_t *avgdata);\ +PCSTATS* pc_stats_new_from_data(const PCSCHEMA *schema, const uint8_t *mindata, const uint8_t *maxdata, const uint8_t *avgdata);\ /** Calculate stats from an existing patch */ int pc_patch_compute_stats(PCPATCH *patch); diff --git a/lib/pc_patch.c b/lib/pc_patch.c index 9c8982d..390171c 100644 --- a/lib/pc_patch.c +++ b/lib/pc_patch.c @@ -76,6 +76,7 @@ pc_patch_free(PCPATCH *patch) if ( patch->stats ) { pc_stats_free( patch->stats ); + patch->stats = NULL; } switch( patch->type ) diff --git a/lib/pc_patch_dimensional.c b/lib/pc_patch_dimensional.c index 45edab2..12cea2e 100644 --- a/lib/pc_patch_dimensional.c +++ b/lib/pc_patch_dimensional.c @@ -73,7 +73,7 @@ pc_patch_dimensional_from_uncompressed(const PCPATCH_UNCOMPRESSED *pa) pdl->schema = schema; pdl->npoints = npoints; pdl->bounds = pa->bounds; - pdl->stats = pa->stats; + pdl->stats = pc_stats_clone(pa->stats); pdl->bytes = pcalloc(ndims * sizeof(PCBYTES)); for ( i = 0; i < ndims; i++ ) diff --git a/lib/pc_patch_ght.c b/lib/pc_patch_ght.c index 5f45dad..963f2c4 100644 --- a/lib/pc_patch_ght.c +++ b/lib/pc_patch_ght.c @@ -231,7 +231,7 @@ pc_patch_ght_from_uncompressed(const PCPATCH_UNCOMPRESSED *pa) paght->schema = pa->schema; paght->npoints = pointcount; paght->bounds = pa->bounds; - paght->stats = pa->stats; + paght->stats = pc_stats_clone(pa->stats); /* Convert the tree to a memory buffer */ ght_writer_new_mem(&writer); @@ -307,7 +307,7 @@ pc_patch_uncompressed_from_ght(const PCPATCH_GHT *paght) patch->schema = schema; patch->npoints = npoints; patch->bounds = paght->bounds; - patch->stats = paght->stats; + patch->stats = pc_stats_clone(paght->stats); patch->maxpoints = npoints; patch->datasize = schema->size * npoints; patch->data = pcalloc(patch->datasize); @@ -360,7 +360,6 @@ pc_patch_ght_from_wkb(const PCSCHEMA *schema, const uint8_t *wkb, size_t wkbsize pcerror("%s: libght support is not enabled", __func__); return NULL; #else - /* byte: endianness (1 = NDR, 0 = XDR) uint32: pcid (key to POINTCLOUD_SCHEMAS) @@ -369,7 +368,6 @@ pc_patch_ght_from_wkb(const PCSCHEMA *schema, const uint8_t *wkb, size_t wkbsize uint32: ghtsize uint8[]: ghtbuffer */ - static size_t hdrsz = 1+4+4+4; /* endian + pcid + compression + npoints */ PCPATCH_GHT *patch; uint8_t swap_endian = (wkb[0] != machine_endian()); @@ -394,10 +392,11 @@ pc_patch_ght_from_wkb(const PCSCHEMA *schema, const uint8_t *wkb, size_t wkbsize /* Start on the GHT */ buf = wkb+hdrsz; ghtsize = wkb_get_int32(buf, swap_endian); - buf += sizeof(int32_t); /* Move to start of GHT buffer */ + buf += 4; /* Move to start of GHT buffer */ /* Copy in the tree buffer */ patch->ght = pcalloc(ghtsize); + patch->ghtsize = ghtsize; memcpy(patch->ght, buf, ghtsize); return (PCPATCH*)patch; @@ -476,10 +475,10 @@ pc_patch_ght_to_wkb(const PCPATCH_GHT *patch, size_t *wkbsize) uint32_t pcid = patch->schema->pcid; uint32_t ghtsize = patch->ghtsize; wkb[0] = endian; /* Write endian flag */ - memcpy(wkb + 1, &pcid, 4); /* Write PCID */ - memcpy(wkb + 5, &compression, 4); /* Write compression */ - memcpy(wkb + 9, &npoints, 4); /* Write npoints */ - memcpy(wkb + 9, &ghtsize, 4); /* Write ght buffer size */ + memcpy(wkb + 1, &pcid, 4); /* Write PCID */ + memcpy(wkb + 5, &compression, 4); /* Write compression */ + memcpy(wkb + 9, &npoints, 4); /* Write npoints */ + memcpy(wkb + 13, &ghtsize, 4); /* Write ght buffer size */ buf = wkb + 17; memcpy(buf, patch->ght, patch->ghtsize); diff --git a/lib/pc_stats.c b/lib/pc_stats.c index c773ddd..56d75e3 100644 --- a/lib/pc_stats.c +++ b/lib/pc_stats.c @@ -61,13 +61,13 @@ pc_dstats_free(PCDOUBLESTATS *stats) void pc_stats_free(PCSTATS *stats) { - if ( ! stats->min.readonly ) + if ( stats->min.readonly != PC_TRUE ) pcfree(stats->min.data); - if ( ! stats->max.readonly ) + if ( stats->max.readonly != PC_TRUE ) pcfree(stats->max.data); - if ( ! stats->avg.readonly ) + if ( stats->avg.readonly != PC_TRUE ) pcfree(stats->avg.data); pcfree(stats); @@ -80,7 +80,7 @@ pc_stats_free(PCSTATS *stats) * serialization. */ PCSTATS * -pc_stats_new_from_data(const PCSCHEMA *schema, uint8_t *mindata, uint8_t *maxdata, uint8_t *avgdata) +pc_stats_new_from_data(const PCSCHEMA *schema, const uint8_t *mindata, const uint8_t *maxdata, const uint8_t *avgdata) { size_t sz = schema->size; PCSTATS *stats = pcalloc(sizeof(PCSTATS)); @@ -89,9 +89,9 @@ pc_stats_new_from_data(const PCSCHEMA *schema, uint8_t *mindata, uint8_t *maxdat stats->max.schema = schema; stats->avg.schema = schema; /* Data points into serialization */ - stats->min.data = mindata; - stats->max.data = maxdata; - stats->avg.data = avgdata; + stats->min.data = (uint8_t*)mindata; + stats->max.data = (uint8_t*)maxdata; + stats->avg.data = (uint8_t*)avgdata; /* Can't modify external data */ stats->min.readonly = PC_TRUE; stats->max.readonly = PC_TRUE; @@ -118,7 +118,7 @@ pc_stats_new(const PCSCHEMA *schema) stats->avg.readonly = PC_FALSE; stats->min.data = pcalloc(schema->size); stats->max.data = pcalloc(schema->size); - stats->avg.data = pcalloc(schema->size);; + stats->avg.data = pcalloc(schema->size); return stats; } @@ -144,15 +144,20 @@ pc_stats_new_from_dstats(const PCSCHEMA *schema, const PCDOUBLESTATS *dstats) PCSTATS * pc_stats_clone(const PCSTATS *stats) { - PCSTATS *snew = pcalloc(sizeof(PCSTATS)); - memcpy(snew, stats, sizeof(PCSTATS)); - snew->min.data = pcalloc(stats->min.schema->size); - snew->max.data = pcalloc(stats->max.schema->size); - snew->avg.data = pcalloc(stats->avg.schema->size); - memcpy(snew->min.data, stats->min.data, stats->min.schema->size); - memcpy(snew->max.data, stats->max.data, stats->max.schema->size); - memcpy(snew->avg.data, stats->avg.data, stats->avg.schema->size); - return snew; + PCSTATS *s; + if ( ! stats ) return NULL; + s = pcalloc(sizeof(PCSTATS)); + s->min.readonly = s->max.readonly = s->avg.readonly = PC_FALSE; + s->min.schema = stats->min.schema; + s->max.schema = stats->max.schema; + s->avg.schema = stats->avg.schema; + s->min.data = pcalloc(stats->min.schema->size); + s->max.data = pcalloc(stats->max.schema->size); + s->avg.data = pcalloc(stats->avg.schema->size); + memcpy(s->min.data, stats->min.data, stats->min.schema->size); + memcpy(s->max.data, stats->max.data, stats->max.schema->size); + memcpy(s->avg.data, stats->avg.data, stats->avg.schema->size); + return s; } int diff --git a/pgsql/pc_pgsql.c b/pgsql/pc_pgsql.c index 7ae32cb..ec1337b 100644 --- a/pgsql/pc_pgsql.c +++ b/pgsql/pc_pgsql.c @@ -445,21 +445,23 @@ size_t pc_patch_serialized_size(const PCPATCH *patch) { size_t stats_size = patch->schema->size * 3; + size_t common_size = sizeof(SERIALIZED_PATCH) - 1; switch( patch->type ) { case PC_NONE: { PCPATCH_UNCOMPRESSED *pu = (PCPATCH_UNCOMPRESSED*)patch; - return sizeof(SERIALIZED_PATCH) - 1 + stats_size + pu->datasize; + return common_size + stats_size + pu->datasize; } case PC_GHT: { + static size_t ghtsize_size = 4; PCPATCH_GHT *pg = (PCPATCH_GHT*)patch; - return sizeof(SERIALIZED_PATCH) - 1 + stats_size + 4 + pg->ghtsize; + return common_size + stats_size + ghtsize_size + pg->ghtsize; } case PC_DIMENSIONAL: { - return sizeof(SERIALIZED_PATCH) - 1 + stats_size + pc_patch_dimensional_serialized_size((PCPATCH_DIMENSIONAL*)patch); + return common_size + stats_size + pc_patch_dimensional_serialized_size((PCPATCH_DIMENSIONAL*)patch); } default: { @@ -495,12 +497,12 @@ pc_patch_stats_serialize(uint8_t *buf, const PCSCHEMA *schema, const PCSTATS *st * a point, the schema->size. */ static PCSTATS * -pc_patch_stats_deserialize(const PCSCHEMA *schema, uint8_t *buf) +pc_patch_stats_deserialize(const PCSCHEMA *schema, const uint8_t *buf) { size_t sz = schema->size; - uint8_t *buf_min = buf; - uint8_t *buf_max = buf + sz; - uint8_t *buf_avg = buf + 2*sz; + const uint8_t *buf_min = buf; + const uint8_t *buf_max = buf + sz; + const uint8_t *buf_avg = buf + 2*sz; return pc_stats_new_from_data(schema, buf_min, buf_max, buf_avg); } @@ -514,7 +516,8 @@ pc_patch_dimensional_serialize(const PCPATCH *patch_in) // uint32_t npoints; // double xmin, xmax, ymin, ymax; // data: - // serialized_pcbytes []; + // pcpoint[3] stats; + // serialized_pcbytes[ndims] dimensions; int i; uint8_t *buf; @@ -567,12 +570,14 @@ pc_patch_ght_serialize(const PCPATCH *patch_in) // uint32_t npoints; // double xmin, xmax, ymin, ymax; // data: + // pcpoint[3] stats; // uint32_t ghtsize; // uint8_t ght[]; size_t serpch_size = pc_patch_serialized_size(patch_in); SERIALIZED_PATCH *serpch = pcalloc(serpch_size); const PCPATCH_GHT *patch = (PCPATCH_GHT*)patch_in; + uint32_t ghtsize = patch->ghtsize; uint8_t *buf = serpch->data; assert(patch); @@ -595,7 +600,7 @@ pc_patch_ght_serialize(const PCPATCH *patch_in) } /* Write tree buffer size */ - memcpy(buf, &(patch->ghtsize), 4); + memcpy(buf, &(ghtsize), 4); buf += 4; /* Write tree buffer */ @@ -662,7 +667,8 @@ pc_patch_serialize(const PCPATCH *patch_in, void *userdata) */ if ( ! patch->stats ) { - pc_patch_compute_stats(patch); + pcerror("%s: patch is missing stats", __func__); + return NULL; } /* * Convert the patch to the final target compression, @@ -758,7 +764,7 @@ pc_patch_uncompressed_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHE /* Calculate the point data buffer size */ patch->datasize = VARSIZE(serpatch) - sizeof(SERIALIZED_PATCH) + 1 - stats_size; /* Point into the stats area */ - patch->stats = pc_patch_stats_deserialize(schema, patch->data); + patch->stats = pc_patch_stats_deserialize(schema, serpatch->data); /* Set up basic info */ patch->type = serpatch->compression; @@ -804,6 +810,9 @@ pc_patch_dimensional_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEM patch->npoints = npoints; patch->bounds = serpatch->bounds; + /* Point into the stats area */ + patch->stats = pc_patch_stats_deserialize(schema, serpatch->data); + /* Set up dimensions */ patch->bytes = pcalloc(ndims * sizeof(PCBYTES)); buf = serpatch->data + stats_size; @@ -858,6 +867,9 @@ pc_patch_ght_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEMA *schem patch->npoints = npoints; patch->bounds = serpatch->bounds; + /* Point into the stats area */ + patch->stats = pc_patch_stats_deserialize(schema, serpatch->data); + /* Set up ght buffer */ memcpy(&ghtsize, buf, 4); patch->ghtsize = ghtsize;