internal H5NamedReference InternalGet(string path, H5LinkAccess linkAccess) { if (path == "/") { return(this.File.Reference); } var isRooted = path.StartsWith('/'); var segments = isRooted ? path.Split('/').Skip(1).ToArray() : path.Split('/'); var current = isRooted ? this.File.Reference : this.Reference; for (int i = 0; i < segments.Length; i++) { var group = current.Dereference() as H5Group; if (group == null) { throw new Exception($"Path segment '{segments[i - 1]}' is not a group."); } if (!group.TryGetReference(segments[i], linkAccess, out var reference)) { throw new Exception($"Could not find part of the path '{path}'."); } current = reference; } return(current); }
private bool InternalExists(string path, H5LinkAccess linkAccess) { if (path == "/") { return(true); } var isRooted = path.StartsWith('/'); var segments = isRooted ? path.Split('/').Skip(1).ToArray() : path.Split('/'); var current = isRooted ? this.File.Reference : this.Reference; for (int i = 0; i < segments.Length; i++) { var group = current.Dereference() as H5Group; if (group == null) { return(false); } if (!group.TryGetReference(segments[i], linkAccess, out var reference)) { return(false); } current = reference; } return(true); }
private H5NamedReference GetObjectReference(LinkMessage linkMessage, H5LinkAccess linkAccess) { return(linkMessage.LinkInfo switch { HardLinkInfo hard => new H5NamedReference(linkMessage.LinkName, hard.HeaderAddress, this.File), SoftLinkInfo soft => new H5SymbolicLink(linkMessage, this).GetTarget(linkAccess), ExternalLinkInfo external => new H5SymbolicLink(linkMessage, this).GetTarget(linkAccess), _ => throw new Exception($"Unknown link type '{linkMessage.LinkType}'.") });
public H5Object Get(H5ObjectReference reference, H5LinkAccess linkAccess = default) { if (this.Reference.Value == reference.Value) { return(this); } return(this .InternalGet(reference, linkAccess) .Dereference()); }
public H5Group Group(string path, H5LinkAccess linkAccess = default) { var link = this.Get(path, linkAccess); var group = link as H5Group; if (group == null) { throw new Exception($"The requested link exists but cannot be casted to {nameof(H5Group)} because it is of type {link.GetType().Name}."); } return(group); }
public H5CommitedDatatype CommitedDatatype(string path, H5LinkAccess linkAccess = default) { var link = this.Get(path, linkAccess); var castedLink = link as H5CommitedDatatype; if (castedLink == null) { throw new Exception($"The requested link exists but cannot be casted to {nameof(H5CommitedDatatype)} because it is of type {link.GetType().Name}."); } return(castedLink); }
internal H5NamedReference InternalGet(H5ObjectReference reference, H5LinkAccess linkAccess) { var alreadyVisted = new HashSet <ulong>(); if (this.TryGetReference(reference, alreadyVisted, linkAccess, recursionLevel: 0, out var namedReference)) { return(namedReference); } else { throw new Exception($"Could not find object for reference with value '{reference.Value:X}'."); } }
public H5NamedReference GetTarget(H5LinkAccess linkAccess) { // this file if (string.IsNullOrWhiteSpace(this.ObjectPath)) { try { var reference = this.Parent.InternalGet(this.Value, linkAccess); reference.Name = this.Name; return(reference); } catch (Exception ex) { return(new H5NamedReference(this.Name, Superblock.UndefinedAddress) { Exception = ex }); } } // external file else { try { var absoluteFilePath = H5Utils.ConstructExternalFilePath(this.Parent.File, this.Value, linkAccess); var objectPath = this.ObjectPath; var externalFile = H5Cache.GetH5File(this.Parent.Context.Superblock, absoluteFilePath); return(externalFile.InternalGet(objectPath, linkAccess)); } catch (Exception ex) { return(new H5NamedReference(this.Name, Superblock.UndefinedAddress) { Exception = ex }); } } }
public H5Object Get(string path, H5LinkAccess linkAccess = default) { return(this .InternalGet(path, linkAccess) .Dereference()); }
public bool Exists(string path, H5LinkAccess linkAccess = default) { return(this.InternalExists(path, linkAccess)); }
private IEnumerable <H5NamedReference> EnumerateReferences(H5LinkAccess linkAccess) { // https://support.hdfgroup.org/HDF5/doc/RM/RM_H5G.html // section "Group implementations in HDF5" /* cached data */ if (_scratchPad != null) { var localHeap = _scratchPad.LocalHeap; var references = this .EnumerateSymbolTableNodes(_scratchPad.GetBTree1(this.DecodeGroupKey)) .SelectMany(node => node.GroupEntries .Select(entry => this.GetObjectReferencesForSymbolTableEntry(localHeap, entry, linkAccess))); foreach (var reference in references) { yield return(reference); } } 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 references = this .EnumerateSymbolTableNodes(smessage.GetBTree1(this.DecodeGroupKey)) .SelectMany(node => node.GroupEntries .Select(entry => this.GetObjectReferencesForSymbolTableEntry(localHeap, entry, linkAccess))); foreach (var reference in references) { yield return(reference); } } else { var linkInfoMessages = this.Header.GetMessages <LinkInfoMessage>(); if (linkInfoMessages.Any()) { IEnumerable <LinkMessage> linkMessages; 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)) { linkMessages = this.EnumerateLinkMessagesFromLinkInfoMessage(lmessage); } /* 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 { linkMessages = this.Header.GetMessages <LinkMessage>(); } // build links foreach (var linkMessage in linkMessages) { yield return(this.GetObjectReference(linkMessage, linkAccess)); } } else { throw new Exception("No link information found in object header."); } } } }
internal bool TryGetReference(H5ObjectReference reference, HashSet <ulong> alreadyVisited, H5LinkAccess linkAccess, int recursionLevel, out H5NamedReference namedReference) { // similar to H5Gint.c (H5G_visit) if (recursionLevel >= 100) { throw new Exception("Too much recursion."); } bool skip = false; namedReference = default; /* If its ref count is > 1, we add it to the list of visited objects * (because it could come up again during traversal) */ if (this.ReferenceCount > 1) { if (alreadyVisited.Contains(this.Reference.Value)) { skip = true; } else { alreadyVisited.Add(this.Reference.Value); } } if (!skip) { var references = this .EnumerateReferences(linkAccess) .ToList(); namedReference = references .FirstOrDefault(current => current.Value == reference.Value); if (namedReference.Name != null /* if struct value is not equal to default */) { return(true); } else { // search childs for reference foreach (var childReference in references) { var group = childReference.Dereference() as H5Group; if (group != null) { if (group.TryGetReference(reference, alreadyVisited, linkAccess, recursionLevel + 1, out namedReference)) { return(true); } } } } } return(false); }
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); }
public IEnumerable <H5Object> GetChildren(H5LinkAccess linkAccess = default) { return(this .EnumerateReferences(linkAccess) .Select(reference => reference.Dereference())); }