diff --git a/CODING_STYLE.md b/CODING_STYLE.md index ac71650..e61073f 100644 --- a/CODING_STYLE.md +++ b/CODING_STYLE.md @@ -11,97 +11,97 @@ The rules don't follow any particular order and don't intend to cover every sing 1. Use 2-spaced indentation. 2. This is the preferred style for statement braces (`if`, `for`, `switch`, etc.): - ```c - if (condition) { + ```c + if (condition) { do_x(); - } else { + } else { do_y(); - } - ``` + } + ``` 3. Braces can be skipped when there's only one statement: - ```c - if (condition) - do_x(); - ``` + ```c + if (condition) + do_x(); + ``` 4. This is also acceptable when line is not too long: - ```c - if (condition) return -1; - ``` + ```c + if (condition) return -1; + ``` 5. Functions are a special case, with opening brace at the beginning of a new line: - ```c - int function(int x) - { - /* Body goes here */ - } - ``` + ```c + int function(int x) + { + /* Body goes here */ + } + ``` 6. Put a space after these keywords: `if, switch, case, for, do, while` 7. When declaring pointers, the preferred use of * is adjacent to the data name or function name and not adjacent to the type name: - ```c - char *str; - char *copy_str(const char *str); - ``` + ```c + char *str; + char *copy_str(const char *str); + ``` 8. Avoid using typedefs as much as possible. Read rationale here: https://www.kernel.org/doc/html/v4.10/process/coding-style.html#typedefs 9. Function names are `snake_case`: - ```c - int process_request(const struct *request); - ``` + ```c + int process_request(const struct *request); + ``` 10. Variable names are `snake_case`: - ```c - size_t arr_len; - char *tmp, *filter_name; - ``` + ```c + size_t arr_len; + char *tmp, *filter_name; + ``` 11. Struct names are `snake_case`: - ```c - struct decoding_ctx { - size_t processed; - size_t remaining; - }; - ``` + ```c + struct decoding_ctx { + size_t processed; + size_t remaining; + }; + ``` 12. Enum names are `snake_case`: - ```c - enum response_error { - BAD_REQUEST_ERROR, - UNREACHABLE_ERROR - }; - ``` + ```c + enum response_error { + BAD_REQUEST_ERROR, + UNREACHABLE_ERROR + }; + ``` 13. Names of macros defining constants are `CAPITALISED`: - ```c - #define MAGIC_NUMBER 42 - ``` + ```c + #define MAGIC_NUMBER 42 + ``` 14. Labels in enums are `CAPITALISED`: - ```c - enum { - PERSIST, - CONTINUE, - ABORT - }; - ``` + ```c + enum { + PERSIST, + CONTINUE, + ABORT + }; + ``` 15. Macros resembling functions may be named in lower case: - ```c - #define list_add(list, element) - ``` + ```c + #define list_add(list, element) + ``` 16. The preferred style for multi-line comments is: - ```c - /* - * This is a multi-line comment that doesn't fit in a - * single line. - * - * Leave a blank line between paragraphs within the block - * comment. - */ - ``` + ```c + /* + * This is a multi-line comment that doesn't fit in a + * single line. + * + * Leave a blank line between paragraphs within the block + * comment. + */ + ``` diff --git a/README.md b/README.md index bfa7f76..6f58dc2 100644 --- a/README.md +++ b/README.md @@ -27,96 +27,114 @@ For reference, VTEnc has been tested on a laptop Ubuntu Desktop 19.10 with a Cor The documented interface is found in the header file `vtenc.h`. -## Examples - -Encoding example: +## Example ```c #include #include #include #include +#include #include "vtenc.h" -int main() +int encode( + vtenc *handler, + const uint8_t *values, + size_t values_len, + uint8_t **out, + size_t *out_len) { - const uint8_t in[] = {13, 14, 29, 39, 65, 80, 88, 106, 152, 154, 155, 177}; - const size_t in_len = sizeof(in) / sizeof(in[0]); - const size_t out_cap = vtenc_max_encoded_size8(in_len); /* output capacity */ - uint8_t *out=NULL; - size_t out_len; - VtencEncoder encoder; - - /* initialise `encoder` */ - vtenc_encoder_init(&encoder); - - /* allocate `out_cap` bytes */ - out = (uint8_t *) malloc(out_cap * sizeof(uint8_t)); - if (out == NULL) { + const size_t out_cap = vtenc_max_encoded_size8(values_len); /* output capacity */ + int rc; + + *out = (uint8_t *) malloc(out_cap * sizeof(uint8_t)); + if (*out == NULL) { fprintf(stderr, "allocation error\n"); - return 1; + return 0; } - /* encode `in` list into `out` stream of bytes */ - out_len = vtenc_encode8(&encoder, in, in_len, out, out_cap); - if (encoder.last_error_code != VtencErrorNoError) { - fprintf(stderr, "encode failed with code: %d\n", encoder.last_error_code); - free(out); - return 1; + rc = vtenc_encode8(handler, values, values_len, *out, out_cap); + if (rc != VTENC_OK) { + fprintf(stderr, "encode failed with code: %d\n", rc); + return 0; } - /* here `out` holds the encoded output, which is `out_len` bytes long */ - - free(out); + *out_len = vtenc_encoded_size(handler); - return 0; + return 1; } -``` -Decoding example: +int decode( + vtenc *handler, + const uint8_t *in, + size_t in_len, + uint8_t **out, + size_t out_len) +{ + int rc; -```c -#include -#include -#include -#include + *out = (uint8_t *) malloc(out_len * sizeof(uint8_t)); + if (*out == NULL) { + fprintf(stderr, "allocation error\n"); + return 0; + } -#include "vtenc.h" + rc = vtenc_decode8(handler, in, in_len, *out, out_len); + if (rc != VTENC_OK) { + fprintf(stderr, "decode failed with code: %d\n", rc); + return 0; + } + + return 1; +} int main() { - const uint8_t in[] = {0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x26, - 0x24, 0x8d, 0x75, 0xfd, 0x95, 0x83, 0x9b, 0x03}; - const size_t in_len = sizeof(in) / sizeof(in[0]); - uint8_t *out = NULL; - size_t out_len = 12; /* the decoded sequence's size needs to be known here */ - VtencDecoder decoder; - - /* initialise decoder */ - vtenc_decoder_init(&decoder); - - /* allocate `out_len` items */ - out = (uint8_t *) malloc(out_len * sizeof(uint8_t)); - if (out == NULL) { - fprintf(stderr, "allocation error\n"); + const uint8_t values[] = {13, 14, 29, 39, 65, 80, 88, 106, 152, 154, 155, 177}; + const size_t values_len = sizeof(values) / sizeof(values[0]); + uint8_t *enc_out=NULL, *dec_out=NULL; + size_t enc_out_len; + int rc = 0; + vtenc *handler = vtenc_create(); + + if (handler == NULL) { + fprintf(stderr, "It failed to create the handler\n"); return 1; } - /* decode `in` stream of bytes into `out` list */ - vtenc_decode8(&decoder, in, in_len, out, out_len); - if (decoder.last_error_code != VtencErrorNoError) { - fprintf(stderr, "decode failed with code: %d\n", decoder.last_error_code); - free(out); - return 1; + if (!encode(handler, values, values_len, &enc_out, &enc_out_len)) { + rc = 1; + goto free_and_return; } - /* here `out` holds the decoded list of integers, of size `out_len` */ + if (!decode(handler, enc_out, enc_out_len, &dec_out, values_len)) { + rc = 1; + goto free_and_return; + } + + printf("Original list: %lu bytes\n", values_len); + printf("Encoded stream: %lu bytes\n", enc_out_len); + + if (memcmp(values, dec_out, values_len) == 0) { + printf("Decoded output matches original list\n"); + } else { + printf("Decoded output different from original list\n"); + rc = 1; + } - free(out); +free_and_return: + if (enc_out != NULL) + free(enc_out); - return 0; + if (dec_out != NULL) + free(dec_out); + + vtenc_destroy(handler); + + return rc; } + ``` ## Limitations diff --git a/bitstream.h b/bitstream.h index 4f03fc1..00509a7 100644 --- a/bitstream.h +++ b/bitstream.h @@ -10,12 +10,9 @@ #include #include -#include "error.h" +#include "internals.h" #include "mem.h" -#define BIT_STREAM_MAX_WRITE 57 -#define BIT_STREAM_MAX_READ BIT_STREAM_MAX_WRITE - struct bswriter { uint64_t bit_container; unsigned int bit_pos; @@ -30,7 +27,7 @@ static inline size_t bswriter_align_buffer_size(size_t orig_size) return orig_size + 8 - (orig_size % 8); } -static inline VtencErrorCode bswriter_init(struct bswriter *writer, +static inline int bswriter_init(struct bswriter *writer, uint8_t *out_buf, size_t out_capacity) { writer->bit_container = 0; @@ -39,8 +36,11 @@ static inline VtencErrorCode bswriter_init(struct bswriter *writer, writer->ptr = writer->start_ptr; writer->end_ptr = writer->start_ptr + out_capacity - sizeof(writer->bit_container); - if (out_capacity < sizeof(writer->bit_container)) return VtencErrorBufferTooSmall; - return VtencErrorNoError; + if (out_capacity < sizeof(writer->bit_container)) { + return VTENC_ERR_BUFFER_TOO_SMALL; + } + + return VTENC_OK; } static inline void bswriter_append(struct bswriter *writer, @@ -53,7 +53,7 @@ static inline void bswriter_append(struct bswriter *writer, writer->bit_pos += n_bits; } -static inline VtencErrorCode bswriter_flush(struct bswriter *writer) +static inline int bswriter_flush(struct bswriter *writer) { size_t const n_bytes = writer->bit_pos >> 3; @@ -63,23 +63,23 @@ static inline VtencErrorCode bswriter_flush(struct bswriter *writer) writer->bit_pos &= 7; writer->bit_container >>= (n_bytes << 3); - if (writer->ptr > writer->end_ptr) return VtencErrorEndOfStream; - return VtencErrorNoError; + if (writer->ptr > writer->end_ptr) return VTENC_ERR_END_OF_STREAM; + return VTENC_OK; } -static inline VtencErrorCode bswriter_write(struct bswriter *writer, +static inline int bswriter_write(struct bswriter *writer, uint64_t value, unsigned int n_bits) { assert(n_bits <= BIT_STREAM_MAX_WRITE); - if (writer->ptr > writer->end_ptr) return VtencErrorEndOfStream; + if (writer->ptr > writer->end_ptr) return VTENC_ERR_END_OF_STREAM; if (n_bits + writer->bit_pos >= 64) return_if_error(bswriter_flush(writer)); bswriter_append(writer, value, n_bits); - return VtencErrorNoError; + return VTENC_OK; } static inline size_t bswriter_close(struct bswriter *writer) @@ -110,7 +110,7 @@ static inline void bsreader_init(struct bsreader *reader, reader->end_ptr = reader->start_ptr + buf_len; } -static inline VtencErrorCode bsreader_load(struct bsreader *reader) +static inline int bsreader_load(struct bsreader *reader) { size_t n_bytes; @@ -119,7 +119,7 @@ static inline VtencErrorCode bsreader_load(struct bsreader *reader) assert(reader->ptr <= reader->end_ptr); n_bytes = reader->end_ptr - reader->ptr; - if (n_bytes == 0) return VtencErrorEndOfStream; + if (n_bytes == 0) return VTENC_ERR_END_OF_STREAM; if (n_bytes >= 8) { reader->bit_container = mem_read_le_u64(reader->ptr); @@ -142,10 +142,10 @@ static inline VtencErrorCode bsreader_load(struct bsreader *reader) reader->bits_consumed &= 7; } - return VtencErrorNoError; + return VTENC_OK; } -static inline VtencErrorCode bsreader_read(struct bsreader *reader, +static inline int bsreader_read(struct bsreader *reader, unsigned int n_bits, uint64_t *read_value) { assert(n_bits <= BIT_STREAM_MAX_READ); @@ -154,13 +154,13 @@ static inline VtencErrorCode bsreader_read(struct bsreader *reader, return_if_error(bsreader_load(reader)); if (n_bits + reader->bits_consumed > reader->bits_loaded) - return VtencErrorNotEnoughBits; + return VTENC_ERR_NOT_ENOUGH_BITS; } *read_value = (reader->bit_container >> reader->bits_consumed) & ((1ULL << n_bits) - 1ULL); reader->bits_consumed += n_bits; - return VtencErrorNoError; + return VTENC_OK; } static inline size_t bsreader_size(struct bsreader *reader) diff --git a/common.c b/common.c new file mode 100644 index 0000000..b367ba2 --- /dev/null +++ b/common.c @@ -0,0 +1,69 @@ +/** + Copyright (c) 2022 Vicente Romero Calero. All rights reserved. + Licensed under the MIT License. + See LICENSE file in the project root for full license information. + */ +#include +#include + +#include "internals.h" + +vtenc *vtenc_create(void) +{ + vtenc *handler; + + handler = malloc(sizeof(*handler)); + + if (handler) { + handler->params.allow_repeated_values = 1; + handler->params.skip_full_subtrees = 1; + handler->params.min_cluster_length = 1; + handler->out_size = 0; + } + + return handler; +} + +void vtenc_destroy(vtenc *handler) +{ + if (!handler) + return; + + free(handler); +} + +int vtenc_config(vtenc *handler, int op, ...) +{ + va_list ap; + int rc = VTENC_OK; + + va_start(ap, op); + + switch (op) { + case VTENC_CONFIG_ALLOW_REPEATED_VALUES: { + handler->params.allow_repeated_values = va_arg(ap, int); + break; + } + case VTENC_CONFIG_SKIP_FULL_SUBTREES: { + handler->params.skip_full_subtrees = va_arg(ap, int); + break; + } + case VTENC_CONFIG_MIN_CLUSTER_LENGTH: { + handler->params.min_cluster_length = va_arg(ap, size_t); + break; + } + default: { + rc = VTENC_ERR_CONFIG; + break; + } + } + + va_end(ap); + + return rc; +} + +size_t vtenc_encoded_size(vtenc *enc) +{ + return enc->out_size; +} diff --git a/decode.c b/decode.c index 6758e78..ce6ee05 100644 --- a/decode.c +++ b/decode.c @@ -3,20 +3,10 @@ Licensed under the MIT License. See LICENSE file in the project root for full license information. */ -#include "vtenc.h" - #include "internals.h" #include "stack.h" -void vtenc_decoder_init(VtencDecoder *dec) -{ - dec->allow_repeated_values = 1; - dec->skip_full_subtrees = 1; - dec->min_cluster_length = 1; - dec->last_error_code = VtencErrorNoError; -} - -#define DECODE_STACK_MAX_SIZE 64 +#define DEC_STACK_MAX_SIZE 64 struct dec_bit_cluster { size_t from; @@ -25,7 +15,7 @@ struct dec_bit_cluster { uint64_t higher_bits; }; -CREATE_STACK(dec_stack, struct dec_bit_cluster, DECODE_STACK_MAX_SIZE) +CREATE_STACK(dec_stack, struct dec_bit_cluster, DEC_STACK_MAX_SIZE) #define LIST_MAX_VALUES VTENC_LIST_MAX_VALUES diff --git a/decode_generic.h b/decode_generic.h index 48628df..ec15a22 100644 --- a/decode_generic.h +++ b/decode_generic.h @@ -3,13 +3,11 @@ Licensed under the MIT License. See LICENSE file in the project root for full license information. */ -#include #include #include #include "bitstream.h" #include "common.h" -#include "error.h" #include "internals.h" #define decctx_(_width_) BITWIDTH_SUFFIX(decctx, _width_) @@ -33,20 +31,6 @@ #define vtenc_decode_(_width_) BITWIDTH_SUFFIX(vtenc_decode, _width_) #define vtenc_decode vtenc_decode_(BITWIDTH) -#define dec_return_with_code(dec, code) \ -do { \ - (dec)->last_error_code = code; \ - return; \ -} while (0) - -#define dec_return_on_error(dec, exp) \ -do { \ - const VtencErrorCode code = (exp); \ - if (code != VtencErrorNoError) { \ - dec_return_with_code(dec, code); \ - } \ -} while (0) - struct decctx { TYPE *values; size_t values_len; @@ -56,9 +40,8 @@ struct decctx { struct bsreader bits_reader; }; -static VtencErrorCode decctx_init(struct decctx *ctx, - const VtencDecoder *dec, const uint8_t *in, size_t in_len, - TYPE *out, size_t out_len) +static int decctx_init(struct decctx *ctx, const vtenc *dec, + const uint8_t *in, size_t in_len, TYPE *out, size_t out_len) { ctx->values = out; ctx->values_len = out_len; @@ -67,18 +50,19 @@ static VtencErrorCode decctx_init(struct decctx *ctx, * `skip_full_subtrees` parameter is only applicable to sets, i.e. sequences * with no repeated values. */ - ctx->reconstruct_full_subtrees = !dec->allow_repeated_values && dec->skip_full_subtrees; + ctx->reconstruct_full_subtrees = !dec->params.allow_repeated_values && + dec->params.skip_full_subtrees; - ctx->min_cluster_length = dec->min_cluster_length; + ctx->min_cluster_length = dec->params.min_cluster_length; dec_stack_init(&ctx->stack); bsreader_init(&(ctx->bits_reader), in, in_len); - return VtencErrorNoError; + return VTENC_OK; } -static inline VtencErrorCode decode_lower_bits_step(struct decctx *ctx, +static inline int decode_lower_bits_step(struct decctx *ctx, TYPE *value, unsigned int n_bits) { #if BITWIDTH > BIT_STREAM_MAX_READ @@ -95,18 +79,18 @@ static inline VtencErrorCode decode_lower_bits_step(struct decctx *ctx, return_if_error(bsreader_read(&(ctx->bits_reader), n_bits, &lower)); *value |= lower << shift; - return VtencErrorNoError; + return VTENC_OK; #else uint64_t lower; return_if_error(bsreader_read(&(ctx->bits_reader), n_bits, &lower)); *value |= (TYPE)lower; - return VtencErrorNoError; + return VTENC_OK; #endif } -static inline VtencErrorCode decode_lower_bits(struct decctx *ctx, +static inline int decode_lower_bits(struct decctx *ctx, TYPE *values, size_t values_len, unsigned int n_bits, TYPE higher_bits) { size_t i; @@ -116,7 +100,7 @@ static inline VtencErrorCode decode_lower_bits(struct decctx *ctx, return_if_error(decode_lower_bits_step(ctx, &values[i], n_bits)); } - return VtencErrorNoError; + return VTENC_OK; } static inline void decode_full_subtree(TYPE *values, size_t values_len, TYPE higher_bits) @@ -147,7 +131,7 @@ static inline struct dec_bit_cluster *bcltree_next(struct decctx *ctx) return dec_stack_pop(&ctx->stack); } -static VtencErrorCode decode_bit_cluster_tree(struct decctx *ctx) +static int decode_bit_cluster_tree(struct decctx *ctx) { bcltree_add(ctx, &(struct dec_bit_cluster){0, ctx->values_len, BITWIDTH, 0}); @@ -184,7 +168,7 @@ static VtencErrorCode decode_bit_cluster_tree(struct decctx *ctx) return_if_error(bsreader_read(&(ctx->bits_reader), enc_len, &n_zeros)); - if (n_zeros > (uint64_t)cl_len) return VtencErrorWrongFormat; + if (n_zeros > (uint64_t)cl_len) return VTENC_ERR_WRONG_FORMAT; { unsigned int next_bit_pos = cl_bit_pos - 1; @@ -196,26 +180,23 @@ static VtencErrorCode decode_bit_cluster_tree(struct decctx *ctx) } } - return VtencErrorNoError; + return VTENC_OK; } -void vtenc_decode(VtencDecoder *dec, const uint8_t *in, size_t in_len, - TYPE *out, size_t out_len) +int vtenc_decode(vtenc *dec, const uint8_t *in, size_t in_len, TYPE *out, size_t out_len) { + int rc; struct decctx ctx; - uint64_t max_values = dec->allow_repeated_values ? LIST_MAX_VALUES : SET_MAX_VALUES; + uint64_t max_values = dec->params.allow_repeated_values ? LIST_MAX_VALUES : SET_MAX_VALUES; - dec->last_error_code = VtencErrorNoError; + if ((uint64_t)out_len > max_values) + return VTENC_ERR_OUTPUT_TOO_BIG; - dec_return_on_error(dec, - decctx_init(&ctx, dec, in, in_len, out, out_len) - ); - - if ((uint64_t)out_len > max_values) { - dec_return_with_code(dec, VtencErrorOutputTooBig); - } + rc = decctx_init(&ctx, dec, in, in_len, out, out_len); + if (rc != VTENC_OK) + return rc; memset(out, 0, out_len * sizeof(*out)); - dec_return_on_error(dec, decode_bit_cluster_tree(&ctx)); + return decode_bit_cluster_tree(&ctx); } diff --git a/encode.c b/encode.c index 34a2686..2f711cd 100644 --- a/encode.c +++ b/encode.c @@ -3,20 +3,10 @@ Licensed under the MIT License. See LICENSE file in the project root for full license information. */ -#include "vtenc.h" - #include "internals.h" #include "stack.h" -void vtenc_encoder_init(VtencEncoder *enc) -{ - enc->allow_repeated_values = 1; - enc->skip_full_subtrees = 1; - enc->min_cluster_length = 1; - enc->last_error_code = VtencErrorNoError; -} - -#define ENCODE_STACK_MAX_SIZE 64 +#define ENC_STACK_MAX_SIZE 64 struct enc_bit_cluster { size_t from; @@ -24,7 +14,7 @@ struct enc_bit_cluster { unsigned int bit_pos; }; -CREATE_STACK(enc_stack, struct enc_bit_cluster, ENCODE_STACK_MAX_SIZE) +CREATE_STACK(enc_stack, struct enc_bit_cluster, ENC_STACK_MAX_SIZE) #define LIST_MAX_VALUES VTENC_LIST_MAX_VALUES diff --git a/encode_generic.h b/encode_generic.h index 792475f..c0d630c 100644 --- a/encode_generic.h +++ b/encode_generic.h @@ -3,14 +3,12 @@ Licensed under the MIT License. See LICENSE file in the project root for full license information. */ -#include #include #include #include "bitstream.h" #include "common.h" #include "countbits.h" -#include "error.h" #include "internals.h" #define encctx_(_width_) BITWIDTH_SUFFIX(encctx, _width_) @@ -38,21 +36,6 @@ #define vtenc_max_encoded_size_(_width_) BITWIDTH_SUFFIX(vtenc_max_encoded_size, _width_) #define vtenc_max_encoded_size vtenc_max_encoded_size_(BITWIDTH) -#define enc_return_with_code(ctx, enc, code) \ -do { \ - (enc)->last_error_code = code; \ - encctx_close((ctx)); \ - return 0; \ -} while (0) - -#define enc_return_on_error(ctx, enc, exp) \ -do { \ - const VtencErrorCode code = (exp); \ - if (code != VtencErrorNoError) { \ - enc_return_with_code(ctx, enc, code); \ - } \ -} while(0) - struct encctx { const TYPE *values; size_t values_len; @@ -62,9 +45,8 @@ struct encctx { struct bswriter bits_writer; }; -static VtencErrorCode encctx_init(struct encctx *ctx, - const VtencEncoder *enc, const TYPE *in, size_t in_len, - uint8_t *out, size_t out_cap) +static int encctx_init(struct encctx *ctx, const vtenc *enc, + const TYPE *in, size_t in_len, uint8_t *out, size_t out_cap) { ctx->values = in; ctx->values_len = in_len; @@ -73,9 +55,10 @@ static VtencErrorCode encctx_init(struct encctx *ctx, * `skip_full_subtrees` parameter is only applicable to sets, i.e. sequences * with no repeated values. */ - ctx->skip_full_subtrees = !enc->allow_repeated_values && enc->skip_full_subtrees; + ctx->skip_full_subtrees = !enc->params.allow_repeated_values && + enc->params.skip_full_subtrees; - ctx->min_cluster_length = enc->min_cluster_length; + ctx->min_cluster_length = enc->params.min_cluster_length; enc_stack_init(&ctx->stack); @@ -87,7 +70,7 @@ static inline size_t encctx_close(struct encctx *ctx) return bswriter_close(&(ctx->bits_writer)); } -static inline VtencErrorCode encode_lower_bits_step(struct encctx *ctx, +static inline int encode_lower_bits_step(struct encctx *ctx, uint64_t value, unsigned int n_bits) { #if BITWIDTH > BIT_STREAM_MAX_WRITE @@ -106,7 +89,7 @@ static inline VtencErrorCode encode_lower_bits_step(struct encctx *ctx, return bswriter_write(&(ctx->bits_writer), value & BITS_SIZE_MASK[n_bits], n_bits); } -static inline VtencErrorCode encode_lower_bits(struct encctx *ctx, +static inline int encode_lower_bits(struct encctx *ctx, const TYPE *values, size_t values_len, unsigned int n_bits) { size_t i; @@ -115,7 +98,7 @@ static inline VtencErrorCode encode_lower_bits(struct encctx *ctx, return_if_error(encode_lower_bits_step(ctx, values[i], n_bits)); } - return VtencErrorNoError; + return VTENC_OK; } static inline void bcltree_add(struct encctx *ctx, @@ -140,7 +123,7 @@ static inline struct enc_bit_cluster *bcltree_next(struct encctx *ctx) return enc_stack_pop(&ctx->stack); } -static VtencErrorCode encode_bit_cluster_tree(struct encctx *ctx) +static int encode_bit_cluster_tree(struct encctx *ctx) { bcltree_add(ctx, &(struct enc_bit_cluster){0, ctx->values_len, BITWIDTH}); @@ -172,28 +155,30 @@ static VtencErrorCode encode_bit_cluster_tree(struct encctx *ctx) } } - return VtencErrorNoError; + return VTENC_OK; } -size_t vtenc_encode(VtencEncoder *enc, const TYPE *in, size_t in_len, - uint8_t *out, size_t out_cap) +int vtenc_encode(vtenc *enc, const TYPE *in, size_t in_len, uint8_t *out, size_t out_cap) { + int rc; + uint64_t max_values = enc->params.allow_repeated_values ? LIST_MAX_VALUES : SET_MAX_VALUES; struct encctx ctx; - uint64_t max_values = enc->allow_repeated_values ? LIST_MAX_VALUES : SET_MAX_VALUES; - enc->last_error_code = VtencErrorNoError; + enc->out_size = 0; - enc_return_on_error(&ctx, enc, - encctx_init(&ctx, enc, in, in_len, out, out_cap) - ); + if ((uint64_t)in_len > max_values) + return VTENC_ERR_INPUT_TOO_BIG; - if ((uint64_t)in_len > max_values) { - enc_return_with_code(&ctx, enc, VtencErrorInputTooBig); - } + rc = encctx_init(&ctx, enc, in, in_len, out, out_cap); + if (rc != VTENC_OK) + return rc; + + rc = encode_bit_cluster_tree(&ctx); - enc_return_on_error(&ctx, enc, encode_bit_cluster_tree(&ctx)); + if (rc == VTENC_OK) + enc->out_size = encctx_close(&ctx); - return encctx_close(&ctx); + return rc; } size_t vtenc_max_encoded_size(size_t in_len) diff --git a/error.h b/error.h deleted file mode 100644 index e0a21d1..0000000 --- a/error.h +++ /dev/null @@ -1,19 +0,0 @@ -/** - Copyright (c) 2019 Vicente Romero Calero. All rights reserved. - Licensed under the MIT License. - See LICENSE file in the project root for full license information. - */ -#ifndef VTENC_ERROR_H_ -#define VTENC_ERROR_H_ - -#include "vtenc.h" - -#define return_if_error(exp) \ -do { \ - const VtencErrorCode code = (exp); \ - if (code != VtencErrorNoError) { \ - return code; \ - } \ -} while(0) - -#endif /* VTENC_ERROR_H_ */ diff --git a/internals.h b/internals.h index d79d95b..9a20c22 100644 --- a/internals.h +++ b/internals.h @@ -7,18 +7,20 @@ #define VTENC_INTERNALS_H_ #include "bits.h" -#include "bitstream.h" +#include "vtenc.h" /* Shared macros */ - #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define PASTE2(x, y) x ## y #define PASTE3(x, y, z) x ## y ## z #define BITWIDTH_SUFFIX(_name_, _width_) PASTE2(_name_, _width_) -/* VTEnc constants */ +/* Bitstream constants */ +#define BIT_STREAM_MAX_WRITE 57 +#define BIT_STREAM_MAX_READ BIT_STREAM_MAX_WRITE +/* VTEnc constants */ #define VTENC_MAX_VALUES_LIMIT BITS_SIZE_MASK[BIT_STREAM_MAX_WRITE] #define VTENC_LIST_MAX_VALUES VTENC_MAX_VALUES_LIMIT @@ -28,4 +30,23 @@ #define VTENC_SET_MAX_VALUES32 MIN(BITS_POS_MASK64[32], VTENC_MAX_VALUES_LIMIT) #define VTENC_SET_MAX_VALUES64 MIN(BITS_SIZE_MASK[64], VTENC_MAX_VALUES_LIMIT) +/* Encoding/decoding handler structure */ +struct vtenc { + struct vtenc_enc_params { /* Encoding parameters */ + int allow_repeated_values; /* 1 if repeated values are allowed */ + int skip_full_subtrees; /* 1 to skip full subtrees */ + size_t min_cluster_length; /* Minimum cluster length to serialise */ + } params; + size_t out_size; /* Output size in bytes */ +}; + +/* Error-handling helper macro */ +#define return_if_error(exp) \ +do { \ + const int code = (exp); \ + if (code != VTENC_OK) { \ + return code; \ + } \ +} while(0) + #endif /* VTENC_INTERNALS_H_ */ diff --git a/tests/encdec.c b/tests/encdec.c index 165c801..cb52f0f 100644 --- a/tests/encdec.c +++ b/tests/encdec.c @@ -87,11 +87,17 @@ void encdec_init64(struct EncDec *encdec) int encdec_encode(struct EncDec *encdec, const void *in, size_t in_len) { size_t enc_out_cap; - VtencEncoder encoder = { - .allow_repeated_values = encdec->allow_repeated_values, - .skip_full_subtrees = encdec->skip_full_subtrees, - .min_cluster_length = encdec->min_cluster_length - }; + int rc, res=1; + vtenc *encoder = vtenc_create(); + + if (encoder == NULL) { + fprintf(stderr, "failed to create the encoder\n"); + return 0; + } + + vtenc_config(encoder, VTENC_CONFIG_ALLOW_REPEATED_VALUES, encdec->allow_repeated_values); + vtenc_config(encoder, VTENC_CONFIG_SKIP_FULL_SUBTREES, encdec->skip_full_subtrees); + vtenc_config(encoder, VTENC_CONFIG_MIN_CLUSTER_LENGTH, encdec->min_cluster_length); encdec->ctx.in = in; encdec->ctx.in_len = in_len; @@ -99,35 +105,46 @@ int encdec_encode(struct EncDec *encdec, const void *in, size_t in_len) enc_out_cap = encdec->funcs->max_encoded_size(in_len); encdec->ctx.enc_out = (uint8_t *) malloc(enc_out_cap * sizeof(uint8_t)); - if (encdec->ctx.enc_out == NULL) { fprintf(stderr, "allocation error\n"); - return 0; + res = 0; + goto destroy_and_return; } - encdec->ctx.enc_out_len = encdec->funcs->encode( - &encoder, + rc = encdec->funcs->encode( + encoder, encdec->ctx.in, encdec->ctx.in_len, encdec->ctx.enc_out, enc_out_cap ); - - if (encoder.last_error_code != VtencErrorNoError) { - fprintf(stderr, "encode failed with code: %d\n", encoder.last_error_code); - return 0; + if (rc != VTENC_OK) { + fprintf(stderr, "encode failed with code: %d\n", rc); + res = 0; + goto destroy_and_return; } - return 1; + encdec->ctx.enc_out_len = vtenc_encoded_size(encoder); + +destroy_and_return: + vtenc_destroy(encoder); + + return res; } int encdec_decode(struct EncDec *encdec) { - VtencDecoder decoder = { - .allow_repeated_values = encdec->allow_repeated_values, - .skip_full_subtrees = encdec->skip_full_subtrees, - .min_cluster_length = encdec->min_cluster_length - }; + int rc, res=1; + vtenc *decoder = vtenc_create(); + + if (decoder == NULL) { + fprintf(stderr, "failed to create the decoder\n"); + return 0; + } + + vtenc_config(decoder, VTENC_CONFIG_ALLOW_REPEATED_VALUES, encdec->allow_repeated_values); + vtenc_config(decoder, VTENC_CONFIG_SKIP_FULL_SUBTREES, encdec->skip_full_subtrees); + vtenc_config(decoder, VTENC_CONFIG_MIN_CLUSTER_LENGTH, encdec->min_cluster_length); encdec->ctx.dec_out_len = encdec->ctx.in_len; @@ -135,23 +152,28 @@ int encdec_decode(struct EncDec *encdec) if (encdec->ctx.dec_out == NULL) { fprintf(stderr, "allocation error\n"); - return 0; + res = 0; + goto destroy_and_return; } - encdec->funcs->decode( - &decoder, + rc = encdec->funcs->decode( + decoder, encdec->ctx.enc_out, encdec->ctx.enc_out_len, encdec->ctx.dec_out, encdec->ctx.dec_out_len ); - if (decoder.last_error_code != VtencErrorNoError) { - fprintf(stderr, "decode failed with code: %d\n", decoder.last_error_code); - return 0; + if (rc != VTENC_OK) { + fprintf(stderr, "decode failed with code: %d\n", rc); + res = 0; + goto destroy_and_return; } - return 1; +destroy_and_return: + vtenc_destroy(decoder); + + return res; } int encdec_check_equality(struct EncDec *encdec) @@ -172,11 +194,11 @@ int encdec_check_equality(struct EncDec *encdec) void encdec_print_summary(struct EncDec *encdec) { size_t in_len_in_bytes = encdec->ctx.in_len * encdec->funcs->type_size(); - double ratio = encdec->ctx.enc_out_len / (double)in_len_in_bytes; + double ratio = in_len_in_bytes / (double)encdec->ctx.enc_out_len; printf("input size: %lu (%lu bytes)\n", encdec->ctx.in_len, in_len_in_bytes); printf("encoded size: %lu bytes\n", encdec->ctx.enc_out_len); - printf("compression ratio: %f (%.4f%%)\n", ratio, ratio * 100.0); + printf("compression ratio: %.1f\n", ratio); } void encdec_free(struct EncDec *encdec) diff --git a/tests/encdec.h b/tests/encdec.h index c3645b8..26871d5 100644 --- a/tests/encdec.h +++ b/tests/encdec.h @@ -13,8 +13,8 @@ typedef size_t (*type_size_func_t)(); typedef size_t (*max_encoded_size_func_t)(size_t); -typedef size_t (*encode_func_t)(VtencEncoder *, const void *, size_t, uint8_t *, size_t); -typedef void (*decode_func_t)(VtencDecoder *, const uint8_t *, size_t, void *, size_t); +typedef int (*encode_func_t)(vtenc *, const void *, size_t, uint8_t *, size_t); +typedef int (*decode_func_t)(vtenc *, const uint8_t *, size_t, void *, size_t); struct EncDecFuncs { type_size_func_t type_size; diff --git a/tests/unit/bitstream_test.c b/tests/unit/bitstream_test.c index 1ae0251..3dac8d0 100644 --- a/tests/unit/bitstream_test.c +++ b/tests/unit/bitstream_test.c @@ -30,7 +30,7 @@ int test_bswriter_init_1(void) const size_t buf_cap = 4; uint8_t buf[buf_cap]; - EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorBufferTooSmall); + EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VTENC_ERR_BUFFER_TOO_SMALL); return 1; } @@ -41,7 +41,7 @@ int test_bswriter_init_2(void) const size_t buf_cap = 8; uint8_t buf[buf_cap]; - EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError); + EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VTENC_OK); return 1; } @@ -54,15 +54,15 @@ int test_bswriter_write_1(void) memset(buf, 0, buf_cap); - EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError); + EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VTENC_OK); - EXPECT_TRUE(bswriter_write(&writer, 0xffff, 16) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x2, 4) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x2, 4) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x00, 8) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x99999999, 32) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x44, 8) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0xaa, 8) == VtencErrorNoError); + EXPECT_TRUE(bswriter_write(&writer, 0xffff, 16) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x2, 4) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x2, 4) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x00, 8) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x99999999, 32) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x44, 8) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0xaa, 8) == VTENC_OK); bswriter_close(&writer); @@ -79,16 +79,16 @@ int test_bswriter_write_2(void) memset(buf, 0, buf_cap); - EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError); + EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VTENC_OK); - EXPECT_TRUE(bswriter_write(&writer, 0x0, 0) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x0, 0) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0xffffffff, 32) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x7fffffff, 31) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x0, 0) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x0, 0) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x1, 1) == VtencErrorEndOfStream); - EXPECT_TRUE(bswriter_write(&writer, 0x1, 1) == VtencErrorEndOfStream); + EXPECT_TRUE(bswriter_write(&writer, 0x0, 0) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x0, 0) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0xffffffff, 32) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x7fffffff, 31) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x0, 0) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x0, 0) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x1, 1) == VTENC_ERR_END_OF_STREAM); + EXPECT_TRUE(bswriter_write(&writer, 0x1, 1) == VTENC_ERR_END_OF_STREAM); bswriter_close(&writer); @@ -105,11 +105,11 @@ int test_bswriter_write_3(void) memset(buf, 0, buf_cap); - EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError); + EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VTENC_OK); - EXPECT_TRUE(bswriter_write(&writer, 0x1ffffffffffffff, 57) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x1ffffffffffffff, 57) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x1ffffffffffffff, 57) == VtencErrorNoError); + EXPECT_TRUE(bswriter_write(&writer, 0x1ffffffffffffff, 57) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x1ffffffffffffff, 57) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x1ffffffffffffff, 57) == VTENC_OK); bswriter_close(&writer); @@ -127,7 +127,7 @@ int test_bswriter_close_1(void) const size_t buf_cap = 8; uint8_t buf[buf_cap]; - EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError); + EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VTENC_OK); EXPECT_TRUE(bswriter_close(&writer) == 0); return 1; @@ -139,12 +139,12 @@ int test_bswriter_close_2(void) const size_t buf_cap = 8; uint8_t buf[buf_cap]; - EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError); + EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VTENC_OK); - EXPECT_TRUE(bswriter_write(&writer, 0x12, 8) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x3, 2) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0x7, 3) == VtencErrorNoError); - EXPECT_TRUE(bswriter_write(&writer, 0xe, 4) == VtencErrorNoError); + EXPECT_TRUE(bswriter_write(&writer, 0x12, 8) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x3, 2) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0x7, 3) == VTENC_OK); + EXPECT_TRUE(bswriter_write(&writer, 0xe, 4) == VTENC_OK); EXPECT_TRUE(bswriter_close(&writer) == 3); @@ -160,7 +160,7 @@ int test_bsreader_read_1(void) bsreader_init(&reader, buf, buf_len); - EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VtencErrorEndOfStream); + EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VTENC_ERR_END_OF_STREAM); return 1; } @@ -174,8 +174,8 @@ int test_bsreader_read_2(void) bsreader_init(&reader, buf, buf_len); - EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VtencErrorNoError && val == 0xff); - EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VtencErrorEndOfStream); + EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VTENC_OK && val == 0xff); + EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VTENC_ERR_END_OF_STREAM); return 1; } @@ -189,9 +189,9 @@ int test_bsreader_read_3(void) bsreader_init(&reader, buf, buf_len); - EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VtencErrorNoError && val == 0xff); - EXPECT_TRUE(bsreader_read(&reader, 16, &val) == VtencErrorNotEnoughBits); - EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VtencErrorNoError && val == 0x66); + EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VTENC_OK && val == 0xff); + EXPECT_TRUE(bsreader_read(&reader, 16, &val) == VTENC_ERR_NOT_ENOUGH_BITS); + EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VTENC_OK && val == 0x66); return 1; } @@ -205,12 +205,12 @@ int test_bsreader_read_4(void) bsreader_init(&reader, buf, buf_len); - EXPECT_TRUE(bsreader_read(&reader, 0, &val) == VtencErrorNoError); - EXPECT_TRUE(bsreader_read(&reader, 4, &val) == VtencErrorNoError && val == 0xa); - EXPECT_TRUE(bsreader_read(&reader, 0, &val) == VtencErrorNoError); - EXPECT_TRUE(bsreader_read(&reader, 4, &val) == VtencErrorNoError && val == 0xb); - EXPECT_TRUE(bsreader_read(&reader, 0, &val) == VtencErrorNoError); - EXPECT_TRUE(bsreader_read(&reader, 1, &val) == VtencErrorEndOfStream); + EXPECT_TRUE(bsreader_read(&reader, 0, &val) == VTENC_OK); + EXPECT_TRUE(bsreader_read(&reader, 4, &val) == VTENC_OK && val == 0xa); + EXPECT_TRUE(bsreader_read(&reader, 0, &val) == VTENC_OK); + EXPECT_TRUE(bsreader_read(&reader, 4, &val) == VTENC_OK && val == 0xb); + EXPECT_TRUE(bsreader_read(&reader, 0, &val) == VTENC_OK); + EXPECT_TRUE(bsreader_read(&reader, 1, &val) == VTENC_ERR_END_OF_STREAM); return 1; } @@ -227,10 +227,10 @@ int test_bsreader_read_5(void) bsreader_init(&reader, buf, buf_len); - EXPECT_TRUE(bsreader_read(&reader, 48, &val) == VtencErrorNoError && val == 0x111111111111); - EXPECT_TRUE(bsreader_read(&reader, 48, &val) == VtencErrorNoError && val == 0x222222222222); - EXPECT_TRUE(bsreader_read(&reader, 48, &val) == VtencErrorNoError && val == 0x333333333333); - EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VtencErrorEndOfStream); + EXPECT_TRUE(bsreader_read(&reader, 48, &val) == VTENC_OK && val == 0x111111111111); + EXPECT_TRUE(bsreader_read(&reader, 48, &val) == VTENC_OK && val == 0x222222222222); + EXPECT_TRUE(bsreader_read(&reader, 48, &val) == VTENC_OK && val == 0x333333333333); + EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VTENC_ERR_END_OF_STREAM); return 1; } @@ -246,18 +246,18 @@ int test_bsreader_read_6(void) bsreader_init(&reader, buf, buf_len); - EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VtencErrorNoError && val == 0xff); - EXPECT_TRUE(bsreader_read(&reader, 4, &val) == VtencErrorNoError && val == 0xb); - EXPECT_TRUE(bsreader_read(&reader, 4, &val) == VtencErrorNoError && val == 0xa); - EXPECT_TRUE(bsreader_read(&reader, 1, &val) == VtencErrorNoError && val == 0x1); - EXPECT_TRUE(bsreader_read(&reader, 2, &val) == VtencErrorNoError && val == 0x0); - EXPECT_TRUE(bsreader_read(&reader, 2, &val) == VtencErrorNoError && val == 0x2); - EXPECT_TRUE(bsreader_read(&reader, 3, &val) == VtencErrorNoError && val == 0x0); - EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VtencErrorNoError && val == 0xcd); - EXPECT_TRUE(bsreader_read(&reader, 16, &val) == VtencErrorNoError && val == 0x5555); - EXPECT_TRUE(bsreader_read(&reader, 16, &val) == VtencErrorNoError && val == 0x5555); - EXPECT_TRUE(bsreader_read(&reader, 32, &val) == VtencErrorNoError && val == 0x66666666); - EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VtencErrorEndOfStream); + EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VTENC_OK && val == 0xff); + EXPECT_TRUE(bsreader_read(&reader, 4, &val) == VTENC_OK && val == 0xb); + EXPECT_TRUE(bsreader_read(&reader, 4, &val) == VTENC_OK && val == 0xa); + EXPECT_TRUE(bsreader_read(&reader, 1, &val) == VTENC_OK && val == 0x1); + EXPECT_TRUE(bsreader_read(&reader, 2, &val) == VTENC_OK && val == 0x0); + EXPECT_TRUE(bsreader_read(&reader, 2, &val) == VTENC_OK && val == 0x2); + EXPECT_TRUE(bsreader_read(&reader, 3, &val) == VTENC_OK && val == 0x0); + EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VTENC_OK && val == 0xcd); + EXPECT_TRUE(bsreader_read(&reader, 16, &val) == VTENC_OK && val == 0x5555); + EXPECT_TRUE(bsreader_read(&reader, 16, &val) == VTENC_OK && val == 0x5555); + EXPECT_TRUE(bsreader_read(&reader, 32, &val) == VTENC_OK && val == 0x66666666); + EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VTENC_ERR_END_OF_STREAM); return 1; } @@ -274,9 +274,9 @@ int test_bsreader_read_7(void) bsreader_init(&reader, buf, buf_len); - EXPECT_TRUE(bsreader_read(&reader, 57, &val) == VtencErrorNoError && val == 0x155555555555555); - EXPECT_TRUE(bsreader_read(&reader, 57, &val) == VtencErrorNoError && val == 0x0aaaaaaaaaaaaaa); - EXPECT_TRUE(bsreader_read(&reader, 6, &val) == VtencErrorNoError && val == 0x15); + EXPECT_TRUE(bsreader_read(&reader, 57, &val) == VTENC_OK && val == 0x155555555555555); + EXPECT_TRUE(bsreader_read(&reader, 57, &val) == VTENC_OK && val == 0x0aaaaaaaaaaaaaa); + EXPECT_TRUE(bsreader_read(&reader, 6, &val) == VTENC_OK && val == 0x15); return 1; } diff --git a/tests/unit/decode_test.c b/tests/unit/decode_test.c index ee506b9..c497dcc 100644 --- a/tests/unit/decode_test.c +++ b/tests/unit/decode_test.c @@ -3,6 +3,7 @@ Licensed under the MIT License. See LICENSE file in the project root for full license information. */ +#include #include #include #include @@ -10,22 +11,14 @@ #include "unit_tests.h" #include "../../vtenc.h" -int test_vtenc_decoder_init(void) -{ - VtencDecoder dec; - - vtenc_decoder_init(&dec); - - EXPECT_TRUE(dec.allow_repeated_values == 1); - EXPECT_TRUE(dec.skip_full_subtrees == 1); - EXPECT_TRUE(dec.min_cluster_length == 1); - EXPECT_TRUE(dec.last_error_code == VtencErrorNoError); - - return 1; -} +struct EncodingParams { + int allow_repeated_values; + int skip_full_subtrees; + size_t min_cluster_length; +}; struct DecodeTestCaseInput { - VtencDecoder decoder; + struct EncodingParams params; const uint8_t *bytes; size_t bytes_len; size_t values_len; @@ -33,7 +26,7 @@ struct DecodeTestCaseInput { struct DecodeTestCaseOutput { void *values; - VtencErrorCode last_error_code; + int result_code; }; struct DecodeTestCase { @@ -44,7 +37,7 @@ struct DecodeTestCase { static struct DecodeTestCase test_cases8[] = { { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -55,12 +48,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){}, - .last_error_code = VtencErrorWrongFormat + .result_code = VTENC_ERR_WRONG_FORMAT } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -71,12 +64,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){}, - .last_error_code = VtencErrorOutputTooBig + .result_code = VTENC_ERR_OUTPUT_TOO_BIG } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -87,12 +80,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -103,12 +96,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){38}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -121,12 +114,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){5, 22, 23, 44, 62, 69, 109, 113, 178, 194, 206}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -137,12 +130,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){57, 57, 57, 111, 111, 111, 111, 208, 208}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -153,12 +146,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){}, - .last_error_code = VtencErrorWrongFormat + .result_code = VTENC_ERR_WRONG_FORMAT } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -169,12 +162,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){}, - .last_error_code = VtencErrorOutputTooBig + .result_code = VTENC_ERR_OUTPUT_TOO_BIG } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -185,12 +178,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -219,12 +212,12 @@ static struct DecodeTestCase test_cases8[] = { 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -235,12 +228,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){33}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -251,12 +244,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){0, 1, 2, 3, 4, 5, 6, 7, 160, 161, 162, 163}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -267,12 +260,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){13, 77, 88, 93, 149, 212}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 2 @@ -283,12 +276,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){2, 3, 8, 11, 16, 122}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 3 @@ -299,12 +292,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){2, 3, 8, 11, 16, 122}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 4 @@ -315,12 +308,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){2, 3, 8, 11, 16, 122}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 8 @@ -331,12 +324,12 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){2, 3, 8, 11, 16, 122}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 8 @@ -347,7 +340,7 @@ static struct DecodeTestCase test_cases8[] = { }, .expected_output = { .values = (uint8_t []){0, 1, 2, 3, 4, 5, 6, 7, 10}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } } }; @@ -355,7 +348,7 @@ static struct DecodeTestCase test_cases8[] = { static struct DecodeTestCase test_cases16[] = { { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -366,12 +359,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){}, - .last_error_code = VtencErrorWrongFormat + .result_code = VTENC_ERR_WRONG_FORMAT } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -382,12 +375,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){}, - .last_error_code = VtencErrorOutputTooBig + .result_code = VTENC_ERR_OUTPUT_TOO_BIG } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -398,12 +391,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -414,12 +407,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){13862}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -433,12 +426,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){1099, 2227, 8102, 27654, 29001, 35511, 50083}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -451,12 +444,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){677, 677, 677, 8881, 8881, 8881, 8881, 8881}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -467,12 +460,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){}, - .last_error_code = VtencErrorWrongFormat + .result_code = VTENC_ERR_WRONG_FORMAT } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -483,12 +476,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){}, - .last_error_code = VtencErrorOutputTooBig + .result_code = VTENC_ERR_OUTPUT_TOO_BIG } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -499,12 +492,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -515,12 +508,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){23091}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -534,12 +527,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){1655, 3391, 4111, 8770, 29006, 32712, 32993, 58042}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -555,12 +548,12 @@ static struct DecodeTestCase test_cases16[] = { 14000, 14001, 14002, 14003, 14004, 14005, 14006, 14007, 20000, 20001, 20002, 20003 }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 2 @@ -573,12 +566,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){543, 600, 9701, 9888, 32944}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 4 @@ -591,12 +584,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){543, 600, 9701, 9888, 32944}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 8 @@ -609,12 +602,12 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){543, 600, 9701, 9888, 32944}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 8 @@ -625,7 +618,7 @@ static struct DecodeTestCase test_cases16[] = { }, .expected_output = { .values = (uint16_t []){0, 1, 2, 3, 4, 5, 6, 7, 10}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } } }; @@ -633,7 +626,7 @@ static struct DecodeTestCase test_cases16[] = { static struct DecodeTestCase test_cases32[] = { { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -644,12 +637,12 @@ static struct DecodeTestCase test_cases32[] = { }, .expected_output = { .values = (uint32_t []){}, - .last_error_code = VtencErrorWrongFormat + .result_code = VTENC_ERR_WRONG_FORMAT } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -660,12 +653,12 @@ static struct DecodeTestCase test_cases32[] = { }, .expected_output = { .values = (uint32_t []){}, - .last_error_code = VtencErrorOutputTooBig + .result_code = VTENC_ERR_OUTPUT_TOO_BIG } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -676,12 +669,12 @@ static struct DecodeTestCase test_cases32[] = { }, .expected_output = { .values = (uint32_t []){}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -692,12 +685,12 @@ static struct DecodeTestCase test_cases32[] = { }, .expected_output = { .values = (uint32_t []){726550617}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -713,12 +706,12 @@ static struct DecodeTestCase test_cases32[] = { .values = (uint32_t []){ 5348, 13089333, 88199704, 271008013, 1451881090 }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -734,12 +727,12 @@ static struct DecodeTestCase test_cases32[] = { .values = (uint32_t []){ 77865901, 77865901, 77865901, 77865901, 314976310, 314976310 }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -750,12 +743,12 @@ static struct DecodeTestCase test_cases32[] = { }, .expected_output = { .values = (uint32_t []){}, - .last_error_code = VtencErrorWrongFormat + .result_code = VTENC_ERR_WRONG_FORMAT } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -766,12 +759,12 @@ static struct DecodeTestCase test_cases32[] = { }, .expected_output = { .values = (uint32_t []){}, - .last_error_code = VtencErrorOutputTooBig + .result_code = VTENC_ERR_OUTPUT_TOO_BIG } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -782,12 +775,12 @@ static struct DecodeTestCase test_cases32[] = { }, .expected_output = { .values = (uint32_t []){}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -798,12 +791,12 @@ static struct DecodeTestCase test_cases32[] = { }, .expected_output = { .values = (uint32_t []){0x77e3ba42}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -819,12 +812,12 @@ static struct DecodeTestCase test_cases32[] = { .values = (uint32_t []){ 0x98b204, 0x122fabb4, 0x378ecef0, 0x77ccab8f, 0xa40609bb }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -843,12 +836,12 @@ static struct DecodeTestCase test_cases32[] = { 0x4bbb00, 0x4bbb01, 0xffff00, 0xffff01, 0xffff02, 0xffff03, 0xffff04, 0xffff05, 0xffff06, 0xffff07 }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 2 @@ -864,12 +857,12 @@ static struct DecodeTestCase test_cases32[] = { .values = (uint32_t []){ 0x88f1ab05, 0x88f1ab09, 0x89633bd0, 0x89633bdf, 0xc8116ffe }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 4 @@ -885,12 +878,12 @@ static struct DecodeTestCase test_cases32[] = { .values = (uint32_t []){ 0x88f1ab05, 0x88f1ab09, 0x89633bd0, 0x89633bdf, 0xc8116ffe }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 8 @@ -906,12 +899,12 @@ static struct DecodeTestCase test_cases32[] = { .values = (uint32_t []){ 0x88f1ab05, 0x88f1ab09, 0x89633bd0, 0x89633bdf, 0xc8116ffe }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 8 @@ -925,7 +918,7 @@ static struct DecodeTestCase test_cases32[] = { }, .expected_output = { .values = (uint32_t []){0, 1, 2, 3, 4, 5, 6, 7, 10}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } } }; @@ -933,7 +926,7 @@ static struct DecodeTestCase test_cases32[] = { static struct DecodeTestCase test_cases64[] = { { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -944,12 +937,12 @@ static struct DecodeTestCase test_cases64[] = { }, .expected_output = { .values = (uint64_t []){}, - .last_error_code = VtencErrorWrongFormat + .result_code = VTENC_ERR_WRONG_FORMAT } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -960,12 +953,12 @@ static struct DecodeTestCase test_cases64[] = { }, .expected_output = { .values = (uint64_t []){}, - .last_error_code = VtencErrorOutputTooBig + .result_code = VTENC_ERR_OUTPUT_TOO_BIG } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -976,12 +969,12 @@ static struct DecodeTestCase test_cases64[] = { }, .expected_output = { .values = (uint64_t []){}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -994,12 +987,12 @@ static struct DecodeTestCase test_cases64[] = { }, .expected_output = { .values = (uint64_t []){0xab778190fec42261ULL}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -1016,12 +1009,12 @@ static struct DecodeTestCase test_cases64[] = { .values = (uint64_t []){ 0x12a6ULL, 0x8addf0ULL, 0xffa1b4bbULL, 0x21258ee39aaaULL }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -1039,12 +1032,12 @@ static struct DecodeTestCase test_cases64[] = { 0x55555555ULL, 0x55555555ULL, 0x55555555ULL, 0x111111111111ULL, 0x111111111111ULL }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -1055,12 +1048,12 @@ static struct DecodeTestCase test_cases64[] = { }, .expected_output = { .values = (uint64_t []){}, - .last_error_code = VtencErrorWrongFormat + .result_code = VTENC_ERR_WRONG_FORMAT } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -1071,12 +1064,12 @@ static struct DecodeTestCase test_cases64[] = { }, .expected_output = { .values = (uint64_t []){}, - .last_error_code = VtencErrorOutputTooBig + .result_code = VTENC_ERR_OUTPUT_TOO_BIG } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -1087,12 +1080,12 @@ static struct DecodeTestCase test_cases64[] = { }, .expected_output = { .values = (uint64_t []){}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -1105,12 +1098,12 @@ static struct DecodeTestCase test_cases64[] = { }, .expected_output = { .values = (uint64_t []){0x1122334455667788ULL}, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -1129,12 +1122,12 @@ static struct DecodeTestCase test_cases64[] = { 0x11223344ULL, 0xaabbccddULL, 0x1010101010ULL, 0x5555555555ULL, 0xf0f0f0f0f0ULL, 0x998877665544ULL, 0xffeeffeeffeeULL }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -1154,12 +1147,12 @@ static struct DecodeTestCase test_cases64[] = { 0x80000000ULL, 0x80000001ULL, 0x2000000000ULL, 0x2000000001ULL }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 2 @@ -1179,12 +1172,12 @@ static struct DecodeTestCase test_cases64[] = { 0x300000010001ULL, 0x30000001000fULL, 0x600000000001ULL, 0x60000000000fULL }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 4 @@ -1204,12 +1197,12 @@ static struct DecodeTestCase test_cases64[] = { 0x300000010001ULL, 0x30000001000fULL, 0x600000000001ULL, 0x60000000000fULL }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 8 @@ -1229,12 +1222,12 @@ static struct DecodeTestCase test_cases64[] = { 0x300000010001ULL, 0x30000001000fULL, 0x600000000001ULL, 0x60000000000fULL }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .decoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 8 @@ -1251,7 +1244,7 @@ static struct DecodeTestCase test_cases64[] = { .values = (uint64_t []){ 0ULL, 1ULL, 2ULL, 3ULL, 4ULL, 5ULL, 6ULL, 7ULL, 10ULL }, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } } }; @@ -1260,10 +1253,16 @@ int vtenc_decode8_test_case(struct DecodeTestCase *test_case) { struct DecodeTestCaseInput *input = &(test_case->input); struct DecodeTestCaseOutput *expected_output = &(test_case->expected_output); - VtencDecoder *decoder = &(input->decoder); uint8_t out[input->values_len & 0xffff]; // mask length to avoid large allocations on the stack + int rc; + vtenc *decoder = vtenc_create(); + assert(decoder != NULL); + + vtenc_config(decoder, VTENC_CONFIG_ALLOW_REPEATED_VALUES, input->params.allow_repeated_values); + vtenc_config(decoder, VTENC_CONFIG_SKIP_FULL_SUBTREES, input->params.skip_full_subtrees); + vtenc_config(decoder, VTENC_CONFIG_MIN_CLUSTER_LENGTH, input->params.min_cluster_length); - vtenc_decode8( + rc = vtenc_decode8( decoder, input->bytes, input->bytes_len, @@ -1271,11 +1270,13 @@ int vtenc_decode8_test_case(struct DecodeTestCase *test_case) input->values_len ); - EXPECT_TRUE(decoder->last_error_code == expected_output->last_error_code); - if (decoder->last_error_code == VtencErrorNoError) { + EXPECT_TRUE(rc == expected_output->result_code); + if (rc == VTENC_OK) { EXPECT_TRUE(memcmp(out, expected_output->values, sizeof(out)) == 0); } + vtenc_destroy(decoder); + return 1; } @@ -1283,10 +1284,16 @@ int vtenc_decode16_test_case(struct DecodeTestCase *test_case) { struct DecodeTestCaseInput *input = &(test_case->input); struct DecodeTestCaseOutput *expected_output = &(test_case->expected_output); - VtencDecoder *decoder = &(input->decoder); uint16_t out[input->values_len & 0xffff]; // mask length to avoid large allocations on the stack + int rc; + vtenc *decoder = vtenc_create(); + assert(decoder != NULL); + + vtenc_config(decoder, VTENC_CONFIG_ALLOW_REPEATED_VALUES, input->params.allow_repeated_values); + vtenc_config(decoder, VTENC_CONFIG_SKIP_FULL_SUBTREES, input->params.skip_full_subtrees); + vtenc_config(decoder, VTENC_CONFIG_MIN_CLUSTER_LENGTH, input->params.min_cluster_length); - vtenc_decode16( + rc = vtenc_decode16( decoder, input->bytes, input->bytes_len, @@ -1294,11 +1301,13 @@ int vtenc_decode16_test_case(struct DecodeTestCase *test_case) input->values_len ); - EXPECT_TRUE(decoder->last_error_code == expected_output->last_error_code); - if (decoder->last_error_code == VtencErrorNoError) { + EXPECT_TRUE(rc == expected_output->result_code); + if (rc == VTENC_OK) { EXPECT_TRUE(memcmp(out, expected_output->values, sizeof(out)) == 0); } + vtenc_destroy(decoder); + return 1; } @@ -1306,10 +1315,16 @@ int vtenc_decode32_test_case(struct DecodeTestCase *test_case) { struct DecodeTestCaseInput *input = &(test_case->input); struct DecodeTestCaseOutput *expected_output = &(test_case->expected_output); - VtencDecoder *decoder = &(input->decoder); uint32_t out[input->values_len & 0xffff]; // mask length to avoid large allocations on the stack + int rc; + vtenc *decoder = vtenc_create(); + assert(decoder != NULL); + + vtenc_config(decoder, VTENC_CONFIG_ALLOW_REPEATED_VALUES, input->params.allow_repeated_values); + vtenc_config(decoder, VTENC_CONFIG_SKIP_FULL_SUBTREES, input->params.skip_full_subtrees); + vtenc_config(decoder, VTENC_CONFIG_MIN_CLUSTER_LENGTH, input->params.min_cluster_length); - vtenc_decode32( + rc = vtenc_decode32( decoder, input->bytes, input->bytes_len, @@ -1317,11 +1332,13 @@ int vtenc_decode32_test_case(struct DecodeTestCase *test_case) input->values_len ); - EXPECT_TRUE(decoder->last_error_code == expected_output->last_error_code); - if (decoder->last_error_code == VtencErrorNoError) { + EXPECT_TRUE(rc == expected_output->result_code); + if (rc == VTENC_OK) { EXPECT_TRUE(memcmp(out, expected_output->values, sizeof(out)) == 0); } + vtenc_destroy(decoder); + return 1; } @@ -1329,10 +1346,16 @@ int vtenc_decode64_test_case(struct DecodeTestCase *test_case) { struct DecodeTestCaseInput *input = &(test_case->input); struct DecodeTestCaseOutput *expected_output = &(test_case->expected_output); - VtencDecoder *decoder = &(input->decoder); uint64_t out[input->values_len & 0xffff]; // mask length to avoid large allocations on the stack + int rc; + vtenc *decoder = vtenc_create(); + assert(decoder != NULL); + + vtenc_config(decoder, VTENC_CONFIG_ALLOW_REPEATED_VALUES, input->params.allow_repeated_values); + vtenc_config(decoder, VTENC_CONFIG_SKIP_FULL_SUBTREES, input->params.skip_full_subtrees); + vtenc_config(decoder, VTENC_CONFIG_MIN_CLUSTER_LENGTH, input->params.min_cluster_length); - vtenc_decode64( + rc = vtenc_decode64( decoder, input->bytes, input->bytes_len, @@ -1340,11 +1363,13 @@ int vtenc_decode64_test_case(struct DecodeTestCase *test_case) input->values_len ); - EXPECT_TRUE(decoder->last_error_code == expected_output->last_error_code); - if (decoder->last_error_code == VtencErrorNoError) { + EXPECT_TRUE(rc == expected_output->result_code); + if (rc == VTENC_OK) { EXPECT_TRUE(memcmp(out, expected_output->values, sizeof(out)) == 0); } + vtenc_destroy(decoder); + return 1; } diff --git a/tests/unit/encode_test.c b/tests/unit/encode_test.c index b113c9f..f109a2d 100644 --- a/tests/unit/encode_test.c +++ b/tests/unit/encode_test.c @@ -3,28 +3,21 @@ Licensed under the MIT License. See LICENSE file in the project root for full license information. */ +#include #include #include #include "unit_tests.h" #include "../../vtenc.h" -int test_vtenc_encoder_init(void) -{ - VtencEncoder enc; - - vtenc_encoder_init(&enc); - - EXPECT_TRUE(enc.allow_repeated_values == 1); - EXPECT_TRUE(enc.skip_full_subtrees == 1); - EXPECT_TRUE(enc.min_cluster_length == 1); - EXPECT_TRUE(enc.last_error_code == VtencErrorNoError); - - return 1; -} +struct EncodingParams { + int allow_repeated_values; + int skip_full_subtrees; + size_t min_cluster_length; +}; struct EncodeTestCaseInput { - VtencEncoder encoder; + struct EncodingParams params; const void *values; size_t values_len; }; @@ -32,7 +25,7 @@ struct EncodeTestCaseInput { struct EncodeTestCaseOutput { uint8_t *bytes; size_t bytes_len; - VtencErrorCode last_error_code; + int result_code; }; struct EncodeTestCase { @@ -43,7 +36,7 @@ struct EncodeTestCase { static struct EncodeTestCase test_cases8[] = { { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -54,12 +47,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorInputTooBig + .result_code = VTENC_ERR_INPUT_TOO_BIG } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -70,12 +63,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -86,12 +79,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){0x26}, .bytes_len = 1, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -104,12 +97,12 @@ static struct EncodeTestCase test_cases8[] = { 0x58, 0xab, 0x84, 0x62, 0xaf, 0xd4, 0x91, 0xac, 0xc9 }, .bytes_len = 9, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -120,12 +113,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){0x37, 0xe0, 0x01, 0x01, 0x00, 0x51, 0x05}, .bytes_len = 7, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -136,12 +129,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorInputTooBig + .result_code = VTENC_ERR_INPUT_TOO_BIG } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -152,12 +145,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -186,12 +179,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -202,12 +195,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){0x21}, .bytes_len = 1, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -218,12 +211,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){0x88, 0x88, 0x48, 0x90, 0x04}, .bytes_len = 5, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -234,12 +227,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){0x4c, 0x73, 0x4d, 0x54, 0x45, 0x01}, .bytes_len = 6, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 2 @@ -250,12 +243,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){0x6e, 0x29, 0x0d, 0x03, 0x1d}, .bytes_len = 5, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 3 @@ -266,12 +259,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){0x6e, 0x29, 0x0d, 0x03, 0x1d}, .bytes_len = 5, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 4 @@ -282,12 +275,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){0x6e, 0x29, 0x83, 0x0b, 0x3a}, .bytes_len = 5, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 8 @@ -298,12 +291,12 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){0x02, 0x03, 0x08, 0x0b, 0x10, 0x7a}, .bytes_len = 6, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 8 @@ -314,7 +307,7 @@ static struct EncodeTestCase test_cases8[] = { .expected_output = { .bytes = (uint8_t []){0x99, 0x99, 0x28}, .bytes_len = 3, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } } }; @@ -322,7 +315,7 @@ static struct EncodeTestCase test_cases8[] = { static struct EncodeTestCase test_cases16[] = { { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -333,12 +326,12 @@ static struct EncodeTestCase test_cases16[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorInputTooBig + .result_code = VTENC_ERR_INPUT_TOO_BIG } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -349,12 +342,12 @@ static struct EncodeTestCase test_cases16[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -365,12 +358,12 @@ static struct EncodeTestCase test_cases16[] = { .expected_output = { .bytes = (uint8_t []){0x26, 0x36}, .bytes_len = 2, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -384,12 +377,12 @@ static struct EncodeTestCase test_cases16[] = { 0x0e }, .bytes_len = 13, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -402,12 +395,12 @@ static struct EncodeTestCase test_cases16[] = { 0x88, 0xf3, 0x33, 0xf3, 0x4c, 0x5b, 0x14, 0x05, 0xda, 0x02 }, .bytes_len = 10, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -418,12 +411,12 @@ static struct EncodeTestCase test_cases16[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorInputTooBig + .result_code = VTENC_ERR_INPUT_TOO_BIG } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -434,12 +427,12 @@ static struct EncodeTestCase test_cases16[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -450,12 +443,12 @@ static struct EncodeTestCase test_cases16[] = { .expected_output = { .bytes = (uint8_t []){0x33, 0x5a}, .bytes_len = 2, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -469,12 +462,12 @@ static struct EncodeTestCase test_cases16[] = { 0x07, 0x74, 0x45 }, .bytes_len = 15, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -490,12 +483,12 @@ static struct EncodeTestCase test_cases16[] = { 0x8c, 0x00, 0x08, 0x80, 0x80, 0x00, 0x48, 0x02, 0x20, 0x09, 0x92 }, .bytes_len = 11, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 2 @@ -508,12 +501,12 @@ static struct EncodeTestCase test_cases16[] = { 0xa4, 0x3e, 0x04, 0x96, 0x28, 0x2f, 0xa0, 0x06, 0x16, 0x00 }, .bytes_len = 10, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 4 @@ -526,12 +519,12 @@ static struct EncodeTestCase test_cases16[] = { 0xfc, 0x10, 0x60, 0x09, 0xca, 0x4b, 0xa0, 0x26, 0x58, 0x00 }, .bytes_len = 10, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 8 @@ -544,12 +537,12 @@ static struct EncodeTestCase test_cases16[] = { 0x1f, 0x02, 0x58, 0x02, 0xe5, 0x25, 0xa0, 0x26, 0xb0, 0x80 }, .bytes_len = 10, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 8 @@ -560,7 +553,7 @@ static struct EncodeTestCase test_cases16[] = { .expected_output = { .bytes = (uint8_t []){0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x28}, .bytes_len = 7, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } } }; @@ -568,7 +561,7 @@ static struct EncodeTestCase test_cases16[] = { static struct EncodeTestCase test_cases32[] = { { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -579,12 +572,12 @@ static struct EncodeTestCase test_cases32[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorInputTooBig + .result_code = VTENC_ERR_INPUT_TOO_BIG } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -595,12 +588,12 @@ static struct EncodeTestCase test_cases32[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -613,12 +606,12 @@ static struct EncodeTestCase test_cases32[] = { 0x59, 0x48, 0x4e, 0x2b }, .bytes_len = 4, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -632,12 +625,12 @@ static struct EncodeTestCase test_cases32[] = { 0x43, 0xd0, 0x09, 0x08, 0xca, 0x27, 0x5a }, .bytes_len = 19, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -653,12 +646,12 @@ static struct EncodeTestCase test_cases32[] = { 0x8a, 0xa0, 0x82, 0x8a, 0xa8, 0x0a, 0x82 }, .bytes_len = 19, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -669,12 +662,12 @@ static struct EncodeTestCase test_cases32[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorInputTooBig + .result_code = VTENC_ERR_INPUT_TOO_BIG } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -685,12 +678,12 @@ static struct EncodeTestCase test_cases32[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -701,12 +694,12 @@ static struct EncodeTestCase test_cases32[] = { .expected_output = { .bytes = (uint8_t []){0x42, 0xba, 0xe3, 0x77}, .bytes_len = 4, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -722,12 +715,12 @@ static struct EncodeTestCase test_cases32[] = { 0xc7, 0x55, 0xe6, 0x7b, 0x37, 0xc1, 0x80, 0x04 }, .bytes_len = 20, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -746,12 +739,12 @@ static struct EncodeTestCase test_cases32[] = { 0x00, 0x10, 0x11, 0x11 }, .bytes_len = 28, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 2 @@ -767,12 +760,12 @@ static struct EncodeTestCase test_cases32[] = { 0xdf, 0x3b, 0x63, 0xfe, 0x6f, 0x11, 0x08 }, .bytes_len = 19, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 4 @@ -788,12 +781,12 @@ static struct EncodeTestCase test_cases32[] = { 0xdf, 0x3b, 0x63, 0x89, 0xff, 0x5b, 0x04, 0x02 }, .bytes_len = 20, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 8 @@ -809,12 +802,12 @@ static struct EncodeTestCase test_cases32[] = { 0xdf, 0x3b, 0x63, 0x89, 0xfe, 0x6f, 0x11, 0xc8 }, .bytes_len = 20, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 8 @@ -828,7 +821,7 @@ static struct EncodeTestCase test_cases32[] = { 0x99, 0x99, 0x28 }, .bytes_len = 15, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } } }; @@ -836,7 +829,7 @@ static struct EncodeTestCase test_cases32[] = { static struct EncodeTestCase test_cases64[] = { { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -847,12 +840,12 @@ static struct EncodeTestCase test_cases64[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorInputTooBig + .result_code = VTENC_ERR_INPUT_TOO_BIG } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -863,12 +856,12 @@ static struct EncodeTestCase test_cases64[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -881,12 +874,12 @@ static struct EncodeTestCase test_cases64[] = { 0x61, 0x22, 0xc4, 0xfe, 0x90, 0x81, 0x77, 0xab }, .bytes_len = 8, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -903,12 +896,12 @@ static struct EncodeTestCase test_cases64[] = { 0x8e, 0x3b, 0x96, 0x04 }, .bytes_len = 28, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 1 @@ -926,12 +919,12 @@ static struct EncodeTestCase test_cases64[] = { 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0x02 }, .bytes_len = 30, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -942,12 +935,12 @@ static struct EncodeTestCase test_cases64[] = { .expected_output = { .bytes = (uint8_t []){}, .bytes_len = 0, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -960,12 +953,12 @@ static struct EncodeTestCase test_cases64[] = { 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 }, .bytes_len = 8, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -984,12 +977,12 @@ static struct EncodeTestCase test_cases64[] = { 0xec, 0x0e, 0x31, 0x73, 0xff, 0x77, 0xff, 0x77, 0xff, 0x01 }, .bytes_len = 46, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 1 @@ -1009,12 +1002,12 @@ static struct EncodeTestCase test_cases64[] = { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01 }, .bytes_len = 44, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 2 @@ -1034,12 +1027,12 @@ static struct EncodeTestCase test_cases64[] = { 0x00, 0x08 }, .bytes_len = 38, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 4 @@ -1059,12 +1052,12 @@ static struct EncodeTestCase test_cases64[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }, .bytes_len = 42, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 1, .skip_full_subtrees = 0, .min_cluster_length = 8 @@ -1084,12 +1077,12 @@ static struct EncodeTestCase test_cases64[] = { 0x00, 0x60, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00 }, .bytes_len = 48, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } }, { .input = { - .encoder = { + .params = { .allow_repeated_values = 0, .skip_full_subtrees = 1, .min_cluster_length = 8 @@ -1106,7 +1099,7 @@ static struct EncodeTestCase test_cases64[] = { 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x28 }, .bytes_len = 31, - .last_error_code = VtencErrorNoError + .result_code = VTENC_OK } } }; @@ -1115,12 +1108,18 @@ int vtenc_encode8_test_case(struct EncodeTestCase *test_case) { struct EncodeTestCaseInput *input = &(test_case->input); struct EncodeTestCaseOutput *expected_output = &(test_case->expected_output); - VtencEncoder *encoder = &(input->encoder); const size_t out_cap = vtenc_max_encoded_size8(input->values_len); uint8_t out[out_cap & 0xffff]; // mask capacity to avoid large allocations on the stack size_t out_len; + int rc; + vtenc *encoder = vtenc_create(); + assert(encoder != NULL); + + vtenc_config(encoder, VTENC_CONFIG_ALLOW_REPEATED_VALUES, input->params.allow_repeated_values); + vtenc_config(encoder, VTENC_CONFIG_SKIP_FULL_SUBTREES, input->params.skip_full_subtrees); + vtenc_config(encoder, VTENC_CONFIG_MIN_CLUSTER_LENGTH, input->params.min_cluster_length); - out_len = vtenc_encode8( + rc = vtenc_encode8( encoder, input->values, input->values_len, @@ -1128,9 +1127,13 @@ int vtenc_encode8_test_case(struct EncodeTestCase *test_case) out_cap ); + out_len = vtenc_encoded_size(encoder); + EXPECT_TRUE(out_len == expected_output->bytes_len); EXPECT_TRUE(memcmp(out, expected_output->bytes, expected_output->bytes_len) == 0); - EXPECT_TRUE(encoder->last_error_code == expected_output->last_error_code); + EXPECT_TRUE(rc == expected_output->result_code); + + vtenc_destroy(encoder); return 1; } @@ -1139,12 +1142,18 @@ int vtenc_encode16_test_case(struct EncodeTestCase *test_case) { struct EncodeTestCaseInput *input = &(test_case->input); struct EncodeTestCaseOutput *expected_output = &(test_case->expected_output); - VtencEncoder *encoder = &(input->encoder); const size_t out_cap = vtenc_max_encoded_size16(input->values_len); uint8_t out[out_cap & 0xffff]; // mask capacity to avoid large allocations on the stack size_t out_len; + int rc; + vtenc *encoder = vtenc_create(); + assert(encoder != NULL); - out_len = vtenc_encode16( + vtenc_config(encoder, VTENC_CONFIG_ALLOW_REPEATED_VALUES, input->params.allow_repeated_values); + vtenc_config(encoder, VTENC_CONFIG_SKIP_FULL_SUBTREES, input->params.skip_full_subtrees); + vtenc_config(encoder, VTENC_CONFIG_MIN_CLUSTER_LENGTH, input->params.min_cluster_length); + + rc = vtenc_encode16( encoder, input->values, input->values_len, @@ -1152,9 +1161,13 @@ int vtenc_encode16_test_case(struct EncodeTestCase *test_case) out_cap ); + out_len = vtenc_encoded_size(encoder); + EXPECT_TRUE(out_len == expected_output->bytes_len); EXPECT_TRUE(memcmp(out, expected_output->bytes, expected_output->bytes_len) == 0); - EXPECT_TRUE(encoder->last_error_code == expected_output->last_error_code); + EXPECT_TRUE(rc == expected_output->result_code); + + vtenc_destroy(encoder); return 1; } @@ -1163,12 +1176,18 @@ int vtenc_encode32_test_case(struct EncodeTestCase *test_case) { struct EncodeTestCaseInput *input = &(test_case->input); struct EncodeTestCaseOutput *expected_output = &(test_case->expected_output); - VtencEncoder *encoder = &(input->encoder); const size_t out_cap = vtenc_max_encoded_size32(input->values_len); uint8_t out[out_cap & 0xffff]; // mask capacity to avoid large allocations on the stack size_t out_len; + int rc; + vtenc *encoder = vtenc_create(); + assert(encoder != NULL); - out_len = vtenc_encode32( + vtenc_config(encoder, VTENC_CONFIG_ALLOW_REPEATED_VALUES, input->params.allow_repeated_values); + vtenc_config(encoder, VTENC_CONFIG_SKIP_FULL_SUBTREES, input->params.skip_full_subtrees); + vtenc_config(encoder, VTENC_CONFIG_MIN_CLUSTER_LENGTH, input->params.min_cluster_length); + + rc = vtenc_encode32( encoder, input->values, input->values_len, @@ -1176,9 +1195,13 @@ int vtenc_encode32_test_case(struct EncodeTestCase *test_case) out_cap ); + out_len = vtenc_encoded_size(encoder); + EXPECT_TRUE(out_len == expected_output->bytes_len); EXPECT_TRUE(memcmp(out, expected_output->bytes, expected_output->bytes_len) == 0); - EXPECT_TRUE(encoder->last_error_code == expected_output->last_error_code); + EXPECT_TRUE(rc == expected_output->result_code); + + vtenc_destroy(encoder); return 1; } @@ -1187,12 +1210,18 @@ int vtenc_encode64_test_case(struct EncodeTestCase *test_case) { struct EncodeTestCaseInput *input = &(test_case->input); struct EncodeTestCaseOutput *expected_output = &(test_case->expected_output); - VtencEncoder *encoder = &(input->encoder); const size_t out_cap = vtenc_max_encoded_size64(input->values_len); uint8_t out[out_cap & 0xffff]; // mask capacity to avoid large allocations on the stack size_t out_len; + int rc; + vtenc *encoder = vtenc_create(); + assert(encoder != NULL); + + vtenc_config(encoder, VTENC_CONFIG_ALLOW_REPEATED_VALUES, input->params.allow_repeated_values); + vtenc_config(encoder, VTENC_CONFIG_SKIP_FULL_SUBTREES, input->params.skip_full_subtrees); + vtenc_config(encoder, VTENC_CONFIG_MIN_CLUSTER_LENGTH, input->params.min_cluster_length); - out_len = vtenc_encode64( + rc = vtenc_encode64( encoder, input->values, input->values_len, @@ -1200,9 +1229,13 @@ int vtenc_encode64_test_case(struct EncodeTestCase *test_case) out_cap ); + out_len = vtenc_encoded_size(encoder); + EXPECT_TRUE(out_len == expected_output->bytes_len); EXPECT_TRUE(memcmp(out, expected_output->bytes, expected_output->bytes_len) == 0); - EXPECT_TRUE(encoder->last_error_code == expected_output->last_error_code); + EXPECT_TRUE(rc == expected_output->result_code); + + vtenc_destroy(encoder); return 1; } diff --git a/tests/unit/unit_tests.c b/tests/unit/unit_tests.c index a6c4875..6f97008 100644 --- a/tests/unit/unit_tests.c +++ b/tests/unit/unit_tests.c @@ -58,8 +58,6 @@ int main() RUN_TEST(test_count_zeros_at_bit_pos32); RUN_TEST(test_count_zeros_at_bit_pos64); - RUN_TEST(test_vtenc_encoder_init); - RUN_TEST(test_vtenc_encode8); RUN_TEST(test_vtenc_encode16); RUN_TEST(test_vtenc_encode32); @@ -70,8 +68,6 @@ int main() RUN_TEST(test_vtenc_max_encoded_size32); RUN_TEST(test_vtenc_max_encoded_size64); - RUN_TEST(test_vtenc_decoder_init); - RUN_TEST(test_vtenc_decode8); RUN_TEST(test_vtenc_decode16); RUN_TEST(test_vtenc_decode32); diff --git a/tests/unit/unit_tests.h b/tests/unit/unit_tests.h index 99ded43..3b7feff 100644 --- a/tests/unit/unit_tests.h +++ b/tests/unit/unit_tests.h @@ -63,8 +63,6 @@ int test_count_zeros_at_bit_pos16(void); int test_count_zeros_at_bit_pos32(void); int test_count_zeros_at_bit_pos64(void); -int test_vtenc_encoder_init(void); - int test_vtenc_encode8(void); int test_vtenc_encode16(void); int test_vtenc_encode32(void); @@ -75,8 +73,6 @@ int test_vtenc_max_encoded_size16(void); int test_vtenc_max_encoded_size32(void); int test_vtenc_max_encoded_size64(void); -int test_vtenc_decoder_init(void); - int test_vtenc_decode8(void); int test_vtenc_decode16(void); int test_vtenc_decode32(void); diff --git a/vtenc.h b/vtenc.h index d3ed7e0..4585ca2 100644 --- a/vtenc.h +++ b/vtenc.h @@ -13,7 +13,7 @@ extern "C" { #endif -/** +/* * This library provides a series of functions to encode and decode sorted * sequences of unsigned integers using VTEnc algorithm. * @@ -21,51 +21,58 @@ extern "C" { * uint64_t. */ -/* Error codes */ -typedef enum { - VtencErrorNoError = 0, - VtencErrorMemoryAlloc = 1, - VtencErrorBufferTooSmall = 2, - VtencErrorEndOfStream = 3, - VtencErrorNotEnoughBits = 4, - VtencErrorInputTooBig = 6, - VtencErrorOutputTooBig = 7, - VtencErrorWrongFormat = 8 -} VtencErrorCode; - -/** - * typedef VtencEncoder - VTEnc encoder. +/* + * Result codes. + * + * Most VTEnc functions return an integer result code from the following set + * to indicate success or failure. */ -typedef struct { - /** - * Indicates whether repeated values are allowed or not. - */ - int allow_repeated_values; - - /** - * Indicates whether to skip full subtrees or not. - * This parameter is only applicable to sets, i.e. sequences with no repeated - * values. It's ignored if `allow_repeated_values` is set to 1. - */ - int skip_full_subtrees; - - /** - * Minimum cluster length to serialise. - */ - size_t min_cluster_length; - - /** - * 'Returning state' after calling a encode function. It'll hold the error - * code value if the encode function fails, or a 'VtencErrorNoError' value if - * the function runs successfully. - */ - VtencErrorCode last_error_code; -} VtencEncoder; - -/** - * vtenc_encoder_init - initialises encoder @enc. +#define VTENC_OK 0 /* Successful code */ +#define VTENC_ERR_BUFFER_TOO_SMALL (-1) /* Buffer too small */ +#define VTENC_ERR_END_OF_STREAM (-2) /* Write or Read reaches end of the stream */ +#define VTENC_ERR_NOT_ENOUGH_BITS (-3) /* Not enough bits to read */ +#define VTENC_ERR_INPUT_TOO_BIG (-4) /* Input size too big */ +#define VTENC_ERR_OUTPUT_TOO_BIG (-5) /* Output size too big */ +#define VTENC_ERR_WRONG_FORMAT (-6) /* Wrong encoded format */ +#define VTENC_ERR_CONFIG (-7) /* Unrecognised config option */ + +/* Encoding/decoding handler */ +typedef struct vtenc vtenc; + +/* Create a new encoding/decoding handler */ +vtenc *vtenc_create(void); + +/* Destroy an encoding/decoding handler */ +void vtenc_destroy(vtenc *handler); + +/* + * Configuration options. + * + * These constants are the available integer options that can be passed as the + * second argument to the vtenc_config() function. + * + * VTENC_CONFIG_ALLOW_REPEATED_VALUES takes a single argument of type int. If + * non-zero, the sequence to be encoded or decoded can have repeated values. + * If the parameter is zero, the sequence is considered to be a set with no + * repeated values. + * + * VTENC_CONFIG_SKIP_FULL_SUBTREES takes a single argument of type int. If + * non-zero, full subtrees are skipped to be encoded, meaning that children + * nodes in a full subtree are not part of the encoded stream. If argument is + * zero, this functionality is disabled. + * VTENC_CONFIG_SKIP_FULL_SUBTREES is only relevant to sets, so this config + * will be ignored when VTENC_CONFIG_ALLOW_REPEATED_VALUES is set to a non-zero + * value. + * + * VTENC_CONFIG_MIN_CLUSTER_LENGTH takes a single argument of type size_t. It + * sets the minimun cluster length that is encoded. */ -void vtenc_encoder_init(VtencEncoder *enc); +#define VTENC_CONFIG_ALLOW_REPEATED_VALUES 0 /* int */ +#define VTENC_CONFIG_SKIP_FULL_SUBTREES 1 /* int */ +#define VTENC_CONFIG_MIN_CLUSTER_LENGTH 2 /* size_t */ + +/* Configure encoding/decoding handler */ +int vtenc_config(vtenc *handler, int op, ...); /** * vtenc_encode* functions. @@ -73,27 +80,31 @@ void vtenc_encoder_init(VtencEncoder *enc); * Functions to encode the sequence @in into the already-allocated stream of * bytes @out, using the VTEnc algorithm with the provided encoding parameters. * - * @enc: encoder. Provides encoding parameters and holds the returning state. + * @enc: encoder. Provides encoding parameters. * @in: input sequence to be encoded. * @in_len: size of @in. * @out: output stream of bytes. * @out_cap: capacity of @out / number of allocated bytes in @out. * - * In case of error, @enc->last_error_code contains a specific error code - * after calling the function. Otherwise, it has a 'VtencErrorNoError' code. + * Returns VTENC_OK if the encoding is successful. Otherwise, an error code + * will be returned (see result codes for more info). * - * Note that these functions assume that @in is a sorted sequence and they don't - * check its order. If you pass in an unsorted sequence, @enc->last_error_code - * will still have a 'VtencErrorNoError' value after calling the function, but - * the output won't correspond to the correct encoded stream for the input - * sequence. + * The output size can be obtained by calling vtenc_encoded_size() separately. * - * Return the size of the encoded output @out. + * Note that these functions assume that @in is a sorted sequence and they don't + * check its order. If you pass in an unsorted sequence, you may still get a + * VTENC_OK code, but the output won't necessarily correspond to the correct + * encoded stream for the input sequence. + */ +int vtenc_encode8(vtenc *enc, const uint8_t *in, size_t in_len, uint8_t *out, size_t out_cap); +int vtenc_encode16(vtenc *enc, const uint16_t *in, size_t in_len, uint8_t *out, size_t out_cap); +int vtenc_encode32(vtenc *enc, const uint32_t *in, size_t in_len, uint8_t *out, size_t out_cap); +int vtenc_encode64(vtenc *enc, const uint64_t *in, size_t in_len, uint8_t *out, size_t out_cap); + +/* + * Returns the number of bytes of the output of calling a vtenc_encode* function. */ -size_t vtenc_encode8(VtencEncoder *enc, const uint8_t *in, size_t in_len, uint8_t *out, size_t out_cap); -size_t vtenc_encode16(VtencEncoder *enc, const uint16_t *in, size_t in_len, uint8_t *out, size_t out_cap); -size_t vtenc_encode32(VtencEncoder *enc, const uint32_t *in, size_t in_len, uint8_t *out, size_t out_cap); -size_t vtenc_encode64(VtencEncoder *enc, const uint64_t *in, size_t in_len, uint8_t *out, size_t out_cap); +size_t vtenc_encoded_size(vtenc *enc); /** * vtenc_max_encoded_size* functions. @@ -109,61 +120,28 @@ size_t vtenc_max_encoded_size16(size_t in_len); size_t vtenc_max_encoded_size32(size_t in_len); size_t vtenc_max_encoded_size64(size_t in_len); -/** - * typedef VtencDecoder - VTEnc decoder. - */ -typedef struct { - /** - * Indicates whether repeated values are allowed or not. - */ - int allow_repeated_values; - - /** - * Indicates whether to skip full subtrees or not. - * This parameter is only applicable to sets, i.e. sequences with no repeated - * values. It's ignored if `allow_repeated_values` is set to 1. - */ - int skip_full_subtrees; - - /** - * Minimum cluster length to serialise. - */ - size_t min_cluster_length; - - /** - * 'Returning state' after calling a decode function. It'll hold the error - * code value if the decode function fails, or a 'VtencErrorNoError' value if - * the function runs successfully. - */ - VtencErrorCode last_error_code; -} VtencDecoder; - -/** - * vtenc_decoder_init - initialises decoder @dec. - */ -void vtenc_decoder_init(VtencDecoder *dec); - /** * vtenc_decode* functions. * * Functions to decode the stream of bytes @in into the already-allocated - * sequence @out, using the VTEnc algorithm with the provided decoding + * sequence @out, using the VTEnc algorithm with the provided encoding * parameters. * - * @dec: decoder. Provides decoding parameters and holds the returning state. + * @dec: decoder. Provides encoding parameters. * @in: input stream of bytes to be decoded. * @in_len: size of @in. * @out: output sequence. * @out_len: size of @out. * - * In case of failure, @dec->last_error_code contains the error code after - * calling the function. If the function didn't fail, it holds a - * 'VtencErrorNoError' value. + * Returns VTENC_OK when the decoding is successful or an error code otherwise. + * + * Note that the size of the output (@out_len) needs to be known to call a + * vtenc_decode* function. */ -void vtenc_decode8(VtencDecoder *dec, const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len); -void vtenc_decode16(VtencDecoder *dec, const uint8_t *in, size_t in_len, uint16_t *out, size_t out_len); -void vtenc_decode32(VtencDecoder *dec, const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len); -void vtenc_decode64(VtencDecoder *dec, const uint8_t *in, size_t in_len, uint64_t *out, size_t out_len); +int vtenc_decode8(vtenc *dec, const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len); +int vtenc_decode16(vtenc *dec, const uint8_t *in, size_t in_len, uint16_t *out, size_t out_len); +int vtenc_decode32(vtenc *dec, const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len); +int vtenc_decode64(vtenc *dec, const uint8_t *in, size_t in_len, uint64_t *out, size_t out_len); #ifdef __cplusplus }