File Coverage

xs/obj.xs
Criterion Covered Total %
statement 94 104 90.3
branch 55 94 58.5
condition n/a
subroutine n/a
pod n/a
total 149 198 75.2


line stmt bran cond sub pod time code
1             MODULE = PDF::Make PACKAGE = PDF::Make::Obj
2             PROTOTYPES: ENABLE
3              
4             void
5             DESTROY(self)
6             pdfmake_obj_xs_t *self
7             CODE:
8 453 50         if (self->arena_sv) {
9 453           SvREFCNT_dec(self->arena_sv);
10             }
11 453           Safefree(self);
12              
13             IV
14             kind(self)
15             pdfmake_obj_xs_t *self
16             CODE:
17 10 50         RETVAL = self->obj->kind;
18             OUTPUT:
19             RETVAL
20              
21             int
22             is_null(self)
23             pdfmake_obj_xs_t *self
24             CODE:
25 2           RETVAL = pdfmake_is_null(self->obj);
26             OUTPUT:
27             RETVAL
28              
29             int
30             is_bool(self)
31             pdfmake_obj_xs_t *self
32             CODE:
33 2           RETVAL = pdfmake_is_bool(self->obj);
34             OUTPUT:
35             RETVAL
36              
37             int
38             is_int(self)
39             pdfmake_obj_xs_t *self
40             CODE:
41 2           RETVAL = pdfmake_is_int(self->obj);
42             OUTPUT:
43             RETVAL
44              
45             int
46             is_real(self)
47             pdfmake_obj_xs_t *self
48             CODE:
49 2           RETVAL = pdfmake_is_real(self->obj);
50             OUTPUT:
51             RETVAL
52              
53             int
54             is_numeric(self)
55             pdfmake_obj_xs_t *self
56             CODE:
57 3           RETVAL = pdfmake_is_numeric(self->obj);
58             OUTPUT:
59             RETVAL
60              
61             int
62             is_name(self)
63             pdfmake_obj_xs_t *self
64             CODE:
65 2           RETVAL = pdfmake_is_name(self->obj);
66             OUTPUT:
67             RETVAL
68              
69             int
70             is_str(self)
71             pdfmake_obj_xs_t *self
72             CODE:
73 3           RETVAL = pdfmake_is_str(self->obj);
74             OUTPUT:
75             RETVAL
76              
77             int
78             is_array(self)
79             pdfmake_obj_xs_t *self
80             CODE:
81 3           RETVAL = pdfmake_is_array(self->obj);
82             OUTPUT:
83             RETVAL
84              
85             int
86             is_dict(self)
87             pdfmake_obj_xs_t *self
88             CODE:
89 4           RETVAL = pdfmake_is_dict(self->obj);
90             OUTPUT:
91             RETVAL
92              
93             int
94             is_stream(self)
95             pdfmake_obj_xs_t *self
96             CODE:
97 1           RETVAL = pdfmake_is_stream(self->obj);
98             OUTPUT:
99             RETVAL
100              
101             int
102             is_indirect_ref(self)
103             pdfmake_obj_xs_t *self
104             CODE:
105 1           RETVAL = pdfmake_is_ref(self->obj);
106             OUTPUT:
107             RETVAL
108              
109             SV *
110             value(self)
111             pdfmake_obj_xs_t *self
112             PREINIT:
113             const uint8_t *bytes;
114             size_t len;
115             CODE:
116 14           switch (self->obj->kind) {
117 0           case PDFMAKE_NULL:
118 0           RETVAL = &PL_sv_undef;
119 0           break;
120 2           case PDFMAKE_BOOL:
121 2 100         RETVAL = pdfmake_get_bool(self->obj) ? &PL_sv_yes : &PL_sv_no;
122 2           break;
123 7           case PDFMAKE_INT:
124 7           RETVAL = newSViv(pdfmake_get_int(self->obj));
125 7           break;
126 1           case PDFMAKE_REAL:
127 1           RETVAL = newSVnv(pdfmake_get_real(self->obj));
128 1           break;
129 2           case PDFMAKE_NAME:
130 2           bytes = (const uint8_t *)pdfmake_get_name_bytes(self->arena_xs->arena, self->obj);
131 2 50         RETVAL = bytes ? newSVpv((const char *)bytes, 0) : &PL_sv_undef;
132 2           break;
133 1           case PDFMAKE_STR:
134 1           bytes = pdfmake_get_str_bytes(self->obj, &len);
135 1 50         RETVAL = bytes ? newSVpvn((const char *)bytes, len) : &PL_sv_undef;
136 1           break;
137 1           default:
138             /* For composites, return undef - use specific methods */
139 1           RETVAL = &PL_sv_undef;
140 1           break;
141             }
142             OUTPUT:
143             RETVAL
144              
145             # Array methods
146              
147             SV *
148             push(self, item)
149             pdfmake_obj_xs_t *self
150             pdfmake_obj_xs_t *item
151             CODE:
152 206 100         if (self->obj->kind != PDFMAKE_ARRAY)
153 1           croak("PDF::Make::Obj::push: not an array");
154 205 50         if (!pdfmake_array_push(self->arena_xs->arena, self->obj, *item->obj))
155 0           croak("PDF::Make::Obj::push: failed");
156 205           RETVAL = SvREFCNT_inc(ST(0));
157             OUTPUT:
158             RETVAL
159              
160             UV
161             len(self)
162             pdfmake_obj_xs_t *self
163             CODE:
164 7 100         if (self->obj->kind == PDFMAKE_ARRAY) {
165 2           RETVAL = pdfmake_array_len(self->obj);
166 5 100         } else if (self->obj->kind == PDFMAKE_DICT) {
167 3           RETVAL = pdfmake_dict_len(self->obj);
168 2 100         } else if (self->obj->kind == PDFMAKE_STR) {
169             size_t slen;
170 1           pdfmake_get_str_bytes(self->obj, &slen);
171 1           RETVAL = slen;
172             } else {
173 1           croak("PDF::Make::Obj::len: not an array, dict, or string");
174             }
175             OUTPUT:
176             RETVAL
177              
178             pdfmake_obj_xs_t *
179             get(self, index_or_key)
180             pdfmake_obj_xs_t *self
181             SV *index_or_key
182             CODE:
183 11           pdfmake_obj_t *result = NULL;
184 11 100         if (self->obj->kind == PDFMAKE_ARRAY) {
185 6           UV idx = SvUV(index_or_key);
186 6           result = pdfmake_array_get(self->obj, idx);
187 5 50         } else if (self->obj->kind == PDFMAKE_DICT) {
188             /* Key is a name string - need to intern it */
189             STRLEN len;
190 5           const char *key = SvPV(index_or_key, len);
191 5           uint32_t name_id = pdfmake_arena_intern_name(self->arena_xs->arena, key, len);
192 5           result = pdfmake_dict_get(self->obj, name_id);
193             } else {
194 0           croak("PDF::Make::Obj::get: not an array or dict");
195             }
196 11 100         if (!result) {
197 2           XSRETURN_UNDEF;
198             }
199             /* Wrap the result - it lives in the same arena */
200 9           Newxz(RETVAL, 1, pdfmake_obj_xs_t);
201 9           RETVAL->arena_xs = self->arena_xs;
202 9           RETVAL->arena_sv = SvREFCNT_inc(self->arena_sv);
203 9           RETVAL->obj = result;
204             OUTPUT:
205             RETVAL
206              
207             # Dict methods
208              
209             SV *
210             set(self, key, val)
211             pdfmake_obj_xs_t *self
212             SV *key
213             pdfmake_obj_xs_t *val
214             PREINIT:
215             STRLEN len;
216             const char *key_str;
217             uint32_t name_id;
218             CODE:
219 104 50         if (self->obj->kind != PDFMAKE_DICT)
220 0           croak("PDF::Make::Obj::set: not a dict");
221 104           key_str = SvPV(key, len);
222 104           name_id = pdfmake_arena_intern_name(self->arena_xs->arena, key_str, len);
223 104 50         if (!pdfmake_dict_set(self->arena_xs->arena, self->obj, name_id, *val->obj))
224 0           croak("PDF::Make::Obj::set: failed");
225 104           RETVAL = SvREFCNT_inc(ST(0));
226             OUTPUT:
227             RETVAL
228              
229             int
230             has(self, key)
231             pdfmake_obj_xs_t *self
232             SV *key
233             PREINIT:
234             STRLEN len;
235             const char *key_str;
236             uint32_t name_id;
237             CODE:
238 5 100         if (self->obj->kind != PDFMAKE_DICT)
239 1           croak("PDF::Make::Obj::has: not a dict");
240 4           key_str = SvPV(key, len);
241 4           name_id = pdfmake_arena_intern_name(self->arena_xs->arena, key_str, len);
242 4           RETVAL = pdfmake_dict_has(self->obj, name_id);
243             OUTPUT:
244             RETVAL
245              
246             int
247             del(self, key)
248             pdfmake_obj_xs_t *self
249             SV *key
250             PREINIT:
251             STRLEN len;
252             const char *key_str;
253             uint32_t name_id;
254             CODE:
255 4 50         if (self->obj->kind != PDFMAKE_DICT)
256 0           croak("PDF::Make::Obj::del: not a dict");
257 4           key_str = SvPV(key, len);
258 4           name_id = pdfmake_arena_intern_name(self->arena_xs->arena, key_str, len);
259 4           RETVAL = pdfmake_dict_del(self->obj, name_id);
260             OUTPUT:
261             RETVAL
262              
263             # Indirect reference accessors
264              
265             UV
266             obj_ref_num(self)
267             pdfmake_obj_xs_t *self
268             CODE:
269 1 50         if (self->obj->kind != PDFMAKE_REF)
270 0           croak("PDF::Make::Obj::obj_ref_num: not a ref");
271 1 50         RETVAL = self->obj->as.ref.num;
272             OUTPUT:
273             RETVAL
274              
275             UV
276             obj_ref_gen(self)
277             pdfmake_obj_xs_t *self
278             CODE:
279 1 50         if (self->obj->kind != PDFMAKE_REF)
280 0           croak("PDF::Make::Obj::obj_ref_gen: not a ref");
281 1 50         RETVAL = self->obj->as.ref.gen;
282             OUTPUT:
283             RETVAL
284              
285             BOOT:
286             {
287 90           HV *stash = gv_stashpv("PDF::Make::Obj", GV_ADD);
288             /* Indirect getters: self->obj->field */
289 90 50         PDFMAKE_REGISTER_INDIRECT_GETTER(stash, "kind",
    50          
290             pdfmake_obj_xs_t, obj, pdfmake_obj_t, kind, PDFMAKE_FIELD_INT);
291 90 50         PDFMAKE_REGISTER_INDIRECT_GETTER(stash, "obj_ref_num",
    50          
292             pdfmake_obj_xs_t, obj, pdfmake_obj_t, as.ref.num, PDFMAKE_FIELD_UV);
293 90 50         PDFMAKE_REGISTER_INDIRECT_GETTER(stash, "obj_ref_gen",
    50          
294             pdfmake_obj_xs_t, obj, pdfmake_obj_t, as.ref.gen, PDFMAKE_FIELD_UV);
295             /* Type tests: self->obj->kind == PDFMAKE_X */
296 90 50         PDFMAKE_REGISTER_TYPETEST(stash, "is_null",
    50          
297             pdfmake_obj_xs_t, obj, pdfmake_obj_t, kind, PDFMAKE_NULL);
298 90 50         PDFMAKE_REGISTER_TYPETEST(stash, "is_bool",
    50          
299             pdfmake_obj_xs_t, obj, pdfmake_obj_t, kind, PDFMAKE_BOOL);
300 90 50         PDFMAKE_REGISTER_TYPETEST(stash, "is_int",
    50          
301             pdfmake_obj_xs_t, obj, pdfmake_obj_t, kind, PDFMAKE_INT);
302 90 50         PDFMAKE_REGISTER_TYPETEST(stash, "is_real",
    50          
303             pdfmake_obj_xs_t, obj, pdfmake_obj_t, kind, PDFMAKE_REAL);
304 90 50         PDFMAKE_REGISTER_TYPETEST(stash, "is_name",
    50          
305             pdfmake_obj_xs_t, obj, pdfmake_obj_t, kind, PDFMAKE_NAME);
306 90 50         PDFMAKE_REGISTER_TYPETEST(stash, "is_str",
    50          
307             pdfmake_obj_xs_t, obj, pdfmake_obj_t, kind, PDFMAKE_STR);
308 90 50         PDFMAKE_REGISTER_TYPETEST(stash, "is_array",
    50          
309             pdfmake_obj_xs_t, obj, pdfmake_obj_t, kind, PDFMAKE_ARRAY);
310 90 50         PDFMAKE_REGISTER_TYPETEST(stash, "is_dict",
    50          
311             pdfmake_obj_xs_t, obj, pdfmake_obj_t, kind, PDFMAKE_DICT);
312 90 50         PDFMAKE_REGISTER_TYPETEST(stash, "is_stream",
    50          
313             pdfmake_obj_xs_t, obj, pdfmake_obj_t, kind, PDFMAKE_STREAM);
314 90 50         PDFMAKE_REGISTER_TYPETEST(stash, "is_indirect_ref",
    50          
315             pdfmake_obj_xs_t, obj, pdfmake_obj_t, kind, PDFMAKE_REF);
316             }