Go to the source code of this file.
Functions | |
int | cbf_compress_canonical (void *source, size_t elsize, int elsign, size_t nelem, unsigned int compression, cbf_file *file, size_t *compressedsize, int *storedbits) |
int | cbf_decompress_canonical (void *destination, size_t elsize, int elsign, size_t nelem, size_t *nelem_read, unsigned int compression, cbf_file *file) |
int cbf_compress_canonical | ( | void * | source, |
size_t | elsize, | ||
int | elsign, | ||
size_t | nelem, | ||
unsigned int | compression, | ||
cbf_file * | file, | ||
size_t * | compressedsize, | ||
int * | storedbits | ||
) |
Definition at line 1284 of file cbf_canonical.c.
References cbf_compress_nodestruct::bitcount, cbf_compress_data::bits, bits(), CBF_ARGUMENT, CBF_BITCOUNT, cbf_count_bits(), cbf_count_values(), cbf_create_list(), cbf_failnez, cbf_free_compressdata(), cbf_generate_canonicalcodes(), cbf_generate_codelengths(), cbf_initialise_compressdata(), cbf_make_compressdata(), cbf_onfailnez, cbf_put_code(), cbf_put_integer(), cbf_put_stopcode(), cbf_put_table(), cbf_reduce_list(), CBF_SHIFT63, cbf_compress_nodestruct::code, cbf_compress_nodestruct::count, cbf_compress_nodestruct::next, and cbf_compress_data::node.
Referenced by cbf_compress().
{ int code, minelement, maxelement; unsigned int count, element, lastelement, bits, unsign, sign, limit, endcode; unsigned long bitcount, expected_bitcount; unsigned char *unsigned_char_data; cbf_compress_node *node, *start; cbf_compress_data *data; /* Is the element size valid? */ if (elsize != sizeof (int) && elsize != sizeof (short) && elsize != sizeof (char)) return CBF_ARGUMENT; /* Create and initialise the compression data */ cbf_failnez (cbf_make_compressdata (&data, file)) cbf_onfailnez (cbf_initialise_compressdata (data, 8, 0), cbf_free_compressdata (data)) /* Count the symbols */ cbf_onfailnez (cbf_count_values (data, source, elsize, elsign, nelem, &minelement, &maxelement), cbf_free_compressdata (data)) /* Generate the code lengths */ start = cbf_create_list (data); while (start->next) start = cbf_reduce_list (data, start); cbf_generate_codelengths (start, 0); /* Count the expected number of bits */ expected_bitcount = cbf_count_bits (data); /* Write the number of elements (64 bits) */ cbf_onfailnez (cbf_put_integer (file, nelem, 0, 64), cbf_free_compressdata (data)) /* Write the minimum element (64 bits) */ cbf_onfailnez (cbf_put_integer (file, minelement, elsign, 64), cbf_free_compressdata (data)) /* Write the maximum element (64 bits) */ cbf_onfailnez (cbf_put_integer (file, maxelement, elsign, 64), cbf_free_compressdata (data)) /* Write the reserved entry (64 bits) */ cbf_onfailnez (cbf_put_integer (file, 0, 0, 64), cbf_free_compressdata (data)) bitcount = 4 * 64; /* Write the table */ cbf_onfailnez (cbf_put_table (data, &bits), cbf_free_compressdata (data)) bitcount += bits; /* Generate the canonical bitcodes */ cbf_onfailnez (cbf_generate_canonicalcodes (data), \ cbf_free_compressdata (data)) /* Initialise the pointers */ unsigned_char_data = (unsigned char *) source; node = data->node; /* Maximum limit (unsigned) is 64 bits */ if (elsize * CHAR_BIT > 64) { sign = 1 << CBF_SHIFT63; limit = ~-(sign << 1); if (storedbits) *storedbits = 64; } else { sign = 1 << (elsize * CHAR_BIT - 1); limit = ~0; if (storedbits) *storedbits = elsize * CHAR_BIT; } /* Offset to make the value unsigned */ if (elsign) unsign = sign; else unsign = 0; /* Start from 0 */ lastelement = unsign; endcode = 1 << data->bits; for (count = 0; count < nelem; count++) { /* Get the next element */ if (elsize == sizeof (int)) element = *((unsigned int *) unsigned_char_data); else if (elsize == sizeof (short)) element = *((unsigned short *) unsigned_char_data); else element = *unsigned_char_data; unsigned_char_data += elsize; /* Make the element unsigned */ element += unsign; /* Limit the value to 64 bits */ if (element > limit) if (elsign && (int) (element - unsign) < 0) element = 0; else element = limit; /* Calculate the offset to save */ code = element - lastelement; /* Write the (overflowed?) code */ cbf_onfailnez (cbf_put_code (data, code, (element < lastelement) ^ (code < 0), &bits), cbf_free_compressdata (data)) bitcount += bits; /* Update the previous element */ lastelement = element; } /* End code */ cbf_onfailnez (cbf_put_stopcode (data, &bits), cbf_free_compressdata (data)) bitcount += bits; /* Free memory */ cbf_free_compressdata (data); /* Does the actual bit count match the expected bit count? */ if (bitcount != expected_bitcount) return CBF_BITCOUNT; /* Calculate the number of characters written */ if (binsize) *binsize = (bitcount + 7) / 8; /* Success */ return 0; }
int cbf_decompress_canonical | ( | void * | destination, |
size_t | elsize, | ||
int | elsign, | ||
size_t | nelem, | ||
size_t * | nelem_read, | ||
unsigned int | compression, | ||
cbf_file * | file | ||
) |
Definition at line 1530 of file cbf_canonical.c.
References bits(), CBF_ARGUMENT, cbf_failnez, cbf_free_compressdata(), cbf_get_code(), cbf_get_integer(), cbf_get_table(), cbf_make_compressdata(), cbf_onfailnez, cbf_setup_decode(), CBF_SHIFT63, and cbf_compress_nodestruct::count.
Referenced by cbf_decompress().
{ unsigned int bits, element, sign, unsign, limit, count64, count; unsigned char *unsigned_char_data; cbf_compress_data *data; cbf_compress_node *start; unsigned int offset [4], last_element [4]; int errorcode; /* Is the element size valid? */ if (elsize != sizeof (int) && elsize != sizeof (short) && elsize != sizeof (char)) return CBF_ARGUMENT; /* Discard the reserved entry (64 bits) */ cbf_failnez (cbf_get_integer (file, NULL, 0, 64)) /* Create and initialise the compression data */ cbf_failnez (cbf_make_compressdata (&data, file)) /* Read the compression table */ cbf_onfailnez (cbf_get_table (data), cbf_free_compressdata (data)) /* Set up the decode data */ cbf_onfailnez (cbf_setup_decode (data, &start), cbf_free_compressdata (data)) /* Initialise the pointer */ unsigned_char_data = (unsigned char *) destination; /* Maximum limit (unsigned) is 64 bits */ if (elsize * CHAR_BIT > 64) { sign = 1 << CBF_SHIFT63; limit = ~-(sign << 1); } else { sign = 1 << (elsize * CHAR_BIT - 1); if (elsize == sizeof (int)) limit = ~0; else limit = ~-(1 << (elsize * CHAR_BIT)); } /* Offset to make the value unsigned */ if (elsign) unsign = sign; else unsign = 0; /* How many ints do we need to hold 64 bits? */ count64 = (64 + sizeof (int) * CHAR_BIT - 1) / (sizeof (int) * CHAR_BIT); /* Initialise the first element */ last_element [0] = unsign; for (count = 1; count < count64; count++) last_element [count] = 0; /* Read the elements */ for (count = 0; count < nelem; count++) { /* Read the offset */ errorcode = cbf_get_code (data, start, offset, &bits); if (errorcode) { if (nelem_read) *nelem_read = count; cbf_free_compressdata (data); return errorcode; } /* Update the current element */ last_element [0] += offset [0]; element = last_element [0]; /* Limit the value to fit the element size */ if (element > limit) if (elsign && (int) (element - unsign) < 0) element = 0; else element = limit; /* Make the element signed? */ element -= unsign; /* Save the element */ if (elsize == sizeof (int)) *((unsigned int *) unsigned_char_data) = element; else if (elsize == sizeof (short)) *((unsigned short *) unsigned_char_data) = element; else *unsigned_char_data = element; unsigned_char_data += elsize; } /* Number read */ if (nelem_read) *nelem_read = count; /* Free memory */ cbf_free_compressdata (data); /* Success */ return 0; }