return shiftBitsToLSB(bytes, numBits);
}
- // Setters
- // data: array where data will be stored
- // input: the data that need to be stored in the data array
- // startOffset: bit from where to start writing
- // numBits: number of bits to read
-
/**
- * Bits are expected to be stored in the input byte array from LSB.
+ * Store a byte in {@code data}, starting at {@code startOffset} (in bits from MSB).
*
* @param data
* to set the input byte
* byte to be inserted
* @param startOffset
* offset of data[] to start inserting byte from
- * @param numBits
- * number of bits of input to be inserted into data[]
- *
* @throws BufferException
* when the input, startOffset and numBits are not congruent
* with the data buffer size
*/
- public static void setByte(final byte[] data, final byte input, final int startOffset, final int numBits)
+ static void setByte(final byte[] data, final byte input, final int startOffset)
throws BufferException {
- byte[] inputByteArray = new byte[1];
- Arrays.fill(inputByteArray, 0, 1, input);
- setBytes(data, inputByteArray, startOffset, numBits);
+ copyBitsFromLsb(data, new byte[] { input }, startOffset, Byte.SIZE);
}
/**
* @throws BufferException
* when the startOffset and numBits parameters are not congruent
* with data and input buffers' size
+ * @deprecated Use {@link #copyBitsFromLsb(byte[], byte[], int, int)} instead.
*/
+ @Deprecated
public static void setBytes(final byte[] data, final byte[] input, final int startOffset, final int numBits)
throws BufferException {
- checkExceptions(data, startOffset, numBits);
- insertBits(data, input, startOffset, numBits);
+ copyBitsFromLsb(data, input, startOffset, numBits);
+ }
+
+ /**
+ * Copy {@code count} bits from {@code src} to {@code dest}, starting at {@code startOffset} in {@code dest}.
+ * Bits are copied from the low end of the source.
+ *
+ * @param dest The destination byte array.
+ * @param src The source byte array.
+ * @param startOffset The source offset (in bits, counted from the MSB) in the destination byte array.
+ * @param count The number of bits to copy.
+ *
+ * @throws BufferException if the destination byte array can't fit the requested number of bits at the requested
+ * position.
+ */
+ static void copyBitsFromLsb(final byte[] dest, final byte[] src, final int startOffset, final int count)
+ throws BufferException {
+ checkExceptions(dest, startOffset, count);
+ copyBits(src, dest, count, src.length * Byte.SIZE - count, startOffset);
+ }
+
+ /**
+ * Copy {@code count} bits from {@code src} to {@code dest}, starting at {@code startOffset} in {@code dest}.
+ * Bits are copied from the low end of the source.
+ *
+ * @param dest The destination byte array.
+ * @param src The source byte array.
+ * @param startOffset The source offset (in bits, counted from the MSB) in the destination byte array.
+ * @param count The number of bits to copy.
+ *
+ * @throws BufferException if the destination byte array can't fit the requested number of bits at the requested
+ * position.
+ */
+ static void copyBitsFromMsb(final byte[] dest, final byte[] src, final int startOffset, final int count)
+ throws BufferException {
+ checkExceptions(dest, startOffset, count);
+ copyBits(src, dest, count, 0, startOffset);
+ }
+
+ private static void copyBits(byte[] src, byte[] dest, int count, int srcBitIndex, int destBitIndex) {
+ int bitsRemaining = count;
+ while (bitsRemaining > 0) {
+ // How many bits can we, and do we need to, write, this time round?
+ int bitsToCopy = bitsRemaining % Byte.SIZE;
+ if (bitsToCopy == 0) {
+ bitsToCopy = Byte.SIZE;
+ }
+ int targetByteIndex = destBitIndex / Byte.SIZE;
+ int targetBitIndexInByte = destBitIndex % Byte.SIZE;
+ if (targetBitIndexInByte > 0 && (Byte.SIZE - targetBitIndexInByte) < bitsToCopy) {
+ // We can't write that many bits
+ bitsToCopy = Byte.SIZE - targetBitIndexInByte;
+ }
+ int sourceByteIndex = srcBitIndex / Byte.SIZE;
+ int sourceBitIndexInByte = srcBitIndex % Byte.SIZE;
+ if (sourceBitIndexInByte > 0 && (Byte.SIZE - sourceBitIndexInByte) < bitsToCopy) {
+ // We can't read that many bits
+ bitsToCopy = Byte.SIZE - sourceBitIndexInByte;
+ }
+
+ // Check the indexes
+ if (sourceByteIndex >= src.length || targetByteIndex >= dest.length) {
+ break;
+ }
+
+ if (bitsToCopy == Byte.SIZE) {
+ // Fast path
+ dest[targetByteIndex] = src[sourceByteIndex];
+ } else {
+ // We need to mask and shift
+ // Read the target *byte* and keep the bits we're not going to touch
+ byte targetMask = 0;
+ int sourceShift = 0;
+ if (targetBitIndexInByte > 0) {
+ targetMask |= getMSBMask(targetBitIndexInByte);
+ }
+ if (targetBitIndexInByte + bitsToCopy < Byte.SIZE) {
+ targetMask |= getLSBMask(Byte.SIZE - (targetBitIndexInByte + bitsToCopy));
+ // We'll need to shift left
+ sourceShift = Byte.SIZE - (targetBitIndexInByte + bitsToCopy);
+ }
+ final byte target = (byte) (dest[targetByteIndex] & targetMask);
+
+ // Read the source *byte* and keep the bits we need
+ byte sourceMask = -1;
+ if (sourceBitIndexInByte > 0) {
+ sourceMask &= ~getMSBMask(sourceBitIndexInByte);
+ }
+ if (sourceBitIndexInByte + bitsToCopy < Byte.SIZE) {
+ sourceMask &= ~getLSBMask(Byte.SIZE - (sourceBitIndexInByte + bitsToCopy));
+ // We'll need to shift right
+ sourceShift -= Byte.SIZE - (sourceBitIndexInByte + bitsToCopy);
+ }
+ byte source = (byte) (src[sourceByteIndex] & sourceMask);
+ if (sourceShift < 0) {
+ source = (byte) ((source & 0xFF) >>> -sourceShift);
+ } else if (sourceShift > 0) {
+ source <<= sourceShift;
+ }
+
+ // All good, copy
+ dest[targetByteIndex] = (byte) (target | source);
+ }
+
+ // All done, update indexes
+ bitsRemaining -= bitsToCopy;
+ srcBitIndex += bitsToCopy;
+ destBitIndex += bitsToCopy;
+ }
}
/**
return shiftedBytes;
}
- /**
- * Insert in the data buffer at position dictated by the offset the number
- * of bits specified from the input data byte array. The input byte array
- * has the bits stored starting from the LSB
- */
- public static void insertBits(final byte[] data, final byte[] inputdataLSB, final int startOffset,
- final int numBits) {
- byte[] inputdata = shiftBitsToMSB(inputdataLSB, numBits); // Align to
- // MSB the
- // passed
- // byte
- // array
- int numBytes = numBits / NetUtils.NUM_BITS_IN_A_BYTE;
- int startByteOffset = startOffset / NetUtils.NUM_BITS_IN_A_BYTE;
- int extraOffsetBits = startOffset % NetUtils.NUM_BITS_IN_A_BYTE;
- int extranumBits = numBits % NetUtils.NUM_BITS_IN_A_BYTE;
- int restBits = numBits % NetUtils.NUM_BITS_IN_A_BYTE;
- int inputMSBbits;
- int inputLSBbits = 0;
-
- if (numBits == 0) {
- return;
- }
-
- if (extraOffsetBits == 0) {
- if (extranumBits == 0) {
- numBytes = numBits / NetUtils.NUM_BITS_IN_A_BYTE;
- System.arraycopy(inputdata, 0, data, startByteOffset, numBytes);
- } else {
- System.arraycopy(inputdata, 0, data, startByteOffset, numBytes);
- data[startByteOffset + numBytes] = (byte) (data[startByteOffset + numBytes]
- | inputdata[numBytes] & getMSBMask(extranumBits));
- }
- } else {
- int index;
- for (index = 0; index < numBytes; index++) {
- if (index != 0) {
- inputLSBbits = inputdata[index - 1] & getLSBMask(extraOffsetBits);
- }
- inputMSBbits = (byte) (inputdata[index] & getMSBMask(NetUtils.NUM_BITS_IN_A_BYTE - extraOffsetBits));
- inputMSBbits = inputMSBbits >= 0 ? inputMSBbits : inputMSBbits + 256;
- data[startByteOffset + index] = (byte) (data[startByteOffset + index]
- | inputLSBbits << NetUtils.NUM_BITS_IN_A_BYTE - extraOffsetBits
- | inputMSBbits >> extraOffsetBits);
- inputMSBbits = inputLSBbits = 0;
- }
- if (restBits < NetUtils.NUM_BITS_IN_A_BYTE - extraOffsetBits) {
- if (numBytes != 0) {
- inputLSBbits = inputdata[index - 1] & getLSBMask(extraOffsetBits);
- }
- inputMSBbits = (byte) (inputdata[index] & getMSBMask(restBits));
- inputMSBbits = inputMSBbits >= 0 ? inputMSBbits : inputMSBbits + 256;
- data[startByteOffset + index] = (byte) (data[startByteOffset + index]
- | inputLSBbits << NetUtils.NUM_BITS_IN_A_BYTE - extraOffsetBits
- | inputMSBbits >> extraOffsetBits);
- } else if (restBits == NetUtils.NUM_BITS_IN_A_BYTE - extraOffsetBits) {
- if (numBytes != 0) {
- inputLSBbits = inputdata[index - 1] & getLSBMask(extraOffsetBits);
- }
- inputMSBbits = (byte) (inputdata[index] & getMSBMask(NetUtils.NUM_BITS_IN_A_BYTE - extraOffsetBits));
- inputMSBbits = inputMSBbits >= 0 ? inputMSBbits : inputMSBbits + 256;
- data[startByteOffset + index] = (byte) (data[startByteOffset + index]
- | inputLSBbits << NetUtils.NUM_BITS_IN_A_BYTE - extraOffsetBits
- | inputMSBbits >> extraOffsetBits);
- } else {
- if (numBytes != 0) {
- inputLSBbits = inputdata[index - 1] & getLSBMask(extraOffsetBits);
- }
- inputMSBbits = (byte) (inputdata[index] & getMSBMask(NetUtils.NUM_BITS_IN_A_BYTE - extraOffsetBits));
- inputMSBbits = inputMSBbits >= 0 ? inputMSBbits : inputMSBbits + 256;
- data[startByteOffset + index] = (byte) (data[startByteOffset + index]
- | inputLSBbits << NetUtils.NUM_BITS_IN_A_BYTE - extraOffsetBits
- | inputMSBbits >> extraOffsetBits);
-
- inputLSBbits = inputdata[index]
- & getLSBMask(restBits - (NetUtils.NUM_BITS_IN_A_BYTE - extraOffsetBits))
- << NetUtils.NUM_BITS_IN_A_BYTE
- - restBits;
- data[startByteOffset + index + 1] = (byte) (data[startByteOffset + index + 1]
- | inputLSBbits << NetUtils.NUM_BITS_IN_A_BYTE - extraOffsetBits);
- }
- }
- }
-
/**
* Checks for overflow and underflow exceptions.
*
package org.opendaylight.openflowplugin.libraries.liblldp;
import org.junit.Assert;
-import org.junit.Ignore;
import org.junit.Test;
public class BitBufferHelperTest {
byte[] data = new byte[20];
input = 125;
- BitBufferHelper.setByte(data, input, 0, Byte.SIZE);
+ BitBufferHelper.setByte(data, input, 0);
Assert.assertEquals(125, data[0]);
input = 109;
- BitBufferHelper.setByte(data, input, 152, Byte.SIZE);
+ BitBufferHelper.setByte(data, input, 152);
Assert.assertEquals(109, data[19]);
}
@Test
- public void testSetBytes() throws Exception {
- byte[] input = { 0, 1 };
- byte[] data = { 6, 0 };
+ public void testCopyBitsFromLsb() throws Exception {
+ byte[] input = { 0, 1 }; // 00000000 00000001
+ byte[] data = { 6, 0 }; // 00000110 00000000
- BitBufferHelper.setBytes(data, input, 7, 9);
+ BitBufferHelper.copyBitsFromLsb(data, input, 7, 9);
+ // Expecting 00000110 000000001
Assert.assertEquals(6, data[0]);
Assert.assertEquals(1, data[1]);
}
@Test
- @Ignore("Currently broken")
//INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} =
// [01001011] [01101110] [01101011] [10100000] [00001010] [00001100] [00100011] [01100100] [11111101] [01000001]*/
- public void testInsertBits() {
+ public void testCopyBitsFromMsb() throws BufferException {
//CASE 1: startOffset%8 == 0 && numBits%8 == 0
byte[] inputdata = { 75, 110, 107, 80, 10, 12, 35, 100, 125, 65 };
int startOffset;
byte[] data1 = new byte[2];
startOffset = 0;
numBits = 16;
- BitBufferHelper.insertBits(data1, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data1, inputdata, startOffset, numBits);
Assert.assertEquals(75, data1[0]);
Assert.assertEquals(110, data1[1]);
byte[] data2 = new byte[4];
startOffset = 0;
numBits = 32;
- BitBufferHelper.insertBits(data2, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data2, inputdata, startOffset, numBits);
Assert.assertEquals(75, data2[0]);
Assert.assertEquals(110, data2[1]);
Assert.assertEquals(107, data2[2]);
byte[] data10 = new byte[2];
startOffset = 0;
numBits = 13;
- BitBufferHelper.insertBits(data10, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data10, inputdata, startOffset, numBits);
Assert.assertEquals(75, data10[0]);
Assert.assertEquals(104, data10[1]);
byte[] data11 = new byte[4];
startOffset = 8;
numBits = 6;
- BitBufferHelper.insertBits(data11, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data11, inputdata, startOffset, numBits);
Assert.assertEquals(72, data11[1]);
// INPUT: {75, 110, 107, 80, 10, 12, 35, 100, 125, 65} =
byte[] data12 = new byte[4];
startOffset = 0;
numBits = 23;
- BitBufferHelper.insertBits(data12, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data12, inputdata, startOffset, numBits);
Assert.assertEquals(75, data12[0]);
Assert.assertEquals(110, data12[1]);
Assert.assertEquals(106, data12[2]);
byte[] data13 = new byte[4];
startOffset = 8;
numBits = 20;
- BitBufferHelper.insertBits(data13, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data13, inputdata, startOffset, numBits);
Assert.assertEquals(75, data13[1]);
Assert.assertEquals(110, data13[2]);
Assert.assertEquals(96, data13[3]);
byte[] data14 = new byte[4];
startOffset = 0;
numBits = 30;
- BitBufferHelper.insertBits(data14, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data14, inputdata, startOffset, numBits);
Assert.assertEquals(75, data14[0]);
Assert.assertEquals(110, data14[1]);
Assert.assertEquals(107, data14[2]);
byte[] data16 = new byte[5];
startOffset = 3;
numBits = 8;
- BitBufferHelper.insertBits(data16, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data16, inputdata, startOffset, numBits);
Assert.assertEquals(9, data16[0]);
Assert.assertEquals(96, data16[1]);
Assert.assertEquals(0, data16[2]);
startOffset = 3;
numBits = 16;
byte[] data17 = new byte[5];
- BitBufferHelper.insertBits(data17, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data17, inputdata, startOffset, numBits);
Assert.assertEquals(9, data17[0]);
Assert.assertEquals(109, data17[1]);
Assert.assertEquals(data17[2], -64);
byte[] inputdata3 = { 79, 110, 111 };
startOffset = 3;
numBits = 16;
- BitBufferHelper.insertBits(data18, inputdata3, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data18, inputdata3, startOffset, numBits);
Assert.assertEquals(9, data18[0]);
Assert.assertEquals(data18[1], -19);
Assert.assertEquals(data18[2], -64);
startOffset = 3;
numBits = 32;
byte[] data19 = new byte[5];
- BitBufferHelper.insertBits(data19, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data19, inputdata, startOffset, numBits);
Assert.assertEquals(9, data19[0]);
Assert.assertEquals(109, data19[1]);
Assert.assertEquals(data19[2], -51);
startOffset = 33;
numBits = 16;
byte[] data20 = new byte[7];
- BitBufferHelper.insertBits(data20, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data20, inputdata, startOffset, numBits);
Assert.assertEquals(37, data20[4]);
Assert.assertEquals(data20[5], -73);
Assert.assertEquals(0, data20[6]);
startOffset = 3;
numBits = 7;
byte[] data21 = new byte[7];
- BitBufferHelper.insertBits(data21, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data21, inputdata, startOffset, numBits);
Assert.assertEquals(9, data21[0]);
Assert.assertEquals(64, data21[1]);
Assert.assertEquals(0, data21[2]);
startOffset = 5;
numBits = 17;
byte[] data22 = new byte[7];
- BitBufferHelper.insertBits(data22, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data22, inputdata, startOffset, numBits);
Assert.assertEquals(2, data22[0]);
Assert.assertEquals(91, data22[1]);
Assert.assertEquals(112, data22[2]);
startOffset = 3;
numBits = 23;
byte[] data23 = new byte[7];
- BitBufferHelper.insertBits(data23, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data23, inputdata, startOffset, numBits);
Assert.assertEquals(9, data23[0]);
Assert.assertEquals(109, data23[1]);
Assert.assertEquals(data23[2], -51);
startOffset = 3;
numBits = 13;
byte[] data24 = new byte[7];
- BitBufferHelper.insertBits(data24, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data24, inputdata, startOffset, numBits);
Assert.assertEquals(9, data24[0]);
Assert.assertEquals(109, data24[1]);
Assert.assertEquals(0, data24[2]);
startOffset = 4;
numBits = 20;
byte[] data25 = new byte[7];
- BitBufferHelper.insertBits(data25, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data25, inputdata, startOffset, numBits);
Assert.assertEquals(4, data25[0]);
Assert.assertEquals(data25[1], -74);
Assert.assertEquals(data25[2], -26);
startOffset = 13;
numBits = 11;
byte[] data26 = new byte[7];
- BitBufferHelper.insertBits(data26, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data26, inputdata, startOffset, numBits);
Assert.assertEquals(0, data26[0]);
Assert.assertEquals(2, data26[1]);
Assert.assertEquals(91, data26[2]);
startOffset = 3;
numBits = 17;
byte[] data27 = new byte[7];
- BitBufferHelper.insertBits(data27, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data27, inputdata, startOffset, numBits);
Assert.assertEquals(9, data27[0]);
Assert.assertEquals(109, data27[1]);
Assert.assertEquals(data27[2], -64);
startOffset = 18;
numBits = 34;
byte[] data28 = new byte[7];
- BitBufferHelper.insertBits(data28, inputdata, startOffset, numBits);
+ BitBufferHelper.copyBitsFromMsb(data28, inputdata, startOffset, numBits);
Assert.assertEquals(0, data28[0]);
Assert.assertEquals(0, data28[1]);
Assert.assertEquals(18, data28[2]);
Assert.assertEquals(data28[4], -102);
Assert.assertEquals(data28[5], -44);
Assert.assertEquals(0, data28[6]);
-
}
@Test