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 /**
021 * Utility class that represents a two byte integer with conversion
022 * rules for the big endian byte order of ZIP files.
023 * @Immutable
024 */
025 public final class ZipShort implements Cloneable {
026 private static final int BYTE_MASK = 0xFF;
027 private static final int BYTE_1_MASK = 0xFF00;
028 private static final int BYTE_1_SHIFT = 8;
029
030 private final int value;
031
032 /**
033 * Create instance from a number.
034 * @param value the int to store as a ZipShort
035 */
036 public ZipShort (int value) {
037 this.value = value;
038 }
039
040 /**
041 * Create instance from bytes.
042 * @param bytes the bytes to store as a ZipShort
043 */
044 public ZipShort (byte[] bytes) {
045 this(bytes, 0);
046 }
047
048 /**
049 * Create instance from the two bytes starting at offset.
050 * @param bytes the bytes to store as a ZipShort
051 * @param offset the offset to start
052 */
053 public ZipShort (byte[] bytes, int offset) {
054 value = ZipShort.getValue(bytes, offset);
055 }
056
057 /**
058 * Get value as two bytes in big endian byte order.
059 * @return the value as a a two byte array in big endian byte order
060 */
061 public byte[] getBytes() {
062 byte[] result = new byte[2];
063 result[0] = (byte) (value & BYTE_MASK);
064 result[1] = (byte) ((value & BYTE_1_MASK) >> BYTE_1_SHIFT);
065 return result;
066 }
067
068 /**
069 * Get value as Java int.
070 * @return value as a Java int
071 */
072 public int getValue() {
073 return value;
074 }
075
076 /**
077 * Get value as two bytes in big endian byte order.
078 * @param value the Java int to convert to bytes
079 * @return the converted int as a byte array in big endian byte order
080 */
081 public static byte[] getBytes(int value) {
082 byte[] result = new byte[2];
083 result[0] = (byte) (value & BYTE_MASK);
084 result[1] = (byte) ((value & BYTE_1_MASK) >> BYTE_1_SHIFT);
085 return result;
086 }
087
088 /**
089 * Helper method to get the value as a java int from two bytes starting at given array offset
090 * @param bytes the array of bytes
091 * @param offset the offset to start
092 * @return the correspondanding java int value
093 */
094 public static int getValue(byte[] bytes, int offset) {
095 int value = (bytes[offset + 1] << BYTE_1_SHIFT) & BYTE_1_MASK;
096 value += (bytes[offset] & BYTE_MASK);
097 return value;
098 }
099
100 /**
101 * Helper method to get the value as a java int from a two-byte array
102 * @param bytes the array of bytes
103 * @return the correspondanding java int value
104 */
105 public static int getValue(byte[] bytes) {
106 return getValue(bytes, 0);
107 }
108
109 /**
110 * Override to make two instances with same value equal.
111 * @param o an object to compare
112 * @return true if the objects are equal
113 */
114 public boolean equals(Object o) {
115 if (o == null || !(o instanceof ZipShort)) {
116 return false;
117 }
118 return value == ((ZipShort) o).getValue();
119 }
120
121 /**
122 * Override to make two instances with same value equal.
123 * @return the value stored in the ZipShort
124 */
125 public int hashCode() {
126 return value;
127 }
128
129 public Object clone() {
130 try {
131 return super.clone();
132 } catch (CloneNotSupportedException cnfe) {
133 // impossible
134 throw new RuntimeException(cnfe);
135 }
136 }
137 }