001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018 package org.apache.commons.compress.archivers.zip; 019 020 import java.math.BigInteger; 021 022 /** 023 * Utility class that represents an eight byte integer with conversion 024 * rules for the big endian byte order of ZIP files. 025 * @Immutable 026 * 027 * @since Apache Commons Compress 1.2 028 */ 029 public final class ZipEightByteInteger { 030 031 private static final int BYTE_MASK = 0xFF; 032 033 private static final int BYTE_1 = 1; 034 private static final int BYTE_1_MASK = 0xFF00; 035 private static final int BYTE_1_SHIFT = 8; 036 037 private static final int BYTE_2 = 2; 038 private static final int BYTE_2_MASK = 0xFF0000; 039 private static final int BYTE_2_SHIFT = 16; 040 041 private static final int BYTE_3 = 3; 042 private static final long BYTE_3_MASK = 0xFF000000L; 043 private static final int BYTE_3_SHIFT = 24; 044 045 private static final int BYTE_4 = 4; 046 private static final long BYTE_4_MASK = 0xFF00000000L; 047 private static final int BYTE_4_SHIFT = 32; 048 049 private static final int BYTE_5 = 5; 050 private static final long BYTE_5_MASK = 0xFF0000000000L; 051 private static final int BYTE_5_SHIFT = 40; 052 053 private static final int BYTE_6 = 6; 054 private static final long BYTE_6_MASK = 0xFF000000000000L; 055 private static final int BYTE_6_SHIFT = 48; 056 057 private static final int BYTE_7 = 7; 058 private static final long BYTE_7_MASK = 0x7F00000000000000L; 059 private static final int BYTE_7_SHIFT = 56; 060 061 private static final int LEFTMOST_BIT_SHIFT = 63; 062 private static final byte LEFTMOST_BIT = (byte) 0x80; 063 064 private final BigInteger value; 065 066 /** 067 * Create instance from a number. 068 * @param value the long to store as a ZipEightByteInteger 069 */ 070 public ZipEightByteInteger(long value) { 071 this(BigInteger.valueOf(value)); 072 } 073 074 /** 075 * Create instance from a number. 076 * @param value the BigInteger to store as a ZipEightByteInteger 077 */ 078 public ZipEightByteInteger(BigInteger value) { 079 this.value = value; 080 } 081 082 /** 083 * Create instance from bytes. 084 * @param bytes the bytes to store as a ZipEightByteInteger 085 */ 086 public ZipEightByteInteger (byte[] bytes) { 087 this(bytes, 0); 088 } 089 090 /** 091 * Create instance from the eight bytes starting at offset. 092 * @param bytes the bytes to store as a ZipEightByteInteger 093 * @param offset the offset to start 094 */ 095 public ZipEightByteInteger (byte[] bytes, int offset) { 096 value = ZipEightByteInteger.getValue(bytes, offset); 097 } 098 099 /** 100 * Get value as eight bytes in big endian byte order. 101 * @return value as eight bytes in big endian order 102 */ 103 public byte[] getBytes() { 104 return ZipEightByteInteger.getBytes(value); 105 } 106 107 /** 108 * Get value as Java long. 109 * @return value as a long 110 */ 111 public long getLongValue() { 112 return value.longValue(); 113 } 114 115 /** 116 * Get value as Java long. 117 * @return value as a long 118 */ 119 public BigInteger getValue() { 120 return value; 121 } 122 123 /** 124 * Get value as eight bytes in big endian byte order. 125 * @param value the value to convert 126 * @return value as eight bytes in big endian byte order 127 */ 128 public static byte[] getBytes(long value) { 129 return getBytes(BigInteger.valueOf(value)); 130 } 131 132 /** 133 * Get value as eight bytes in big endian byte order. 134 * @param value the value to convert 135 * @return value as eight bytes in big endian byte order 136 */ 137 public static byte[] getBytes(BigInteger value) { 138 byte[] result = new byte[8]; 139 long val = value.longValue(); 140 result[0] = (byte) ((val & BYTE_MASK)); 141 result[BYTE_1] = (byte) ((val & BYTE_1_MASK) >> BYTE_1_SHIFT); 142 result[BYTE_2] = (byte) ((val & BYTE_2_MASK) >> BYTE_2_SHIFT); 143 result[BYTE_3] = (byte) ((val & BYTE_3_MASK) >> BYTE_3_SHIFT); 144 result[BYTE_4] = (byte) ((val & BYTE_4_MASK) >> BYTE_4_SHIFT); 145 result[BYTE_5] = (byte) ((val & BYTE_5_MASK) >> BYTE_5_SHIFT); 146 result[BYTE_6] = (byte) ((val & BYTE_6_MASK) >> BYTE_6_SHIFT); 147 result[BYTE_7] = (byte) ((val & BYTE_7_MASK) >> BYTE_7_SHIFT); 148 if (value.testBit(LEFTMOST_BIT_SHIFT)) { 149 result[BYTE_7] |= LEFTMOST_BIT; 150 } 151 return result; 152 } 153 154 /** 155 * Helper method to get the value as a Java long from eight bytes 156 * starting at given array offset 157 * @param bytes the array of bytes 158 * @param offset the offset to start 159 * @return the corresponding Java long value 160 */ 161 public static long getLongValue(byte[] bytes, int offset) { 162 return getValue(bytes, offset).longValue(); 163 } 164 165 /** 166 * Helper method to get the value as a Java BigInteger from eight 167 * bytes starting at given array offset 168 * @param bytes the array of bytes 169 * @param offset the offset to start 170 * @return the corresponding Java BigInteger value 171 */ 172 public static BigInteger getValue(byte[] bytes, int offset) { 173 long value = ((long) bytes[offset + BYTE_7] << BYTE_7_SHIFT) & BYTE_7_MASK; 174 value += ((long) bytes[offset + BYTE_6] << BYTE_6_SHIFT) & BYTE_6_MASK; 175 value += ((long) bytes[offset + BYTE_5] << BYTE_5_SHIFT) & BYTE_5_MASK; 176 value += ((long) bytes[offset + BYTE_4] << BYTE_4_SHIFT) & BYTE_4_MASK; 177 value += ((long) bytes[offset + BYTE_3] << BYTE_3_SHIFT) & BYTE_3_MASK; 178 value += ((long) bytes[offset + BYTE_2] << BYTE_2_SHIFT) & BYTE_2_MASK; 179 value += ((long) bytes[offset + BYTE_1] << BYTE_1_SHIFT) & BYTE_1_MASK; 180 value += ((long) bytes[offset] & BYTE_MASK); 181 BigInteger val = BigInteger.valueOf(value); 182 return (bytes[offset + BYTE_7] & LEFTMOST_BIT) == LEFTMOST_BIT 183 ? val.setBit(LEFTMOST_BIT_SHIFT) : val; 184 } 185 186 /** 187 * Helper method to get the value as a Java long from an eight-byte array 188 * @param bytes the array of bytes 189 * @return the corresponding Java long value 190 */ 191 public static long getLongValue(byte[] bytes) { 192 return getLongValue(bytes, 0); 193 } 194 195 /** 196 * Helper method to get the value as a Java long from an eight-byte array 197 * @param bytes the array of bytes 198 * @return the corresponding Java BigInteger value 199 */ 200 public static BigInteger getValue(byte[] bytes) { 201 return getValue(bytes, 0); 202 } 203 204 /** 205 * Override to make two instances with same value equal. 206 * @param o an object to compare 207 * @return true if the objects are equal 208 */ 209 public boolean equals(Object o) { 210 if (o == null || !(o instanceof ZipEightByteInteger)) { 211 return false; 212 } 213 return value.equals(((ZipEightByteInteger) o).getValue()); 214 } 215 216 /** 217 * Override to make two instances with same value equal. 218 * @return the hashCode of the value stored in the ZipEightByteInteger 219 */ 220 public int hashCode() { 221 return value.hashCode(); 222 } 223 224 public String toString() { 225 return "ZipEightByteInteger value: " + value; 226 } 227 }