Skip to content

GraphNode

Description

Opaque node handle used by traversal helpers.

This carries the owning graph pointer plus the stable node id. Users typically obtain it from GraphGetNode, GraphForeachNode, or GraphNodeForeachNeighbor.

The handle is meant for active traversal and graph-aware node access. Long-lived external state should usually be stored separately, keyed by GraphNodeGetId(node) or by application data held in the node payload.

Usage example (Cross-references)

Usage examples (Cross-references)
    }
    
    static GraphNode graph_validate_node_handle(GraphNode node) {
        GenericGraph *graph;
    }
    
    GraphNode graph_get_node(GenericGraph *graph, GraphNodeId node_id) {
        GraphNode node;
    
    GraphNode graph_get_node(GenericGraph *graph, GraphNodeId node_id) {
        GraphNode node;
    
        ValidateGraph(graph);
    }
    
    void *graph_node_data_ptr_checked(GenericGraph *graph, GraphNode node) {
        GraphNode validated = graph_validate_node_handle(node);
    
    void *graph_node_data_ptr_checked(GenericGraph *graph, GraphNode node) {
        GraphNode validated = graph_validate_node_handle(node);
    
        if (GENERIC_GRAPH(validated._graph_) != graph) {
    }
    
    u64 GraphNodeVisit(GraphNode node) {
        GenericGraph     *graph;
        GenericGraphSlot *slot;
    }
    
    void GraphNodeUnvisit(GraphNode node) {
        GenericGraph     *graph;
        GenericGraphSlot *slot;
    }
    
    u64 GraphNodeVisitCount(GraphNode node) {
        GenericGraph           *graph;
        const GenericGraphSlot *slot;
    }
    
    bool GraphNodeVisited(GraphNode node) {
        return GraphNodeVisitCount(node) > 0;
    }
    }
    
    bool GraphMarkNodeForDeletion(GraphNode node) {
        GenericGraph     *graph;
        GenericGraphSlot *slot;
    }
    
    bool GraphNodeMarkedForDeletion(GraphNode node) {
        GenericGraph           *graph;
        const GenericGraphSlot *slot;
    }
    
    bool GraphUnmarkNodeForDeletion(GraphNode node) {
        GenericGraph     *graph;
        GenericGraphSlot *slot;
    }
    
    bool graph_node_iter_next(GenericGraphNodeIter *iter, GraphNode *out_node) {
        if (!iter || !out_node) {
            LOG_FATAL("invalid arguments");
    }
    
    GenericGraphNeighborIter graph_neighbor_iter_begin(GraphNode node) {
        GenericGraphNeighborIter iter;
        GenericGraph            *graph;
    }
    
    bool graph_neighbor_iter_next(GenericGraphNeighborIter *iter, GraphNode *out_node) {
        GraphNeighbors *neighbors;
    }
    
    GenericGraphPredecessorIter graph_predecessor_iter_begin(GraphNode node) {
        GenericGraphPredecessorIter iter;
        GenericGraph               *graph;
    }
    
    bool graph_predecessor_iter_next(GenericGraphPredecessorIter *iter, GraphNode *out_node) {
        GraphNeighbors *neighbors;
        GraphNodeId b = GraphAddNodeR(&graph, 20);
        GraphNodeId c = GraphAddNodeR(&graph, 30);
        GraphNode   node_b;
        GraphAddEdge(&graph, a, b);
        GraphAddEdge(&graph, a, c);
        IntGraph  graph_a = GraphInit(&alloc);
        IntGraph  graph_b = GraphInit(&alloc);
        GraphNode node    = GraphGetNode(&graph_a, GraphAddNodeR(&graph_a, 10));
    
        (void)GraphNodeData(&graph_b, node);
    
        GraphNodeId node_id = GraphAddNodeR(&graph, 11);
        GraphNode   node    = GraphGetNode(&graph, node_id);
    
        bool result = GraphAllocator(&graph)->alignment == 32 && GraphNodeIdIndex(node_id) == 0 &&
    
        GraphNodeId a    = GraphAddNodeR(&graph, 10);
        GraphNode   node = GraphGetNode(&graph, a);
    
        bool result = !GraphNodeVisited(node) && (GraphNodeVisitCount(node) == 0);
    
        GraphNodeId a    = GraphAddNodeR(&graph, 10);
        GraphNode   node = GraphGetNode(&graph, a);
    
        bool result = !GraphNodeMarkedForDeletion(node);
    
    static bool test_graph_stale_node_handle_after_commit_deadend(void) {
        WriteFmt("Testing stale GraphNode handle after commit (should abort)\n");
    
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        GraphNodeId a    = GraphAddNodeR(&graph, 10);
        GraphNode   node = GraphGetNode(&graph, a);
    
        (void)GraphMarkNodeForDeletion(node);
        Str         name  = StrInitFromZstr("alpha", &alloc);
        GraphNodeId node_id;
        GraphNode   node;
        Str        *stored_name;
        StrGraph    graph = GraphInitWithDeepCopy(NULL, str_deinit, &alloc);
        GraphNodeId node_id;
        GraphNode   node;
        Str        *stored_name;
    }
    
    static bool city_reachable_from(GraphNode node, GraphNodeId goal_id) {
        if (GraphNodeVisitCount(node) > 0) {
            return false;
        /// TAGS: Graph, Node, Visit, Mutation
        ///
        u64 GraphNodeVisit(GraphNode node);
    
        ///
        /// TAGS: Graph, Node, Visit, Reset
        ///
        void GraphNodeUnvisit(GraphNode node);
    
        ///
        /// TAGS: Graph, Node, Delete, Mark
        ///
        bool GraphMarkNodeForDeletion(GraphNode node);
    
        ///
        /// TAGS: Graph, Node, Delete, Query
        ///
        bool GraphNodeMarkedForDeletion(GraphNode node);
    
        ///
        /// TAGS: Graph, Node, Delete, Unmark
        ///
        bool GraphUnmarkNodeForDeletion(GraphNode node);
    
    #ifdef __cplusplus
        /// TAGS: Graph, Node, Visit, Count, Query
        ///
        u64 GraphNodeVisitCount(GraphNode node);
    
        ///
        /// TAGS: Graph, Node, Visit, Query
        ///
        bool GraphNodeVisited(GraphNode node);
    
    #ifdef __cplusplus
                for (GenericGraphNodeIter UNPL(iter) = graph_node_iter_begin(GENERIC_GRAPH(UNPL(pg))); UNPL(iter).graph;  \
                     UNPL(iter).graph = NULL)                                                                              \
                    for (GraphNode node = {0}; graph_node_iter_next(&UNPL(iter), &node);)
    
    ///
    ///
    #define GraphNodeForeachNeighbor(node, neighbor)                                                                       \
        for (GraphNode UNPL(src_node) = (node); UNPL(src_node)._graph_; UNPL(src_node)._graph_ = NULL)                    \
            for (GenericGraphNeighborIter UNPL(iter) = graph_neighbor_iter_begin(UNPL(src_node)); UNPL(iter).graph;       \
                 UNPL(iter).graph = NULL)                                                                                  \
            for (GenericGraphNeighborIter UNPL(iter) = graph_neighbor_iter_begin(UNPL(src_node)); UNPL(iter).graph;       \
                 UNPL(iter).graph = NULL)                                                                                  \
                for (GraphNode neighbor = {0}; graph_neighbor_iter_next(&UNPL(iter), &neighbor);)
    
    ///
    ///
    #define GraphNodeForeachPredecessor(node, predecessor)                                                                \
        for (GraphNode UNPL(dst_node) = (node); UNPL(dst_node)._graph_; UNPL(dst_node)._graph_ = NULL)                   \
            for (GenericGraphPredecessorIter UNPL(iter) = graph_predecessor_iter_begin(UNPL(dst_node));                  \
                 UNPL(iter).graph;                                                                                        \
                 UNPL(iter).graph;                                                                                        \
                 UNPL(iter).graph = NULL)                                                                                 \
                for (GraphNode predecessor = {0}; graph_predecessor_iter_next(&UNPL(iter), &predecessor);)
    
    #endif // MISRA_STD_CONTAINER_GRAPH_FOREACH_H
        void       *_graph_;
        GraphNodeId _id_;
    } GraphNode;
    
    ///
Last updated on