comparison hg4j/src/main/java/org/tmatesoft/hg/core/Nodeid.java @ 213:6ec4af642ba8 gradle

Project uses Gradle for build - actual changes
author Alexander Kitaev <kitaev@gmail.com>
date Tue, 10 May 2011 10:52:53 +0200
parents
children
comparison
equal deleted inserted replaced
212:edb2e2829352 213:6ec4af642ba8
1 /*
2 * Copyright (c) 2010-2011 TMate Software Ltd
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * For information on how to redistribute this software under
14 * the terms of a license other than GNU General Public License
15 * contact TMate Software at support@hg4j.com
16 */
17 package org.tmatesoft.hg.core;
18
19 import static org.tmatesoft.hg.internal.DigestHelper.toHexString;
20
21 import java.util.Arrays;
22
23
24
25 /**
26 * A 20-bytes (40 characters) long hash value to identify a revision.
27 * @see http://mercurial.selenic.com/wiki/Nodeid
28 *
29 * @author Artem Tikhomirov
30 * @author TMate Software Ltd.
31 *
32 */
33 public final class Nodeid implements Comparable<Nodeid> {
34
35 /**
36 * <b>nullid</b>, empty root revision.
37 */
38 public static final Nodeid NULL = new Nodeid(new byte[20], false);
39
40 private final byte[] binaryData;
41
42 /**
43 * @param binaryRepresentation - array of exactly 20 bytes
44 * @param shallClone - true if array is subject to future modification and shall be copied, not referenced
45 * @throws IllegalArgumentException if supplied binary representation doesn't correspond to 20 bytes of sha1 digest
46 */
47 public Nodeid(byte[] binaryRepresentation, boolean shallClone) {
48 // 5 int fields => 32 bytes
49 // byte[20] => 48 bytes (16 bytes is Nodeid with one field, 32 bytes for byte[20]
50 if (binaryRepresentation == null || binaryRepresentation.length != 20) {
51 throw new IllegalArgumentException();
52 }
53 /*
54 * byte[].clone() is not reflected when ran with -agentlib:hprof=heap=sites
55 * thus not to get puzzled why there are N Nodeids and much less byte[] instances,
56 * may use following code to see N byte[] as well.
57 *
58 if (shallClone) {
59 binaryData = new byte[20];
60 System.arraycopy(binaryRepresentation, 0, binaryData, 0, 20);
61 } else {
62 binaryData = binaryRepresentation;
63 }
64 */
65 binaryData = shallClone ? binaryRepresentation.clone() : binaryRepresentation;
66 }
67
68 @Override
69 public int hashCode() {
70 // digest (part thereof) seems to be nice candidate for the hashCode
71 byte[] b = binaryData;
72 return b[0] << 24 | (b[1] & 0xFF) << 16 | (b[2] & 0xFF) << 8 | (b[3] & 0xFF);
73 }
74
75 @Override
76 public boolean equals(Object o) {
77 if (o instanceof Nodeid) {
78 return this == o || equalsTo(((Nodeid) o).binaryData);
79 }
80 return false;
81 }
82
83 public boolean equalsTo(byte[] buf) {
84 return Arrays.equals(this.binaryData, buf);
85 }
86
87 public int compareTo(Nodeid o) {
88 if (this == o) {
89 return 0;
90 }
91 for (int i = 0; i < 20; i++) {
92 if (binaryData[i] != o.binaryData[i]) {
93 return binaryData[i] < o.binaryData[i] ? -1 : 1;
94 }
95 }
96 return 0;
97 }
98
99 @Override
100 public String toString() {
101 // XXX may want to output just single 0 for the NULL id?
102 return toHexString(binaryData, 0, binaryData.length);
103 }
104
105 public String shortNotation() {
106 return toHexString(binaryData, 0, 6);
107 }
108
109 public boolean isNull() {
110 if (this == NULL) {
111 return true;
112 }
113 for (int i = 0; i < 20; i++) {
114 if (this.binaryData[i] != 0) {
115 return false;
116 }
117 }
118 return true;
119 }
120
121 // copy
122 public byte[] toByteArray() {
123 return binaryData.clone();
124 }
125
126 /**
127 * Factory for {@link Nodeid Nodeids}.
128 * Primary difference with cons is handling of NULL id (this method returns constant) and control over array
129 * duplication - this method always makes a copy of an array passed
130 * @param binaryRepresentation - byte array of a length at least offset + 20
131 * @param offset - index in the array to start from
132 * @throws IllegalArgumentException when arguments don't select 20 bytes
133 */
134 public static Nodeid fromBinary(byte[] binaryRepresentation, int offset) {
135 if (binaryRepresentation == null || binaryRepresentation.length - offset < 20) {
136 throw new IllegalArgumentException();
137 }
138 int i = 0;
139 while (i < 20 && binaryRepresentation[offset+i] == 0) i++;
140 if (i == 20) {
141 return NULL;
142 }
143 if (offset == 0 && binaryRepresentation.length == 20) {
144 return new Nodeid(binaryRepresentation, true);
145 }
146 byte[] b = new byte[20]; // create new instance if no other reasonable guesses possible
147 System.arraycopy(binaryRepresentation, offset, b, 0, 20);
148 return new Nodeid(b, false);
149 }
150
151 /**
152 * Parse encoded representation.
153 *
154 * @param asciiRepresentation - encoded form of the Nodeid.
155 * @return object representation
156 * @throws IllegalArgumentException when argument doesn't match encoded form of 20-bytes sha1 digest.
157 */
158 public static Nodeid fromAscii(String asciiRepresentation) {
159 if (asciiRepresentation.length() != 40) {
160 throw new IllegalArgumentException();
161 }
162 // XXX is better impl for String possible?
163 return fromAscii(asciiRepresentation.getBytes(), 0, 40);
164 }
165
166 /**
167 * Parse encoded representation. Similar to {@link #fromAscii(String)}.
168 */
169 public static Nodeid fromAscii(byte[] asciiRepresentation, int offset, int length) {
170 if (length != 40) {
171 throw new IllegalArgumentException();
172 }
173 byte[] data = new byte[20];
174 boolean zeroBytes = true;
175 for (int i = 0, j = offset; i < data.length; i++) {
176 int hiNibble = Character.digit(asciiRepresentation[j++], 16);
177 int lowNibble = Character.digit(asciiRepresentation[j++], 16);
178 byte b = (byte) (((hiNibble << 4) | lowNibble) & 0xFF);
179 data[i] = b;
180 zeroBytes = zeroBytes && b == 0;
181 }
182 if (zeroBytes) {
183 return NULL;
184 }
185 return new Nodeid(data, false);
186 }
187 }