From: Geoffrey Allott Date: Sat, 30 Jul 2022 20:43:17 +0000 (+0100) Subject: initial commit X-Git-Url: https://git.pointlesshacks.com/?a=commitdiff_plain;h=11ad72e3d7f414b68f7a928152709f9ed29404e8;p=tANS.git initial commit --- 11ad72e3d7f414b68f7a928152709f9ed29404e8 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..50a3785 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +.*.sw* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cedffbd --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +CFLAGS = -Isrc -g -Wall -Wextra -Wconversion + +OBJS = $(patsubst %.c, %.o, $(wildcard src/*.o)) +TEST_OBJS = $(patsubst %.c, %.o, $(wildcard test/*.o)) +TESTS = $(patsubst %.c, %, $(wildcard test/*.c)) +RUN_TESTS = $(addprefix run_, $(TESTS)) + +default: $(RUN_TESTS) + +$(RUN_TESTS): run_%: % + $^ + +all: $(OBJS) + +$(OBJS): %.o: %.h src/tans_constants.h +$(TEST_OBJS): test/test.h $(OBJS) + +test/test_tans_bit_reader.o: src/tans_buf_bit_reader.h src/tans_file_bit_reader.h src/tans_bit_reader.h +test/test_tans_bit_reader: src/tans_buf_bit_reader.o src/tans_file_bit_reader.o +test/test_tans_bit_writer.o: src/tans_buf_bit_writer.h src/tans_bit_writer.h +test/test_tans_bit_writer: src/tans_buf_bit_writer.o +test/test_tans_encode_st.o: src/tans_buf_bit_writer.h src/tans_bit_writer.h src/tans_encode_st.h src/tans_symbol_tbl.h src/tans_freq_tbl.h +test/test_tans_encode_st: src/tans_buf_bit_writer.o src/tans_encode_st.o src/tans_encode_tbl.o src/tans_symbol_tbl.o + +clean: + rm -f $(OBJS) + rm -f $(TEST_OBJS) + rm -f $(TESTS) + +.PHONY: default all clean $(RUN_TESTS) diff --git a/src/floor_log2.h b/src/floor_log2.h new file mode 100644 index 0000000..24c2e0e --- /dev/null +++ b/src/floor_log2.h @@ -0,0 +1,22 @@ +#pragma once + +static uint16_t floor_log2(uint16_t x) +{ + if (x <= 1) return 0; + if (x <= 2) return 1; + if (x <= 4) return 2; + if (x <= 8) return 3; + if (x <= 16) return 4; + if (x <= 32) return 5; + if (x <= 64) return 6; + if (x <= 128) return 7; + if (x <= 256) return 8; + if (x <= 512) return 9; + if (x <= 1024) return 10; + if (x <= 2048) return 11; + if (x <= 4096) return 12; + if (x <= 8192) return 13; + if (x <= 16384) return 14; + if (x <= 32768) return 15; + /*if (x <= 65536)*/ return 16; +} diff --git a/src/tans_bit_reader.h b/src/tans_bit_reader.h new file mode 100644 index 0000000..dc139f8 --- /dev/null +++ b/src/tans_bit_reader.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +struct tans_bit_reader; + +struct tans_bit_reader_ops { + uint16_t (*read)(struct tans_bit_reader *self, uint8_t bits); +}; + +struct tans_bit_reader { + const struct tans_bit_reader_ops *vtable; +}; diff --git a/src/tans_bit_writer.h b/src/tans_bit_writer.h new file mode 100644 index 0000000..119c138 --- /dev/null +++ b/src/tans_bit_writer.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +struct tans_bit_writer; + +struct tans_bit_writer_ops { + uint16_t (*write)(struct tans_bit_writer *self, uint16_t value, uint8_t bits); +}; + +struct tans_bit_writer { + const struct tans_bit_writer_ops *vtable; +}; diff --git a/src/tans_buf_bit_reader.c b/src/tans_buf_bit_reader.c new file mode 100644 index 0000000..564549e --- /dev/null +++ b/src/tans_buf_bit_reader.c @@ -0,0 +1,36 @@ +#include "tans_buf_bit_reader.h" + +static uint16_t tans_buf_bit_reader_read(struct tans_bit_reader *reader, uint8_t bits) +{ + struct tans_buf_bit_reader *self = (struct tans_buf_bit_reader *) reader; + uint32_t bit = self->bit % 8; + uint32_t byte = self->bit / 8; + + if (bits == 0 || self->bit + bits > self->len * 8) { + return (uint16_t) -1; + } + + self->bit += bits; + + if (bit + bits <= 8) { + return (uint16_t) (((1 << bits) - 1) & (self->buf[byte] >> bit)); + } else if (bit + bits <= 16) { + return (uint16_t) (((1 << bits) - 1) & ((self->buf[byte] | (self->buf[byte+1] << 8)) >> bit)); + } else if (bit + bits <= 24) { + return (uint16_t) (((1 << bits) - 1) & ((self->buf[byte] | (self->buf[byte+1] << 8) | (self->buf[byte+2] << 16)) >> bit)); + } else { + return (uint16_t) -1; + } +} + +static const struct tans_bit_reader_ops vtable = { + .read = tans_buf_bit_reader_read, +}; + +void tans_buf_bit_reader_init(struct tans_buf_bit_reader *self, const uint8_t *buf, uint32_t len) +{ + self->vtable = &vtable; + self->bit = 0; + self->len = len; + self->buf = buf; +} diff --git a/src/tans_buf_bit_reader.h b/src/tans_buf_bit_reader.h new file mode 100644 index 0000000..71d7d07 --- /dev/null +++ b/src/tans_buf_bit_reader.h @@ -0,0 +1,12 @@ +#pragma once + +#include "tans_bit_reader.h" + +struct tans_buf_bit_reader { + const struct tans_bit_reader_ops *vtable; + uint32_t bit; + uint32_t len; + const uint8_t *buf; +}; + +void tans_buf_bit_reader_init(struct tans_buf_bit_reader *self, const uint8_t *buf, uint32_t len); diff --git a/src/tans_buf_bit_writer.c b/src/tans_buf_bit_writer.c new file mode 100644 index 0000000..20186a1 --- /dev/null +++ b/src/tans_buf_bit_writer.c @@ -0,0 +1,46 @@ +#include "tans_buf_bit_writer.h" + +static uint16_t tans_buf_bit_writer_write(struct tans_bit_writer *writer, uint16_t value, uint8_t bits) +{ + struct tans_buf_bit_writer *self = (struct tans_buf_bit_writer *) writer; + uint32_t bit = self->bit % 8; + uint32_t byte = self->bit / 8; + + if (bits == 0) { + return 0; + } + + if (self->bit + bits > self->len * 8) { + return (uint16_t) -1; + } + + self->bit += bits; + + if (bit + bits <= 8) { + self->buf[byte] |= (uint8_t) ((value & ((1 << bits) - 1)) << bit); + return bits; + } else if (bit + bits <= 16) { + self->buf[byte] |= (uint8_t) ((value << bit) & 0xff); + self->buf[byte+1] |= (uint8_t) ((value & ((1 << bits) - 1)) >> (8 - bit)); + return bits; + } else if (bit + bits <= 24) { + self->buf[byte] |= (uint8_t) ((value << bit) & 0xff); + self->buf[byte+1] |= (uint8_t) ((value >> (8 - bit)) & 0xff); + self->buf[byte+2] |= (uint8_t) ((value & ((1 << bits) - 1)) >> (16 - bit)); + return bits; + } else { + return (uint16_t) -1; + } +} + +static const struct tans_bit_writer_ops vtable = { + .write = tans_buf_bit_writer_write, +}; + +void tans_buf_bit_writer_init(struct tans_buf_bit_writer *self, uint8_t *buf, uint32_t len) +{ + self->vtable = &vtable; + self->bit = 0; + self->len = len; + self->buf = buf; +} diff --git a/src/tans_buf_bit_writer.h b/src/tans_buf_bit_writer.h new file mode 100644 index 0000000..20d1488 --- /dev/null +++ b/src/tans_buf_bit_writer.h @@ -0,0 +1,12 @@ +#pragma once + +#include "tans_bit_writer.h" + +struct tans_buf_bit_writer { + const struct tans_bit_writer_ops *vtable; + uint32_t bit; + uint32_t len; + uint8_t *buf; +}; + +void tans_buf_bit_writer_init(struct tans_buf_bit_writer *self, uint8_t *buf, uint32_t len); diff --git a/src/tans_constants.h b/src/tans_constants.h new file mode 100644 index 0000000..ea031f2 --- /dev/null +++ b/src/tans_constants.h @@ -0,0 +1,4 @@ +#pragma once + +#define TANS_R 10 +#define TANS_L (1 << TANS_R) diff --git a/src/tans_decode_st.c b/src/tans_decode_st.c new file mode 100644 index 0000000..c5077fc --- /dev/null +++ b/src/tans_decode_st.c @@ -0,0 +1,24 @@ +#include "tans_decode_st.h" + +void tans_decode_st_init(struct tans_decode_st *self, struct tans_symbol_tbl *symbol_tbl) +{ + tans_decode_tbl_init(&self->decode_tbl, symbol_tbl); + self->x = 0; +} + +uint16_t tans_decode_st_next(struct tans_decode_st *self, struct tans_bit_reader *bit_reader) +{ + uint8_t ret; + uint16_t read; + struct tans_decode_tbl_entry t = self->decode_tbl.entries[self->x]; + + read = bit_reader->vtable->read(bit_reader, t.nb_bits); + if (read == -1) { + return -1; + } + + ret = t.symbol; + self->x = t.new_x + read; + + return (uint16_t) ret; +} diff --git a/src/tans_decode_st.h b/src/tans_decode_st.h new file mode 100644 index 0000000..09165a8 --- /dev/null +++ b/src/tans_decode_st.h @@ -0,0 +1,12 @@ +#pragma once + +#include "tans_decode_tbl.h" +#include "tans_bit_reader.h" + +struct tans_decode_st { + struct tans_decode_tbl decode_tbl; + uint16_t x; +}; + +void tans_decode_st_init(struct tans_decode_st *self, struct tans_symbol_tbl *symbol_tbl); +uint16_t tans_decode_st_next(struct tans_decode_st *self, struct tans_bit_reader *bit_reader); diff --git a/src/tans_decode_tbl.c b/src/tans_decode_tbl.c new file mode 100644 index 0000000..e3feb24 --- /dev/null +++ b/src/tans_decode_tbl.c @@ -0,0 +1,17 @@ +#include "tans_decode_tbl.h" + +#include "floor_log2.h" + +void tans_decode_tbl_init(struct tans_decode_tbl *self, struct tans_symbol_tbl *symbol_tbl) +{ + uint16_t i; + uint16_t x; + uint8_t s; + + for (i = 0; i < TANS_L; ++i) { + s = self->entries[i].symbol = symbol_tbl->symbol[i]; + x = symbol_tbl->entries[s].next++; + self->entries[s].nb_bits = TANS_R - floor_log2(x); + self->entries[s].new_x = (x << self->entries[s].nb_bits) - TANS_L; + } +} diff --git a/src/tans_decode_tbl.h b/src/tans_decode_tbl.h new file mode 100644 index 0000000..e191176 --- /dev/null +++ b/src/tans_decode_tbl.h @@ -0,0 +1,15 @@ +#pragma once + +#include "tans_symbol_tbl.h" + +struct tans_decode_tbl_entry { + uint8_t symbol; + uint8_t nb_bits; + uint16_t new_x; +}; + +struct tans_decode_tbl { + struct tans_decode_tbl_entry entries[TANS_L]; +}; + +void tans_decode_tbl_init(struct tans_decode_tbl *self, struct tans_symbol_tbl *symbol_tbl); diff --git a/src/tans_encode_st.c b/src/tans_encode_st.c new file mode 100644 index 0000000..d6c7232 --- /dev/null +++ b/src/tans_encode_st.c @@ -0,0 +1,23 @@ +#include "tans_encode_st.h" + +void tans_encode_st_init(struct tans_encode_st *self, const struct tans_symbol_tbl *symbol_tbl) +{ + self->symbol_tbl = *symbol_tbl; + tans_encode_tbl_init(&self->encode_tbl, &self->symbol_tbl); + self->x = 0; +} + +uint16_t tans_encode_st_next(struct tans_encode_st *self, struct tans_bit_writer *bit_writer, uint8_t symbol) +{ + uint8_t nb_bits; + uint16_t written; + + nb_bits = (uint8_t) ((self->x + TANS_L + self->symbol_tbl.entries[symbol].nb) >> (TANS_R + 1)); + written = bit_writer->vtable->write(bit_writer, self->x + TANS_L, nb_bits); + if (written != nb_bits) { + return (uint16_t) -1; + } + self->x = self->encode_tbl.entries[self->symbol_tbl.entries[symbol].start + ((self->x + TANS_L) >> nb_bits)].x; + + return written; +} diff --git a/src/tans_encode_st.h b/src/tans_encode_st.h new file mode 100644 index 0000000..e31ef79 --- /dev/null +++ b/src/tans_encode_st.h @@ -0,0 +1,13 @@ +#pragma once + +#include "tans_encode_tbl.h" +#include "tans_bit_writer.h" + +struct tans_encode_st { + struct tans_symbol_tbl symbol_tbl; + struct tans_encode_tbl encode_tbl; + uint16_t x; +}; + +void tans_encode_st_init(struct tans_encode_st *self, const struct tans_symbol_tbl *symbol_tbl); +uint16_t tans_encode_st_next(struct tans_encode_st *self, struct tans_bit_writer *bit_writer, uint8_t symbol); diff --git a/src/tans_encode_tbl.c b/src/tans_encode_tbl.c new file mode 100644 index 0000000..a60ebdc --- /dev/null +++ b/src/tans_encode_tbl.c @@ -0,0 +1,12 @@ +#include "tans_encode_tbl.h" + +void tans_encode_tbl_init(struct tans_encode_tbl *self, struct tans_symbol_tbl *symbol_tbl) +{ + uint8_t s; + uint16_t x; + + for (x = TANS_L; x < TANS_L << 1; ++x) { + s = symbol_tbl->symbol[x-TANS_L]; + self->entries[symbol_tbl->entries[s].start + symbol_tbl->entries[s].next++].x = x - TANS_L; + } +} diff --git a/src/tans_encode_tbl.h b/src/tans_encode_tbl.h new file mode 100644 index 0000000..79ccf30 --- /dev/null +++ b/src/tans_encode_tbl.h @@ -0,0 +1,15 @@ +#pragma once + +#include "tans_constants.h" +#include "tans_symbol_tbl.h" + +struct tans_encode_tbl_entry { + uint16_t x; +}; + +struct tans_encode_tbl { + // TODO verify size of entries table + struct tans_encode_tbl_entry entries[TANS_L]; +}; + +void tans_encode_tbl_init(struct tans_encode_tbl *self, struct tans_symbol_tbl *symbol_tbl); diff --git a/src/tans_file_bit_reader.c b/src/tans_file_bit_reader.c new file mode 100644 index 0000000..fa79ddd --- /dev/null +++ b/src/tans_file_bit_reader.c @@ -0,0 +1,56 @@ +#include "tans_file_bit_reader.h" + +#include +#include +#include + +static uint16_t tans_file_bit_reader_read(struct tans_bit_reader *reader, uint8_t bits) +{ + struct tans_file_bit_reader *self = (struct tans_file_bit_reader *) reader; + ssize_t bytes_read; + uint32_t bit = self->bit % 8; + uint32_t byte = self->bit / 8; + + if (bits == 0) { + return (uint16_t) -1; + } + + while (self->len * 8 - self->bit < bits) { + memmove(self->buf, self->buf + byte, self->len - byte); + bytes_read = read(self->fd, self->buf + self->len, sizeof self->buf - self->len); + if (bytes_read <= 0) { + return (uint16_t) -1; + } + self->len += (uint32_t) bytes_read; + } + + self->bit += bits; + + if (bit + bits <= 8) { + return (uint16_t) (((1 << bits) - 1) & (self->buf[byte] >> bit)); + } else if (bit + bits <= 16) { + return (uint16_t) (((1 << bits) - 1) & ((self->buf[byte] >> bit) | (self->buf[byte+1] << (8 - bit)))); + } else if (bit + bits <= 24) { + return (uint16_t) (((1 << bits) - 1) & ((self->buf[byte] >> bit) | ((self->buf[byte+1] | (self->buf[byte+2] << 8)) << (8 - bit)))); + } else { + return (uint16_t) -1; + } +} + +static const struct tans_bit_reader_ops vtable = { + .read = tans_file_bit_reader_read, +}; + +int tans_file_bit_reader_init(struct tans_file_bit_reader *self, const char *filename) +{ + self->vtable = &vtable; + self->fd = open(filename, O_RDONLY | O_CLOEXEC); + self->bit = 0; + self->len = 0; + + if (self->fd == -1) { + return -1; + } + + return 0; +} diff --git a/src/tans_file_bit_reader.h b/src/tans_file_bit_reader.h new file mode 100644 index 0000000..4e29dc3 --- /dev/null +++ b/src/tans_file_bit_reader.h @@ -0,0 +1,15 @@ +#pragma once + +#include "tans_bit_reader.h" + +#define TANS_FILE_BIT_READER_BUFSZ 1024 + +struct tans_file_bit_reader { + const struct tans_bit_reader_ops *vtable; + int fd; + uint32_t bit; + uint32_t len; + uint8_t buf[TANS_FILE_BIT_READER_BUFSZ]; +}; + +int tans_file_bit_reader_init(struct tans_file_bit_reader *self, const char *filename); diff --git a/src/tans_freq_tbl.h b/src/tans_freq_tbl.h new file mode 100644 index 0000000..d2ff754 --- /dev/null +++ b/src/tans_freq_tbl.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +struct tans_freq_tbl { + uint16_t freq[256]; +}; diff --git a/src/tans_symbol_tbl.c b/src/tans_symbol_tbl.c new file mode 100644 index 0000000..a1237b9 --- /dev/null +++ b/src/tans_symbol_tbl.c @@ -0,0 +1,32 @@ +#include "tans_symbol_tbl.h" + +#include "floor_log2.h" + +int tans_symbol_tbl_init(struct tans_symbol_tbl *self, const struct tans_freq_tbl *freq_tbl) +{ + uint16_t x, step, s, i, start, freq, k; + + x = 0; + step = TANS_L*5/8 + 3; + start = 0; + + for (s = 0; s < 256; ++s) { + freq = freq_tbl->freq[s]; + self->entries[s].start = start; + self->entries[s].next = freq; + k = TANS_R - floor_log2(freq); + self->entries[s].nb = (uint16_t) ((k << (TANS_R + 1)) - (freq << k)); + start += freq; + for (i = 0; i < freq; ++i) { + self->symbol[x] = (uint8_t) s; + x += step; + x %= TANS_L; + } + } + + if (start != TANS_L) { // freq entries must add up to TANS_L + return -1; + } + + return 0; +} diff --git a/src/tans_symbol_tbl.h b/src/tans_symbol_tbl.h new file mode 100644 index 0000000..985928c --- /dev/null +++ b/src/tans_symbol_tbl.h @@ -0,0 +1,17 @@ +#pragma once + +#include "tans_constants.h" +#include "tans_freq_tbl.h" + +struct tans_symbol_tbl_entry { + uint16_t nb; + uint16_t start; + uint16_t next; +}; + +struct tans_symbol_tbl { + uint8_t symbol[TANS_L]; + struct tans_symbol_tbl_entry entries[256]; +}; + +int tans_symbol_tbl_init(struct tans_symbol_tbl *self, const struct tans_freq_tbl *freq_tbl); diff --git a/test/test.h b/test/test.h new file mode 100644 index 0000000..d9888ea --- /dev/null +++ b/test/test.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +enum test_result { + TEST_SUCCESS = 0x100, + TEST_SKIP = 0x101, + TEST_FAILURE = 0x102, +}; + +#define ASSERT_EQ(lhs, rhs) do { \ + long a = (long) (lhs), b = (long) (rhs); \ + if ((a) != (b)) { \ + printf("ERROR: " #lhs " (%ld) != " #rhs " (%ld)\n", (a), (b)); \ + return TEST_FAILURE; \ + } \ + } while(0) + +#define ASSERT_NE(lhs, rhs) do { \ + long a = (long) (lhs), b = (long) (rhs); \ + if ((a) == (b)) { \ + printf("ERROR: " #lhs " (%ld) == " #rhs " (%ld)\n", (a), (b)); \ + return TEST_FAILURE; \ + } \ + } while(0) + +#define RUN_TEST(test_fn) switch (test_fn()) { \ + case TEST_SUCCESS: printf("PASS: " #test_fn "\n"); break; \ + case TEST_SKIP: printf("SKIP: " #test_fn "\n"); break; \ + case TEST_FAILURE: printf("FAIL: " #test_fn "\n"); return 1; \ + default: printf("FAIL: " #test_fn "\n"); return 1; \ +} + diff --git a/test/test_tans_bit_reader b/test/test_tans_bit_reader new file mode 100755 index 0000000..1f43ac2 Binary files /dev/null and b/test/test_tans_bit_reader differ diff --git a/test/test_tans_bit_reader.c b/test/test_tans_bit_reader.c new file mode 100644 index 0000000..f94a931 --- /dev/null +++ b/test/test_tans_bit_reader.c @@ -0,0 +1,49 @@ +#include "test.h" + +#include "tans_buf_bit_reader.h" +#include "tans_file_bit_reader.h" + +enum test_result test_tans_buf_bit_reader(void) +{ + struct tans_buf_bit_reader bit_reader; + uint8_t buf[8] = {0x01, 0xff, 0x02, 0xfe, 0x03, 0xfd, 0x08, 0xfc}; + + tans_buf_bit_reader_init(&bit_reader, buf, sizeof buf); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 0), (uint16_t) -1); + + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 8), 1); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 4), 0xf); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 6), 0x2f); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 2), 0); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 16), 0x3fe0); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 8), 0xd0); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 7), 0x0f); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 1), 1); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 3), 0); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 5), 0x18); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 4), 0xf); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 1), (uint16_t) -1); + + return TEST_SUCCESS; +} + +enum test_result test_tans_file_bit_reader(void) +{ + struct tans_file_bit_reader bit_reader; + uint8_t bits; + + ASSERT_EQ(tans_file_bit_reader_init(&bit_reader, "/dev/zero"), 0); + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, 0), (uint16_t) -1); + + for (bits = 1; bits <= 16; ++bits) { + ASSERT_EQ(bit_reader.vtable->read((struct tans_bit_reader *) &bit_reader, bits), 0); + } + + return TEST_SUCCESS; +} + +int main(void) +{ + RUN_TEST(test_tans_buf_bit_reader); + RUN_TEST(test_tans_file_bit_reader); +} diff --git a/test/test_tans_bit_writer b/test/test_tans_bit_writer new file mode 100755 index 0000000..e8fe9ba Binary files /dev/null and b/test/test_tans_bit_writer differ diff --git a/test/test_tans_bit_writer.c b/test/test_tans_bit_writer.c new file mode 100644 index 0000000..b31177b --- /dev/null +++ b/test/test_tans_bit_writer.c @@ -0,0 +1,42 @@ +#include "test.h" + +#include "tans_buf_bit_writer.h" + +enum test_result test_tans_buf_bit_writer(void) +{ + struct tans_buf_bit_writer buf_bit_writer; + struct tans_bit_writer *bit_writer = (struct tans_bit_writer *) &buf_bit_writer; + uint8_t buf[8] = {0}; + + tans_buf_bit_writer_init(&buf_bit_writer, buf, sizeof buf); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0, 0), 0); + + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 1, 8), 8); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0xf, 4), 4); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0x2f, 6), 6); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0, 2), 2); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0x3fe0, 16), 16); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0xd0, 8), 8); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0x0f, 7), 7); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 1, 1), 1); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0, 3), 3); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0x18, 5), 5); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0xf, 4), 4); + ASSERT_EQ(bit_writer->vtable->write(bit_writer, 0, 1), (uint16_t) -1); + + ASSERT_EQ(buf[0], 0x01); + ASSERT_EQ(buf[1], 0xff); + ASSERT_EQ(buf[2], 0x02); + ASSERT_EQ(buf[3], 0xfe); + ASSERT_EQ(buf[4], 0x03); + ASSERT_EQ(buf[5], 0xfd); + ASSERT_EQ(buf[6], 0x08); + ASSERT_EQ(buf[7], 0xfc); + + return TEST_SUCCESS; +} + +int main(void) +{ + RUN_TEST(test_tans_buf_bit_writer); +} diff --git a/test/test_tans_encode_st b/test/test_tans_encode_st new file mode 100755 index 0000000..5721161 Binary files /dev/null and b/test/test_tans_encode_st differ diff --git a/test/test_tans_encode_st.c b/test/test_tans_encode_st.c new file mode 100644 index 0000000..a7bb884 --- /dev/null +++ b/test/test_tans_encode_st.c @@ -0,0 +1,37 @@ +#include "test.h" + +#include "tans_buf_bit_writer.h" +#include "tans_encode_st.h" + +enum test_result test_tans_encode_st_equal_freq(void) +{ + struct tans_freq_tbl freq_tbl; + struct tans_symbol_tbl symbol_tbl; + struct tans_encode_st encode_st; + struct tans_buf_bit_writer buf_bit_writer; + struct tans_bit_writer *bit_writer = (struct tans_bit_writer *) &buf_bit_writer; + uint8_t data[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; + uint8_t buf[8] = {0}; + uint16_t i; + + for (i = 0; i < 256; ++i) { + freq_tbl.freq[i] = TANS_L / 256; + } + ASSERT_EQ(tans_symbol_tbl_init(&symbol_tbl, &freq_tbl), 0); + tans_encode_st_init(&encode_st, &symbol_tbl); + tans_buf_bit_writer_init(&buf_bit_writer, buf, sizeof buf); + + for (i = 0; i < sizeof data; ++i) { + ASSERT_NE(tans_encode_st_next(&encode_st, bit_writer, data[i]), (uint16_t) -1); + } + + ASSERT_EQ(buf_bit_writer.bit, buf_bit_writer.len * 8); + ASSERT_EQ(tans_encode_st_next(&encode_st, bit_writer, 0), (uint16_t) -1); + + return TEST_SUCCESS; +} + +int main(void) +{ + RUN_TEST(test_tans_encode_st_equal_freq); +}