View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.commons.compress.archivers.zip;
20  
21  import java.io.Serializable;
22  
23  import org.apache.commons.compress.utils.ByteUtils;
24  import org.apache.commons.lang3.ArrayUtils;
25  
26  /**
27   * Utility class that represents a two byte integer with conversion rules for the little-endian byte order of ZIP files.
28   *
29   * @Immutable
30   */
31  public final class ZipShort implements Cloneable, Serializable {
32  
33      private static final int SIZE = 2;
34  
35      /**
36       * ZipShort with a value of 0.
37       *
38       * @since 1.14
39       */
40      public static final ZipShort ZERO = new ZipShort(0);
41  
42      private static final long serialVersionUID = 1L;
43  
44      /**
45       * Gets value as two bytes in big-endian byte order.
46       *
47       * @param value the Java int to convert to bytes
48       * @return the converted int as a byte array in big-endian byte order
49       */
50      public static byte[] getBytes(final int value) {
51          final byte[] result = new byte[SIZE];
52          putShort(value, result, 0);
53          return result;
54      }
55  
56      /**
57       * Helper method to get the value as a Java int from a two-byte array
58       *
59       * @param bytes the array of bytes
60       * @return the corresponding Java int value
61       */
62      public static int getValue(final byte[] bytes) {
63          return getValue(bytes, 0);
64      }
65  
66      /**
67       * Helper method to get the value as a Java int from two bytes starting at given array offset
68       *
69       * @param bytes  the array of bytes
70       * @param offset the offset to start
71       * @return the corresponding Java int value
72       */
73      public static int getValue(final byte[] bytes, final int offset) {
74          return (int) ByteUtils.fromLittleEndian(bytes, offset, SIZE);
75      }
76  
77      static ZipShort lengthOf(final byte[] array) {
78          return new ZipShort(ArrayUtils.getLength(array));
79      }
80  
81      /**
82       * put the value as two bytes in big-endian byte order.
83       *
84       * @param value  the Java int to convert to bytes
85       * @param buf    the output buffer
86       * @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}
87       */
88      public static void putShort(final int value, final byte[] buf, final int offset) {
89          ByteUtils.toLittleEndian(buf, value, offset, SIZE);
90      }
91  
92      private final int value;
93  
94      /**
95       * Constructs a new instance from bytes.
96       *
97       * @param bytes the bytes to store as a ZipShort
98       */
99      public ZipShort(final byte[] bytes) {
100         this(bytes, 0);
101     }
102 
103     /**
104      * Constructs a new instance from the two bytes starting at offset.
105      *
106      * @param bytes  the bytes to store as a ZipShort
107      * @param offset the offset to start
108      */
109     public ZipShort(final byte[] bytes, final int offset) {
110         value = getValue(bytes, offset);
111     }
112 
113     /**
114      * Constructs a new instance from a number.
115      *
116      * @param value the int to store as a ZipShort
117      */
118     public ZipShort(final int value) {
119         this.value = value;
120     }
121 
122     @Override
123     public Object clone() {
124         try {
125             return super.clone();
126         } catch (final CloneNotSupportedException cnfe) {
127             // impossible
128             throw new UnsupportedOperationException(cnfe); // NOSONAR
129         }
130     }
131 
132     /**
133      * Override to make two instances with same value equal.
134      *
135      * @param o an object to compare
136      * @return true if the objects are equal
137      */
138     @Override
139     public boolean equals(final Object o) {
140         if (!(o instanceof ZipShort)) {
141             return false;
142         }
143         return value == ((ZipShort) o).getValue();
144     }
145 
146     /**
147      * Gets value as two bytes in big-endian byte order.
148      *
149      * @return the value as a two byte array in big-endian byte order
150      */
151     public byte[] getBytes() {
152         final byte[] result = new byte[SIZE];
153         ByteUtils.toLittleEndian(result, value, 0, SIZE);
154         return result;
155     }
156 
157     /**
158      * Gets value as Java int.
159      *
160      * @return value as a Java int
161      */
162     public int getValue() {
163         return value;
164     }
165 
166     /**
167      * Override to make two instances with same value equal.
168      *
169      * @return the value stored in the ZipShort
170      */
171     @Override
172     public int hashCode() {
173         return value;
174     }
175 
176     @Override
177     public String toString() {
178         return "ZipShort value: " + value;
179     }
180 }