void AddNameIndexes(Dictionary <uint, BlobDataInfoPosition> dict, TablesHeap tables, Table table, int column) { var mdTable = tables.MDTables[(int)table]; if (mdTable.Rows == 0) { return; } var heapStart = Span.Span.Start; var heapEnd = Span.Span.End; var buffer = Span.Buffer; var recPos = mdTable.Span.Start; var rows = mdTable.Rows; var colInfo = mdTable.Columns[column]; uint recSize = mdTable.RowSize; bool bigBlob = colInfo.Size == 4; for (uint rid = 1; rid <= rows; rid++, recPos += recSize) { uint offs = bigBlob ? buffer.ReadUInt32(recPos + colInfo.Offset) : buffer.ReadUInt16(recPos + colInfo.Offset); if (offs == 0) { continue; } var pos = heapStart + offs; int len = ReadCompressedUInt32(ref pos) ?? -1; if (len <= 0) { continue; } var end = HexPosition.Min(heapEnd, pos + len); pos = SkipUtf8Char(pos, end); while (pos < end) { var nameOffs = ReadCompressedUInt32(ref pos) ?? -1; if (nameOffs < 0) { break; } if (nameOffs != 0 && !dict.ContainsKey((uint)nameOffs)) { var namePos = heapStart + nameOffs; if (namePos < heapEnd) { dict[(uint)nameOffs] = new BlobDataInfoPosition(namePos, BlobDataKind.Utf8Name); } } } } }
void Add(Dictionary <uint, BlobDataInfoPosition> dict, MDTable mdTable, int column1, BlobDataKind kind1) { var heapStart = Span.Span.Start; var heapEnd = Span.Span.End; var buffer = Span.Buffer; var recPos = mdTable.Span.Start; var rows = mdTable.Rows; var colInfo1 = mdTable.Columns[column1]; Debug.Assert(colInfo1.ColumnSize == ColumnSize.Blob); uint recSize = mdTable.RowSize; bool bigBlob = colInfo1.Size == 4; uint tokenBase = new MDToken(mdTable.Table, 0).Raw; for (uint rid = 1; rid <= rows; rid++, recPos += recSize) { uint offs1 = bigBlob ? buffer.ReadUInt32(recPos + colInfo1.Offset) : buffer.ReadUInt16(recPos + colInfo1.Offset); if (offs1 == 0) { continue; } List <uint> tokens; BlobDataInfoPosition info; if (dict.TryGetValue(offs1, out info)) { tokens = info.Tokens; } else { var pos = heapStart + offs1; if (pos < heapEnd) { dict[offs1] = info = new BlobDataInfoPosition(pos, kind1); tokens = info.Tokens; } else { tokens = null; } } tokens?.Add(tokenBase + rid); } }
BlobDataInfo[] CreateBlobDataInfos(TablesHeap?tables) { if (tables is null || Span.IsEmpty) { return(Array.Empty <BlobDataInfo>()); } var dict = new Dictionary <uint, BlobDataInfoPosition>(); foreach (var info in tableInitInfos) { if (info.Column2 >= 0) { Add(dict, tables.MDTables[(int)info.Table], info.Column1, info.Kind1, info.Column2, info.Kind2); } else { Add(dict, tables.MDTables[(int)info.Table], info.Column1, info.Kind1); } } AddNameIndexes(dict, tables, Table.Document, 0); AddImportScopeIndexes(dict, tables, Table.ImportScope, 1); dict[0] = new BlobDataInfoPosition(Span.Span.Start, BlobDataKind.None); var infos = dict.Values.ToArray(); var res = new BlobDataInfo[infos.Length]; Array.Sort(infos, (a, b) => a.Position.CompareTo(b.Position)); for (int i = 0; i < infos.Length; i++) { var info = infos[i]; var end = i + 1 < infos.Length ? infos[i + 1].Position : Span.Span.End; res[i] = new BlobDataInfo(HexSpan.FromBounds(info.Position, end), info.Tokens.ToArray(), info.Kind); } return(res); }
void AddImportScopeIndexes(Dictionary <uint, BlobDataInfoPosition> dict, TablesHeap tables, Table table, int column) { var mdTable = tables.MDTables[(int)table]; if (mdTable.Rows == 0) { return; } var heapStart = Span.Span.Start; var heapEnd = Span.Span.End; var buffer = Span.Buffer; var recPos = mdTable.Span.Start; var rows = mdTable.Rows; var colInfo = mdTable.Columns[column]; uint recSize = mdTable.RowSize; bool bigBlob = colInfo.Size == 4; for (uint rid = 1; rid <= rows; rid++, recPos += recSize) { uint offs = bigBlob ? buffer.ReadUInt32(recPos + colInfo.Offset) : buffer.ReadUInt16(recPos + colInfo.Offset); if (offs == 0) { continue; } var pos = heapStart + offs; int len = ReadCompressedUInt32(ref pos) ?? -1; if (len <= 0) { continue; } var end = HexPosition.Min(heapEnd, pos + len); while (pos < end) { var kind = ReadCompressedUInt32(ref pos); if (kind is null || pos > end) { break; } var flags = GetImportFlags(kind.Value); Debug.Assert(flags != 0); if (flags == 0) { break; } if ((flags & ImportFlags.Alias) != 0) { var valueTmp = ReadCompressedUInt32(ref pos); if (valueTmp is null || pos > end) { break; } var value = valueTmp.Value; if (value != 0 && !dict.ContainsKey((uint)value)) { var namePos = heapStart + value; if (namePos < heapEnd) { dict[(uint)value] = new BlobDataInfoPosition(namePos, BlobDataKind.Utf8Name); } } } if ((flags & ImportFlags.TargetAssembly) != 0) { var valueTmp = ReadCompressedUInt32(ref pos); if (valueTmp is null || pos > end) { break; } } if ((flags & ImportFlags.TargetNamespace) != 0) { var valueTmp = ReadCompressedUInt32(ref pos); if (valueTmp is null || pos > end) { break; } var value = valueTmp.Value; if (value != 0 && !dict.ContainsKey((uint)value)) { var namePos = heapStart + value; if (namePos < heapEnd) { dict[(uint)value] = new BlobDataInfoPosition(namePos, BlobDataKind.Utf8Name); } } } if ((flags & ImportFlags.TargetType) != 0) { var valueTmp = ReadCompressedUInt32(ref pos); if (valueTmp is null || pos > end) { break; } } } } }