Adding prefix{Ones,Zeros} to ImmutableByteSequence
Change-Id: Ibf8c0d1101d763729478fba5118ed9aa0f22ca50
diff --git a/utils/misc/src/main/java/org/onlab/util/ImmutableByteSequence.java b/utils/misc/src/main/java/org/onlab/util/ImmutableByteSequence.java
index 68ec0f8..07dda85 100644
--- a/utils/misc/src/main/java/org/onlab/util/ImmutableByteSequence.java
+++ b/utils/misc/src/main/java/org/onlab/util/ImmutableByteSequence.java
@@ -164,19 +164,18 @@
}
/**
- * Creates a new byte sequence of the given size where alla bits are 0.
+ * Creates a new byte sequence of the given size where all bits are 0.
*
* @param size number of bytes
* @return a new immutable byte sequence
*/
public static ImmutableByteSequence ofZeros(int size) {
- byte[] bytes = new byte[size];
- Arrays.fill(bytes, (byte) 0);
- return new ImmutableByteSequence(ByteBuffer.wrap(bytes));
+ // array is initialized to all 0's by default
+ return new ImmutableByteSequence(ByteBuffer.wrap(new byte[size]));
}
/**
- * Creates a new byte sequence of the given size where alla bits are 1.
+ * Creates a new byte sequence of the given size where all bits are 1.
*
* @param size number of bytes
* @return a new immutable byte sequence
@@ -188,6 +187,51 @@
}
/**
+ * Creates a new byte sequence that is prefixed with specified number of
+ * zeros if val = 0 or ones if val = 0xff.
+ *
+ * @param size number of total bytes
+ * @param prefixBits number of bits in prefix
+ * @param val 0 for prefix of zeros; 0xff for prefix of ones
+ * @return new immutable byte sequence
+ */
+ static ImmutableByteSequence prefix(int size, long prefixBits, byte val) {
+ checkArgument(val == 0 || val == (byte) 0xff, "Val must be 0 or 0xff");
+ byte[] bytes = new byte[size];
+ int prefixBytes = (int) (prefixBits / Byte.SIZE);
+ Arrays.fill(bytes, 0, prefixBytes, val);
+ Arrays.fill(bytes, prefixBytes, bytes.length, (byte) ~val);
+ int partialBits = (int) (prefixBits % Byte.SIZE);
+ if (partialBits != 0) {
+ bytes[prefixBytes] = val == 0 ?
+ (byte) (0xff >> partialBits) : (byte) (0xff << Byte.SIZE - partialBits);
+ }
+ return new ImmutableByteSequence(ByteBuffer.wrap(bytes));
+ }
+
+ /**
+ * Creates a new byte sequence that is prefixed with specified number of zeros.
+ *
+ * @param size number of total bytes
+ * @param prefixBits number of bits in prefix
+ * @return new immutable byte sequence
+ */
+ public static ImmutableByteSequence prefixZeros(int size, long prefixBits) {
+ return prefix(size, prefixBits, (byte) 0);
+ }
+
+ /**
+ * Creates a new byte sequence that is prefixed with specified number of ones.
+ *
+ * @param size number of total bytes
+ * @param prefixBits number of bits in prefix
+ * @return new immutable byte sequence
+ */
+ public static ImmutableByteSequence prefixOnes(int size, long prefixBits) {
+ return prefix(size, prefixBits, (byte) 0xff);
+ }
+
+ /**
* Returns a view of this sequence as a read-only {@link ByteBuffer}.
* <p>
* The returned buffer will have position 0, while limit and capacity will
diff --git a/utils/misc/src/test/java/org/onlab/util/ImmutableByteSequenceTest.java b/utils/misc/src/test/java/org/onlab/util/ImmutableByteSequenceTest.java
index 055f824..07aa40e 100644
--- a/utils/misc/src/test/java/org/onlab/util/ImmutableByteSequenceTest.java
+++ b/utils/misc/src/test/java/org/onlab/util/ImmutableByteSequenceTest.java
@@ -17,7 +17,9 @@
package org.onlab.util;
import com.google.common.testing.EqualsTester;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -28,6 +30,8 @@
import static org.hamcrest.Matchers.is;
public class ImmutableByteSequenceTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
@Test
public void testCopy() throws Exception {
@@ -115,4 +119,71 @@
ByteOrder.BIG_ENDIAN)
.testEquals();
}
+
+ @Test
+ public void testBitSetMethods() throws Exception {
+ // All zeros tests
+ assertThat("3 bytes, all 0's",
+ ImmutableByteSequence.ofZeros(3),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{0, 0, 0}))));
+ assertThat("3 bytes, all 0's via prefix",
+ ImmutableByteSequence.prefixZeros(3, 3 * Byte.SIZE),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{0, 0, 0}))));
+
+ // All ones tests
+ assertThat("3 bytes, all 1's",
+ ImmutableByteSequence.ofZeros(3),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{0, 0, 0}))));
+ assertThat("3 bytes, all 1's via prefix",
+ ImmutableByteSequence.prefixOnes(3, 3 * Byte.SIZE),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff}))));
+
+ // Zero prefix tests
+ assertThat("2 bytes, prefixed with 5 0's",
+ ImmutableByteSequence.prefix(2, 5, (byte) 0),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{(byte) 0x7, (byte) 0xff}))));
+ assertThat("4 bytes, prefixed with 16 0's",
+ ImmutableByteSequence.prefix(4, 16, (byte) 0),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{0, 0, (byte) 0xff, (byte) 0xff}))));
+ assertThat("4 bytes, prefixed with 20 0's",
+ ImmutableByteSequence.prefix(4, 20, (byte) 0),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{0, 0, (byte) 0x0f, (byte) 0xff}))));
+ assertThat("8 bytes, prefixed with 36 0's",
+ ImmutableByteSequence.prefixZeros(8, 38),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{0, 0, 0, 0, (byte) 0x03, (byte) 0xff, (byte) 0xff, (byte) 0xff}))));
+
+ // Ones prefix tests
+ assertThat("2 bytes, prefixed with 5 1's",
+ ImmutableByteSequence.prefix(2, 5, (byte) 0xff),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{(byte) 0xf8, 0}))));
+ assertThat("4 bytes, prefixed with 16 1's",
+ ImmutableByteSequence.prefix(4, 16, (byte) 0xff),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{(byte) 0xff, (byte) 0xff, 0, 0}))));
+ assertThat("4 bytes, prefixed with 20 1's",
+ ImmutableByteSequence.prefix(4, 20, (byte) 0xff),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xf0, 0}))));
+ assertThat("8 bytes, prefixed with 10 1's",
+ ImmutableByteSequence.prefixOnes(8, 10),
+ is(equalTo(ImmutableByteSequence.copyFrom(
+ new byte[]{(byte) 0xff, (byte) 0xc0, 0, 0, 0, 0, 0, 0}))));
+ }
+
+ @Test
+ public void testBadPrefixVal() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.reportMissingExceptionWithMessage(
+ "Expect IllegalArgumentException due to val = 0x7");
+ ImmutableByteSequence.prefix(5, 10, (byte) 0x7);
+ }
}
\ No newline at end of file