private DataBlockElement[] ReadExtensibleArrayDataBlock(ExtensibleArrayHeader header, uint chunkSizeLength, uint elementIndex) { var secondaryBlockIndex = header.ComputeSecondaryBlockIndex(elementIndex + header.IndexBlockElementsCount); var elementsCount = header.SecondaryBlockInfos[secondaryBlockIndex].ElementsCount; var dataBlock = new ExtensibleArrayDataBlock(this.Context.Reader, this.Context.Superblock, header, chunkSizeLength, elementsCount); if (dataBlock.PageCount > 0) { var pages = new List <DataBlockPage>((int)dataBlock.PageCount); for (int i = 0; i < (int)dataBlock.PageCount; i++) { var page = new DataBlockPage(this.Context.Reader, this.Context.Superblock, header.DataBlockPageElementsCount, dataBlock.ClientID, chunkSizeLength); pages.Add(page); } return(pages .SelectMany(page => page.Elements) .ToArray()); } else { return(dataBlock.Elements); } }
// for later: H5EA__lookup_elmt private void ReadExtensibleArray(Span <byte> buffer, ulong chunkSize) { var chunkSizeLength = this.ComputeChunkSizeLength(chunkSize); var header = new ExtensibleArrayHeader(this.Context.Reader, this.Context.Superblock, chunkSizeLength); var indexBlock = header.IndexBlock; var elementIndex = 0U; var elements = new List <DataBlockElement>() .AsEnumerable(); // elements elements = elements.Concat(indexBlock.Elements); // data blocks ReadDataBlocks(indexBlock.DataBlockAddresses); // secondary blocks #warning Is there any precalculated way to avoid checking all addresses? var addresses = indexBlock .SecondaryBlockAddresses .Where(address => !this.Context.Superblock.IsUndefinedAddress(address)); foreach (var secondaryBlockAddress in addresses) { this.Context.Reader.Seek((long)secondaryBlockAddress, SeekOrigin.Begin); var secondaryBlockIndex = header.ComputeSecondaryBlockIndex(elementIndex + header.IndexBlockElementsCount); var secondaryBlock = new ExtensibleArraySecondaryBlock(this.Context.Reader, this.Context.Superblock, header, secondaryBlockIndex); ReadDataBlocks(secondaryBlock.DataBlockAddresses); } var offset = 0UL; foreach (var element in elements) { // if page/element is initialized (see also datablock.PageBitmap) #warning Is there any precalculated way to avoid checking all addresses? if (element.Address > 0 && !this.Context.Superblock.IsUndefinedAddress(element.Address)) { this.SeekSliceAndReadChunk(offset, chunkSize, element.ChunkSize, element.Address, buffer); } offset += chunkSize; } void ReadDataBlocks(ulong[] dataBlockAddresses) { #warning Is there any precalculated way to avoid checking all addresses? dataBlockAddresses = dataBlockAddresses .Where(address => !this.Context.Superblock.IsUndefinedAddress(address)) .ToArray(); foreach (var dataBlockAddress in dataBlockAddresses) { this.Context.Reader.Seek((long)dataBlockAddress, SeekOrigin.Begin); var newElements = this.ReadExtensibleArrayDataBlock(header, chunkSizeLength, elementIndex); elements = elements.Concat(newElements); elementIndex += (uint)newElements.Length; } } }