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