``class FlowGraph`` implements a directed flow graph to be shown in the UI. This class allows plugins to create custom flow graphs and render them in the UI using the flow graph report API. An example of creating a flow graph and presenting it in the UI: >>> graph = FlowGraph() >>> node_a
| 377 | |
| 378 | |
| 379 | class FlowGraph: |
| 380 | """ |
| 381 | ``class FlowGraph`` implements a directed flow graph to be shown in the UI. This class allows plugins to |
| 382 | create custom flow graphs and render them in the UI using the flow graph report API. |
| 383 | |
| 384 | An example of creating a flow graph and presenting it in the UI: |
| 385 | |
| 386 | >>> graph = FlowGraph() |
| 387 | >>> node_a = FlowGraphNode(graph) |
| 388 | >>> node_a.lines = ["Node A"] |
| 389 | >>> node_b = FlowGraphNode(graph) |
| 390 | >>> node_b.lines = ["Node B"] |
| 391 | >>> node_c = FlowGraphNode(graph) |
| 392 | >>> node_c.lines = ["Node C"] |
| 393 | >>> graph.append(node_a) |
| 394 | 0 |
| 395 | >>> graph.append(node_b) |
| 396 | 1 |
| 397 | >>> graph.append(node_c) |
| 398 | 2 |
| 399 | >>> edge = EdgeStyle(EdgePenStyle.DashDotDotLine, 2, ThemeColor.AddressColor) |
| 400 | >>> node_a.add_outgoing_edge(BranchType.UserDefinedBranch, node_b, edge) |
| 401 | >>> node_a.add_outgoing_edge(BranchType.UnconditionalBranch, node_c) |
| 402 | >>> show_graph_report("Custom Graph", graph) |
| 403 | |
| 404 | .. note:: In the current implementation, only graphs that have a single start node where all other nodes are \ |
| 405 | reachable from outgoing edges can be rendered correctly. This describes the natural limitations of a control \ |
| 406 | flow graph, which is what the rendering logic was designed for. Graphs that have nodes that are only reachable \ |
| 407 | from incoming edges, or graphs that have disjoint subgraphs will not render correctly. This will be fixed \ |
| 408 | in a future version. |
| 409 | """ |
| 410 | _registered_instances = [] |
| 411 | |
| 412 | def __init__(self, handle: Optional[core.BNCustomFlowGraphHandle] = None): |
| 413 | _handle = handle |
| 414 | if _handle is None: |
| 415 | self._ext_cb = core.BNCustomFlowGraph() |
| 416 | self._ext_cb.context = 0 |
| 417 | self._ext_cb.prepareForLayout = self._ext_cb.prepareForLayout.__class__(self._prepare_for_layout) |
| 418 | self._ext_cb.populateNodes = self._ext_cb.populateNodes.__class__(self._populate_nodes) |
| 419 | self._ext_cb.completeLayout = self._ext_cb.completeLayout.__class__(self._complete_layout) |
| 420 | self._ext_cb.update = self._ext_cb.update.__class__(self._update) |
| 421 | self._ext_cb.externalRefTaken = self._ext_cb.externalRefTaken.__class__(self._external_ref_taken) |
| 422 | self._ext_cb.externalRefReleased = self._ext_cb.externalRefReleased.__class__(self._external_ref_released) |
| 423 | _handle = core.BNCreateCustomFlowGraph(self._ext_cb) |
| 424 | assert _handle is not None |
| 425 | self.handle = _handle |
| 426 | |
| 427 | def __del__(self): |
| 428 | if core is not None: |
| 429 | core.BNFreeFlowGraph(self.handle) |
| 430 | |
| 431 | def __repr__(self): |
| 432 | function = self.function |
| 433 | if function is None: |
| 434 | return "<flow graph>" |
| 435 | return "<graph of %s>" % repr(function) |
| 436 |
no outgoing calls
no test coverage detected