1 /* 2 * Copyright (C) 2015, Matthias Sohn <matthias.sohn@sap.com> 3 * and other copyright owners as documented in the project's IP log. 4 * 5 * This program and the accompanying materials are made available 6 * under the terms of the Eclipse Distribution License v1.0 which 7 * accompanies this distribution, is reproduced below, and is 8 * available at http://www.eclipse.org/org/documents/edl-v10.php 9 * 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials provided 22 * with the distribution. 23 * 24 * - Neither the name of the Eclipse Foundation, Inc. nor the 25 * names of its contributors may be used to endorse or promote 26 * products derived from this software without specific prior 27 * written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 42 */ 43 44 package org.eclipse.jgit.lfs.lib; 45 46 import java.text.MessageFormat; 47 48 import org.eclipse.jgit.lfs.errors.InvalidLongObjectIdException; 49 import org.eclipse.jgit.lfs.internal.LfsText; 50 import org.eclipse.jgit.lib.MutableObjectId; 51 import org.eclipse.jgit.util.NB; 52 import org.eclipse.jgit.util.RawParseUtils; 53 54 /** 55 * A mutable SHA-256 abstraction. 56 * 57 * Ported to SHA-256 from {@link MutableObjectId} 58 * 59 * @since 4.3 60 */ 61 public class MutableLongObjectId extends AnyLongObjectId { 62 /** 63 * Empty constructor. Initialize object with default (zeros) value. 64 */ 65 public MutableLongObjectId() { 66 super(); 67 } 68 69 /** 70 * Copying constructor. 71 * 72 * @param src 73 * original entry, to copy id from 74 */ 75 MutableLongObjectId(MutableLongObjectId src) { 76 fromObjectId(src); 77 } 78 79 /** 80 * Set any byte in the id. 81 * 82 * @param index 83 * index of the byte to set in the raw form of the ObjectId. Must 84 * be in range [0, {@link Constants#LONG_OBJECT_ID_LENGTH}). 85 * @param value 86 * the value of the specified byte at {@code index}. Values are 87 * unsigned and thus are in the range [0,255] rather than the 88 * signed byte range of [-128, 127]. 89 * @throws ArrayIndexOutOfBoundsException 90 * {@code index} is less than 0, equal to 91 * {@link Constants#LONG_OBJECT_ID_LENGTH}, or greater than 92 * {@link Constants#LONG_OBJECT_ID_LENGTH}. 93 */ 94 public void setByte(int index, int value) { 95 switch (index >> 3) { 96 case 0: 97 w1 = set(w1, index & 7, value); 98 break; 99 case 1: 100 w2 = set(w2, index & 7, value); 101 break; 102 case 2: 103 w3 = set(w3, index & 7, value); 104 break; 105 case 3: 106 w4 = set(w4, index & 7, value); 107 break; 108 default: 109 throw new ArrayIndexOutOfBoundsException(index); 110 } 111 } 112 113 private static long set(long w, int index, long value) { 114 value &= 0xff; 115 116 switch (index) { 117 case 0: 118 return (w & 0x00ffffffffffffffL) | (value << 56); 119 case 1: 120 return (w & 0xff00ffffffffffffL) | (value << 48); 121 case 2: 122 return (w & 0xffff00ffffffffffL) | (value << 40); 123 case 3: 124 return (w & 0xffffff00ffffffffL) | (value << 32); 125 case 4: 126 return (w & 0xffffffff00ffffffL) | (value << 24); 127 case 5: 128 return (w & 0xffffffffff00ffffL) | (value << 16); 129 case 6: 130 return (w & 0xffffffffffff00ffL) | (value << 8); 131 case 7: 132 return (w & 0xffffffffffffff00L) | value; 133 default: 134 throw new ArrayIndexOutOfBoundsException(); 135 } 136 } 137 138 /** Make this id match {@link LongObjectId#zeroId()}. */ 139 public void clear() { 140 w1 = 0; 141 w2 = 0; 142 w3 = 0; 143 w4 = 0; 144 } 145 146 /** 147 * Copy an LongObjectId into this mutable buffer. 148 * 149 * @param src 150 * the source id to copy from. 151 */ 152 public void fromObjectId(AnyLongObjectId src) { 153 this.w1 = src.w1; 154 this.w2 = src.w2; 155 this.w3 = src.w3; 156 this.w4 = src.w4; 157 } 158 159 /** 160 * Convert an LongObjectId from raw binary representation. 161 * 162 * @param bs 163 * the raw byte buffer to read from. At least 32 bytes must be 164 * available within this byte array. 165 */ 166 public void fromRaw(final byte[] bs) { 167 fromRaw(bs, 0); 168 } 169 170 /** 171 * Convert an LongObjectId from raw binary representation. 172 * 173 * @param bs 174 * the raw byte buffer to read from. At least 32 bytes after p 175 * must be available within this byte array. 176 * @param p 177 * position to read the first byte of data from. 178 */ 179 public void fromRaw(final byte[] bs, final int p) { 180 w1 = NB.decodeInt64(bs, p); 181 w2 = NB.decodeInt64(bs, p + 8); 182 w3 = NB.decodeInt64(bs, p + 16); 183 w4 = NB.decodeInt64(bs, p + 24); 184 } 185 186 /** 187 * Convert an LongObjectId from binary representation expressed in integers. 188 * 189 * @param longs 190 * the raw long buffer to read from. At least 4 longs must be 191 * available within this longs array. 192 */ 193 public void fromRaw(final long[] longs) { 194 fromRaw(longs, 0); 195 } 196 197 /** 198 * Convert an LongObjectId from binary representation expressed in longs. 199 * 200 * @param longs 201 * the raw int buffer to read from. At least 4 longs after p must 202 * be available within this longs array. 203 * @param p 204 * position to read the first integer of data from. 205 * 206 */ 207 public void fromRaw(final long[] longs, final int p) { 208 w1 = longs[p]; 209 w2 = longs[p + 1]; 210 w3 = longs[p + 2]; 211 w4 = longs[p + 3]; 212 } 213 214 /** 215 * Convert an LongObjectId from hex characters (US-ASCII). 216 * 217 * @param buf 218 * the US-ASCII buffer to read from. At least 32 bytes after 219 * offset must be available within this byte array. 220 * @param offset 221 * position to read the first character from. 222 */ 223 public void fromString(final byte[] buf, final int offset) { 224 fromHexString(buf, offset); 225 } 226 227 /** 228 * Convert an LongObjectId from hex characters. 229 * 230 * @param str 231 * the string to read from. Must be 64 characters long. 232 */ 233 public void fromString(final String str) { 234 if (str.length() != Constants.LONG_OBJECT_ID_STRING_LENGTH) 235 throw new IllegalArgumentException( 236 MessageFormat.format(LfsText.get().invalidLongId, str)); 237 fromHexString(org.eclipse.jgit.lib.Constants.encodeASCII(str), 0); 238 } 239 240 private void fromHexString(final byte[] bs, int p) { 241 try { 242 w1 = RawParseUtils.parseHexInt64(bs, p); 243 w2 = RawParseUtils.parseHexInt64(bs, p + 16); 244 w3 = RawParseUtils.parseHexInt64(bs, p + 32); 245 w4 = RawParseUtils.parseHexInt64(bs, p + 48); 246 } catch (ArrayIndexOutOfBoundsException e1) { 247 throw new InvalidLongObjectIdException(bs, p, 248 Constants.LONG_OBJECT_ID_STRING_LENGTH); 249 } 250 } 251 252 @Override 253 public LongObjectId toObjectId() { 254 return new LongObjectId(this); 255 } 256 }