/// <summary> /// Gets a rid list (eg. field list) /// </summary> /// <param name="tableSource">Source table, eg. <c>TypeDef</c></param> /// <param name="tableSourceRid">Row ID in <paramref name="tableSource"/></param> /// <param name="colIndex">Column index in <paramref name="tableSource"/>, eg. 4 for <c>TypeDef.FieldList</c></param> /// <param name="tableDest">Destination table, eg. <c>Field</c></param> /// <returns>A new <see cref="RidList"/> instance</returns> RidList GetRidList(MDTable tableSource, uint tableSourceRid, int colIndex, MDTable tableDest) { var column = tableSource.TableInfo.Columns[colIndex]; if (!tablesStream.TryReadColumn24(tableSource, tableSourceRid, column, out uint startRid)) { return(RidList.Empty); } bool hasNext = tablesStream.TryReadColumn24(tableSource, tableSourceRid + 1, column, out uint nextListRid); uint lastRid = tableDest.Rows + 1; if (startRid == 0 || startRid >= lastRid) { return(RidList.Empty); } uint endRid = hasNext && nextListRid != 0 ? nextListRid : lastRid; if (endRid < startRid) { endRid = startRid; } if (endRid > lastRid) { endRid = lastRid; } return(RidList.Create(startRid, endRid - startRid)); }
/// <summary> /// Finds all rows owned by <paramref name="key"/> in table <paramref name="tableSource"/> /// whose index is <paramref name="keyColIndex"/> /// </summary> /// <param name="tableSource">Table to search</param> /// <param name="keyColIndex">Key column index</param> /// <param name="key">Key</param> /// <returns>A <see cref="RidList"/> instance</returns> protected RidList FindAllRows(MDTable tableSource, int keyColIndex, uint key) { uint startRid = BinarySearch(tableSource, keyColIndex, key); if (tableSource.IsInvalidRID(startRid)) { return(RidList.Empty); } uint endRid = startRid + 1; var column = tableSource.TableInfo.Columns[keyColIndex]; for (; startRid > 1; startRid--) { if (!tablesStream.TryReadColumn24(tableSource, startRid - 1, column, out uint key2)) { break; // Should never happen since startRid is valid } if (key != key2) { break; } } for (; endRid <= tableSource.Rows; endRid++) { if (!tablesStream.TryReadColumn24(tableSource, endRid, column, out uint key2)) { break; // Should never happen since endRid is valid } if (key != key2) { break; } } return(RidList.Create(startRid, endRid - startRid)); }
/// <inheritdoc/> public override RidList GetExportedTypeRidList() { if (!hasDeletedRows) { return(base.GetExportedTypeRidList()); } uint rows = tablesStream.ExportedTypeTable.Rows; var list = new List <uint>((int)rows); for (uint rid = 1; rid <= rows; rid++) { if (!tablesStream.TryReadExportedTypeRow(rid, out var row)) { continue; // Should never happen since rid is valid } // RTSpecialName is ignored by the CLR. It's only the name that indicates // whether it's been deleted. if (stringsStream.ReadNoNull(row.TypeName).StartsWith(DeletedName)) { continue; // ignore this deleted row } list.Add(rid); } return(RidList.Create(list)); }
/// <summary> /// Find all rids that contain <paramref name="key"/> /// </summary> /// <param name="key">The key</param> /// <returns>A new <see cref="RidList"/> instance</returns> public RidList FindAllRows(uint key) { int startIndex = BinarySearch(key); if (startIndex == 0) { return(RidList.Empty); } int endIndex = startIndex + 1; for (; startIndex > 1; startIndex--) { if (key != rows[startIndex - 1].key) { break; } } for (; endIndex < rows.Length; endIndex++) { if (key != rows[endIndex].key) { break; } } var list = new List <uint>(endIndex - startIndex); for (int i = startIndex; i < endIndex; i++) { list.Add(rows[i].rid); } return(RidList.Create(list)); }
public override RidList GetNestedClassRidList(uint typeDefRid) { if (typeDefRidToNestedClasses == null) { InitializeNestedClassesDictionary(); } if (typeDefRidToNestedClasses.TryGetValue(typeDefRid, out var ridList)) { return(RidList.Create(ridList)); } return(RidList.Empty); }
/// <inheritdoc/> public override RidList GetPropertyRidList(uint propertyMapRid) { var list = GetRidList(tablesStream.PropertyMapTable, propertyMapRid, 1, tablesStream.PropertyTable); if (list.Count == 0 || (!hasPropertyPtr && !hasDeletedRows)) { return(list); } var destTable = tablesStream.PropertyTable; var newList = new List <uint>(list.Count); for (int i = 0; i < list.Count; i++) { var rid = ToPropertyRid(list[i]); if (destTable.IsInvalidRID(rid)) { continue; } if (hasDeletedRows) { // It's a deleted row if RTSpecialName is set and name is "_Deleted" if (!tablesStream.TryReadPropertyRow(rid, out var row)) { continue; // Should never happen since rid is valid } if ((row.PropFlags & (uint)PropertyAttributes.RTSpecialName) != 0) { if (stringsStream.ReadNoNull(row.Name).StartsWith(DeletedName)) { continue; // ignore this deleted row } } } // It's a valid non-deleted rid so add it newList.Add(rid); } return(RidList.Create(newList)); }
/// <inheritdoc/> public override RidList GetParamRidList(uint methodRid) { var list = GetRidList(tablesStream.MethodTable, methodRid, 5, tablesStream.ParamTable); if (list.Count == 0 || !hasParamPtr) { return(list); } var destTable = tablesStream.ParamTable; var newList = new List <uint>(list.Count); for (int i = 0; i < list.Count; i++) { var rid = ToParamRid(list[i]); if (destTable.IsInvalidRID(rid)) { continue; } newList.Add(rid); } return(RidList.Create(newList)); }
void InitializeNestedClassesDictionary() { var table = tablesStream.NestedClassTable; var destTable = tablesStream.TypeDefTable; Dictionary <uint, bool> validTypeDefRids = null; var typeDefRidList = GetTypeDefRidList(); if ((uint)typeDefRidList.Count != destTable.Rows) { validTypeDefRids = new Dictionary <uint, bool>(typeDefRidList.Count); for (int i = 0; i < typeDefRidList.Count; i++) { validTypeDefRids[typeDefRidList[i]] = true; } } var nestedRidsDict = new Dictionary <uint, bool>((int)table.Rows); var nestedRids = new List <uint>((int)table.Rows); // Need it so we add the rids in correct order for (uint rid = 1; rid <= table.Rows; rid++) { if (validTypeDefRids != null && !validTypeDefRids.ContainsKey(rid)) { continue; } if (!tablesStream.TryReadNestedClassRow(rid, out var row)) { continue; // Should never happen since rid is valid } if (!destTable.IsValidRID(row.NestedClass) || !destTable.IsValidRID(row.EnclosingClass)) { continue; } if (nestedRidsDict.ContainsKey(row.NestedClass)) { continue; } nestedRidsDict[row.NestedClass] = true; nestedRids.Add(row.NestedClass); } var newTypeDefRidToNestedClasses = new Dictionary <uint, List <uint> >(); int count = nestedRids.Count; for (int i = 0; i < count; i++) { var nestedRid = nestedRids[i]; if (!tablesStream.TryReadNestedClassRow(GetNestedClassRid(nestedRid), out var row)) { continue; } if (!newTypeDefRidToNestedClasses.TryGetValue(row.EnclosingClass, out var ridList)) { newTypeDefRidToNestedClasses[row.EnclosingClass] = ridList = new List <uint>(); } ridList.Add(nestedRid); } var newNonNestedTypes = new List <uint>((int)(destTable.Rows - nestedRidsDict.Count)); for (uint rid = 1; rid <= destTable.Rows; rid++) { if (validTypeDefRids != null && !validTypeDefRids.ContainsKey(rid)) { continue; } if (nestedRidsDict.ContainsKey(rid)) { continue; } newNonNestedTypes.Add(rid); } Interlocked.CompareExchange(ref nonNestedTypes, new StrongBox <RidList>(RidList.Create(newNonNestedTypes)), null); // Initialize this one last since it's tested by the callers of this method Interlocked.CompareExchange(ref typeDefRidToNestedClasses, newTypeDefRidToNestedClasses, null); }
public override RidList GetExportedTypeRidList() => RidList.Create(1, tablesStream.ExportedTypeTable.Rows);
public override RidList GetTypeDefRidList() => RidList.Create(1, tablesStream.TypeDefTable.Rows);