Mercurial > hg4j
diff src/org/tmatesoft/hg/core/Nodeid.java @ 74:6f1b88693d48
Complete refactoring to org.tmatesoft
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Mon, 24 Jan 2011 03:14:45 +0100 |
parents | src/com/tmate/hgkit/ll/Nodeid.java@4022c34a4804 |
children | c25c5c348d1b |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/tmatesoft/hg/core/Nodeid.java Mon Jan 24 03:14:45 2011 +0100 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2010-2011 TMate Software Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * 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 General Public License for more details. + * + * For information on how to redistribute this software under + * the terms of a license other than GNU General Public License + * contact TMate Software at support@svnkit.com + */ +package org.tmatesoft.hg.core; + +import static org.tmatesoft.hg.internal.DigestHelper.toHexString; + +import java.util.Arrays; + + + +/** + * A 20-bytes (40 characters) long hash value to identify a revision. + * @see http://mercurial.selenic.com/wiki/Nodeid + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + * + */ +public final class Nodeid { + + /** + * <b>nullid</b>, empty root revision. + */ + public static final Nodeid NULL = new Nodeid(new byte[20], false); + + private final byte[] binaryData; + + /** + * @param binaryRepresentation - array of exactly 20 bytes + * @param shallClone - true if array is subject to future modification and shall be copied, not referenced + */ + public Nodeid(byte[] binaryRepresentation, boolean shallClone) { + // 5 int fields => 32 bytes + // byte[20] => 48 bytes + if (binaryRepresentation == null || binaryRepresentation.length != 20) { + throw new IllegalArgumentException(); + } + this.binaryData = shallClone ? binaryRepresentation.clone() : binaryRepresentation; + } + + @Override + public int hashCode() { + // digest (part thereof) seems to be nice candidate for the hashCode + byte[] b = binaryData; + return b[0] << 24 | (b[1] & 0xFF) << 16 | (b[2] & 0xFF) << 8 | (b[3] & 0xFF); + } + + @Override + public boolean equals(Object o) { + if (o instanceof Nodeid) { + return Arrays.equals(this.binaryData, ((Nodeid) o).binaryData); + } + return false; + } + + public boolean equalsTo(byte[] buf) { + return Arrays.equals(this.binaryData, buf); + } + + @Override + public String toString() { + // XXX may want to output just single 0 for the NULL id? + return toHexString(binaryData, 0, binaryData.length); + } + + public String shortNotation() { + return toHexString(binaryData, 0, 6); + } + + public boolean isNull() { + if (this == NULL) { + return true; + } + for (int i = 0; i < 20; i++) { + if (this.binaryData[i] != 0) { + return false; + } + } + return true; + } + + // copy + public byte[] toByteArray() { + return binaryData.clone(); + } + + // primary difference with cons is handling of NULL id (this method returns constant) + // always makes a copy of an array passed + public static Nodeid fromBinary(byte[] binaryRepresentation, int offset) { + if (binaryRepresentation == null || binaryRepresentation.length - offset < 20) { + throw new IllegalArgumentException(); + } + int i = 0; + while (i < 20 && binaryRepresentation[offset+i] == 0) i++; + if (i == 20) { + return NULL; + } + if (offset == 0 && binaryRepresentation.length == 20) { + return new Nodeid(binaryRepresentation, true); + } + byte[] b = new byte[20]; // create new instance if no other reasonable guesses possible + System.arraycopy(binaryRepresentation, offset, b, 0, 20); + return new Nodeid(b, false); + } + + public static Nodeid fromAscii(byte[] asciiRepresentation, int offset, int length) { + if (length != 40) { + throw new IllegalArgumentException(); + } + byte[] data = new byte[20]; + boolean zeroBytes = true; + for (int i = 0, j = offset; i < data.length; i++) { + int hiNibble = Character.digit(asciiRepresentation[j++], 16); + int lowNibble = Character.digit(asciiRepresentation[j++], 16); + byte b = (byte) (((hiNibble << 4) | lowNibble) & 0xFF); + data[i] = b; + zeroBytes = zeroBytes && b == 0; + } + if (zeroBytes) { + return NULL; + } + return new Nodeid(data, false); + } +}