/* * Copyright (C) 2014 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY;https://www.hsr.ch/HSR-intern-Anmeldung.4409.0.html?&no_cache=1 without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include "bliss_huffman_coder.h" typedef struct private_bliss_huffman_coder_t private_bliss_huffman_coder_t; /** * Private data structure for bliss_huffman_coder_t object */ struct private_bliss_huffman_coder_t { /** * Public interface. */ bliss_huffman_coder_t public; /** * Bitpacker to write to or read from */ bliss_bitpacker_t *packer; /** * Huffman code table to be used */ bliss_huffman_code_t *code; /** * Maximum index into tuples table */ int index_max; /** * Number of encoded or decoded bits */ size_t bits; }; METHOD(bliss_huffman_coder_t, get_bits, size_t, private_bliss_huffman_coder_t *this) { return this->bits; } METHOD(bliss_huffman_coder_t, encode, bool, private_bliss_huffman_coder_t *this, int32_t z1, int16_t z2) { uint32_t code; uint16_t bits; int index; index = z1 * (2*this->code->n_z2 - 1) + z2 + this->code->n_z2 - 1; if (index >= this->index_max) { DBG1(DBG_LIB, "index exceeded in Huffman encoding table"); return FALSE; } code = this->code->tuples[index].code; bits = this->code->tuples[index].bits; if (!this->packer->write_bits(this->packer, code, bits)) { DBG1(DBG_LIB, "bitpacker exceeded its buffer"); return FALSE; } this->bits += bits; return TRUE; } METHOD(bliss_huffman_coder_t, decode, bool, private_bliss_huffman_coder_t *this, int32_t *z1, int16_t *z2) { bliss_huffman_code_node_t *node; uint32_t bit; node = this->code->nodes; while (node->tuple == BLISS_HUFFMAN_CODE_NO_TUPLE) { if (node->node_0 == BLISS_HUFFMAN_CODE_NO_NODE || node->node_1 == BLISS_HUFFMAN_CODE_NO_NODE) { DBG1(DBG_LIB, "error in Huffman decoding table"); return FALSE; } if (!this->packer->read_bits(this->packer, &bit, 1)) { DBG1(DBG_LIB, "bitpacker depleted its buffer"); return FALSE; } node = &this->code->nodes[bit ? node->node_1 : node->node_0]; this->bits++; } *z1 = node->tuple / (2*this->code->n_z2 - 1); *z2 = node->tuple - (2*this->code->n_z2 - 1) * (*z1) - this->code->n_z2 + 1; return TRUE; } METHOD(bliss_huffman_coder_t, destroy, void, private_bliss_huffman_coder_t *this) { free(this); } /** * See header. */ bliss_huffman_coder_t *bliss_huffman_coder_create(bliss_huffman_code_t *code, bliss_bitpacker_t *packer) { private_bliss_huffman_coder_t *this; INIT(this, .public = { .get_bits = _get_bits, .encode = _encode, .decode = _decode, .destroy = _destroy, }, .packer = packer, .code = code, .index_max = (2*code->n_z2 - 1) * code->n_z1, ); return &this->public; }