1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */

17 package org.apache.commons.compress.archivers.zip;
18
19 import java.io.Serializable;
20
21 import org.apache.commons.compress.utils.ByteUtils;
22
23 /**
24  * Utility class that represents a two byte integer with conversion rules for the little-endian byte order of ZIP files.
25  *
26  * @Immutable
27  */

28 public final class ZipShort implements Cloneable, Serializable {
29     /**
30      * ZipShort with a value of 0.
31      *
32      * @since 1.14
33      */

34     public static final ZipShort ZERO = new ZipShort(0);
35
36     private static final long serialVersionUID = 1L;
37
38     /**
39      * Gets value as two bytes in big-endian byte order.
40      *
41      * @param value the Java int to convert to bytes
42      * @return the converted int as a byte array in big-endian byte order
43      */

44     public static byte[] getBytes(final int value) {
45         final byte[] result = new byte[2];
46         putShort(value, result, 0);
47         return result;
48     }
49
50     /**
51      * Helper method to get the value as a Java int from a two-byte array
52      *
53      * @param bytes the array of bytes
54      * @return the corresponding Java int value
55      */

56     public static int getValue(final byte[] bytes) {
57         return getValue(bytes, 0);
58     }
59
60     /**
61      * Helper method to get the value as a Java int from two bytes starting at given array offset
62      *
63      * @param bytes  the array of bytes
64      * @param offset the offset to start
65      * @return the corresponding Java int value
66      */

67     public static int getValue(final byte[] bytes, final int offset) {
68         return (int) ByteUtils.fromLittleEndian(bytes, offset, 2);
69     }
70
71     /**
72      * put the value as two bytes in big-endian byte order.
73      *
74      * @param value  the Java int to convert to bytes
75      * @param buf    the output buffer
76      * @param offset The offset within the output buffer of the first byte to be written. must be non-negative and no larger than {@code buf.length-2}
77      */

78     public static void putShort(final int value, final byte[] buf, final int offset) {
79         ByteUtils.toLittleEndian(buf, value, offset, 2);
80     }
81
82     private final int value;
83
84     /**
85      * Constructs a new instance from bytes.
86      *
87      * @param bytes the bytes to store as a ZipShort
88      */

89     public ZipShort(final byte[] bytes) {
90         this(bytes, 0);
91     }
92
93     /**
94      * Constructs a new instance from the two bytes starting at offset.
95      *
96      * @param bytes  the bytes to store as a ZipShort
97      * @param offset the offset to start
98      */

99     public ZipShort(final byte[] bytes, final int offset) {
100         value = ZipShort.getValue(bytes, offset);
101     }
102
103     /**
104      * Constructs a new instance from a number.
105      *
106      * @param value the int to store as a ZipShort
107      */

108     public ZipShort(final int value) {
109         this.value = value;
110     }
111
112     @Override
113     public Object clone() {
114         try {
115             return super.clone();
116         } catch (final CloneNotSupportedException cnfe) {
117             // impossible
118             throw new UnsupportedOperationException(cnfe); // NOSONAR
119         }
120     }
121
122     /**
123      * Override to make two instances with same value equal.
124      *
125      * @param o an object to compare
126      * @return true if the objects are equal
127      */

128     @Override
129     public boolean equals(final Object o) {
130         if (!(o instanceof ZipShort)) {
131             return false;
132         }
133         return value == ((ZipShort) o).getValue();
134     }
135
136     /**
137      * Gets value as two bytes in big-endian byte order.
138      *
139      * @return the value as a two byte array in big-endian byte order
140      */

141     public byte[] getBytes() {
142         final byte[] result = new byte[2];
143         ByteUtils.toLittleEndian(result, value, 0, 2);
144         return result;
145     }
146
147     /**
148      * Gets value as Java int.
149      *
150      * @return value as a Java int
151      */

152     public int getValue() {
153         return value;
154     }
155
156     /**
157      * Override to make two instances with same value equal.
158      *
159      * @return the value stored in the ZipShort
160      */

161     @Override
162     public int hashCode() {
163         return value;
164     }
165
166     @Override
167     public String toString() {
168         return "ZipShort value: " + value;
169     }
170 }
171