You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2022/05/27 15:19:55 UTC

[commons-lang] 01/03: Rewrite method to be the same as binaryToHexDigit but working from the end of the array backwards.

This is an automated email from the ASF dual-hosted git repository.

aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git

commit cf7c9522aa99d0d180e54ac5abe849f19d153d25
Author: Arturo Bernal <ar...@gmail.com>
AuthorDate: Thu Apr 7 10:48:49 2022 +0200

    Rewrite method to be the same as binaryToHexDigit but working from the end of the array backwards.
---
 .../java/org/apache/commons/lang3/Conversion.java  | 50 +++++++++++-----------
 .../org/apache/commons/lang3/ConversionTest.java   | 28 ++++++++++++
 2 files changed, 54 insertions(+), 24 deletions(-)

diff --git a/src/main/java/org/apache/commons/lang3/Conversion.java b/src/main/java/org/apache/commons/lang3/Conversion.java
index e71070131..47b1a5799 100644
--- a/src/main/java/org/apache/commons/lang3/Conversion.java
+++ b/src/main/java/org/apache/commons/lang3/Conversion.java
@@ -435,39 +435,41 @@ public class Conversion {
      * @return a hexadecimal digit representing the selected bits
      * @throws IllegalArgumentException if {@code src} is empty
      * @throws NullPointerException if {@code src} is {@code null}
+     * @throws IndexOutOfBoundsException if {@code srcPos} is outside the array.
      */
     public static char binaryBeMsb0ToHexDigit(boolean[] src, int srcPos) {
-        if (src.length == 0) {
-            throw new IllegalArgumentException("Cannot convert an empty array.");
-        }
-        final int beSrcPos = src.length - 1 - srcPos;
-        final int srcLen = Math.min(4, beSrcPos + 1);
-        final boolean[] paddedSrc = new boolean[4];
-        System.arraycopy(src, beSrcPos + 1 - srcLen, paddedSrc, 4 - srcLen, srcLen);
-        src = paddedSrc;
-        srcPos = 0;
-        if (src[srcPos]) {
-            if (src.length > srcPos + 1 && src[srcPos + 1]) {
-                if (src.length > srcPos + 2 && src[srcPos + 2]) {
-                    return src.length > srcPos + 3 && src[srcPos + 3] ? 'f' : 'e';
+        // JDK 9: Objects.checkIndex(int index, int length)
+        if (Integer.compareUnsigned(srcPos, src.length) >= 0) {
+            // Throw the correct exception
+            if (src.length == 0) {
+                throw new IllegalArgumentException("Cannot convert an empty array.");
+            }
+            throw new IndexOutOfBoundsException(srcPos + " is not within array length " + src.length);
+        }
+        // Little-endian bit 0 position
+        final int pos = src.length - 1 - srcPos;
+        if (3 <= pos && src[pos - 3]) {
+            if (src[pos - 2]) {
+                if (src[pos - 1]) {
+                    return src[pos] ? 'f' : 'e';
                 }
-                return src.length > srcPos + 3 && src[srcPos + 3] ? 'd' : 'c';
+                return src[pos] ? 'd' : 'c';
             }
-            if (src.length > srcPos + 2 && src[srcPos + 2]) {
-                return src.length > srcPos + 3 && src[srcPos + 3] ? 'b' : 'a';
+            if (src[pos - 1]) {
+                return src[pos] ? 'b' : 'a';
             }
-            return src.length > srcPos + 3 && src[srcPos + 3] ? '9' : '8';
+            return src[pos] ? '9' : '8';
         }
-        if (src.length > srcPos + 1 && src[srcPos + 1]) {
-            if (src.length > srcPos + 2 && src[srcPos + 2]) {
-                return src.length > srcPos + 3 && src[srcPos + 3] ? '7' : '6';
+        if (2 <= pos && src[pos - 2]) {
+            if (src[pos - 1]) {
+                return src[pos] ? '7' : '6';
             }
-            return src.length > srcPos + 3 && src[srcPos + 3] ? '5' : '4';
+            return src[pos] ? '5' : '4';
         }
-        if (src.length > srcPos + 2 && src[srcPos + 2]) {
-            return src.length > srcPos + 3 && src[srcPos + 3] ? '3' : '2';
+        if (1 <= pos && src[pos - 1]) {
+            return src[pos] ? '3' : '2';
         }
-        return src.length > srcPos + 3 && src[srcPos + 3] ? '1' : '0';
+        return src[pos] ? '1' : '0';
     }
 
     /**
diff --git a/src/test/java/org/apache/commons/lang3/ConversionTest.java b/src/test/java/org/apache/commons/lang3/ConversionTest.java
index 59b372bd6..ec104e6dd 100644
--- a/src/test/java/org/apache/commons/lang3/ConversionTest.java
+++ b/src/test/java/org/apache/commons/lang3/ConversionTest.java
@@ -20,9 +20,13 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
+import java.util.Arrays;
+import java.util.SplittableRandom;
 import java.util.UUID;
 
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 
 /**
@@ -413,6 +417,30 @@ public class ConversionTest {
 
     }
 
+    @Test
+    public void testBinaryToHexDigitReverse() {
+        final SplittableRandom rng = new SplittableRandom();
+        final boolean[] x = new boolean[8];
+        for (int i = 0; i < 100; i++) {
+            Conversion.longToBinary(rng.nextLong(), 0, x, 0, 8);
+            for (int j = 1; j <= 8; j++) {
+                final boolean[] a = Arrays.copyOf(x, j);
+                final boolean[] b = a.clone();
+                ArrayUtils.reverse(b);
+                for (int k = 0; k < j; k++) {
+                    assertEquals(Conversion.binaryToHexDigit(a, k),
+                            Conversion.binaryBeMsb0ToHexDigit(b, k));
+                }
+            }
+        }
+    }
+
+    @ParameterizedTest
+    @ValueSource(ints = {-1, 8, 99})
+    public void binaryBeMsb0ToHexDigitPosOutsideArray(int index) {
+        assertThrows(IndexOutOfBoundsException.class,
+                () -> Conversion.binaryBeMsb0ToHexDigit(new boolean[8], index));
+    }
     /**
      * Tests {@link Conversion#intToHexDigit(int)}.
      */