2 * Copyright (C) 2008, Google Inc.
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
.UnsupportedEncodingException
;
42 import org
.spearce
.jgit
.util
.NB
;
45 * A prefix abbreviation of an {@link ObjectId}.
47 * Sometimes Git produces abbreviated SHA-1 strings, using sufficient leading
48 * digits from the ObjectId name to still be unique within the repository the
49 * string was generated from. These ids are likely to be unique for a useful
50 * period of time, especially if they contain at least 6-10 hex digits.
52 * This class converts the hex string into a binary form, to make it more
53 * efficient for matching against an object.
55 public class AbbreviatedObjectId
{
57 * Convert an AbbreviatedObjectId from hex characters (US-ASCII).
60 * the US-ASCII buffer to read from.
62 * position to read the first character from.
64 * one past the last position to read (<code>end-offset</code> is
65 * the length of the string).
66 * @return the converted object id.
68 public static final AbbreviatedObjectId
fromString(final byte[] buf
,
69 final int offset
, final int end
) {
70 if (end
- offset
> AnyObjectId
.STR_LEN
)
71 throw new IllegalArgumentException("Invalid id");
72 return fromHexString(buf
, offset
, end
);
76 * Convert an AbbreviatedObjectId from hex characters.
79 * the string to read from. Must be <= 40 characters.
80 * @return the converted object id.
82 public static final AbbreviatedObjectId
fromString(final String str
) {
83 if (str
.length() > AnyObjectId
.STR_LEN
)
84 throw new IllegalArgumentException("Invalid id: " + str
);
85 final byte[] b
= Constants
.encodeASCII(str
);
86 return fromHexString(b
, 0, b
.length
);
89 private static final AbbreviatedObjectId
fromHexString(final byte[] bs
,
90 int ptr
, final int end
) {
92 final int a
= hexUInt32(bs
, ptr
, end
);
93 final int b
= hexUInt32(bs
, ptr
+ 8, end
);
94 final int c
= hexUInt32(bs
, ptr
+ 16, end
);
95 final int d
= hexUInt32(bs
, ptr
+ 24, end
);
96 final int e
= hexUInt32(bs
, ptr
+ 32, end
);
97 return new AbbreviatedObjectId(end
- ptr
, a
, b
, c
, d
, e
);
98 } catch (ArrayIndexOutOfBoundsException e1
) {
100 final String str
= new String(bs
, ptr
, end
- ptr
, "US-ASCII");
101 throw new IllegalArgumentException("Invalid id: " + str
);
102 } catch (UnsupportedEncodingException e2
) {
103 throw new IllegalArgumentException("Invalid id");
108 private static final int hexUInt32(final byte[] bs
, int p
, final int end
) {
110 return AnyObjectId
.hexUInt32(bs
, p
);
113 while (n
< 8 && p
< end
) {
114 final int v
= AnyObjectId
.fromhex
[bs
[p
++]];
116 throw new ArrayIndexOutOfBoundsException();
121 return r
<< (8 - n
) * 4;
124 static int mask(final int nibbles
, final int word
, final int v
) {
125 final int b
= (word
- 1) * 8;
126 if (b
+ 8 <= nibbles
) {
127 // We have all of the bits required for this word.
133 // We have none of the bits required for this word.
138 final int s
= 32 - (nibbles
- b
) * 4;
139 return (v
>>> s
) << s
;
142 /** Number of half-bytes used by this id. */
155 private AbbreviatedObjectId(final int n
, final int new_1
, final int new_2
,
156 final int new_3
, final int new_4
, final int new_5
) {
165 /** @return number of hex digits appearing in this id */
166 public int length() {
170 /** @return true if this ObjectId is actually a complete id. */
171 public boolean isComplete() {
172 return length() == AnyObjectId
.RAW_LEN
* 2;
175 /** @return a complete ObjectId; null if {@link #isComplete()} is false */
176 public ObjectId
toObjectId() {
177 return isComplete() ?
new ObjectId(w1
, w2
, w3
, w4
, w5
) : null;
181 * Compares this abbreviation to a full object id.
184 * the other object id.
185 * @return <0 if this abbreviation names an object that is less than
186 * <code>other</code>; 0 if this abbreviation exactly matches the
187 * first {@link #length()} digits of <code>other.name()</code>;
188 * >0 if this abbreviation names an object that is after
189 * <code>other</code>.
191 public int prefixCompare(final AnyObjectId other
) {
194 cmp
= NB
.compareUInt32(w1
, mask(1, other
.w1
));
198 cmp
= NB
.compareUInt32(w2
, mask(2, other
.w2
));
202 cmp
= NB
.compareUInt32(w3
, mask(3, other
.w3
));
206 cmp
= NB
.compareUInt32(w4
, mask(4, other
.w4
));
210 return NB
.compareUInt32(w5
, mask(5, other
.w5
));
213 private int mask(final int word
, final int v
) {
214 return mask(nibbles
, word
, v
);
218 public int hashCode() {
223 public boolean equals(final Object o
) {
224 if (o
instanceof AbbreviatedObjectId
) {
225 final AbbreviatedObjectId b
= (AbbreviatedObjectId
) o
;
226 return nibbles
== b
.nibbles
&& w1
== b
.w1
&& w2
== b
.w2
227 && w3
== b
.w3
&& w4
== b
.w4
&& w5
== b
.w5
;
233 * @return string form of the abbreviation, in lower case hexadecimal.
235 public final String
name() {
236 final char[] b
= new char[AnyObjectId
.STR_LEN
];
238 AnyObjectId
.formatHexChar(b
, 0, w1
);
240 return new String(b
, 0, nibbles
);
242 AnyObjectId
.formatHexChar(b
, 8, w2
);
244 return new String(b
, 0, nibbles
);
246 AnyObjectId
.formatHexChar(b
, 16, w3
);
248 return new String(b
, 0, nibbles
);
250 AnyObjectId
.formatHexChar(b
, 24, w4
);
252 return new String(b
, 0, nibbles
);
254 AnyObjectId
.formatHexChar(b
, 32, w5
);
255 return new String(b
, 0, nibbles
);
259 public String
toString() {
260 return "AbbreviatedObjectId[" + name() + "]";