1536db18cSMatthias Sohn /* 2*5c5f7c6bSMatthias Sohn * Copyright (C) 2015, Matthias Sohn <matthias.sohn@sap.com> and others 3536db18cSMatthias Sohn * 4*5c5f7c6bSMatthias Sohn * This program and the accompanying materials are made available under the 5*5c5f7c6bSMatthias Sohn * terms of the Eclipse Distribution License v. 1.0 which is available at 6*5c5f7c6bSMatthias Sohn * https://www.eclipse.org/org/documents/edl-v10.php. 7536db18cSMatthias Sohn * 8*5c5f7c6bSMatthias 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.OutputStream; 15536db18cSMatthias Sohn import java.io.Writer; 16536db18cSMatthias Sohn import java.nio.ByteBuffer; 17536db18cSMatthias Sohn 18536db18cSMatthias Sohn import org.eclipse.jgit.lib.AnyObjectId; 19536db18cSMatthias Sohn import org.eclipse.jgit.util.NB; 20bac0e8fdSMatthias Sohn import org.eclipse.jgit.util.References; 21536db18cSMatthias Sohn 22536db18cSMatthias Sohn /** 23536db18cSMatthias Sohn * A (possibly mutable) SHA-256 abstraction. 24536db18cSMatthias Sohn * <p> 25e0332bfbSMatthias Sohn * If this is an instance of 26e0332bfbSMatthias Sohn * {@link org.eclipse.jgit.lfs.lib.MutableLongObjectId} the concept of equality 27536db18cSMatthias Sohn * with this instance can alter at any time, if this instance is modified to 28536db18cSMatthias Sohn * represent a different object name. 29536db18cSMatthias Sohn * 30e0332bfbSMatthias Sohn * Ported to SHA-256 from {@link org.eclipse.jgit.lib.AnyObjectId} 31536db18cSMatthias Sohn * 32536db18cSMatthias Sohn * @since 4.3 33536db18cSMatthias Sohn */ 34536db18cSMatthias Sohn public abstract class AnyLongObjectId implements Comparable<AnyLongObjectId> { 35536db18cSMatthias Sohn 36536db18cSMatthias Sohn /** 37536db18cSMatthias Sohn * Compare two object identifier byte sequences for equality. 38536db18cSMatthias Sohn * 39536db18cSMatthias Sohn * @param firstObjectId 40536db18cSMatthias Sohn * the first identifier to compare. Must not be null. 41536db18cSMatthias Sohn * @param secondObjectId 42536db18cSMatthias Sohn * the second identifier to compare. Must not be null. 43536db18cSMatthias Sohn * @return true if the two identifiers are the same. 4413df53c1SDavid Pursehouse * @deprecated use {@link #isEqual(AnyLongObjectId, AnyLongObjectId)} 4513df53c1SDavid Pursehouse * instead. 46536db18cSMatthias Sohn */ 4713df53c1SDavid Pursehouse @Deprecated 4813df53c1SDavid Pursehouse @SuppressWarnings("AmbiguousMethodReference") equals(final AnyLongObjectId firstObjectId, final AnyLongObjectId secondObjectId)49536db18cSMatthias Sohn public static boolean equals(final AnyLongObjectId firstObjectId, 50536db18cSMatthias Sohn final AnyLongObjectId secondObjectId) { 5113df53c1SDavid Pursehouse return isEqual(firstObjectId, secondObjectId); 5213df53c1SDavid Pursehouse } 5313df53c1SDavid Pursehouse 5413df53c1SDavid Pursehouse /** 5513df53c1SDavid Pursehouse * Compare two object identifier byte sequences for equality. 5613df53c1SDavid Pursehouse * 5713df53c1SDavid Pursehouse * @param firstObjectId 5813df53c1SDavid Pursehouse * the first identifier to compare. Must not be null. 5913df53c1SDavid Pursehouse * @param secondObjectId 6013df53c1SDavid Pursehouse * the second identifier to compare. Must not be null. 6113df53c1SDavid Pursehouse * @return true if the two identifiers are the same. 6213df53c1SDavid Pursehouse * @since 5.4 6313df53c1SDavid Pursehouse */ isEqual(final AnyLongObjectId firstObjectId, final AnyLongObjectId secondObjectId)6413df53c1SDavid Pursehouse public static boolean isEqual(final AnyLongObjectId firstObjectId, 6513df53c1SDavid Pursehouse final AnyLongObjectId secondObjectId) { 66bac0e8fdSMatthias Sohn if (References.isSameObject(firstObjectId, secondObjectId)) { 67536db18cSMatthias Sohn return true; 68bac0e8fdSMatthias Sohn } 69536db18cSMatthias Sohn 70536db18cSMatthias Sohn // We test word 2 first as odds are someone already used our 71536db18cSMatthias Sohn // word 1 as a hash code, and applying that came up with these 72536db18cSMatthias Sohn // two instances we are comparing for equality. Therefore the 73536db18cSMatthias Sohn // first two words are very likely to be identical. We want to 74536db18cSMatthias Sohn // break away from collisions as quickly as possible. 75536db18cSMatthias Sohn // 76536db18cSMatthias Sohn return firstObjectId.w2 == secondObjectId.w2 77536db18cSMatthias Sohn && firstObjectId.w3 == secondObjectId.w3 78536db18cSMatthias Sohn && firstObjectId.w4 == secondObjectId.w4 79536db18cSMatthias Sohn && firstObjectId.w1 == secondObjectId.w1; 80536db18cSMatthias Sohn } 81536db18cSMatthias Sohn 82536db18cSMatthias Sohn long w1; 83536db18cSMatthias Sohn 84536db18cSMatthias Sohn long w2; 85536db18cSMatthias Sohn 86536db18cSMatthias Sohn long w3; 87536db18cSMatthias Sohn 88536db18cSMatthias Sohn long w4; 89536db18cSMatthias Sohn 90536db18cSMatthias Sohn /** 91536db18cSMatthias Sohn * Get the first 8 bits of the LongObjectId. 92536db18cSMatthias Sohn * 93536db18cSMatthias Sohn * This is a faster version of {@code getByte(0)}. 94536db18cSMatthias Sohn * 95536db18cSMatthias Sohn * @return a discriminator usable for a fan-out style map. Returned values 96536db18cSMatthias Sohn * are unsigned and thus are in the range [0,255] rather than the 97536db18cSMatthias Sohn * signed byte range of [-128, 127]. 98536db18cSMatthias Sohn */ getFirstByte()99536db18cSMatthias Sohn public final int getFirstByte() { 100536db18cSMatthias Sohn return (int) (w1 >>> 56); 101536db18cSMatthias Sohn } 102536db18cSMatthias Sohn 103536db18cSMatthias Sohn /** 104536db18cSMatthias Sohn * Get the second 8 bits of the LongObjectId. 105536db18cSMatthias Sohn * 106536db18cSMatthias Sohn * @return a discriminator usable for a fan-out style map. Returned values 107536db18cSMatthias Sohn * are unsigned and thus are in the range [0,255] rather than the 108536db18cSMatthias Sohn * signed byte range of [-128, 127]. 109536db18cSMatthias Sohn */ getSecondByte()110536db18cSMatthias Sohn public final int getSecondByte() { 111536db18cSMatthias Sohn return (int) ((w1 >>> 48) & 0xff); 112536db18cSMatthias Sohn } 113536db18cSMatthias Sohn 114536db18cSMatthias Sohn /** 115536db18cSMatthias Sohn * Get any byte from the LongObjectId. 116536db18cSMatthias Sohn * 117536db18cSMatthias Sohn * Callers hard-coding {@code getByte(0)} should instead use the much faster 118536db18cSMatthias Sohn * special case variant {@link #getFirstByte()}. 119536db18cSMatthias Sohn * 120536db18cSMatthias Sohn * @param index 121536db18cSMatthias Sohn * index of the byte to obtain from the raw form of the 122536db18cSMatthias Sohn * LongObjectId. Must be in range [0, 123e0332bfbSMatthias Sohn * {@link org.eclipse.jgit.lfs.lib.Constants#LONG_OBJECT_ID_LENGTH}). 124536db18cSMatthias Sohn * @return the value of the requested byte at {@code index}. Returned values 125536db18cSMatthias Sohn * are unsigned and thus are in the range [0,255] rather than the 126536db18cSMatthias Sohn * signed byte range of [-128, 127]. 127e0332bfbSMatthias Sohn * @throws java.lang.ArrayIndexOutOfBoundsException 128536db18cSMatthias Sohn * {@code index} is less than 0, equal to 129e0332bfbSMatthias Sohn * {@link org.eclipse.jgit.lfs.lib.Constants#LONG_OBJECT_ID_LENGTH}, 130e0332bfbSMatthias Sohn * or greater than 131e0332bfbSMatthias Sohn * {@link org.eclipse.jgit.lfs.lib.Constants#LONG_OBJECT_ID_LENGTH}. 132536db18cSMatthias Sohn */ getByte(int index)133536db18cSMatthias Sohn public final int getByte(int index) { 134536db18cSMatthias Sohn long w; 135536db18cSMatthias Sohn switch (index >> 3) { 136536db18cSMatthias Sohn case 0: 137536db18cSMatthias Sohn w = w1; 138536db18cSMatthias Sohn break; 139536db18cSMatthias Sohn case 1: 140536db18cSMatthias Sohn w = w2; 141536db18cSMatthias Sohn break; 142536db18cSMatthias Sohn case 2: 143536db18cSMatthias Sohn w = w3; 144536db18cSMatthias Sohn break; 145536db18cSMatthias Sohn case 3: 146536db18cSMatthias Sohn w = w4; 147536db18cSMatthias Sohn break; 148536db18cSMatthias Sohn default: 149536db18cSMatthias Sohn throw new ArrayIndexOutOfBoundsException(index); 150536db18cSMatthias Sohn } 151536db18cSMatthias Sohn 152536db18cSMatthias Sohn return (int) ((w >>> (8 * (15 - (index & 15)))) & 0xff); 153536db18cSMatthias Sohn } 154536db18cSMatthias Sohn 155536db18cSMatthias Sohn /** 156e0332bfbSMatthias Sohn * {@inheritDoc} 157536db18cSMatthias Sohn * 158e0332bfbSMatthias Sohn * Compare this LongObjectId to another and obtain a sort ordering. 159536db18cSMatthias Sohn */ 1607ac182f4SDavid Pursehouse @Override compareTo(AnyLongObjectId other)1616d370d83SHan-Wen Nienhuys public final int compareTo(AnyLongObjectId other) { 162536db18cSMatthias Sohn if (this == other) 163536db18cSMatthias Sohn return 0; 164536db18cSMatthias Sohn 165536db18cSMatthias Sohn int cmp; 166536db18cSMatthias Sohn 167536db18cSMatthias Sohn cmp = NB.compareUInt64(w1, other.w1); 168536db18cSMatthias Sohn if (cmp != 0) 169536db18cSMatthias Sohn return cmp; 170536db18cSMatthias Sohn 171536db18cSMatthias Sohn cmp = NB.compareUInt64(w2, other.w2); 172536db18cSMatthias Sohn if (cmp != 0) 173536db18cSMatthias Sohn return cmp; 174536db18cSMatthias Sohn 175536db18cSMatthias Sohn cmp = NB.compareUInt64(w3, other.w3); 176536db18cSMatthias Sohn if (cmp != 0) 177536db18cSMatthias Sohn return cmp; 178536db18cSMatthias Sohn 179536db18cSMatthias Sohn return NB.compareUInt64(w4, other.w4); 180536db18cSMatthias Sohn } 181536db18cSMatthias Sohn 182536db18cSMatthias Sohn /** 183536db18cSMatthias Sohn * Compare this LongObjectId to a network-byte-order LongObjectId. 184536db18cSMatthias Sohn * 185536db18cSMatthias Sohn * @param bs 186536db18cSMatthias Sohn * array containing the other LongObjectId in network byte order. 187536db18cSMatthias Sohn * @param p 188536db18cSMatthias Sohn * position within {@code bs} to start the compare at. At least 189536db18cSMatthias Sohn * 32 bytes, starting at this position are required. 190536db18cSMatthias Sohn * @return a negative integer, zero, or a positive integer as this object is 191536db18cSMatthias Sohn * less than, equal to, or greater than the specified object. 192536db18cSMatthias Sohn */ compareTo(byte[] bs, int p)1936d370d83SHan-Wen Nienhuys public final int compareTo(byte[] bs, int p) { 194536db18cSMatthias Sohn int cmp; 195536db18cSMatthias Sohn 196536db18cSMatthias Sohn cmp = NB.compareUInt64(w1, NB.decodeInt64(bs, p)); 197536db18cSMatthias Sohn if (cmp != 0) 198536db18cSMatthias Sohn return cmp; 199536db18cSMatthias Sohn 200536db18cSMatthias Sohn cmp = NB.compareUInt64(w2, NB.decodeInt64(bs, p + 8)); 201536db18cSMatthias Sohn if (cmp != 0) 202536db18cSMatthias Sohn return cmp; 203536db18cSMatthias Sohn 204536db18cSMatthias Sohn cmp = NB.compareUInt64(w3, NB.decodeInt64(bs, p + 16)); 205536db18cSMatthias Sohn if (cmp != 0) 206536db18cSMatthias Sohn return cmp; 207536db18cSMatthias Sohn 208536db18cSMatthias Sohn return NB.compareUInt64(w4, NB.decodeInt64(bs, p + 24)); 209536db18cSMatthias Sohn } 210536db18cSMatthias Sohn 211536db18cSMatthias Sohn /** 212536db18cSMatthias Sohn * Compare this LongObjectId to a network-byte-order LongObjectId. 213536db18cSMatthias Sohn * 214536db18cSMatthias Sohn * @param bs 215536db18cSMatthias Sohn * array containing the other LongObjectId in network byte order. 216536db18cSMatthias Sohn * @param p 217536db18cSMatthias Sohn * position within {@code bs} to start the compare at. At least 4 218536db18cSMatthias Sohn * longs, starting at this position are required. 219536db18cSMatthias Sohn * @return a negative integer, zero, or a positive integer as this object is 220536db18cSMatthias Sohn * less than, equal to, or greater than the specified object. 221536db18cSMatthias Sohn */ compareTo(long[] bs, int p)2226d370d83SHan-Wen Nienhuys public final int compareTo(long[] bs, int p) { 223536db18cSMatthias Sohn int cmp; 224536db18cSMatthias Sohn 225536db18cSMatthias Sohn cmp = NB.compareUInt64(w1, bs[p]); 226536db18cSMatthias Sohn if (cmp != 0) 227536db18cSMatthias Sohn return cmp; 228536db18cSMatthias Sohn 229536db18cSMatthias Sohn cmp = NB.compareUInt64(w2, bs[p + 1]); 230536db18cSMatthias Sohn if (cmp != 0) 231536db18cSMatthias Sohn return cmp; 232536db18cSMatthias Sohn 233536db18cSMatthias Sohn cmp = NB.compareUInt64(w3, bs[p + 2]); 234536db18cSMatthias Sohn if (cmp != 0) 235536db18cSMatthias Sohn return cmp; 236536db18cSMatthias Sohn 237536db18cSMatthias Sohn return NB.compareUInt64(w4, bs[p + 3]); 238536db18cSMatthias Sohn } 239536db18cSMatthias Sohn 240536db18cSMatthias Sohn /** 241536db18cSMatthias Sohn * Tests if this LongObjectId starts with the given abbreviation. 242536db18cSMatthias Sohn * 243536db18cSMatthias Sohn * @param abbr 244536db18cSMatthias Sohn * the abbreviation. 245536db18cSMatthias Sohn * @return true if this LongObjectId begins with the abbreviation; else 246536db18cSMatthias Sohn * false. 247536db18cSMatthias Sohn */ startsWith(AbbreviatedLongObjectId abbr)2486d370d83SHan-Wen Nienhuys public boolean startsWith(AbbreviatedLongObjectId abbr) { 249536db18cSMatthias Sohn return abbr.prefixCompare(this) == 0; 250536db18cSMatthias Sohn } 251536db18cSMatthias Sohn 252e0332bfbSMatthias Sohn /** {@inheritDoc} */ 2537ac182f4SDavid Pursehouse @Override hashCode()254536db18cSMatthias Sohn public final int hashCode() { 255536db18cSMatthias Sohn return (int) (w1 >> 32); 256536db18cSMatthias Sohn } 257536db18cSMatthias Sohn 258536db18cSMatthias Sohn /** 259536db18cSMatthias Sohn * Determine if this LongObjectId has exactly the same value as another. 260536db18cSMatthias Sohn * 261536db18cSMatthias Sohn * @param other 262536db18cSMatthias Sohn * the other id to compare to. May be null. 263536db18cSMatthias Sohn * @return true only if both LongObjectIds have identical bits. 264536db18cSMatthias Sohn */ 26513df53c1SDavid Pursehouse @SuppressWarnings({ "NonOverridingEquals", "AmbiguousMethodReference" }) equals(AnyLongObjectId other)2666d370d83SHan-Wen Nienhuys public final boolean equals(AnyLongObjectId other) { 267536db18cSMatthias Sohn return other != null ? equals(this, other) : false; 268536db18cSMatthias Sohn } 269536db18cSMatthias Sohn 270e0332bfbSMatthias Sohn /** {@inheritDoc} */ 2717ac182f4SDavid Pursehouse @Override equals(Object o)2726d370d83SHan-Wen Nienhuys public final boolean equals(Object o) { 27398cdca9bSDavid Pursehouse if (o instanceof AnyLongObjectId) { 274536db18cSMatthias Sohn return equals((AnyLongObjectId) o); 27598cdca9bSDavid Pursehouse } 276536db18cSMatthias Sohn return false; 277536db18cSMatthias Sohn } 278536db18cSMatthias Sohn 279536db18cSMatthias Sohn /** 280536db18cSMatthias Sohn * Copy this LongObjectId to an output writer in raw binary. 281536db18cSMatthias Sohn * 282536db18cSMatthias Sohn * @param w 283536db18cSMatthias Sohn * the buffer to copy to. Must be in big endian order. 284536db18cSMatthias Sohn */ copyRawTo(ByteBuffer w)2856d370d83SHan-Wen Nienhuys public void copyRawTo(ByteBuffer w) { 286536db18cSMatthias Sohn w.putLong(w1); 287536db18cSMatthias Sohn w.putLong(w2); 288536db18cSMatthias Sohn w.putLong(w3); 289536db18cSMatthias Sohn w.putLong(w4); 290536db18cSMatthias Sohn } 291536db18cSMatthias Sohn 292536db18cSMatthias Sohn /** 293536db18cSMatthias Sohn * Copy this LongObjectId to a byte array. 294536db18cSMatthias Sohn * 295536db18cSMatthias Sohn * @param b 296536db18cSMatthias Sohn * the buffer to copy to. 297536db18cSMatthias Sohn * @param o 298536db18cSMatthias Sohn * the offset within b to write at. 299536db18cSMatthias Sohn */ copyRawTo(byte[] b, int o)3006d370d83SHan-Wen Nienhuys public void copyRawTo(byte[] b, int o) { 301536db18cSMatthias Sohn NB.encodeInt64(b, o, w1); 302536db18cSMatthias Sohn NB.encodeInt64(b, o + 8, w2); 303536db18cSMatthias Sohn NB.encodeInt64(b, o + 16, w3); 304536db18cSMatthias Sohn NB.encodeInt64(b, o + 24, w4); 305536db18cSMatthias Sohn } 306536db18cSMatthias Sohn 307536db18cSMatthias Sohn /** 308536db18cSMatthias Sohn * Copy this LongObjectId to an long array. 309536db18cSMatthias Sohn * 310536db18cSMatthias Sohn * @param b 311536db18cSMatthias Sohn * the buffer to copy to. 312536db18cSMatthias Sohn * @param o 313536db18cSMatthias Sohn * the offset within b to write at. 314536db18cSMatthias Sohn */ copyRawTo(long[] b, int o)3156d370d83SHan-Wen Nienhuys public void copyRawTo(long[] b, int o) { 316536db18cSMatthias Sohn b[o] = w1; 317536db18cSMatthias Sohn b[o + 1] = w2; 318536db18cSMatthias Sohn b[o + 2] = w3; 319536db18cSMatthias Sohn b[o + 3] = w4; 320536db18cSMatthias Sohn } 321536db18cSMatthias Sohn 322536db18cSMatthias Sohn /** 323536db18cSMatthias Sohn * Copy this LongObjectId to an output writer in raw binary. 324536db18cSMatthias Sohn * 325536db18cSMatthias Sohn * @param w 326536db18cSMatthias Sohn * the stream to write to. 327e0332bfbSMatthias Sohn * @throws java.io.IOException 328536db18cSMatthias Sohn * the stream writing failed. 329536db18cSMatthias Sohn */ copyRawTo(OutputStream w)3306d370d83SHan-Wen Nienhuys public void copyRawTo(OutputStream w) throws IOException { 331536db18cSMatthias Sohn writeRawLong(w, w1); 332536db18cSMatthias Sohn writeRawLong(w, w2); 333536db18cSMatthias Sohn writeRawLong(w, w3); 334536db18cSMatthias Sohn writeRawLong(w, w4); 335536db18cSMatthias Sohn } 336536db18cSMatthias Sohn writeRawLong(OutputStream w, long v)3376d370d83SHan-Wen Nienhuys private static void writeRawLong(OutputStream w, long v) 338536db18cSMatthias Sohn throws IOException { 339536db18cSMatthias Sohn w.write((int) (v >>> 56)); 340536db18cSMatthias Sohn w.write((int) (v >>> 48)); 341536db18cSMatthias Sohn w.write((int) (v >>> 40)); 342536db18cSMatthias Sohn w.write((int) (v >>> 32)); 343536db18cSMatthias Sohn w.write((int) (v >>> 24)); 344536db18cSMatthias Sohn w.write((int) (v >>> 16)); 345536db18cSMatthias Sohn w.write((int) (v >>> 8)); 346536db18cSMatthias Sohn w.write((int) v); 347536db18cSMatthias Sohn } 348536db18cSMatthias Sohn 349536db18cSMatthias Sohn /** 350536db18cSMatthias Sohn * Copy this LongObjectId to an output writer in hex format. 351536db18cSMatthias Sohn * 352536db18cSMatthias Sohn * @param w 353536db18cSMatthias Sohn * the stream to copy to. 354e0332bfbSMatthias Sohn * @throws java.io.IOException 355536db18cSMatthias Sohn * the stream writing failed. 356536db18cSMatthias Sohn */ copyTo(OutputStream w)3576d370d83SHan-Wen Nienhuys public void copyTo(OutputStream w) throws IOException { 358536db18cSMatthias Sohn w.write(toHexByteArray()); 359536db18cSMatthias Sohn } 360536db18cSMatthias Sohn 361536db18cSMatthias Sohn /** 362536db18cSMatthias Sohn * Copy this LongObjectId to a byte array in hex format. 363536db18cSMatthias Sohn * 364536db18cSMatthias Sohn * @param b 365536db18cSMatthias Sohn * the buffer to copy to. 366536db18cSMatthias Sohn * @param o 367536db18cSMatthias Sohn * the offset within b to write at. 368536db18cSMatthias Sohn */ copyTo(byte[] b, int o)369536db18cSMatthias Sohn public void copyTo(byte[] b, int o) { 370536db18cSMatthias Sohn formatHexByte(b, o + 0, w1); 371536db18cSMatthias Sohn formatHexByte(b, o + 16, w2); 372536db18cSMatthias Sohn formatHexByte(b, o + 32, w3); 373536db18cSMatthias Sohn formatHexByte(b, o + 48, w4); 374536db18cSMatthias Sohn } 375536db18cSMatthias Sohn 376536db18cSMatthias Sohn /** 377536db18cSMatthias Sohn * Copy this LongObjectId to a ByteBuffer in hex format. 378536db18cSMatthias Sohn * 379536db18cSMatthias Sohn * @param b 380536db18cSMatthias Sohn * the buffer to copy to. 381536db18cSMatthias Sohn */ copyTo(ByteBuffer b)382536db18cSMatthias Sohn public void copyTo(ByteBuffer b) { 383536db18cSMatthias Sohn b.put(toHexByteArray()); 384536db18cSMatthias Sohn } 385536db18cSMatthias Sohn toHexByteArray()386536db18cSMatthias Sohn private byte[] toHexByteArray() { 387536db18cSMatthias Sohn final byte[] dst = new byte[Constants.LONG_OBJECT_ID_STRING_LENGTH]; 388536db18cSMatthias Sohn formatHexByte(dst, 0, w1); 389536db18cSMatthias Sohn formatHexByte(dst, 16, w2); 390536db18cSMatthias Sohn formatHexByte(dst, 32, w3); 391536db18cSMatthias Sohn formatHexByte(dst, 48, w4); 392536db18cSMatthias Sohn return dst; 393536db18cSMatthias Sohn } 394536db18cSMatthias Sohn 395536db18cSMatthias Sohn private static final byte[] hexbyte = { '0', '1', '2', '3', '4', '5', '6', 396536db18cSMatthias Sohn '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 397536db18cSMatthias Sohn formatHexByte(byte[] dst, int p, long w)3986d370d83SHan-Wen Nienhuys private static void formatHexByte(byte[] dst, int p, long w) { 399536db18cSMatthias Sohn int o = p + 15; 400536db18cSMatthias Sohn while (o >= p && w != 0) { 401536db18cSMatthias Sohn dst[o--] = hexbyte[(int) (w & 0xf)]; 402536db18cSMatthias Sohn w >>>= 4; 403536db18cSMatthias Sohn } 404536db18cSMatthias Sohn while (o >= p) 405536db18cSMatthias Sohn dst[o--] = '0'; 406536db18cSMatthias Sohn } 407536db18cSMatthias Sohn 408536db18cSMatthias Sohn /** 409536db18cSMatthias Sohn * Copy this LongObjectId to an output writer in hex format. 410536db18cSMatthias Sohn * 411536db18cSMatthias Sohn * @param w 412536db18cSMatthias Sohn * the stream to copy to. 413e0332bfbSMatthias Sohn * @throws java.io.IOException 414536db18cSMatthias Sohn * the stream writing failed. 415536db18cSMatthias Sohn */ copyTo(Writer w)4166d370d83SHan-Wen Nienhuys public void copyTo(Writer w) throws IOException { 417536db18cSMatthias Sohn w.write(toHexCharArray()); 418536db18cSMatthias Sohn } 419536db18cSMatthias Sohn 420536db18cSMatthias Sohn /** 421536db18cSMatthias Sohn * Copy this LongObjectId to an output writer in hex format. 422536db18cSMatthias Sohn * 423536db18cSMatthias Sohn * @param tmp 424536db18cSMatthias Sohn * temporary char array to buffer construct into before writing. 425536db18cSMatthias Sohn * Must be at least large enough to hold 2 digits for each byte 426536db18cSMatthias Sohn * of object id (64 characters or larger). 427536db18cSMatthias Sohn * @param w 428536db18cSMatthias Sohn * the stream to copy to. 429e0332bfbSMatthias Sohn * @throws java.io.IOException 430536db18cSMatthias Sohn * the stream writing failed. 431536db18cSMatthias Sohn */ copyTo(char[] tmp, Writer w)4326d370d83SHan-Wen Nienhuys public void copyTo(char[] tmp, Writer w) throws IOException { 433536db18cSMatthias Sohn toHexCharArray(tmp); 434536db18cSMatthias Sohn w.write(tmp, 0, Constants.LONG_OBJECT_ID_STRING_LENGTH); 435536db18cSMatthias Sohn } 436536db18cSMatthias Sohn 437536db18cSMatthias Sohn /** 438536db18cSMatthias Sohn * Copy this LongObjectId to a StringBuilder in hex format. 439536db18cSMatthias Sohn * 440536db18cSMatthias Sohn * @param tmp 441536db18cSMatthias Sohn * temporary char array to buffer construct into before writing. 442536db18cSMatthias Sohn * Must be at least large enough to hold 2 digits for each byte 443536db18cSMatthias Sohn * of object id (64 characters or larger). 444536db18cSMatthias Sohn * @param w 445536db18cSMatthias Sohn * the string to append onto. 446536db18cSMatthias Sohn */ copyTo(char[] tmp, StringBuilder w)4476d370d83SHan-Wen Nienhuys public void copyTo(char[] tmp, StringBuilder w) { 448536db18cSMatthias Sohn toHexCharArray(tmp); 449536db18cSMatthias Sohn w.append(tmp, 0, Constants.LONG_OBJECT_ID_STRING_LENGTH); 450536db18cSMatthias Sohn } 451536db18cSMatthias Sohn toHexCharArray()452536db18cSMatthias Sohn char[] toHexCharArray() { 453536db18cSMatthias Sohn final char[] dst = new char[Constants.LONG_OBJECT_ID_STRING_LENGTH]; 454536db18cSMatthias Sohn toHexCharArray(dst); 455536db18cSMatthias Sohn return dst; 456536db18cSMatthias Sohn } 457536db18cSMatthias Sohn toHexCharArray(char[] dst)4586d370d83SHan-Wen Nienhuys private void toHexCharArray(char[] dst) { 459536db18cSMatthias Sohn formatHexChar(dst, 0, w1); 460536db18cSMatthias Sohn formatHexChar(dst, 16, w2); 461536db18cSMatthias Sohn formatHexChar(dst, 32, w3); 462536db18cSMatthias Sohn formatHexChar(dst, 48, w4); 463536db18cSMatthias Sohn } 464536db18cSMatthias Sohn 465536db18cSMatthias Sohn private static final char[] hexchar = { '0', '1', '2', '3', '4', '5', '6', 466536db18cSMatthias Sohn '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 467536db18cSMatthias Sohn formatHexChar(char[] dst, int p, long w)468f3ec7cf3SHan-Wen Nienhuys static void formatHexChar(char[] dst, int p, long w) { 469536db18cSMatthias Sohn int o = p + 15; 470536db18cSMatthias Sohn while (o >= p && w != 0) { 471536db18cSMatthias Sohn dst[o--] = hexchar[(int) (w & 0xf)]; 472536db18cSMatthias Sohn w >>>= 4; 473536db18cSMatthias Sohn } 474536db18cSMatthias Sohn while (o >= p) 475536db18cSMatthias Sohn dst[o--] = '0'; 476536db18cSMatthias Sohn } 477536db18cSMatthias Sohn 478e0332bfbSMatthias Sohn /** {@inheritDoc} */ 479536db18cSMatthias Sohn @SuppressWarnings("nls") 480536db18cSMatthias Sohn @Override toString()481536db18cSMatthias Sohn public String toString() { 482536db18cSMatthias Sohn return "AnyLongObjectId[" + name() + "]"; 483536db18cSMatthias Sohn } 484536db18cSMatthias Sohn 485536db18cSMatthias Sohn /** 486e0332bfbSMatthias Sohn * Get string form of the SHA-256 487e0332bfbSMatthias Sohn * 488536db18cSMatthias Sohn * @return string form of the SHA-256, in lower case hexadecimal. 489536db18cSMatthias Sohn */ name()490536db18cSMatthias Sohn public final String name() { 491536db18cSMatthias Sohn return new String(toHexCharArray()); 492536db18cSMatthias Sohn } 493536db18cSMatthias Sohn 494536db18cSMatthias Sohn /** 495e0332bfbSMatthias Sohn * Get string form of the SHA-256 496e0332bfbSMatthias Sohn * 497536db18cSMatthias Sohn * @return string form of the SHA-256, in lower case hexadecimal. 498536db18cSMatthias Sohn */ getName()499536db18cSMatthias Sohn public final String getName() { 500536db18cSMatthias Sohn return name(); 501536db18cSMatthias Sohn } 502536db18cSMatthias Sohn 503536db18cSMatthias Sohn /** 504536db18cSMatthias Sohn * Return an abbreviation (prefix) of this object SHA-256. 505536db18cSMatthias Sohn * <p> 506536db18cSMatthias Sohn * This implementation does not guarantee uniqueness. Callers should instead 507e0332bfbSMatthias Sohn * use 508e0332bfbSMatthias Sohn * {@link org.eclipse.jgit.lib.ObjectReader#abbreviate(AnyObjectId, int)} to 509e0332bfbSMatthias Sohn * obtain a unique abbreviation within the scope of a particular object 510e0332bfbSMatthias Sohn * database. 511536db18cSMatthias Sohn * 512536db18cSMatthias Sohn * @param len 513536db18cSMatthias Sohn * length of the abbreviated string. 514536db18cSMatthias Sohn * @return SHA-256 abbreviation. 515536db18cSMatthias Sohn */ abbreviate(int len)5166d370d83SHan-Wen Nienhuys public AbbreviatedLongObjectId abbreviate(int len) { 517536db18cSMatthias Sohn final long a = AbbreviatedLongObjectId.mask(len, 1, w1); 518536db18cSMatthias Sohn final long b = AbbreviatedLongObjectId.mask(len, 2, w2); 519536db18cSMatthias Sohn final long c = AbbreviatedLongObjectId.mask(len, 3, w3); 520536db18cSMatthias Sohn final long d = AbbreviatedLongObjectId.mask(len, 4, w4); 521536db18cSMatthias Sohn return new AbbreviatedLongObjectId(len, a, b, c, d); 522536db18cSMatthias Sohn } 523536db18cSMatthias Sohn 524536db18cSMatthias Sohn /** 525536db18cSMatthias Sohn * Obtain an immutable copy of this current object. 526536db18cSMatthias Sohn * <p> 527536db18cSMatthias Sohn * Only returns <code>this</code> if this instance is an unsubclassed 528e0332bfbSMatthias Sohn * instance of {@link org.eclipse.jgit.lfs.lib.LongObjectId}; otherwise a 529e0332bfbSMatthias Sohn * new instance is returned holding the same value. 530536db18cSMatthias Sohn * <p> 531536db18cSMatthias Sohn * This method is useful to shed any additional memory that may be tied to 532536db18cSMatthias Sohn * the subclass, yet retain the unique identity of the object id for future 533536db18cSMatthias Sohn * lookups within maps and repositories. 534536db18cSMatthias Sohn * 535536db18cSMatthias Sohn * @return an immutable copy, using the smallest memory footprint possible. 536536db18cSMatthias Sohn */ copy()537536db18cSMatthias Sohn public final LongObjectId copy() { 538536db18cSMatthias Sohn if (getClass() == LongObjectId.class) 539536db18cSMatthias Sohn return (LongObjectId) this; 540536db18cSMatthias Sohn return new LongObjectId(this); 541536db18cSMatthias Sohn } 542536db18cSMatthias Sohn 543536db18cSMatthias Sohn /** 544536db18cSMatthias Sohn * Obtain an immutable copy of this current object. 545536db18cSMatthias Sohn * <p> 546536db18cSMatthias Sohn * See {@link #copy()} if <code>this</code> is a possibly subclassed (but 547536db18cSMatthias Sohn * immutable) identity and the application needs a lightweight identity 548536db18cSMatthias Sohn * <i>only</i> reference. 549536db18cSMatthias Sohn * 550536db18cSMatthias Sohn * @return an immutable copy. May be <code>this</code> if this is already an 551536db18cSMatthias Sohn * immutable instance. 552536db18cSMatthias Sohn */ toObjectId()553536db18cSMatthias Sohn public abstract LongObjectId toObjectId(); 554536db18cSMatthias Sohn } 555