001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.duplications.block;
021
022 import java.nio.ByteBuffer;
023 import java.nio.IntBuffer;
024 import java.util.Arrays;
025
026 /**
027 * Represents hash for {@link Block}. Immutable.
028 *
029 * TODO Godin: would be better to rename to BlockHash,
030 * also maybe we can incorporate it into Block to reduce memory footprint during detection of duplicates
031 */
032 public final class ByteArray {
033
034 private final byte[] bytes;
035
036 /**
037 * Cache for hash code.
038 */
039 private int hash;
040
041 public ByteArray(String hexString) {
042 int len = hexString.length();
043 this.bytes = new byte[len / 2];
044 for (int i = 0; i < len; i += 2) {
045 bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
046 }
047 }
048
049 public ByteArray(byte[] bytes) {
050 this.bytes = new byte[bytes.length];
051 System.arraycopy(bytes, 0, this.bytes, 0, bytes.length);
052 }
053
054 public ByteArray(long value) {
055 this.bytes = new byte[] {
056 (byte) (value >>> 56),
057 (byte) (value >>> 48),
058 (byte) (value >>> 40),
059 (byte) (value >>> 32),
060 (byte) (value >>> 24),
061 (byte) (value >>> 16),
062 (byte) (value >>> 8),
063 (byte) value };
064 }
065
066 public ByteArray(int value) {
067 this.bytes = new byte[] {
068 (byte) (value >>> 24),
069 (byte) (value >>> 16),
070 (byte) (value >>> 8),
071 (byte) value };
072 }
073
074 public ByteArray(int[] intArray) {
075 ByteBuffer bb = ByteBuffer.allocate(intArray.length * 4);
076 for (int i : intArray) {
077 bb.putInt(i);
078 }
079 this.bytes = bb.array();
080 }
081
082 public int[] toIntArray() {
083 int size = (bytes.length / 4) + (bytes.length % 4 == 0 ? 0 : 1); // Pad the size to multiple of 4
084 ByteBuffer bb = ByteBuffer.allocate(size * 4);
085 bb.put(bytes);
086 bb.rewind();
087 IntBuffer ib = bb.asIntBuffer();
088 int[] result = new int[size];
089 ib.get(result);
090 return result;
091 }
092
093 private static final String HEXES = "0123456789abcdef";
094
095 public String toHexString() {
096 StringBuilder hex = new StringBuilder(2 * bytes.length);
097 for (byte b : bytes) {
098 hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
099 }
100 return hex.toString();
101 }
102
103 @Override
104 public String toString() {
105 return toHexString();
106 }
107
108 @Override
109 public boolean equals(Object o) {
110 if (this == o) {
111 return true;
112 }
113 if (o == null || getClass() != o.getClass()) {
114 return false;
115 }
116 ByteArray other = (ByteArray) o;
117 return Arrays.equals(bytes, other.bytes);
118 }
119
120 @Override
121 public int hashCode() {
122 int h = hash;
123 int len = bytes.length;
124 if (h == 0 && len > 0) {
125 h = Arrays.hashCode(bytes);
126 hash = h;
127 }
128 return h;
129 }
130
131 }