예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
 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}'.")
     });
예제 #4
0
        public H5Object Get(H5ObjectReference reference, H5LinkAccess linkAccess = default)
        {
            if (this.Reference.Value == reference.Value)
            {
                return(this);
            }

            return(this
                   .InternalGet(reference, linkAccess)
                   .Dereference());
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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
                    });
                }
            }
        }
예제 #9
0
 public H5Object Get(string path, H5LinkAccess linkAccess = default)
 {
     return(this
            .InternalGet(path, linkAccess)
            .Dereference());
 }
예제 #10
0
 public bool Exists(string path, H5LinkAccess linkAccess = default)
 {
     return(this.InternalExists(path, linkAccess));
 }
예제 #11
0
        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.");
                    }
                }
            }
        }
예제 #12
0
        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);
        }
예제 #13
0
        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);
        }
예제 #14
0
 public IEnumerable <H5Object> GetChildren(H5LinkAccess linkAccess = default)
 {
     return(this
            .EnumerateReferences(linkAccess)
            .Select(reference => reference.Dereference()));
 }