/*
* SonarQube
* Copyright (C) 2009-2017 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.duplications.block;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Arrays;
/**
* Represents hash for {@link Block}. Immutable.
*
* TODO Godin: would be better to rename to BlockHash,
* also maybe we can incorporate it into Block to reduce memory footprint during detection of duplicates
*/
public final class ByteArray {
private final byte[] bytes;
/**
* Cache for hash code.
*/
private int hash;
public ByteArray(String hexString) {
int len = hexString.length();
this.bytes = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
}
}
public ByteArray(byte[] bytes) {
this.bytes = new byte[bytes.length];
System.arraycopy(bytes, 0, this.bytes, 0, bytes.length);
}
public ByteArray(long value) {
this.bytes = new byte[] {
(byte) (value >>> 56),
(byte) (value >>> 48),
(byte) (value >>> 40),
(byte) (value >>> 32),
(byte) (value >>> 24),
(byte) (value >>> 16),
(byte) (value >>> 8),
(byte) value};
}
public ByteArray(int value) {
this.bytes = new byte[] {
(byte) (value >>> 24),
(byte) (value >>> 16),
(byte) (value >>> 8),
(byte) value};
}
public ByteArray(int[] intArray) {
ByteBuffer bb = ByteBuffer.allocate(intArray.length * 4);
for (int i : intArray) {
bb.putInt(i);
}
this.bytes = bb.array();
}
public byte[] getBytes() {
return bytes;
}
public int[] toIntArray() {
// Pad the size to multiple of 4
int size = (bytes.length / 4) + (bytes.length % 4 == 0 ? 0 : 1);
ByteBuffer bb = ByteBuffer.allocate(size * 4);
bb.put(bytes);
bb.rewind();
IntBuffer ib = bb.asIntBuffer();
int[] result = new int[size];
ib.get(result);
return result;
}
private static final String HEXES = "0123456789abcdef";
public String toHexString() {
StringBuilder hex = new StringBuilder(2 * bytes.length);
for (byte b : bytes) {
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt(b & 0x0F));
}
return hex.toString();
}
@Override
public String toString() {
return toHexString();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ByteArray other = (ByteArray) o;
return Arrays.equals(bytes, other.bytes);
}
@Override
public int hashCode() {
int h = hash;
int len = bytes.length;
if (h == 0 && len > 0) {
h = Arrays.hashCode(bytes);
hash = h;
}
return h;
}
}