File Coverage

Magic.xs
Criterion Covered Total %
statement 70 83 84.3
branch 25 40 62.5
condition n/a
subroutine n/a
pod n/a
total 95 123 77.2


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4              
5             #include "ppport.h"
6              
7             #include "xs_object_magic.h"
8              
9             STATIC MGVTBL null_mg_vtbl = {
10             NULL, /* get */
11             NULL, /* set */
12             NULL, /* len */
13             NULL, /* clear */
14             NULL, /* free */
15             #if MGf_COPY
16             NULL, /* copy */
17             #endif /* MGf_COPY */
18             #if MGf_DUP
19             NULL, /* dup */
20             #endif /* MGf_DUP */
21             #if MGf_LOCAL
22             NULL, /* local */
23             #endif /* MGf_LOCAL */
24             };
25              
26 5           void xs_object_magic_attach_struct (pTHX_ SV *sv, void *ptr) {
27 5           sv_magicext(sv, NULL, PERL_MAGIC_ext, &null_mg_vtbl, ptr, 0 );
28 5           }
29              
30 5           int xs_object_magic_detach_struct (pTHX_ SV *sv, void *ptr) {
31 5           MAGIC *mg, *prevmagic, *moremagic = NULL;
32 5           int removed = 0;
33              
34 5 50         if (SvTYPE(sv) < SVt_PVMG)
35 0           return 0;
36              
37             /* find our magic, remembering the magic before and the magic after */
38 10 100         for (prevmagic = NULL, mg = SvMAGIC(sv); mg; prevmagic = mg, mg = moremagic) {
39 5           moremagic = mg->mg_moremagic;
40 5 50         if (mg->mg_type == PERL_MAGIC_ext &&
    50          
41 5 100         mg->mg_virtual == &null_mg_vtbl &&
42 4 100         ( ptr == NULL || mg->mg_ptr == ptr )) {
43              
44 4 50         if(prevmagic != NULL) {
45 0           prevmagic->mg_moremagic = moremagic;
46             }
47             else {
48 4           SvMAGIC_set(sv, moremagic);
49             }
50              
51 4           mg->mg_moremagic = NULL;
52 4           Safefree(mg);
53              
54 4           mg = prevmagic;
55 4           removed++;
56             }
57              
58             }
59              
60 5           return removed;
61             }
62              
63 5           int xs_object_magic_detach_struct_rv (pTHX_ SV *sv, void *ptr){
64 5 50         if(sv && SvROK(sv)) {
    50          
65 5           sv = SvRV(sv);
66 5           return xs_object_magic_detach_struct(aTHX_ sv, ptr);
67             }
68 0           return 0;
69             }
70              
71 4           SV *xs_object_magic_create (pTHX_ void *ptr, HV *stash) {
72 4           HV *hv = newHV();
73 4           SV *obj = newRV_noinc((SV *)hv);
74              
75 4           sv_bless(obj, stash);
76              
77 4           xs_object_magic_attach_struct(aTHX_ (SV *)hv, ptr);
78              
79 4           return obj;
80             }
81              
82 19           MAGIC *xs_object_magic_get_mg (pTHX_ SV *sv) {
83             MAGIC *mg;
84              
85 19 50         if (SvTYPE(sv) >= SVt_PVMG) {
86 19 100         for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
87 12 50         if (
88 12           (mg->mg_type == PERL_MAGIC_ext)
89 12 50         &&
90 12           (mg->mg_virtual == &null_mg_vtbl)
91             ) {
92 12           return mg;
93             }
94             }
95             }
96              
97 7           return NULL;
98             }
99              
100 0           int xs_object_magic_has_struct (pTHX_ SV *sv) {
101 0           MAGIC *mg = xs_object_magic_get_mg(aTHX_ sv);
102 0           return mg ? 1 : 0;
103             }
104              
105 9           int xs_object_magic_has_struct_rv (pTHX_ SV *sv) {
106 9 50         if( sv && SvROK(sv) ){
    50          
107 9           sv = SvRV(sv);
108 9           MAGIC *mg = xs_object_magic_get_mg(aTHX_ sv);
109 9           return mg ? 1 : 0;
110             }
111 0           return 0;
112             }
113              
114 0           void *xs_object_magic_get_struct (pTHX_ SV *sv) {
115 0           MAGIC *mg = xs_object_magic_get_mg(aTHX_ sv);
116              
117 0 0         if ( mg )
118 0           return mg->mg_ptr;
119             else
120 0           return NULL;
121             }
122              
123 10           void *xs_object_magic_get_struct_rv_pretty (pTHX_ SV *sv, const char *name) {
124 10 50         if ( sv && SvROK(sv) ) {
    50          
125 10           MAGIC *mg = xs_object_magic_get_mg(aTHX_ SvRV(sv));
126              
127 10 100         if ( mg )
128 7           return mg->mg_ptr;
129             else
130 3           croak("%s does not have a struct associated with it", name);
131             } else {
132 0           croak("%s is not a reference", name);
133             }
134             }
135              
136 3           void *xs_object_magic_get_struct_rv (pTHX_ SV *sv) {
137 3           return xs_object_magic_get_struct_rv_pretty(aTHX_ sv, "argument");
138             }
139              
140             /* stuff for the test follows */
141              
142             typedef struct {
143             I32 i;
144             } _xs_magic_object_test_t;
145              
146             static I32 destroyed = 0;
147              
148 4           static _xs_magic_object_test_t *test_new () {
149             _xs_magic_object_test_t *t;
150 4           Newx(t, 1, _xs_magic_object_test_t);
151 4           t->i = 0;
152 4           return t;
153             }
154              
155 3           static int test_count (_xs_magic_object_test_t *t) {
156 3           return ++t->i;
157             }
158              
159 1           static void test_DESTROY (_xs_magic_object_test_t *t) {
160 1           Safefree(t);
161 1           destroyed++;
162 1           }
163              
164              
165             MODULE = XS::Object::Magic PACKAGE = XS::Object::Magic::Test PREFIX = test_
166             PROTOTYPES: DISABLE
167              
168             SV *
169             new(char *class)
170             CODE:
171 4           RETVAL = xs_object_magic_create(aTHX_ (void *)test_new(), gv_stashpv(class, 0));
172             OUTPUT: RETVAL
173              
174             I32
175             test_count (self)
176             _xs_magic_object_test_t *self;
177              
178             void
179             test_has (self)
180             SV *self;
181             PPCODE:
182 9 100         if (xs_object_magic_has_struct_rv(aTHX_ self))
183 5           XSRETURN_YES;
184              
185 4           XSRETURN_NO;
186              
187             void
188             test_attach_again (self)
189             SV *self
190             void *s = xs_object_magic_get_struct_rv(aTHX_ self);
191             CODE:
192 1           xs_object_magic_attach_struct(aTHX_ SvRV(self), s );
193              
194             int
195             test_detach_null (self)
196             SV *self;
197             CODE:
198 2           RETVAL = xs_object_magic_detach_struct_rv(aTHX_ self, NULL);
199             OUTPUT: RETVAL
200              
201             int
202             test_detach_struct (self)
203             SV *self;
204             void *s = xs_object_magic_get_struct_rv(aTHX_ self);
205             CODE:
206 2           RETVAL = xs_object_magic_detach_struct_rv(aTHX_ self, s);
207             OUTPUT: RETVAL
208              
209             int
210             test_detach_garbage (self)
211             SV *self;
212             void *s = (void *) 0x123456;
213             CODE:
214 1           RETVAL = xs_object_magic_detach_struct_rv(aTHX_ self, s);
215             OUTPUT: RETVAL
216              
217             void
218             test_DESTROY (self)
219             _xs_magic_object_test_t *self;
220              
221             I32
222             destroyed ()
223             CODE:
224 2           RETVAL = destroyed;
225             OUTPUT: RETVAL