private void CopyEntries(DeltaIndexScanner scan) { // Rebuild the entries list from the scanner, positioning all // blocks in the same hash chain next to each other. We can // then later discard the next list, along with the scanner. // int next = 1; for (int i = 0; i < table.Length; i++) { int h = table[i]; if (h == 0) { continue; } table[i] = next; do { entries[next++] = scan.entries[h]; h = scan.next[h]; } while (h != 0); } }
private int CountEntries(DeltaIndexScanner scan) { // Figure out exactly how many entries we need. As we do the // enumeration truncate any delta chains longer than what we // are willing to scan during encode. This keeps the encode // logic linear in the size of the input rather than quadratic. // int cnt = 0; for (int i = 0; i < table.Length; i++) { int h = table[i]; if (h == 0) { continue; } int len = 0; do { if (++len == MAX_CHAIN_LENGTH) { scan.next[h] = 0; break; } h = scan.next[h]; } while (h != 0); cnt += len; } return cnt; }
/// <summary>Construct an index from the source file.</summary> /// <remarks>Construct an index from the source file.</remarks> /// <param name="sourceBuffer"> /// the source file's raw contents. The buffer will be held by the /// index instance to facilitate matching, and therefore must not /// be modified by the caller. /// </param> public DeltaIndex(byte[] sourceBuffer) { src = sourceBuffer; DeltaIndexScanner scan = new DeltaIndexScanner(src, src.Length); // Reuse the same table the scanner made. We will replace the // values at each position, but we want the same-length array. // table = scan.table; tableMask = scan.tableMask; // Because entry index 0 means there are no entries for the // slot in the table, we have to allocate one extra position. // entries = new long[1 + CountEntries(scan)]; CopyEntries(scan); }