File Coverage

Shared.xs
Criterion Covered Total %
statement 70 80 87.5
branch 83 164 50.6
condition n/a
subroutine n/a
pod n/a
total 153 244 62.7


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 "bitset.h"
7              
8             #define EXTRACT_BS(sv) \
9             if (!sv_isobject(sv) || !sv_derived_from(sv, "Data::BitSet::Shared")) \
10             croak("Expected a Data::BitSet::Shared object"); \
11             BsHandle *h = INT2PTR(BsHandle*, SvIV(SvRV(sv))); \
12             if (!h) croak("Attempted to use a destroyed Data::BitSet::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             #define CHECK_BIT(h, bit) \
21             if ((UV)(bit) >= (h)->hdr->capacity) \
22             croak("bit %" UVuf " out of range (capacity %" UVuf ")", (UV)(bit), (UV)(h)->hdr->capacity)
23              
24             MODULE = Data::BitSet::Shared PACKAGE = Data::BitSet::Shared
25              
26             PROTOTYPES: DISABLE
27              
28             SV *
29             new(class, path, capacity)
30             const char *class
31             SV *path
32             UV capacity
33             PREINIT:
34             char errbuf[BS_ERR_BUFLEN];
35             CODE:
36 5 100         const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
37 5           BsHandle *h = bs_create(p, capacity, errbuf);
38 5 50         if (!h) croak("Data::BitSet::Shared->new: %s", errbuf);
39 5           MAKE_OBJ(class, h);
40             OUTPUT:
41             RETVAL
42              
43             SV *
44             new_memfd(class, name, capacity)
45             const char *class
46             const char *name
47             UV capacity
48             PREINIT:
49             char errbuf[BS_ERR_BUFLEN];
50             CODE:
51 1           BsHandle *h = bs_create_memfd(name, capacity, errbuf);
52 1 50         if (!h) croak("Data::BitSet::Shared->new_memfd: %s", errbuf);
53 1           MAKE_OBJ(class, h);
54             OUTPUT:
55             RETVAL
56              
57             SV *
58             new_from_fd(class, fd)
59             const char *class
60             int fd
61             PREINIT:
62             char errbuf[BS_ERR_BUFLEN];
63             CODE:
64 1           BsHandle *h = bs_open_fd(fd, errbuf);
65 1 50         if (!h) croak("Data::BitSet::Shared->new_from_fd: %s", errbuf);
66 1           MAKE_OBJ(class, h);
67             OUTPUT:
68             RETVAL
69              
70             void
71             DESTROY(self)
72             SV *self
73             CODE:
74 7 50         if (!SvROK(self)) return;
75 7           BsHandle *h = INT2PTR(BsHandle*, SvIV(SvRV(self)));
76 7 50         if (!h) return;
77 7           sv_setiv(SvRV(self), 0);
78 7           bs_destroy(h);
79              
80             IV
81             test(self, bit)
82             SV *self
83             UV bit
84             PREINIT:
85 264 50         EXTRACT_BS(self);
    50          
    50          
86             CODE:
87 264 100         CHECK_BIT(h, bit);
88 263 100         RETVAL = bs_test(h, bit);
89             OUTPUT:
90             RETVAL
91              
92             IV
93             set(self, bit)
94             SV *self
95             UV bit
96             PREINIT:
97 19 50         EXTRACT_BS(self);
    50          
    50          
98             CODE:
99 19 100         CHECK_BIT(h, bit);
100 18 50         RETVAL = bs_set(h, bit);
101             OUTPUT:
102             RETVAL
103              
104             IV
105             clear(self, bit)
106             SV *self
107             UV bit
108             PREINIT:
109 2 50         EXTRACT_BS(self);
    50          
    50          
110             CODE:
111 2 50         CHECK_BIT(h, bit);
112 2 50         RETVAL = bs_clear(h, bit);
113             OUTPUT:
114             RETVAL
115              
116             IV
117             toggle(self, bit)
118             SV *self
119             UV bit
120             PREINIT:
121 2 50         EXTRACT_BS(self);
    50          
    50          
122             CODE:
123 2 50         CHECK_BIT(h, bit);
124 2 50         RETVAL = bs_toggle(h, bit);
125             OUTPUT:
126             RETVAL
127              
128             UV
129             count(self)
130             SV *self
131             PREINIT:
132 10 50         EXTRACT_BS(self);
    50          
    50          
133             CODE:
134 10           RETVAL = (UV)bs_count(h);
135             OUTPUT:
136             RETVAL
137              
138             UV
139             capacity(self)
140             SV *self
141             PREINIT:
142 2 50         EXTRACT_BS(self);
    50          
    50          
143             CODE:
144 2 50         RETVAL = (UV)h->hdr->capacity;
145             OUTPUT:
146             RETVAL
147              
148             IV
149             any(self)
150             SV *self
151             PREINIT:
152 1 50         EXTRACT_BS(self);
    50          
    50          
153             CODE:
154 1 50         RETVAL = bs_any(h);
155             OUTPUT:
156             RETVAL
157              
158             IV
159             none(self)
160             SV *self
161             PREINIT:
162 1 50         EXTRACT_BS(self);
    50          
    50          
163             CODE:
164 1 50         RETVAL = bs_none(h);
165             OUTPUT:
166             RETVAL
167              
168             void
169             fill(self)
170             SV *self
171             PREINIT:
172 3 50         EXTRACT_BS(self);
    50          
    50          
173             CODE:
174 3           bs_fill(h);
175              
176             void
177             zero(self)
178             SV *self
179             PREINIT:
180 4 50         EXTRACT_BS(self);
    50          
    50          
181             CODE:
182 4           bs_zero(h);
183              
184             SV *
185             first_set(self)
186             SV *self
187             PREINIT:
188 3 50         EXTRACT_BS(self);
    50          
    50          
189             CODE:
190 3           int64_t r = bs_first_set(h);
191 3 100         RETVAL = (r >= 0) ? newSViv((IV)r) : &PL_sv_undef;
192             OUTPUT:
193             RETVAL
194              
195             SV *
196             first_clear(self)
197             SV *self
198             PREINIT:
199 3 50         EXTRACT_BS(self);
    50          
    50          
200             CODE:
201 3           int64_t r = bs_first_clear(h);
202 3 100         RETVAL = (r >= 0) ? newSViv((IV)r) : &PL_sv_undef;
203             OUTPUT:
204             RETVAL
205              
206             SV *
207             path(self)
208             SV *self
209             PREINIT:
210 1 50         EXTRACT_BS(self);
    50          
    50          
211             CODE:
212 1 50         RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
213             OUTPUT:
214             RETVAL
215              
216             IV
217             memfd(self)
218             SV *self
219             PREINIT:
220 1 50         EXTRACT_BS(self);
    50          
    50          
221             CODE:
222 1 50         RETVAL = h->backing_fd;
223             OUTPUT:
224             RETVAL
225              
226             void
227             sync(self)
228             SV *self
229             PREINIT:
230 0 0         EXTRACT_BS(self);
    0          
    0          
231             CODE:
232 0           bs_msync(h);
233              
234             void
235             unlink(self_or_class, ...)
236             SV *self_or_class
237             CODE:
238             const char *p;
239 0 0         if (sv_isobject(self_or_class)) {
240 0           BsHandle *h = INT2PTR(BsHandle*, SvIV(SvRV(self_or_class)));
241 0 0         if (!h) croak("destroyed object");
242 0           p = h->path;
243             } else {
244 0 0         if (items < 2) croak("Usage: ...->unlink($path)");
245 0           p = SvPV_nolen(ST(1));
246             }
247 0 0         if (!p) croak("cannot unlink anonymous or memfd object");
248 0 0         if (unlink(p) != 0) croak("unlink(%s): %s", p, strerror(errno));
249              
250             SV *
251             stats(self)
252             SV *self
253             PREINIT:
254 1 50         EXTRACT_BS(self);
    50          
    50          
255             CODE:
256 1           HV *hv = newHV();
257 1           hv_store(hv, "capacity", 8, newSVuv((UV)h->hdr->capacity), 0);
258 1           hv_store(hv, "count", 5, newSVuv((UV)bs_count(h)), 0);
259 1           hv_store(hv, "sets", 4, newSVuv((UV)h->hdr->stat_sets), 0);
260 1           hv_store(hv, "clears", 6, newSVuv((UV)h->hdr->stat_clears), 0);
261 1           hv_store(hv, "toggles", 7, newSVuv((UV)h->hdr->stat_toggles), 0);
262 1           hv_store(hv, "mmap_size", 9, newSVuv((UV)h->mmap_size), 0);
263 1           RETVAL = newRV_noinc((SV *)hv);
264             OUTPUT:
265             RETVAL
266              
267             SV *
268             to_string(self, ...)
269             SV *self
270             PREINIT:
271 2 50         EXTRACT_BS(self);
    50          
    50          
272             CODE:
273 2           uint64_t cap = h->hdr->capacity;
274 2           uint32_t nw = h->hdr->num_words;
275             char *buf;
276 2           Newx(buf, cap + 1, char);
277 2           uint64_t idx = 0;
278 10 100         for (uint32_t w = 0; w < nw && idx < cap; w++) {
    50          
279 8           uint64_t word = __atomic_load_n(&h->data[w], __ATOMIC_RELAXED);
280 520 100         for (int b = 0; b < 64 && idx < cap; b++, idx++)
    50          
281 512 100         buf[idx] = (word >> b) & 1 ? '1' : '0';
282             }
283 2           buf[cap] = '\0';
284 2           RETVAL = newSVpvn(buf, cap);
285 2           Safefree(buf);
286             OUTPUT:
287             RETVAL