From 3f21caa35b2088459b6eedc443d17db3d3349828 Mon Sep 17 00:00:00 2001 From: Ziver Koc Date: Wed, 11 May 2016 17:11:18 +0200 Subject: [PATCH] Impl variable length binary struct. Data will now be shifted to the correct possitions --- src/zutil/ByteUtil.java | 58 ++++++++++++++----- src/zutil/converter/Converter.java | 22 ++----- src/zutil/parser/binary/BinaryFieldData.java | 2 +- .../binary/BinaryStructInputStream.java | 15 +++-- test/zutil/ByteUtilTest.java | 17 ++++++ test/zutil/converter/ConverterTest.java | 6 +- .../binary/BinaryStructInputStreamTest.java | 2 +- 7 files changed, 77 insertions(+), 45 deletions(-) diff --git a/src/zutil/ByteUtil.java b/src/zutil/ByteUtil.java index 6a1d807..8c0908f 100755 --- a/src/zutil/ByteUtil.java +++ b/src/zutil/ByteUtil.java @@ -45,21 +45,7 @@ public class ByteUtil { }; /** - * Creates a new sub byte from index and with a length and shifts the data to the left - * - * @param data is the byte data - * @param index is the bit index, valid values 0-7 - * @param length is the length of bits to return, valid values 1-8 - * @return a new byte containing a sub byte defined by the index and length - */ - public static byte getShiftedBits(byte data, int index, int length){ - int ret = 0xFF & getBits(data, index, length); - ret = ret >>> index+1-length; - return (byte) ret; - } - - /** - * Creates a new sub byte from index and with the given length length + * Creates a new sub byte from MSB to the given length * * @param data is the byte data * @param length is the length of bits to return, valid values 1-8 @@ -83,7 +69,21 @@ public class ByteUtil { } /** - * Creates a new sub byte array with only the given length of bits from the data array. + * Creates a new sub byte from index and with a length and shifts the data to the left + * + * @param data is the byte data + * @param index is the bit index, valid values 0-7 + * @param length is the length of bits to return, valid values 1-8 + * @return a new byte containing a sub byte defined by the index and length + */ + public static byte getShiftedBits(byte data, int index, int length){ + int ret = 0xFF & getBits(data, index, length); + ret = ret >>> index+1-length; + return (byte) ret; + } + + /** + * Creates a new sub byte array with only the given length of bits from the LSB. * * @param data is the byte data array * @param length is the length of bits to return @@ -127,6 +127,32 @@ public class ByteUtil { return (byte) BYTE_MASK[index][length]; } + + /** + * Shifts a whole byte array to the left by the specified amount. + * + * @param data the array to be shifted + * @param shiftBy the amount to shift. Currently only supports maximum value of 8 + * @return same data reference as the data input + */ + public static byte[] shiftLeft(byte[] data, int shiftBy) { + if(0 > shiftBy || shiftBy > 8) + throw new IllegalArgumentException("Invalid shiftBy argument, allowed values: 0-8"); + if (shiftBy == 0) + return data; + + byte rest = 0; + for (int i=0; i>>= shiftBy; + if(i != 0) + data[i-1] |= rest; + } + + return data; + } + + /** * Presents a binary array in HEX and ASCII * diff --git a/src/zutil/converter/Converter.java b/src/zutil/converter/Converter.java index 2c855a2..bb6ce98 100755 --- a/src/zutil/converter/Converter.java +++ b/src/zutil/converter/Converter.java @@ -361,24 +361,10 @@ public class Converter { int i = 0; switch (b.length){ default: - case 4: - i |= 0xFF000000 & (b[0] << 24); - i |= 0x00FF0000 & (b[1] << 16); - i |= 0x0000FF00 & (b[2] << 8); - i |= 0x000000FF & b[3]; - break; - case 3: - i |= 0x00FF0000 & (b[0] << 16); - i |= 0x0000FF00 & (b[1] << 8); - i |= 0x000000FF & b[2]; - break; - case 2: - i |= 0x0000FF00 & (b[0] << 8); - i |= 0x000000FF & b[1]; - break; - case 1: - i |= 0x000000FF & b[0]; - break; + case 4: i |= 0xFF000000 & (b[3] << 24); + case 3: i |= 0x00FF0000 & (b[2] << 16); + case 2: i |= 0x0000FF00 & (b[1] << 8); + case 1: i |= 0x000000FF & b[0]; case 0: break; } return i; diff --git a/src/zutil/parser/binary/BinaryFieldData.java b/src/zutil/parser/binary/BinaryFieldData.java index 278a808..e363418 100755 --- a/src/zutil/parser/binary/BinaryFieldData.java +++ b/src/zutil/parser/binary/BinaryFieldData.java @@ -95,7 +95,7 @@ public class BinaryFieldData { else if (field.getType() == Integer.class || field.getType() == int.class) field.set(obj, Converter.toInt(data)); else if (field.getType() == String.class) - field.set(obj, new String(data, StandardCharsets.ISO_8859_1)); + field.set(obj, new String(ByteUtil.getReverseByteOrder(data), StandardCharsets.ISO_8859_1)); else throw new UnsupportedOperationException("Unsupported BinaryStruct field class: "+ field.getClass()); } catch (IllegalAccessException e){ diff --git a/src/zutil/parser/binary/BinaryStructInputStream.java b/src/zutil/parser/binary/BinaryStructInputStream.java index 798b482..a90f86c 100755 --- a/src/zutil/parser/binary/BinaryStructInputStream.java +++ b/src/zutil/parser/binary/BinaryStructInputStream.java @@ -77,20 +77,23 @@ public class BinaryStructInputStream { } else { byte[] valueData = new byte[(int) Math.ceil(field.getBitLength(struct) / 8.0)]; - int fieldReadLength = 0; + int fieldReadLength = 0; // How much we have read so far + int shiftBy = (dataBitIndex+1 + field.getBitLength(struct)) % 8; + // Parse value - for (int valueDataIndex = 0; valueDataIndex < valueData.length; ++valueDataIndex) { + for (int valueDataIndex=valueData.length-1; valueDataIndex >= 0 ; --valueDataIndex) { if (dataBitIndex < 0) { // Read new data? data = (byte) in.read(); dataBitIndex = 7; } - int bitLength = Math.min(dataBitIndex + 1, field.getBitLength(struct) - fieldReadLength); - valueData[valueDataIndex] = ByteUtil.getShiftedBits(data, dataBitIndex, bitLength); - fieldReadLength += bitLength; - dataBitIndex -= bitLength; + int subBitLength = Math.min(dataBitIndex + 1, field.getBitLength(struct) - fieldReadLength); + valueData[valueDataIndex] = ByteUtil.getBits(data, dataBitIndex, subBitLength); + fieldReadLength += subBitLength; + dataBitIndex -= subBitLength; } // Set value + ByteUtil.shiftLeft(valueData, shiftBy); // shift data so that LSB is at the beginning field.setByteValue(struct, valueData); totalReadLength += fieldReadLength; } diff --git a/test/zutil/ByteUtilTest.java b/test/zutil/ByteUtilTest.java index fe4202e..bf3d516 100755 --- a/test/zutil/ByteUtilTest.java +++ b/test/zutil/ByteUtilTest.java @@ -99,4 +99,21 @@ public class ByteUtilTest { "024 00 00 00 00 00 00 00 00 '........'", ByteUtil.toFormattedString(data3)); } + + + @Test + public void shiftLeft(){ + assertArrayEquals( new byte[]{}, + ByteUtil.shiftLeft(new byte[]{}, 4)); + assertArrayEquals( new byte[]{0b0000_0001}, + ByteUtil.shiftLeft(new byte[]{0b0000_0001}, 0)); + assertArrayEquals( new byte[]{0b0000_0001}, + ByteUtil.shiftLeft(new byte[]{0b0001_0000}, 4)); + assertArrayEquals( new byte[]{0b0001_0001, 0b0000_0000}, + ByteUtil.shiftLeft(new byte[]{0b0001_0000, 0b0000_0001}, 4)); + assertArrayEquals( new byte[]{0b0100_1001, 0b0000_0001}, + ByteUtil.shiftLeft(new byte[]{0b0111_1111, 0b0101_0010}, 6)); + assertArrayEquals( new byte[]{0b0000_0001,0b0000_0001,0b0000_0001,0b0000_0001}, + ByteUtil.shiftLeft(new byte[]{0b0001_0000,0b0001_0000,0b0001_0000,0b0001_0000}, 4)); + } } diff --git a/test/zutil/converter/ConverterTest.java b/test/zutil/converter/ConverterTest.java index 7aed9a3..5d25d2f 100755 --- a/test/zutil/converter/ConverterTest.java +++ b/test/zutil/converter/ConverterTest.java @@ -84,11 +84,11 @@ public class ConverterTest { public void byteArrayToInt(){ assertEquals(0, Converter.toInt(new byte[]{})); assertEquals(1, Converter.toInt(new byte[]{0b0000_0001})); - assertEquals(1, Converter.toInt(new byte[]{0x00,0x01})); + assertEquals(1, Converter.toInt(new byte[]{0x01,0x00})); assertEquals(256, Converter.toInt(new byte[]{0x00,0x01,0x00})); assertEquals(-1, Converter.toInt(new byte[]{(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF})); - assertEquals(Integer.MAX_VALUE, Converter.toInt(new byte[]{(byte)0x7F,(byte)0xFF,(byte)0xFF,(byte)0xFF})); - assertEquals(Integer.MAX_VALUE, Converter.toInt(new byte[]{(byte)0x7F,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF})); + assertEquals(Integer.MAX_VALUE, Converter.toInt(new byte[]{(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x7F})); + assertEquals(Integer.MAX_VALUE, Converter.toInt(new byte[]{(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0x7F, (byte)0xFF,(byte)0xFF})); } @Test diff --git a/test/zutil/parser/binary/BinaryStructInputStreamTest.java b/test/zutil/parser/binary/BinaryStructInputStreamTest.java index 2e585da..44a8f68 100755 --- a/test/zutil/parser/binary/BinaryStructInputStreamTest.java +++ b/test/zutil/parser/binary/BinaryStructInputStreamTest.java @@ -112,7 +112,7 @@ public class BinaryStructInputStreamTest { } // TODO: add full non lined length support - // @Test + @Test public void nonLinedLength2(){ BinaryTestStruct struct = new BinaryTestStruct() { @BinaryField(index=1, length=12)