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