// Copyright 2013 Thomas Müller // This file is part of MarMoT, which is licensed under GPLv3. package marmot.util; import marmot.core.Feature; public class Decoder { private int[] bytes_; private short byte_index_; private short bit_index_; private short total_byte_length; private short total_bit_index; public Decoder(Feature feature) { bytes_ = feature.getBytes(); total_bit_index = feature.getCurrentBitIndex(); total_byte_length = (short)(feature.getCurrentLength() - 1); } int decode(int bits) { if (byte_index_ > total_byte_length || (bit_index_ > total_bit_index && byte_index_ == total_byte_length)) return -1; int bits_read = 0; int value = 0; while (bits_read < bits) { int read_now = Math.min(Integer.SIZE - bit_index_, bits - bits_read); assert read_now > 0; if (byte_index_ > total_byte_length) { return -1; } int byte_value = bytes_[byte_index_]; byte_value >>= bit_index_; int mask = (2 << (read_now - 1)) - 1; int new_value = byte_value & mask; //System.err.format("new_value %s\n", Integer.toBinaryString(new_value)); new_value <<= bits_read; //System.err.format("new_value shifted %s %d\n", Integer.toBinaryString(new_value), new_value); //System.err.format("value %s %d\n", Integer.toBinaryString(value), value); value += new_value; //System.err.format("value %s %d\n", Integer.toBinaryString(value), value); bits_read += read_now; bit_index_ += read_now; if (bit_index_ > total_bit_index && byte_index_ == total_byte_length) { return -1; } if (bit_index_ == Integer.SIZE) { bit_index_ = 0; byte_index_ ++; } } return value; } public static void main(String[] args) { Encoder encoder = new Encoder(3); encoder.append(0, 1); encoder.append(0, 2); encoder.append(8, 5); encoder.append(65, 7); encoder.append(20, 7); encoder.append(14, 7); encoder.append(6, 7); encoder.append(5, 7); encoder.append(3, 7); encoder.append(16, 7); encoder.append(6, 7); Feature f = encoder.getFeature(); Decoder decoder = new Decoder(f); assert 0 == decoder.decode(1); assert 0 == decoder.decode(2); assert 8 == decoder.decode(5); assert 65 == decoder.decode(7); assert 20 == decoder.decode(7); assert 14 == decoder.decode(7); assert 6 == decoder.decode(7); assert 5 == decoder.decode(7); assert 3 == decoder.decode(7); assert 16 == decoder.decode(7); assert 6 == decoder.decode(7); assert -1 == decoder.decode(1); } public short getByteLength() { return byte_index_; } public short getBitIndex() { return bit_index_; } public short getTotalByteLength() { return total_byte_length; } public short getTotalBitIndex() { return total_bit_index; } }