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 */ 017package org.apache.commons.compress.archivers.zip; 018 019import static org.apache.commons.compress.archivers.zip.ZipConstants.BYTE_MASK; 020 021import java.io.Serializable; 022import java.math.BigInteger; 023 024/** 025 * Utility class that represents an eight byte integer with conversion rules for the little-endian byte order of ZIP files. 026 * 027 * @Immutable 028 * 029 * @since 1.2 030 */ 031public final class ZipEightByteInteger implements Serializable { 032 private static final long serialVersionUID = 1L; 033 034 private static final int BYTE_1 = 1; 035 private static final int BYTE_1_MASK = 0xFF00; 036 private static final int BYTE_1_SHIFT = 8; 037 038 private static final int BYTE_2 = 2; 039 private static final int BYTE_2_MASK = 0xFF0000; 040 private static final int BYTE_2_SHIFT = 16; 041 042 private static final int BYTE_3 = 3; 043 private static final long BYTE_3_MASK = 0xFF000000L; 044 private static final int BYTE_3_SHIFT = 24; 045 046 private static final int BYTE_4 = 4; 047 private static final long BYTE_4_MASK = 0xFF00000000L; 048 private static final int BYTE_4_SHIFT = 32; 049 050 private static final int BYTE_5 = 5; 051 private static final long BYTE_5_MASK = 0xFF0000000000L; 052 private static final int BYTE_5_SHIFT = 40; 053 054 private static final int BYTE_6 = 6; 055 private static final long BYTE_6_MASK = 0xFF000000000000L; 056 private static final int BYTE_6_SHIFT = 48; 057 058 private static final int BYTE_7 = 7; 059 private static final long BYTE_7_MASK = 0x7F00000000000000L; 060 private static final int BYTE_7_SHIFT = 56; 061 062 private static final int LEFTMOST_BIT_SHIFT = 63; 063 private static final byte LEFTMOST_BIT = (byte) 0x80; 064 065 public static final ZipEightByteInteger ZERO = new ZipEightByteInteger(0); 066 067 /** 068 * Gets value as eight bytes in big-endian byte order. 069 * 070 * @param value the value to convert 071 * @return value as eight bytes in big-endian byte order 072 */ 073 public static byte[] getBytes(final BigInteger value) { 074 final byte[] result = new byte[8]; 075 final long val = value.longValue(); 076 result[0] = (byte) (val & BYTE_MASK); 077 result[BYTE_1] = (byte) ((val & BYTE_1_MASK) >> BYTE_1_SHIFT); 078 result[BYTE_2] = (byte) ((val & BYTE_2_MASK) >> BYTE_2_SHIFT); 079 result[BYTE_3] = (byte) ((val & BYTE_3_MASK) >> BYTE_3_SHIFT); 080 result[BYTE_4] = (byte) ((val & BYTE_4_MASK) >> BYTE_4_SHIFT); 081 result[BYTE_5] = (byte) ((val & BYTE_5_MASK) >> BYTE_5_SHIFT); 082 result[BYTE_6] = (byte) ((val & BYTE_6_MASK) >> BYTE_6_SHIFT); 083 result[BYTE_7] = (byte) ((val & BYTE_7_MASK) >> BYTE_7_SHIFT); 084 if (value.testBit(LEFTMOST_BIT_SHIFT)) { 085 result[BYTE_7] |= LEFTMOST_BIT; 086 } 087 return result; 088 } 089 090 /** 091 * Gets value as eight bytes in big-endian byte order. 092 * 093 * @param value the value to convert 094 * @return value as eight bytes in big-endian byte order 095 */ 096 public static byte[] getBytes(final long value) { 097 return getBytes(BigInteger.valueOf(value)); 098 } 099 100 /** 101 * Helper method to get the value as a Java long from an eight-byte array 102 * 103 * @param bytes the array of bytes 104 * @return the corresponding Java long value 105 */ 106 public static long getLongValue(final byte[] bytes) { 107 return getLongValue(bytes, 0); 108 } 109 110 /** 111 * Helper method to get the value as a Java long from eight bytes starting at given array offset 112 * 113 * @param bytes the array of bytes 114 * @param offset the offset to start 115 * @return the corresponding Java long value 116 */ 117 public static long getLongValue(final byte[] bytes, final int offset) { 118 return getValue(bytes, offset).longValue(); 119 } 120 121 /** 122 * Helper method to get the value as a Java long from an eight-byte array 123 * 124 * @param bytes the array of bytes 125 * @return the corresponding Java BigInteger value 126 */ 127 public static BigInteger getValue(final byte[] bytes) { 128 return getValue(bytes, 0); 129 } 130 131 /** 132 * Helper method to get the value as a Java BigInteger from eight bytes starting at given array offset 133 * 134 * @param bytes the array of bytes 135 * @param offset the offset to start 136 * @return the corresponding Java BigInteger value 137 */ 138 public static BigInteger getValue(final byte[] bytes, final int offset) { 139 long value = (long) bytes[offset + BYTE_7] << BYTE_7_SHIFT & BYTE_7_MASK; 140 value += (long) bytes[offset + BYTE_6] << BYTE_6_SHIFT & BYTE_6_MASK; 141 value += (long) bytes[offset + BYTE_5] << BYTE_5_SHIFT & BYTE_5_MASK; 142 value += (long) bytes[offset + BYTE_4] << BYTE_4_SHIFT & BYTE_4_MASK; 143 value += (long) bytes[offset + BYTE_3] << BYTE_3_SHIFT & BYTE_3_MASK; 144 value += (long) bytes[offset + BYTE_2] << BYTE_2_SHIFT & BYTE_2_MASK; 145 value += (long) bytes[offset + BYTE_1] << BYTE_1_SHIFT & BYTE_1_MASK; 146 value += (long) bytes[offset] & BYTE_MASK; 147 final BigInteger val = BigInteger.valueOf(value); 148 return (bytes[offset + BYTE_7] & LEFTMOST_BIT) == LEFTMOST_BIT ? val.setBit(LEFTMOST_BIT_SHIFT) : val; 149 } 150 151 private final BigInteger value; 152 153 /** 154 * Constructs a new instance from a number. 155 * 156 * @param value the BigInteger to store as a ZipEightByteInteger 157 */ 158 public ZipEightByteInteger(final BigInteger value) { 159 this.value = value; 160 } 161 162 /** 163 * Constructs a new instance from bytes. 164 * 165 * @param bytes the bytes to store as a ZipEightByteInteger 166 */ 167 public ZipEightByteInteger(final byte[] bytes) { 168 this(bytes, 0); 169 } 170 171 /** 172 * Constructs a new instance from the eight bytes starting at offset. 173 * 174 * @param bytes the bytes to store as a ZipEightByteInteger 175 * @param offset the offset to start 176 */ 177 public ZipEightByteInteger(final byte[] bytes, final int offset) { 178 value = getValue(bytes, offset); 179 } 180 181 /** 182 * Constructs a new instance from a number. 183 * 184 * @param value the long to store as a ZipEightByteInteger 185 */ 186 public ZipEightByteInteger(final long value) { 187 this(BigInteger.valueOf(value)); 188 } 189 190 /** 191 * Override to make two instances with same value equal. 192 * 193 * @param o an object to compare 194 * @return true if the objects are equal 195 */ 196 @Override 197 public boolean equals(final Object o) { 198 if (!(o instanceof ZipEightByteInteger)) { 199 return false; 200 } 201 return value.equals(((ZipEightByteInteger) o).getValue()); 202 } 203 204 /** 205 * Gets value as eight bytes in big-endian byte order. 206 * 207 * @return value as eight bytes in big-endian order 208 */ 209 public byte[] getBytes() { 210 return getBytes(value); 211 } 212 213 /** 214 * Gets value as Java long. 215 * 216 * @return value as a long 217 */ 218 public long getLongValue() { 219 return value.longValue(); 220 } 221 222 /** 223 * Gets value as Java BigInteger. 224 * 225 * @return value as a BigInteger 226 */ 227 public BigInteger getValue() { 228 return value; 229 } 230 231 /** 232 * Override to make two instances with same value equal. 233 * 234 * @return the hash code of the value stored in the ZipEightByteInteger 235 */ 236 @Override 237 public int hashCode() { 238 return value.hashCode(); 239 } 240 241 @Override 242 public String toString() { 243 return "ZipEightByteInteger value: " + value; 244 } 245}