diff --git a/examples/example_compress_chunk.c b/examples/example_compress_chunk.c index 4dac0d85186eb68c8769ef9e23502d8dac5f44c3..900eb0177373f7dc4b87b17b89b3b0f54b8c1b25 100644 --- a/examples/example_compress_chunk.c +++ b/examples/example_compress_chunk.c @@ -63,7 +63,7 @@ static int demo_comperss_chunk_1d(void) uint8_t chunk[CHUNK_SIZE] = {0}; /* Do not put large amount of data on the stack! */ uint32_t *compressed_data; - int cmp_size_bytes; + uint32_t cmp_size_bytes; { /* build a chunk of a background and an offset collection */ struct collection_hdr *col = (struct collection_hdr *)chunk; @@ -99,11 +99,17 @@ static int demo_comperss_chunk_1d(void) cmp_par.nc_background_mean = 3; cmp_par.nc_background_variance = 4; cmp_par.nc_background_outlier_pixels = 5; + /* Only the compression parameters needed to compress offset and + * background collections are set. + */ /* prepare the buffer for the compressed data */ cmp_size_bound = compress_chunk_cmp_size_bound(chunk, CHUNK_SIZE); - if (!cmp_size_bound) { + if (cmp_is_error(cmp_size_bound)) { printf("Error occurred during compress_chunk_cmp_size_bound()\n"); + printf("Failed with error code %d: %s\n", + cmp_get_error_code(cmp_size_bound), + cmp_get_error_name(cmp_size_bound)); /* error handling */ return -1; } @@ -117,17 +123,23 @@ static int demo_comperss_chunk_1d(void) cmp_size_bytes = compress_chunk(chunk, CHUNK_SIZE, NULL, NULL, compressed_data, cmp_size_bound, &cmp_par); - if (cmp_size_bytes < 0) { + /* this is another way to check if a function failed */ + if (cmp_get_error_code(cmp_size_bytes) != CMP_ERROR_NO_ERROR) { printf("Error occurred during compress_chunk()\n"); - if (cmp_size_bytes == CMP_ERROR_SMALL_BUF) - printf("The compressed data buffer is too small to hold all compressed data!\n"); + printf("Failed with error code %d: %s\n", + cmp_get_error_code(cmp_size_bytes), + cmp_get_error_name(cmp_size_bytes)); free(compressed_data); /* error handling */ return -1; } - if (compress_chunk_set_model_id_and_counter(compressed_data, cmp_size_bytes, - MODEL_ID, 0)) { + cmp_size_bytes = compress_chunk_set_model_id_and_counter(compressed_data, + cmp_size_bytes, MODEL_ID, 0); + if (cmp_is_error(cmp_size_bytes)) { printf("Error occurred during compress_chunk_set_model_id_and_counter()\n"); + printf("we get error code %d: %s\n", + cmp_get_error_code(cmp_size_bytes), + cmp_get_error_name(cmp_size_bytes)); free(compressed_data); /* error handling */ return -1; @@ -135,7 +147,7 @@ static int demo_comperss_chunk_1d(void) } { /* have a look at the compressed data */ - int i; + uint32_t i; printf("Here's the compressed data including the compression entity header (size %d):\n", cmp_size_bytes); for (i = 0; i < cmp_size_bytes; i++) { @@ -176,7 +188,7 @@ static int demo_comperss_chunk_model(void) * the number of collections in the chunk (2 in this demo) */ uint32_t compressed_data[COMPRESS_CHUNK_BOUND(CHUNK_SIZE, 2)/4]; /* Do not put large amount of data on the stack! */ - int cmp_size_bytes; + uint32_t cmp_size_bytes; { /* build a chunk of a background and an offset collection */ struct collection_hdr *col = (struct collection_hdr *)chunk; @@ -228,27 +240,35 @@ static int demo_comperss_chunk_model(void) cmp_par.nc_background_mean = 3; cmp_par.nc_background_variance = 4; cmp_par.nc_background_outlier_pixels = 5; + /* Only the compression parameters needed to compress offset and + * background collections are set. + */ cmp_size_bytes = compress_chunk(chunk, CHUNK_SIZE, model_chunk, updated_chunk_model, compressed_data, sizeof(compressed_data), &cmp_par); - if (cmp_size_bytes < 0) { + if (cmp_is_error(cmp_size_bytes)) { printf("Error occurred during compress_chunk()\n"); - if (cmp_size_bytes == CMP_ERROR_SMALL_BUF) - printf("The compressed data buffer is too small to hold all compressed data!\n"); + printf("Failed with error code %d: %s\n", + cmp_get_error_code(cmp_size_bytes), + cmp_get_error_name(cmp_size_bytes)); /* error handling */ return -1; } - if (compress_chunk_set_model_id_and_counter(compressed_data, cmp_size_bytes, - MODEL_ID, MODEL_COUNTER)) { + cmp_size_bytes = compress_chunk_set_model_id_and_counter(compressed_data, + cmp_size_bytes, MODEL_ID, MODEL_COUNTER); + if (cmp_is_error(cmp_size_bytes)) { printf("Error occurred during compress_chunk_set_model_id_and_counter()\n"); + printf("Failed with error code %d: %s\n", + cmp_get_error_code(cmp_size_bytes), + cmp_get_error_name(cmp_size_bytes)); /* error handling */ return -1; } } { /* have a look at the compressed data */ - int i; + uint32_t i; printf("Here's the compressed data including the compression entity header (size %d):\n", cmp_size_bytes); for (i = 0; i < cmp_size_bytes; i++) { diff --git a/lib/cmp_chunk.h b/lib/cmp_chunk.h index ea305e52a31a48eaee146a4ba7bf6a1d469c6fb3..114c95202440cc1c920ffd498148cea459bc8802 100644 --- a/lib/cmp_chunk.h +++ b/lib/cmp_chunk.h @@ -22,6 +22,7 @@ #include "common/cmp_support.h" #include "common/cmp_entity.h" +#include "common/cmp_error_list.h" #define ROUND_UP_TO_4(x) ((((x)+3)/4)*4) @@ -112,10 +113,11 @@ struct cmp_par { * COMPRESS_CHUNK_BOUND macro for compilation-time evaluation * (stack memory allocation for example) * - * @param chunk pointer to the chunk you want compress + * @param chunk pointer to the chunk you want to compress * @param chunk_size size of the chunk in bytes * - * @returns maximum compressed size for a chunk compression; 0 on error + * @returns maximum compressed size for a chunk compression on success or an + * error code if it fails (which can be tested with cmp_is_error()) */ uint32_t compress_chunk_cmp_size_bound(const void *chunk, size_t chunk_size); @@ -129,7 +131,7 @@ uint32_t compress_chunk_cmp_size_bound(const void *chunk, size_t chunk_size); * * @param return_timestamp pointer to a function returning a current 48-bit * timestamp - * @param version_id version identifier of the applications software + * @param version_id application software version identifier */ void compress_chunk_init(uint64_t(return_timestamp)(void), uint32_t version_id); @@ -156,35 +158,79 @@ void compress_chunk_init(uint64_t(return_timestamp)(void), uint32_t version_id); * compress_chunk_cmp_size_bound(chunk, chunk_size) * as it eliminates one potential failure scenario: * not enough space in the dst buffer to write the - * compressed data; size is internally round down + * compressed data; size is internally rounded down * to a multiple of 4 - * @returns the byte size of the compressed_data buffer on success; negative on - * error, CMP_ERROR_SMALL_BUF (-2) if the compressed data buffer is too - * small to hold the whole compressed data; the compressed and updated - * model are only valid on positive return values + * @returns the byte size of the compressed data or an error code if it + * fails (which can be tested with cmp_is_error()) */ -int32_t compress_chunk(void *chunk, uint32_t chunk_size, - void *chunk_model, void *updated_chunk_model, - uint32_t *dst, uint32_t dst_capacity, - const struct cmp_par *cmp_par); +uint32_t compress_chunk(void *chunk, uint32_t chunk_size, + void *chunk_model, void *updated_chunk_model, + uint32_t *dst, uint32_t dst_capacity, + const struct cmp_par *cmp_par); /** * @brief set the model id and model counter in the compression entity header * - * @param dst pointer to the compressed data starting with a - * compression entity header + * @param dst pointer to the compressed data (starting with a + * compression entity header) * @param dst_size byte size of the dst buffer * @param model_id model identifier; for identifying entities that originate * from the same starting model * @param model_counter model_counter; counts how many times the model was * updated; for non model mode compression use 0 * - * @returns 0 on success, otherwise error + * @returns the byte size of the dst buffer (= dst_size) on success or an error + * code if it fails (which can be tested with cmp_is_error()) */ -int compress_chunk_set_model_id_and_counter(void *dst, int dst_size, - uint16_t model_id, uint8_t model_counter); +uint32_t compress_chunk_set_model_id_and_counter(void *dst, uint32_t dst_size, + uint16_t model_id, uint8_t model_counter); + + +/** + * @brief tells if a result is an error code + * + * @param code return value to check + * + * @returns non-zero if the code is an error + */ + +unsigned int cmp_is_error(uint32_t code); + + +/** + * @brief provides a readable string from a compression return value (useful for debugging) + * + * @param code compression return value to describe + * + * @returns a pointer to a string literal that describes the error code. + */ + +const char* cmp_get_error_name(uint32_t code); + + +/** + * @brief convert a function result into a cmp_error enum + * + * @param code compression return value to get the error code + * + * @returns error code + */ + +enum cmp_error cmp_get_error_code(uint32_t code); + + +/** + * @brief get a string describing an error code + * + * @param code the error code to describe, obtain with cmp_get_error_code() + * + * @returns a pointer to a string literal that describes the error code. + */ + +const char* cmp_get_error_string(enum cmp_error code); + #endif /* CMP_CHUNK_H */ diff --git a/lib/common/cmp_debug.h b/lib/common/cmp_debug.h index 5d950932b7b8f40f6ac9715be5decd96937ccd01..a4c18dfbba0eaec324032e0d19f6b4f878ffa115 100644 --- a/lib/common/cmp_debug.h +++ b/lib/common/cmp_debug.h @@ -41,5 +41,12 @@ void cmp_debug_print_impl(const char *fmt, ...); # define debug_print(...) do {} while (0) #endif +#define debug_print_level(level, ...) \ + do { \ + if (level <= DEBUGLEVEL) \ + debug_print(__VA_ARGS__); \ + } while (0) + + #endif /* CMP_DEBUG_H */ diff --git a/lib/common/cmp_error.c b/lib/common/cmp_error.c new file mode 100644 index 0000000000000000000000000000000000000000..b81e5954c973c9893c7f399177a46b87cc7ebd06 --- /dev/null +++ b/lib/common/cmp_error.c @@ -0,0 +1,141 @@ +/** + * @file cmp_error.c + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2024 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief handling errors functions + */ + +#include <stdint.h> + +#include "cmp_error.h" +#include "cmp_error_list.h" +#include "../cmp_chunk.h" + + +/** + * @brief tells if a result is an error code + * + * @param code return value to check + * + * @returns non-zero if the code is an error + */ + +unsigned int cmp_is_error(uint32_t code) +{ + return (code > CMP_ERROR(MAX_CODE)); +} + + +/** + * @brief convert a function result into a cmp_error enum + * + * @param code compression return value to get the error code + * + * @returns error code + */ + +enum cmp_error cmp_get_error_code(uint32_t code) +{ + if (cmp_is_error(code)) + return (enum cmp_error)(0-code); + + return CMP_ERROR_NO_ERROR; +} + + +/** + * @brief get a string describing an error code + * + * @param code the error code to describe, obtain with cmp_get_error_code() + * + * @returns a pointer to a string literal that describes the error code. + */ + +const char* cmp_get_error_string(enum cmp_error code) +{ +#ifdef CMP_STRIP_ERROR_STRINGS + (void)code; + return "Error strings stripped"; +#else + static const char* const notErrorCode = "Unspecified error code"; + switch (code) { + case CMP_ERROR_NO_ERROR: + return "No error detected"; + case CMP_ERROR_GENERIC: + return "Error (generic)"; + case CMP_ERROR_SMALL_BUF_: + return "Destination buffer is too small to hold the whole compressed data"; + case CMP_ERROR_DATA_VALUE_TOO_LARGE: + return "Data value is larger than expected"; + + + case CMP_ERROR_PAR_GENERIC: + return "Compression mode or model value or lossy rounding parameter is unsupported"; + case CMP_ERROR_PAR_SPECIFIC: + return "Specific compression parameters or combination is unsupported"; + case CMP_ERROR_PAR_BUFFERS: + return "Buffer related parameter is not valid"; + + case CMP_ERROR_CHUNK_NULL: + return "Pointer to the chunk is NULL. No data, no compression"; + case CMP_ERROR_CHUNK_TOO_LARGE: + return "Chunk size too large"; + case CMP_ERROR_CHUNK_TOO_SMALL: + return "Chunk size too small. Minimum size is the size of a collection header"; + case CMP_ERROR_CHUNK_SIZE_INCONSISTENT: + return "Chunk size is not consistent with the sum of the sizes in the compression headers. Chunk size may be wrong?"; + case CMP_ERROR_CHUNK_SUBSERVICE_INCONSISTENT: + return "The chunk contains collections with an incompatible combination of subservices"; + + case CMP_ERROR_COL_SUBSERVICE_UNSUPPORTED: + return "Unsupported collection subservice"; + case CMP_ERROR_COL_SIZE_INCONSISTENT: + return "Inconsistency detected between the collection subservice and data length"; + + case CMP_ERROR_ENTITY_NULL: + return "Compression entity pointer is NULL"; + case CMP_ERROR_ENTITY_TOO_SMALL: + return "Compression entity size is too small"; + case CMP_ERROR_ENTITY_HEADER: + return "An error occurred while generating the compression entity header"; + case CMP_ERROR_ENTITY_TIMESTAMP: + return "Timestamp too large for the compression entity header"; + + case CMP_ERROR_INT_DECODER: + return "Internal decoder error occurred"; + case CMP_ERROR_INT_DATA_TYPE_UNSUPPORTED: + return "Internal error: Data type not supported"; + case CMP_ERROR_INT_CMP_COL_TOO_LARGE: + return "Internal error: compressed collection to large"; + + case CMP_ERROR_MAX_CODE: + default: + return notErrorCode; + } +#endif +} + + +/** + * @brief provides a readable string from a compression return value (useful for debugging) + * + * @param code compression return value to describe + * + * @returns a pointer to a string literal that describes the error code. + */ + +const char* cmp_get_error_name(uint32_t code) +{ + return cmp_get_error_string(cmp_get_error_code(code)); +} diff --git a/lib/common/cmp_error.h b/lib/common/cmp_error.h new file mode 100644 index 0000000000000000000000000000000000000000..333bbc9565e4c8a574540f957c6ba932f3cc6400 --- /dev/null +++ b/lib/common/cmp_error.h @@ -0,0 +1,149 @@ +/** + * @file cmp_error.h + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2024 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief collection of macros to handling errors + * This is heavy inspired by the error handling of zstd (lib/common/error_private.h) by + * @author Yann Collet et al. + * https://github.com/facebook/zstd/blob/dev/ + */ + +#ifndef CMP_ERROR_H +#define CMP_ERROR_H + + +#include <stdint.h> +#include "cmp_error_list.h" + + +/** + * @brief add the CMP_ERROR prefix to the error name + * + * @param name the name to concatenate with cmp error prefix + */ + +#define PREFIX_CMP_ERRROR(name) CMP_ERROR_##name + + +/** + * @brief generate a return value of a error + * + * @param name error name without CMP_ERROR prefix to create an error code for + */ + +#define CMP_ERROR(name) ((uint32_t)-PREFIX_CMP_ERRROR(name)) + + +/** + * @brief ignore this is an internal helper + * + * this is a helper function to help force c99-correctness during compilation + * under strict compilation modes variadic macro arguments can't be empty + * however variadic function arguments can be using a function therefore lets + * us statically check that at least one string argument was passed + * independent of the compilation flags + */ + +static __inline void _force_has_format_string(const char *format, ...) { + (void)format; +} + + +/** + * @brief ignore this is an internal helper + * + * we want to force this function invocation to be syntactically correct but + * we don't want to force runtime evaluation of its arguments + */ + +__extension__ +#define _FORCE_HAS_FORMAT_STRING(...) \ + do { \ + if (0) { \ + _force_has_format_string(__VA_ARGS__); \ + } \ + } while (0) + +#define ERR_QUOTE(str) #str + + +/** + * @brief return the specified error if the condition evaluates to true + * + * @param cond the condition to evaluate + * @param err the error to return if the condition is true + * @param ... additional arguments for error logging + * + * in debug modes (DEBUGLEVEL>=3) prints additional information + */ + +__extension__ +#define RETURN_ERROR_IF(cond, err, ...) \ + do { \ + if (cond) { \ + debug_print_level(3, "%s:%d: Error: check %s failed, returning %s", \ + __FILE__, __LINE__, ERR_QUOTE(cond), \ + ERR_QUOTE(CMP_ERROR(err))); \ + _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ + debug_print_level(3, "-> " __VA_ARGS__); \ + return CMP_ERROR(err); \ + } \ + } while (0) + + +/** + * @brief unconditionally return the specified error + * + * @param err the error to return unconditionally + * @param ... additional arguments for error logging + * + * in debug modes (DEBUGLEVEL>=3) prints additional information + */ + +__extension__ +#define RETURN_ERROR(err, ...) \ + do { \ + debug_print_level(3, "%s:%d: Error: unconditional check failed, returning %s", \ + __FILE__, __LINE__, ERR_QUOTE(ERROR(err))); \ + _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ + debug_print_level(3, "-> " __VA_ARGS__); \ + return CMP_ERROR(err); \ + } while(0) + + +/** + * @brief if the provided expression evaluates to an error code returns that error code + * + * @param err the error expression to evaluate + * @param ... additional arguments for error logging + * + * in debug modes (DEBUGLEVEL>=3) prints additional information + */ + +__extension__ +#define FORWARD_IF_ERROR(err, ...) \ + do { \ + uint32_t const err_code = (err); \ + if (cmp_is_error(err_code)) { \ + debug_print_level(3, "%s:%d: Error: forwarding error in %s: %s",\ + __FILE__, __LINE__, ERR_QUOTE(err), \ + cmp_get_error_name(err_code)); \ + _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \ + debug_print_level(3, "--> " __VA_ARGS__); \ + return err_code; \ + } \ + } while(0) + + +#endif /* CMP_ERROR_H */ diff --git a/lib/common/cmp_error_list.h b/lib/common/cmp_error_list.h new file mode 100644 index 0000000000000000000000000000000000000000..f2f8bffbd2307dc7c420953c0cb56bd78d5eee67 --- /dev/null +++ b/lib/common/cmp_error_list.h @@ -0,0 +1,59 @@ +/** + * @file cmp_error_list.h + * @author Dominik Loidolt (dominik.loidolt@univie.ac.at) + * @date 2024 + * + * @copyright GPLv2 + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * @brief definition of the compression error codes + */ + +#ifndef CMP_ERROR_LIST_H +#define CMP_ERROR_LIST_H + + +/** + * @brief compression error codes + * @warning error codes (name and value) are TBC + */ + +enum cmp_error { + CMP_ERROR_NO_ERROR = 0, + CMP_ERROR_GENERIC = 1, + CMP_ERROR_SMALL_BUF_ = 2, + CMP_ERROR_DATA_VALUE_TOO_LARGE = 3, + /* compression parameter errors */ + CMP_ERROR_PAR_GENERIC = 20, + CMP_ERROR_PAR_SPECIFIC = 21, + CMP_ERROR_PAR_BUFFERS = 22, + /* chunk errors */ + CMP_ERROR_CHUNK_NULL = 40, + CMP_ERROR_CHUNK_TOO_LARGE = 41, + CMP_ERROR_CHUNK_TOO_SMALL = 42, + CMP_ERROR_CHUNK_SIZE_INCONSISTENT = 43, + CMP_ERROR_CHUNK_SUBSERVICE_INCONSISTENT = 44, + /* collection errors */ + CMP_ERROR_COL_SUBSERVICE_UNSUPPORTED = 60, + CMP_ERROR_COL_SIZE_INCONSISTENT = 61, + /* compression entity errors */ + CMP_ERROR_ENTITY_NULL = 80, + CMP_ERROR_ENTITY_TOO_SMALL = 81, + CMP_ERROR_ENTITY_HEADER = 82, + CMP_ERROR_ENTITY_TIMESTAMP = 83, + /* internal compressor errors */ + CMP_ERROR_INT_DECODER = 100, + CMP_ERROR_INT_DATA_TYPE_UNSUPPORTED = 101, + CMP_ERROR_INT_CMP_COL_TOO_LARGE = 102, + + CMP_ERROR_MAX_CODE = 127 /* Prefer using cmp_is_error() for error checking. */ +}; + +#endif /* CMP_ERROR_LIST_H */ diff --git a/lib/common/meson.build b/lib/common/meson.build index f24b91bfd2db2b20694b5f6fd2312f2a448e26a9..1214439e01f215e2fd00920b6032b281209258a5 100644 --- a/lib/common/meson.build +++ b/lib/common/meson.build @@ -2,6 +2,7 @@ common_sources = files([ 'cmp_data_types.c', 'cmp_debug.c', 'cmp_entity.c', + 'cmp_error.c', 'cmp_max_used_bits.c', 'cmp_support.c', 'vsnprintf.c' diff --git a/lib/icu_compress/cmp_icu.c b/lib/icu_compress/cmp_icu.c index 22919272f034cc8d64da0a9a7dc98a8d7d8deb71..f697620f81e5e295d4a409e8a67d848e530379be 100644 --- a/lib/icu_compress/cmp_icu.c +++ b/lib/icu_compress/cmp_icu.c @@ -15,16 +15,6 @@ * * @brief software compression library * @see Data Compression User Manual PLATO-UVIE-PL-UM-0001 - * - * To compress data, first create a compression configuration with the - * cmp_cfg_icu_create() function. - * Then set the different data buffers with the data to compressed, the model - * data and the compressed data with the cmp_cfg_icu_buffers() function. - * Then set the compression data type specific compression parameters. For - * imagette data use the cmp_cfg_icu_imagette() function. For flux and center of - * brightness data use the cmp_cfg_fx_cob() function. And for background, offset - * and smearing data use the cmp_cfg_aux() function. - * Finally, you can compress the data with the icu_compress_data() function. */ @@ -37,6 +27,8 @@ #include "../common/cmp_data_types.h" #include "../common/cmp_support.h" #include "../common/cmp_entity.h" +#include "../common/cmp_error.h" +#include "../common/leon_inttypes.h" #include "../cmp_icu.h" #include "../cmp_chunk.h" @@ -84,7 +76,7 @@ typedef uint32_t (*generate_cw_f_pt)(uint32_t value, uint32_t encoder_par1, struct encoder_setupt { generate_cw_f_pt generate_cw_f; /**< function pointer to a code word encoder */ - int (*encode_method_f)(uint32_t data, uint32_t model, int stream_len, + uint32_t (*encode_method_f)(uint32_t data, uint32_t model, uint32_t stream_len, const struct encoder_setupt *setup); /**< pointer to the encoding function */ uint32_t *bitstream_adr; /**< start address of the compressed data bitstream */ uint32_t max_stream_len; /**< maximum length of the bitstream/icu_output_buf in bits */ @@ -96,23 +88,6 @@ struct encoder_setupt { }; -/** - * @brief types of chunks containing different types of collections - * according to DetailedBudgetWorking_2023-10-11 - */ - -enum chunk_type { - CHUNK_TYPE_UNKNOWN, - CHUNK_TYPE_NCAM_IMAGETTE, - CHUNK_TYPE_SHORT_CADENCE, - CHUNK_TYPE_LONG_CADENCE, - CHUNK_TYPE_SAT_IMAGETTE, - CHUNK_TYPE_OFFSET_BACKGROUND, /* N-CAM */ - CHUNK_TYPE_SMEARING, - CHUNK_TYPE_F_CHAIN -}; - - /** * @brief create an ICU compression configuration * @@ -217,13 +192,13 @@ uint32_t cmp_cfg_icu_buffers(struct cmp_cfg *cfg, void *data_to_compress, /** - * @brief set up the maximum length of the different data products types for + * @brief set up the maximum length of the different data product types for * an ICU compression * * @param cfg pointer to a compression configuration (created with the * cmp_cfg_icu_create() function) * @param max_used_bits pointer to a max_used_bits struct containing the maximum - * length of the different data products types + * length of the different data product types * * @returns 0 if all max_used_bits parameters are valid, non-zero if parameters are invalid * @@ -330,7 +305,7 @@ int cmp_cfg_fx_cob(struct cmp_cfg *cfg, * @brief set up the configuration parameters for an auxiliary science data compression * @note auxiliary compression data types are: DATA_TYPE_OFFSET, DATA_TYPE_BACKGROUND, DATA_TYPE_SMEARING, DATA_TYPE_F_CAM_OFFSET, DATA_TYPE_F_CAM_BACKGROUND - * @note not all parameters are needed for the every auxiliary compression data type + * @note not all parameters are needed for every auxiliary compression data type * * @param cfg pointer to a compression configuration (created * with the cmp_cfg_icu_create() function) @@ -419,7 +394,7 @@ static uint32_t map_to_pos(uint32_t value_to_map, unsigned int max_data_bits) /** - * @brief put the value of up to 32 bits into a big endian bitstream + * @brief put the value of up to 32 bits into a big-endian bitstream * * @param value the value to put into the bitstream * @param n_bits number of bits to put into the bitstream @@ -430,12 +405,13 @@ static uint32_t map_to_pos(uint32_t value_to_map, unsigned int max_data_bits) * @param max_stream_len maximum length of the bitstream in *bits*; is * ignored if bitstream_adr is NULL * - * @returns length in bits of the generated bitstream on success; returns - * negative in case of erroneous input; returns CMP_ERROR_SMALL_BUF if - * the bitstream buffer is too small to put the value in the bitstream + * @returns the length of the generated bitstream in bits on success or an error + * code (which can be tested with cmp_is_error()) in the event of an + * incorrect input or if the bitstream buffer is too small to put the + * value in the bitstream. */ -static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset, +static uint32_t put_n_bits32(uint32_t value, unsigned int n_bits, uint32_t bit_offset, uint32_t *bitstream_adr, unsigned int max_stream_len) { /* @@ -448,29 +424,25 @@ static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset, * |-----------------------------|XXX|XXX|-----------------------------| * |----------bits_left----------|n_bits-|---------bits_right----------| */ - unsigned int bits_left = bit_offset & 0x1F; - unsigned int bits_right = 64 - bits_left - n_bits; - unsigned int shift_left = 32 - n_bits; - int stream_len = (int)(n_bits + (unsigned int)bit_offset); + uint32_t bits_left = bit_offset & 0x1F; + uint32_t bits_right = 64 - bits_left - n_bits; + uint32_t shift_left = 32 - n_bits; + uint32_t stream_len = n_bits + bit_offset; /* no check for overflow */ uint32_t *local_adr; uint32_t mask, tmp; /* Leave in case of erroneous input */ - if (bit_offset < 0) - return -1; + RETURN_ERROR_IF((int)shift_left < 0, INT_DECODER, "cannot insert more than 32 bits into the bit stream"); /* check n_bits <= 32 */ if (n_bits == 0) return stream_len; - if ((int)shift_left < 0) /* check n_bits <= 32 */ - return -1; - if (!bitstream_adr) /* Do we need to write data to the bitstream? */ return stream_len; - /* Check if bitstream buffer is large enough */ - if ((unsigned int)stream_len > max_stream_len) - return CMP_ERROR_SMALL_BUF; + /* Check if the bitstream buffer is large enough */ + if (stream_len > max_stream_len) + return CMP_ERROR(SMALL_BUF_); local_adr = bitstream_adr + (bit_offset >> 5); @@ -502,15 +474,15 @@ static int put_n_bits32(uint32_t value, unsigned int n_bits, int bit_offset, * @brief forms the codeword according to the Rice code * * @param value value to be encoded (must be smaller or equal than cmp_ima_max_spill(m)) - * @param m Golomb parameter, only m's which are power of 2 are allowed + * @param m Golomb parameter, only m's which are a power of 2 are allowed * maximum allowed Golomb parameter is 0x80000000 * @param log2_m Rice parameter, is ilog_2(m) calculate outside function * for better performance * @param cw address where the code word is stored * * @warning no check of the validity of the input parameters! - * @returns the length of the formed code word in bits; code word is invalid if - * the return value is greater than 32 + * @returns the length of the formed code word in bits; the code word is invalid + * if the return value is greater than 32 */ static uint32_t rice_encoder(uint32_t value, uint32_t m, uint32_t log2_m, @@ -543,8 +515,8 @@ static uint32_t rice_encoder(uint32_t value, uint32_t m, uint32_t log2_m, * @param cw address where the code word is stored * * @warning no check of the validity of the input parameters! - * @returns the length of the formed code word in bits; code word is invalid if - * the return value is greater than 32 + * @returns the length of the formed code word in bits; the code word is invalid + * if the return value is greater than 32 */ static uint32_t golomb_encoder(uint32_t value, uint32_t m, uint32_t log2_m, @@ -571,7 +543,7 @@ static uint32_t golomb_encoder(uint32_t value, uint32_t m, uint32_t log2_m, /** - * @brief generate a code word without an outlier mechanism and put in the + * @brief generate a code word without an outlier mechanism and put it in the * bitstream * * @param value value to encode in the bitstream @@ -583,7 +555,7 @@ static uint32_t golomb_encoder(uint32_t value, uint32_t m, uint32_t log2_m, * is too small to put the value in the bitstream */ -static int encode_normal(uint32_t value, int stream_len, +static uint32_t encode_normal(uint32_t value, uint32_t stream_len, const struct encoder_setupt *setup) { uint32_t code_word, cw_len; @@ -597,7 +569,7 @@ static int encode_normal(uint32_t value, int stream_len, /** - * @brief subtract the model from the data, encode the result and put it into + * @brief subtract the model from the data, encode the result and puts it into * bitstream, for encoding outlier use the zero escape symbol mechanism * * @param data data to encode @@ -613,8 +585,8 @@ static int encode_normal(uint32_t value, int stream_len, * @note no check if the setup->spillover_par is in the allowed range */ -static int encode_value_zero(uint32_t data, uint32_t model, int stream_len, - const struct encoder_setupt *setup) +static uint32_t encode_value_zero(uint32_t data, uint32_t model, uint32_t stream_len, + const struct encoder_setupt *setup) { data -= model; /* possible underflow is intended */ @@ -635,14 +607,12 @@ static int encode_value_zero(uint32_t data, uint32_t model, int stream_len, /* use zero as escape symbol */ stream_len = encode_normal(0, stream_len, setup); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) return stream_len; /* put the data unencoded in the bitstream */ - stream_len = put_n_bits32(data, setup->max_data_bits, stream_len, + return put_n_bits32(data, setup->max_data_bits, stream_len, setup->bitstream_adr, setup->max_stream_len); - - return stream_len; } @@ -663,8 +633,8 @@ static int encode_value_zero(uint32_t data, uint32_t model, int stream_len, * @note no check if the setup->spillover_par is in the allowed range */ -static int encode_value_multi(uint32_t data, uint32_t model, int stream_len, - const struct encoder_setupt *setup) +static uint32_t encode_value_multi(uint32_t data, uint32_t model, uint32_t stream_len, + const struct encoder_setupt *setup) { uint32_t unencoded_data; unsigned int unencoded_data_len; @@ -680,9 +650,9 @@ static int encode_value_multi(uint32_t data, uint32_t model, int stream_len, /* * In this mode we put the difference between the data and the spillover * threshold value (unencoded_data) after an encoded escape symbol, which - * indicate that the next codeword is unencoded. - * We use different escape symbol depended on the size the needed bit of - * unencoded data: + * indicates that the next codeword is unencoded. + * We use different escape symbols depending on the size of the needed + * bit of unencoded data: * 0, 1, 2 bits needed for unencoded data -> escape symbol is spillover_par + 0 * 3, 4 bits needed for unencoded data -> escape symbol is spillover_par + 1 * 5, 6 bits needed for unencoded data -> escape symbol is spillover_par + 2 @@ -700,7 +670,7 @@ static int encode_value_multi(uint32_t data, uint32_t model, int stream_len, /* put the escape symbol in the bitstream */ stream_len = encode_normal(escape_sym, stream_len, setup); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) return stream_len; /* put the unencoded data in the bitstream */ @@ -727,7 +697,7 @@ static int encode_value_multi(uint32_t data, uint32_t model, int stream_len, * */ -static int encode_value_none(uint32_t value, uint32_t unused, int stream_len, +static uint32_t encode_value_none(uint32_t value, uint32_t unused, uint32_t stream_len, const struct encoder_setupt *setup) { (void)(unused); @@ -752,7 +722,7 @@ static int encode_value_none(uint32_t value, uint32_t unused, int stream_len, * the value or the model is bigger than the max_used_bits parameter allows */ -static int encode_value(uint32_t data, uint32_t model, int stream_len, +static uint32_t encode_value(uint32_t data, uint32_t model, uint32_t stream_len, const struct encoder_setupt *setup) { uint32_t mask = ~(0xFFFFFFFFU >> (32-setup->max_data_bits)); @@ -761,10 +731,7 @@ static int encode_value(uint32_t data, uint32_t model, int stream_len, data = round_fwd(data, setup->lossy_par); model = round_fwd(model, setup->lossy_par); - if (data & mask || model & mask) { - debug_print("Error: The data or the model of the data are bigger than expected."); - return CMP_ERROR_HIGH_VALUE; - } + RETURN_ERROR_IF(data & mask || model & mask, DATA_VALUE_TOO_LARGE, ""); return setup->encode_method_f(data, model, stream_len, setup); } @@ -856,7 +823,7 @@ static void configure_encoder_setup(struct encoder_setupt *setup, * bigger than the max_used_bits parameter allows */ -static int compress_imagette(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_imagette(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; struct encoder_setupt setup; @@ -896,7 +863,7 @@ static int compress_imagette(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(get_unaligned(&data_buf[i]), model, stream_len, &setup); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) break; if (up_model_buf) { @@ -923,7 +890,7 @@ static int compress_imagette(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_s_fx(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_s_fx(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -951,12 +918,12 @@ static int compress_s_fx(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, stream_len, &setup_exp_flag); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; if (up_model_buf) { up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, @@ -984,7 +951,7 @@ static int compress_s_fx(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_s_fx_efx(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_s_fx_efx(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1014,15 +981,15 @@ static int compress_s_fx_efx(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, stream_len, &setup_exp_flag); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].efx, model.efx, stream_len, &setup_efx); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) return stream_len; if (up_model_buf) { @@ -1053,7 +1020,7 @@ static int compress_s_fx_efx(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_s_fx_ncob(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_s_fx_ncob(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1083,20 +1050,20 @@ static int compress_s_fx_ncob(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, stream_len, &setup_exp_flag); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; if (up_model_buf) { up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, @@ -1128,7 +1095,7 @@ static int compress_s_fx_ncob(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1163,32 +1130,32 @@ static int compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, stream_len, &setup_exp_flag); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].efx, model.efx, stream_len, &setup_efx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ecob_x, model.ecob_x, stream_len, &setup_ecob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ecob_y, model.ecob_y, stream_len, &setup_ecob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; if (up_model_buf) { up_model_buf[i].exp_flags = cmp_up_model(data_buf[i].exp_flags, model.exp_flags, @@ -1226,7 +1193,7 @@ static int compress_s_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len * value in the bitstream */ -static int compress_f_fx(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_f_fx(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1252,8 +1219,8 @@ static int compress_f_fx(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; if (up_model_buf) { up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, @@ -1279,7 +1246,7 @@ static int compress_f_fx(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_f_fx_efx(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_f_fx_efx(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1307,12 +1274,12 @@ static int compress_f_fx_efx(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].efx, model.efx, stream_len, &setup_efx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; if (up_model_buf) { up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, @@ -1340,7 +1307,7 @@ static int compress_f_fx_efx(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_f_fx_ncob(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_f_fx_ncob(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1368,16 +1335,16 @@ static int compress_f_fx_ncob(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; if (up_model_buf) { up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, @@ -1407,7 +1374,7 @@ static int compress_f_fx_ncob(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1439,28 +1406,28 @@ static int compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len for (i = 0;; i++) { stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].efx, model.efx, stream_len, &setup_efx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ecob_x, model.ecob_x, stream_len, &setup_ecob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ecob_y, model.ecob_y, stream_len, &setup_ecob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; if (up_model_buf) { up_model_buf[i].fx = cmp_up_model(data_buf[i].fx, model.fx, @@ -1496,7 +1463,7 @@ static int compress_f_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len * value in the bitstream */ -static int compress_l_fx(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_l_fx(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1526,16 +1493,16 @@ static int compress_l_fx(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, stream_len, &setup_exp_flag); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance, stream_len, &setup_fx_var); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; if (up_model_buf) { up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, @@ -1565,7 +1532,7 @@ static int compress_l_fx(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_l_fx_efx(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_l_fx_efx(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1597,20 +1564,20 @@ static int compress_l_fx_efx(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, stream_len, &setup_exp_flag); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].efx, model.efx, stream_len, &setup_efx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance, stream_len, &setup_fx_var); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; if (up_model_buf) { up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, @@ -1642,7 +1609,7 @@ static int compress_l_fx_efx(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_l_fx_ncob(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_l_fx_ncob(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1669,7 +1636,7 @@ static int compress_l_fx_ncob(const struct cmp_cfg *cfg, int stream_len) cfg->round, cfg->max_used_bits->l_fx, cfg); configure_encoder_setup(&setup_ncob, cfg->cmp_par_ncob, cfg->spill_ncob, cfg->round, cfg->max_used_bits->l_ncob, cfg); - /* we use compression parameter for both variance data fields */ + /* we use the cmp_par_fx_cob_variance parameter for fx and cob variance data */ configure_encoder_setup(&setup_fx_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, cfg->round, cfg->max_used_bits->l_fx_variance, cfg); configure_encoder_setup(&setup_cob_var, cfg->cmp_par_fx_cob_variance, cfg->spill_fx_cob_variance, @@ -1678,32 +1645,32 @@ static int compress_l_fx_ncob(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, stream_len, &setup_exp_flag); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance, stream_len, &setup_fx_var); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].cob_x_variance, model.cob_x_variance, stream_len, &setup_cob_var); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].cob_y_variance, model.cob_y_variance, stream_len, &setup_cob_var); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; if (up_model_buf) { up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, @@ -1741,7 +1708,7 @@ static int compress_l_fx_ncob(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1781,44 +1748,44 @@ static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len for (i = 0;; i++) { stream_len = encode_value(data_buf[i].exp_flags, model.exp_flags, stream_len, &setup_exp_flag); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx, model.fx, stream_len, &setup_fx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_x, model.ncob_x, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ncob_y, model.ncob_y, stream_len, &setup_ncob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].efx, model.efx, stream_len, &setup_efx); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ecob_x, model.ecob_x, stream_len, &setup_ecob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].ecob_y, model.ecob_y, stream_len, &setup_ecob); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].fx_variance, model.fx_variance, stream_len, &setup_fx_var); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].cob_x_variance, model.cob_x_variance, stream_len, &setup_cob_var); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; stream_len = encode_value(data_buf[i].cob_y_variance, model.cob_y_variance, stream_len, &setup_cob_var); - if (stream_len <= 0) - return stream_len; + if (cmp_is_error(stream_len)) + break; if (up_model_buf) { up_model_buf[i].exp_flags = cmp_up_model32(data_buf[i].exp_flags, model.exp_flags, @@ -1861,7 +1828,7 @@ static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg, int stream_len * value in the bitstream */ -static int compress_offset(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_offset(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1904,11 +1871,11 @@ static int compress_offset(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].mean, model.mean, stream_len, &setup_mean); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) return stream_len; stream_len = encode_value(data_buf[i].variance, model.variance, stream_len, &setup_var); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) return stream_len; if (up_model_buf) { @@ -1936,7 +1903,7 @@ static int compress_offset(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_background(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_background(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -1983,15 +1950,15 @@ static int compress_background(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].mean, model.mean, stream_len, &setup_mean); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) return stream_len; stream_len = encode_value(data_buf[i].variance, model.variance, stream_len, &setup_var); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) return stream_len; stream_len = encode_value(data_buf[i].outlier_pixels, model.outlier_pixels, stream_len, &setup_pix); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) return stream_len; if (up_model_buf) { @@ -2022,7 +1989,7 @@ static int compress_background(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int compress_smearing(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_smearing(const struct cmp_cfg *cfg, uint32_t stream_len) { size_t i; @@ -2052,15 +2019,15 @@ static int compress_smearing(const struct cmp_cfg *cfg, int stream_len) for (i = 0;; i++) { stream_len = encode_value(data_buf[i].mean, model.mean, stream_len, &setup_mean); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) return stream_len; stream_len = encode_value(data_buf[i].variance_mean, model.variance_mean, stream_len, &setup_var_mean); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) return stream_len; stream_len = encode_value(data_buf[i].outlier_pixels, model.outlier_pixels, stream_len, &setup_pix); - if (stream_len <= 0) + if (cmp_is_error(stream_len)) return stream_len; if (up_model_buf) { @@ -2081,6 +2048,38 @@ static int compress_smearing(const struct cmp_cfg *cfg, int stream_len) } +/** + * @brief checks if the ICU compression configuration is valid + * + * @param cfg pointer to the cmp_cfg structure to be validated + * + * @returns an error code if any of the configuration parameters are invalid, + * otherwise returns CMP_ERROR_NO_ERROR on valid configuration + */ + +static uint32_t cmp_cfg_icu_is_invalid_error_code(const struct cmp_cfg *cfg) +{ + + RETURN_ERROR_IF(cmp_cfg_gen_par_is_invalid(cfg, ICU_CHECK) , PAR_GENERIC, ""); + RETURN_ERROR_IF(cmp_cfg_icu_buffers_is_invalid(cfg), PAR_BUFFERS, ""); + + if (cfg->cmp_mode != CMP_MODE_RAW) + RETURN_ERROR_IF(cmp_cfg_icu_max_used_bits_out_of_limit(cfg->max_used_bits), GENERIC, ""); + + if (cmp_imagette_data_type_is_used(cfg->data_type)) { + RETURN_ERROR_IF(cmp_cfg_imagette_is_invalid(cfg, ICU_CHECK), PAR_SPECIFIC, ""); + } else if (cmp_fx_cob_data_type_is_used(cfg->data_type)) { + RETURN_ERROR_IF(cmp_cfg_fx_cob_is_invalid(cfg), PAR_SPECIFIC, ""); + } else if (cmp_aux_data_type_is_used(cfg->data_type)) { + RETURN_ERROR_IF(cmp_cfg_aux_is_invalid(cfg), PAR_SPECIFIC, ""); + } else { + RETURN_ERROR(INT_DATA_TYPE_UNSUPPORTED, ""); + } + + return CMP_ERROR(NO_ERROR); +} + + /** * @brief fill the last part of the bitstream with zeros * @@ -2092,13 +2091,10 @@ static int compress_smearing(const struct cmp_cfg *cfg, int stream_len) * value in the bitstream */ -static int pad_bitstream(const struct cmp_cfg *cfg, int cmp_size) +static uint32_t pad_bitstream(const struct cmp_cfg *cfg, uint32_t cmp_size) { unsigned int output_buf_len_bits, n_pad_bits; - if (cmp_size < 0) - return cmp_size; - if (!cfg->icu_output_buf) return cmp_size; @@ -2109,12 +2105,10 @@ static int pad_bitstream(const struct cmp_cfg *cfg, int cmp_size) /* maximum length of the bitstream/icu_output_buf in bits */ output_buf_len_bits = cmp_buffer_length_to_bits(cfg->buffer_length); - n_pad_bits = 32 - ((unsigned int)cmp_size & 0x1FU); + n_pad_bits = 32 - (cmp_size & 0x1FU); if (n_pad_bits < 32) { - int n_bits = put_n_bits32(0, n_pad_bits, cmp_size, cfg->icu_output_buf, - output_buf_len_bits); - if (n_bits < 0) - return n_bits; + FORWARD_IF_ERROR(put_n_bits32(0, n_pad_bits, cmp_size, + cfg->icu_output_buf, output_buf_len_bits), ""); } return cmp_size; @@ -2131,36 +2125,30 @@ static int pad_bitstream(const struct cmp_cfg *cfg, int cmp_size) * @note the validity of the cfg structure is checked before the compression is * started * - * @returns the bit length of the bitstream on success; negative on error, - * CMP_ERROR_SMALL_BUF (-2) if the compressed data buffer is too small to - * hold the whole compressed data, CMP_ERROR_HIGH_VALUE (-3) if a data or - * model value is bigger than the max_used_bits parameter + * @returns the bit length of the bitstream on success or an error code if it + * fails (which can be tested with cmp_is_error()) */ -static int compress_data_internal(const struct cmp_cfg *cfg, int stream_len) +static uint32_t compress_data_internal(const struct cmp_cfg *cfg, uint32_t stream_len) { - int bitsize = 0; + uint32_t bitsize = 0; - if (!cfg) - return -1; + FORWARD_IF_ERROR(stream_len, ""); + RETURN_ERROR_IF(cfg == NULL, GENERIC, ""); + RETURN_ERROR_IF(stream_len & 0x7, GENERIC, "The stream_len parameter must be a multiple of 8."); - if (stream_len < 0) - return stream_len; + if (raw_mode_is_used(cfg->cmp_mode) && cfg->icu_output_buf) { + uint32_t raw_stream_size = (stream_len >> 3) + + cfg->samples * (uint32_t)size_of_a_sample(cfg->data_type); + /* TODO: move this check to the memcpy */ + RETURN_ERROR_IF(raw_stream_size > cfg->buffer_length, SMALL_BUF_, ""); + } if (cfg->samples == 0) /* nothing to compress we are done */ return stream_len; - if (stream_len & 0x7) { - debug_print("Error: The stream_len parameter must be a multiple of 8."); - return -1; - } - - if (raw_mode_is_used(cfg->cmp_mode) && cfg->icu_output_buf) - if (((uint32_t)stream_len >> 3) + cfg->samples * size_of_a_sample(cfg->data_type) > cfg->buffer_length) - return CMP_ERROR_SMALL_BUF; + FORWARD_IF_ERROR(cmp_cfg_icu_is_invalid_error_code(cfg), ""); - if (cmp_cfg_icu_is_invalid(cfg)) - return -1; if (raw_mode_is_used(cfg->cmp_mode)) { uint32_t raw_size = cfg->samples * (uint32_t)size_of_a_sample(cfg->data_type); @@ -2169,14 +2157,10 @@ static int compress_data_internal(const struct cmp_cfg *cfg, int stream_len) uint8_t *p = (uint8_t *)cfg->icu_output_buf + (stream_len >> 3); memcpy(p, cfg->input_buf, raw_size); - if (cpu_to_be_data_type(p, raw_size, cfg->data_type)) - return -1; + RETURN_ERROR_IF(cpu_to_be_data_type(p, raw_size, cfg->data_type), GENERIC, ""); } - bitsize += stream_len + (int)raw_size*8; /* convert to bits */ + bitsize += stream_len + raw_size*8; /* convert to bits */ } else { - if (cfg->icu_output_buf && cfg->samples/3 > cfg->buffer_length) - debug_print("Warning: The size of the compressed_data buffer is 3 times smaller than the data_to_compress. This is probably unintended."); - switch (cfg->data_type) { case DATA_TYPE_IMAGETTE: case DATA_TYPE_IMAGETTE_ADAPTIVE: @@ -2241,12 +2225,12 @@ static int compress_data_internal(const struct cmp_cfg *cfg, int stream_len) /* LCOV_EXCL_START */ case DATA_TYPE_UNKNOWN: default: - debug_print("Error: Data type not supported."); - bitsize = -1; + RETURN_ERROR(INT_DATA_TYPE_UNSUPPORTED, ""); } /* LCOV_EXCL_STOP */ } + FORWARD_IF_ERROR(bitsize, ""); bitsize = pad_bitstream(cfg, bitsize); return bitsize; @@ -2272,7 +2256,7 @@ static int compress_data_internal(const struct cmp_cfg *cfg, int stream_len) int icu_compress_data(const struct cmp_cfg *cfg) { struct cmp_cfg cfg_cpy; - int dst_capacity_used = 0; + uint32_t dst_capacity_used = 0; if (cfg) { if (cfg->samples == 0) @@ -2296,9 +2280,9 @@ int icu_compress_data(const struct cmp_cfg *cfg) cfg_cpy.model_buf = (uint8_t *)cfg->model_buf + COLLECTION_HDR_SIZE; dst_capacity_used = COLLECTION_HDR_SIZE*8; } - return compress_data_internal(&cfg_cpy, dst_capacity_used); + return (int)compress_data_internal(&cfg_cpy, dst_capacity_used); } - return compress_data_internal(NULL, dst_capacity_used); + return (int)compress_data_internal(NULL, dst_capacity_used); } @@ -2328,18 +2312,17 @@ static uint32_t cmp_guess_good_spill(uint32_t golomb_par) * size of the compressed collection size field * itself) * - * @returns 0 on success; -1 on failure + * @returns error code */ -static int set_cmp_col_size(uint8_t *cmp_col_size_field, int32_t cmp_col_size) +static uint32_t set_cmp_col_size(uint8_t *cmp_col_size_field, uint32_t cmp_col_size) { uint16_t const v = cpu_to_be16((uint16_t)cmp_col_size); - if (cmp_col_size > UINT16_MAX) - return -1; + RETURN_ERROR_IF(cmp_col_size > UINT16_MAX, INT_CMP_COL_TOO_LARGE, + "%"PRIu32" is bigger than the maximum allowed compression collection size", cmp_col_size_field); - if (cmp_col_size_field) - memcpy(cmp_col_size_field, &v, CMP_COLLECTION_FILD_SIZE); + memcpy(cmp_col_size_field, &v, CMP_COLLECTION_FILD_SIZE); return 0; } @@ -2360,26 +2343,32 @@ static int set_cmp_col_size(uint8_t *cmp_col_size_field, int32_t cmp_col_size) * @param dst_size the already used size of the dst buffer in bytes * * @returns the size of the compressed data in bytes (new dst_size) on - * success; negative on error, CMP_ERROR_SMALL_BUF (-2) if the compressed - * data buffer is too small to hold the whole compressed data; the - * compressed and updated model are only valid on positive return - * values + * success or an error code if it fails (which can be tested with + * cmp_is_error()) */ -static int32_t cmp_collection(uint8_t *col, uint8_t *model, uint8_t *updated_model, - uint32_t *dst, uint32_t dst_capacity, - struct cmp_cfg *cfg, int32_t dst_size) +static uint32_t cmp_collection(uint8_t *col, uint8_t *model, uint8_t *updated_model, + uint32_t *dst, uint32_t dst_capacity, + struct cmp_cfg *cfg, uint32_t dst_size) { - int32_t dst_size_begin = dst_size; - int dst_size_bits; + uint32_t dst_size_begin = dst_size; + uint32_t dst_size_bits; + struct collection_hdr *col_hdr = (struct collection_hdr *)col; + uint16_t col_data_length = cmp_col_get_data_length(col_hdr); + uint16_t sample_size; + + /* sanity check of the collection header */ + cfg->data_type = convert_subservice_to_cmp_data_type(cmp_col_get_subservice(col_hdr)); + sample_size = (uint16_t)size_of_a_sample(cfg->data_type); + RETURN_ERROR_IF(sample_size == 0, COL_SUBSERVICE_UNSUPPORTED, + "unsupported subservice: %u", cmp_col_get_subservice(col_hdr)); + RETURN_ERROR_IF(col_data_length % sample_size, COL_SIZE_INCONSISTENT, + "col_data_length: %u %% sample_size: %u != 0", col_data_length, sample_size); + cfg->samples = col_data_length/sample_size; - if (dst_size < 0) - return dst_size; - if (!col) - return -1; if (cfg->cmp_mode != CMP_MODE_RAW) { - /* we put the compressed data size be */ + /* hear we reserve space for the compressed data size field */ dst_size += CMP_COLLECTION_FILD_SIZE; } @@ -2387,12 +2376,11 @@ static int32_t cmp_collection(uint8_t *col, uint8_t *model, uint8_t *updated_mod * into the compressed data */ if (dst) { - if ((uint32_t)dst_size + COLLECTION_HDR_SIZE > dst_capacity) - return CMP_ERROR_SMALL_BUF; + RETURN_ERROR_IF(dst_size + COLLECTION_HDR_SIZE > dst_capacity, + SMALL_BUF_, ""); memcpy((uint8_t *)dst + dst_size, col, COLLECTION_HDR_SIZE); } dst_size += COLLECTION_HDR_SIZE; - if (model_mode_is_used(cfg->cmp_mode) && updated_model) memcpy(updated_model, col, COLLECTION_HDR_SIZE); @@ -2404,51 +2392,42 @@ static int32_t cmp_collection(uint8_t *col, uint8_t *model, uint8_t *updated_mod if (updated_model) cfg->icu_new_model_buf = updated_model + COLLECTION_HDR_SIZE; - { - struct collection_hdr *col_hdr = (struct collection_hdr *)col; - uint8_t subservice = cmp_col_get_subservice(col_hdr); - uint16_t col_data_length = cmp_col_get_data_length(col_hdr); - - cfg->data_type = convert_subservice_to_cmp_data_type(subservice); - - if (!size_of_a_sample(cfg->data_type)) - return -1; - if (col_data_length % size_of_a_sample(cfg->data_type)) - return -1; - cfg->samples = col_data_length/size_of_a_sample(cfg->data_type); - if ((dst && (uint32_t)dst_size + col_data_length > dst_capacity) || - cfg->cmp_mode == CMP_MODE_RAW) { - cfg->buffer_length = dst_capacity; + /* is enough capacity in the dst buffer to store the data uncompressed */ + if ((!dst || dst_capacity >= dst_size + col_data_length) && + cfg->cmp_mode != CMP_MODE_RAW) { + /* we set the compressed buffer size to the data size -1 to provoke + * a CMP_ERROR_SMALL_BUF_ error if the data are not compressible + */ + cfg->buffer_length = dst_size + col_data_length - 1; + dst_size_bits = compress_data_internal(cfg, dst_size<<3); + + if (cmp_get_error_code(dst_size_bits) == CMP_ERROR_SMALL_BUF_ || + (!dst && cmp_bit_to_byte(dst_size_bits)-dst_size > col_data_length)) { /* if dst == NULL compress_data_internal will not return a CMP_ERROR_SMALL_BUF */ + /* can not compress the data with the given parameters; + * put them uncompressed (raw) into the dst buffer */ + enum cmp_mode cmp_mode_cpy = cfg->cmp_mode; + + cfg->buffer_length = dst_size + col_data_length; + cfg->cmp_mode = CMP_MODE_RAW; dst_size_bits = compress_data_internal(cfg, dst_size<<3); - if (dst_size < 0) - return dst_size_bits; - } else { - /* we limit the size of the compressed data buffer */ - cfg->buffer_length = (uint32_t)dst_size + col_data_length-1; - dst_size_bits = compress_data_internal(cfg, dst_size<<3); - if (dst_size_bits == CMP_ERROR_SMALL_BUF || - (!dst && (int)cmp_bit_to_byte((unsigned int)dst_size_bits)-dst_size > col_data_length)) { /* if dst == NULL icu_compress_data_2 will not return a CMP_ERROR_SMALL_BUF */ - enum cmp_mode cmp_mode_cpy = cfg->cmp_mode; - - cfg->buffer_length = (uint32_t)dst_size + col_data_length; - cfg->cmp_mode = CMP_MODE_RAW; - dst_size_bits = compress_data_internal(cfg, dst_size<<3); - cfg->cmp_mode = cmp_mode_cpy; - if (model_mode_is_used(cfg->cmp_mode) && cfg->icu_new_model_buf) - memcpy(cfg->icu_new_model_buf, cfg->input_buf, col_data_length); - } + cfg->cmp_mode = cmp_mode_cpy; + /* updated model is in this case a copy of the data to compress */ + if (model_mode_is_used(cfg->cmp_mode) && cfg->icu_new_model_buf) + memcpy(cfg->icu_new_model_buf, cfg->input_buf, col_data_length); } - if (dst_size_bits < 0) - return dst_size_bits; + } else { + cfg->buffer_length = dst_capacity; + dst_size_bits = compress_data_internal(cfg, dst_size<<3); } + FORWARD_IF_ERROR(dst_size_bits, "compression failed"); - dst_size = (int32_t)cmp_bit_to_byte((unsigned int)dst_size_bits); /*TODO: fix casts */ - if (dst && cfg->cmp_mode != CMP_MODE_RAW) { - int32_t cmp_col_size = dst_size - dst_size_begin - + dst_size = cmp_bit_to_byte(dst_size_bits); + if (cfg->cmp_mode != CMP_MODE_RAW && dst) { + uint8_t *cmp_col_size_field = (uint8_t *)dst+dst_size_begin; + uint32_t cmp_col_size = dst_size - dst_size_begin - COLLECTION_HDR_SIZE - CMP_COLLECTION_FILD_SIZE; - if (set_cmp_col_size((uint8_t *)dst+dst_size_begin, cmp_col_size)) - return -1; + FORWARD_IF_ERROR(set_cmp_col_size(cmp_col_size_field, cmp_col_size), ""); } return dst_size; @@ -2458,7 +2437,7 @@ static int32_t cmp_collection(uint8_t *col, uint8_t *model, uint8_t *updated_mod /** * @brief builds a compressed entity header for a compressed chunk * - * @param ent start address of the compression entity header + * @param entity start address of the compression entity header * (can be NULL if you only want the entity header * size) * @param chunk_size the original size of the chunk in bytes @@ -2468,29 +2447,25 @@ static int32_t cmp_collection(uint8_t *col, uint8_t *model, uint8_t *updated_mod * @param cmp_ent_size_byte the size of the compression entity (entity * header plus compressed data) * - * @return the size of the compressed entity header in bytes, or -1 if an error - * occurred + * @return the size of the compressed entity header in bytes or an error code + * if it fails (which can be tested with cmp_is_error()) */ -static int cmp_ent_build_chunk_header(struct cmp_entity *ent, uint32_t chunk_size, - const struct cmp_cfg *cfg, uint64_t start_timestamp, - int32_t cmp_ent_size_byte) +static uint32_t cmp_ent_build_chunk_header(uint32_t *entity, uint32_t chunk_size, + const struct cmp_cfg *cfg, uint64_t start_timestamp, + uint32_t cmp_ent_size_byte) { - if (ent) { /* setup the compressed entity header */ + if (entity) { /* setup the compressed entity header */ + struct cmp_entity *ent = (struct cmp_entity *)entity; int err = 0; - if (cmp_ent_size_byte < 0) - cmp_ent_size_byte = 0; - err |= cmp_ent_set_version_id(ent, version_identifier); - err |= cmp_ent_set_size(ent, (uint32_t)cmp_ent_size_byte); - if (cmp_ent_set_original_size(ent, chunk_size)) { - debug_print("Error: The size of the chunk is too."); - return -1; - } - err |= cmp_ent_set_start_timestamp(ent, start_timestamp); + err |= cmp_ent_set_version_id(ent, version_identifier); /* set by compress_chunk_init */ + err |= cmp_ent_set_size(ent, cmp_ent_size_byte); + err |= cmp_ent_set_original_size(ent, chunk_size); err |= cmp_ent_set_data_type(ent, DATA_TYPE_CHUNK, cfg->cmp_mode == CMP_MODE_RAW); err |= cmp_ent_set_cmp_mode(ent, cfg->cmp_mode); err |= cmp_ent_set_model_value(ent, cfg->model_value); + /* model id/counter are set by the user with the compress_chunk_set_model_id_and_counter() */ err |= cmp_ent_set_model_id(ent, 0); err |= cmp_ent_set_model_counter(ent, 0); if (cfg->max_used_bits) @@ -2512,9 +2487,11 @@ static int cmp_ent_build_chunk_header(struct cmp_entity *ent, uint32_t chunk_siz err |= cmp_ent_set_non_ima_spill6(ent, cfg->spill_par_6); err |= cmp_ent_set_non_ima_cmp_par6(ent, cfg->cmp_par_6); } - err |= cmp_ent_set_end_timestamp(ent, get_timestamp()); - if (err) - return -1; + RETURN_ERROR_IF(err, ENTITY_HEADER, ""); + RETURN_ERROR_IF(cmp_ent_set_start_timestamp(ent, start_timestamp), + ENTITY_TIMESTAMP, ""); + RETURN_ERROR_IF(cmp_ent_set_end_timestamp(ent, get_timestamp()), + ENTITY_TIMESTAMP, ""); } if (cfg->cmp_mode == CMP_MODE_RAW) @@ -2525,20 +2502,38 @@ static int cmp_ent_build_chunk_header(struct cmp_entity *ent, uint32_t chunk_siz /** - * @brief map a sub-service to a chunk service according to + * @brief types of chunks containing different types of collections + * according to DetailedBudgetWorking_2023-10-11 + */ + +enum chunk_type { + CHUNK_TYPE_UNKNOWN, + CHUNK_TYPE_NCAM_IMAGETTE, + CHUNK_TYPE_SHORT_CADENCE, + CHUNK_TYPE_LONG_CADENCE, + CHUNK_TYPE_SAT_IMAGETTE, + CHUNK_TYPE_OFFSET_BACKGROUND, /* N-CAM */ + CHUNK_TYPE_SMEARING, + CHUNK_TYPE_F_CHAIN +}; + + +/** + * @brief get the chunk_type of a collection + * @details map a sub-service to a chunk service according to * DetailedBudgetWorking_2023-10-11 * - * @param subservice subservice of a science data product + * @param col pointer to a collection header * - * @returns the chunk type of the subservice on success, CHUNK_TYPE_UNKNOWN on + * @returns chunk type of the collection, CHUNK_TYPE_UNKNOWN on * failure */ -static enum chunk_type get_chunk_type(uint8_t subservice) +static enum chunk_type cmp_col_get_chunk_type(const struct collection_hdr *col) { - enum chunk_type chunk_type = CHUNK_TYPE_UNKNOWN; + enum chunk_type chunk_type; - switch (subservice) { + switch (cmp_col_get_subservice(col)) { case SST_NCxx_S_SCIENCE_IMAGETTE: chunk_type = CHUNK_TYPE_NCAM_IMAGETTE; break; @@ -2574,32 +2569,16 @@ static enum chunk_type get_chunk_type(uint8_t subservice) case SST_NCxx_S_SCIENCE_F_FX_NCOB: case SST_NCxx_S_SCIENCE_F_FX_EFX_NCOB_ECOB: debug_print("Error: No chunk is defined for fast cadence subservices"); - chunk_type = CHUNK_TYPE_UNKNOWN; - break; + /* fall through */ default: - debug_print("Error: Unknown subservice: %i.", subservice); chunk_type = CHUNK_TYPE_UNKNOWN; break; - }; + } return chunk_type; } -/** - * @brief get the chunk_type of a collection - * - * @param col pointer to a collection header - * - * @returns chunk type of the collection - */ - -static enum chunk_type cmp_col_get_chunk_type(const struct collection_hdr *col) -{ - return get_chunk_type(cmp_col_get_subservice(col)); -} - - /** * @brief Set the compression configuration from the compression parameters * based on the chunk type @@ -2607,15 +2586,14 @@ static enum chunk_type cmp_col_get_chunk_type(const struct collection_hdr *col) * @param[in] par pointer to a compression parameters struct * @param[in] chunk_type the type of the chunk to be compressed * @param[out] cfg pointer to a compression configuration - * - * @returns 0 success; -1 on failure */ -static int init_cmp_cfg_from_cmp_par(const struct cmp_par *par, enum chunk_type chunk_type, +static void init_cmp_cfg_from_cmp_par(const struct cmp_par *par, enum chunk_type chunk_type, struct cmp_cfg *cfg) { memset(cfg, 0, sizeof(struct cmp_cfg)); + /* the ranges of the parameters are checked in cmp_cfg_icu_is_invalid() */ cfg->cmp_mode = par->cmp_mode; cfg->model_value = par->model_value; cfg->round = par->lossy_par; @@ -2669,9 +2647,8 @@ static int init_cmp_cfg_from_cmp_par(const struct cmp_par *par, enum chunk_type cfg->cmp_par_background_pixels_error = par->fc_background_outlier_pixels; break; case CHUNK_TYPE_UNKNOWN: - default: - return -1; - }; + break; + } cfg->spill_par_1 = cmp_guess_good_spill(cfg->cmp_par_1); cfg->spill_par_2 = cmp_guess_good_spill(cfg->cmp_par_2); @@ -2679,7 +2656,6 @@ static int init_cmp_cfg_from_cmp_par(const struct cmp_par *par, enum chunk_type cfg->spill_par_4 = cmp_guess_good_spill(cfg->cmp_par_4); cfg->spill_par_5 = cmp_guess_good_spill(cfg->cmp_par_5); cfg->spill_par_6 = cmp_guess_good_spill(cfg->cmp_par_6); - return 0; } @@ -2691,7 +2667,7 @@ static int init_cmp_cfg_from_cmp_par(const struct cmp_par *par, enum chunk_type * * @param return_timestamp pointer to a function returning a current 48-bit * timestamp - * @param version_id version identifier of the applications software + * @param version_id application software version identifier */ void compress_chunk_init(uint64_t(return_timestamp)(void), uint32_t version_id) @@ -2724,59 +2700,54 @@ void compress_chunk_init(uint64_t(return_timestamp)(void), uint32_t version_id) * compress_chunk_cmp_size_bound(chunk, chunk_size) * as it eliminates one potential failure scenario: * not enough space in the dst buffer to write the - * compressed data; size is internally round down + * compressed data; size is internally rounded down * to a multiple of 4 - * @returns the byte size of the compressed_data buffer on success; negative on - * error, CMP_ERROR_SMALL_BUF (-2) if the compressed data buffer is too - * small to hold the whole compressed data; the compressed and updated - * model are only valid on non negative return values + * @returns the byte size of the compressed data or an error code if it + * fails (which can be tested with cmp_is_error()) */ -int32_t compress_chunk(void *chunk, uint32_t chunk_size, - void *chunk_model, void *updated_chunk_model, - uint32_t *dst, uint32_t dst_capacity, - const struct cmp_par *cmp_par) +uint32_t compress_chunk(void *chunk, uint32_t chunk_size, + void *chunk_model, void *updated_chunk_model, + uint32_t *dst, uint32_t dst_capacity, + const struct cmp_par *cmp_par) { uint64_t start_timestamp = get_timestamp(); - size_t read_bytes; struct collection_hdr *col = (struct collection_hdr *)chunk; - int32_t cmp_size_byte; /* size of the compressed data in bytes */ enum chunk_type chunk_type; struct cmp_cfg cfg; - int err; + uint32_t cmp_size_byte; /* size of the compressed data in bytes */ + size_t read_bytes; - if (!chunk) { - debug_print("Error: Pointer to the data chunk is NULL. No data no compression."); - return -1; - } - if (chunk_size < COLLECTION_HDR_SIZE) { - debug_print("Error: The chunk size is smaller than the minimum size."); - return -1; - } - if (chunk_size > CMP_ENTITY_MAX_ORIGINAL_SIZE) { - debug_print("Error: The chunk size is bigger than the maximum allowed chunk size."); - return -1; - } + RETURN_ERROR_IF(chunk == NULL, CHUNK_NULL, ""); + RETURN_ERROR_IF(chunk_size < COLLECTION_HDR_SIZE, CHUNK_SIZE_INCONSISTENT, + "chunk_size: %"PRIu32"", chunk_size); + RETURN_ERROR_IF(chunk_size > CMP_ENTITY_MAX_ORIGINAL_SIZE, CHUNK_TOO_LARGE, + "chunk_size: %"PRIu32"", chunk_size); chunk_type = cmp_col_get_chunk_type(col); - if (init_cmp_cfg_from_cmp_par(cmp_par, chunk_type, &cfg)) - return -1; + RETURN_ERROR_IF(chunk_type == CHUNK_TYPE_UNKNOWN, COL_SUBSERVICE_UNSUPPORTED, + "unsupported subservice: %u", cmp_col_get_subservice(col)); + + init_cmp_cfg_from_cmp_par(cmp_par, chunk_type, &cfg); - /* we will build the compression header after the compression of the chunk */ + /* reserve space for the compression entity header, we will build the + * header after the compression of the chunk + */ cmp_size_byte = cmp_ent_build_chunk_header(NULL, chunk_size, &cfg, start_timestamp, 0); if (dst) { - if (dst_capacity < (uint32_t)cmp_size_byte) { - debug_print("Error: The destination capacity is smaller than the minimum compression entity size."); - return CMP_ERROR_SMALL_BUF; - } - memset(dst, 0, (uint32_t)cmp_size_byte); + RETURN_ERROR_IF(dst_capacity < cmp_size_byte, SMALL_BUF_, + "dst_capacity must be at least as large as the minimum size of the compression unit."); + memset(dst, 0, cmp_size_byte); } + /* compress one collection after another */ for (read_bytes = 0; read_bytes <= chunk_size - COLLECTION_HDR_SIZE; - read_bytes += cmp_col_get_size(col)) { + read_bytes += cmp_col_get_size(col)) + { uint8_t *col_model = NULL; uint8_t *col_up_model = NULL; + /* setup pointers for the next collection we want to compress */ col = (struct collection_hdr *)((uint8_t *)chunk + read_bytes); if (chunk_model) @@ -2784,26 +2755,21 @@ int32_t compress_chunk(void *chunk, uint32_t chunk_size, if (updated_chunk_model) col_up_model = ((uint8_t *)updated_chunk_model + read_bytes); - if (cmp_col_get_chunk_type(col) != chunk_type) { - debug_print("Error: The chunk contains collections with an incompatible mix of subservices."); - return -1; - } + RETURN_ERROR_IF(cmp_col_get_chunk_type(col) != chunk_type, CHUNK_SUBSERVICE_INCONSISTENT, ""); + + /* chunk size is inconsistent with the sum of sizes in the collection headers */ if (read_bytes + cmp_col_get_size(col) > chunk_size) break; cmp_size_byte = cmp_collection((uint8_t *)col, col_model, col_up_model, dst, dst_capacity, &cfg, cmp_size_byte); + FORWARD_IF_ERROR(cmp_size_byte, "error occurred when compressing the collection with offset %u", read_bytes); } - if (read_bytes != chunk_size) { - debug_print("Error: The sum of the compressed collections does not match the size of the data in the compression header."); - return -1; - } + RETURN_ERROR_IF(read_bytes != chunk_size, CHUNK_SIZE_INCONSISTENT, ""); - err = cmp_ent_build_chunk_header((struct cmp_entity *)dst, chunk_size, - &cfg, start_timestamp, cmp_size_byte); - if (err < 0) - return err; + FORWARD_IF_ERROR(cmp_ent_build_chunk_header(dst, chunk_size, &cfg, + start_timestamp, cmp_size_byte), ""); return cmp_size_byte; } @@ -2811,7 +2777,6 @@ int32_t compress_chunk(void *chunk, uint32_t chunk_size, /** * @brief returns the maximum compressed size in a worst case scenario - * * In case the input data is not compressible * This function is primarily useful for memory allocation purposes * (destination buffer size). @@ -2820,56 +2785,67 @@ int32_t compress_chunk(void *chunk, uint32_t chunk_size, * COMPRESS_CHUNK_BOUND macro for compilation-time evaluation * (stack memory allocation for example) * - * @param chunk pointer to the chunk you want compress + * @param chunk pointer to the chunk you want to compress * @param chunk_size size of the chunk in bytes * - * @returns maximum compressed size for a chunk compression; 0 on error + * @returns maximum compressed size for a chunk compression on success or an + * error code if it fails (which can be tested with cmp_is_error()) */ uint32_t compress_chunk_cmp_size_bound(const void *chunk, size_t chunk_size) { int32_t read_bytes; uint32_t num_col = 0; + size_t bound; + size_t const max_chunk_size = CMP_ENTITY_MAX_ORIGINAL_SIZE + - NON_IMAGETTE_HEADER_SIZE - CMP_COLLECTION_FILD_SIZE; - if (chunk_size > CMP_ENTITY_MAX_ORIGINAL_SIZE-NON_IMAGETTE_HEADER_SIZE-CMP_COLLECTION_FILD_SIZE) { - debug_print("Error: The chunk size is bigger than the maximum allowed chunk size."); - return 0; - } + RETURN_ERROR_IF(chunk == NULL, CHUNK_NULL, ""); + RETURN_ERROR_IF(chunk_size < COLLECTION_HDR_SIZE, CHUNK_SIZE_INCONSISTENT, ""); + RETURN_ERROR_IF(chunk_size > max_chunk_size, CHUNK_TOO_LARGE, + "chunk_size: %"PRIu32" > max_chunk_size: %"PRIu32"", + chunk_size, max_chunk_size); + /* count the number of collections in the chunk */ for (read_bytes = 0; read_bytes <= (int32_t)chunk_size-COLLECTION_HDR_SIZE; read_bytes += cmp_col_get_size((const struct collection_hdr *)((const uint8_t *)chunk + read_bytes))) num_col++; + RETURN_ERROR_IF((uint32_t)read_bytes != chunk_size, CHUNK_SIZE_INCONSISTENT, ""); - if ((uint32_t)read_bytes != chunk_size) { - debug_print("Error: The sum of the compressed collections does not match the size of the data in the compression header."); - return 0; - } + bound = COMPRESS_CHUNK_BOUND_UNSAFE(chunk_size, num_col); + RETURN_ERROR_IF(bound > CMP_ENTITY_MAX_SIZE, CHUNK_TOO_LARGE, "bound: %lu", bound); - return (uint32_t)COMPRESS_CHUNK_BOUND(chunk_size, num_col); + return (uint32_t)bound; } /** * @brief set the model id and model counter in the compression entity header * - * @param dst pointer to the compressed data starting with a - * compression entity header + * @param dst pointer to the compressed data (starting with a + * compression entity header) * @param dst_size byte size of the dst buffer * @param model_id model identifier; for identifying entities that originate * from the same starting model * @param model_counter model_counter; counts how many times the model was * updated; for non model mode compression use 0 * - * @returns 0 on success, otherwise error + * @returns the byte size of the dst buffer (= dst_size) on success or an error + * code if it fails (which can be tested with cmp_is_error()) */ -int compress_chunk_set_model_id_and_counter(void *dst, int dst_size, - uint16_t model_id, uint8_t model_counter) +uint32_t compress_chunk_set_model_id_and_counter(void *dst, uint32_t dst_size, + uint16_t model_id, uint8_t model_counter) { - if (dst_size < GENERIC_HEADER_SIZE) - return 1; + RETURN_ERROR_IF(dst == NULL, ENTITY_NULL, ""); + FORWARD_IF_ERROR(dst_size, ""); + RETURN_ERROR_IF(dst_size < GENERIC_HEADER_SIZE, ENTITY_TOO_SMALL, + "dst_size: %"PRIu32"", dst_size); + + cmp_ent_set_model_id(dst, model_id); + cmp_ent_set_model_counter(dst, model_counter); - return cmp_ent_set_model_id(dst, model_id) || cmp_ent_set_model_counter(dst, model_counter); + return dst_size; } diff --git a/test/cmp_decmp/test_cmp_decmp.c b/test/cmp_decmp/test_cmp_decmp.c index d4959caafe5dfd124cbdc1eab17c3bd900a339db..b1363a0100da9abf6a28f6d4ac5747eb85234def 100644 --- a/test/cmp_decmp/test_cmp_decmp.c +++ b/test/cmp_decmp/test_cmp_decmp.c @@ -33,6 +33,7 @@ #include <cmp_data_types.h> #include <leon_inttypes.h> #include <byteorder.h> +#include <cmp_error.h> #if defined __has_include # if __has_include(<time.h>) @@ -42,7 +43,7 @@ # endif #endif -#define ROUND_UP_TO_MULTIPLE_OF_4(x) (((x) + 3) & ~3) +#define ROUND_UP_TO_MULTIPLE_OF_4(x) (((x) + 3U) & ~3U) /** @@ -56,6 +57,7 @@ void setUp(void) #ifdef HAS_TIME_H seed = (uint64_t)(time(NULL) ^ getpid() ^ (intptr_t)&setUp); + seed = 0; #else seed = 1; #endif @@ -877,12 +879,12 @@ void test_random_compression_decompress_rdcu_data(void) } -static int32_t chunk_round_trip(void *data, uint32_t data_size, - void *model, void *up_model, - uint32_t *cmp_data, uint32_t cmp_data_capacity, - struct cmp_par *cmp_par, int use_decmp_buf, int use_decmp_up_model) +static uint32_t chunk_round_trip(void *data, uint32_t data_size, + void *model, void *up_model, + uint32_t *cmp_data, uint32_t cmp_data_capacity, + struct cmp_par *cmp_par, int use_decmp_buf, int use_decmp_up_model) { - int32_t cmp_size; + uint32_t cmp_size; void *model_cpy = NULL; /* if in-place model update is used (up_model == model), the model @@ -899,7 +901,6 @@ static int32_t chunk_round_trip(void *data, uint32_t data_size, cmp_size = compress_chunk(data, data_size, model, up_model, cmp_data, cmp_data_capacity, cmp_par); - TEST_ASSERT(cmp_size != CMP_ERROR_HIGH_VALUE); #if 0 { /* Compress a second time and check for determinism */ @@ -921,7 +922,7 @@ static int32_t chunk_round_trip(void *data, uint32_t data_size, free(up_model2); } #endif - if (cmp_size >= 0 && cmp_data) { + if (!cmp_is_error(cmp_size) && cmp_data) { void *decmp_data = NULL; void *up_model_decmp = NULL; int decmp_size; @@ -1012,7 +1013,7 @@ void test_random_collection_round_trip(void) for (cmp_mode = CMP_MODE_RAW; cmp_mode <= CMP_MODE_DIFF_MULTI; cmp_mode++) { struct cmp_par par; - int32_t cmp_size; + uint32_t cmp_size; generate_random_cmp_par(&par); par.cmp_mode = cmp_mode; @@ -1024,9 +1025,9 @@ void test_random_collection_round_trip(void) /* No chunk is defined for fast cadence subservices */ if (data_type == DATA_TYPE_F_FX || data_type == DATA_TYPE_F_FX_EFX || data_type == DATA_TYPE_F_FX_NCOB || data_type == DATA_TYPE_F_FX_EFX_NCOB_ECOB) - TEST_ASSERT(cmp_size == -1); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SUBSERVICE_UNSUPPORTED, cmp_get_error_code(cmp_size)); else - TEST_ASSERT(cmp_size > 0); + TEST_ASSERT_FALSE(cmp_is_error(cmp_size)); } } #ifndef __sparc__ @@ -1053,7 +1054,7 @@ void test_cmp_collection_raw(void) struct cmp_par par = {0}; const uint32_t col_size = COLLECTION_HDR_SIZE+2*sizeof(struct s_fx); const size_t exp_cmp_size_byte = GENERIC_HEADER_SIZE + col_size; - int cmp_size_byte; + uint32_t cmp_size_byte; par.cmp_mode = CMP_MODE_RAW; @@ -1100,7 +1101,8 @@ void test_cmp_collection_raw(void) /* error case: buffer for the compressed data is to small */ dst_capacity -= 1; - TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par)); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF_, + cmp_get_error_code(compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par))); free(col); free(dst); @@ -1135,7 +1137,7 @@ void test_cmp_collection_diff(void) { /* compress data */ - int cmp_size_byte; + uint32_t cmp_size_byte; const int exp_cmp_size_byte = NON_IMAGETTE_HEADER_SIZE + CMP_COLLECTION_FILD_SIZE + COLLECTION_HDR_SIZE + cmp_size_byte_exp; @@ -1184,7 +1186,7 @@ void test_cmp_collection_diff(void) /* error cases dst buffer to small */ dst_capacity -= 1; - TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par)); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF_, cmp_get_error_code(compress_chunk(col, col_size, NULL, NULL, dst, dst_capacity, &par))); free(col); free(dst); @@ -1203,7 +1205,7 @@ void test_cmp_collection_worst_case(void) uint32_t dst_capacity = 0; struct cmp_par par = {0}; const uint16_t cmp_size_byte_exp = 2*sizeof(struct s_fx); - int cmp_size_byte; + uint32_t cmp_size_byte; struct s_fx *data; uint32_t samples = 2; const uint32_t col_size = COLLECTION_HDR_SIZE+samples*sizeof(*data); @@ -1289,7 +1291,7 @@ void test_cmp_collection_imagette_worst_case(void) uint32_t *dst = NULL; struct cmp_par par = {0}; uint16_t const cmp_size_byte_exp = 10*sizeof(uint16_t); - int cmp_size_byte; + uint32_t cmp_size_byte; uint32_t const col_size = COLLECTION_HDR_SIZE + cmp_size_byte_exp; { /* generate test data */ @@ -1359,6 +1361,8 @@ void test_cmp_collection_imagette_worst_case(void) TEST_ASSERT_EQUAL_HEX8_ARRAY(col, decompressed_data, decmp_size); free(decompressed_data); } + free(dst); + free(col); } @@ -1388,7 +1392,7 @@ void test_cmp_decmp_chunk_raw(void) /* "compress" data */ { size_t cmp_size_exp = GENERIC_HEADER_SIZE + chunk_size_exp; - int cmp_size; + uint32_t cmp_size; par.cmp_mode = CMP_MODE_RAW; @@ -1455,13 +1459,14 @@ void test_cmp_decmp_chunk_raw(void) free(decompressed_data); } { /* error case: buffer to small for compressed data */ - int cmp_size; + uint32_t cmp_size; dst_capacity -= 1; cmp_size = compress_chunk(chunk, chunk_size, NULL, NULL, dst, dst_capacity, &par); - TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF_, cmp_get_error_code(cmp_size)); } + free(dst); free(chunk); } @@ -1473,7 +1478,7 @@ void test_cmp_decmp_chunk_worst_case(void) uint32_t chunk_size = CHUNK_SIZE_EXP; void *chunk = NULL; uint32_t dst[COMPRESS_CHUNK_BOUND(CHUNK_SIZE_EXP, ARRAY_SIZE(chunk_def))/sizeof(uint32_t)]; - int cmp_size_byte = 0; + uint32_t cmp_size_byte = 0; struct cmp_par par = {0}; { /* generate test data */ @@ -1571,7 +1576,7 @@ void test_cmp_decmp_chunk_worst_case(void) /* error case: buffer to small for compressed data */ cmp_size_byte = compress_chunk(chunk, chunk_size, NULL, NULL, dst, chunk_size, &par); - TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF, cmp_size_byte); + TEST_ASSERT_EQUAL_INT(CMP_ERROR_SMALL_BUF_, cmp_get_error_code(cmp_size_byte)); free(chunk); } @@ -1632,7 +1637,7 @@ void test_cmp_decmp_diff(void) { /* compress data */ struct cmp_par par = {0}; uint32_t dst_capacity = 0; - int cmp_size; + uint32_t cmp_size; par.cmp_mode = CMP_MODE_DIFF_ZERO; par.s_exp_flags = 1; @@ -1664,4 +1669,5 @@ void test_cmp_decmp_diff(void) free(decompressed_data); } free(dst); + free(chunk); }