TurboPFor: Java Critical Natives
This commit is contained in:
BIN
ext/vtenc-master.zip
Normal file
BIN
ext/vtenc-master.zip
Normal file
Binary file not shown.
3
ext/vtenc/.gitignore
vendored
Normal file
3
ext/vtenc/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
21
ext/vtenc/LICENSE
Normal file
21
ext/vtenc/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Vicente Romero Calero
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
48
ext/vtenc/Makefile
Normal file
48
ext/vtenc/Makefile
Normal file
@ -0,0 +1,48 @@
|
||||
# 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.
|
||||
|
||||
TESTSDIR = tests
|
||||
UNITTESTSDIR = tests/unit
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -O3
|
||||
DEBUGFLAGS = -Wall -O0 -g3
|
||||
LDFLAGS = -shared
|
||||
AR = ar
|
||||
|
||||
SRC = $(wildcard *.c)
|
||||
OBJ = $(SRC:.c=.o)
|
||||
|
||||
.PHONY: default
|
||||
default: lib
|
||||
|
||||
.PHONY: all
|
||||
all: lib test
|
||||
|
||||
.PHONY: debug
|
||||
debug: CFLAGS = $(DEBUGFLAGS)
|
||||
debug: all
|
||||
|
||||
%.o: %.c
|
||||
${CC} -c $(CFLAGS) $<
|
||||
|
||||
libvtenc.a: $(OBJ)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
libvtenc.so: $(OBJ)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
|
||||
|
||||
.PHONY: lib
|
||||
lib: libvtenc.a libvtenc.so
|
||||
|
||||
.PHONY: test
|
||||
test: lib
|
||||
$(MAKE) -C $(TESTSDIR) all CFLAGS="$(CFLAGS)"
|
||||
$(MAKE) -C $(UNITTESTSDIR) all CFLAGS="$(CFLAGS)"
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f *.o libvtenc.a libvtenc.so
|
||||
$(MAKE) -C $(TESTSDIR) clean
|
||||
$(MAKE) -C $(UNITTESTSDIR) clean
|
||||
131
ext/vtenc/README.md
Normal file
131
ext/vtenc/README.md
Normal file
@ -0,0 +1,131 @@
|
||||
# VTEnc
|
||||
|
||||
[VTEnc](https://vteromero.github.io/2019/07/28/vtenc.html) is a compression algorithm for sorted lists of unsigned integers. This C library provides an interface to use VTEnc with different data types (8, 16, 32 and 64 bits) and with both lists and sets.
|
||||
|
||||
## Results
|
||||
|
||||
*This is a work-in-progress section. Last updated on: 27/10/2019*
|
||||
|
||||
For reference, VTEnc has been tested on a laptop Ubuntu Desktop 19.04 with a Core i7-6700HQ CPU @ 2.60GHz x 8, using different data sets (see [Tests](https://github.com/vteromero/vtenc#tests) for further information), and comparing it with other integer compression algorithms.
|
||||
|
||||
* Timestamps (`ts.txt`):
|
||||
|
||||
| Algorithm |Encoded Size|Ratio %|Encoding Speed|Decoding Speed|
|
||||
|:----------|-----------:|------:|:------------:|:------------:|
|
||||
| VTEnc | 21,686| 0.0038| - | - |
|
||||
| memcpy | 577,141,992| 100.0| - | - |
|
||||
|
||||
* `gov2.sorted`:
|
||||
|
||||
| Algorithm | Encoded Size |Ratio %|Encoding Speed|Decoding Speed|
|
||||
|:----------|-------------:|------:|:------------:|:------------:|
|
||||
| VTEnc | 2,889,599,350| 12.08| - | - |
|
||||
| memcpy |23,918,861,764| 100.0| - | - |
|
||||
|
||||
## API
|
||||
|
||||
The documented interface is found in the header file `vtenc.h`.
|
||||
|
||||
## Examples
|
||||
|
||||
Encoding example:
|
||||
|
||||
```c
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "vtenc.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
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_list_max_encoded_size_u8(in_len); /* output capacity */
|
||||
uint8_t *out=NULL;
|
||||
size_t out_len=0;
|
||||
VtencErrorCode code;
|
||||
|
||||
/* allocate `out_cap` bytes */
|
||||
out = (uint8_t *) malloc(out_cap * sizeof(uint8_t));
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "allocation error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* encode `in` list into `out` stream of bytes */
|
||||
code = vtenc_list_encode_u8(in, in_len, out, out_cap, &out_len);
|
||||
if (code != VtencErrorNoError) {
|
||||
fprintf(stderr, "failed encoding with error code: %u\n", code);
|
||||
free(out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* here `out` holds the encoded output, which is `out_len` bytes long */
|
||||
|
||||
free(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Decoding example:
|
||||
|
||||
```c
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "vtenc.h"
|
||||
|
||||
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]);
|
||||
size_t out_len = vtenc_list_decoded_size_u8(in, in_len); /* output length */
|
||||
uint8_t *out=NULL;
|
||||
VtencErrorCode code;
|
||||
|
||||
/* allocate `out_len` items */
|
||||
out = (uint8_t *) malloc(out_len * sizeof(uint8_t));
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "allocation error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* decode `in` stream of bytes into `out` list */
|
||||
code = vtenc_list_decode_u8(in, in_len, out, out_len);
|
||||
if (code != VtencErrorNoError) {
|
||||
fprintf(stderr, "failed decoding with error code: %u\n", code);
|
||||
free(out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* here `out` holds the decoded list of integers, of size `out_len` */
|
||||
|
||||
free(out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
For now, this library has only been tested on Linux and MacOS systems. It shouldn't be too difficult to support Windows as well and I'm planing to do so in future releases.
|
||||
|
||||
## Building
|
||||
|
||||
To compile the library, run `make` in root directory. That will generate the static and the shared libraries (`.a` and `.so` files), ready to be included in your own projects.
|
||||
|
||||
## Tests
|
||||
|
||||
This library is well covered with unit tests and with a few little programs to test different data sets. To build both the programs and the unit tests, run `make test` in the root directory. The following executable files will be created:
|
||||
|
||||
* `tests/unit/unit_tests`: invoke it to run all the unit tests.
|
||||
|
||||
* `tests/timestamps`: program to test [ts.txt](https://github.com/zentures/encoding/tree/master/benchmark/data), a text file with a big list of timestamps.
|
||||
|
||||
* `tests/gov2`: program to test [gov2.sorted](https://lemire.me/data/integercompression2014.html) file, which is part of the "Document identifier data set" created by [D. Lemire](https://lemire.me/en/).
|
||||
103
ext/vtenc/bits.c
Normal file
103
ext/vtenc/bits.c
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include "vtenc.h"
|
||||
|
||||
static const unsigned int BITS_LEN8[] = {
|
||||
1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
|
||||
};
|
||||
|
||||
uint16_t bits_swap_u16(uint16_t value)
|
||||
{
|
||||
return (value << 8) | (value >> 8);
|
||||
}
|
||||
|
||||
uint32_t bits_swap_u32(uint32_t value)
|
||||
{
|
||||
return ((value << 24) & 0xff000000 ) |
|
||||
((value << 8) & 0x00ff0000 ) |
|
||||
((value >> 8) & 0x0000ff00 ) |
|
||||
((value >> 24) & 0x000000ff );
|
||||
}
|
||||
|
||||
uint64_t bits_swap_u64(uint64_t value)
|
||||
{
|
||||
return ((value << 56) & 0xff00000000000000ULL) |
|
||||
((value << 40) & 0x00ff000000000000ULL) |
|
||||
((value << 24) & 0x0000ff0000000000ULL) |
|
||||
((value << 8) & 0x000000ff00000000ULL) |
|
||||
((value >> 8) & 0x00000000ff000000ULL) |
|
||||
((value >> 24) & 0x0000000000ff0000ULL) |
|
||||
((value >> 40) & 0x000000000000ff00ULL) |
|
||||
((value >> 56) & 0x00000000000000ffULL);
|
||||
}
|
||||
|
||||
unsigned int bits_len_u8(uint8_t value)
|
||||
{
|
||||
return BITS_LEN8[value];
|
||||
}
|
||||
|
||||
unsigned int bits_len_u16(uint16_t value)
|
||||
{
|
||||
unsigned int n = 0;
|
||||
|
||||
if (value > 0x00ff) {
|
||||
value >>= 8;
|
||||
n = 8;
|
||||
}
|
||||
|
||||
return n + BITS_LEN8[value];
|
||||
}
|
||||
|
||||
unsigned int bits_len_u32(uint32_t value)
|
||||
{
|
||||
unsigned int n = 0;
|
||||
|
||||
if (value > 0x0000ffff) {
|
||||
value >>= 16;
|
||||
n = 16;
|
||||
}
|
||||
if (value > 0x000000ff) {
|
||||
value >>= 8;
|
||||
n += 8;
|
||||
}
|
||||
|
||||
return n + BITS_LEN8[value];
|
||||
}
|
||||
|
||||
unsigned int bits_len_u64(uint64_t value)
|
||||
{
|
||||
unsigned int n = 0;
|
||||
|
||||
if (value > 0x00000000ffffffffULL) {
|
||||
value >>= 32;
|
||||
n = 32;
|
||||
}
|
||||
if (value > 0x000000000000ffffULL) {
|
||||
value >>= 16;
|
||||
n += 16;
|
||||
}
|
||||
if (value > 0x00000000000000ffULL) {
|
||||
value >>= 8;
|
||||
n += 8;
|
||||
}
|
||||
|
||||
return n + BITS_LEN8[value];
|
||||
}
|
||||
61
ext/vtenc/bits.h
Normal file
61
ext/vtenc/bits.h
Normal file
@ -0,0 +1,61 @@
|
||||
/**
|
||||
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_BITS_H_
|
||||
#define VTENC_BITS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static const uint64_t BITS_SIZE_MASK[] = {
|
||||
0x0ULL,
|
||||
0x1ULL, 0x3ULL, 0x7ULL, 0xfULL,
|
||||
0x1fULL, 0x3fULL, 0x7fULL, 0xffULL,
|
||||
0x1ffULL, 0x3ffULL, 0x7ffULL, 0xfffULL,
|
||||
0x1fffULL, 0x3fffULL, 0x7fffULL, 0xffffULL,
|
||||
0x1ffffULL, 0x3ffffULL, 0x7ffffULL, 0xfffffULL,
|
||||
0x1fffffULL, 0x3fffffULL, 0x7fffffULL, 0xffffffULL,
|
||||
0x1ffffffULL, 0x3ffffffULL, 0x7ffffffULL, 0xfffffffULL,
|
||||
0x1fffffffULL, 0x3fffffffULL, 0x7fffffffULL, 0xffffffffULL,
|
||||
0x1ffffffffULL, 0x3ffffffffULL, 0x7ffffffffULL, 0xfffffffffULL,
|
||||
0x1fffffffffULL, 0x3fffffffffULL, 0x7fffffffffULL, 0xffffffffffULL,
|
||||
0x1ffffffffffULL, 0x3ffffffffffULL, 0x7ffffffffffULL, 0xfffffffffffULL,
|
||||
0x1fffffffffffULL, 0x3fffffffffffULL, 0x7fffffffffffULL, 0xffffffffffffULL,
|
||||
0x1ffffffffffffULL, 0x3ffffffffffffULL, 0x7ffffffffffffULL, 0xfffffffffffffULL,
|
||||
0x1fffffffffffffULL, 0x3fffffffffffffULL, 0x7fffffffffffffULL, 0xffffffffffffffULL,
|
||||
0x1ffffffffffffffULL, 0x3ffffffffffffffULL, 0x7ffffffffffffffULL, 0xfffffffffffffffULL,
|
||||
0x1fffffffffffffffULL, 0x3fffffffffffffffULL, 0x7fffffffffffffffULL, 0xffffffffffffffffULL
|
||||
};
|
||||
#define BITS_SIZE_MASK_LEN (sizeof(BITS_SIZE_MASK) / sizeof(BITS_SIZE_MASK[0]))
|
||||
|
||||
static const uint64_t BITS_POS_MASK[] = {
|
||||
0x1ULL, 0x2ULL, 0x4ULL, 0x8ULL,
|
||||
0x10ULL, 0x20ULL, 0x40ULL, 0x80ULL,
|
||||
0x100ULL, 0x200ULL, 0x400ULL, 0x800ULL,
|
||||
0x1000ULL, 0x2000ULL, 0x4000ULL, 0x8000ULL,
|
||||
0x10000ULL, 0x20000ULL, 0x40000ULL, 0x80000ULL,
|
||||
0x100000ULL, 0x200000ULL, 0x400000ULL, 0x800000ULL,
|
||||
0x1000000ULL, 0x2000000ULL, 0x4000000ULL, 0x8000000ULL,
|
||||
0x10000000ULL, 0x20000000ULL, 0x40000000ULL, 0x80000000ULL,
|
||||
0x100000000ULL, 0x200000000ULL, 0x400000000ULL, 0x800000000ULL,
|
||||
0x1000000000ULL, 0x2000000000ULL, 0x4000000000ULL, 0x8000000000ULL,
|
||||
0x10000000000ULL, 0x20000000000ULL, 0x40000000000ULL, 0x80000000000ULL,
|
||||
0x100000000000ULL, 0x200000000000ULL, 0x400000000000ULL, 0x800000000000ULL,
|
||||
0x1000000000000ULL, 0x2000000000000ULL, 0x4000000000000ULL, 0x8000000000000ULL,
|
||||
0x10000000000000ULL, 0x20000000000000ULL, 0x40000000000000ULL, 0x80000000000000ULL,
|
||||
0x100000000000000ULL, 0x200000000000000ULL, 0x400000000000000ULL, 0x800000000000000ULL,
|
||||
0x1000000000000000ULL, 0x2000000000000000ULL, 0x4000000000000000ULL, 0x8000000000000000ULL
|
||||
};
|
||||
#define BITS_POS_MASK_LEN (sizeof(BITS_POS_MASK) / sizeof(BITS_POS_MASK[0]))
|
||||
|
||||
uint16_t bits_swap_u16(uint16_t value);
|
||||
uint32_t bits_swap_u32(uint32_t value);
|
||||
uint64_t bits_swap_u64(uint64_t value);
|
||||
|
||||
unsigned int bits_len_u8(uint8_t value);
|
||||
unsigned int bits_len_u16(uint16_t value);
|
||||
unsigned int bits_len_u32(uint32_t value);
|
||||
unsigned int bits_len_u64(uint64_t value);
|
||||
|
||||
#endif /* VTENC_BITS_H_ */
|
||||
148
ext/vtenc/bitstream.c
Normal file
148
ext/vtenc/bitstream.c
Normal file
@ -0,0 +1,148 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include "bitstream.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "bits.h"
|
||||
#include "mem.h"
|
||||
|
||||
size_t bswriter_align_buffer_size(size_t orig_size)
|
||||
{
|
||||
if ((orig_size > 0) && (orig_size%8 == 0)) return orig_size;
|
||||
return orig_size + 8 - (orig_size % 8);
|
||||
}
|
||||
|
||||
VtencErrorCode bswriter_init(BSWriter *writer, uint8_t *out_buf, size_t out_capacity)
|
||||
{
|
||||
writer->bit_container = 0;
|
||||
writer->bit_pos = 0;
|
||||
writer->start_ptr = out_buf;
|
||||
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;
|
||||
}
|
||||
|
||||
static void bswriter_append(BSWriter *writer, uint64_t value, unsigned int n_bits)
|
||||
{
|
||||
assert(n_bits <= BIT_STREAM_MAX_WRITE);
|
||||
assert(n_bits < BITS_SIZE_MASK_LEN);
|
||||
assert(n_bits + writer->bit_pos < 64);
|
||||
|
||||
writer->bit_container |= (value & BITS_SIZE_MASK[n_bits]) << writer->bit_pos;
|
||||
writer->bit_pos += n_bits;
|
||||
}
|
||||
|
||||
static VtencErrorCode bswriter_flush(BSWriter *writer)
|
||||
{
|
||||
size_t const n_bytes = writer->bit_pos >> 3;
|
||||
|
||||
assert(writer->bit_pos < 64);
|
||||
mem_write_le_u64(writer->ptr, writer->bit_container);
|
||||
|
||||
writer->ptr += n_bytes;
|
||||
writer->bit_pos &= 7;
|
||||
writer->bit_container >>= (n_bytes << 3);
|
||||
|
||||
if (writer->ptr > writer->end_ptr) return VtencErrorEndOfStream;
|
||||
return VtencErrorNoError;
|
||||
}
|
||||
|
||||
VtencErrorCode bswriter_write(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 (n_bits + writer->bit_pos >= 64)
|
||||
RETURN_IF_ERROR(bswriter_flush(writer));
|
||||
|
||||
bswriter_append(writer, value, n_bits);
|
||||
|
||||
return VtencErrorNoError;
|
||||
}
|
||||
|
||||
size_t bswriter_close(BSWriter *writer)
|
||||
{
|
||||
if (writer->ptr <= writer->end_ptr)
|
||||
bswriter_flush(writer);
|
||||
|
||||
return (writer->ptr - writer->start_ptr) + (writer->bit_pos > 0);
|
||||
}
|
||||
|
||||
VtencErrorCode bsreader_init(BSReader *reader, const uint8_t *buf, size_t buf_len)
|
||||
{
|
||||
reader->bit_container = 0;
|
||||
reader->bits_loaded = 0;
|
||||
reader->bits_consumed = 0;
|
||||
reader->start_ptr = buf;
|
||||
reader->ptr = reader->start_ptr;
|
||||
reader->end_ptr = reader->start_ptr + buf_len;
|
||||
|
||||
if (buf_len == 0) return VtencErrorBufferTooSmall;
|
||||
return VtencErrorNoError;
|
||||
}
|
||||
|
||||
static VtencErrorCode bsreader_load(BSReader *reader)
|
||||
{
|
||||
size_t n_bytes;
|
||||
|
||||
reader->ptr += reader->bits_consumed >> 3;
|
||||
|
||||
assert(reader->ptr <= reader->end_ptr);
|
||||
n_bytes = reader->end_ptr - reader->ptr;
|
||||
|
||||
if (n_bytes == 0) return VtencErrorEndOfStream;
|
||||
|
||||
if (n_bytes >= 8) {
|
||||
reader->bit_container = mem_read_le_u64(reader->ptr);
|
||||
reader->bits_loaded = 64;
|
||||
reader->bits_consumed &= 7;
|
||||
} else {
|
||||
reader->bit_container = (uint64_t)(reader->ptr[0]);
|
||||
|
||||
switch (n_bytes) {
|
||||
case 7: reader->bit_container |= (uint64_t)(reader->ptr[6]) << 48;
|
||||
case 6: reader->bit_container |= (uint64_t)(reader->ptr[5]) << 40;
|
||||
case 5: reader->bit_container |= (uint64_t)(reader->ptr[4]) << 32;
|
||||
case 4: reader->bit_container |= (uint64_t)(reader->ptr[3]) << 24;
|
||||
case 3: reader->bit_container |= (uint64_t)(reader->ptr[2]) << 16;
|
||||
case 2: reader->bit_container |= (uint64_t)(reader->ptr[1]) << 8;
|
||||
default: break;
|
||||
}
|
||||
|
||||
reader->bits_loaded = n_bytes << 3;
|
||||
reader->bits_consumed &= 7;
|
||||
}
|
||||
|
||||
return VtencErrorNoError;
|
||||
}
|
||||
|
||||
VtencErrorCode bsreader_read(BSReader *reader, unsigned int n_bits, uint64_t *read_value)
|
||||
{
|
||||
assert(n_bits <= BIT_STREAM_MAX_READ);
|
||||
assert(n_bits < BITS_SIZE_MASK_LEN);
|
||||
assert(reader->bits_consumed <= reader->bits_loaded);
|
||||
|
||||
if (n_bits + reader->bits_consumed > reader->bits_loaded) {
|
||||
RETURN_IF_ERROR(bsreader_load(reader));
|
||||
|
||||
if (n_bits + reader->bits_consumed > reader->bits_loaded)
|
||||
return VtencErrorNotEnoughBits;
|
||||
}
|
||||
|
||||
*read_value = (reader->bit_container >> reader->bits_consumed) & BITS_SIZE_MASK[n_bits];
|
||||
reader->bits_consumed += n_bits;
|
||||
|
||||
return VtencErrorNoError;
|
||||
}
|
||||
|
||||
size_t bsreader_size(BSReader *reader)
|
||||
{
|
||||
return (reader->ptr - reader->start_ptr) + (reader->bits_consumed >> 3) + ((reader->bits_consumed & 7) > 0);
|
||||
}
|
||||
44
ext/vtenc/bitstream.h
Normal file
44
ext/vtenc/bitstream.h
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
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_BITSTREAM_H_
|
||||
#define VTENC_BITSTREAM_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#define BIT_STREAM_MAX_WRITE 57
|
||||
#define BIT_STREAM_MAX_READ BIT_STREAM_MAX_WRITE
|
||||
|
||||
typedef struct {
|
||||
uint64_t bit_container;
|
||||
unsigned int bit_pos;
|
||||
uint8_t *start_ptr;
|
||||
uint8_t *ptr;
|
||||
uint8_t *end_ptr;
|
||||
} BSWriter;
|
||||
|
||||
size_t bswriter_align_buffer_size(size_t orig_size);
|
||||
|
||||
VtencErrorCode bswriter_init(BSWriter *writer, uint8_t *out_buf, size_t out_capacity);
|
||||
VtencErrorCode bswriter_write(BSWriter *writer, uint64_t value, unsigned int n_bits);
|
||||
size_t bswriter_close(BSWriter *writer);
|
||||
|
||||
typedef struct {
|
||||
uint64_t bit_container;
|
||||
unsigned int bits_loaded;
|
||||
unsigned int bits_consumed;
|
||||
const uint8_t *start_ptr;
|
||||
const uint8_t *ptr;
|
||||
const uint8_t *end_ptr;
|
||||
} BSReader;
|
||||
|
||||
VtencErrorCode bsreader_init(BSReader *reader, const uint8_t *buf, size_t buf_len);
|
||||
VtencErrorCode bsreader_read(BSReader *reader, unsigned int n_bits, uint64_t *read_value);
|
||||
size_t bsreader_size(BSReader *reader);
|
||||
|
||||
#endif /* VTENC_BITSTREAM_H_ */
|
||||
19
ext/vtenc/common.h
Normal file
19
ext/vtenc/common.h
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
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_COMMON_H_
|
||||
#define VTENC_COMMON_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bits.h"
|
||||
|
||||
static unsigned int is_full_subtree(size_t values_len, unsigned int bit_pos)
|
||||
{
|
||||
return ((uint64_t)values_len == BITS_POS_MASK[bit_pos + 1]);
|
||||
}
|
||||
|
||||
#endif /* VTENC_COMMON_H_ */
|
||||
54
ext/vtenc/decode.c
Normal file
54
ext/vtenc/decode.c
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include "vtenc.h"
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
#define LIST_MAX_VALUES VTENC_LIST_MAX_VALUES
|
||||
#define LIST_CARDINALITY_SIZE VTENC_LIST_CARDINALITY_SIZE
|
||||
|
||||
#define TYPE uint8_t
|
||||
#define WIDTH 8
|
||||
#define SET_MAX_VALUES VTENC_SET_MAX_VALUES_U8
|
||||
#define SET_CARDINALITY_SIZE VTENC_SET_CARDINALITY_SIZE_U8
|
||||
#include "decode_generic.h"
|
||||
#undef TYPE
|
||||
#undef WIDTH
|
||||
#undef SET_MAX_VALUES
|
||||
#undef SET_CARDINALITY_SIZE
|
||||
|
||||
#define TYPE uint16_t
|
||||
#define WIDTH 16
|
||||
#define SET_MAX_VALUES VTENC_SET_MAX_VALUES_U16
|
||||
#define SET_CARDINALITY_SIZE VTENC_SET_CARDINALITY_SIZE_U16
|
||||
#include "decode_generic.h"
|
||||
#undef TYPE
|
||||
#undef WIDTH
|
||||
#undef SET_MAX_VALUES
|
||||
#undef SET_CARDINALITY_SIZE
|
||||
|
||||
#define TYPE uint32_t
|
||||
#define WIDTH 32
|
||||
#define SET_MAX_VALUES VTENC_SET_MAX_VALUES_U32
|
||||
#define SET_CARDINALITY_SIZE VTENC_SET_CARDINALITY_SIZE_U32
|
||||
#include "decode_generic.h"
|
||||
#undef TYPE
|
||||
#undef WIDTH
|
||||
#undef SET_MAX_VALUES
|
||||
#undef SET_CARDINALITY_SIZE
|
||||
|
||||
#define TYPE uint64_t
|
||||
#define WIDTH 64
|
||||
#define SET_MAX_VALUES VTENC_SET_MAX_VALUES_U64
|
||||
#define SET_CARDINALITY_SIZE VTENC_SET_CARDINALITY_SIZE_U64
|
||||
#include "decode_generic.h"
|
||||
#undef TYPE
|
||||
#undef WIDTH
|
||||
#undef SET_MAX_VALUES
|
||||
#undef SET_CARDINALITY_SIZE
|
||||
|
||||
#undef LIST_MAX_VALUES
|
||||
#undef LIST_CARDINALITY_SIZE
|
||||
169
ext/vtenc/decode_generic.h
Normal file
169
ext/vtenc/decode_generic.h
Normal file
@ -0,0 +1,169 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "common.h"
|
||||
#include "error.h"
|
||||
#include "internals.h"
|
||||
|
||||
#define DecodeCtx(_width_) PASTE2(DecodeCtx, _width_)
|
||||
#define decode_ctx_init(_width_) ADD_UINT_SUFFIX(decode_ctx_init, _width_)
|
||||
#define decode_full_subtree(_width_) ADD_UINT_SUFFIX(decode_full_subtree, _width_)
|
||||
#define set_ones_at_bit_pos(_width_) ADD_UINT_SUFFIX(set_ones_at_bit_pos, _width_)
|
||||
#define decode_bits_tree(_width_) ADD_UINT_SUFFIX(decode_bits_tree, _width_)
|
||||
#define list_read_cardinality(_width_) ADD_UINT_SUFFIX(list_read_cardinality, _width_)
|
||||
#define set_read_cardinality(_width_) ADD_UINT_SUFFIX(set_read_cardinality, _width_)
|
||||
#define vtenc_list_decode(_width_) ADD_UINT_SUFFIX(vtenc_list_decode, _width_)
|
||||
#define vtenc_set_decode(_width_) ADD_UINT_SUFFIX(vtenc_set_decode, _width_)
|
||||
#define vtenc_list_decoded_size(_width_) ADD_UINT_SUFFIX(vtenc_list_decoded_size, _width_)
|
||||
#define vtenc_set_decoded_size(_width_) ADD_UINT_SUFFIX(vtenc_set_decoded_size, _width_)
|
||||
|
||||
struct DecodeCtx(WIDTH) {
|
||||
TYPE *values;
|
||||
size_t values_len;
|
||||
unsigned int reconstruct_full_subtrees;
|
||||
BSReader bits_reader;
|
||||
};
|
||||
|
||||
static VtencErrorCode decode_ctx_init(WIDTH)(struct DecodeCtx(WIDTH) *ctx,
|
||||
const uint8_t *in, size_t in_len, TYPE *out, size_t out_len)
|
||||
{
|
||||
ctx->values = out;
|
||||
ctx->values_len = out_len;
|
||||
ctx->reconstruct_full_subtrees = 0;
|
||||
return bsreader_init(&(ctx->bits_reader), in, in_len);
|
||||
}
|
||||
|
||||
static void decode_full_subtree(WIDTH)(TYPE *values, size_t values_len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < values_len; ++i) {
|
||||
values[i] |= (TYPE)i;
|
||||
}
|
||||
}
|
||||
|
||||
static void set_ones_at_bit_pos(WIDTH)(TYPE *values,
|
||||
size_t values_len, unsigned int bit_pos)
|
||||
{
|
||||
int i;
|
||||
const TYPE mask = (const TYPE)BITS_POS_MASK[bit_pos];
|
||||
|
||||
for (i = 0; i < values_len; ++i) {
|
||||
values[i] |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
static VtencErrorCode decode_bits_tree(WIDTH)(struct DecodeCtx(WIDTH) *ctx,
|
||||
unsigned int bit_pos, size_t idx_from, size_t idx_to)
|
||||
{
|
||||
TYPE *values_chunk = ctx->values + idx_from;
|
||||
size_t values_chunk_len = idx_to - idx_from;
|
||||
unsigned int enc_len;
|
||||
uint64_t n_zeros;
|
||||
|
||||
assert(bit_pos <= MAX_BIT_POS(WIDTH));
|
||||
assert(idx_from <= idx_to);
|
||||
assert(idx_to <= ctx->values_len);
|
||||
|
||||
if (values_chunk_len == 0) return VtencErrorNoError;
|
||||
|
||||
if (ctx->reconstruct_full_subtrees && is_full_subtree(values_chunk_len, bit_pos)) {
|
||||
decode_full_subtree(WIDTH)(values_chunk, values_chunk_len);
|
||||
return VtencErrorNoError;
|
||||
}
|
||||
|
||||
enc_len = bits_len_u64(values_chunk_len);
|
||||
|
||||
RETURN_IF_ERROR(bsreader_read(&(ctx->bits_reader), enc_len, &n_zeros));
|
||||
|
||||
if (n_zeros > (uint64_t)values_chunk_len) return VtencErrorWrongFormat;
|
||||
|
||||
set_ones_at_bit_pos(WIDTH)(values_chunk + n_zeros, values_chunk_len - n_zeros, bit_pos);
|
||||
|
||||
if (bit_pos == 0) return VtencErrorNoError;
|
||||
|
||||
RETURN_IF_ERROR(decode_bits_tree(WIDTH)(ctx, bit_pos - 1, idx_from, idx_from + n_zeros));
|
||||
return decode_bits_tree(WIDTH)(ctx, bit_pos - 1, idx_from + n_zeros, idx_to);
|
||||
}
|
||||
|
||||
static VtencErrorCode list_read_cardinality(WIDTH)(BSReader *reader, uint64_t *cardinality)
|
||||
{
|
||||
return bsreader_read(reader, LIST_CARDINALITY_SIZE, cardinality);
|
||||
}
|
||||
|
||||
static VtencErrorCode set_read_cardinality(WIDTH)(BSReader *reader, uint64_t *cardinality)
|
||||
{
|
||||
RETURN_IF_ERROR(bsreader_read(reader, SET_CARDINALITY_SIZE, cardinality));
|
||||
++(*cardinality);
|
||||
return VtencErrorNoError;
|
||||
}
|
||||
|
||||
VtencErrorCode vtenc_list_decode(WIDTH)(const uint8_t *in, size_t in_len, TYPE *out, size_t out_len)
|
||||
{
|
||||
struct DecodeCtx(WIDTH) ctx;
|
||||
uint64_t cardinality;
|
||||
|
||||
memset(out, 0, out_len * sizeof(*out));
|
||||
|
||||
RETURN_IF_ERROR(decode_ctx_init(WIDTH)(&ctx, in, in_len, out, out_len));
|
||||
|
||||
RETURN_IF_ERROR(list_read_cardinality(WIDTH)(&(ctx.bits_reader), &cardinality));
|
||||
|
||||
if (cardinality > LIST_MAX_VALUES) return VtencErrorWrongFormat;
|
||||
if (cardinality != (uint64_t)out_len) return VtencErrorWrongFormat;
|
||||
|
||||
RETURN_IF_ERROR(decode_bits_tree(WIDTH)(&ctx, MAX_BIT_POS(WIDTH), 0, out_len));
|
||||
|
||||
return VtencErrorNoError;
|
||||
}
|
||||
|
||||
VtencErrorCode vtenc_set_decode(WIDTH)(const uint8_t *in, size_t in_len, TYPE *out, size_t out_len)
|
||||
{
|
||||
struct DecodeCtx(WIDTH) ctx;
|
||||
uint64_t cardinality;
|
||||
|
||||
memset(out, 0, out_len * sizeof(*out));
|
||||
|
||||
RETURN_IF_ERROR(decode_ctx_init(WIDTH)(&ctx, in, in_len, out, out_len));
|
||||
|
||||
ctx.reconstruct_full_subtrees = 1;
|
||||
|
||||
RETURN_IF_ERROR(set_read_cardinality(WIDTH)(&(ctx.bits_reader), &cardinality));
|
||||
|
||||
if (cardinality > SET_MAX_VALUES) return VtencErrorWrongFormat;
|
||||
if (cardinality != (uint64_t)out_len) return VtencErrorWrongFormat;
|
||||
|
||||
RETURN_IF_ERROR(decode_bits_tree(WIDTH)(&ctx, MAX_BIT_POS(WIDTH), 0, out_len));
|
||||
|
||||
return VtencErrorNoError;
|
||||
}
|
||||
|
||||
size_t vtenc_list_decoded_size(WIDTH)(const uint8_t *in, size_t in_len)
|
||||
{
|
||||
BSReader reader;
|
||||
size_t dec_len;
|
||||
|
||||
RETURN_ZERO_IF_ERROR(bsreader_init(&reader, in, in_len));
|
||||
RETURN_ZERO_IF_ERROR(list_read_cardinality(WIDTH)(&reader, &dec_len));
|
||||
|
||||
return dec_len;
|
||||
}
|
||||
|
||||
size_t vtenc_set_decoded_size(WIDTH)(const uint8_t *in, size_t in_len)
|
||||
{
|
||||
BSReader reader;
|
||||
size_t dec_len;
|
||||
|
||||
RETURN_ZERO_IF_ERROR(bsreader_init(&reader, in, in_len));
|
||||
RETURN_ZERO_IF_ERROR(set_read_cardinality(WIDTH)(&reader, &dec_len));
|
||||
|
||||
return dec_len;
|
||||
}
|
||||
54
ext/vtenc/encode.c
Normal file
54
ext/vtenc/encode.c
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include "vtenc.h"
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
#define LIST_MAX_VALUES VTENC_LIST_MAX_VALUES
|
||||
#define LIST_CARDINALITY_SIZE VTENC_LIST_CARDINALITY_SIZE
|
||||
|
||||
#define TYPE uint8_t
|
||||
#define WIDTH 8
|
||||
#define SET_MAX_VALUES VTENC_SET_MAX_VALUES_U8
|
||||
#define SET_CARDINALITY_SIZE VTENC_SET_CARDINALITY_SIZE_U8
|
||||
#include "encode_generic.h"
|
||||
#undef TYPE
|
||||
#undef WIDTH
|
||||
#undef SET_MAX_VALUES
|
||||
#undef SET_CARDINALITY_SIZE
|
||||
|
||||
#define TYPE uint16_t
|
||||
#define WIDTH 16
|
||||
#define SET_MAX_VALUES VTENC_SET_MAX_VALUES_U16
|
||||
#define SET_CARDINALITY_SIZE VTENC_SET_CARDINALITY_SIZE_U16
|
||||
#include "encode_generic.h"
|
||||
#undef TYPE
|
||||
#undef WIDTH
|
||||
#undef SET_MAX_VALUES
|
||||
#undef SET_CARDINALITY_SIZE
|
||||
|
||||
#define TYPE uint32_t
|
||||
#define WIDTH 32
|
||||
#define SET_MAX_VALUES VTENC_SET_MAX_VALUES_U32
|
||||
#define SET_CARDINALITY_SIZE VTENC_SET_CARDINALITY_SIZE_U32
|
||||
#include "encode_generic.h"
|
||||
#undef TYPE
|
||||
#undef WIDTH
|
||||
#undef SET_MAX_VALUES
|
||||
#undef SET_CARDINALITY_SIZE
|
||||
|
||||
#define TYPE uint64_t
|
||||
#define WIDTH 64
|
||||
#define SET_MAX_VALUES VTENC_SET_MAX_VALUES_U64
|
||||
#define SET_CARDINALITY_SIZE VTENC_SET_CARDINALITY_SIZE_U64
|
||||
#include "encode_generic.h"
|
||||
#undef TYPE
|
||||
#undef WIDTH
|
||||
#undef SET_MAX_VALUES
|
||||
#undef SET_CARDINALITY_SIZE
|
||||
|
||||
#undef LIST_MAX_VALUES
|
||||
#undef LIST_CARDINALITY_SIZE
|
||||
154
ext/vtenc/encode_generic.h
Normal file
154
ext/vtenc/encode_generic.h
Normal file
@ -0,0 +1,154 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "common.h"
|
||||
#include "error.h"
|
||||
#include "internals.h"
|
||||
|
||||
#define EncodeCtx(_width_) PASTE2(EncodeCtx, _width_)
|
||||
#define encode_ctx_init(_width_) ADD_UINT_SUFFIX(encode_ctx_init, _width_)
|
||||
#define encode_ctx_close(_width_) ADD_UINT_SUFFIX(encode_ctx_close, _width_)
|
||||
#define count_zeros_at_bit_pos(_width_) ADD_UINT_SUFFIX(count_zeros_at_bit_pos, _width_)
|
||||
#define encode_bits_tree(_width_) ADD_UINT_SUFFIX(encode_bits_tree, _width_)
|
||||
#define list_write_cardinality(_width_) ADD_UINT_SUFFIX(list_write_cardinality, _width_)
|
||||
#define set_write_cardinality(_width_) ADD_UINT_SUFFIX(set_write_cardinality, _width_)
|
||||
#define vtenc_list_encode(_width_) ADD_UINT_SUFFIX(vtenc_list_encode, _width_)
|
||||
#define vtenc_set_encode(_width_) ADD_UINT_SUFFIX(vtenc_set_encode, _width_)
|
||||
#define vtenc_list_max_encoded_size(_width_) ADD_UINT_SUFFIX(vtenc_list_max_encoded_size, _width_)
|
||||
#define vtenc_set_max_encoded_size(_width_) ADD_UINT_SUFFIX(vtenc_set_max_encoded_size, _width_)
|
||||
|
||||
struct EncodeCtx(WIDTH) {
|
||||
const TYPE *values;
|
||||
size_t values_len;
|
||||
unsigned int skip_full_subtrees;
|
||||
BSWriter bits_writer;
|
||||
};
|
||||
|
||||
static VtencErrorCode encode_ctx_init(WIDTH)(struct EncodeCtx(WIDTH) *ctx,
|
||||
const TYPE *in, size_t in_len, uint8_t *out, size_t out_cap)
|
||||
{
|
||||
ctx->values = in;
|
||||
ctx->values_len = in_len;
|
||||
ctx->skip_full_subtrees = 0;
|
||||
return bswriter_init(&(ctx->bits_writer), out, out_cap);
|
||||
}
|
||||
|
||||
static size_t encode_ctx_close(WIDTH)(struct EncodeCtx(WIDTH) *ctx)
|
||||
{
|
||||
return bswriter_close(&(ctx->bits_writer));
|
||||
}
|
||||
|
||||
static size_t count_zeros_at_bit_pos(WIDTH)(const TYPE *values,
|
||||
size_t values_len, unsigned int bit_pos)
|
||||
{
|
||||
const TYPE mask = (const TYPE)BITS_POS_MASK[bit_pos];
|
||||
size_t l = 0;
|
||||
size_t r = values_len;
|
||||
size_t m, i;
|
||||
|
||||
do {
|
||||
m = (r - l) / 2;
|
||||
i = l + m;
|
||||
if((values[i] & mask) == 0) {
|
||||
l = i;
|
||||
} else {
|
||||
r = i;
|
||||
}
|
||||
} while (m > 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static VtencErrorCode encode_bits_tree(WIDTH)(struct EncodeCtx(WIDTH) *ctx,
|
||||
unsigned int bit_pos, size_t idx_from, size_t idx_to)
|
||||
{
|
||||
const TYPE *values_chunk = ctx->values + idx_from;
|
||||
const size_t values_chunk_len = idx_to - idx_from;
|
||||
size_t n_zeros;
|
||||
unsigned int enc_len;
|
||||
|
||||
assert(bit_pos <= MAX_BIT_POS(WIDTH));
|
||||
assert(idx_from <= idx_to);
|
||||
assert(idx_to <= ctx->values_len);
|
||||
|
||||
if (values_chunk_len == 0) return VtencErrorNoError;
|
||||
|
||||
if (ctx->skip_full_subtrees && is_full_subtree(values_chunk_len, bit_pos))
|
||||
return VtencErrorNoError;
|
||||
|
||||
n_zeros = count_zeros_at_bit_pos(WIDTH)(values_chunk, values_chunk_len, bit_pos);
|
||||
enc_len = bits_len_u64(values_chunk_len);
|
||||
|
||||
RETURN_IF_ERROR(bswriter_write(&(ctx->bits_writer), n_zeros, enc_len));
|
||||
|
||||
if (bit_pos == 0) return VtencErrorNoError;
|
||||
|
||||
RETURN_IF_ERROR(encode_bits_tree(WIDTH)(ctx, bit_pos - 1, idx_from, idx_from + n_zeros));
|
||||
return encode_bits_tree(WIDTH)(ctx, bit_pos - 1, idx_from + n_zeros, idx_to);
|
||||
}
|
||||
|
||||
static VtencErrorCode list_write_cardinality(WIDTH)(struct EncodeCtx(WIDTH) *ctx)
|
||||
{
|
||||
return bswriter_write(&(ctx->bits_writer), ctx->values_len, LIST_CARDINALITY_SIZE);
|
||||
}
|
||||
|
||||
static VtencErrorCode set_write_cardinality(WIDTH)(struct EncodeCtx(WIDTH) *ctx)
|
||||
{
|
||||
return bswriter_write(&(ctx->bits_writer), ctx->values_len - 1, SET_CARDINALITY_SIZE);
|
||||
}
|
||||
|
||||
VtencErrorCode vtenc_list_encode(WIDTH)(const TYPE *in, size_t in_len,
|
||||
uint8_t *out, size_t out_cap, size_t *out_len)
|
||||
{
|
||||
struct EncodeCtx(WIDTH) ctx;
|
||||
|
||||
if ((uint64_t)in_len > LIST_MAX_VALUES) return VtencErrorInputTooBig;
|
||||
|
||||
RETURN_IF_ERROR(encode_ctx_init(WIDTH)(&ctx, in, in_len, out, out_cap));
|
||||
|
||||
RETURN_IF_ERROR(list_write_cardinality(WIDTH)(&ctx));
|
||||
|
||||
RETURN_IF_ERROR(encode_bits_tree(WIDTH)(&ctx, MAX_BIT_POS(WIDTH), 0, in_len));
|
||||
|
||||
*out_len = encode_ctx_close(WIDTH)(&ctx);
|
||||
|
||||
return VtencErrorNoError;
|
||||
}
|
||||
|
||||
VtencErrorCode vtenc_set_encode(WIDTH)(const TYPE *in, size_t in_len,
|
||||
uint8_t *out, size_t out_cap, size_t *out_len)
|
||||
{
|
||||
struct EncodeCtx(WIDTH) ctx;
|
||||
|
||||
if (in_len == 0) return VtencErrorInputTooSmall;
|
||||
if ((uint64_t)in_len > SET_MAX_VALUES) return VtencErrorInputTooBig;
|
||||
|
||||
RETURN_IF_ERROR(encode_ctx_init(WIDTH)(&ctx, in, in_len, out, out_cap));
|
||||
|
||||
ctx.skip_full_subtrees = 1;
|
||||
|
||||
RETURN_IF_ERROR(set_write_cardinality(WIDTH)(&ctx));
|
||||
|
||||
RETURN_IF_ERROR(encode_bits_tree(WIDTH)(&ctx, MAX_BIT_POS(WIDTH), 0, in_len));
|
||||
|
||||
*out_len = encode_ctx_close(WIDTH)(&ctx);
|
||||
|
||||
return VtencErrorNoError;
|
||||
}
|
||||
|
||||
size_t vtenc_list_max_encoded_size(WIDTH)(size_t in_len)
|
||||
{
|
||||
return bswriter_align_buffer_size((LIST_CARDINALITY_SIZE / 8) + (WIDTH / 8) * (in_len + 1));
|
||||
}
|
||||
|
||||
size_t vtenc_set_max_encoded_size(WIDTH)(size_t in_len)
|
||||
{
|
||||
return bswriter_align_buffer_size((SET_CARDINALITY_SIZE / 8) + (WIDTH / 8) * (in_len + 1));
|
||||
}
|
||||
25
ext/vtenc/error.h
Normal file
25
ext/vtenc/error.h
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
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)
|
||||
|
||||
#define RETURN_ZERO_IF_ERROR(exp) \
|
||||
do { \
|
||||
const VtencErrorCode code = (exp); \
|
||||
if (code != VtencErrorNoError) \
|
||||
return 0; \
|
||||
} while(0)
|
||||
|
||||
#endif /* VTENC_ERROR_H_ */
|
||||
35
ext/vtenc/internals.h
Normal file
35
ext/vtenc/internals.h
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
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_INTERNALS_H_
|
||||
#define VTENC_INTERNALS_H_
|
||||
|
||||
#include "bits.h"
|
||||
#include "bitstream.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 ADD_UINT_SUFFIX(_name_, _width_) PASTE3(_name_, _u, _width_)
|
||||
#define MAX_BIT_POS(_width_) ((_width_) - 1)
|
||||
|
||||
/* VTEnc constants */
|
||||
|
||||
#define VTENC_LIST_CARDINALITY_SIZE BIT_STREAM_MAX_WRITE
|
||||
#define VTENC_LIST_MAX_VALUES BITS_SIZE_MASK[BIT_STREAM_MAX_WRITE]
|
||||
|
||||
#define VTENC_SET_CARDINALITY_SIZE_U8 MIN(8, BIT_STREAM_MAX_WRITE)
|
||||
#define VTENC_SET_MAX_VALUES_U8 BITS_POS_MASK[VTENC_SET_CARDINALITY_SIZE_U8]
|
||||
#define VTENC_SET_CARDINALITY_SIZE_U16 MIN(16, BIT_STREAM_MAX_WRITE)
|
||||
#define VTENC_SET_MAX_VALUES_U16 BITS_POS_MASK[VTENC_SET_CARDINALITY_SIZE_U16]
|
||||
#define VTENC_SET_CARDINALITY_SIZE_U32 MIN(32, BIT_STREAM_MAX_WRITE)
|
||||
#define VTENC_SET_MAX_VALUES_U32 BITS_POS_MASK[VTENC_SET_CARDINALITY_SIZE_U32]
|
||||
#define VTENC_SET_CARDINALITY_SIZE_U64 MIN(64, BIT_STREAM_MAX_WRITE)
|
||||
#define VTENC_SET_MAX_VALUES_U64 BITS_POS_MASK[VTENC_SET_CARDINALITY_SIZE_U64]
|
||||
|
||||
#endif /* VTENC_INTERNALS_H_ */
|
||||
108
ext/vtenc/mem.c
Normal file
108
ext/vtenc/mem.c
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include "mem.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "bits.h"
|
||||
|
||||
unsigned mem_is_little_endian(void)
|
||||
{
|
||||
const union { uint32_t u; uint8_t c[4]; } one = { 1 };
|
||||
return one.c[0];
|
||||
}
|
||||
|
||||
/* Generic read functions */
|
||||
|
||||
uint16_t mem_read_u16(const void* mem_ptr)
|
||||
{
|
||||
uint16_t value;
|
||||
memcpy(&value, mem_ptr, sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t mem_read_u32(const void* mem_ptr)
|
||||
{
|
||||
uint32_t value;
|
||||
memcpy(&value, mem_ptr, sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
uint64_t mem_read_u64(const void* mem_ptr)
|
||||
{
|
||||
uint64_t value;
|
||||
memcpy(&value, mem_ptr, sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Generic write functions */
|
||||
|
||||
void mem_write_u16(void* mem_ptr, uint16_t value)
|
||||
{
|
||||
memcpy(mem_ptr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
void mem_write_u32(void* mem_ptr, uint32_t value)
|
||||
{
|
||||
memcpy(mem_ptr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
void mem_write_u64(void* mem_ptr, uint64_t value)
|
||||
{
|
||||
memcpy(mem_ptr, &value, sizeof(value));
|
||||
}
|
||||
|
||||
/* Little endian read functions */
|
||||
|
||||
uint16_t mem_read_le_u16(const void* mem_ptr)
|
||||
{
|
||||
if (mem_is_little_endian())
|
||||
return mem_read_u16(mem_ptr);
|
||||
else
|
||||
return bits_swap_u16(mem_read_u16(mem_ptr));
|
||||
}
|
||||
|
||||
uint32_t mem_read_le_u32(const void* mem_ptr)
|
||||
{
|
||||
if (mem_is_little_endian())
|
||||
return mem_read_u32(mem_ptr);
|
||||
else
|
||||
return bits_swap_u32(mem_read_u32(mem_ptr));
|
||||
}
|
||||
|
||||
uint64_t mem_read_le_u64(const void* mem_ptr)
|
||||
{
|
||||
if (mem_is_little_endian())
|
||||
return mem_read_u64(mem_ptr);
|
||||
else
|
||||
return bits_swap_u64(mem_read_u64(mem_ptr));
|
||||
}
|
||||
|
||||
/* Little endian write functions */
|
||||
|
||||
void mem_write_le_u16(void* mem_ptr, uint16_t value)
|
||||
{
|
||||
if (mem_is_little_endian())
|
||||
mem_write_u16(mem_ptr, value);
|
||||
else
|
||||
mem_write_u16(mem_ptr, bits_swap_u16(value));
|
||||
}
|
||||
|
||||
void mem_write_le_u32(void* mem_ptr, uint32_t value)
|
||||
{
|
||||
if (mem_is_little_endian())
|
||||
mem_write_u32(mem_ptr, value);
|
||||
else
|
||||
mem_write_u32(mem_ptr, bits_swap_u32(value));
|
||||
}
|
||||
|
||||
void mem_write_le_u64(void* mem_ptr, uint64_t value)
|
||||
{
|
||||
if (mem_is_little_endian())
|
||||
mem_write_u64(mem_ptr, value);
|
||||
else
|
||||
mem_write_u64(mem_ptr, bits_swap_u64(value));
|
||||
}
|
||||
19
ext/vtenc/mem.h
Normal file
19
ext/vtenc/mem.h
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
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_MEM_H_
|
||||
#define VTENC_MEM_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint16_t mem_read_le_u16(const void* mem_ptr);
|
||||
uint32_t mem_read_le_u32(const void* mem_ptr);
|
||||
uint64_t mem_read_le_u64(const void* mem_ptr);
|
||||
|
||||
void mem_write_le_u16(void* mem_ptr, uint16_t value);
|
||||
void mem_write_le_u32(void* mem_ptr, uint32_t value);
|
||||
void mem_write_le_u64(void* mem_ptr, uint64_t value);
|
||||
|
||||
#endif /* VTENC_MEM_H_ */
|
||||
27
ext/vtenc/tests/Makefile
Normal file
27
ext/vtenc/tests/Makefile
Normal file
@ -0,0 +1,27 @@
|
||||
# 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.
|
||||
|
||||
VTENCDIR = ..
|
||||
|
||||
CC = gcc
|
||||
CFLAGS ?= -Wall -O3
|
||||
|
||||
.PHONY: default
|
||||
default: all
|
||||
|
||||
.PHONY: all
|
||||
all: timestamps gov2
|
||||
|
||||
%.o: %.c
|
||||
${CC} -c $(CFLAGS) $<
|
||||
|
||||
timestamps: timestamps.o
|
||||
$(CC) $(CFLAGS) $^ $(VTENCDIR)/libvtenc.a -o $@
|
||||
|
||||
gov2: gov2.o
|
||||
$(CC) $(CFLAGS) $^ $(VTENCDIR)/libvtenc.a -o $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f *.o timestamps gov2
|
||||
207
ext/vtenc/tests/gov2.c
Normal file
207
ext/vtenc/tests/gov2.c
Normal file
@ -0,0 +1,207 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../vtenc.h"
|
||||
|
||||
struct Stats {
|
||||
size_t n_sets;
|
||||
size_t total_input_size;
|
||||
size_t total_encoded_size;
|
||||
};
|
||||
|
||||
void stats_init(struct Stats *stats)
|
||||
{
|
||||
stats->n_sets = 0;
|
||||
stats->total_input_size = 0;
|
||||
stats->total_encoded_size = 0;
|
||||
}
|
||||
|
||||
void stats_print(const struct Stats *stats)
|
||||
{
|
||||
double ratio = stats->total_encoded_size / (double)(stats->total_input_size);
|
||||
|
||||
printf("number of sets processed: %lu\n", stats->n_sets);
|
||||
printf("input size: %lu bytes\n", stats->total_input_size);
|
||||
printf("encoded size: %lu bytes\n", stats->total_encoded_size);
|
||||
printf("compression ratio: %f (%.4f%%)\n", ratio, ratio * 100.0);
|
||||
}
|
||||
|
||||
int read_u32_from_file(FILE *fp, uint32_t *value)
|
||||
{
|
||||
char bytes[4];
|
||||
size_t n_read = fread(bytes, sizeof(char), sizeof(bytes), fp);
|
||||
|
||||
if (n_read < sizeof(bytes)) {
|
||||
return 0;
|
||||
} else {
|
||||
memcpy(value, bytes, sizeof(*value));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int read_values_from_file(FILE *fp, uint32_t *values, uint32_t values_len)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < values_len; ++i) {
|
||||
if (!read_u32_from_file(fp, &(values[i]))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int has_strictly_ascending_order(const uint32_t *values, uint32_t values_len)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 1; i < values_len; ++i) {
|
||||
if (values[i] <= values[i - 1]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int encode_and_decode_set(const uint32_t *values, uint32_t values_len, struct Stats *stats)
|
||||
{
|
||||
size_t enc_out_cap, enc_out_len, dec_out_len;
|
||||
uint8_t *enc_out;
|
||||
uint32_t *dec_out;
|
||||
VtencErrorCode enc_ret_code, dec_ret_code;
|
||||
int exit_code = 1;
|
||||
|
||||
enc_out_cap = vtenc_set_max_encoded_size_u32(values_len);
|
||||
enc_out = (uint8_t *) malloc(enc_out_cap * sizeof(uint8_t));
|
||||
if (enc_out == NULL) {
|
||||
fprintf(stderr, "allocation error\n");
|
||||
exit_code = 0;
|
||||
goto cleanup0;
|
||||
}
|
||||
|
||||
enc_ret_code = vtenc_set_encode_u32(values, values_len, enc_out, enc_out_cap, &enc_out_len);
|
||||
if (enc_ret_code != VtencErrorNoError) {
|
||||
fprintf(stderr, "encode error code: %d\n", enc_ret_code);
|
||||
exit_code = 0;
|
||||
goto cleanup1;
|
||||
}
|
||||
|
||||
dec_out_len = vtenc_set_decoded_size_u32(enc_out, enc_out_len);
|
||||
dec_out = (uint32_t *) malloc(dec_out_len * sizeof(uint32_t));
|
||||
if (dec_out == NULL) {
|
||||
fprintf(stderr, "allocation error\n");
|
||||
exit_code = 0;
|
||||
goto cleanup1;
|
||||
}
|
||||
|
||||
dec_ret_code = vtenc_set_decode_u32(enc_out, enc_out_len, dec_out, dec_out_len);
|
||||
if (dec_ret_code != VtencErrorNoError) {
|
||||
fprintf(stderr, "decode error code: %d\n", dec_ret_code);
|
||||
exit_code = 0;
|
||||
goto cleanup2;
|
||||
}
|
||||
|
||||
if (memcmp(values, dec_out, values_len) != 0) {
|
||||
fprintf(stderr, "decoded output different from original input\n");
|
||||
exit_code = 0;
|
||||
goto cleanup2;
|
||||
}
|
||||
|
||||
stats->n_sets++;
|
||||
stats->total_input_size += values_len * sizeof(uint32_t);
|
||||
stats->total_encoded_size += enc_out_len;
|
||||
|
||||
cleanup2:
|
||||
free(dec_out);
|
||||
|
||||
cleanup1:
|
||||
free(enc_out);
|
||||
|
||||
cleanup0:
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
size_t do_test(const char *filename)
|
||||
{
|
||||
uint32_t *values=NULL, values_len=0;
|
||||
size_t exit_code=0;
|
||||
struct Stats stats;
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
|
||||
stats_init(&stats);
|
||||
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "failed opening '%s' file\n", filename);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while ((exit_code == 0) && read_u32_from_file(fp, &values_len)) {
|
||||
values = (uint32_t *) malloc(values_len * sizeof(uint32_t));
|
||||
if (values == NULL) {
|
||||
fprintf(stderr, "allocation error\n");
|
||||
exit_code = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!read_values_from_file(fp, values, values_len)) {
|
||||
fprintf(stderr, "failed reading values from file\n");
|
||||
exit_code = EXIT_FAILURE;
|
||||
goto cleanup_values;
|
||||
}
|
||||
|
||||
if (!has_strictly_ascending_order(values, values_len)) {
|
||||
fprintf(stderr, "wrong set order\n");
|
||||
exit_code = EXIT_FAILURE;
|
||||
goto cleanup_values;
|
||||
}
|
||||
|
||||
if (!encode_and_decode_set(values, values_len, &stats)) {
|
||||
exit_code = EXIT_FAILURE;
|
||||
goto cleanup_values;
|
||||
}
|
||||
|
||||
cleanup_values:
|
||||
free(values);
|
||||
}
|
||||
|
||||
stats_print(&stats);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
void usage(const char *program)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s <file>\n"
|
||||
"\n"
|
||||
" <file> is a binary file containing a list of sets. Each set starts with a\n"
|
||||
" 32-bit unsigned integer indicating its length followed by a sequence of\n"
|
||||
" 32-bit unsigned integers that make up the set. The values of each set\n"
|
||||
" are sorted in ascending order.\n"
|
||||
" This program was originally created to test a specific data set:\n"
|
||||
" 'gov2.sorted'. You can download it from the following URL:\n"
|
||||
" https://lemire.me/data/integercompression2014.html\n",
|
||||
program);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
usage(argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return do_test(argv[1]);
|
||||
}
|
||||
175
ext/vtenc/tests/timestamps.c
Normal file
175
ext/vtenc/tests/timestamps.c
Normal file
@ -0,0 +1,175 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../vtenc.h"
|
||||
|
||||
struct array_t {
|
||||
uint32_t *values;
|
||||
size_t size;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
void array_init(struct array_t *arr, size_t capacity)
|
||||
{
|
||||
arr->values = (uint32_t *) malloc(capacity * sizeof(uint32_t));
|
||||
if (arr->values == NULL) {
|
||||
fprintf(stderr, "array_init: allocation error\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
arr->size = 0;
|
||||
arr->capacity = capacity;
|
||||
}
|
||||
|
||||
void array_push(struct array_t *arr, uint32_t value)
|
||||
{
|
||||
arr->values[arr->size++] = value;
|
||||
|
||||
if (arr->size >= arr->capacity) {
|
||||
arr->capacity *= 2;
|
||||
arr->values = (uint32_t *) realloc(arr->values, arr->capacity * sizeof(uint32_t));
|
||||
if (arr->values == NULL) {
|
||||
fprintf(stderr, "array_push: re-allocation error\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void array_free(struct array_t *arr)
|
||||
{
|
||||
free(arr->values);
|
||||
arr->size = 0;
|
||||
arr->capacity = 0;
|
||||
}
|
||||
|
||||
void array_load_from_txt_file(const char *filename, struct array_t *arr)
|
||||
{
|
||||
char buf[20], *end;
|
||||
uint32_t v;
|
||||
FILE *f = fopen(filename, "r");
|
||||
|
||||
if (f == NULL) {
|
||||
fprintf(stderr, "array_load_from_txt_file: failed opening '%s' file\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while (fgets(buf, sizeof(buf), f) != NULL) {
|
||||
v = strtoul(buf, &end, 10);
|
||||
array_push(arr, v);
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
int has_ascending_order(uint32_t *values, size_t values_len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 1; i < values_len; ++i) {
|
||||
if (values[i] < values[i - 1]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void usage(const char *program)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s <file>\n"
|
||||
"\n"
|
||||
" <file> can be any text file containing a sorted list of 32-bit unsigned\n"
|
||||
" integers, one per line.\n"
|
||||
" This program was originally created to test a specific data set: 'ts.txt'.\n"
|
||||
" You can download it from the following URL:\n"
|
||||
" https://github.com/zentures/encoding/tree/master/benchmark/data\n",
|
||||
program);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct array_t arr;
|
||||
size_t exit_code=0, enc_out_cap, enc_out_len, dec_out_len;
|
||||
uint8_t *enc_out;
|
||||
uint32_t *dec_out;
|
||||
VtencErrorCode enc_ret_code, dec_ret_code;
|
||||
double ratio;
|
||||
|
||||
if (argc != 2) {
|
||||
usage(argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
array_init(&arr, 10000);
|
||||
|
||||
array_load_from_txt_file(argv[1], &arr);
|
||||
|
||||
if (!has_ascending_order(arr.values, arr.size)) {
|
||||
fprintf(stderr, "wrong list order\n");
|
||||
exit_code = EXIT_FAILURE;
|
||||
goto error0;
|
||||
}
|
||||
|
||||
enc_out_cap = vtenc_list_max_encoded_size_u32(arr.size);
|
||||
enc_out = (uint8_t *) malloc(enc_out_cap * sizeof(uint8_t));
|
||||
if (enc_out == NULL) {
|
||||
fprintf(stderr, "allocation error\n");
|
||||
exit_code = EXIT_FAILURE;
|
||||
goto error0;
|
||||
}
|
||||
|
||||
enc_ret_code = vtenc_list_encode_u32(arr.values, arr.size, enc_out, enc_out_cap, &enc_out_len);
|
||||
if (enc_ret_code != VtencErrorNoError) {
|
||||
fprintf(stderr, "encode error code: %d\n", enc_ret_code);
|
||||
exit_code = EXIT_FAILURE;
|
||||
goto error1;
|
||||
}
|
||||
|
||||
dec_out_len = vtenc_list_decoded_size_u32(enc_out, enc_out_len);
|
||||
dec_out = (uint32_t *) malloc(dec_out_len * sizeof(uint32_t));
|
||||
if (dec_out == NULL) {
|
||||
fprintf(stderr, "allocation error\n");
|
||||
exit_code = EXIT_FAILURE;
|
||||
goto error1;
|
||||
}
|
||||
|
||||
dec_ret_code = vtenc_list_decode_u32(enc_out, enc_out_len, dec_out, dec_out_len);
|
||||
if (dec_ret_code != VtencErrorNoError) {
|
||||
fprintf(stderr, "decode error code: %d\n", dec_ret_code);
|
||||
exit_code = EXIT_FAILURE;
|
||||
goto error2;
|
||||
}
|
||||
|
||||
if (memcmp(arr.values, dec_out, arr.size) != 0) {
|
||||
fprintf(stderr, "decoded output different from original input\n");
|
||||
exit_code = EXIT_FAILURE;
|
||||
goto error2;
|
||||
}
|
||||
|
||||
ratio = enc_out_len / (double)(arr.size * sizeof(uint32_t));
|
||||
|
||||
printf("input size: %lu (%lu bytes)\n", arr.size, arr.size * sizeof(uint32_t));
|
||||
printf("encoded size: %lu bytes\n", enc_out_len);
|
||||
printf("decoded size: %lu (%lu bytes)\n", dec_out_len, dec_out_len * sizeof(uint32_t));
|
||||
printf("compression ratio: %f (%.4f%%)\n", ratio, ratio * 100.0);
|
||||
|
||||
error2:
|
||||
free(dec_out);
|
||||
|
||||
error1:
|
||||
free(enc_out);
|
||||
|
||||
error0:
|
||||
array_free(&arr);
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
27
ext/vtenc/tests/unit/Makefile
Normal file
27
ext/vtenc/tests/unit/Makefile
Normal file
@ -0,0 +1,27 @@
|
||||
# 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.
|
||||
|
||||
VTENCDIR = ../..
|
||||
|
||||
CC = gcc
|
||||
CFLAGS ?= -Wall -O3
|
||||
|
||||
SRC = $(wildcard *.c)
|
||||
OBJ = $(SRC:.c=.o)
|
||||
|
||||
.PHONY: default
|
||||
default: all
|
||||
|
||||
.PHONY: all
|
||||
all: unit_tests
|
||||
|
||||
%.o: %.c
|
||||
${CC} -c $(CFLAGS) $<
|
||||
|
||||
unit_tests: $(OBJ)
|
||||
$(CC) $(CFLAGS) $^ $(VTENCDIR)/libvtenc.a -o $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f *.o unit_tests
|
||||
114
ext/vtenc/tests/unit/bits_test.c
Normal file
114
ext/vtenc/tests/unit/bits_test.c
Normal file
@ -0,0 +1,114 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include "unit_tests.h"
|
||||
#include "../../bits.h"
|
||||
|
||||
int test_bits_swap_u16(void)
|
||||
{
|
||||
EXPECT_TRUE(bits_swap_u16(0) == 0);
|
||||
EXPECT_TRUE(bits_swap_u16(0xaabb) == 0xbbaa);
|
||||
EXPECT_TRUE(bits_swap_u16(0xffff) == 0xffff);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bits_swap_u32(void)
|
||||
{
|
||||
EXPECT_TRUE(bits_swap_u32(0) == 0);
|
||||
EXPECT_TRUE(bits_swap_u32(0xaaaabbbb) == 0xbbbbaaaa);
|
||||
EXPECT_TRUE(bits_swap_u32(0xffffffff) == 0xffffffff);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bits_swap_u64(void)
|
||||
{
|
||||
EXPECT_TRUE(bits_swap_u64(0) == 0);
|
||||
EXPECT_TRUE(bits_swap_u64(0xaaaaaaaabbbbbbbbULL) == 0xbbbbbbbbaaaaaaaaULL);
|
||||
EXPECT_TRUE(bits_swap_u64(0xffffffffffffffffULL) == 0xffffffffffffffffULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bits_len_u8(void)
|
||||
{
|
||||
EXPECT_TRUE(bits_len_u8(0) == 1);
|
||||
EXPECT_TRUE(bits_len_u8(1) == 1);
|
||||
EXPECT_TRUE(bits_len_u8(3) == 2);
|
||||
EXPECT_TRUE(bits_len_u8(7) == 3);
|
||||
EXPECT_TRUE(bits_len_u8(11) == 4);
|
||||
EXPECT_TRUE(bits_len_u8(25) == 5);
|
||||
EXPECT_TRUE(bits_len_u8(50) == 6);
|
||||
EXPECT_TRUE(bits_len_u8(100) == 7);
|
||||
EXPECT_TRUE(bits_len_u8(200) == 8);
|
||||
EXPECT_TRUE(bits_len_u8(255) == 8);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bits_len_u16(void)
|
||||
{
|
||||
EXPECT_TRUE(bits_len_u16(0) == 1);
|
||||
EXPECT_TRUE(bits_len_u16(1) == 1);
|
||||
EXPECT_TRUE(bits_len_u16(3) == 2);
|
||||
EXPECT_TRUE(bits_len_u16(7) == 3);
|
||||
EXPECT_TRUE(bits_len_u16(11) == 4);
|
||||
EXPECT_TRUE(bits_len_u16(25) == 5);
|
||||
EXPECT_TRUE(bits_len_u16(50) == 6);
|
||||
EXPECT_TRUE(bits_len_u16(100) == 7);
|
||||
EXPECT_TRUE(bits_len_u16(200) == 8);
|
||||
EXPECT_TRUE(bits_len_u16(255) == 8);
|
||||
EXPECT_TRUE(bits_len_u16(256) == 9);
|
||||
EXPECT_TRUE(bits_len_u16(2000) == 11);
|
||||
EXPECT_TRUE(bits_len_u16(50000) == 16);
|
||||
EXPECT_TRUE(bits_len_u16(65535) == 16);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bits_len_u32(void)
|
||||
{
|
||||
EXPECT_TRUE(bits_len_u32(0) == 1);
|
||||
EXPECT_TRUE(bits_len_u32(1) == 1);
|
||||
EXPECT_TRUE(bits_len_u32(50) == 6);
|
||||
EXPECT_TRUE(bits_len_u32(100) == 7);
|
||||
EXPECT_TRUE(bits_len_u32(255) == 8);
|
||||
EXPECT_TRUE(bits_len_u32(256) == 9);
|
||||
EXPECT_TRUE(bits_len_u32(10000) == 14);
|
||||
EXPECT_TRUE(bits_len_u32(65535) == 16);
|
||||
EXPECT_TRUE(bits_len_u32(65536) == 17);
|
||||
EXPECT_TRUE(bits_len_u32(1000000) == 20);
|
||||
EXPECT_TRUE(bits_len_u32(16777215) == 24);
|
||||
EXPECT_TRUE(bits_len_u32(16777216) == 25);
|
||||
EXPECT_TRUE(bits_len_u32(1000000000) == 30);
|
||||
EXPECT_TRUE(bits_len_u32(4294967295) == 32);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bits_len_u64(void)
|
||||
{
|
||||
EXPECT_TRUE(bits_len_u64(0) == 1);
|
||||
EXPECT_TRUE(bits_len_u64(1) == 1);
|
||||
EXPECT_TRUE(bits_len_u64(50) == 6);
|
||||
EXPECT_TRUE(bits_len_u64(100) == 7);
|
||||
EXPECT_TRUE(bits_len_u64(255) == 8);
|
||||
EXPECT_TRUE(bits_len_u64(256) == 9);
|
||||
EXPECT_TRUE(bits_len_u64(10000) == 14);
|
||||
EXPECT_TRUE(bits_len_u64(65535) == 16);
|
||||
EXPECT_TRUE(bits_len_u64(65536) == 17);
|
||||
EXPECT_TRUE(bits_len_u64(1000000) == 20);
|
||||
EXPECT_TRUE(bits_len_u64(16777215) == 24);
|
||||
EXPECT_TRUE(bits_len_u64(16777216) == 25);
|
||||
EXPECT_TRUE(bits_len_u64(1000000000) == 30);
|
||||
EXPECT_TRUE(bits_len_u64(4294967295) == 32);
|
||||
EXPECT_TRUE(bits_len_u64(0x000000ffffffffffULL) == 40);
|
||||
EXPECT_TRUE(bits_len_u64(0x0000ffffffffffffULL) == 48);
|
||||
EXPECT_TRUE(bits_len_u64(0x00ffffffffffffffULL) == 56);
|
||||
EXPECT_TRUE(bits_len_u64(0xffffffffffffffffULL) == 64);
|
||||
|
||||
return 1;
|
||||
}
|
||||
304
ext/vtenc/tests/unit/bitstream_test.c
Normal file
304
ext/vtenc/tests/unit/bitstream_test.c
Normal file
@ -0,0 +1,304 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "unit_tests.h"
|
||||
#include "../../bitstream.h"
|
||||
|
||||
int test_bswriter_align_buffer_size(void)
|
||||
{
|
||||
EXPECT_TRUE(bswriter_align_buffer_size(0) == 8);
|
||||
EXPECT_TRUE(bswriter_align_buffer_size(1) == 8);
|
||||
EXPECT_TRUE(bswriter_align_buffer_size(7) == 8);
|
||||
EXPECT_TRUE(bswriter_align_buffer_size(8) == 8);
|
||||
EXPECT_TRUE(bswriter_align_buffer_size(9) == 16);
|
||||
EXPECT_TRUE(bswriter_align_buffer_size(13) == 16);
|
||||
EXPECT_TRUE(bswriter_align_buffer_size(16) == 16);
|
||||
EXPECT_TRUE(bswriter_align_buffer_size(33) == 40);
|
||||
EXPECT_TRUE(bswriter_align_buffer_size(48) == 48);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bswriter_init_1(void)
|
||||
{
|
||||
BSWriter writer;
|
||||
const size_t buf_cap = 4;
|
||||
uint8_t buf[buf_cap];
|
||||
|
||||
EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorBufferTooSmall);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bswriter_init_2(void)
|
||||
{
|
||||
BSWriter writer;
|
||||
const size_t buf_cap = 8;
|
||||
uint8_t buf[buf_cap];
|
||||
|
||||
EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bswriter_write_1(void)
|
||||
{
|
||||
BSWriter writer;
|
||||
const size_t buf_cap = 16;
|
||||
uint8_t buf[buf_cap];
|
||||
|
||||
memset(buf, 0, buf_cap);
|
||||
|
||||
EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError);
|
||||
|
||||
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);
|
||||
|
||||
bswriter_close(&writer);
|
||||
|
||||
EXPECT_TRUE(memcmp(buf, "\xff\xff\x22\x00\x99\x99\x99\x99\x44\xaa\x00\x00\x00\x00\x00\x00", buf_cap) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bswriter_write_2(void)
|
||||
{
|
||||
BSWriter writer;
|
||||
const size_t buf_cap = 8;
|
||||
uint8_t buf[buf_cap];
|
||||
|
||||
memset(buf, 0, buf_cap);
|
||||
|
||||
EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError);
|
||||
|
||||
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);
|
||||
|
||||
bswriter_close(&writer);
|
||||
|
||||
EXPECT_TRUE(memcmp(buf, "\xff\xff\xff\xff\xff\xff\xff\x7f", buf_cap) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bswriter_write_3(void)
|
||||
{
|
||||
BSWriter writer;
|
||||
const size_t buf_cap = 24;
|
||||
uint8_t buf[buf_cap];
|
||||
|
||||
memset(buf, 0, buf_cap);
|
||||
|
||||
EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError);
|
||||
|
||||
EXPECT_TRUE(bswriter_write(&writer, 0x1ffffffffffffff, 57) == VtencErrorNoError);
|
||||
EXPECT_TRUE(bswriter_write(&writer, 0x1ffffffffffffff, 57) == VtencErrorNoError);
|
||||
EXPECT_TRUE(bswriter_write(&writer, 0x1ffffffffffffff, 57) == VtencErrorNoError);
|
||||
|
||||
bswriter_close(&writer);
|
||||
|
||||
EXPECT_TRUE(memcmp(buf,
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\xff\xff\xff\xff\xff\x07\x00\x00", buf_cap) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bswriter_close_1(void)
|
||||
{
|
||||
BSWriter writer;
|
||||
const size_t buf_cap = 8;
|
||||
uint8_t buf[buf_cap];
|
||||
|
||||
EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError);
|
||||
EXPECT_TRUE(bswriter_close(&writer) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bswriter_close_2(void)
|
||||
{
|
||||
BSWriter writer;
|
||||
const size_t buf_cap = 8;
|
||||
uint8_t buf[buf_cap];
|
||||
|
||||
EXPECT_TRUE(bswriter_init(&writer, buf, buf_cap) == VtencErrorNoError);
|
||||
|
||||
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_close(&writer) == 3);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bsreader_init_1(void)
|
||||
{
|
||||
BSReader reader;
|
||||
const size_t buf_len = 0;
|
||||
const uint8_t *buf = (const uint8_t *)"";
|
||||
|
||||
EXPECT_TRUE(bsreader_init(&reader, buf, buf_len) == VtencErrorBufferTooSmall);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bsreader_init_2(void)
|
||||
{
|
||||
BSReader reader;
|
||||
const size_t buf_len = 1;
|
||||
const uint8_t *buf = (const uint8_t *)"\xff";
|
||||
|
||||
EXPECT_TRUE(bsreader_init(&reader, buf, buf_len) == VtencErrorNoError);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bsreader_read_1(void)
|
||||
{
|
||||
BSReader reader;
|
||||
const size_t buf_len = 1;
|
||||
const uint8_t *buf = (const uint8_t *)"\xff";
|
||||
uint64_t val=0;
|
||||
|
||||
bsreader_init(&reader, buf, buf_len);
|
||||
|
||||
EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VtencErrorNoError && val == 0xff);
|
||||
EXPECT_TRUE(bsreader_read(&reader, 8, &val) == VtencErrorEndOfStream);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bsreader_read_2(void)
|
||||
{
|
||||
BSReader reader;
|
||||
const size_t buf_len = 2;
|
||||
const uint8_t *buf = (const uint8_t *)"\xff\x66";
|
||||
uint64_t val=0;
|
||||
|
||||
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);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bsreader_read_3(void)
|
||||
{
|
||||
BSReader reader;
|
||||
const size_t buf_len = 1;
|
||||
const uint8_t *buf = (const uint8_t *)"\xba";
|
||||
uint64_t val=0;
|
||||
|
||||
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);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bsreader_read_4(void)
|
||||
{
|
||||
BSReader reader;
|
||||
const size_t buf_len = 18;
|
||||
const uint8_t *buf = (const uint8_t *)"\x11\x11\x11\x11\x11\x11\x22\x22\x22\x22\x22\x22\x33\x33\x33\x33\x33\x33";
|
||||
uint64_t val=0;
|
||||
|
||||
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);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bsreader_read_5(void)
|
||||
{
|
||||
BSReader reader;
|
||||
const size_t buf_len = 12;
|
||||
const uint8_t *buf = (const uint8_t *)"\xff\xab\x11\xcd\x55\x55\x55\x55\x66\x66\x66\x66";
|
||||
uint64_t val=0;
|
||||
|
||||
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);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bsreader_read_6(void)
|
||||
{
|
||||
BSReader reader;
|
||||
const size_t buf_len = 15;
|
||||
const uint8_t *buf = (const uint8_t *)"\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55";
|
||||
uint64_t val=0;
|
||||
|
||||
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);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_bsreader_size(void)
|
||||
{
|
||||
BSReader reader;
|
||||
const size_t buf_len = 12;
|
||||
const uint8_t *buf = (const uint8_t *)"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
|
||||
uint64_t val=0;
|
||||
|
||||
bsreader_init(&reader, buf, buf_len);
|
||||
|
||||
EXPECT_TRUE(bsreader_size(&reader) == 0);
|
||||
bsreader_read(&reader, 1, &val); EXPECT_TRUE(bsreader_size(&reader) == 1);
|
||||
bsreader_read(&reader, 5, &val); EXPECT_TRUE(bsreader_size(&reader) == 1);
|
||||
bsreader_read(&reader, 5, &val); EXPECT_TRUE(bsreader_size(&reader) == 2);
|
||||
bsreader_read(&reader, 5, &val); EXPECT_TRUE(bsreader_size(&reader) == 2);
|
||||
bsreader_read(&reader, 1, &val); EXPECT_TRUE(bsreader_size(&reader) == 3);
|
||||
bsreader_read(&reader, 20, &val); EXPECT_TRUE(bsreader_size(&reader) == 5);
|
||||
bsreader_read(&reader, 40, &val); EXPECT_TRUE(bsreader_size(&reader) == 10);
|
||||
bsreader_read(&reader, 16, &val); EXPECT_TRUE(bsreader_size(&reader) == 12);
|
||||
|
||||
return 1;
|
||||
}
|
||||
674
ext/vtenc/tests/unit/decode_test.c
Normal file
674
ext/vtenc/tests/unit/decode_test.c
Normal file
@ -0,0 +1,674 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "unit_tests.h"
|
||||
#include "../../vtenc.h"
|
||||
|
||||
int test_vtenc_list_decode_u8_1(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\xff\xff\xff\xff\xff\xff\xff\xff";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = 1;
|
||||
uint8_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u8(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u8_2(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x09\x00\x00\x00\x00\x00\x00\x00";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = 4;
|
||||
uint8_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u8(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u8_3(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x04\x00\x00\x00\x00\x00\x00\x0e";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = vtenc_list_decoded_size_u8(in, in_len);
|
||||
uint8_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u8(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u8_4(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x0b\x00\x00\x00\x00\x00\x00\xb0\x56\x09\xc5\xd8\x8a\x2e\x56\x2b\x01";
|
||||
const size_t in_len = 17;
|
||||
size_t out_len = vtenc_list_decoded_size_u8(in, in_len);
|
||||
uint8_t out[out_len];
|
||||
uint8_t expected[] = {5, 22, 23, 44, 62, 69, 109, 113, 178, 194, 206};
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u8(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 11);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u8_5(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x09\x00\x00\x00\x00\x00\x00\x6e\xc0\x03\x02\x00\xa2\x0a";
|
||||
const size_t in_len = 14;
|
||||
size_t out_len = vtenc_list_decoded_size_u8(in, in_len);
|
||||
uint8_t out[out_len];
|
||||
uint8_t expected[] = {57, 57, 57, 111, 111, 111, 111, 208, 208};
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u8(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 9);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u16_1(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\xff\xff\xff\xff\xff\xff\xff\xff";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = 1;
|
||||
uint16_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u16(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u16_2(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x09\x00\x00\x00\x00\x00\x00\x00";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = 4;
|
||||
uint16_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u16(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u16_3(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x04\x00\x00\x00\x00\x00\x00\x0e";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = vtenc_list_decoded_size_u16(in, in_len);
|
||||
uint16_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u16(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u16_4(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x07\x00\x00\x00\x00\x00\x00\xba\xcd\x2d\x97\x01\x4d\xe2\xcf\x6b\x6b\x95\x78\x74\x00";
|
||||
const size_t in_len = 21;
|
||||
size_t out_len = vtenc_list_decoded_size_u16(in, in_len);
|
||||
uint16_t out[out_len];
|
||||
uint16_t expected[] = {1099, 2227, 8102, 27654, 29001, 35511, 50083};
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u16(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 7);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u16_5(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x08\x00\x00\x00\x00\x00\x00\x10\xe7\x67\xe6\x99\xb6\x28\x0a\xb4\x05";
|
||||
const size_t in_len = 17;
|
||||
size_t out_len = vtenc_list_decoded_size_u16(in, in_len);
|
||||
uint16_t out[out_len];
|
||||
uint16_t expected[] = {677, 677, 677, 8881, 8881, 8881, 8881, 8881};
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u16(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 8);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u32_1(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\xff\xff\xff\xff\xff\xff\xff\xff";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = 1;
|
||||
uint32_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u32(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u32_2(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x09\x00\x00\x00\x00\x00\x00\x00";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = 4;
|
||||
uint32_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u32(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u32_3(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x04\x00\x00\x00\x00\x00\x00\x0e";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = vtenc_list_decoded_size_u32(in, in_len);
|
||||
uint32_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u32(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u32_4(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x05\x00\x00\x00\x00\x00\x00\x4a\x6e\xb5"
|
||||
"\xff\x35\xb6\x43\x74\xaa\x3e\xda\xf3\xdf\xe8\x7b\x2a\xdd\x60\x7d\x01";
|
||||
const size_t in_len = 27;
|
||||
size_t out_len = vtenc_list_decoded_size_u32(in, in_len);
|
||||
uint32_t out[out_len];
|
||||
uint32_t expected[] = {5348, 13089333, 88199704, 271008013, 1451881090};
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u32(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 5);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u32_5(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x06\x00\x00\x00\x00\x00\x00\x6c\x93\x20"
|
||||
"\x41\x90\x20\x49\x90\x04\x40\x10\x20\x14\x41\x05\x15\x51\x15\x04\x01";
|
||||
const size_t in_len = 27;
|
||||
size_t out_len = vtenc_list_decoded_size_u32(in, in_len);
|
||||
uint32_t out[out_len];
|
||||
uint32_t expected[] = {77865901, 77865901, 77865901, 77865901, 314976310, 314976310};
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u32(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 6);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u64_1(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\xff\xff\xff\xff\xff\xff\xff\xff";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = 1;
|
||||
uint64_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u64(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u64_2(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x09\x00\x00\x00\x00\x00\x00\x00";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = 4;
|
||||
uint64_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u64(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u64_3(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x04\x00\x00\x00\x00\x00\x00\x0e";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = vtenc_list_decoded_size_u64(in, in_len);
|
||||
uint64_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u64(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u64_4(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x04\x00\x00\x00\x00\x00\x00\x48\x92\x24"
|
||||
"\x49\x92\x24\xc9\xfd\xff\xff\xaf\xaa\xda\xff\x56\xf3\x4a\x04\x0f\xd0\x93\x16"
|
||||
"\x79\x5b\x8e\x38\xa6\xaa";
|
||||
const size_t in_len = 35;
|
||||
size_t out_len = vtenc_list_decoded_size_u64(in, in_len);
|
||||
uint64_t out[out_len];
|
||||
uint64_t expected[] = {0x12a6, 0x8addf0, 0xffa1b4bb, 0x21258ee39aaa};
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u64(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 4);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decode_u64_5(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x05\x00\x00\x00\x00\x00\x00\xda\xb6\x6d"
|
||||
"\xdb\xb6\x6d\xdb\xee\xff\xff\x7f\x66\x66\x66\x66\x66\x66\x66\x46\x45\x45\x45"
|
||||
"\x45\x45\x45\x45\x45\x45\x45\x05";
|
||||
const size_t in_len = 37;
|
||||
size_t out_len = vtenc_list_decoded_size_u64(in, in_len);
|
||||
uint64_t out[out_len];
|
||||
uint64_t expected[] = {0x55555555, 0x55555555, 0x55555555, 0x111111111111, 0x111111111111};
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decode_u64(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 5);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u8_1(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x00";
|
||||
const size_t in_len = 1;
|
||||
size_t out_len = 0;
|
||||
uint8_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u8(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u8_2(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x03\xff";
|
||||
const size_t in_len = 2;
|
||||
size_t out_len = vtenc_set_decoded_size_u8(in, in_len);
|
||||
uint8_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u8(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u8_3(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\xff";
|
||||
const size_t in_len = 1;
|
||||
size_t out_len = vtenc_set_decoded_size_u8(in, in_len);
|
||||
uint8_t out[out_len];
|
||||
size_t expected_len = 256;
|
||||
uint8_t expected[expected_len];
|
||||
size_t i;
|
||||
|
||||
for (i=0; i<expected_len; ++i) expected[i] = (uint8_t)i;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u8(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == expected_len);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u8_4(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x0b\x88\x88\x48\x90\x04";
|
||||
const size_t in_len = 6;
|
||||
size_t out_len = vtenc_set_decoded_size_u8(in, in_len);
|
||||
uint8_t out[out_len];
|
||||
uint8_t expected[] = {0, 1, 2, 3, 4, 5, 6, 7, 160, 161, 162, 163};
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u8(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 12);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u8_5(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x05\xcc\x74\x44\x57\x55\x03";
|
||||
const size_t in_len = 7;
|
||||
size_t out_len = vtenc_set_decoded_size_u8(in, in_len);
|
||||
uint8_t out[out_len];
|
||||
uint8_t expected[] = {13, 77, 88, 93, 149, 212};
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u8(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 6);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u16_1(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x00\x00";
|
||||
const size_t in_len = 2;
|
||||
size_t out_len = 0;
|
||||
uint16_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u16(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u16_2(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x03\x00\xff";
|
||||
const size_t in_len = 3;
|
||||
size_t out_len = vtenc_set_decoded_size_u16(in, in_len);
|
||||
uint16_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u16(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u16_3(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x07\x00\xc6\x19\x23\x34\xf0\x0f\xb7\x17\x5a\x23\xd8\xfb\xf1\x5c\x51";
|
||||
const size_t in_len = 17;
|
||||
size_t out_len = vtenc_set_decoded_size_u16(in, in_len);
|
||||
uint16_t out[out_len];
|
||||
uint16_t expected[] = {1655, 3391, 4111, 8770, 29006, 32712, 32993, 58042};
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u16(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 8);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u16_4(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x0b\x00\x8c\x00\x08\x80\x80\x00\x48\x02\x20\x09\x92";
|
||||
const size_t in_len = 13;
|
||||
size_t out_len = vtenc_set_decoded_size_u16(in, in_len);
|
||||
uint16_t out[out_len];
|
||||
uint16_t expected[] = {
|
||||
14000, 14001, 14002, 14003, 14004, 14005, 14006, 14007,
|
||||
20000, 20001, 20002, 20003
|
||||
};
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u16(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 12);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u32_1(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x00\x00\x00\x00";
|
||||
const size_t in_len = 4;
|
||||
size_t out_len = 0;
|
||||
uint32_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u32(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u32_2(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x03\x00\x00\x00\xff";
|
||||
const size_t in_len = 5;
|
||||
size_t out_len = vtenc_set_decoded_size_u32(in, in_len);
|
||||
uint32_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u32(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u32_3(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x04\x00\x00\x00\x9c\xbd\xb9\xec\xf7\x2e"
|
||||
"\xa8\x48\x0b\x47\x46\x78\x82\x59\xc5\xa1\xfd\xf9\x26\x02";
|
||||
const size_t in_len = 24;
|
||||
size_t out_len = vtenc_set_decoded_size_u32(in, in_len);
|
||||
uint32_t out[out_len];
|
||||
uint32_t expected[] = {0x98b204, 0x122fabb4, 0x378ecef0, 0x77ccab8f, 0xa40609bb};
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u32(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 5);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u32_4(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)
|
||||
"\x0d\x00\x00\x00\xee\xee\xee\xee\x46\x92\x24\x41\x90\x20\x48\x92"
|
||||
"\x54\x04\x04\x04\x55\x15\x00\x00\x00\x00\x00\x00\x00\x10\x11\x11";
|
||||
const size_t in_len = 32;
|
||||
size_t out_len = vtenc_set_decoded_size_u32(in, in_len);
|
||||
uint32_t out[out_len];
|
||||
uint32_t expected[] = {
|
||||
0xa500, 0xa501, 0xa502, 0xa503,
|
||||
0x4bbb00, 0x4bbb01,
|
||||
0xffff00, 0xffff01, 0xffff02, 0xffff03, 0xffff04, 0xffff05, 0xffff06, 0xffff07
|
||||
};
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u32(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 14);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u64_1(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\xff\xff\xff\xff\xff\xff\xff\xff";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = 0;
|
||||
uint64_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u64(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u64_2(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = 0;
|
||||
uint64_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u64(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u64_3(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x03\x00\x00\x00\x00\x00\x00\xfe";
|
||||
const size_t in_len = 8;
|
||||
size_t out_len = vtenc_set_decoded_size_u64(in, in_len);
|
||||
uint64_t out[out_len];
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u64(in, in_len, out, out_len) == VtencErrorWrongFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u64_4(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)
|
||||
"\x06\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xdb\xb6\x6d"
|
||||
"\xb9\x55\x6d\xb7\x3b\xd3\x5d\x15\x61\x26\xfa\xfb\xfb\xfb\xfb\xaa"
|
||||
"\xaa\xaa\xaa\x0a\x0f\x0f\x0f\x0f\x5f\xe6\x1e\x91\x59\xd5\x0d\x20"
|
||||
"\x02\x20\x02\x20\x02";
|
||||
const size_t in_len = 53;
|
||||
size_t out_len = vtenc_set_decoded_size_u64(in, in_len);
|
||||
uint64_t out[out_len];
|
||||
uint64_t expected[] = {
|
||||
0x11223344ULL, 0xaabbccddULL, 0x1010101010ULL, 0x5555555555ULL, 0xf0f0f0f0f0ULL,
|
||||
0x998877665544ULL, 0xffeeffeeffeeULL
|
||||
};
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u64(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 7);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decode_u64_5(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)
|
||||
"\x07\x00\x00\x00\x00\x00\x00\x10\x11\x11\x11\x11\x11\x11\x11\x11"
|
||||
"\x11\x11\x11\x11\xcd\xb6\x4d\x82\x24\x49\x92\x24\x49\x92\x24\x49"
|
||||
"\x92\xa4\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
|
||||
"\xaa\xaa\x02";
|
||||
const size_t in_len = 51;
|
||||
size_t out_len = vtenc_set_decoded_size_u64(in, in_len);
|
||||
uint64_t out[out_len];
|
||||
uint64_t expected[] = {
|
||||
0x20000000ULL, 0x20000001ULL, 0x20000002ULL, 0x20000003ULL,
|
||||
0x80000000ULL, 0x80000001ULL,
|
||||
0x2000000000ULL, 0x2000000001ULL
|
||||
};
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decode_u64(in, in_len, out, out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 8);
|
||||
EXPECT_TRUE(memcmp(out, expected, sizeof(out)) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decoded_size_1(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"";
|
||||
const size_t in_len = 0;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u8(in, in_len) == 0);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u16(in, in_len) == 0);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u32(in, in_len) == 0);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u64(in, in_len) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decoded_size_2(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\xff\xff";
|
||||
const size_t in_len = 1;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u8(in, in_len) == 0);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u16(in, in_len) == 0);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u32(in, in_len) == 0);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u64(in, in_len) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decoded_size_3(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\x07\x00\x00\x00\x00\x00\x00\x00";
|
||||
const size_t in_len = 8;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u8(in, in_len) == 7);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u16(in, in_len) == 7);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u32(in, in_len) == 7);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u64(in, in_len) == 7);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_decoded_size_4(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"\xff\xff\x0f\x00\x00\x00\x00\x00";
|
||||
const size_t in_len = 8;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u8(in, in_len) == 1048575);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u16(in, in_len) == 1048575);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u32(in, in_len) == 1048575);
|
||||
EXPECT_TRUE(vtenc_list_decoded_size_u64(in, in_len) == 1048575);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decoded_size_with_wrong_input(void)
|
||||
{
|
||||
const uint8_t *in = (const uint8_t *)"";
|
||||
const size_t in_len = 0;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_decoded_size_u8(in, in_len) == 0);
|
||||
EXPECT_TRUE(vtenc_set_decoded_size_u16(in, in_len) == 0);
|
||||
EXPECT_TRUE(vtenc_set_decoded_size_u32(in, in_len) == 0);
|
||||
EXPECT_TRUE(vtenc_set_decoded_size_u64(in, in_len) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decoded_size_u8(void)
|
||||
{
|
||||
const uint8_t *in;
|
||||
const size_t in_len = 1;
|
||||
|
||||
in = (const uint8_t *)"\x00"; EXPECT_TRUE(vtenc_set_decoded_size_u8(in, in_len) == 1);
|
||||
in = (const uint8_t *)"\x05"; EXPECT_TRUE(vtenc_set_decoded_size_u8(in, in_len) == 6);
|
||||
in = (const uint8_t *)"\x34"; EXPECT_TRUE(vtenc_set_decoded_size_u8(in, in_len) == 53);
|
||||
in = (const uint8_t *)"\xb3"; EXPECT_TRUE(vtenc_set_decoded_size_u8(in, in_len) == 180);
|
||||
in = (const uint8_t *)"\xff"; EXPECT_TRUE(vtenc_set_decoded_size_u8(in, in_len) == 256);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decoded_size_u16(void)
|
||||
{
|
||||
const uint8_t *in;
|
||||
const size_t in_len = 2;
|
||||
|
||||
in = (const uint8_t *)"\x00\x00"; EXPECT_TRUE(vtenc_set_decoded_size_u16(in, in_len) == 1);
|
||||
in = (const uint8_t *)"\x01\x01"; EXPECT_TRUE(vtenc_set_decoded_size_u16(in, in_len) == 258);
|
||||
in = (const uint8_t *)"\x25\x33"; EXPECT_TRUE(vtenc_set_decoded_size_u16(in, in_len) == 13094);
|
||||
in = (const uint8_t *)"\x00\xff"; EXPECT_TRUE(vtenc_set_decoded_size_u16(in, in_len) == 65281);
|
||||
in = (const uint8_t *)"\xff\xff"; EXPECT_TRUE(vtenc_set_decoded_size_u16(in, in_len) == 65536);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decoded_size_u32(void)
|
||||
{
|
||||
const uint8_t *in;
|
||||
const size_t in_len = 4;
|
||||
|
||||
in = (const uint8_t *)"\x00\x00\x00\x00"; EXPECT_TRUE(vtenc_set_decoded_size_u32(in, in_len) == 1);
|
||||
in = (const uint8_t *)"\x01\x01\x01\x01"; EXPECT_TRUE(vtenc_set_decoded_size_u32(in, in_len) == 16843010);
|
||||
in = (const uint8_t *)"\x55\x55\x55\x55"; EXPECT_TRUE(vtenc_set_decoded_size_u32(in, in_len) == 1431655766);
|
||||
in = (const uint8_t *)"\x00\xff\xff\x00"; EXPECT_TRUE(vtenc_set_decoded_size_u32(in, in_len) == 16776961);
|
||||
in = (const uint8_t *)"\xff\xff\xff\xff"; EXPECT_TRUE(vtenc_set_decoded_size_u32(in, in_len) == 4294967296);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_decoded_size_u64(void)
|
||||
{
|
||||
const uint8_t *in;
|
||||
const size_t in_len = 8;
|
||||
|
||||
in = (const uint8_t *)"\x00\x00\x00\x00\x00\x00\x00\x00"; EXPECT_TRUE(vtenc_set_decoded_size_u64(in, in_len) == 1);
|
||||
in = (const uint8_t *)"\x01\x01\x01\x01\x01\x01\x01\x01"; EXPECT_TRUE(vtenc_set_decoded_size_u64(in, in_len) == 0x0101010101010102ULL);
|
||||
in = (const uint8_t *)"\x55\x55\x55\x55\x55\x55\x55\x55"; EXPECT_TRUE(vtenc_set_decoded_size_u64(in, in_len) == 0x0155555555555556ULL);
|
||||
in = (const uint8_t *)"\x00\xff\xff\x00\x00\xff\xff\x00"; EXPECT_TRUE(vtenc_set_decoded_size_u64(in, in_len) == 0x00ffff0000ffff01ULL);
|
||||
in = (const uint8_t *)"\xff\xff\xff\xff\xff\xff\xff\xff"; EXPECT_TRUE(vtenc_set_decoded_size_u64(in, in_len) == 0x0200000000000000ULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
566
ext/vtenc/tests/unit/encode_test.c
Normal file
566
ext/vtenc/tests/unit/encode_test.c
Normal file
@ -0,0 +1,566 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "unit_tests.h"
|
||||
#include "../../vtenc.h"
|
||||
|
||||
int test_vtenc_list_encode_u8_1(void)
|
||||
{
|
||||
const uint8_t in[] = {};
|
||||
const size_t in_len = 0;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u8(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u8(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 8);
|
||||
EXPECT_TRUE(memcmp(out, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_encode_u8_2(void)
|
||||
{
|
||||
const uint8_t in[] = {5, 22, 23, 44, 62, 69, 109, 113, 178, 194, 206};
|
||||
const size_t in_len = 11;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u8(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u8(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 17);
|
||||
EXPECT_TRUE(memcmp(out, "\x0b\x00\x00\x00\x00\x00\x00\xb0\x56\x09\xc5\xd8\x8a\x2e\x56\x2b\x01", 17) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_encode_u8_3(void)
|
||||
{
|
||||
const uint8_t in[] = {57, 57, 57, 111, 111, 111, 111, 208, 208};
|
||||
const size_t in_len = 9;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u8(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u8(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 14);
|
||||
EXPECT_TRUE(memcmp(out, "\x09\x00\x00\x00\x00\x00\x00\x6e\xc0\x03\x02\x00\xa2\x0a", 14) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_encode_u16_1(void)
|
||||
{
|
||||
const uint16_t in[] = {};
|
||||
const size_t in_len = 0;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u16(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u16(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 8);
|
||||
EXPECT_TRUE(memcmp(out, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_encode_u16_2(void)
|
||||
{
|
||||
const uint16_t in[] = {1099, 2227, 8102, 27654, 29001, 35511, 50083};
|
||||
const size_t in_len = 7;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u16(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u16(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 21);
|
||||
EXPECT_TRUE(memcmp(out,
|
||||
"\x07\x00\x00\x00\x00\x00\x00\xba\xcd\x2d\x97\x01\x4d\xe2\xcf\x6b"
|
||||
"\x6b\x95\x78\x74\x00", 21) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_encode_u16_3(void)
|
||||
{
|
||||
const uint16_t in[] = {677, 677, 677, 8881, 8881, 8881, 8881, 8881};
|
||||
const size_t in_len = 8;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u16(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u16(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 17);
|
||||
EXPECT_TRUE(memcmp(out, "\x08\x00\x00\x00\x00\x00\x00\x10\xe7\x67\xe6\x99\xb6\x28\x0a\xb4\x05", 17) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_encode_u32_1(void)
|
||||
{
|
||||
const uint32_t in[] = {};
|
||||
const size_t in_len = 0;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u32(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u32(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 8);
|
||||
EXPECT_TRUE(memcmp(out, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_encode_u32_2(void)
|
||||
{
|
||||
const uint32_t in[] = {5348, 13089333, 88199704, 271008013, 1451881090};
|
||||
const size_t in_len = 5;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u32(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u32(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 27);
|
||||
EXPECT_TRUE(memcmp(out,
|
||||
"\x05\x00\x00\x00\x00\x00\x00\x4a\x6e\xb5\xff\x35\xb6\x43\x74\xaa"
|
||||
"\x3e\xda\xf3\xdf\xe8\x7b\x2a\xdd\x60\x7d\x01", 27) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_encode_u32_3(void)
|
||||
{
|
||||
const uint32_t in[] = {77865901, 77865901, 77865901, 77865901, 314976310, 314976310};
|
||||
const size_t in_len = 6;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u32(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u32(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 27);
|
||||
EXPECT_TRUE(memcmp(out,
|
||||
"\x06\x00\x00\x00\x00\x00\x00\x6c\x93\x20\x41\x90\x20\x49\x90\x04"
|
||||
"\x40\x10\x20\x14\x41\x05\x15\x51\x15\x04\x01", 27) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_encode_u64_1(void)
|
||||
{
|
||||
const uint64_t in[] = {};
|
||||
const size_t in_len = 0;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u64(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u64(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 8);
|
||||
EXPECT_TRUE(memcmp(out, "\x00\x00\x00\x00\x00\x00\x00\x00", 8) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_encode_u64_2(void)
|
||||
{
|
||||
const uint64_t in[] = {0x12a6, 0x8addf0, 0xffa1b4bb, 0x21258ee39aaa};
|
||||
const size_t in_len = 4;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u64(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u64(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 35);
|
||||
EXPECT_TRUE(memcmp(out,
|
||||
"\x04\x00\x00\x00\x00\x00\x00\x48\x92\x24\x49\x92\x24\xc9\xfd\xff"
|
||||
"\xff\xaf\xaa\xda\xff\x56\xf3\x4a\x04\x0f\xd0\x93\x16\x79\x5b\x8e"
|
||||
"\x38\xa6\xaa", 35) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_encode_u64_3(void)
|
||||
{
|
||||
const uint64_t in[] = {0x55555555, 0x55555555, 0x55555555, 0x111111111111, 0x111111111111};
|
||||
const size_t in_len = 5;
|
||||
const size_t out_cap = vtenc_list_max_encoded_size_u64(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_list_encode_u64(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 37);
|
||||
EXPECT_TRUE(memcmp(out,
|
||||
"\x05\x00\x00\x00\x00\x00\x00\xda\xb6\x6d\xdb\xb6\x6d\xdb\xee\xff"
|
||||
"\xff\x7f\x66\x66\x66\x66\x66\x66\x66\x46\x45\x45\x45\x45\x45\x45"
|
||||
"\x45\x45\x45\x45\x05", 37) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u8_1(void)
|
||||
{
|
||||
const uint8_t in[] = {};
|
||||
const size_t in_len = 0;
|
||||
const size_t out_cap = 0;
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u8(in, in_len, out, out_cap, &out_len) == VtencErrorInputTooSmall);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u8_2(void)
|
||||
{
|
||||
const uint8_t in[] = {};
|
||||
const size_t in_len = 257;
|
||||
const size_t out_cap = 0;
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u8(in, in_len, out, out_cap, &out_len) == VtencErrorInputTooBig);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u8_3(void)
|
||||
{
|
||||
const size_t in_len = 256;
|
||||
uint8_t in[in_len];
|
||||
const size_t out_cap = vtenc_set_max_encoded_size_u8(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len, i;
|
||||
|
||||
for (i=0; i<in_len; ++i) in[i] = (uint8_t)i;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u8(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 1);
|
||||
EXPECT_TRUE(memcmp(out, "\xff", 1) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u8_4(void)
|
||||
{
|
||||
const uint8_t in[] = {33};
|
||||
const size_t in_len = 1;
|
||||
const size_t out_cap = vtenc_set_max_encoded_size_u8(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u8(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 2);
|
||||
EXPECT_TRUE(memcmp(out, "\x00\x7b", 2) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u8_5(void)
|
||||
{
|
||||
const uint8_t in[] = {0, 1, 2, 3, 4, 5, 6, 7, 160, 161, 162, 163};
|
||||
const size_t in_len = 12;
|
||||
const size_t out_cap = vtenc_set_max_encoded_size_u8(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u8(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 6);
|
||||
EXPECT_TRUE(memcmp(out, "\x0b\x88\x88\x48\x90\x04", 6) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u8_6(void)
|
||||
{
|
||||
const uint8_t in[] = {13, 77, 88, 93, 149, 212};
|
||||
const size_t in_len = 6;
|
||||
const size_t out_cap = vtenc_set_max_encoded_size_u8(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u8(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 7);
|
||||
EXPECT_TRUE(memcmp(out, "\x05\xcc\x74\x44\x57\x55\x03", 7) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u16_1(void)
|
||||
{
|
||||
const uint16_t in[] = {};
|
||||
const size_t in_len = 0;
|
||||
const size_t out_cap = 0;
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u16(in, in_len, out, out_cap, &out_len) == VtencErrorInputTooSmall);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u16_2(void)
|
||||
{
|
||||
const uint16_t in[] = {};
|
||||
const size_t in_len = 65537;
|
||||
const size_t out_cap = 0;
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u16(in, in_len, out, out_cap, &out_len) == VtencErrorInputTooBig);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u16_3(void)
|
||||
{
|
||||
const uint16_t in[] = {1655, 3391, 4111, 8770, 29006, 32712, 32993, 58042};
|
||||
const size_t in_len = 8;
|
||||
const size_t out_cap = vtenc_set_max_encoded_size_u16(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u16(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 17);
|
||||
EXPECT_TRUE(memcmp(out, "\x07\x00\xc6\x19\x23\x34\xf0\x0f\xb7\x17\x5a\x23\xd8\xfb\xf1\x5c\x51", 17) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u16_4(void)
|
||||
{
|
||||
const uint16_t in[] = {
|
||||
14000, 14001, 14002, 14003, 14004, 14005, 14006, 14007,
|
||||
20000, 20001, 20002, 20003
|
||||
};
|
||||
const size_t in_len = 12;
|
||||
const size_t out_cap = vtenc_set_max_encoded_size_u16(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u16(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 13);
|
||||
EXPECT_TRUE(memcmp(out, "\x0b\x00\x8c\x00\x08\x80\x80\x00\x48\x02\x20\x09\x92", 13) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u32_1(void)
|
||||
{
|
||||
const uint32_t in[] = {};
|
||||
const size_t in_len = 0;
|
||||
const size_t out_cap = 0;
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u32(in, in_len, out, out_cap, &out_len) == VtencErrorInputTooSmall);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u32_2(void)
|
||||
{
|
||||
const uint32_t in[] = {};
|
||||
const size_t in_len = 0x200000000;
|
||||
const size_t out_cap = 0;
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u32(in, in_len, out, out_cap, &out_len) == VtencErrorInputTooBig);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u32_3(void)
|
||||
{
|
||||
const uint32_t in[] = {0x98b204, 0x122fabb4, 0x378ecef0, 0x77ccab8f, 0xa40609bb};
|
||||
const size_t in_len = 5;
|
||||
const size_t out_cap = vtenc_set_max_encoded_size_u32(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u32(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 24);
|
||||
EXPECT_TRUE(memcmp(out,
|
||||
"\x04\x00\x00\x00\x9c\xbd\xb9\xec\xf7\x2e\xa8\x48\x0b\x47\x46\x78"
|
||||
"\x82\x59\xc5\xa1\xfd\xf9\x26\x02", 24) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u32_4(void)
|
||||
{
|
||||
const uint32_t in[] = {
|
||||
0xa500, 0xa501, 0xa502, 0xa503,
|
||||
0x4bbb00, 0x4bbb01,
|
||||
0xffff00, 0xffff01, 0xffff02, 0xffff03, 0xffff04, 0xffff05, 0xffff06, 0xffff07
|
||||
};
|
||||
const size_t in_len = 14;
|
||||
const size_t out_cap = vtenc_set_max_encoded_size_u32(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u32(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 32);
|
||||
EXPECT_TRUE(memcmp(out,
|
||||
"\x0d\x00\x00\x00\xee\xee\xee\xee\x46\x92\x24\x41\x90\x20\x48\x92"
|
||||
"\x54\x04\x04\x04\x55\x15\x00\x00\x00\x00\x00\x00\x00\x10\x11\x11", 32) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u64_1(void)
|
||||
{
|
||||
const uint64_t in[] = {};
|
||||
const size_t in_len = 0;
|
||||
const size_t out_cap = 0;
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u64(in, in_len, out, out_cap, &out_len) == VtencErrorInputTooSmall);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u64_2(void)
|
||||
{
|
||||
const uint64_t in[] = {
|
||||
0x11223344ULL, 0xaabbccddULL, 0x1010101010ULL, 0x5555555555ULL, 0xf0f0f0f0f0ULL,
|
||||
0x998877665544ULL, 0xffeeffeeffeeULL
|
||||
};
|
||||
const size_t in_len = 7;
|
||||
const size_t out_cap = vtenc_set_max_encoded_size_u64(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u64(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 53);
|
||||
EXPECT_TRUE(memcmp(out,
|
||||
"\x06\x00\x00\x00\x00\x00\x00\xfe\xff\xff\xff\xff\xff\xdb\xb6\x6d"
|
||||
"\xb9\x55\x6d\xb7\x3b\xd3\x5d\x15\x61\x26\xfa\xfb\xfb\xfb\xfb\xaa"
|
||||
"\xaa\xaa\xaa\x0a\x0f\x0f\x0f\x0f\x5f\xe6\x1e\x91\x59\xd5\x0d\x20"
|
||||
"\x02\x20\x02\x20\x02", 53) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_encode_u64_3(void)
|
||||
{
|
||||
const uint64_t in[] = {
|
||||
0x20000000ULL, 0x20000001ULL, 0x20000002ULL, 0x20000003ULL,
|
||||
0x80000000ULL, 0x80000001ULL,
|
||||
0x2000000000ULL, 0x2000000001ULL
|
||||
};
|
||||
const size_t in_len = 8;
|
||||
const size_t out_cap = vtenc_set_max_encoded_size_u64(in_len);
|
||||
uint8_t out[out_cap];
|
||||
size_t out_len;
|
||||
|
||||
EXPECT_TRUE(vtenc_set_encode_u64(in, in_len, out, out_cap, &out_len) == VtencErrorNoError);
|
||||
EXPECT_TRUE(out_len == 51);
|
||||
EXPECT_TRUE(memcmp(out,
|
||||
"\x07\x00\x00\x00\x00\x00\x00\x10\x11\x11\x11\x11\x11\x11\x11\x11"
|
||||
"\x11\x11\x11\x11\xcd\xb6\x4d\x82\x24\x49\x92\x24\x49\x92\x24\x49"
|
||||
"\x92\xa4\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
|
||||
"\xaa\xaa\x02", 51) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_max_encoded_size_u8(void)
|
||||
{
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u8(0) == 8);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u8(1) == 16);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u8(5) == 16);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u8(10) == 24);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u8(100) == 112);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u8(1000) == 1008);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_max_encoded_size_u16(void)
|
||||
{
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u16(0) == 16);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u16(1) == 16);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u16(5) == 24);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u16(10) == 32);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u16(100) == 216);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u16(1000) == 2016);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_max_encoded_size_u32(void)
|
||||
{
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u32(0) == 16);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u32(1) == 16);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u32(5) == 32);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u32(10) == 56);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u32(100) == 416);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u32(1000) == 4016);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_list_max_encoded_size_u64(void)
|
||||
{
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u64(0) == 16);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u64(1) == 24);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u64(5) == 56);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u64(10) == 96);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u64(100) == 816);
|
||||
EXPECT_TRUE(vtenc_list_max_encoded_size_u64(1000) == 8016);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_max_encoded_size_u8(void)
|
||||
{
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u8(0) == 8);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u8(1) == 8);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u8(5) == 8);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u8(10) == 16);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u8(100) == 104);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_max_encoded_size_u16(void)
|
||||
{
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u16(0) == 8);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u16(1) == 8);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u16(5) == 16);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u16(10) == 24);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u16(100) == 208);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u16(1000) == 2008);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_max_encoded_size_u32(void)
|
||||
{
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u32(0) == 8);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u32(1) == 16);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u32(5) == 32);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u32(10) == 48);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u32(100) == 408);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u32(1000) == 4008);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_vtenc_set_max_encoded_size_u64(void)
|
||||
{
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u64(0) == 16);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u64(1) == 24);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u64(5) == 56);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u64(10) == 96);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u64(100) == 816);
|
||||
EXPECT_TRUE(vtenc_set_max_encoded_size_u64(1000) == 8016);
|
||||
|
||||
return 1;
|
||||
}
|
||||
53
ext/vtenc/tests/unit/mem_test.c
Normal file
53
ext/vtenc/tests/unit/mem_test.c
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "unit_tests.h"
|
||||
#include "../../mem.h"
|
||||
|
||||
int test_little_endian_read_and_write_u16(void)
|
||||
{
|
||||
const char *in_data = "\x11\x22";
|
||||
char out_data[2];
|
||||
uint16_t value;
|
||||
|
||||
value = mem_read_le_u16(in_data);
|
||||
mem_write_le_u16(out_data, value);
|
||||
|
||||
EXPECT_TRUE(memcmp(in_data, out_data, 2) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_little_endian_read_and_write_u32(void)
|
||||
{
|
||||
const char *in_data = "\x11\x22\x33\x44";
|
||||
char out_data[4];
|
||||
uint32_t value;
|
||||
|
||||
value = mem_read_le_u32(in_data);
|
||||
mem_write_le_u32(out_data, value);
|
||||
|
||||
EXPECT_TRUE(memcmp(in_data, out_data, 4) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int test_little_endian_read_and_write_u64(void)
|
||||
{
|
||||
const char *in_data = "\x11\x22\x33\x44\x55\x66\x77\x88";
|
||||
char out_data[8];
|
||||
uint64_t value;
|
||||
|
||||
value = mem_read_le_u64(in_data);
|
||||
mem_write_le_u64(out_data, value);
|
||||
|
||||
EXPECT_TRUE(memcmp(in_data, out_data, 8) == 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
144
ext/vtenc/tests/unit/unit_tests.c
Normal file
144
ext/vtenc/tests/unit/unit_tests.c
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
#include "unit_tests.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define RUN_TEST(fn_name) \
|
||||
do { \
|
||||
printf(""#fn_name"..."); \
|
||||
if ((fn_name)()) printf(" OK\n"); \
|
||||
else printf(" KO\n"); \
|
||||
} while (0)
|
||||
|
||||
int main()
|
||||
{
|
||||
RUN_TEST(test_bits_swap_u16);
|
||||
RUN_TEST(test_bits_swap_u32);
|
||||
RUN_TEST(test_bits_swap_u64);
|
||||
|
||||
RUN_TEST(test_bits_len_u8);
|
||||
RUN_TEST(test_bits_len_u16);
|
||||
RUN_TEST(test_bits_len_u32);
|
||||
RUN_TEST(test_bits_len_u64);
|
||||
|
||||
RUN_TEST(test_little_endian_read_and_write_u16);
|
||||
RUN_TEST(test_little_endian_read_and_write_u32);
|
||||
RUN_TEST(test_little_endian_read_and_write_u64);
|
||||
|
||||
RUN_TEST(test_bswriter_align_buffer_size);
|
||||
RUN_TEST(test_bswriter_init_1);
|
||||
RUN_TEST(test_bswriter_init_2);
|
||||
RUN_TEST(test_bswriter_write_1);
|
||||
RUN_TEST(test_bswriter_write_2);
|
||||
RUN_TEST(test_bswriter_write_3);
|
||||
RUN_TEST(test_bswriter_close_1);
|
||||
RUN_TEST(test_bswriter_close_2);
|
||||
|
||||
RUN_TEST(test_bsreader_init_1);
|
||||
RUN_TEST(test_bsreader_init_2);
|
||||
RUN_TEST(test_bsreader_read_1);
|
||||
RUN_TEST(test_bsreader_read_2);
|
||||
RUN_TEST(test_bsreader_read_3);
|
||||
RUN_TEST(test_bsreader_read_4);
|
||||
RUN_TEST(test_bsreader_read_5);
|
||||
RUN_TEST(test_bsreader_read_6);
|
||||
RUN_TEST(test_bsreader_size);
|
||||
|
||||
RUN_TEST(test_vtenc_list_encode_u8_1);
|
||||
RUN_TEST(test_vtenc_list_encode_u8_2);
|
||||
RUN_TEST(test_vtenc_list_encode_u8_3);
|
||||
RUN_TEST(test_vtenc_list_encode_u16_1);
|
||||
RUN_TEST(test_vtenc_list_encode_u16_2);
|
||||
RUN_TEST(test_vtenc_list_encode_u16_3);
|
||||
RUN_TEST(test_vtenc_list_encode_u32_1);
|
||||
RUN_TEST(test_vtenc_list_encode_u32_2);
|
||||
RUN_TEST(test_vtenc_list_encode_u32_3);
|
||||
RUN_TEST(test_vtenc_list_encode_u64_1);
|
||||
RUN_TEST(test_vtenc_list_encode_u64_2);
|
||||
RUN_TEST(test_vtenc_list_encode_u64_3);
|
||||
|
||||
RUN_TEST(test_vtenc_set_encode_u8_1);
|
||||
RUN_TEST(test_vtenc_set_encode_u8_2);
|
||||
RUN_TEST(test_vtenc_set_encode_u8_3);
|
||||
RUN_TEST(test_vtenc_set_encode_u8_4);
|
||||
RUN_TEST(test_vtenc_set_encode_u8_5);
|
||||
RUN_TEST(test_vtenc_set_encode_u8_6);
|
||||
RUN_TEST(test_vtenc_set_encode_u16_1);
|
||||
RUN_TEST(test_vtenc_set_encode_u16_2);
|
||||
RUN_TEST(test_vtenc_set_encode_u16_3);
|
||||
RUN_TEST(test_vtenc_set_encode_u16_4);
|
||||
RUN_TEST(test_vtenc_set_encode_u32_1);
|
||||
RUN_TEST(test_vtenc_set_encode_u32_2);
|
||||
RUN_TEST(test_vtenc_set_encode_u32_3);
|
||||
RUN_TEST(test_vtenc_set_encode_u32_4);
|
||||
RUN_TEST(test_vtenc_set_encode_u64_1);
|
||||
RUN_TEST(test_vtenc_set_encode_u64_2);
|
||||
RUN_TEST(test_vtenc_set_encode_u64_3);
|
||||
|
||||
RUN_TEST(test_vtenc_list_max_encoded_size_u8);
|
||||
RUN_TEST(test_vtenc_list_max_encoded_size_u16);
|
||||
RUN_TEST(test_vtenc_list_max_encoded_size_u32);
|
||||
RUN_TEST(test_vtenc_list_max_encoded_size_u64);
|
||||
|
||||
RUN_TEST(test_vtenc_set_max_encoded_size_u8);
|
||||
RUN_TEST(test_vtenc_set_max_encoded_size_u16);
|
||||
RUN_TEST(test_vtenc_set_max_encoded_size_u32);
|
||||
RUN_TEST(test_vtenc_set_max_encoded_size_u64);
|
||||
|
||||
RUN_TEST(test_vtenc_list_decode_u8_1);
|
||||
RUN_TEST(test_vtenc_list_decode_u8_2);
|
||||
RUN_TEST(test_vtenc_list_decode_u8_3);
|
||||
RUN_TEST(test_vtenc_list_decode_u8_4);
|
||||
RUN_TEST(test_vtenc_list_decode_u8_5);
|
||||
RUN_TEST(test_vtenc_list_decode_u16_1);
|
||||
RUN_TEST(test_vtenc_list_decode_u16_2);
|
||||
RUN_TEST(test_vtenc_list_decode_u16_3);
|
||||
RUN_TEST(test_vtenc_list_decode_u16_4);
|
||||
RUN_TEST(test_vtenc_list_decode_u16_5);
|
||||
RUN_TEST(test_vtenc_list_decode_u32_1);
|
||||
RUN_TEST(test_vtenc_list_decode_u32_2);
|
||||
RUN_TEST(test_vtenc_list_decode_u32_3);
|
||||
RUN_TEST(test_vtenc_list_decode_u32_4);
|
||||
RUN_TEST(test_vtenc_list_decode_u32_5);
|
||||
RUN_TEST(test_vtenc_list_decode_u64_1);
|
||||
RUN_TEST(test_vtenc_list_decode_u64_2);
|
||||
RUN_TEST(test_vtenc_list_decode_u64_3);
|
||||
RUN_TEST(test_vtenc_list_decode_u64_4);
|
||||
RUN_TEST(test_vtenc_list_decode_u64_5);
|
||||
|
||||
RUN_TEST(test_vtenc_set_decode_u8_1);
|
||||
RUN_TEST(test_vtenc_set_decode_u8_2);
|
||||
RUN_TEST(test_vtenc_set_decode_u8_3);
|
||||
RUN_TEST(test_vtenc_set_decode_u8_4);
|
||||
RUN_TEST(test_vtenc_set_decode_u8_5);
|
||||
RUN_TEST(test_vtenc_set_decode_u16_1);
|
||||
RUN_TEST(test_vtenc_set_decode_u16_2);
|
||||
RUN_TEST(test_vtenc_set_decode_u16_3);
|
||||
RUN_TEST(test_vtenc_set_decode_u16_4);
|
||||
RUN_TEST(test_vtenc_set_decode_u32_1);
|
||||
RUN_TEST(test_vtenc_set_decode_u32_2);
|
||||
RUN_TEST(test_vtenc_set_decode_u32_3);
|
||||
RUN_TEST(test_vtenc_set_decode_u32_4);
|
||||
RUN_TEST(test_vtenc_set_decode_u64_1);
|
||||
RUN_TEST(test_vtenc_set_decode_u64_2);
|
||||
RUN_TEST(test_vtenc_set_decode_u64_3);
|
||||
RUN_TEST(test_vtenc_set_decode_u64_4);
|
||||
RUN_TEST(test_vtenc_set_decode_u64_5);
|
||||
|
||||
RUN_TEST(test_vtenc_list_decoded_size_1);
|
||||
RUN_TEST(test_vtenc_list_decoded_size_2);
|
||||
RUN_TEST(test_vtenc_list_decoded_size_3);
|
||||
RUN_TEST(test_vtenc_list_decoded_size_4);
|
||||
|
||||
RUN_TEST(test_vtenc_set_decoded_size_with_wrong_input);
|
||||
RUN_TEST(test_vtenc_set_decoded_size_u8);
|
||||
RUN_TEST(test_vtenc_set_decoded_size_u16);
|
||||
RUN_TEST(test_vtenc_set_decoded_size_u32);
|
||||
RUN_TEST(test_vtenc_set_decoded_size_u64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
143
ext/vtenc/tests/unit/unit_tests.h
Normal file
143
ext/vtenc/tests/unit/unit_tests.h
Normal file
@ -0,0 +1,143 @@
|
||||
/**
|
||||
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_UNIT_TESTS_H_
|
||||
#define VTENC_UNIT_TESTS_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define EXPECT_TRUE(test) \
|
||||
do { \
|
||||
if (!(test)) { \
|
||||
printf("\n\t\""#test"\" failed!\n"); \
|
||||
return 0; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
int test_bits_swap_u16(void);
|
||||
int test_bits_swap_u32(void);
|
||||
int test_bits_swap_u64(void);
|
||||
|
||||
int test_bits_len_u8(void);
|
||||
int test_bits_len_u16(void);
|
||||
int test_bits_len_u32(void);
|
||||
int test_bits_len_u64(void);
|
||||
|
||||
int test_little_endian_read_and_write_u16(void);
|
||||
int test_little_endian_read_and_write_u32(void);
|
||||
int test_little_endian_read_and_write_u64(void);
|
||||
|
||||
int test_bswriter_align_buffer_size(void);
|
||||
int test_bswriter_init_1(void);
|
||||
int test_bswriter_init_2(void);
|
||||
int test_bswriter_write_1(void);
|
||||
int test_bswriter_write_2(void);
|
||||
int test_bswriter_write_3(void);
|
||||
int test_bswriter_close_1(void);
|
||||
int test_bswriter_close_2(void);
|
||||
|
||||
int test_bsreader_init_1(void);
|
||||
int test_bsreader_init_2(void);
|
||||
int test_bsreader_read_1(void);
|
||||
int test_bsreader_read_2(void);
|
||||
int test_bsreader_read_3(void);
|
||||
int test_bsreader_read_4(void);
|
||||
int test_bsreader_read_5(void);
|
||||
int test_bsreader_read_6(void);
|
||||
int test_bsreader_size(void);
|
||||
|
||||
int test_vtenc_list_encode_u8_1(void);
|
||||
int test_vtenc_list_encode_u8_2(void);
|
||||
int test_vtenc_list_encode_u8_3(void);
|
||||
int test_vtenc_list_encode_u16_1(void);
|
||||
int test_vtenc_list_encode_u16_2(void);
|
||||
int test_vtenc_list_encode_u16_3(void);
|
||||
int test_vtenc_list_encode_u32_1(void);
|
||||
int test_vtenc_list_encode_u32_2(void);
|
||||
int test_vtenc_list_encode_u32_3(void);
|
||||
int test_vtenc_list_encode_u64_1(void);
|
||||
int test_vtenc_list_encode_u64_2(void);
|
||||
int test_vtenc_list_encode_u64_3(void);
|
||||
|
||||
int test_vtenc_set_encode_u8_1(void);
|
||||
int test_vtenc_set_encode_u8_2(void);
|
||||
int test_vtenc_set_encode_u8_3(void);
|
||||
int test_vtenc_set_encode_u8_4(void);
|
||||
int test_vtenc_set_encode_u8_5(void);
|
||||
int test_vtenc_set_encode_u8_6(void);
|
||||
int test_vtenc_set_encode_u16_1(void);
|
||||
int test_vtenc_set_encode_u16_2(void);
|
||||
int test_vtenc_set_encode_u16_3(void);
|
||||
int test_vtenc_set_encode_u16_4(void);
|
||||
int test_vtenc_set_encode_u32_1(void);
|
||||
int test_vtenc_set_encode_u32_2(void);
|
||||
int test_vtenc_set_encode_u32_3(void);
|
||||
int test_vtenc_set_encode_u32_4(void);
|
||||
int test_vtenc_set_encode_u64_1(void);
|
||||
int test_vtenc_set_encode_u64_2(void);
|
||||
int test_vtenc_set_encode_u64_3(void);
|
||||
|
||||
int test_vtenc_list_max_encoded_size_u8(void);
|
||||
int test_vtenc_list_max_encoded_size_u16(void);
|
||||
int test_vtenc_list_max_encoded_size_u32(void);
|
||||
int test_vtenc_list_max_encoded_size_u64(void);
|
||||
|
||||
int test_vtenc_set_max_encoded_size_u8(void);
|
||||
int test_vtenc_set_max_encoded_size_u16(void);
|
||||
int test_vtenc_set_max_encoded_size_u32(void);
|
||||
int test_vtenc_set_max_encoded_size_u64(void);
|
||||
|
||||
int test_vtenc_list_decode_u8_1(void);
|
||||
int test_vtenc_list_decode_u8_2(void);
|
||||
int test_vtenc_list_decode_u8_3(void);
|
||||
int test_vtenc_list_decode_u8_4(void);
|
||||
int test_vtenc_list_decode_u8_5(void);
|
||||
int test_vtenc_list_decode_u16_1(void);
|
||||
int test_vtenc_list_decode_u16_2(void);
|
||||
int test_vtenc_list_decode_u16_3(void);
|
||||
int test_vtenc_list_decode_u16_4(void);
|
||||
int test_vtenc_list_decode_u16_5(void);
|
||||
int test_vtenc_list_decode_u32_1(void);
|
||||
int test_vtenc_list_decode_u32_2(void);
|
||||
int test_vtenc_list_decode_u32_3(void);
|
||||
int test_vtenc_list_decode_u32_4(void);
|
||||
int test_vtenc_list_decode_u32_5(void);
|
||||
int test_vtenc_list_decode_u64_1(void);
|
||||
int test_vtenc_list_decode_u64_2(void);
|
||||
int test_vtenc_list_decode_u64_3(void);
|
||||
int test_vtenc_list_decode_u64_4(void);
|
||||
int test_vtenc_list_decode_u64_5(void);
|
||||
|
||||
int test_vtenc_set_decode_u8_1(void);
|
||||
int test_vtenc_set_decode_u8_2(void);
|
||||
int test_vtenc_set_decode_u8_3(void);
|
||||
int test_vtenc_set_decode_u8_4(void);
|
||||
int test_vtenc_set_decode_u8_5(void);
|
||||
int test_vtenc_set_decode_u16_1(void);
|
||||
int test_vtenc_set_decode_u16_2(void);
|
||||
int test_vtenc_set_decode_u16_3(void);
|
||||
int test_vtenc_set_decode_u16_4(void);
|
||||
int test_vtenc_set_decode_u32_1(void);
|
||||
int test_vtenc_set_decode_u32_2(void);
|
||||
int test_vtenc_set_decode_u32_3(void);
|
||||
int test_vtenc_set_decode_u32_4(void);
|
||||
int test_vtenc_set_decode_u64_1(void);
|
||||
int test_vtenc_set_decode_u64_2(void);
|
||||
int test_vtenc_set_decode_u64_3(void);
|
||||
int test_vtenc_set_decode_u64_4(void);
|
||||
int test_vtenc_set_decode_u64_5(void);
|
||||
|
||||
int test_vtenc_list_decoded_size_1(void);
|
||||
int test_vtenc_list_decoded_size_2(void);
|
||||
int test_vtenc_list_decoded_size_3(void);
|
||||
int test_vtenc_list_decoded_size_4(void);
|
||||
|
||||
int test_vtenc_set_decoded_size_with_wrong_input(void);
|
||||
int test_vtenc_set_decoded_size_u8(void);
|
||||
int test_vtenc_set_decoded_size_u16(void);
|
||||
int test_vtenc_set_decoded_size_u32(void);
|
||||
int test_vtenc_set_decoded_size_u64(void);
|
||||
|
||||
#endif /* VTENC_UNIT_TESTS_H_ */
|
||||
123
ext/vtenc/vtenc.h
Normal file
123
ext/vtenc/vtenc.h
Normal file
@ -0,0 +1,123 @@
|
||||
/**
|
||||
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_H_
|
||||
#define VTENC_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This library provides a series of functions to encode and decode sorted
|
||||
* sequences of unsigned integers using VTEnc algorithm. It supports different
|
||||
* types (uint8_t, uint16_t, uint32_t and uint64_t) and two different kind of
|
||||
* sequences: lists and sets.
|
||||
*
|
||||
* Lists and sets differ in that lists can have duplicate values, whereas sets
|
||||
* cannot. Both have to be sorted in ascending order.
|
||||
*/
|
||||
|
||||
/* Error codes */
|
||||
typedef enum {
|
||||
VtencErrorNoError = 0,
|
||||
VtencErrorBufferTooSmall = 1,
|
||||
VtencErrorEndOfStream = 2,
|
||||
VtencErrorNotEnoughBits = 3,
|
||||
VtencErrorInputTooSmall = 4,
|
||||
VtencErrorInputTooBig = 5,
|
||||
VtencErrorWrongFormat = 6
|
||||
} VtencErrorCode;
|
||||
|
||||
/**
|
||||
* Encoding functions.
|
||||
*
|
||||
* Each function encodes the list or set `in` into the already-allocated stream
|
||||
* of bytes `out`.
|
||||
*
|
||||
* `in_len`: size of `in`.
|
||||
* `out_cap`: capacity in bytes of `out`.
|
||||
* `out_len`: actual size of the encoded output. This is an output argument, so
|
||||
* its value will be available after the encode function is called.
|
||||
*
|
||||
* Returns 'VtencErrorNoError' if there was no error. Otherwise, a specific error
|
||||
* code is returned.
|
||||
*
|
||||
* Note that these functions assume that `in` is a sorted sequence and they don't
|
||||
* check its order. If you pass in an unsorted list or set, they'll still
|
||||
* return a 'VtencErrorNoError' code, but the output won't correspond to the
|
||||
* correct encoded stream for the input sequence.
|
||||
*/
|
||||
VtencErrorCode vtenc_list_encode_u8(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_cap, size_t *out_len);
|
||||
VtencErrorCode vtenc_list_encode_u16(const uint16_t *in, size_t in_len, uint8_t *out, size_t out_cap, size_t *out_len);
|
||||
VtencErrorCode vtenc_list_encode_u32(const uint32_t *in, size_t in_len, uint8_t *out, size_t out_cap, size_t *out_len);
|
||||
VtencErrorCode vtenc_list_encode_u64(const uint64_t *in, size_t in_len, uint8_t *out, size_t out_cap, size_t *out_len);
|
||||
|
||||
VtencErrorCode vtenc_set_encode_u8(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_cap, size_t *out_len);
|
||||
VtencErrorCode vtenc_set_encode_u16(const uint16_t *in, size_t in_len, uint8_t *out, size_t out_cap, size_t *out_len);
|
||||
VtencErrorCode vtenc_set_encode_u32(const uint32_t *in, size_t in_len, uint8_t *out, size_t out_cap, size_t *out_len);
|
||||
VtencErrorCode vtenc_set_encode_u64(const uint64_t *in, size_t in_len, uint8_t *out, size_t out_cap, size_t *out_len);
|
||||
|
||||
/**
|
||||
* Functions to calculate the maximum encoded size in bytes when encoding a list
|
||||
* or set of size `in_len`. The returned value is an approximation of the actual
|
||||
* encoded length and it's guaranteed to be at least as big as the actual size.
|
||||
*/
|
||||
size_t vtenc_list_max_encoded_size_u8(size_t in_len);
|
||||
size_t vtenc_list_max_encoded_size_u16(size_t in_len);
|
||||
size_t vtenc_list_max_encoded_size_u32(size_t in_len);
|
||||
size_t vtenc_list_max_encoded_size_u64(size_t in_len);
|
||||
|
||||
size_t vtenc_set_max_encoded_size_u8(size_t in_len);
|
||||
size_t vtenc_set_max_encoded_size_u16(size_t in_len);
|
||||
size_t vtenc_set_max_encoded_size_u32(size_t in_len);
|
||||
size_t vtenc_set_max_encoded_size_u64(size_t in_len);
|
||||
|
||||
/**
|
||||
* Decoding functions.
|
||||
*
|
||||
* Each function decodes the stream of bytes `in` into the already-allocated
|
||||
* list or set `out`.
|
||||
*
|
||||
* `in_len`: size of `in`.
|
||||
* `out_len`: size of `out`.
|
||||
*
|
||||
* Returns 'VtencErrorNoError' in case of success. Otherwise, a specific error
|
||||
* code is returned.
|
||||
*/
|
||||
VtencErrorCode vtenc_list_decode_u8(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len);
|
||||
VtencErrorCode vtenc_list_decode_u16(const uint8_t *in, size_t in_len, uint16_t *out, size_t out_len);
|
||||
VtencErrorCode vtenc_list_decode_u32(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len);
|
||||
VtencErrorCode vtenc_list_decode_u64(const uint8_t *in, size_t in_len, uint64_t *out, size_t out_len);
|
||||
|
||||
VtencErrorCode vtenc_set_decode_u8(const uint8_t *in, size_t in_len, uint8_t *out, size_t out_len);
|
||||
VtencErrorCode vtenc_set_decode_u16(const uint8_t *in, size_t in_len, uint16_t *out, size_t out_len);
|
||||
VtencErrorCode vtenc_set_decode_u32(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len);
|
||||
VtencErrorCode vtenc_set_decode_u64(const uint8_t *in, size_t in_len, uint64_t *out, size_t out_len);
|
||||
|
||||
/**
|
||||
* Functions to extract the size of the decoded sequence from the encoded stream
|
||||
* of bytes `in` of size `in_len`. These functions are used to allocate memory
|
||||
* for the list or set to be decoded before calling the corresponding decode
|
||||
* function.
|
||||
*/
|
||||
size_t vtenc_list_decoded_size_u8(const uint8_t *in, size_t in_len);
|
||||
size_t vtenc_list_decoded_size_u16(const uint8_t *in, size_t in_len);
|
||||
size_t vtenc_list_decoded_size_u32(const uint8_t *in, size_t in_len);
|
||||
size_t vtenc_list_decoded_size_u64(const uint8_t *in, size_t in_len);
|
||||
|
||||
size_t vtenc_set_decoded_size_u8(const uint8_t *in, size_t in_len);
|
||||
size_t vtenc_set_decoded_size_u16(const uint8_t *in, size_t in_len);
|
||||
size_t vtenc_set_decoded_size_u32(const uint8_t *in, size_t in_len);
|
||||
size_t vtenc_set_decoded_size_u64(const uint8_t *in, size_t in_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VTENC_H_ */
|
||||
Reference in New Issue
Block a user