mirror of
https://github.com/pgpointcloud/pointcloud.git
synced 2025-12-08 20:36:04 +00:00
Add in RLE primitives to lib
This commit is contained in:
parent
070609ef87
commit
d5fec6a94c
@ -191,6 +191,8 @@ LIBS="$LIBS_SAVE"
|
||||
|
||||
AC_DEFINE_UNQUOTED([LIBXML2_VERSION], ["$LIBXML2_VERSION"], [PointCloud libxml2 version])
|
||||
AC_SUBST([LIBXML2_VERSION])
|
||||
AC_SUBST([XML2_LDFLAGS])
|
||||
AC_SUBST([XML2_CPPFLAGS])
|
||||
|
||||
|
||||
dnl ===========================================================================
|
||||
|
||||
@ -5,6 +5,7 @@ CPPFLAGS = $(XML2_CPPFLAGS)
|
||||
LDFLAGS = $(XML2_LDFLAGS)
|
||||
|
||||
OBJS = \
|
||||
pc_dimensional.o \
|
||||
pc_mem.o \
|
||||
pc_patch.o \
|
||||
pc_point.o \
|
||||
|
||||
@ -177,12 +177,101 @@ test_patch_hex_out()
|
||||
pcfree(wkt);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/** Convert RLE bytes to value bytes */
|
||||
uint8_t* pc_bytes_run_length_decode(const uint8_t *bytes_rle, size_t bytes_rle_size, uint32_t interpretation, size_t *bytes_nelems);
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
test_run_length_encoding()
|
||||
{
|
||||
char *bytes, *bytes_rle, *bytes_de_rle;
|
||||
int nr;
|
||||
uint32_t bytes_nelems;
|
||||
size_t bytes_rle_size;
|
||||
size_t size;
|
||||
uint8_t interp;
|
||||
size_t interp_size;
|
||||
|
||||
bytes = "aaaabbbbccdde";
|
||||
nr = pc_bytes_run_count(bytes, PC_UINT8, strlen(bytes));
|
||||
CU_ASSERT_EQUAL(nr, 5);
|
||||
|
||||
bytes = "a";
|
||||
nr = pc_bytes_run_count(bytes, PC_UINT8, strlen(bytes));
|
||||
CU_ASSERT_EQUAL(nr, 1);
|
||||
|
||||
bytes = "aa";
|
||||
nr = pc_bytes_run_count(bytes, PC_UINT8, strlen(bytes));
|
||||
CU_ASSERT_EQUAL(nr, 1);
|
||||
|
||||
bytes = "ab";
|
||||
nr = pc_bytes_run_count(bytes, PC_UINT8, strlen(bytes));
|
||||
CU_ASSERT_EQUAL(nr, 2);
|
||||
|
||||
bytes = "abcdefg";
|
||||
nr = pc_bytes_run_count(bytes, PC_UINT8, strlen(bytes));
|
||||
CU_ASSERT_EQUAL(nr, 7);
|
||||
|
||||
bytes = "aabcdefg";
|
||||
nr = pc_bytes_run_count(bytes, PC_UINT8, strlen(bytes));
|
||||
CU_ASSERT_EQUAL(nr, 7);
|
||||
|
||||
bytes = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";
|
||||
nr = pc_bytes_run_count(bytes, PC_UINT8, strlen(bytes));
|
||||
CU_ASSERT_EQUAL(nr, 1);
|
||||
|
||||
bytes_rle = pc_bytes_run_length_encode(bytes, PC_UINT8, strlen(bytes), &bytes_rle_size);
|
||||
bytes_de_rle = pc_bytes_run_length_decode(bytes_rle, bytes_rle_size, PC_UINT8, &bytes_nelems);
|
||||
CU_ASSERT_EQUAL(memcmp(bytes, bytes_de_rle, strlen(bytes)), 0);
|
||||
pcfree(bytes_rle);
|
||||
pcfree(bytes_de_rle);
|
||||
|
||||
bytes = "aabcdefg";
|
||||
interp = PC_UINT8;
|
||||
interp_size = INTERPRETATION_SIZES[interp];
|
||||
size = strlen(bytes) / interp_size;
|
||||
bytes_rle = pc_bytes_run_length_encode(bytes, interp, size, &bytes_rle_size);
|
||||
bytes_de_rle = pc_bytes_run_length_decode(bytes_rle, bytes_rle_size, interp, &bytes_nelems);
|
||||
CU_ASSERT_EQUAL(memcmp(bytes, bytes_de_rle, strlen(bytes)), 0);
|
||||
CU_ASSERT_EQUAL(bytes_nelems, strlen(bytes)/interp_size);
|
||||
pcfree(bytes_rle);
|
||||
pcfree(bytes_de_rle);
|
||||
|
||||
bytes = "aaaaaabbbbeeeeeeeeeehhiiiiiioooo";
|
||||
interp = PC_UINT32;
|
||||
interp_size = INTERPRETATION_SIZES[interp];
|
||||
size = strlen(bytes) / interp_size;
|
||||
bytes_rle = pc_bytes_run_length_encode(bytes, interp, size, &bytes_rle_size);
|
||||
bytes_de_rle = pc_bytes_run_length_decode(bytes_rle, bytes_rle_size, interp, &bytes_nelems);
|
||||
CU_ASSERT_EQUAL(memcmp(bytes, bytes_de_rle, strlen(bytes)), 0);
|
||||
CU_ASSERT_EQUAL(bytes_nelems, strlen(bytes)/interp_size);
|
||||
pcfree(bytes_rle);
|
||||
pcfree(bytes_de_rle);
|
||||
|
||||
bytes = "aaaaaabbbbeeeeeeeeeehhiiiiiioooo";
|
||||
interp = PC_UINT16;
|
||||
interp_size = INTERPRETATION_SIZES[interp];
|
||||
size = strlen(bytes) / interp_size;
|
||||
bytes_rle = pc_bytes_run_length_encode(bytes, interp, size, &bytes_rle_size);
|
||||
bytes_de_rle = pc_bytes_run_length_decode(bytes_rle, bytes_rle_size, interp, &bytes_nelems);
|
||||
CU_ASSERT_EQUAL(memcmp(bytes, bytes_de_rle, strlen(bytes)), 0);
|
||||
CU_ASSERT_EQUAL(bytes_nelems, strlen(bytes)/interp_size);
|
||||
pcfree(bytes_rle);
|
||||
pcfree(bytes_de_rle);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* REGISTER ***********************************************************/
|
||||
|
||||
CU_TestInfo patch_tests[] = {
|
||||
PG_TEST(test_endian_flip),
|
||||
PG_TEST(test_patch_hex_in),
|
||||
PG_TEST(test_patch_hex_out),
|
||||
PG_TEST(test_run_length_encoding),
|
||||
CU_TEST_INFO_NULL
|
||||
};
|
||||
|
||||
|
||||
@ -84,5 +84,13 @@ int pc_schema_has_name(const PCSCHEMA *s, const char *name);
|
||||
/** Copy a string within the global memory management context */
|
||||
char* pcstrdup(const char *str);
|
||||
|
||||
/** How many runs are there in a value array? */
|
||||
uint32_t pc_bytes_run_count(const uint8_t *bytes, uint32_t interpretation, uint32_t nelems);
|
||||
|
||||
/** Convert value bytes to RLE bytes */
|
||||
uint8_t* pc_bytes_run_length_encode(const uint8_t *bytes, uint32_t interpretation, uint32_t nelems, size_t *bytes_rle_size);
|
||||
|
||||
/** Convert RLE bytes to value bytes */
|
||||
uint8_t* pc_bytes_run_length_decode(const uint8_t *bytes_rle, size_t bytes_rle_size, uint32_t interpretation, uint32_t *bytes_nelems);
|
||||
|
||||
#endif /* _PC_API_INTERNAL_H */
|
||||
@ -19,3 +19,130 @@
|
||||
#include <stdarg.h>
|
||||
#include "pc_api_internal.h"
|
||||
|
||||
|
||||
uint32_t
|
||||
pc_bytes_run_count(const uint8_t *bytes, uint32_t interpretation, uint32_t nelems)
|
||||
{
|
||||
int i;
|
||||
const uint8_t *ptr0;
|
||||
const uint8_t *ptr1;
|
||||
size_t size = INTERPRETATION_SIZES[interpretation];
|
||||
uint32_t runcount = 1;
|
||||
|
||||
for ( i = 1; i < nelems; i++ )
|
||||
{
|
||||
ptr0 = bytes + (i-1)*size;
|
||||
ptr1 = bytes + i*size;
|
||||
if ( memcmp(ptr0, ptr1, size) != 0 )
|
||||
{
|
||||
runcount++;
|
||||
}
|
||||
}
|
||||
return runcount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the uncompressed bytes and run-length encode (RLE) them.
|
||||
* Structure of RLE array as:
|
||||
* <uint8> number of elements
|
||||
* <val> value
|
||||
* ...
|
||||
*/
|
||||
uint8_t *
|
||||
pc_bytes_run_length_encode(const uint8_t *bytes, uint32_t interpretation, uint32_t nelems, size_t *bytes_rle_size)
|
||||
{
|
||||
int i;
|
||||
uint8_t *buf, *bufptr;
|
||||
const uint8_t *bytesptr;
|
||||
const uint8_t *runstart;
|
||||
uint8_t *bytes_rle;
|
||||
size_t size = INTERPRETATION_SIZES[interpretation];
|
||||
uint8_t runlength = 1;
|
||||
|
||||
/* Allocate more size than we need (worst case: n elements, n runs) */
|
||||
buf = pcalloc(nelems*size + sizeof(uint8_t)*size);
|
||||
bufptr = buf;
|
||||
|
||||
/* First run starts at the start! */
|
||||
runstart = bytes;
|
||||
|
||||
for ( i = 1; i <= nelems; i++ )
|
||||
{
|
||||
bytesptr = bytes + i*size;
|
||||
/* Run continues... */
|
||||
if ( i < nelems && runlength < 255 && memcmp(runstart, bytesptr, size) == 0 )
|
||||
{
|
||||
runlength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Write # elements in the run */
|
||||
*bufptr = runlength;
|
||||
bufptr += 1;
|
||||
/* Write element value */
|
||||
memcpy(bufptr, runstart, size);
|
||||
bufptr += size;
|
||||
/* Advance read head */
|
||||
runstart = bytesptr;
|
||||
runlength = 1;
|
||||
}
|
||||
}
|
||||
/* Length of buffer */
|
||||
if ( bytes_rle_size )
|
||||
{
|
||||
*bytes_rle_size = (bufptr - buf);
|
||||
}
|
||||
/* Write out shortest buffer possible */
|
||||
bytes_rle = pcalloc(*bytes_rle_size);
|
||||
memcpy(bytes_rle, buf, *bytes_rle_size);
|
||||
pcfree(buf);
|
||||
|
||||
return bytes_rle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the compressed bytes and run-length dencode (RLE) them.
|
||||
* Structure of RLE array is:
|
||||
* <uint8> number of elements
|
||||
* <val> value
|
||||
* ...
|
||||
*/
|
||||
uint8_t *
|
||||
pc_bytes_run_length_decode(const uint8_t *bytes_rle, size_t bytes_rle_size, uint32_t interpretation, uint32_t *bytes_nelems)
|
||||
{
|
||||
int i, n;
|
||||
uint8_t *bytes;
|
||||
uint8_t *bytes_ptr;
|
||||
const uint8_t *bytes_rle_ptr = bytes_rle;
|
||||
const uint8_t *bytes_rle_end = bytes_rle + bytes_rle_size;
|
||||
|
||||
size_t size = INTERPRETATION_SIZES[interpretation];
|
||||
uint8_t runlength;
|
||||
uint32_t nelems = 0;
|
||||
|
||||
/* Count up how big our output is. */
|
||||
while( bytes_rle_ptr < bytes_rle_end )
|
||||
{
|
||||
nelems += *bytes_rle_ptr;
|
||||
bytes_rle_ptr += 1 + size;
|
||||
}
|
||||
*bytes_nelems = nelems;
|
||||
|
||||
/* Alocate output and fill it up */
|
||||
bytes = pcalloc(size * nelems);
|
||||
bytes_ptr = bytes;
|
||||
bytes_rle_ptr = bytes_rle;
|
||||
while ( bytes_rle_ptr < bytes_rle_end )
|
||||
{
|
||||
n = *bytes_rle_ptr;
|
||||
bytes_rle_ptr += 1;
|
||||
for ( i = 0; i < n; i++ )
|
||||
{
|
||||
memcpy(bytes_ptr, bytes_rle_ptr, size);
|
||||
bytes_ptr += size;
|
||||
}
|
||||
bytes_rle_ptr += size;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user