public BlockHeader(BinaryDeserializer Reader) { this.BytesUsed = Reader.ReadUInt16(); // 0: Counts number of bytes used in block, excluding the node header, and the last block link (14 bytes in total). this.SizeSubtree = Reader.ReadUInt32(); // 2: Order statistic tree, counting number of objects rooted at the current node. this.LastBlockIndex = Reader.ReadBlockLink(); // 6: Last block link. this.ParentBlockIndex = Reader.ReadBlockLink(); // 10: Parent block link. }
private async Task <ulong?> GoToObject(ulong ObjectIndex, uint BlockIndex) { if (ObjectIndex == 0) { if (await this.GoToFirst(BlockIndex)) { return(1); } else { return(null); } } object ObjectId; int Len; int Pos; uint BlockLink; bool IsEmpty; byte[] Block = await this.LoadBlock(BlockIndex); BinaryDeserializer Reader = new BinaryDeserializer(this.file.CollectionName, this.file.Encoding, Block, this.file.BlockLimit); BlockHeader Header = new BlockHeader(Reader); ulong Count = 0; ulong?SubtreeCount; if (ObjectIndex >= Header.SizeSubtree && Header.SizeSubtree < uint.MaxValue) { return(Header.SizeSubtree); } do { Pos = Reader.Position; BlockLink = Reader.ReadBlockLink(); // Block link. ObjectId = this.recordHandler.GetKey(Reader); // Object ID of object. IsEmpty = (ObjectId == null); if (IsEmpty) { break; } Len = this.recordHandler.GetPayloadSize(Reader); // Remaining length of object. Reader.Position += Len; if (BlockLink != 0) { SubtreeCount = await this.GoToObject(ObjectIndex - Count, BlockLink); if (SubtreeCount.HasValue) { Count += SubtreeCount.Value; if (Count > ObjectIndex) { return(Count); } } else { return(null); } } if (Count++ == ObjectIndex) { this.currentBlockIndex = BlockIndex; this.currentBlock = Block; this.currentReader = Reader; this.currentHeader = Header; await this.LoadObject(ObjectId, Pos + 4); return(Count); } }while (Reader.BytesLeft >= 4); if (Header.LastBlockIndex != 0) { SubtreeCount = await this.GoToObject(ObjectIndex - Count, Header.LastBlockIndex); if (SubtreeCount.HasValue) { Count += SubtreeCount.Value; if (Count == ObjectIndex) { return(Count); } } else { return(null); } } return(Count); }