Skip to content
GraphNodeIdIndex

GraphNodeIdIndex

Description

Extract the slot index encoded in a node id.

Parameters

Name Direction Description
id in Graph node id.

Success

Low 32-bit slot index encoded in id.

Failure

Function cannot fail.

Usage example (Cross-references)

Usage examples (Cross-references)
    /// TAGS: Graph, Node, Index, Handle
    ///
    #define GraphNodeIndex(node) GraphNodeIdIndex(GraphNodeGetId(node))
    
    ///
        const GenericGraphSlot *slot;
    
        index      = GraphNodeIdIndex(node_id);
        generation = GraphNodeIdGeneration(node_id);
    static GenericGraphSlot *graph_require_live_slot(GenericGraph *graph, GraphNodeId node_id) {
        graph_validate_node_id(graph, node_id);
        return graph_slot_ptr_raw(graph, GraphNodeIdIndex(node_id));
    }
    static const GenericGraphSlot *graph_require_live_slot_const(const GenericGraph *graph, GraphNodeId node_id) {
        graph_validate_node_id(graph, node_id);
        return graph_slot_ptr_const_raw(graph, GraphNodeIdIndex(node_id));
    }
            const GenericGraphSlot *slot;
    
            graph_validate_node_index_raw(graph, GraphNodeIdIndex(neighbor_id));
            slot = graph_slot_ptr_const_raw(graph, GraphNodeIdIndex(neighbor_id));
    
            graph_validate_node_index_raw(graph, GraphNodeIdIndex(neighbor_id));
            slot = graph_slot_ptr_const_raw(graph, GraphNodeIdIndex(neighbor_id));
    
            if (graph_slot_is_occupied(slot) && !graph_slot_is_marked(slot) &&
        ValidateGraph(graph);
    
        index      = GraphNodeIdIndex(node_id);
        generation = GraphNodeIdGeneration(node_id);
        GraphNodeId d = GraphAddNodeR(&graph, 40);
    
        result = result && (GraphNodeIdIndex(d) == GraphNodeIdIndex(b));
        result = result && (GraphNodeIdGeneration(d) == (GraphNodeIdGeneration(b) + 1));
        result = result && (GraphNodeData(&graph, GraphGetNode(&graph, d)) == 40);
        u64         counts[2] = {0};
    
        counts[GraphNodeIdIndex(a)] = 11;
        counts[GraphNodeIdIndex(b)] = 29;
    
        counts[GraphNodeIdIndex(a)] = 11;
        counts[GraphNodeIdIndex(b)] = 29;
    
        bool result = GraphMarkNodeForDeletion(GraphGetNode(&graph, b));
        GraphNodeId reused = GraphAddNodeR(&graph, 99);
    
        result = result && (GraphNodeIdIndex(reused) == GraphNodeIdIndex(b));
        result = result && (GraphNodeIdGeneration(reused) == (GraphNodeIdGeneration(b) + 1));
        result = result && (counts[GraphNodeIdIndex(reused)] == 29);
        result = result && (GraphNodeIdIndex(reused) == GraphNodeIdIndex(b));
        result = result && (GraphNodeIdGeneration(reused) == (GraphNodeIdGeneration(b) + 1));
        result = result && (counts[GraphNodeIdIndex(reused)] == 29);
    
        counts[GraphNodeIdIndex(reused)] = 0;
        result = result && (counts[GraphNodeIdIndex(reused)] == 29);
    
        counts[GraphNodeIdIndex(reused)] = 0;
        result                           = result && (counts[GraphNodeIdIndex(reused)] == 0);
        result                           = result && (counts[GraphNodeIdIndex(a)] == 11);
    
        counts[GraphNodeIdIndex(reused)] = 0;
        result                           = result && (counts[GraphNodeIdIndex(reused)] == 0);
        result                           = result && (counts[GraphNodeIdIndex(a)] == 11);
        result                           = result && (GraphNodeAt(&graph, reused) == 99);
        counts[GraphNodeIdIndex(reused)] = 0;
        result                           = result && (counts[GraphNodeIdIndex(reused)] == 0);
        result                           = result && (counts[GraphNodeIdIndex(a)] == 11);
        result                           = result && (GraphNodeAt(&graph, reused) == 99);
        // logical lengths to 0 (stale b remains in a.out's buffer at index 0) so
        // the graph looks edge-free while the pending removal still names a->b.
        GenericGraphSlot *slot_a     = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(a));
        GenericGraphSlot *slot_b     = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(b));
        slot_a->out_neighbors.length = 0;
        // the graph looks edge-free while the pending removal still names a->b.
        GenericGraphSlot *slot_a     = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(a));
        GenericGraphSlot *slot_b     = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(b));
        slot_a->out_neighbors.length = 0;
        slot_b->in_neighbors.length  = 0;
        }
    
        result = result && (VecPtrAt(&graph.slots, GraphNodeIdIndex(first_id))->generation == (first_generation + 1));
        result = result && (VecPtrAt(&graph.slots, GraphNodeIdIndex(second_id))->generation == (second_generation + 1));
        result = result && (VecPtrAt(&graph.slots, GraphNodeIdIndex(third_id))->generation == (third_generation + 1));
    
        result = result && (VecPtrAt(&graph.slots, GraphNodeIdIndex(first_id))->generation == (first_generation + 1));
        result = result && (VecPtrAt(&graph.slots, GraphNodeIdIndex(second_id))->generation == (second_generation + 1));
        result = result && (VecPtrAt(&graph.slots, GraphNodeIdIndex(third_id))->generation == (third_generation + 1));
        result = result && (VecPtrAt(&graph.slots, GraphNodeIdIndex(first_id))->generation == (first_generation + 1));
        result = result && (VecPtrAt(&graph.slots, GraphNodeIdIndex(second_id))->generation == (second_generation + 1));
        result = result && (VecPtrAt(&graph.slots, GraphNodeIdIndex(third_id))->generation == (third_generation + 1));
    
        GraphDeinit(&graph);
        stored_name = GraphNodeDataPtr(&graph, node);
    
        bool result = GraphNodeIdIndex(node_id) == 0 && StrBegin(&name) != NULL && GraphNodeCount(&graph) == 1 &&
                      ZstrCompare(StrBegin(stored_name), "alpha") == 0 && StrBegin(stored_name) != StrBegin(&name);
        stored_name = GraphNodeDataPtr(&graph, node);
    
        bool result = GraphNodeIdIndex(node_id) == 0 && GraphNodeCount(&graph) == 1 && StrBegin(stored_name) != NULL &&
                      ZstrCompare(StrBegin(stored_name), "alpha") == 0;
        GraphNodeId id1 = GraphAddNodeR(&graph, shared);
    
        bool result = GraphNodeIdIndex(id0) == 0 && GraphNodeIdGeneration(id0) == 1 && GraphNodeIdIndex(id1) == 1;
        result      = result && owned == 0 && shared == 7;
        result      = result && GraphNodeAt(&graph, id0) == 42;
        GraphNodeId reused    = GraphAddNodeR(&graph, 99);
    
        bool result = (GraphNodeIdIndex(reused) == GraphNodeIdIndex(b));
        result      = result && (GraphMutationEpoch(&graph) > old_epoch);
    
        bool result = (failed_id == 0);
        result      = result && (GraphNodeIdIndex(reused) == GraphNodeIdIndex(b));
        result      = result && (GraphNodeAt(&graph, reused) == 40);
        result      = result && (GraphNodeCount(&graph) == 2);
    static GenericGraphSlot *mutant_slot(void *graph_handle, GraphNodeId id) {
        GenericGraph *g = GENERIC_GRAPH(graph_handle);
        return (GenericGraphSlot *)VecPtrAt(&g->slots, GraphNodeIdIndex(id));
    }
        GraphNode   node    = GraphGetNode(&graph, node_id);
    
        bool result = GraphAllocator(&graph)->alignment == 32 && GraphNodeIdIndex(node_id) == 0 &&
                      GraphNodeIdGeneration(node_id) == 1;
        result = result && GraphNodeGetId(node) == node_id;
        GenericGraph *g = GENERIC_GRAPH(&graph);
        // free_indices now holds b's old slot index; redirect it to a (occupied).
        *VecPtrAt(&g->free_indices, 0) = GraphNodeIdIndex(a);
    
        MAGIC_MARK_DIRTY(g);
        // free_indices now holds two freed indices; redirect the last to a
        // (occupied) so only a loop that reaches the last entry catches it.
        *VecPtrAt(&g->free_indices, VecLen(&g->free_indices) - 1) = GraphNodeIdIndex(a);
    
        MAGIC_MARK_DIRTY(g);
        // neighbor id so its generation is 0 (an always-invalid generation),
        // without bumping the mutation epoch or re-flagging the validated bit.
        GenericGraphSlot *slot_a = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(a));
        GraphNodeId      *entry  = VecPtrAt(&slot_a->out_neighbors, 0);
        *entry                   = (GraphNodeId)GraphNodeIdIndex(b);
        GenericGraphSlot *slot_a = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(a));
        GraphNodeId      *entry  = VecPtrAt(&slot_a->out_neighbors, 0);
        *entry                   = (GraphNodeId)GraphNodeIdIndex(b);
    
        GraphNode out = {0};
        // Intentional bypass: rewrite `b`'s sole in-neighbor (a) so its generation
        // is 0, leaving the epoch and validated bit untouched.
        GenericGraphSlot *slot_b = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(b));
        GraphNodeId      *entry  = VecPtrAt(&slot_b->in_neighbors, 0);
        *entry                   = (GraphNodeId)GraphNodeIdIndex(a);
        GenericGraphSlot *slot_b = (GenericGraphSlot *)VecPtrAt(&GENERIC_GRAPH(&graph)->slots, GraphNodeIdIndex(b));
        GraphNodeId      *entry  = VecPtrAt(&slot_b->in_neighbors, 0);
        *entry                   = (GraphNodeId)GraphNodeIdIndex(a);
    
        GraphNode out = {0};
        result = result && GraphNodeData(&graph, node_b) == 25;
        result = result && GraphNodeGetId(node_b) == b;
        result = result && GraphNodeIndex(node_b) == GraphNodeIdIndex(b);
        result = result && GraphOutDegree(&graph, a) == 2;
        result = result && GraphInDegree(&graph, a) == 1;
        // generation. Real code: slot is unoccupied => not contained. Mutant:
        // occupancy term forced truthy + generation matches => wrongly contained.
        GraphNodeId free_slot_id = make_raw_node_id(GraphNodeIdIndex(a), GraphNodeIdGeneration(a) + 1);
        result                   = result && !GraphContainsNode(&graph, free_slot_id);
        // id with that exact generation: index in bounds, generation nonzero and
        // matching, slot unoccupied -> only the occupancy guard rejects it.
        GraphNodeId free_match = make_raw_node_id(GraphNodeIdIndex(a), GraphNodeIdGeneration(a) + 1);
    
        (void)GraphGetNode(&graph, free_match);
Last updated on