comparison src/com/tmate/hgkit/ll/Nodeid.java @ 24:d4fdd1845b3f

Nodeid with array of exactly 20 bytes
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 06 Jan 2011 04:42:15 +0100
parents 603806cd2dc6
children b2251b7a9823
comparison
equal deleted inserted replaced
23:6f9aca1a97be 24:d4fdd1845b3f
1 /* 1 /*
2 * Copyright (c) 2010, 2011 Artem Tikhomirov 2 * Copyright (c) 2010, 2011 Artem Tikhomirov
3 */ 3 */
4 package com.tmate.hgkit.ll; 4 package com.tmate.hgkit.ll;
5
6 import java.util.Arrays;
5 7
6 8
7 9
8 /** 10 /**
9 * Whether to store fixed size array (20 bytes) - ease of manipulation (e.g. hashcode/equals), or 11 * Whether to store fixed size array (20 bytes) - ease of manipulation (e.g. hashcode/equals), or
11 * Fixed size array looks most appealing to me now - I doubt one can save any significant amount of memory. 13 * Fixed size array looks most appealing to me now - I doubt one can save any significant amount of memory.
12 * There'd always 20 non-zero bytes, the difference is only for any extra bytes one may pass to constructor 14 * There'd always 20 non-zero bytes, the difference is only for any extra bytes one may pass to constructor
13 * @author artem 15 * @author artem
14 * 16 *
15 */ 17 */
16 public final class Nodeid implements Comparable<Nodeid> { 18 public final class Nodeid {
17 19
18 public static int NULLREV = -1; 20 public static int NULLREV = -1;
19 private final byte[] binaryData; 21 private final byte[] binaryData;
20 22
23 /**
24 * @param binaryRepresentation - byte[20], kept by reference. Use {@link #clone()} if original array may get changed.
25 */
21 public Nodeid(byte[] binaryRepresentation) { 26 public Nodeid(byte[] binaryRepresentation) {
22 // 5 int fields => 32 bytes 27 // 5 int fields => 32 bytes
23 // byte[20] => 48 bytes 28 // byte[20] => 48 bytes
29 if (binaryRepresentation == null || binaryRepresentation.length != 20) {
30 throw new IllegalArgumentException();
31 }
24 this.binaryData = binaryRepresentation; 32 this.binaryData = binaryRepresentation;
25 } 33 }
26 34
27 // instead of hashCode/equals 35 @Override
28 public int compareTo(Nodeid o) { 36 public int hashCode() {
29 return equals(this.binaryData, o.binaryData) ? 0 : -1; 37 // TODO consider own impl, especially if byte[] get replaced with 5 ints
38 return Arrays.hashCode(binaryData);
39 }
40
41 @Override
42 public boolean equals(Object o) {
43 if (o instanceof Nodeid) {
44 return Arrays.equals(this.binaryData, ((Nodeid) o).binaryData);
45 }
46 return false;
30 } 47 }
31 48
32 public boolean equalsTo(byte[] buf) { 49 public boolean equalsTo(byte[] buf) {
33 return equals(this.binaryData, buf); 50 return Arrays.equals(this.binaryData, buf);
34 } 51 }
35 52
36 private static boolean equals(byte[] a1, byte[] a2) {
37 if (a1 == null || a1.length < 20 || a2 == null || a2.length < 20) {
38 throw new IllegalArgumentException();
39 }
40 // assume significant bits are at the end of the array
41 final int s1 = a1.length - 20, s2 = a2.length - 20;
42 for (int i = 0; i < 20; i++) {
43 if (a1[s1+i] != a2[s2+i]) {
44 return false;
45 }
46 }
47 return true;
48 }
49
50 @Override 53 @Override
51 public String toString() { 54 public String toString() {
52 return new DigestHelper().toHexString(binaryData, 0, binaryData.length); 55 return new DigestHelper().toHexString(binaryData, 0, binaryData.length);
53 } 56 }
54 57
55 // binascii.unhexlify() 58 // binascii.unhexlify()
56 public static Nodeid fromAscii(byte[] asciiRepresentation, int offset, int length) { 59 public static Nodeid fromAscii(byte[] asciiRepresentation, int offset, int length) {
57 assert length % 2 == 0; // Python's binascii.hexlify convert each byte into 2 digits 60 if (length != 40) {
58 byte[] data = new byte[length >>> 1]; // XXX use known size instead? nodeid is always 20 bytes 61 throw new IllegalArgumentException();
62 }
63 byte[] data = new byte[20];
59 for (int i = 0, j = offset; i < data.length; i++) { 64 for (int i = 0, j = offset; i < data.length; i++) {
60 int hiNibble = Character.digit(asciiRepresentation[j++], 16); 65 int hiNibble = Character.digit(asciiRepresentation[j++], 16);
61 int lowNibble = Character.digit(asciiRepresentation[j++], 16); 66 int lowNibble = Character.digit(asciiRepresentation[j++], 16);
62 data[i] = (byte) (((hiNibble << 4) | lowNibble) & 0xFF); 67 data[i] = (byte) (((hiNibble << 4) | lowNibble) & 0xFF);
63 } 68 }