001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.commons.compress.archivers.zip; 020 021import java.io.Serializable; 022import java.math.BigInteger; 023import java.nio.ByteBuffer; 024import java.nio.ByteOrder; 025 026/** 027 * Utility class that represents an eight byte integer with conversion rules for the little-endian byte order of ZIP files. 028 * 029 * @Immutable 030 * @since 1.2 031 */ 032public final class ZipEightByteInteger implements Serializable { 033 034 /** 035 * The number of bytes used to represent an instance in binary form. 036 */ 037 static final int BYTES = 8; 038 039 private static final long serialVersionUID = 1L; 040 041 /** 042 * Constant for a value of zero. 043 */ 044 public static final ZipEightByteInteger ZERO = new ZipEightByteInteger(0); 045 046 private static final BigInteger HIGHEST_BIT = BigInteger.ONE.shiftLeft(63); 047 048 /** 049 * Gets value as eight bytes in big-endian byte order. 050 * 051 * @param value the value to convert. 052 * @return value as eight bytes in big-endian byte order. 053 */ 054 public static byte[] getBytes(final BigInteger value) { 055 return getBytes(value.longValue()); 056 } 057 058 /** 059 * Gets value as eight bytes in big-endian byte order. 060 * 061 * @param value the value to convert. 062 * @return value as eight bytes in big-endian byte order. 063 */ 064 public static byte[] getBytes(final long value) { 065 return ByteBuffer.allocate(BYTES).order(ByteOrder.LITTLE_ENDIAN).putLong(value).array(); 066 } 067 068 /** 069 * Gets the value as a Java long from an eight-byte array. 070 * 071 * @param bytes the array of bytes. 072 * @return the corresponding Java long value. 073 */ 074 public static long getLongValue(final byte[] bytes) { 075 return getLongValue(bytes, 0); 076 } 077 078 /** 079 * Gets the value as a Java long from eight bytes starting at given array offset. 080 * 081 * @param bytes the array of bytes. 082 * @param offset the offset to start. 083 * @return the corresponding Java long value. 084 */ 085 public static long getLongValue(final byte[] bytes, final int offset) { 086 return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getLong(offset); 087 } 088 089 /** 090 * Gets the value as a Java long from an eight-byte array. 091 * 092 * @param bytes the array of bytes. 093 * @return the corresponding Java BigInteger value. 094 */ 095 public static BigInteger getValue(final byte[] bytes) { 096 return getValue(bytes, 0); 097 } 098 099 /** 100 * Gets the value as a Java BigInteger from eight bytes starting at given array offset. 101 * 102 * @param bytes the array of bytes. 103 * @param offset the offset to start. 104 * @return the corresponding Java BigInteger value. 105 */ 106 public static BigInteger getValue(final byte[] bytes, final int offset) { 107 return toUnsignedBigInteger(getLongValue(bytes, offset)); 108 } 109 110 /** 111 * package private for tests only. 112 */ 113 static BigInteger toUnsignedBigInteger(final long value) { 114 if (value >= 0L) { 115 return BigInteger.valueOf(value); 116 } 117 return BigInteger.valueOf(value & Long.MAX_VALUE).add(HIGHEST_BIT); 118 } 119 120 /** 121 * The value is treated as unsigned. 122 */ 123 private final long value; 124 125 /** 126 * Constructs a new instance from a number. 127 * 128 * @param value the BigInteger to store as a ZipEightByteInteger 129 */ 130 public ZipEightByteInteger(final BigInteger value) { 131 this.value = value.longValue(); 132 } 133 134 /** 135 * Constructs a new instance from bytes. 136 * 137 * @param bytes the bytes to store as a ZipEightByteInteger. 138 */ 139 public ZipEightByteInteger(final byte[] bytes) { 140 this(bytes, 0); 141 } 142 143 /** 144 * Constructs a new instance from the eight bytes starting at offset. 145 * 146 * @param bytes the bytes to store as a ZipEightByteInteger. 147 * @param offset the offset to start. 148 */ 149 public ZipEightByteInteger(final byte[] bytes, final int offset) { 150 this.value = getLongValue(bytes, offset); 151 } 152 153 /** 154 * Constructs a new instance from a number. 155 * 156 * @param value the long to store as a ZipEightByteInteger. 157 */ 158 public ZipEightByteInteger(final long value) { 159 this.value = value; 160 } 161 162 /** 163 * Override to make two instances with same value equal. 164 * 165 * @param o an object to compare. 166 * @return true if the objects are equal. 167 */ 168 @Override 169 public boolean equals(final Object o) { 170 if (!(o instanceof ZipEightByteInteger)) { 171 return false; 172 } 173 return value == ((ZipEightByteInteger) o).value; 174 } 175 176 /** 177 * Gets value as eight bytes in big-endian byte order. 178 * 179 * @return value as eight bytes in big-endian order. 180 */ 181 public byte[] getBytes() { 182 return getBytes(value); 183 } 184 185 /** 186 * Gets value as Java long. 187 * 188 * @return value as a long. 189 */ 190 public long getLongValue() { 191 return value; 192 } 193 194 /** 195 * Gets value as Java BigInteger. 196 * 197 * @return value as a BigInteger. 198 */ 199 public BigInteger getValue() { 200 return toUnsignedBigInteger(value); 201 } 202 203 /** 204 * Override to make two instances with same value equal. 205 * 206 * @return the hash code of the value stored in the ZipEightByteInteger. 207 */ 208 @Override 209 public int hashCode() { 210 return Long.hashCode(value); 211 } 212 213 @Override 214 public String toString() { 215 return Long.toUnsignedString(value); 216 } 217}