1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.lib;
12
13 import java.io.Serializable;
14 import java.text.MessageFormat;
15
16 import org.eclipse.jgit.errors.InvalidObjectIdException;
17 import org.eclipse.jgit.internal.JGitText;
18 import org.eclipse.jgit.util.NB;
19 import org.eclipse.jgit.util.RawParseUtils;
20
21
22
23
24
25
26
27
28
29
30
31
32 public final class AbbreviatedObjectId implements Serializable {
33 private static final long serialVersionUID = 1L;
34
35
36
37
38
39
40
41
42
43
44 public static final boolean isId(String id) {
45 if (id.length() < 2 || Constants.OBJECT_ID_STRING_LENGTH < id.length())
46 return false;
47 try {
48 for (int i = 0; i < id.length(); i++)
49 RawParseUtils.parseHexInt4((byte) id.charAt(i));
50 return true;
51 } catch (ArrayIndexOutOfBoundsException e) {
52 return false;
53 }
54 }
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public static final AbbreviatedObjectId fromString(final byte[] buf,
69 final int offset, final int end) {
70 if (end - offset > Constants.OBJECT_ID_STRING_LENGTH)
71 throw new IllegalArgumentException(MessageFormat.format(
72 JGitText.get().invalidIdLength,
73 Integer.valueOf(end - offset),
74 Integer.valueOf(Constants.OBJECT_ID_STRING_LENGTH)));
75 return fromHexString(buf, offset, end);
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89 public static final AbbreviatedObjectId fromObjectId(AnyObjectId id) {
90 return new AbbreviatedObjectId(Constants.OBJECT_ID_STRING_LENGTH,
91 id.w1, id.w2, id.w3, id.w4, id.w5);
92 }
93
94
95
96
97
98
99
100
101 public static final AbbreviatedObjectId fromString(String str) {
102 if (str.length() > Constants.OBJECT_ID_STRING_LENGTH)
103 throw new IllegalArgumentException(MessageFormat.format(JGitText.get().invalidId, str));
104 final byte[] b = Constants.encodeASCII(str);
105 return fromHexString(b, 0, b.length);
106 }
107
108 private static final AbbreviatedObjectId fromHexString(final byte[] bs,
109 int ptr, final int end) {
110 try {
111 final int a = hexUInt32(bs, ptr, end);
112 final int b = hexUInt32(bs, ptr + 8, end);
113 final int c = hexUInt32(bs, ptr + 16, end);
114 final int d = hexUInt32(bs, ptr + 24, end);
115 final int e = hexUInt32(bs, ptr + 32, end);
116 return new AbbreviatedObjectId(end - ptr, a, b, c, d, e);
117 } catch (ArrayIndexOutOfBoundsException e) {
118 InvalidObjectIdException e1 = new InvalidObjectIdException(bs, ptr,
119 end - ptr);
120 e1.initCause(e);
121 throw e1;
122 }
123 }
124
125 private static final int hexUInt32(final byte[] bs, int p, final int end) {
126 if (8 <= end - p)
127 return RawParseUtils.parseHexInt32(bs, p);
128
129 int r = 0, n = 0;
130 while (n < 8 && p < end) {
131 r <<= 4;
132 r |= RawParseUtils.parseHexInt4(bs[p++]);
133 n++;
134 }
135 return r << ((8 - n) * 4);
136 }
137
138 static int mask(int nibbles, int word, int v) {
139 final int b = (word - 1) * 8;
140 if (b + 8 <= nibbles) {
141
142
143 return v;
144 }
145
146 if (nibbles <= b) {
147
148
149 return 0;
150 }
151
152 final int s = 32 - (nibbles - b) * 4;
153 return (v >>> s) << s;
154 }
155
156
157 final int nibbles;
158
159 final int w1;
160
161 final int w2;
162
163 final int w3;
164
165 final int w4;
166
167 final int w5;
168
169 AbbreviatedObjectId(final int n, final int new_1, final int new_2,
170 final int new_3, final int new_4, final int new_5) {
171 nibbles = n;
172 w1 = new_1;
173 w2 = new_2;
174 w3 = new_3;
175 w4 = new_4;
176 w5 = new_5;
177 }
178
179
180
181
182
183
184 public int length() {
185 return nibbles;
186 }
187
188
189
190
191
192
193 public boolean isComplete() {
194 return length() == Constants.OBJECT_ID_STRING_LENGTH;
195 }
196
197
198
199
200
201
202 public ObjectId toObjectId() {
203 return isComplete() ? new ObjectId(w1, w2, w3, w4, w5) : null;
204 }
205
206
207
208
209
210
211
212
213
214
215
216
217 public final int prefixCompare(AnyObjectId other) {
218 int cmp;
219
220 cmp = NB.compareUInt32(w1, mask(1, other.w1));
221 if (cmp != 0)
222 return cmp;
223
224 cmp = NB.compareUInt32(w2, mask(2, other.w2));
225 if (cmp != 0)
226 return cmp;
227
228 cmp = NB.compareUInt32(w3, mask(3, other.w3));
229 if (cmp != 0)
230 return cmp;
231
232 cmp = NB.compareUInt32(w4, mask(4, other.w4));
233 if (cmp != 0)
234 return cmp;
235
236 return NB.compareUInt32(w5, mask(5, other.w5));
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 public final int prefixCompare(byte[] bs, int p) {
254 int cmp;
255
256 cmp = NB.compareUInt32(w1, mask(1, NB.decodeInt32(bs, p)));
257 if (cmp != 0)
258 return cmp;
259
260 cmp = NB.compareUInt32(w2, mask(2, NB.decodeInt32(bs, p + 4)));
261 if (cmp != 0)
262 return cmp;
263
264 cmp = NB.compareUInt32(w3, mask(3, NB.decodeInt32(bs, p + 8)));
265 if (cmp != 0)
266 return cmp;
267
268 cmp = NB.compareUInt32(w4, mask(4, NB.decodeInt32(bs, p + 12)));
269 if (cmp != 0)
270 return cmp;
271
272 return NB.compareUInt32(w5, mask(5, NB.decodeInt32(bs, p + 16)));
273 }
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289 public final int prefixCompare(int[] bs, int p) {
290 int cmp;
291
292 cmp = NB.compareUInt32(w1, mask(1, bs[p]));
293 if (cmp != 0)
294 return cmp;
295
296 cmp = NB.compareUInt32(w2, mask(2, bs[p + 1]));
297 if (cmp != 0)
298 return cmp;
299
300 cmp = NB.compareUInt32(w3, mask(3, bs[p + 2]));
301 if (cmp != 0)
302 return cmp;
303
304 cmp = NB.compareUInt32(w4, mask(4, bs[p + 3]));
305 if (cmp != 0)
306 return cmp;
307
308 return NB.compareUInt32(w5, mask(5, bs[p + 4]));
309 }
310
311
312
313
314
315
316 public final int getFirstByte() {
317 return w1 >>> 24;
318 }
319
320 private int mask(int word, int v) {
321 return mask(nibbles, word, v);
322 }
323
324
325 @Override
326 public int hashCode() {
327 return w1;
328 }
329
330
331 @Override
332 public boolean equals(Object o) {
333 if (o instanceof AbbreviatedObjectId) {
334 final AbbreviatedObjectId/../org/eclipse/jgit/lib/AbbreviatedObjectId.html#AbbreviatedObjectId">AbbreviatedObjectId b = (AbbreviatedObjectId) o;
335 return nibbles == b.nibbles && w1 == b.w1 && w2 == b.w2
336 && w3 == b.w3 && w4 == b.w4 && w5 == b.w5;
337 }
338 return false;
339 }
340
341
342
343
344
345
346 public final String name() {
347 final char[] b = new char[Constants.OBJECT_ID_STRING_LENGTH];
348
349 AnyObjectId.formatHexChar(b, 0, w1);
350 if (nibbles <= 8)
351 return new String(b, 0, nibbles);
352
353 AnyObjectId.formatHexChar(b, 8, w2);
354 if (nibbles <= 16)
355 return new String(b, 0, nibbles);
356
357 AnyObjectId.formatHexChar(b, 16, w3);
358 if (nibbles <= 24)
359 return new String(b, 0, nibbles);
360
361 AnyObjectId.formatHexChar(b, 24, w4);
362 if (nibbles <= 32)
363 return new String(b, 0, nibbles);
364
365 AnyObjectId.formatHexChar(b, 32, w5);
366 return new String(b, 0, nibbles);
367 }
368
369
370 @SuppressWarnings("nls")
371 @Override
372 public String toString() {
373 return "AbbreviatedObjectId[" + name() + "]";
374 }
375 }