public Node CreateNodeAt(NodePath nodePath, AbsoluteNodePath currentPath)
        {
            if (LookupNodeNoSearch(nodePath, currentPath) != null)
            {
                throw new NodeAlreadyExistsException();
            }

            // Find deepest existing node on the path
            NodePath ancestorNodePath = nodePath;
            Node     ancestorNode;
            int      stepsUp = 0;

            do
            {
                ancestorNodePath = ancestorNodePath.RemoveSegment();
                stepsUp++;
                ancestorNode = LookupNodeNoSearch(ancestorNodePath, currentPath);
            } while (ancestorNode == null);

            // Create remaining names to get a node with the desired path
            Node newNode = null;

            string[] nameSegments = nodePath.NameSegments;
            for (int i = nameSegments.Length - stepsUp; i < nameSegments.Length; i++)
            {
                newNode      = new Node((string)nameSegments[i], ancestorNode);
                ancestorNode = newNode;
            }

            return(newNode);
        }
        /// <summary>
        /// Look up the node at a given absolute or relative node path.
        /// This may include "single segment name" paths which invoke the
        /// search strategy described in section 5.3 of the ACPI spec 3.0b.
        /// </summary>
        /// <param name="currentPath">Absolute path of the current path
        /// relative to which any relative node path will be determined.</param>
        /// <returns>The requested node, or null if the node is not found.</returns>
        public Node LookupNode(NodePath nodePath, AbsoluteNodePath currentPath)
        {
            if (nodePath.IsAbsolute)
            {
                return(LookupDescendantNode(rootNode, nodePath.NameSegments));
            }
            else
            {
                Node startNode = LookupNode(currentPath);
                Debug.Assert(startNode != null, "LookupNode: Current path did not resolve");

                if (nodePath.NumParentPrefixes > 0)
                {
                    for (int i = 0; i < nodePath.NumParentPrefixes; i++)
                    {
                        startNode = startNode.ParentNode;
                        if (startNode == null)
                        {
                            throw new ArgumentException("Relative path attempts to move above root");
                        }
                    }
                    return(LookupDescendantNode(startNode, nodePath.NameSegments));
                }
                else
                {
                    // The search rules apply - try successively larger scopes
                    while (startNode != null)
                    {
                        Node result = LookupDescendantNode(startNode, nodePath.NameSegments);
                        if (result != null)
                        {
                            return(result);
                        }
                        startNode = startNode.ParentNode;
                    }
                    return(null);
                }
            }
        }
        /// <summary>
        /// A version of LookupNode that does not ever apply the search rules.
        /// </summary>
        private Node LookupNodeNoSearch(NodePath nodePath, AbsoluteNodePath currentPath)
        {
            if (nodePath.IsAbsolute)
            {
                return(LookupDescendantNode(rootNode, nodePath.NameSegments));
            }
            else
            {
                Node startNode = LookupNode(currentPath);
                Debug.Assert(startNode != null, "LookupNode: Current path did not resolve");

                for (int i = 0; i < nodePath.NumParentPrefixes; i++)
                {
                    startNode = startNode.ParentNode;
                    if (startNode == null)
                    {
                        throw new ArgumentException("Relative path attempts to move above root");
                    }
                }
                return(LookupDescendantNode(startNode, nodePath.NameSegments));
            }
        }
 /// <summary>
 /// Look up the node at a given absolute node path.
 /// </summary>
 /// <returns>The requested node, or null if the node is not found.</returns>
 public Node LookupNode(AbsoluteNodePath nodePath)
 {
     return(LookupDescendantNode(rootNode, nodePath.NameSegments));
 }