private IEnumerable <BTree1Node <T> > EnumerateNodes(BTree1Node <T> node) { // internal node if (node.NodeLevel > 0) { foreach (var address in node.ChildAddresses) { _reader.Seek((long)address, SeekOrigin.Begin); var childNode = new BTree1Node <T>(_reader, _superblock, _decodeKey); // internal node if ((node.NodeLevel - 1) > 0) { var internalNodes = this.EnumerateNodes(childNode); foreach (var internalNode in internalNodes) { yield return(internalNode); } } // leaf node else { yield return(childNode); } } } // leaf node else { yield return(node); } }
public bool TryFindUserData <TUserData>([NotNullWhen(returnValue: true)] out TUserData userData, Func <T, T, int> compare3, FoundDelegate <T, TUserData> found) where TUserData : struct { userData = default; // H5B.c (H5B_find) /* * Perform a binary search to locate the child which contains * the thing for which we're searching. */ (var index, var cmp) = this.LocateRecord(compare3); /* Check if not found */ if (cmp != 0) { return(false); } /* * Follow the link to the subtree or to the data node. */ var childAddress = this.ChildAddresses[(int)index]; var key = this.Keys[index]; if (this.NodeLevel > 0) { _reader.Seek((long)childAddress, SeekOrigin.Begin); var subtree = new BTree1Node <T>(_reader, _superblock, _decodeKey); if (subtree.TryFindUserData(out userData, compare3, found)) { return(true); } } else { if (found(childAddress, key, out userData)) { return(true); } } return(false); }
private void ReadChunkedBTree1(Span <byte> buffer, byte rank, ulong chunkSize) { // btree1 Func <BTree1RawDataChunksKey> decodeKey = () => this.DecodeRawDataChunksKey(rank); var btree1 = new BTree1Node <BTree1RawDataChunksKey>(this.Context.Reader, this.Context.Superblock, decodeKey); var nodes = btree1.EnumerateNodes().ToList(); var childAddresses = nodes.SelectMany(key => key.ChildAddresses).ToArray(); var keys = nodes.SelectMany(key => key.Keys).ToArray(); // read data var offset = 0UL; var chunkCount = (ulong)childAddresses.Length; for (ulong i = 0; i < chunkCount; i++) { var rawChunkSize = keys[i].ChunkSize; this.SeekSliceAndReadChunk(offset, chunkSize, rawChunkSize, childAddresses[i], buffer); offset += rawChunkSize; } }
private bool TryGetReference(string name, H5LinkAccess linkAccess, out H5NamedReference namedReference) { namedReference = default; /* cached data */ if (_scratchPad != null) { var localHeap = _scratchPad.LocalHeap; this.Context.Reader.Seek((long)_scratchPad.BTree1Address, SeekOrigin.Begin); var tree = new BTree1Node <BTree1GroupKey>(this.Context.Reader, this.Context.Superblock, this.DecodeGroupKey); var b = tree.EnumerateNodes().ToList(); this.Context.Reader.Seek((long)_scratchPad.NameHeapAddress, SeekOrigin.Begin); var heap = new LocalHeap(this.Context.Reader, this.Context.Superblock); var c = heap.GetObjectName(0); var success = _scratchPad .GetBTree1(this.DecodeGroupKey) .TryFindUserData(out var userData, (leftKey, rightKey) => this.NodeCompare3(localHeap, name, leftKey, rightKey), (ulong address, out BTree1SymbolTableUserData userData) => this.NodeFound(localHeap, name, address, out userData)); if (success) { namedReference = this.GetObjectReferencesForSymbolTableEntry(localHeap, userData.SymbolTableEntry, linkAccess); return(true); } } else { var symbolTableHeaderMessages = this.Header.GetMessages <SymbolTableMessage>(); if (symbolTableHeaderMessages.Any()) { /* Original approach. * IV.A.2.r.: The Symbol Table Message * Required for "old style" groups; may not be repeated. */ if (symbolTableHeaderMessages.Count() != 1) { throw new Exception("There may be only a single symbol table header message."); } var smessage = symbolTableHeaderMessages.First(); var localHeap = smessage.LocalHeap; var success = smessage .GetBTree1(this.DecodeGroupKey) .TryFindUserData(out var userData, (leftKey, rightKey) => this.NodeCompare3(localHeap, name, leftKey, rightKey), (ulong address, out BTree1SymbolTableUserData userData) => this.NodeFound(localHeap, name, address, out userData)); if (success) { namedReference = this.GetObjectReferencesForSymbolTableEntry(localHeap, userData.SymbolTableEntry, linkAccess); return(true); } } else { var linkInfoMessages = this.Header.GetMessages <LinkInfoMessage>(); if (linkInfoMessages.Any()) { if (linkInfoMessages.Count() != 1) { throw new Exception("There may be only a single link info message."); } var lmessage = linkInfoMessages.First(); /* New (1.8) indexed format (in combination with Group Info Message) * IV.A.2.c. The Link Info Message * Optional; may not be repeated. */ if (!this.Context.Superblock.IsUndefinedAddress(lmessage.BTree2NameIndexAddress)) { if (this.TryGetLinkMessageFromLinkInfoMessage(lmessage, name, out var linkMessage)) { namedReference = this.GetObjectReference(linkMessage, linkAccess); return(true); } } /* New (1.8) compact format * IV.A.2.g. The Link Message * A group is storing its links compactly when the fractal heap address * in the Link Info Message is set to the "undefined address" value. */ else { var linkMessage = this.Header .GetMessages <LinkMessage>() .FirstOrDefault(message => message.LinkName == name); if (linkMessage != null) { namedReference = this.GetObjectReference(linkMessage, linkAccess); return(true); } } } else { throw new Exception("No link information found in object header."); } } } return(false); }