private IEnumerable <T> ReadBTHIndexHelper <T>(List <HNDataBlock> blocks, HID hid, int level) { if (level == 0) { int recCount = HidSize(blocks, hid) / Marshal.SizeOf(typeof(T)); if (hid.GetIndex(ndb.IsUnicode4K) != 0) { // The T record also forms the key of the BTH entry foreach (var row in MapArray <T>(blocks, hid, recCount)) { yield return(row); } } } else { int recCount = HidSize(blocks, hid) / Marshal.SizeOf(typeof(IntermediateBTH4)); var inters = MapArray <IntermediateBTH4>(blocks, hid, recCount); foreach (var inter in inters) { foreach (var row in ReadBTHIndexHelper <T>(blocks, inter.hidNextLevel, level - 1)) { yield return(row); } } } yield break; // No more entries }
// Walk a b-tree implemented on a heap, and return all the type T entries // This is used when reading the index of properties in a PC (property context), or rows in a TC (table context) private IEnumerable <T> ReadBTHIndex <T>(List <HNDataBlock> blocks, HID hid) { var b = MapType <BTHHEADER>(blocks, hid); foreach (var row in ReadBTHIndexHelper <T>(blocks, b.hidRoot, b.bIdxLevels)) { yield return(row); } yield break; // No more entries }
// Dereference the supplied HID in the supplied heap-on-node blocks, // and return the size of the resulting data buffer private int HidSize(List <HNDataBlock> blocks, HID hid) { var index = hid.GetIndex(ndb.IsUnicode4K); if (index == 0) // Check for empty { return(0); } var b = blocks[hid.GetBlockIndex(ndb.IsUnicode4K)]; return(b.rgibAlloc[index] - b.rgibAlloc[index - 1]); }
// Dereference the supplied HID in the supplied heap-on-node blocks, // and map the resulting data buffer onto an array of count occurrences of the specified type T private T[] MapArray <T>(List <HNDataBlock> blocks, HID hid, int count, int offset = 0) { var b = blocks[hid.GetBlockIndex(ndb.IsUnicode4K)]; return(Map.MapArray <T>(b.Buffer, b.rgibAlloc[hid.GetIndex(ndb.IsUnicode4K) - 1] + offset, count)); }