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 */ 018package org.apache.commons.compress.archivers.zip; 019 020import java.io.Serializable; 021 022import static org.apache.commons.compress.archivers.zip.ZipConstants.BYTE_MASK; 023 024/** 025 * Utility class that represents a two byte integer with conversion 026 * rules for the big endian byte order of ZIP files. 027 * @Immutable 028 */ 029public final class ZipShort implements Cloneable, Serializable { 030 private static final long serialVersionUID = 1L; 031 032 private static final int BYTE_1_MASK = 0xFF00; 033 private static final int BYTE_1_SHIFT = 8; 034 035 private final int value; 036 037 /** 038 * Create instance from a number. 039 * @param value the int to store as a ZipShort 040 */ 041 public ZipShort (final int value) { 042 this.value = value; 043 } 044 045 /** 046 * Create instance from bytes. 047 * @param bytes the bytes to store as a ZipShort 048 */ 049 public ZipShort (final byte[] bytes) { 050 this(bytes, 0); 051 } 052 053 /** 054 * Create instance from the two bytes starting at offset. 055 * @param bytes the bytes to store as a ZipShort 056 * @param offset the offset to start 057 */ 058 public ZipShort (final byte[] bytes, final int offset) { 059 value = ZipShort.getValue(bytes, offset); 060 } 061 062 /** 063 * Get value as two bytes in big endian byte order. 064 * @return the value as a a two byte array in big endian byte order 065 */ 066 public byte[] getBytes() { 067 final byte[] result = new byte[2]; 068 result[0] = (byte) (value & BYTE_MASK); 069 result[1] = (byte) ((value & BYTE_1_MASK) >> BYTE_1_SHIFT); 070 return result; 071 } 072 073 /** 074 * Get value as Java int. 075 * @return value as a Java int 076 */ 077 public int getValue() { 078 return value; 079 } 080 081 /** 082 * Get value as two bytes in big endian byte order. 083 * @param value the Java int to convert to bytes 084 * @return the converted int as a byte array in big endian byte order 085 */ 086 public static byte[] getBytes(final int value) { 087 final byte[] result = new byte[2]; 088 putShort(value, result, 0); 089 return result; 090 } 091 092 /** 093 * put the value as two bytes in big endian byte order. 094 * @param value the Java int to convert to bytes 095 * @param buf the output buffer 096 * @param offset 097 * The offset within the output buffer of the first byte to be written. 098 * must be non-negative and no larger than <tt>buf.length-2</tt> 099 */ 100 public static void putShort(final int value, final byte[] buf, final int offset) { 101 buf[offset] = (byte) (value & BYTE_MASK); 102 buf[offset+1] = (byte) ((value & BYTE_1_MASK) >> BYTE_1_SHIFT); 103 } 104 105 /** 106 * Helper method to get the value as a java int from two bytes starting at given array offset 107 * @param bytes the array of bytes 108 * @param offset the offset to start 109 * @return the corresponding java int value 110 */ 111 public static int getValue(final byte[] bytes, final int offset) { 112 int value = (bytes[offset + 1] << BYTE_1_SHIFT) & BYTE_1_MASK; 113 value += (bytes[offset] & BYTE_MASK); 114 return value; 115 } 116 117 /** 118 * Helper method to get the value as a java int from a two-byte array 119 * @param bytes the array of bytes 120 * @return the corresponding java int value 121 */ 122 public static int getValue(final byte[] bytes) { 123 return getValue(bytes, 0); 124 } 125 126 /** 127 * Override to make two instances with same value equal. 128 * @param o an object to compare 129 * @return true if the objects are equal 130 */ 131 @Override 132 public boolean equals(final Object o) { 133 if (o == null || !(o instanceof ZipShort)) { 134 return false; 135 } 136 return value == ((ZipShort) o).getValue(); 137 } 138 139 /** 140 * Override to make two instances with same value equal. 141 * @return the value stored in the ZipShort 142 */ 143 @Override 144 public int hashCode() { 145 return value; 146 } 147 148 @Override 149 public Object clone() { 150 try { 151 return super.clone(); 152 } catch (final CloneNotSupportedException cnfe) { 153 // impossible 154 throw new RuntimeException(cnfe); //NOSONAR 155 } 156 } 157 158 @Override 159 public String toString() { 160 return "ZipShort value: " + value; 161 } 162}