Author: bodewig
Date: Thu Jul 21 08:37:01 2011
New Revision: 1149070

URL: http://svn.apache.org/viewvc?rev=1149070&view=rev
Log:
first piece of infrastructure for ZIP64 support, deal with numbers represented 
as eight bytes in big-endian order.  COMPRESS-36

Added:
    
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipEightByteInteger.java
      - copied, changed from r1149049, 
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipLong.java
    
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipEightByteIntegerTest.java
      - copied, changed from r1149049, 
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipLongTest.java

Copied: 
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipEightByteInteger.java
 (from r1149049, 
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipLong.java)
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipEightByteInteger.java?p2=commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipEightByteInteger.java&p1=commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipLong.java&r1=1149049&r2=1149070&rev=1149070&view=diff
==============================================================================
--- 
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipLong.java
 (original)
+++ 
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/zip/ZipEightByteInteger.java
 Thu Jul 21 08:37:01 2011
@@ -17,15 +17,15 @@
  */
 package org.apache.commons.compress.archivers.zip;
 
+import java.math.BigInteger;
+
 /**
- * Utility class that represents a four byte integer with conversion
+ * Utility class that represents an eight byte integer with conversion
  * rules for the big endian byte order of ZIP files.
  * @Immutable
  */
-public final class ZipLong implements Cloneable {
+public final class ZipEightByteInteger {
 
-    private static final int WORD = 4;
-    //private static final int BYTE_BIT_SIZE = 8;
     private static final int BYTE_MASK = 0xFF;
 
     private static final int BYTE_1 = 1;
@@ -40,95 +40,162 @@ public final class ZipLong implements Cl
     private static final long BYTE_3_MASK = 0xFF000000L;
     private static final int BYTE_3_SHIFT = 24;
 
-    private final long value;
+    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;
 
-    /** Central File Header Signature */
-    public static final ZipLong CFH_SIG = new ZipLong(0X02014B50L);
+    private static final int LEFTMOST_BIT_SHIFT = 63;
+    private static final byte LEFTMOST_BIT = (byte) 0x80;
 
-    /** Local File Header Signature */
-    public static final ZipLong LFH_SIG = new ZipLong(0X04034B50L);
+    private final BigInteger value;
 
     /**
-     * Data Descriptor signature
-     * @since Apache Commons Compress 1.1
+     * Create instance from a number.
+     * @param value the long to store as a ZipEightByteInteger
      */
-    public static final ZipLong DD_SIG = new ZipLong(0X08074B50L);
+    public ZipEightByteInteger(long value) {
+        this(BigInteger.valueOf(value));
+    }
 
     /**
      * Create instance from a number.
-     * @param value the long to store as a ZipLong
+     * @param value the BigInteger to store as a ZipEightByteInteger
      */
-    public ZipLong(long value) {
+    public ZipEightByteInteger(BigInteger value) {
         this.value = value;
     }
 
     /**
      * Create instance from bytes.
-     * @param bytes the bytes to store as a ZipLong
+     * @param bytes the bytes to store as a ZipEightByteInteger
      */
-    public ZipLong (byte[] bytes) {
+    public ZipEightByteInteger (byte[] bytes) {
         this(bytes, 0);
     }
 
     /**
-     * Create instance from the four bytes starting at offset.
-     * @param bytes the bytes to store as a ZipLong
+     * Create instance from the eight bytes starting at offset.
+     * @param bytes the bytes to store as a ZipEightByteInteger
      * @param offset the offset to start
      */
-    public ZipLong (byte[] bytes, int offset) {
-        value = ZipLong.getValue(bytes, offset);
+    public ZipEightByteInteger (byte[] bytes, int offset) {
+        value = ZipEightByteInteger.getValue(bytes, offset);
     }
 
     /**
-     * Get value as four bytes in big endian byte order.
-     * @return value as four bytes in big endian order
+     * Get value as eight bytes in big endian byte order.
+     * @return value as eight bytes in big endian order
      */
     public byte[] getBytes() {
-        return ZipLong.getBytes(value);
+        return ZipEightByteInteger.getBytes(value);
     }
 
     /**
      * Get value as Java long.
      * @return value as a long
      */
-    public long getValue() {
+    public long getLongValue() {
+        return value.longValue();
+    }
+
+    /**
+     * Get value as Java long.
+     * @return value as a long
+     */
+    public BigInteger getValue() {
         return value;
     }
 
     /**
-     * Get value as four bytes in big endian byte order.
+     * Get value as eight bytes in big endian byte order.
      * @param value the value to convert
-     * @return value as four bytes in big endian byte order
+     * @return value as eight bytes in big endian byte order
      */
     public static byte[] getBytes(long value) {
-        byte[] result = new byte[WORD];
-        result[0] = (byte) ((value & BYTE_MASK));
-        result[BYTE_1] = (byte) ((value & BYTE_1_MASK) >> BYTE_1_SHIFT);
-        result[BYTE_2] = (byte) ((value & BYTE_2_MASK) >> BYTE_2_SHIFT);
-        result[BYTE_3] = (byte) ((value & BYTE_3_MASK) >> BYTE_3_SHIFT);
+        return getBytes(BigInteger.valueOf(value));
+    }
+
+    /**
+     * Get value as eight bytes in big endian byte order.
+     * @param value the value to convert
+     * @return value as eight bytes in big endian byte order
+     */
+    public static byte[] getBytes(BigInteger value) {
+        byte[] result = new byte[8];
+        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;
     }
 
     /**
-     * Helper method to get the value as a Java long from four bytes starting 
at given array offset
+     * Helper method to get the value as a Java long from eight bytes
+     * starting at given array offset
      * @param bytes the array of bytes
      * @param offset the offset to start
-     * @return the correspondanding Java long value
+     * @return the corresponding Java long value
      */
-    public static long getValue(byte[] bytes, int offset) {
-        long value = (bytes[offset + BYTE_3] << BYTE_3_SHIFT) & BYTE_3_MASK;
-        value += (bytes[offset + BYTE_2] << BYTE_2_SHIFT) & BYTE_2_MASK;
-        value += (bytes[offset + BYTE_1] << BYTE_1_SHIFT) & BYTE_1_MASK;
-        value += (bytes[offset] & BYTE_MASK);
-        return value;
+    public static long getLongValue(byte[] bytes, int offset) {
+        return getValue(bytes, offset).longValue();
+    }
+
+    /**
+     * Helper method to get the value as a Java BigInteger from eight
+     * bytes starting at given array offset
+     * @param bytes the array of bytes
+     * @param offset the offset to start
+     * @return the corresponding Java BigInteger value
+     */
+    public static BigInteger getValue(byte[] bytes, 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);
+        BigInteger val = BigInteger.valueOf(value);
+        return (bytes[offset + BYTE_7] & LEFTMOST_BIT) == LEFTMOST_BIT
+            ? val.setBit(LEFTMOST_BIT_SHIFT) : val;
     }
 
     /**
-     * Helper method to get the value as a Java long from a four-byte array
+     * Helper method to get the value as a Java long from an eight-byte array
      * @param bytes the array of bytes
-     * @return the correspondanding Java long value
+     * @return the corresponding Java long value
      */
-    public static long getValue(byte[] bytes) {
+    public static long getLongValue(byte[] bytes) {
+        return getLongValue(bytes, 0);
+    }
+
+    /**
+     * Helper method to get the value as a Java long from an eight-byte array
+     * @param bytes the array of bytes
+     * @return the corresponding Java BigInteger value
+     */
+    public static BigInteger getValue(byte[] bytes) {
         return getValue(bytes, 0);
     }
 
@@ -138,26 +205,17 @@ public final class ZipLong implements Cl
      * @return true if the objects are equal
      */
     public boolean equals(Object o) {
-        if (o == null || !(o instanceof ZipLong)) {
+        if (o == null || !(o instanceof ZipEightByteInteger)) {
             return false;
         }
-        return value == ((ZipLong) o).getValue();
+        return value.equals(((ZipEightByteInteger) o).getValue());
     }
 
     /**
      * Override to make two instances with same value equal.
-     * @return the value stored in the ZipLong
+     * @return the hashCode of the value stored in the ZipEightByteInteger
      */
     public int hashCode() {
-        return (int) value;
-    }
-
-    public Object clone() {
-        try {
-            return super.clone();
-        } catch (CloneNotSupportedException cnfe) {
-            // impossible
-            throw new RuntimeException(cnfe);
-        }
+        return value.hashCode();
     }
 }

Copied: 
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipEightByteIntegerTest.java
 (from r1149049, 
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipLongTest.java)
URL: 
http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipEightByteIntegerTest.java?p2=commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipEightByteIntegerTest.java&p1=commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipLongTest.java&r1=1149049&r2=1149070&rev=1149070&view=diff
==============================================================================
--- 
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipLongTest.java
 (original)
+++ 
commons/proper/compress/trunk/src/test/java/org/apache/commons/compress/archivers/zip/ZipEightByteIntegerTest.java
 Thu Jul 21 08:37:01 2011
@@ -18,47 +18,82 @@
 
 package org.apache.commons.compress.archivers.zip;
 
+import java.math.BigInteger;
 import junit.framework.TestCase;
 
 /**
- * JUnit 3 testcases for org.apache.commons.compress.archivers.zip.ZipLong.
+ * JUnit 3 testcases for 
org.apache.commons.compress.archivers.zip.ZipEightByteInteger.
  *
  */
-public class ZipLongTest extends TestCase {
+public class ZipEightByteIntegerTest extends TestCase {
 
-    public ZipLongTest(String name) {
+    public ZipEightByteIntegerTest(String name) {
         super(name);
     }
 
     /**
      * Test conversion to bytes.
      */
-    public void testToBytes() {
-        ZipLong zl = new ZipLong(0x12345678);
+    public void testLongToBytes() {
+        ZipEightByteInteger zl = new ZipEightByteInteger(0xAB12345678l);
         byte[] result = zl.getBytes();
-        assertEquals("length getBytes", 4, result.length);
+        assertEquals("length getBytes", 8, result.length);
         assertEquals("first byte getBytes", 0x78, result[0]);
         assertEquals("second byte getBytes", 0x56, result[1]);
         assertEquals("third byte getBytes", 0x34, result[2]);
         assertEquals("fourth byte getBytes", 0x12, result[3]);
+        assertEquals("fifth byte getBytes", (byte) 0xAB, result[4]);
+        assertEquals("sixth byte getBytes", 0, result[5]);
+        assertEquals("seventh byte getBytes", 0, result[6]);
+        assertEquals("eighth byte getBytes", 0, result[7]);
     }
 
     /**
      * Test conversion from bytes.
      */
-    public void testFromBytes() {
-        byte[] val = new byte[] {0x78, 0x56, 0x34, 0x12};
-        ZipLong zl = new ZipLong(val);
-        assertEquals("value from bytes", 0x12345678, zl.getValue());
+    public void testLongFromBytes() {
+        byte[] val = new byte[] {0x78, 0x56, 0x34, 0x12, (byte) 0xAB, 0x00, 
0x00, 0x00};
+        ZipEightByteInteger zl = new ZipEightByteInteger(val);
+        assertEquals("longValue from bytes", 0xAB12345678l, zl.getLongValue());
+    }
+
+    /**
+     * Test conversion to bytes.
+     */
+    public void testBIToBytes() {
+        ZipEightByteInteger zl =
+            new ZipEightByteInteger(BigInteger.valueOf(Long.MAX_VALUE)
+                                    .shiftLeft(1));
+        byte[] result = zl.getBytes();
+        assertEquals("length getBytes", 8, result.length);
+        assertEquals("first byte getBytes", (byte) 0xFE, result[0]);
+        assertEquals("second byte getBytes", (byte) 0xFF, result[1]);
+        assertEquals("third byte getBytes", (byte) 0xFF, result[2]);
+        assertEquals("fourth byte getBytes", (byte) 0xFF, result[3]);
+        assertEquals("fifth byte getBytes", (byte) 0xFF, result[4]);
+        assertEquals("sixth byte getBytes", (byte) 0xFF, result[5]);
+        assertEquals("seventh byte getBytes", (byte) 0xFF, result[6]);
+        assertEquals("eighth byte getBytes", (byte) 0xFF, result[7]);
+    }
+
+    /**
+     * Test conversion from bytes.
+     */
+    public void testBIFromBytes() {
+        byte[] val = new byte[] {(byte) 0xFE, (byte) 0xFF, (byte) 0xFF, (byte) 
0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF};
+        ZipEightByteInteger zl = new ZipEightByteInteger(val);
+        assertEquals("value from bytes",
+                     BigInteger.valueOf(Long.MAX_VALUE).shiftLeft(1),
+                     zl.getValue());
     }
 
     /**
      * Test the contract of the equals method.
      */
     public void testEquals() {
-        ZipLong zl = new ZipLong(0x12345678);
-        ZipLong zl2 = new ZipLong(0x12345678);
-        ZipLong zl3 = new ZipLong(0x87654321);
+        ZipEightByteInteger zl = new ZipEightByteInteger(0x12345678);
+        ZipEightByteInteger zl2 = new ZipEightByteInteger(0x12345678);
+        ZipEightByteInteger zl3 = new ZipEightByteInteger(0x87654321);
 
         assertTrue("reflexive", zl.equals(zl));
 
@@ -68,22 +103,15 @@ public class ZipLongTest extends TestCas
         assertTrue("symmetric", zl2.equals(zl));
 
         assertTrue("null handling", !zl.equals(null));
-        assertTrue("non ZipLong handling", !zl.equals(new Integer(0x1234)));
+        assertTrue("non ZipEightByteInteger handling", !zl.equals(new 
Integer(0x1234)));
     }
 
     /**
      * Test sign handling.
      */
     public void testSign() {
-        ZipLong zl = new ZipLong(new byte[] {(byte)0xFF, (byte)0xFF, 
(byte)0xFF, (byte)0xFF});
-        assertEquals(0x00000000FFFFFFFFl, zl.getValue());
-    }
-
-    public void testClone() {
-        ZipLong s1 = new ZipLong(42);
-        ZipLong s2 = (ZipLong) s1.clone();
-        assertNotSame(s1, s2);
-        assertEquals(s1, s2);
-        assertEquals(s1.getValue(), s2.getValue());
+        ZipEightByteInteger zl = new ZipEightByteInteger(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());
     }
 }


Reply via email to