2
This code is derived from jgit (http://eclipse.org/jgit).
3
Copyright owners are documented in jgit's IP log.
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
12
Redistribution and use in source and binary forms, with or
13
without modification, are permitted provided that the following
16
- Redistributions of source code must retain the above copyright
17
notice, this list of conditions and the following disclaimer.
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.
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
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.
45
using System.Collections.Generic;
47
using NGit.Storage.File;
51
namespace NGit.Storage.File
53
internal class PackIndexV1 : PackIndex
55
private const int IDX_HDR_LEN = 256 * 4;
57
private readonly long[] idxHeader;
59
private byte[][] idxdata;
61
private long objectCnt;
63
/// <exception cref="NGit.Errors.CorruptObjectException"></exception>
64
/// <exception cref="System.IO.IOException"></exception>
65
internal PackIndexV1(InputStream fd, byte[] hdr)
67
byte[] fanoutTable = new byte[IDX_HDR_LEN];
68
System.Array.Copy(hdr, 0, fanoutTable, 0, hdr.Length);
69
IOUtil.ReadFully(fd, fanoutTable, hdr.Length, IDX_HDR_LEN - hdr.Length);
70
idxHeader = new long[256];
71
// really unsigned 32-bit...
72
for (int k = 0; k < idxHeader.Length; k++)
74
idxHeader[k] = NB.DecodeUInt32(fanoutTable, k * 4);
76
idxdata = new byte[idxHeader.Length][];
77
for (int k_1 = 0; k_1 < idxHeader.Length; k_1++)
82
n = (int)(idxHeader[k_1]);
86
n = (int)(idxHeader[k_1] - idxHeader[k_1 - 1]);
90
idxdata[k_1] = new byte[n * (Constants.OBJECT_ID_LENGTH + 4)];
91
IOUtil.ReadFully(fd, idxdata[k_1], 0, idxdata[k_1].Length);
94
objectCnt = idxHeader[255];
95
packChecksum = new byte[20];
96
IOUtil.ReadFully(fd, packChecksum, 0, packChecksum.Length);
99
internal override long GetObjectCount()
104
internal override long GetOffset64Count()
107
foreach (PackIndex.MutableEntry e in this)
109
if (e.GetOffset() >= int.MaxValue)
117
internal override ObjectId GetObjectId(long nthPosition)
119
int levelOne = System.Array.BinarySearch(idxHeader, nthPosition + 1);
123
// If we hit the bucket exactly the item is in the bucket, or
124
// any bucket before it which has the same object count.
126
@base = idxHeader[levelOne];
127
while (levelOne > 0 && @base == idxHeader[levelOne - 1])
134
// The item is in the bucket we would insert it into.
136
levelOne = -(levelOne + 1);
138
@base = levelOne > 0 ? idxHeader[levelOne - 1] : 0;
139
int p = (int)(nthPosition - @base);
140
int dataIdx = IdOffset(p);
141
return ObjectId.FromRaw(idxdata[levelOne], dataIdx);
144
internal override long FindOffset(AnyObjectId objId)
146
int levelOne = objId.FirstByte;
147
byte[] data = idxdata[levelOne];
152
int high = data.Length / (4 + Constants.OBJECT_ID_LENGTH);
156
int mid = (int)(((uint)(low + high)) >> 1);
157
int pos = IdOffset(mid);
158
int cmp = objId.CompareTo(data, pos);
167
int b0 = data[pos - 4] & unchecked((int)(0xff));
168
int b1 = data[pos - 3] & unchecked((int)(0xff));
169
int b2 = data[pos - 2] & unchecked((int)(0xff));
170
int b3 = data[pos - 1] & unchecked((int)(0xff));
171
return (((long)b0) << 24) | (b1 << 16) | (b2 << 8) | (b3);
183
internal override long FindCRC32(AnyObjectId objId)
185
throw new NotSupportedException();
188
internal override bool HasCRC32Support()
193
public override Sharpen.Iterator<PackIndex.MutableEntry> Iterator()
195
return new PackIndexV1.IndexV1Iterator(this);
198
/// <exception cref="System.IO.IOException"></exception>
199
internal override void Resolve(ICollection<ObjectId> matches, AbbreviatedObjectId
202
byte[] data = idxdata[id.FirstByte];
207
int max = data.Length / (4 + Constants.OBJECT_ID_LENGTH);
212
int p = (int)(((uint)(low + high)) >> 1);
213
int cmp = id.PrefixCompare(data, IdOffset(p));
222
// We may have landed in the middle of the matches. Move
223
// backwards to the start of matches, then walk forwards.
225
while (0 < p && id.PrefixCompare(data, IdOffset(p - 1)) == 0)
229
for (; p < max && id.PrefixCompare(data, IdOffset(p)) == 0; p++)
231
matches.AddItem(ObjectId.FromRaw(data, IdOffset(p)));
232
if (matches.Count > matchLimit)
248
private static int IdOffset(int mid)
250
return ((4 + Constants.OBJECT_ID_LENGTH) * mid) + 4;
253
private class IndexV1Iterator : PackIndex.EntriesIterator
255
private int levelOne;
257
private int levelTwo;
259
protected internal override PackIndex.MutableEntry InitEntry()
261
return new _MutableEntry_219(this);
264
private sealed class _MutableEntry_219 : PackIndex.MutableEntry
266
public _MutableEntry_219(IndexV1Iterator _enclosing)
268
this._enclosing = _enclosing;
271
internal override void EnsureId()
273
this.idBuffer.FromRaw(this._enclosing._enclosing.idxdata[this._enclosing.levelOne
274
], this._enclosing.levelTwo - Constants.OBJECT_ID_LENGTH);
277
private readonly IndexV1Iterator _enclosing;
280
public override PackIndex.MutableEntry Next()
282
for (; this.levelOne < this._enclosing.idxdata.Length; this.levelOne++)
284
if (this._enclosing.idxdata[this.levelOne] == null)
288
if (this.levelTwo < this._enclosing.idxdata[this.levelOne].Length)
290
this.entry.offset = NB.DecodeUInt32(this._enclosing.idxdata[this.levelOne], this.
292
this.levelTwo += Constants.OBJECT_ID_LENGTH + 4;
293
this.returnedNumber++;
298
throw new NoSuchElementException();
301
internal IndexV1Iterator(PackIndexV1 _enclosing) : base(_enclosing)
303
this._enclosing = _enclosing;
306
private readonly PackIndexV1 _enclosing;