001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.commons.compress.archivers.zip; 020 021import java.io.Serializable; 022 023import org.apache.commons.compress.utils.ByteUtils; 024import org.apache.commons.lang3.ArrayUtils; 025 026/** 027 * Utility class that represents a two byte integer with conversion rules for the little-endian byte order of ZIP files. 028 * 029 * @Immutable 030 */ 031public final class ZipShort implements Cloneable, Serializable { 032 033 private static final int SIZE = 2; 034 035 /** 036 * ZipShort with a value of 0. 037 * 038 * @since 1.14 039 */ 040 public static final ZipShort ZERO = new ZipShort(0); 041 042 private static final long serialVersionUID = 1L; 043 044 /** 045 * Gets value as two bytes in big-endian byte order. 046 * 047 * @param value the Java int to convert to bytes 048 * @return the converted int as a byte array in big-endian byte order 049 */ 050 public static byte[] getBytes(final int value) { 051 final byte[] result = new byte[SIZE]; 052 putShort(value, result, 0); 053 return result; 054 } 055 056 /** 057 * Helper method to get the value as a Java int from a two-byte array 058 * 059 * @param bytes the array of bytes 060 * @return the corresponding Java int value 061 */ 062 public static int getValue(final byte[] bytes) { 063 return getValue(bytes, 0); 064 } 065 066 /** 067 * Helper method to get the value as a Java int from two bytes starting at given array offset 068 * 069 * @param bytes the array of bytes 070 * @param offset the offset to start 071 * @return the corresponding Java int value 072 */ 073 public static int getValue(final byte[] bytes, final int offset) { 074 return (int) ByteUtils.fromLittleEndian(bytes, offset, SIZE); 075 } 076 077 static ZipShort lengthOf(final byte[] array) { 078 return new ZipShort(ArrayUtils.getLength(array)); 079 } 080 081 /** 082 * put the value as two bytes in big-endian byte order. 083 * 084 * @param value the Java int to convert to bytes 085 * @param buf the output buffer 086 * @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} 087 */ 088 public static void putShort(final int value, final byte[] buf, final int offset) { 089 ByteUtils.toLittleEndian(buf, value, offset, SIZE); 090 } 091 092 private final int value; 093 094 /** 095 * Constructs a new instance from bytes. 096 * 097 * @param bytes the bytes to store as a ZipShort 098 */ 099 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}