File Coverage

Shared.xs
Criterion Covered Total %
statement 71 79 89.8
branch 76 140 54.2
condition n/a
subroutine n/a
pod n/a
total 147 219 67.1


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5             #include "ppport.h"
6             #include "graph.h"
7              
8             #define EXTRACT_GRAPH(sv) \
9             if (!sv_isobject(sv) || !sv_derived_from(sv, "Data::Graph::Shared")) \
10             croak("Expected a Data::Graph::Shared object"); \
11             GraphHandle *h = INT2PTR(GraphHandle*, SvIV(SvRV(sv))); \
12             if (!h) croak("Attempted to use a destroyed Data::Graph::Shared object")
13              
14             #define MAKE_OBJ(class, handle) \
15             SV *obj = newSViv(PTR2IV(handle)); \
16             SV *ref = newRV_noinc(obj); \
17             sv_bless(ref, gv_stashpv(class, GV_ADD)); \
18             RETVAL = ref
19              
20             MODULE = Data::Graph::Shared PACKAGE = Data::Graph::Shared
21              
22             PROTOTYPES: DISABLE
23              
24             SV *
25             new(class, path, max_nodes, max_edges)
26             const char *class
27             SV *path
28             UV max_nodes
29             UV max_edges
30             PREINIT:
31             char errbuf[GRAPH_ERR_BUFLEN];
32             CODE:
33 3 100         const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
34 3           GraphHandle *h = graph_create(p, (uint32_t)max_nodes, (uint32_t)max_edges, errbuf);
35 3 50         if (!h) croak("Data::Graph::Shared->new: %s", errbuf);
36 3           MAKE_OBJ(class, h);
37             OUTPUT:
38             RETVAL
39              
40             void
41             DESTROY(self)
42             SV *self
43             CODE:
44 3 50         if (!SvROK(self)) return;
45 3           GraphHandle *h = INT2PTR(GraphHandle*, SvIV(SvRV(self)));
46 3 50         if (!h) return;
47 3           sv_setiv(SvRV(self), 0);
48 3           graph_destroy(h);
49              
50             SV *
51             add_node(self, data)
52             SV *self
53             IV data
54             PREINIT:
55 5 50         EXTRACT_GRAPH(self);
    50          
    50          
56             CODE:
57 5           int32_t idx = graph_add_node(h, (int64_t)data);
58 5 50         RETVAL = (idx >= 0) ? newSViv((IV)idx) : &PL_sv_undef;
59             OUTPUT:
60             RETVAL
61              
62             bool
63             add_edge(self, src, dst, ...)
64             SV *self
65             UV src
66             UV dst
67             PREINIT:
68 6 50         EXTRACT_GRAPH(self);
    50          
    50          
69             CODE:
70 6 100         int64_t weight = (items > 3) ? (int64_t)SvIV(ST(3)) : 1;
71 6 100         RETVAL = graph_add_edge(h, (uint32_t)src, (uint32_t)dst, weight);
72             OUTPUT:
73             RETVAL
74              
75             bool
76             remove_node(self, node)
77             SV *self
78             UV node
79             PREINIT:
80 1 50         EXTRACT_GRAPH(self);
    50          
    50          
81             CODE:
82 1 50         RETVAL = graph_remove_node(h, (uint32_t)node);
83             OUTPUT:
84             RETVAL
85              
86             bool
87             has_node(self, node)
88             SV *self
89             UV node
90             PREINIT:
91 13 50         EXTRACT_GRAPH(self);
    50          
    50          
92             CODE:
93 13 100         RETVAL = graph_has_node(h, (uint32_t)node);
94             OUTPUT:
95             RETVAL
96              
97             IV
98             node_data(self, node)
99             SV *self
100             UV node
101             PREINIT:
102 3 50         EXTRACT_GRAPH(self);
    50          
    50          
103             CODE:
104 3           graph_mutex_lock(h->hdr);
105 3 50         if ((uint32_t)node >= h->hdr->max_nodes || !graph_bit_set(h->node_bitmap, (uint32_t)node)) {
    50          
106 0           graph_mutex_unlock(h->hdr);
107 0           croak("node %u does not exist", (unsigned)node);
108             }
109 3           RETVAL = (IV)h->node_data[(uint32_t)node];
110 3           graph_mutex_unlock(h->hdr);
111             OUTPUT:
112             RETVAL
113              
114             void
115             set_node_data(self, node, data)
116             SV *self
117             UV node
118             IV data
119             PREINIT:
120 1 50         EXTRACT_GRAPH(self);
    50          
    50          
121             CODE:
122 1           graph_mutex_lock(h->hdr);
123 1 50         if ((uint32_t)node >= h->hdr->max_nodes || !graph_bit_set(h->node_bitmap, (uint32_t)node)) {
    50          
124 0           graph_mutex_unlock(h->hdr);
125 0           croak("node %u does not exist", (unsigned)node);
126             }
127 1           h->node_data[(uint32_t)node] = (int64_t)data;
128 1           graph_mutex_unlock(h->hdr);
129              
130             void
131             neighbors(self, node)
132             SV *self
133             UV node
134             PREINIT:
135 3 50         EXTRACT_GRAPH(self);
    50          
    50          
136             PPCODE:
137 3           graph_mutex_lock(h->hdr);
138 3 50         if ((uint32_t)node >= h->hdr->max_nodes || !graph_bit_set(h->node_bitmap, (uint32_t)node)) {
    50          
139 0           graph_mutex_unlock(h->hdr);
140 0           croak("node %u does not exist", (unsigned)node);
141             }
142 3           uint32_t eidx = h->node_heads[(uint32_t)node];
143 3           AV *results = newAV();
144 10 100         while (eidx != GRAPH_NONE) {
145 7           AV *pair = newAV();
146 7           av_push(pair, newSVuv(h->edges[eidx].dst));
147 7           av_push(pair, newSViv((IV)h->edges[eidx].weight));
148 7           av_push(results, newRV_noinc((SV *)pair));
149 7           eidx = h->edges[eidx].next;
150             }
151 3           graph_mutex_unlock(h->hdr);
152 3 50         SSize_t count = av_top_index(results) + 1;
153 3 50         if (count > 0) {
154 3 50         EXTEND(SP, count);
    50          
155 10 100         for (SSize_t i = 0; i < count; i++)
156 7           PUSHs(sv_2mortal(SvREFCNT_inc(*av_fetch(results, i, 0))));
157             }
158 3           SvREFCNT_dec((SV *)results);
159              
160             UV
161             degree(self, node)
162             SV *self
163             UV node
164             PREINIT:
165 3 50         EXTRACT_GRAPH(self);
    50          
    50          
166             CODE:
167 3           graph_mutex_lock(h->hdr);
168 3 50         if ((uint32_t)node >= h->hdr->max_nodes || !graph_bit_set(h->node_bitmap, (uint32_t)node)) {
    50          
169 0           graph_mutex_unlock(h->hdr);
170 0           croak("node %u does not exist", (unsigned)node);
171             }
172 3           RETVAL = graph_neighbors(h, (uint32_t)node, NULL, NULL, 0);
173 3           graph_mutex_unlock(h->hdr);
174             OUTPUT:
175             RETVAL
176              
177             UV
178             node_count(self)
179             SV *self
180             PREINIT:
181 4 50         EXTRACT_GRAPH(self);
    50          
    50          
182             CODE:
183 4 50         RETVAL = __atomic_load_n(&h->hdr->node_count, __ATOMIC_ACQUIRE);
184             OUTPUT:
185             RETVAL
186              
187             UV
188             edge_count(self)
189             SV *self
190             PREINIT:
191 4 50         EXTRACT_GRAPH(self);
    50          
    50          
192             CODE:
193 4 50         RETVAL = __atomic_load_n(&h->hdr->edge_count, __ATOMIC_ACQUIRE);
194             OUTPUT:
195             RETVAL
196              
197             UV
198             max_nodes(self)
199             SV *self
200             PREINIT:
201 2 50         EXTRACT_GRAPH(self);
    50          
    50          
202             CODE:
203 2 50         RETVAL = h->hdr->max_nodes;
204             OUTPUT:
205             RETVAL
206              
207             UV
208             max_edges(self)
209             SV *self
210             PREINIT:
211 1 50         EXTRACT_GRAPH(self);
    50          
    50          
212             CODE:
213 1 50         RETVAL = h->hdr->max_edges;
214             OUTPUT:
215             RETVAL
216              
217             SV *
218             stats(self)
219             SV *self
220             PREINIT:
221 1 50         EXTRACT_GRAPH(self);
    50          
    50          
222             CODE:
223 1           HV *hv = newHV();
224 1           hv_store(hv, "node_count", 10, newSVuv(__atomic_load_n(&h->hdr->node_count, __ATOMIC_ACQUIRE)), 0);
225 1           hv_store(hv, "edge_count", 10, newSVuv(__atomic_load_n(&h->hdr->edge_count, __ATOMIC_ACQUIRE)), 0);
226 1           hv_store(hv, "max_nodes", 9, newSVuv(h->hdr->max_nodes), 0);
227 1           hv_store(hv, "max_edges", 9, newSVuv(h->hdr->max_edges), 0);
228 1           hv_store(hv, "ops", 3, newSVuv((UV)h->hdr->stat_ops), 0);
229 1           hv_store(hv, "mmap_size", 9, newSVuv((UV)h->mmap_size), 0);
230 1           RETVAL = newRV_noinc((SV *)hv);
231             OUTPUT:
232             RETVAL
233              
234             SV *
235             path(self)
236             SV *self
237             PREINIT:
238 1 50         EXTRACT_GRAPH(self);
    50          
    50          
239             CODE:
240 1 50         RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
241             OUTPUT:
242             RETVAL