mirror of
https://github.com/volatilityfoundation/volatility3.git
synced 2026-09-07 02:07:39 +02:00
Pull out the interfaces from the TreeGrid/TreeNode structures.
This commit is contained in:
@@ -29,4 +29,122 @@ class ColumnSortKey(metaclass = ABCMeta):
|
||||
"""The key function passed as a sort key to the TreeGrid's visit function"""
|
||||
|
||||
|
||||
class TreeNode(collections.Sequence, metaclass = ABCMeta):
|
||||
def __init__(self, path, treegrid, parent, values):
|
||||
"""Initializes the TreeNode"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def values(self):
|
||||
"""Returns the list of values from the particular node, based on column.index"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def path(self):
|
||||
"""Returns a path identifying string
|
||||
|
||||
This should be seen as opaque by external classes,
|
||||
Parsing of path locations based on this string are not guaranteed to remain stable.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def parent(self):
|
||||
"""Returns the parent node of this node or None"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def path_depth(self):
|
||||
"""Return the path depth of the current node"""
|
||||
|
||||
@abstractmethod
|
||||
def path_changed(self, path, added = False):
|
||||
"""Updates the path based on the addition or removal of a node higher up in the tree
|
||||
|
||||
This should only be called by the containing TreeGrid and expects to only be called for affected nodes.
|
||||
"""
|
||||
|
||||
|
||||
class TreeGrid(object, metaclass = ABCMeta):
|
||||
"""Class providing the interface for a TreeGrid (which contains TreeNodes)
|
||||
|
||||
The structure of a TreeGrid is designed to maintain the structure of the tree in a single object.
|
||||
For this reason each TreeNode does not hold its children, they are managed by the top level object.
|
||||
This leaves the Nodes as simple data carries and prevents them being used to manipulate the tree as a whole.
|
||||
This is a data structure, and is not expected to be modified much once created.
|
||||
|
||||
Carrying the children under the parent makes recursion easier, but then every node is its own little tree
|
||||
and must have all the supporting tree functions. It also allows for a node to be present in several different trees,
|
||||
and to create cycles.
|
||||
"""
|
||||
|
||||
simple_types = set([int, str, float, bytes])
|
||||
|
||||
def __init__(self, columns, generator):
|
||||
"""Constructs a TreeGrid object using a specific set of columns
|
||||
|
||||
The TreeGrid itself is a root element, that can have children but no values.
|
||||
The TreeGrid does *not* contain any information about formatting,
|
||||
these are up to the renderers and plugins.
|
||||
|
||||
:param columns: A list of column tuples made up of (name, type).
|
||||
:param generator: A generator that populates the tree/grid structure
|
||||
"""
|
||||
|
||||
|
||||
@abstractmethod
|
||||
def populate(self, func = None, initial_accumulator = None):
|
||||
"""Generator that returns the next available Node
|
||||
|
||||
This is equivalent to a one-time visit.
|
||||
"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def populated(self):
|
||||
"""Indicates that population has completed and the tree may now be manipulated separately"""
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def columns(self):
|
||||
"""Returns the available columns and their ordering and types"""
|
||||
return self._columns
|
||||
|
||||
@abstractmethod
|
||||
def children(self, node):
|
||||
"""Returns the subnodes of a particular node in order"""
|
||||
|
||||
@abstractmethod
|
||||
def values(self, node):
|
||||
"""Returns the values for a particular node
|
||||
|
||||
The values returned are mutable,
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def is_ancestor(self, node, descendant):
|
||||
"""Returns true if descendent is a child, grandchild, etc of node"""
|
||||
|
||||
@abstractmethod
|
||||
def max_depth(self):
|
||||
"""Returns the maximum depth of the tree"""
|
||||
|
||||
def path_depth(self, node):
|
||||
"""Returns the path depth of a particular node"""
|
||||
return node.path_depth
|
||||
|
||||
def path_is_valid(self, node):
|
||||
"""Returns True is a given path is valid for this treegrid"""
|
||||
return node in self.children(node.parent)
|
||||
|
||||
@abstractmethod
|
||||
def visit(self, node, function, initial_accumulator = None, sort_key = None):
|
||||
"""Visits all the nodes in a tree, calling function on each one.
|
||||
|
||||
function should have the signature function(node, accumulator) and return new_accumulator
|
||||
If accumulators are not needed, the function must still accept a second parameter.
|
||||
|
||||
The order of that the nodes are visited is always depth first, however, the order children are traversed can
|
||||
be set based on a sort_key function which should accept a node's values and return something that can be
|
||||
sorted to receive the desired order (similar to the sort/sorted key).
|
||||
"""
|
||||
|
||||
@@ -7,7 +7,7 @@ import collections
|
||||
from volatility.framework import interfaces
|
||||
|
||||
|
||||
class TreeNode(collections.Sequence):
|
||||
class TreeNode(interfaces.renderers.TreeNode):
|
||||
"""Class representing a particular node in a tree grid"""
|
||||
|
||||
def __init__(self, path, treegrid, parent, values):
|
||||
@@ -78,7 +78,7 @@ class TreeNode(collections.Sequence):
|
||||
self._path = TreeGrid.path_sep.join(components)
|
||||
|
||||
|
||||
class TreeGrid(object):
|
||||
class TreeGrid(interfaces.renderers.TreeGrid):
|
||||
"""Class providing the interface for a TreeGrid (which contains TreeNodes)
|
||||
|
||||
The structure of a TreeGrid is designed to maintain the structure of the tree in a single object.
|
||||
@@ -91,7 +91,6 @@ class TreeGrid(object):
|
||||
and to create cycles.
|
||||
"""
|
||||
|
||||
simple_types = set([int, str, float, bytes])
|
||||
path_sep = "|"
|
||||
|
||||
def __init__(self, columns, generator):
|
||||
@@ -211,18 +210,10 @@ class TreeGrid(object):
|
||||
"""Returns true if descendent is a child, grandchild, etc of node"""
|
||||
return descendant.path.startswith(node.path)
|
||||
|
||||
def path_depth(self, node):
|
||||
"""Returns the path depth of a particular node"""
|
||||
return node.path_depth
|
||||
|
||||
def max_depth(self):
|
||||
"""Returns the maximum depth of the tree"""
|
||||
return self.visit(None, lambda n, a: max(a, self.path_depth(n)), )
|
||||
|
||||
def path_is_valid(self, node):
|
||||
"""Returns True is a given path is valid for this treegrid"""
|
||||
return node in self.children(node.parent)
|
||||
|
||||
def visit(self, node, function, initial_accumulator = None, sort_key = None):
|
||||
"""Visits all the nodes in a tree, calling function on each one.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user