1 /*
2 * Copyright (C) 2008-2009, Google Inc.
3 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
4 * Copyright (C) 2007-2009, Robin Rosenberg <robin.rosenberg@dewire.com>
5 * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org> and others
6 *
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Distribution License v. 1.0 which is available at
9 * https://www.eclipse.org/org/documents/edl-v10.php.
10 *
11 * SPDX-License-Identifier: BSD-3-Clause
12 */
13
14 package org.eclipse.jgit.lib;
15
16 import java.text.MessageFormat;
17
18 import org.eclipse.jgit.errors.InvalidObjectIdException;
19 import org.eclipse.jgit.internal.JGitText;
20 import org.eclipse.jgit.util.NB;
21 import org.eclipse.jgit.util.RawParseUtils;
22
23 /**
24 * A mutable SHA-1 abstraction.
25 */
26 public class MutableObjectId extends AnyObjectId {
27 /**
28 * Empty constructor. Initialize object with default (zeros) value.
29 */
30 public MutableObjectId() {
31 super();
32 }
33
34 /**
35 * Copying constructor.
36 *
37 * @param src
38 * original entry, to copy id from
39 */
40 MutableObjectId(MutableObjectId src) {
41 fromObjectId(src);
42 }
43
44 /**
45 * Set any byte in the id.
46 *
47 * @param index
48 * index of the byte to set in the raw form of the ObjectId. Must
49 * be in range [0,
50 * {@link org.eclipse.jgit.lib.Constants#OBJECT_ID_LENGTH}).
51 * @param value
52 * the value of the specified byte at {@code index}. Values are
53 * unsigned and thus are in the range [0,255] rather than the
54 * signed byte range of [-128, 127].
55 * @throws java.lang.ArrayIndexOutOfBoundsException
56 * {@code index} is less than 0, equal to
57 * {@link org.eclipse.jgit.lib.Constants#OBJECT_ID_LENGTH}, or
58 * greater than
59 * {@link org.eclipse.jgit.lib.Constants#OBJECT_ID_LENGTH}.
60 */
61 public void setByte(int index, int value) {
62 switch (index >> 2) {
63 case 0:
64 w1 = set(w1, index & 3, value);
65 break;
66 case 1:
67 w2 = set(w2, index & 3, value);
68 break;
69 case 2:
70 w3 = set(w3, index & 3, value);
71 break;
72 case 3:
73 w4 = set(w4, index & 3, value);
74 break;
75 case 4:
76 w5 = set(w5, index & 3, value);
77 break;
78 default:
79 throw new ArrayIndexOutOfBoundsException(index);
80 }
81 }
82
83 private static int set(int w, int index, int value) {
84 value &= 0xff;
85
86 switch (index) {
87 case 0:
88 return (w & 0x00ffffff) | (value << 24);
89 case 1:
90 return (w & 0xff00ffff) | (value << 16);
91 case 2:
92 return (w & 0xffff00ff) | (value << 8);
93 case 3:
94 return (w & 0xffffff00) | value;
95 default:
96 throw new ArrayIndexOutOfBoundsException();
97 }
98 }
99
100 /**
101 * Make this id match {@link org.eclipse.jgit.lib.ObjectId#zeroId()}.
102 */
103 public void clear() {
104 w1 = 0;
105 w2 = 0;
106 w3 = 0;
107 w4 = 0;
108 w5 = 0;
109 }
110
111 /**
112 * Copy an ObjectId into this mutable buffer.
113 *
114 * @param src
115 * the source id to copy from.
116 */
117 public void fromObjectId(AnyObjectId src) {
118 this.w1 = src.w1;
119 this.w2 = src.w2;
120 this.w3 = src.w3;
121 this.w4 = src.w4;
122 this.w5 = src.w5;
123 }
124
125 /**
126 * Convert an ObjectId from raw binary representation.
127 *
128 * @param bs
129 * the raw byte buffer to read from. At least 20 bytes must be
130 * available within this byte array.
131 */
132 public void fromRaw(byte[] bs) {
133 fromRaw(bs, 0);
134 }
135
136 /**
137 * Convert an ObjectId from raw binary representation.
138 *
139 * @param bs
140 * the raw byte buffer to read from. At least 20 bytes after p
141 * must be available within this byte array.
142 * @param p
143 * position to read the first byte of data from.
144 */
145 public void fromRaw(byte[] bs, int p) {
146 w1 = NB.decodeInt32(bs, p);
147 w2 = NB.decodeInt32(bs, p + 4);
148 w3 = NB.decodeInt32(bs, p + 8);
149 w4 = NB.decodeInt32(bs, p + 12);
150 w5 = NB.decodeInt32(bs, p + 16);
151 }
152
153 /**
154 * Convert an ObjectId from binary representation expressed in integers.
155 *
156 * @param ints
157 * the raw int buffer to read from. At least 5 integers must be
158 * available within this integers array.
159 */
160 public void fromRaw(int[] ints) {
161 fromRaw(ints, 0);
162 }
163
164 /**
165 * Convert an ObjectId from binary representation expressed in integers.
166 *
167 * @param ints
168 * the raw int buffer to read from. At least 5 integers after p
169 * must be available within this integers array.
170 * @param p
171 * position to read the first integer of data from.
172 */
173 public void fromRaw(int[] ints, int p) {
174 w1 = ints[p];
175 w2 = ints[p + 1];
176 w3 = ints[p + 2];
177 w4 = ints[p + 3];
178 w5 = ints[p + 4];
179 }
180
181 /**
182 * Convert an ObjectId from binary representation expressed in integers.
183 *
184 * @param a
185 * an int.
186 * @param b
187 * an int.
188 * @param c
189 * an int.
190 * @param d
191 * an int.
192 * @param e
193 * an int.
194 * @since 4.7
195 */
196 public void set(int a, int b, int c, int d, int e) {
197 w1 = a;
198 w2 = b;
199 w3 = c;
200 w4 = d;
201 w5 = e;
202 }
203
204 /**
205 * Convert an ObjectId from hex characters (US-ASCII).
206 *
207 * @param buf
208 * the US-ASCII buffer to read from. At least 40 bytes after
209 * offset must be available within this byte array.
210 * @param offset
211 * position to read the first character from.
212 */
213 public void fromString(byte[] buf, int offset) {
214 fromHexString(buf, offset);
215 }
216
217 /**
218 * Convert an ObjectId from hex characters.
219 *
220 * @param str
221 * the string to read from. Must be 40 characters long.
222 */
223 public void fromString(String str) {
224 if (str.length() != Constants.OBJECT_ID_STRING_LENGTH)
225 throw new IllegalArgumentException(MessageFormat.format(
226 JGitText.get().invalidId, str));
227 fromHexString(Constants.encodeASCII(str), 0);
228 }
229
230 private void fromHexString(byte[] bs, int p) {
231 try {
232 w1 = RawParseUtils.parseHexInt32(bs, p);
233 w2 = RawParseUtils.parseHexInt32(bs, p + 8);
234 w3 = RawParseUtils.parseHexInt32(bs, p + 16);
235 w4 = RawParseUtils.parseHexInt32(bs, p + 24);
236 w5 = RawParseUtils.parseHexInt32(bs, p + 32);
237 } catch (ArrayIndexOutOfBoundsException e) {
238 InvalidObjectIdException e1 = new InvalidObjectIdException(bs, p,
239 Constants.OBJECT_ID_STRING_LENGTH);
240 e1.initCause(e);
241 throw e1;
242 }
243 }
244
245 /** {@inheritDoc} */
246 @Override
247 public ObjectId toObjectId() {
248 return new ObjectId(this);
249 }
250 }