This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-compress.git
The following commit(s) were added to refs/heads/master by this push: new 6c6576b39 Optimizing ZipEightByteInteger (#614) 6c6576b39 is described below commit 6c6576b39c45cd4ec36776cc2b73fb9583d118eb Author: Glavo <zjx001...@gmail.com> AuthorDate: Tue Nov 26 23:04:06 2024 +0800 Optimizing ZipEightByteInteger (#614) * toUnsignedBigInteger * Update * Add javadoc * Remove unnecessary parentheses * Update constructor * update ZipEightByteInteger#toString() * Create new tests --- .../archivers/zip/ZipEightByteInteger.java | 96 +++++++--------------- .../archivers/zip/ZipEightByteIntegerTest.java | 29 +++++++ 2 files changed, 58 insertions(+), 67 deletions(-) diff --git a/src/main/java/org/apache/commons/compress/archivers/zip/ZipEightByteInteger.java b/src/main/java/org/apache/commons/compress/archivers/zip/ZipEightByteInteger.java index f9fae8eac..96fd1c54e 100644 --- a/src/main/java/org/apache/commons/compress/archivers/zip/ZipEightByteInteger.java +++ b/src/main/java/org/apache/commons/compress/archivers/zip/ZipEightByteInteger.java @@ -16,10 +16,10 @@ */ package org.apache.commons.compress.archivers.zip; -import static org.apache.commons.compress.archivers.zip.ZipConstants.BYTE_MASK; - import java.io.Serializable; import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; /** * Utility class that represents an eight byte integer with conversion rules for the little-endian byte order of ZIP files. @@ -31,38 +31,20 @@ import java.math.BigInteger; public final class ZipEightByteInteger implements Serializable { private static final long serialVersionUID = 1L; - private static final int BYTE_1 = 1; - private static final int BYTE_1_MASK = 0xFF00; - private static final int BYTE_1_SHIFT = 8; - - private static final int BYTE_2 = 2; - private static final int BYTE_2_MASK = 0xFF0000; - private static final int BYTE_2_SHIFT = 16; - - private static final int BYTE_3 = 3; - private static final long BYTE_3_MASK = 0xFF000000L; - private static final int BYTE_3_SHIFT = 24; - - private static final int BYTE_4 = 4; - private static final long BYTE_4_MASK = 0xFF00000000L; - private static final int BYTE_4_SHIFT = 32; - - private static final int BYTE_5 = 5; - private static final long BYTE_5_MASK = 0xFF0000000000L; - private static final int BYTE_5_SHIFT = 40; - - private static final int BYTE_6 = 6; - private static final long BYTE_6_MASK = 0xFF000000000000L; - private static final int BYTE_6_SHIFT = 48; - - private static final int BYTE_7 = 7; - private static final long BYTE_7_MASK = 0x7F00000000000000L; - private static final int BYTE_7_SHIFT = 56; + public static final ZipEightByteInteger ZERO = new ZipEightByteInteger(0); - private static final int LEFTMOST_BIT_SHIFT = 63; - private static final byte LEFTMOST_BIT = (byte) 0x80; + private static final BigInteger HIGHEST_BIT = BigInteger.ONE.shiftLeft(63); - public static final ZipEightByteInteger ZERO = new ZipEightByteInteger(0); + /** + * package private for tests only. + */ + static BigInteger toUnsignedBigInteger(final long value) { + if (value >= 0L) { + return BigInteger.valueOf(value); + } else { + return BigInteger.valueOf(value & Long.MAX_VALUE).add(HIGHEST_BIT); + } + } /** * Gets value as eight bytes in big-endian byte order. @@ -71,20 +53,7 @@ public final class ZipEightByteInteger implements Serializable { * @return value as eight bytes in big-endian byte order */ public static byte[] getBytes(final BigInteger value) { - final byte[] result = new byte[8]; - final long val = value.longValue(); - result[0] = (byte) (val & BYTE_MASK); - result[BYTE_1] = (byte) ((val & BYTE_1_MASK) >> BYTE_1_SHIFT); - result[BYTE_2] = (byte) ((val & BYTE_2_MASK) >> BYTE_2_SHIFT); - result[BYTE_3] = (byte) ((val & BYTE_3_MASK) >> BYTE_3_SHIFT); - result[BYTE_4] = (byte) ((val & BYTE_4_MASK) >> BYTE_4_SHIFT); - result[BYTE_5] = (byte) ((val & BYTE_5_MASK) >> BYTE_5_SHIFT); - result[BYTE_6] = (byte) ((val & BYTE_6_MASK) >> BYTE_6_SHIFT); - result[BYTE_7] = (byte) ((val & BYTE_7_MASK) >> BYTE_7_SHIFT); - if (value.testBit(LEFTMOST_BIT_SHIFT)) { - result[BYTE_7] |= LEFTMOST_BIT; - } - return result; + return getBytes(value.longValue()); } /** @@ -94,7 +63,9 @@ public final class ZipEightByteInteger implements Serializable { * @return value as eight bytes in big-endian byte order */ public static byte[] getBytes(final long value) { - return getBytes(BigInteger.valueOf(value)); + ByteBuffer buffer = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN); + buffer.putLong(value); + return buffer.array(); } /** @@ -115,7 +86,7 @@ public final class ZipEightByteInteger implements Serializable { * @return the corresponding Java long value */ public static long getLongValue(final byte[] bytes, final int offset) { - return getValue(bytes, offset).longValue(); + return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getLong(offset); } /** @@ -136,19 +107,10 @@ public final class ZipEightByteInteger implements Serializable { * @return the corresponding Java BigInteger value */ public static BigInteger getValue(final byte[] bytes, final int offset) { - long value = (long) bytes[offset + BYTE_7] << BYTE_7_SHIFT & BYTE_7_MASK; - value += (long) bytes[offset + BYTE_6] << BYTE_6_SHIFT & BYTE_6_MASK; - value += (long) bytes[offset + BYTE_5] << BYTE_5_SHIFT & BYTE_5_MASK; - value += (long) bytes[offset + BYTE_4] << BYTE_4_SHIFT & BYTE_4_MASK; - value += (long) bytes[offset + BYTE_3] << BYTE_3_SHIFT & BYTE_3_MASK; - value += (long) bytes[offset + BYTE_2] << BYTE_2_SHIFT & BYTE_2_MASK; - value += (long) bytes[offset + BYTE_1] << BYTE_1_SHIFT & BYTE_1_MASK; - value += (long) bytes[offset] & BYTE_MASK; - final BigInteger val = BigInteger.valueOf(value); - return (bytes[offset + BYTE_7] & LEFTMOST_BIT) == LEFTMOST_BIT ? val.setBit(LEFTMOST_BIT_SHIFT) : val; + return toUnsignedBigInteger(getLongValue(bytes, offset)); } - private final BigInteger value; + private final long value; /** * Constructs a new instance from a number. @@ -156,7 +118,7 @@ public final class ZipEightByteInteger implements Serializable { * @param value the BigInteger to store as a ZipEightByteInteger */ public ZipEightByteInteger(final BigInteger value) { - this.value = value; + this.value = value.longValue(); } /** @@ -175,7 +137,7 @@ public final class ZipEightByteInteger implements Serializable { * @param offset the offset to start */ public ZipEightByteInteger(final byte[] bytes, final int offset) { - value = getValue(bytes, offset); + this.value = getLongValue(bytes, offset); } /** @@ -184,7 +146,7 @@ public final class ZipEightByteInteger implements Serializable { * @param value the long to store as a ZipEightByteInteger */ public ZipEightByteInteger(final long value) { - this(BigInteger.valueOf(value)); + this.value = value; } /** @@ -198,7 +160,7 @@ public final class ZipEightByteInteger implements Serializable { if (!(o instanceof ZipEightByteInteger)) { return false; } - return value.equals(((ZipEightByteInteger) o).getValue()); + return value == ((ZipEightByteInteger) o).value; } /** @@ -216,7 +178,7 @@ public final class ZipEightByteInteger implements Serializable { * @return value as a long */ public long getLongValue() { - return value.longValue(); + return value; } /** @@ -225,7 +187,7 @@ public final class ZipEightByteInteger implements Serializable { * @return value as a BigInteger */ public BigInteger getValue() { - return value; + return toUnsignedBigInteger(value); } /** @@ -235,11 +197,11 @@ public final class ZipEightByteInteger implements Serializable { */ @Override public int hashCode() { - return value.hashCode(); + return Long.hashCode(value); } @Override public String toString() { - return "ZipEightByteInteger value: " + value; + return "ZipEightByteInteger value: " + Long.toUnsignedString(value); } } diff --git a/src/test/java/org/apache/commons/compress/archivers/zip/ZipEightByteIntegerTest.java b/src/test/java/org/apache/commons/compress/archivers/zip/ZipEightByteIntegerTest.java index 5f4992cf6..144244cd4 100644 --- a/src/test/java/org/apache/commons/compress/archivers/zip/ZipEightByteIntegerTest.java +++ b/src/test/java/org/apache/commons/compress/archivers/zip/ZipEightByteIntegerTest.java @@ -29,6 +29,15 @@ import org.junit.jupiter.api.Test; */ public class ZipEightByteIntegerTest { + /** + * Test {@link ZipEightByteInteger#toUnsignedBigInteger(long)}. + */ + @Test + public void testToUnsignedBigInteger() { + assertEquals(BigInteger.valueOf(Long.MAX_VALUE), ZipEightByteInteger.toUnsignedBigInteger(Long.MAX_VALUE)); + assertEquals(BigInteger.valueOf(Long.MAX_VALUE).shiftLeft(1), ZipEightByteInteger.toUnsignedBigInteger(0XFFFFFFFFFFFFFFFEL)); + } + /** * Test conversion from bytes. */ @@ -99,6 +108,16 @@ public class ZipEightByteIntegerTest { assertEquals(0xAB12345678L, zl.getLongValue(), "longValue from bytes"); } + /** + * Test conversion from bytes. + */ + @Test + public void testBILongFromBytes() { + final byte[] val = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF }; + final ZipEightByteInteger zl = new ZipEightByteInteger(val); + assertEquals(0XFFFFFFFFFFFFFFFFL, zl.getLongValue(), "longValue from bytes"); + } + /** * Test conversion to bytes. */ @@ -126,4 +145,14 @@ public class ZipEightByteIntegerTest { new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF }); assertEquals(BigInteger.valueOf(Long.MAX_VALUE).shiftLeft(1).setBit(0), zl.getValue()); } + + /** + * Test {@link ZipEightByteInteger#toString()}. + */ + @Test + public void testToString() { + final ZipEightByteInteger zipEightByteInteger = new ZipEightByteInteger( + new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF }); + assertEquals("ZipEightByteInteger value: 18446744073709551615", zipEightByteInteger.toString()); + } }