2 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * - Neither the name of the Git Development Community nor the
19 * names of its contributors may be used to endorse or promote
20 * products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 package org
.spearce
.jgit
.lib
;
40 import java
.io
.IOException
;
41 import java
.io
.OutputStream
;
42 import java
.io
.Writer
;
43 import java
.nio
.ByteBuffer
;
44 import java
.util
.Arrays
;
46 import org
.spearce
.jgit
.util
.NB
;
49 * A (possibly mutable) SHA-1 abstraction.
51 * If this is an instance of {@link MutableObjectId} the concept of equality
52 * with this instance can alter at any time, if this instance is modified to
53 * represent a different object name.
55 public abstract class AnyObjectId
implements Comparable
{
56 static final int RAW_LEN
= Constants
.OBJECT_ID_LENGTH
;
58 static final int STR_LEN
= RAW_LEN
* 2;
60 static final byte fromhex
[];
63 fromhex
= new byte['f' + 1];
64 Arrays
.fill(fromhex
, (byte) -1);
65 for (char i
= '0'; i
<= '9'; i
++)
66 fromhex
[i
] = (byte) (i
- '0');
67 for (char i
= 'a'; i
<= 'f'; i
++)
68 fromhex
[i
] = (byte) ((i
- 'a') + 10);
71 throw new LinkageError("ObjectId expects"
72 + " Constants.OBJECT_ID_LENGTH = 20; it is " + RAW_LEN
77 * Compare to object identifier byte sequences for equality.
79 * @param firstObjectId
80 * the first identifier to compare. Must not be null.
81 * @param secondObjectId
82 * the second identifier to compare. Must not be null.
83 * @return true if the two identifiers are the same.
85 public static boolean equals(final AnyObjectId firstObjectId
,
86 final AnyObjectId secondObjectId
) {
87 if (firstObjectId
== secondObjectId
)
90 // We test word 2 first as odds are someone already used our
91 // word 1 as a hash code, and applying that came up with these
92 // two instances we are comparing for equality. Therefore the
93 // first two words are very likely to be identical. We want to
94 // break away from collisions as quickly as possible.
96 return firstObjectId
.w2
== secondObjectId
.w2
97 && firstObjectId
.w3
== secondObjectId
.w3
98 && firstObjectId
.w4
== secondObjectId
.w4
99 && firstObjectId
.w5
== secondObjectId
.w5
100 && firstObjectId
.w1
== secondObjectId
.w1
;
103 static final int hexUInt32(final byte[] bs
, final int p
) {
104 int r
= fromhex
[bs
[p
]] << 4;
106 r
|= fromhex
[bs
[p
+ 1]];
109 r
|= fromhex
[bs
[p
+ 2]];
112 r
|= fromhex
[bs
[p
+ 3]];
115 r
|= fromhex
[bs
[p
+ 4]];
118 r
|= fromhex
[bs
[p
+ 5]];
121 r
|= fromhex
[bs
[p
+ 6]];
123 final int last
= fromhex
[bs
[p
+ 7]];
124 if (r
< 0 || last
< 0)
125 throw new ArrayIndexOutOfBoundsException();
126 return (r
<< 4) | last
;
142 * @return a discriminator usable for a fan-out style map
144 public final int getFirstByte() {
149 * Compare this ObjectId to another and obtain a sort ordering.
152 * the other id to compare to. Must not be null.
153 * @return < 0 if this id comes before other; 0 if this id is equal to
154 * other; > 0 if this id comes after other.
156 public int compareTo(final ObjectId other
) {
162 cmp
= NB
.compareUInt32(w1
, other
.w1
);
166 cmp
= NB
.compareUInt32(w2
, other
.w2
);
170 cmp
= NB
.compareUInt32(w3
, other
.w3
);
174 cmp
= NB
.compareUInt32(w4
, other
.w4
);
178 return NB
.compareUInt32(w5
, other
.w5
);
181 public int compareTo(final Object other
) {
182 return compareTo(((ObjectId
) other
));
185 int compareTo(final byte[] bs
, final int p
) {
188 cmp
= NB
.compareUInt32(w1
, NB
.decodeInt32(bs
, p
));
192 cmp
= NB
.compareUInt32(w2
, NB
.decodeInt32(bs
, p
+ 4));
196 cmp
= NB
.compareUInt32(w3
, NB
.decodeInt32(bs
, p
+ 8));
200 cmp
= NB
.compareUInt32(w4
, NB
.decodeInt32(bs
, p
+ 12));
204 return NB
.compareUInt32(w5
, NB
.decodeInt32(bs
, p
+ 16));
207 int compareTo(final int[] bs
, final int p
) {
210 cmp
= NB
.compareUInt32(w1
, bs
[p
]);
214 cmp
= NB
.compareUInt32(w2
, bs
[p
+ 1]);
218 cmp
= NB
.compareUInt32(w3
, bs
[p
+ 2]);
222 cmp
= NB
.compareUInt32(w4
, bs
[p
+ 3]);
226 return NB
.compareUInt32(w5
, bs
[p
+ 4]);
229 public int hashCode() {
234 * Determine if this ObjectId has exactly the same value as another.
237 * the other id to compare to. May be null.
238 * @return true only if both ObjectIds have identical bits.
240 public boolean equals(final ObjectId other
) {
241 return other
!= null ?
equals(this, other
) : false;
244 public boolean equals(final Object o
) {
245 return equals((ObjectId
) o
);
249 * Copy this ObjectId to an output writer in raw binary.
252 * the buffer to copy to. Must be in big endian order.
254 public void copyRawTo(final ByteBuffer w
) {
263 * Copy this ObjectId to a byte array.
266 * the buffer to copy to.
268 * the offset within b to write at.
270 public void copyRawTo(final byte[] b
, final int o
) {
271 NB
.encodeInt32(b
, o
, w1
);
272 NB
.encodeInt32(b
, o
+ 4, w2
);
273 NB
.encodeInt32(b
, o
+ 8, w3
);
274 NB
.encodeInt32(b
, o
+ 12, w4
);
275 NB
.encodeInt32(b
, o
+ 16, w5
);
279 * Copy this ObjectId to an int array.
282 * the buffer to copy to.
284 * the offset within b to write at.
286 public void copyRawTo(final int[] b
, final int o
) {
295 * Copy this ObjectId to an output writer in raw binary.
298 * the stream to write to.
299 * @throws IOException
300 * the stream writing failed.
302 public void copyRawTo(final OutputStream w
) throws IOException
{
310 private static void writeRawInt(final OutputStream w
, int v
)
319 * Copy this ObjectId to an output writer in hex format.
322 * the stream to copy to.
323 * @throws IOException
324 * the stream writing failed.
326 public void copyTo(final OutputStream w
) throws IOException
{
327 w
.write(toHexByteArray());
330 private byte[] toHexByteArray() {
331 final byte[] dst
= new byte[STR_LEN
];
332 formatHexByte(dst
, 0, w1
);
333 formatHexByte(dst
, 8, w2
);
334 formatHexByte(dst
, 16, w3
);
335 formatHexByte(dst
, 24, w4
);
336 formatHexByte(dst
, 32, w5
);
340 private static final byte[] hexbyte
= { '0', '1', '2', '3', '4', '5', '6',
341 '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
343 private static void formatHexByte(final byte[] dst
, final int p
, int w
) {
345 while (o
>= p
&& w
!= 0) {
346 dst
[o
--] = hexbyte
[w
& 0xf];
354 * Copy this ObjectId to an output writer in hex format.
357 * the stream to copy to.
358 * @throws IOException
359 * the stream writing failed.
361 public void copyTo(final Writer w
) throws IOException
{
362 w
.write(toHexCharArray());
366 * Copy this ObjectId to an output writer in hex format.
369 * temporary char array to buffer construct into before writing.
370 * Must be at least large enough to hold 2 digits for each byte
371 * of object id (40 characters or larger).
373 * the stream to copy to.
374 * @throws IOException
375 * the stream writing failed.
377 public void copyTo(final char[] tmp
, final Writer w
) throws IOException
{
382 private char[] toHexCharArray() {
383 final char[] dst
= new char[STR_LEN
];
388 private void toHexCharArray(final char[] dst
) {
389 formatHexChar(dst
, 0, w1
);
390 formatHexChar(dst
, 8, w2
);
391 formatHexChar(dst
, 16, w3
);
392 formatHexChar(dst
, 24, w4
);
393 formatHexChar(dst
, 32, w5
);
396 private static final char[] hexchar
= { '0', '1', '2', '3', '4', '5', '6',
397 '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
399 private static void formatHexChar(final char[] dst
, final int p
, int w
) {
401 while (o
>= p
&& w
!= 0) {
402 dst
[o
--] = hexchar
[w
& 0xf];
410 public String
toString() {
411 return "AnyObjectId[" + name() + "]";
415 * @return string form of the SHA-1, in lower case hexadecimal.
417 public final String
name() {
418 return new String(toHexCharArray());
422 * Return unique abbreviation (prefix) of this object SHA-1.
424 * Current implementation is not guaranteeing uniqueness, it just returns
425 * fixed-length prefix of SHA-1 string.
428 * repository for checking uniqueness within.
429 * @return SHA-1 abbreviation.
431 public String
abbreviate(final Repository repo
) {
432 // TODO implement checking for uniqueness
433 return name().substring(0, 7);
437 * Obtain an immutable copy of this current object name value.
439 * Only returns <code>this</code> if this instance is an unsubclassed
440 * instance of {@link ObjectId}; otherwise a new instance is returned
441 * holding the same value.
443 * This method is useful to shed any additional memory that may be tied to
444 * the subclass, yet retain the unique identity of the object id for future
445 * lookups within maps and repositories.
447 * @return an immutable copy, using the smallest memory footprint possible.
449 public final ObjectId
copy() {
450 if (getClass() == ObjectId
.class)
451 return (ObjectId
) this;
452 return new ObjectId(this);
456 * Obtain an immutable copy of this current object name value.
458 * See {@link #copy()} if <code>this</code> is a possibly subclassed (but
459 * immutable) identity and the application needs a lightweight identity
460 * <i>only</i> reference.
462 * @return an immutable copy. May be <code>this</code> if this is already
463 * an immutable instance.
465 public abstract ObjectId
toObjectId();