1536db18cSMatthias Sohn /* 25c5f7c6bSMatthias Sohn * Copyright (C) 2015, Matthias Sohn <matthias.sohn@sap.com> and others 3536db18cSMatthias Sohn * 45c5f7c6bSMatthias Sohn * This program and the accompanying materials are made available under the 55c5f7c6bSMatthias Sohn * terms of the Eclipse Distribution License v. 1.0 which is available at 65c5f7c6bSMatthias Sohn * https://www.eclipse.org/org/documents/edl-v10.php. 7536db18cSMatthias Sohn * 85c5f7c6bSMatthias Sohn * SPDX-License-Identifier: BSD-3-Clause 9536db18cSMatthias Sohn */ 10536db18cSMatthias Sohn 11536db18cSMatthias Sohn package org.eclipse.jgit.lfs.lib; 12536db18cSMatthias Sohn 13536db18cSMatthias Sohn import java.io.IOException; 14536db18cSMatthias Sohn import java.io.ObjectInputStream; 15536db18cSMatthias Sohn import java.io.ObjectOutputStream; 16536db18cSMatthias Sohn import java.io.Serializable; 17536db18cSMatthias Sohn 18536db18cSMatthias Sohn import org.eclipse.jgit.lfs.errors.InvalidLongObjectIdException; 19536db18cSMatthias Sohn import org.eclipse.jgit.util.NB; 20536db18cSMatthias Sohn import org.eclipse.jgit.util.RawParseUtils; 21536db18cSMatthias Sohn 22536db18cSMatthias Sohn /** 23536db18cSMatthias Sohn * A SHA-256 abstraction. 24536db18cSMatthias Sohn * 25e0332bfbSMatthias Sohn * Ported to SHA-256 from {@link org.eclipse.jgit.lib.ObjectId} 26536db18cSMatthias Sohn * 27536db18cSMatthias Sohn * @since 4.3 28536db18cSMatthias Sohn */ 29536db18cSMatthias Sohn public class LongObjectId extends AnyLongObjectId implements Serializable { 30536db18cSMatthias Sohn private static final long serialVersionUID = 1L; 31536db18cSMatthias Sohn 32536db18cSMatthias Sohn private static final LongObjectId ZEROID; 33536db18cSMatthias Sohn 34536db18cSMatthias Sohn private static final String ZEROID_STR; 35536db18cSMatthias Sohn 36536db18cSMatthias Sohn static { 37536db18cSMatthias Sohn ZEROID = new LongObjectId(0L, 0L, 0L, 0L); 38536db18cSMatthias Sohn ZEROID_STR = ZEROID.name(); 39536db18cSMatthias Sohn } 40536db18cSMatthias Sohn 41536db18cSMatthias Sohn /** 42536db18cSMatthias Sohn * Get the special all-zero LongObjectId. 43536db18cSMatthias Sohn * 44536db18cSMatthias Sohn * @return the all-zero LongObjectId, often used to stand-in for no object. 45536db18cSMatthias Sohn */ zeroId()46536db18cSMatthias Sohn public static final LongObjectId zeroId() { 47536db18cSMatthias Sohn return ZEROID; 48536db18cSMatthias Sohn } 49536db18cSMatthias Sohn 50536db18cSMatthias Sohn /** 51536db18cSMatthias Sohn * Test a string of characters to verify that it can be interpreted as 52536db18cSMatthias Sohn * LongObjectId. 53536db18cSMatthias Sohn * <p> 54536db18cSMatthias Sohn * If true the string can be parsed with {@link #fromString(String)}. 55536db18cSMatthias Sohn * 56536db18cSMatthias Sohn * @param id 57536db18cSMatthias Sohn * the string to test. 58536db18cSMatthias Sohn * @return true if the string can converted into an LongObjectId. 59536db18cSMatthias Sohn */ isId(String id)606d370d83SHan-Wen Nienhuys public static final boolean isId(String id) { 61536db18cSMatthias Sohn if (id.length() != Constants.LONG_OBJECT_ID_STRING_LENGTH) 62536db18cSMatthias Sohn return false; 63536db18cSMatthias Sohn try { 64536db18cSMatthias Sohn for (int i = 0; i < Constants.LONG_OBJECT_ID_STRING_LENGTH; i++) { 65536db18cSMatthias Sohn RawParseUtils.parseHexInt4((byte) id.charAt(i)); 66536db18cSMatthias Sohn } 67536db18cSMatthias Sohn return true; 68536db18cSMatthias Sohn } catch (ArrayIndexOutOfBoundsException e) { 69536db18cSMatthias Sohn return false; 70536db18cSMatthias Sohn } 71536db18cSMatthias Sohn } 72536db18cSMatthias Sohn 73536db18cSMatthias Sohn /** 74536db18cSMatthias Sohn * Convert a LongObjectId into a hex string representation. 75536db18cSMatthias Sohn * 76536db18cSMatthias Sohn * @param i 77536db18cSMatthias Sohn * the id to convert. May be null. 78536db18cSMatthias Sohn * @return the hex string conversion of this id's content. 79536db18cSMatthias Sohn */ toString(LongObjectId i)806d370d83SHan-Wen Nienhuys public static final String toString(LongObjectId i) { 81536db18cSMatthias Sohn return i != null ? i.name() : ZEROID_STR; 82536db18cSMatthias Sohn } 83536db18cSMatthias Sohn 84536db18cSMatthias Sohn /** 85536db18cSMatthias Sohn * Compare two object identifier byte sequences for equality. 86536db18cSMatthias Sohn * 87536db18cSMatthias Sohn * @param firstBuffer 88536db18cSMatthias Sohn * the first buffer to compare against. Must have at least 32 89536db18cSMatthias Sohn * bytes from position fi through the end of the buffer. 90536db18cSMatthias Sohn * @param fi 91536db18cSMatthias Sohn * first offset within firstBuffer to begin testing. 92536db18cSMatthias Sohn * @param secondBuffer 93536db18cSMatthias Sohn * the second buffer to compare against. Must have at least 32 94536db18cSMatthias Sohn * bytes from position si through the end of the buffer. 95536db18cSMatthias Sohn * @param si 96536db18cSMatthias Sohn * first offset within secondBuffer to begin testing. 97536db18cSMatthias Sohn * @return true if the two identifiers are the same. 98536db18cSMatthias Sohn */ equals(final byte[] firstBuffer, final int fi, final byte[] secondBuffer, final int si)99536db18cSMatthias Sohn public static boolean equals(final byte[] firstBuffer, final int fi, 100536db18cSMatthias Sohn final byte[] secondBuffer, final int si) { 101536db18cSMatthias Sohn return firstBuffer[fi] == secondBuffer[si] 102536db18cSMatthias Sohn && firstBuffer[fi + 1] == secondBuffer[si + 1] 103536db18cSMatthias Sohn && firstBuffer[fi + 2] == secondBuffer[si + 2] 104536db18cSMatthias Sohn && firstBuffer[fi + 3] == secondBuffer[si + 3] 105536db18cSMatthias Sohn && firstBuffer[fi + 4] == secondBuffer[si + 4] 106536db18cSMatthias Sohn && firstBuffer[fi + 5] == secondBuffer[si + 5] 107536db18cSMatthias Sohn && firstBuffer[fi + 6] == secondBuffer[si + 6] 108536db18cSMatthias Sohn && firstBuffer[fi + 7] == secondBuffer[si + 7] 109536db18cSMatthias Sohn && firstBuffer[fi + 8] == secondBuffer[si + 8] 110536db18cSMatthias Sohn && firstBuffer[fi + 9] == secondBuffer[si + 9] 111536db18cSMatthias Sohn && firstBuffer[fi + 10] == secondBuffer[si + 10] 112536db18cSMatthias Sohn && firstBuffer[fi + 11] == secondBuffer[si + 11] 113536db18cSMatthias Sohn && firstBuffer[fi + 12] == secondBuffer[si + 12] 114536db18cSMatthias Sohn && firstBuffer[fi + 13] == secondBuffer[si + 13] 115536db18cSMatthias Sohn && firstBuffer[fi + 14] == secondBuffer[si + 14] 116536db18cSMatthias Sohn && firstBuffer[fi + 15] == secondBuffer[si + 15] 117536db18cSMatthias Sohn && firstBuffer[fi + 16] == secondBuffer[si + 16] 118536db18cSMatthias Sohn && firstBuffer[fi + 17] == secondBuffer[si + 17] 119536db18cSMatthias Sohn && firstBuffer[fi + 18] == secondBuffer[si + 18] 120536db18cSMatthias Sohn && firstBuffer[fi + 19] == secondBuffer[si + 19] 121536db18cSMatthias Sohn && firstBuffer[fi + 20] == secondBuffer[si + 20] 122536db18cSMatthias Sohn && firstBuffer[fi + 21] == secondBuffer[si + 21] 123536db18cSMatthias Sohn && firstBuffer[fi + 22] == secondBuffer[si + 22] 124536db18cSMatthias Sohn && firstBuffer[fi + 23] == secondBuffer[si + 23] 125536db18cSMatthias Sohn && firstBuffer[fi + 24] == secondBuffer[si + 24] 126536db18cSMatthias Sohn && firstBuffer[fi + 25] == secondBuffer[si + 25] 127536db18cSMatthias Sohn && firstBuffer[fi + 26] == secondBuffer[si + 26] 128536db18cSMatthias Sohn && firstBuffer[fi + 27] == secondBuffer[si + 27] 129536db18cSMatthias Sohn && firstBuffer[fi + 28] == secondBuffer[si + 28] 130536db18cSMatthias Sohn && firstBuffer[fi + 29] == secondBuffer[si + 29] 131536db18cSMatthias Sohn && firstBuffer[fi + 30] == secondBuffer[si + 30] 132536db18cSMatthias Sohn && firstBuffer[fi + 31] == secondBuffer[si + 31]; 133536db18cSMatthias Sohn } 134536db18cSMatthias Sohn 135536db18cSMatthias Sohn /** 136536db18cSMatthias Sohn * Convert a LongObjectId from raw binary representation. 137536db18cSMatthias Sohn * 138536db18cSMatthias Sohn * @param bs 139536db18cSMatthias Sohn * the raw byte buffer to read from. At least 32 bytes must be 140536db18cSMatthias Sohn * available within this byte array. 141536db18cSMatthias Sohn * @return the converted object id. 142536db18cSMatthias Sohn */ fromRaw(byte[] bs)1436d370d83SHan-Wen Nienhuys public static final LongObjectId fromRaw(byte[] bs) { 144536db18cSMatthias Sohn return fromRaw(bs, 0); 145536db18cSMatthias Sohn } 146536db18cSMatthias Sohn 147536db18cSMatthias Sohn /** 148536db18cSMatthias Sohn * Convert a LongObjectId from raw binary representation. 149536db18cSMatthias Sohn * 150536db18cSMatthias Sohn * @param bs 151536db18cSMatthias Sohn * the raw byte buffer to read from. At least 32 bytes after p 152536db18cSMatthias Sohn * must be available within this byte array. 153536db18cSMatthias Sohn * @param p 154536db18cSMatthias Sohn * position to read the first byte of data from. 155536db18cSMatthias Sohn * @return the converted object id. 156536db18cSMatthias Sohn */ fromRaw(byte[] bs, int p)1576d370d83SHan-Wen Nienhuys public static final LongObjectId fromRaw(byte[] bs, int p) { 158536db18cSMatthias Sohn final long a = NB.decodeInt64(bs, p); 159536db18cSMatthias Sohn final long b = NB.decodeInt64(bs, p + 8); 160536db18cSMatthias Sohn final long c = NB.decodeInt64(bs, p + 16); 161536db18cSMatthias Sohn final long d = NB.decodeInt64(bs, p + 24); 162536db18cSMatthias Sohn return new LongObjectId(a, b, c, d); 163536db18cSMatthias Sohn } 164536db18cSMatthias Sohn 165536db18cSMatthias Sohn /** 166536db18cSMatthias Sohn * Convert a LongObjectId from raw binary representation. 167536db18cSMatthias Sohn * 168536db18cSMatthias Sohn * @param is 169536db18cSMatthias Sohn * the raw long buffer to read from. At least 4 longs must be 170536db18cSMatthias Sohn * available within this long array. 171536db18cSMatthias Sohn * @return the converted object id. 172536db18cSMatthias Sohn */ fromRaw(long[] is)1736d370d83SHan-Wen Nienhuys public static final LongObjectId fromRaw(long[] is) { 174536db18cSMatthias Sohn return fromRaw(is, 0); 175536db18cSMatthias Sohn } 176536db18cSMatthias Sohn 177536db18cSMatthias Sohn /** 178536db18cSMatthias Sohn * Convert a LongObjectId from raw binary representation. 179536db18cSMatthias Sohn * 180536db18cSMatthias Sohn * @param is 181536db18cSMatthias Sohn * the raw long buffer to read from. At least 4 longs after p 182536db18cSMatthias Sohn * must be available within this long array. 183536db18cSMatthias Sohn * @param p 184536db18cSMatthias Sohn * position to read the first long of data from. 185536db18cSMatthias Sohn * @return the converted object id. 186536db18cSMatthias Sohn */ fromRaw(long[] is, int p)1876d370d83SHan-Wen Nienhuys public static final LongObjectId fromRaw(long[] is, int p) { 188536db18cSMatthias Sohn return new LongObjectId(is[p], is[p + 1], is[p + 2], is[p + 3]); 189536db18cSMatthias Sohn } 190536db18cSMatthias Sohn 191536db18cSMatthias Sohn /** 192536db18cSMatthias Sohn * Convert a LongObjectId from hex characters (US-ASCII). 193536db18cSMatthias Sohn * 194536db18cSMatthias Sohn * @param buf 195536db18cSMatthias Sohn * the US-ASCII buffer to read from. At least 64 bytes after 196536db18cSMatthias Sohn * offset must be available within this byte array. 197536db18cSMatthias Sohn * @param offset 198536db18cSMatthias Sohn * position to read the first character from. 199536db18cSMatthias Sohn * @return the converted object id. 200536db18cSMatthias Sohn */ fromString(byte[] buf, int offset)2016d370d83SHan-Wen Nienhuys public static final LongObjectId fromString(byte[] buf, int offset) { 202536db18cSMatthias Sohn return fromHexString(buf, offset); 203536db18cSMatthias Sohn } 204536db18cSMatthias Sohn 205536db18cSMatthias Sohn /** 206536db18cSMatthias Sohn * Convert a LongObjectId from hex characters. 207536db18cSMatthias Sohn * 208536db18cSMatthias Sohn * @param str 209536db18cSMatthias Sohn * the string to read from. Must be 64 characters long. 210536db18cSMatthias Sohn * @return the converted object id. 211536db18cSMatthias Sohn */ fromString(String str)2126d370d83SHan-Wen Nienhuys public static LongObjectId fromString(String str) { 213536db18cSMatthias Sohn if (str.length() != Constants.LONG_OBJECT_ID_STRING_LENGTH) 214536db18cSMatthias Sohn throw new InvalidLongObjectIdException(str); 215536db18cSMatthias Sohn return fromHexString(org.eclipse.jgit.lib.Constants.encodeASCII(str), 216536db18cSMatthias Sohn 0); 217536db18cSMatthias Sohn } 218536db18cSMatthias Sohn fromHexString(byte[] bs, int p)2196d370d83SHan-Wen Nienhuys private static final LongObjectId fromHexString(byte[] bs, int p) { 220536db18cSMatthias Sohn try { 221536db18cSMatthias Sohn final long a = RawParseUtils.parseHexInt64(bs, p); 222536db18cSMatthias Sohn final long b = RawParseUtils.parseHexInt64(bs, p + 16); 223536db18cSMatthias Sohn final long c = RawParseUtils.parseHexInt64(bs, p + 32); 224536db18cSMatthias Sohn final long d = RawParseUtils.parseHexInt64(bs, p + 48); 225536db18cSMatthias Sohn return new LongObjectId(a, b, c, d); 226*4cc13297SDavid Pursehouse } catch (ArrayIndexOutOfBoundsException e) { 227*4cc13297SDavid Pursehouse InvalidLongObjectIdException e1 = new InvalidLongObjectIdException( 228*4cc13297SDavid Pursehouse bs, p, Constants.LONG_OBJECT_ID_STRING_LENGTH); 229*4cc13297SDavid Pursehouse e1.initCause(e); 230*4cc13297SDavid Pursehouse throw e1; 231536db18cSMatthias Sohn } 232536db18cSMatthias Sohn } 233536db18cSMatthias Sohn LongObjectId(final long new_1, final long new_2, final long new_3, final long new_4)234536db18cSMatthias Sohn LongObjectId(final long new_1, final long new_2, final long new_3, 235536db18cSMatthias Sohn final long new_4) { 236536db18cSMatthias Sohn w1 = new_1; 237536db18cSMatthias Sohn w2 = new_2; 238536db18cSMatthias Sohn w3 = new_3; 239536db18cSMatthias Sohn w4 = new_4; 240536db18cSMatthias Sohn } 241536db18cSMatthias Sohn 242536db18cSMatthias Sohn /** 243536db18cSMatthias Sohn * Initialize this instance by copying another existing LongObjectId. 244536db18cSMatthias Sohn * <p> 245536db18cSMatthias Sohn * This constructor is mostly useful for subclasses which want to extend a 246536db18cSMatthias Sohn * LongObjectId with more properties, but initialize from an existing 247536db18cSMatthias Sohn * LongObjectId instance acquired by other means. 248536db18cSMatthias Sohn * 249536db18cSMatthias Sohn * @param src 250536db18cSMatthias Sohn * another already parsed LongObjectId to copy the value out of. 251536db18cSMatthias Sohn */ LongObjectId(AnyLongObjectId src)2526d370d83SHan-Wen Nienhuys protected LongObjectId(AnyLongObjectId src) { 253536db18cSMatthias Sohn w1 = src.w1; 254536db18cSMatthias Sohn w2 = src.w2; 255536db18cSMatthias Sohn w3 = src.w3; 256536db18cSMatthias Sohn w4 = src.w4; 257536db18cSMatthias Sohn } 258536db18cSMatthias Sohn 259e0332bfbSMatthias Sohn /** {@inheritDoc} */ 260536db18cSMatthias Sohn @Override toObjectId()261536db18cSMatthias Sohn public LongObjectId toObjectId() { 262536db18cSMatthias Sohn return this; 263536db18cSMatthias Sohn } 264536db18cSMatthias Sohn writeObject(ObjectOutputStream os)265536db18cSMatthias Sohn private void writeObject(ObjectOutputStream os) throws IOException { 266536db18cSMatthias Sohn os.writeLong(w1); 267536db18cSMatthias Sohn os.writeLong(w2); 268536db18cSMatthias Sohn os.writeLong(w3); 269536db18cSMatthias Sohn os.writeLong(w4); 270536db18cSMatthias Sohn } 271536db18cSMatthias Sohn readObject(ObjectInputStream ois)272536db18cSMatthias Sohn private void readObject(ObjectInputStream ois) throws IOException { 273536db18cSMatthias Sohn w1 = ois.readLong(); 274536db18cSMatthias Sohn w2 = ois.readLong(); 275536db18cSMatthias Sohn w3 = ois.readLong(); 276536db18cSMatthias Sohn w4 = ois.readLong(); 277536db18cSMatthias Sohn } 278536db18cSMatthias Sohn } 279