public Handle GetGenerationHandle(Handle handle, out int generation) { if (handle.IsVirtual) { // TODO: if a virtual handle is connected to real handle then translate the rid, // otherwise return vhandle and base. throw new NotSupportedException(); } if (handle.IsHeapHandle) { int heapOffset = handle.Offset; HeapIndex heapIndex; MetadataTokens.TryGetHeapIndex(handle.Kind, out heapIndex); var sizes = _heapSizes[(int)heapIndex]; generation = sizes.BinarySearch(heapOffset); if (generation >= 0) { Debug.Assert(sizes[generation] == heapOffset); // the index points to the start of the next generation that added data to the heap: do { generation++; }while (generation < sizes.Length && sizes[generation] == heapOffset); } else { generation = ~generation; } if (generation >= sizes.Length) { throw new ArgumentException(SR.HandleBelongsToFutureGeneration, "handle"); } // GUID heap accumulates - previous heap is copied to the next generation int relativeHeapOffset = (handle.Type == HandleType.Guid || generation == 0) ? heapOffset : heapOffset - sizes[generation - 1]; return(new Handle((byte)handle.Type, relativeHeapOffset)); } else { int rowId = handle.RowId; var sizes = _rowCounts[(int)handle.Type]; generation = sizes.BinarySearch(new RowCounts { AggregateInserts = rowId }); if (generation >= 0) { Debug.Assert(sizes[generation].AggregateInserts == rowId); // the row is in a generation that inserted exactly one row -- the one that we are looking for; // or it's in a preceding generation if the current one didn't insert any rows of the kind: while (generation > 0 && sizes[generation - 1].AggregateInserts == rowId) { generation--; } } else { // the row is in a generation that inserted multiple new rows: generation = ~generation; if (generation >= sizes.Length) { throw new ArgumentException(SR.HandleBelongsToFutureGeneration, "handle"); } } // In each delta table updates always precede inserts. int relativeRowId = (generation == 0) ? rowId : rowId - sizes[generation - 1].AggregateInserts + sizes[generation].Updates; return(new Handle((byte)handle.Type, relativeRowId)); } }
public Handle GetGenerationHandle(Handle handle, out int generation) { if (handle.IsVirtual) { // TODO: if a virtual handle is connected to real handle then translate the rid, // otherwise return vhandle and base. throw new NotSupportedException(); } int rowId = (int)handle.RowId; uint typeId = handle.TokenType; int relativeRowId; if (handle.IsHeapHandle) { HeapIndex heapIndex; MetadataTokens.TryGetHeapIndex(handle.Kind, out heapIndex); var sizes = heapSizes[(int)heapIndex]; generation = sizes.BinarySearch(rowId); if (generation >= 0) { DebugCorlib.Assert(sizes[generation] == rowId); // the index points to the start of the next generation that added data to the heap: do { generation++; }while (generation < sizes.Length && sizes[generation] == rowId); } else { generation = ~generation; } if (generation >= sizes.Length) { throw new ArgumentException("Handle belongs to a future generation", "handle"); } // GUID heap accumulates - previous heap is copied to the next generation relativeRowId = (typeId == TokenTypeIds.Guid || generation == 0) ? rowId : rowId - sizes[generation - 1]; } else { var sizes = rowCounts[(int)handle.value >> TokenTypeIds.RowIdBitCount]; generation = sizes.BinarySearch(new RowCounts { AggregateInserts = rowId }); if (generation >= 0) { DebugCorlib.Assert(sizes[generation].AggregateInserts == rowId); // the row is in a generation that inserted exactly one row -- the one that we are looking for; // or it's in a preceeding generation if the current one didn't insert any rows of the kind: while (generation > 0 && sizes[generation - 1].AggregateInserts == rowId) { generation--; } } else { // the row is in a generation that inserted multiple new rows: generation = ~generation; if (generation >= sizes.Length) { throw new ArgumentException("Handle belongs to a future generation", "handle"); } } // In each delta table updates always precede inserts. relativeRowId = (generation == 0) ? rowId : rowId - sizes[generation - 1].AggregateInserts + sizes[generation].Updates; } return(new Handle(typeId | (uint)relativeRowId)); }