File Coverage

src/pdfmake_types.c
Criterion Covered Total %
statement 269 331 81.2
branch 158 282 56.0
condition n/a
subroutine n/a
pod n/a
total 427 613 69.6


line stmt bran cond sub pod time code
1             /*
2             * libpdfmake — PDF object constructors and operations.
3             *
4             * Constructors for all PDF primitive types: null, bool, int, real,
5             * name, string, hexstring, array, dict, ref, and stream.
6             */
7              
8             #include "pdfmake_arena.h"
9             #include
10             #include
11             #include
12              
13             /*----------------------------------------------------------------------------
14             * Primitive constructors (inline values)
15             *--------------------------------------------------------------------------*/
16              
17 178           pdfmake_obj_t pdfmake_null(void) {
18 178           pdfmake_obj_t obj = {0};
19 178           obj.kind = PDFMAKE_NULL;
20 178           return obj;
21             }
22              
23 32           pdfmake_obj_t pdfmake_bool(int value) {
24 32           pdfmake_obj_t obj = {0};
25 32           obj.kind = PDFMAKE_BOOL;
26 32           obj.as.i = value ? 1 : 0;
27 32           return obj;
28             }
29              
30 12509           pdfmake_obj_t pdfmake_int(int64_t value) {
31 12509           pdfmake_obj_t obj = {0};
32 12509           obj.kind = PDFMAKE_INT;
33 12509           obj.as.i = value;
34 12509           return obj;
35             }
36              
37 6101           pdfmake_obj_t pdfmake_real(double value) {
38 6101           pdfmake_obj_t obj = {0};
39 6101           obj.kind = PDFMAKE_REAL;
40 6101           obj.as.r = value;
41 6101           return obj;
42             }
43              
44             /*----------------------------------------------------------------------------
45             * Name constructor (interned)
46             *--------------------------------------------------------------------------*/
47              
48 9186           pdfmake_obj_t pdfmake_name(pdfmake_arena_t *arena, const char *bytes, size_t len) {
49 9186           pdfmake_obj_t obj = {0};
50 9186           obj.kind = PDFMAKE_NAME;
51              
52 9186 50         if (!arena || !bytes) {
    50          
53 0           obj.as.name.id = 0;
54 0           return obj;
55             }
56              
57             /* If len is 0, calculate from null-terminated string. */
58 9186 50         if (len == 0 && bytes[0] != '\0') {
    0          
59 0           len = strlen(bytes);
60             }
61              
62 9186           obj.as.name.id = pdfmake_arena_intern_name(arena, bytes, len);
63 9186           return obj;
64             }
65              
66 1741           pdfmake_obj_t pdfmake_name_cstr(pdfmake_arena_t *arena, const char *cstr) {
67 1741 50         return pdfmake_name(arena, cstr, cstr ? strlen(cstr) : 0);
68             }
69              
70             /*----------------------------------------------------------------------------
71             * String constructors (arena-allocated)
72             *--------------------------------------------------------------------------*/
73              
74 1549           pdfmake_obj_t pdfmake_str(pdfmake_arena_t *arena, const char *bytes, size_t len) {
75 1549           pdfmake_obj_t obj = {0};
76             uint8_t *dup;
77 1549           obj.kind = PDFMAKE_STR;
78              
79 1549 50         if (!arena || !bytes || len == 0) {
    50          
    100          
80 2           obj.as.str.bytes = NULL;
81 2           obj.as.str.len = 0;
82 2           obj.as.str.hex = 0;
83 2           return obj;
84             }
85              
86             /* Copy bytes into arena with null terminator for C string compatibility. */
87 1547           dup = pdfmake_arena_alloc(arena, len + 1);
88 1547 50         if (!dup) {
89 0           obj.as.str.bytes = NULL;
90 0           obj.as.str.len = 0;
91 0           obj.as.str.hex = 0;
92 0           return obj;
93             }
94              
95 1547           memcpy(dup, bytes, len);
96 1547           dup[len] = '\0'; /* null-terminate for C string use */
97 1547           obj.as.str.bytes = dup;
98 1547           obj.as.str.len = (uint32_t)len;
99 1547           obj.as.str.hex = 0;
100 1547           return obj;
101             }
102              
103 776           pdfmake_obj_t pdfmake_str_cstr(pdfmake_arena_t *arena, const char *cstr) {
104 776 50         return pdfmake_str(arena, cstr, cstr ? strlen(cstr) : 0);
105             }
106              
107 455           pdfmake_obj_t pdfmake_hexstr(pdfmake_arena_t *arena, const uint8_t *bytes, size_t len) {
108 455           pdfmake_obj_t obj = pdfmake_str(arena, (const char *)bytes, len);
109 455           obj.as.str.hex = 1;
110 455           return obj;
111             }
112              
113             /*----------------------------------------------------------------------------
114             * Reference constructor
115             *--------------------------------------------------------------------------*/
116              
117 3349           pdfmake_obj_t pdfmake_ref(uint32_t num, uint16_t gen) {
118 3349           pdfmake_obj_t obj = {0};
119 3349           obj.kind = PDFMAKE_REF;
120 3349           obj.as.ref.num = num;
121 3349           obj.as.ref.gen = gen;
122 3349           return obj;
123             }
124              
125             /*----------------------------------------------------------------------------
126             * Array operations
127             *--------------------------------------------------------------------------*/
128              
129             /* Initial array capacity. */
130             #define ARRAY_INIT_CAP 8
131              
132 2020           pdfmake_obj_t pdfmake_array_new(pdfmake_arena_t *arena) {
133 2020           pdfmake_obj_t obj = {0};
134             pdfmake_array_t *arr;
135 2020           obj.kind = PDFMAKE_ARRAY;
136              
137 2020 50         if (!arena) {
138 0           obj.as.arr = NULL;
139 0           return obj;
140             }
141              
142 2020           arr = pdfmake_arena_calloc(arena, sizeof(pdfmake_array_t));
143 2020 50         if (!arr) {
144 0           obj.as.arr = NULL;
145 0           return obj;
146             }
147              
148 2020           arr->items = pdfmake_arena_alloc(arena, ARRAY_INIT_CAP * sizeof(pdfmake_obj_t));
149 2020 50         if (!arr->items) {
150 0           obj.as.arr = NULL;
151 0           return obj;
152             }
153              
154 2020           arr->len = 0;
155 2020           arr->cap = ARRAY_INIT_CAP;
156 2020           obj.as.arr = arr;
157 2020           return obj;
158             }
159              
160 15913           int pdfmake_array_push(pdfmake_arena_t *arena, pdfmake_obj_t *arr_obj, pdfmake_obj_t item) {
161             pdfmake_array_t *arr;
162 15913 50         if (!arena || !arr_obj || arr_obj->kind != PDFMAKE_ARRAY || !arr_obj->as.arr) {
    50          
    50          
    50          
163 0           return 0;
164             }
165              
166 15913           arr = arr_obj->as.arr;
167              
168             /* Grow if needed. */
169 15913 100         if (arr->len >= arr->cap) {
170 560           size_t new_cap = arr->cap * 2;
171 560           pdfmake_obj_t *new_items = pdfmake_arena_alloc(arena, new_cap * sizeof(pdfmake_obj_t));
172 560 50         if (!new_items) return 0;
173              
174 560           memcpy(new_items, arr->items, arr->len * sizeof(pdfmake_obj_t));
175 560           arr->items = new_items;
176 560           arr->cap = (uint32_t)new_cap;
177             }
178              
179 15913           arr->items[arr->len++] = item;
180 15913           return 1;
181             }
182              
183 8875           pdfmake_obj_t *pdfmake_array_get(pdfmake_obj_t *arr_obj, size_t index) {
184             pdfmake_array_t *arr;
185 8875 50         if (!arr_obj || arr_obj->kind != PDFMAKE_ARRAY || !arr_obj->as.arr) {
    50          
    50          
186 0           return NULL;
187             }
188              
189 8875           arr = arr_obj->as.arr;
190 8875 100         if (index >= arr->len) return NULL;
191              
192 8874           return &arr->items[index];
193             }
194              
195 0           int pdfmake_array_set(pdfmake_obj_t *arr_obj, size_t index, pdfmake_obj_t item) {
196             pdfmake_array_t *arr;
197 0 0         if (!arr_obj || arr_obj->kind != PDFMAKE_ARRAY || !arr_obj->as.arr) {
    0          
    0          
198 0           return 0;
199             }
200              
201 0           arr = arr_obj->as.arr;
202 0 0         if (index >= arr->len) return 0;
203              
204 0           arr->items[index] = item;
205 0           return 1;
206             }
207              
208 827           size_t pdfmake_array_len(pdfmake_obj_t *arr_obj) {
209 827 50         if (!arr_obj || arr_obj->kind != PDFMAKE_ARRAY || !arr_obj->as.arr) {
    50          
    50          
210 0           return 0;
211             }
212 827           return arr_obj->as.arr->len;
213             }
214              
215             /*----------------------------------------------------------------------------
216             * Dict operations
217             *--------------------------------------------------------------------------*/
218              
219             /* Initial dict capacity (must be power of 2). */
220             #define DICT_INIT_CAP 16
221              
222             /* Load factor threshold: grow when entries/cap > 70%. */
223             #define DICT_LOAD_FACTOR_NUM 7
224             #define DICT_LOAD_FACTOR_DEN 10
225              
226             /* Find slot for key. Returns index, sets *found = 1 if key exists. */
227 20398           static size_t dict_find_slot(pdfmake_dict_t *dict, uint32_t key, int *found) {
228             size_t mask;
229             size_t idx;
230             size_t first_tombstone;
231             size_t i;
232 20398           *found = 0;
233 20398 50         if (!dict->entries || dict->cap == 0) return 0;
    50          
234              
235 20398           mask = dict->cap - 1;
236 20398           idx = key & mask;
237 20398           first_tombstone = (size_t)-1;
238              
239 21914 50         for (i = 0; i < dict->cap; i++) {
240 21914           pdfmake_dict_entry_t *e = &dict->entries[idx];
241              
242 21914 100         if (e->key == 0 && !e->deleted) {
    100          
243             /* Empty slot. */
244 16225 100         if (first_tombstone != (size_t)-1) {
245 111           return first_tombstone;
246             }
247 16114           return idx;
248             }
249              
250 5689 100         if (e->deleted) {
251             /* Tombstone. */
252 127 100         if (first_tombstone == (size_t)-1) {
253 111           first_tombstone = idx;
254             }
255 5562 100         } else if (e->key == key) {
256             /* Found existing key. */
257 4173           *found = 1;
258 4173           return idx;
259             }
260              
261 1516           idx = (idx + 1) & mask;
262             }
263              
264             /* Table full (shouldn't happen with proper load factor). */
265 0 0         return first_tombstone != (size_t)-1 ? first_tombstone : 0;
266             }
267              
268             /* Grow dict hash table. */
269 28           static int dict_grow(pdfmake_arena_t *arena, pdfmake_dict_t *dict) {
270 28           size_t new_cap = dict->cap * 2;
271             pdfmake_dict_entry_t *new_entries;
272             size_t mask;
273             size_t i;
274 28 50         if (new_cap == 0) new_cap = DICT_INIT_CAP;
275              
276 28           new_entries = pdfmake_arena_calloc(arena, new_cap * sizeof(pdfmake_dict_entry_t));
277 28 50         if (!new_entries) return 0;
278              
279             /* Rehash all non-deleted entries. */
280 28           mask = new_cap - 1;
281 604 100         for (i = 0; i < dict->cap; i++) {
282 576           pdfmake_dict_entry_t *e = &dict->entries[i];
283 576 100         if (e->key != 0 && !e->deleted) {
    50          
284 396           size_t idx = e->key & mask;
285 397 100         while (new_entries[idx].key != 0) {
286 1           idx = (idx + 1) & mask;
287             }
288 396           new_entries[idx] = *e;
289 396           new_entries[idx].deleted = 0;
290             }
291             }
292              
293 28           dict->entries = new_entries;
294 28           dict->cap = (uint32_t)new_cap;
295 28           dict->tombstones = 0;
296 28           return 1;
297             }
298              
299 4423           pdfmake_obj_t pdfmake_dict_new(pdfmake_arena_t *arena) {
300 4423           pdfmake_obj_t obj = {0};
301             pdfmake_dict_t *dict;
302 4423           obj.kind = PDFMAKE_DICT;
303              
304 4423 50         if (!arena) {
305 0           obj.as.dict = NULL;
306 0           return obj;
307             }
308              
309 4423           dict = pdfmake_arena_calloc(arena, sizeof(pdfmake_dict_t));
310 4423 50         if (!dict) {
311 0           obj.as.dict = NULL;
312 0           return obj;
313             }
314              
315 4423           dict->entries = pdfmake_arena_calloc(arena, DICT_INIT_CAP * sizeof(pdfmake_dict_entry_t));
316 4423 50         if (!dict->entries) {
317 0           obj.as.dict = NULL;
318 0           return obj;
319             }
320              
321 4423           dict->cap = DICT_INIT_CAP;
322 4423           dict->len = 0;
323 4423           dict->tombstones = 0;
324 4423           dict->next_order = 0;
325 4423           obj.as.dict = dict;
326 4423           return obj;
327             }
328              
329 13650           int pdfmake_dict_set(pdfmake_arena_t *arena, pdfmake_obj_t *dict_obj, uint32_t key, pdfmake_obj_t value) {
330             pdfmake_dict_t *dict;
331             int found;
332             size_t idx;
333 13650 50         if (!arena || !dict_obj || dict_obj->kind != PDFMAKE_DICT || !dict_obj->as.dict || key == 0) {
    50          
    50          
    50          
    50          
334 0           return 0;
335             }
336              
337 13650           dict = dict_obj->as.dict;
338              
339             /* Check load factor and grow if needed. */
340 13650 100         if ((dict->len + dict->tombstones + 1) * DICT_LOAD_FACTOR_DEN > dict->cap * DICT_LOAD_FACTOR_NUM) {
341 28 50         if (!dict_grow(arena, dict)) return 0;
342             }
343              
344 13650           idx = dict_find_slot(dict, key, &found);
345              
346 13650 100         if (found) {
347             /* Update existing. */
348 203           dict->entries[idx].value = value;
349             } else {
350             /* Insert new. */
351 13447 100         if (dict->entries[idx].deleted) {
352 51           dict->tombstones--;
353             }
354 13447           dict->entries[idx].key = key;
355 13447           dict->entries[idx].value = value;
356 13447           dict->entries[idx].order = dict->next_order++;
357 13447           dict->entries[idx].deleted = 0;
358 13447           dict->len++;
359             }
360              
361 13650           return 1;
362             }
363              
364 6591           pdfmake_obj_t *pdfmake_dict_get(pdfmake_obj_t *dict_obj, uint32_t key) {
365             pdfmake_dict_t *dict;
366             int found;
367             size_t idx;
368 6591 50         if (!dict_obj || dict_obj->kind != PDFMAKE_DICT || !dict_obj->as.dict || key == 0) {
    50          
    50          
    50          
369 0           return NULL;
370             }
371              
372 6591           dict = dict_obj->as.dict;
373 6591           idx = dict_find_slot(dict, key, &found);
374              
375 6591 100         if (found) {
376 3865           return &dict->entries[idx].value;
377             }
378 2726           return NULL;
379             }
380              
381 181           int pdfmake_dict_has(pdfmake_obj_t *dict_obj, uint32_t key) {
382 181           return pdfmake_dict_get(dict_obj, key) != NULL;
383             }
384              
385 157           int pdfmake_dict_del(pdfmake_obj_t *dict_obj, uint32_t key) {
386             pdfmake_dict_t *dict;
387             int found;
388             size_t idx;
389 157 50         if (!dict_obj || dict_obj->kind != PDFMAKE_DICT || !dict_obj->as.dict || key == 0) {
    50          
    50          
    50          
390 0           return 0;
391             }
392              
393 157           dict = dict_obj->as.dict;
394 157           idx = dict_find_slot(dict, key, &found);
395              
396 157 100         if (found) {
397 105           dict->entries[idx].deleted = 1;
398 105           dict->entries[idx].key = 0;
399 105           dict->len--;
400 105           dict->tombstones++;
401 105           return 1;
402             }
403 52           return 0;
404             }
405              
406 3           size_t pdfmake_dict_len(pdfmake_obj_t *dict_obj) {
407 3 50         if (!dict_obj || dict_obj->kind != PDFMAKE_DICT || !dict_obj->as.dict) {
    50          
    50          
408 0           return 0;
409             }
410 3           return dict_obj->as.dict->len;
411             }
412              
413             /* Iterator: return entries in insertion order. */
414             typedef struct {
415             pdfmake_dict_t *dict;
416             uint32_t current_order;
417             size_t visited;
418             } pdfmake_dict_iter_state_t;
419              
420 613           void pdfmake_dict_iter_init(pdfmake_dict_iter_t *iter, pdfmake_obj_t *dict_obj) {
421 613           iter->dict_obj = dict_obj;
422 613           iter->index = 0;
423 613           iter->current_key = 0;
424 613           iter->current_value = NULL;
425 613           }
426              
427 2446           int pdfmake_dict_iter_next(pdfmake_dict_iter_t *iter) {
428             pdfmake_dict_t *dict;
429             uint32_t best_order;
430             size_t best_idx;
431             size_t i;
432 2446 50         if (!iter || !iter->dict_obj || iter->dict_obj->kind != PDFMAKE_DICT || !iter->dict_obj->as.dict) {
    50          
    50          
    50          
433 0           return 0;
434             }
435              
436 2446           dict = iter->dict_obj->as.dict;
437              
438             /* Find next entry with smallest order >= current position.
439             * This is O(n²) worst case but maintains insertion order.
440             * For 10k entries, consider caching sorted keys. */
441              
442 2446           best_order = UINT32_MAX;
443 2446           best_idx = (size_t)-1;
444              
445 41582 100         for (i = 0; i < dict->cap; i++) {
446 39136           pdfmake_dict_entry_t *e = &dict->entries[i];
447 39136 100         if (e->key != 0 && !e->deleted) {
    50          
448 11416 100         if (e->order >= iter->index && e->order < best_order) {
    100          
449 2313           best_order = e->order;
450 2313           best_idx = i;
451             }
452             }
453             }
454              
455 2446 100         if (best_idx == (size_t)-1) {
456 613           return 0;
457             }
458              
459 1833           iter->current_key = dict->entries[best_idx].key;
460 1833           iter->current_value = &dict->entries[best_idx].value;
461 1833           iter->index = best_order + 1;
462 1833           return 1;
463             }
464              
465             /*----------------------------------------------------------------------------
466             * Stream operations
467             *--------------------------------------------------------------------------*/
468              
469 580           pdfmake_obj_t pdfmake_stream_new(pdfmake_arena_t *arena) {
470 580           pdfmake_obj_t obj = {0};
471             pdfmake_stream_t *stream;
472             pdfmake_obj_t dict;
473 580           obj.kind = PDFMAKE_STREAM;
474              
475 580 50         if (!arena) {
476 0           obj.as.stream = NULL;
477 0           return obj;
478             }
479              
480 580           stream = pdfmake_arena_calloc(arena, sizeof(pdfmake_stream_t));
481 580 50         if (!stream) {
482 0           obj.as.stream = NULL;
483 0           return obj;
484             }
485              
486             /* Initialize the stream's dict. */
487 580           dict = pdfmake_dict_new(arena);
488 580 50         if (dict.as.dict) {
489 580           stream->dict = dict.as.dict;
490             }
491              
492 580           stream->raw = NULL;
493 580           stream->raw_len = 0;
494 580           stream->filtered = 0;
495              
496 580           obj.as.stream = stream;
497 580           return obj;
498             }
499              
500 528           int pdfmake_stream_set_data(pdfmake_arena_t *arena, pdfmake_obj_t *stream_obj,
501             const uint8_t *data, size_t len) {
502             pdfmake_stream_t *stream;
503 528 50         if (!arena || !stream_obj || stream_obj->kind != PDFMAKE_STREAM || !stream_obj->as.stream) {
    50          
    50          
    50          
504 0           return 0;
505             }
506              
507 528           stream = stream_obj->as.stream;
508              
509 528 50         if (data && len > 0) {
    100          
510 510           uint8_t *dup = pdfmake_arena_memdup(arena, data, len);
511 510 50         if (!dup) return 0;
512 510           stream->raw = dup;
513 510           stream->raw_len = (uint32_t)len;
514             } else {
515 18           stream->raw = NULL;
516 18           stream->raw_len = 0;
517             }
518              
519 528           return 1;
520             }
521              
522 24           pdfmake_dict_t *pdfmake_stream_dict(pdfmake_obj_t *stream_obj) {
523 24 50         if (!stream_obj || stream_obj->kind != PDFMAKE_STREAM || !stream_obj->as.stream) {
    50          
    50          
524 0           return NULL;
525             }
526 24           return stream_obj->as.stream->dict;
527             }
528              
529 0           int pdfmake_stream_set_flate(pdfmake_arena_t *arena, pdfmake_obj_t *stream_obj) {
530             pdfmake_stream_t *stream;
531             uint32_t filter_key;
532             pdfmake_obj_t filter_name;
533             pdfmake_obj_t dict_obj;
534 0 0         if (!arena || !stream_obj || stream_obj->kind != PDFMAKE_STREAM || !stream_obj->as.stream) {
    0          
    0          
    0          
535 0           return 0;
536             }
537              
538 0           stream = stream_obj->as.stream;
539 0 0         if (!stream->dict) return 0;
540              
541             /* Set /Filter to /FlateDecode */
542 0           filter_key = pdfmake_arena_intern_name(arena, "Filter", 6);
543 0 0         if (filter_key == 0) return 0;
544              
545 0           filter_name = pdfmake_name_cstr(arena, "FlateDecode");
546 0           dict_obj.kind = PDFMAKE_DICT;
547 0           dict_obj.as.dict = stream->dict;
548 0 0         if (!pdfmake_dict_set(arena, &dict_obj, filter_key, filter_name)) {
549 0           return 0;
550             }
551              
552             /* Mark stream as needing compression (filtered=0 means raw data to encode) */
553 0           stream->filtered = 0;
554 0           return 1;
555             }
556              
557             /*----------------------------------------------------------------------------
558             * Type checking and accessors
559             *--------------------------------------------------------------------------*/
560              
561 2           int pdfmake_is_null(pdfmake_obj_t *obj) {
562 2 50         return obj && obj->kind == PDFMAKE_NULL;
    100          
563             }
564              
565 2           int pdfmake_is_bool(pdfmake_obj_t *obj) {
566 2 50         return obj && obj->kind == PDFMAKE_BOOL;
    100          
567             }
568              
569 2           int pdfmake_is_int(pdfmake_obj_t *obj) {
570 2 50         return obj && obj->kind == PDFMAKE_INT;
    100          
571             }
572              
573 2           int pdfmake_is_real(pdfmake_obj_t *obj) {
574 2 50         return obj && obj->kind == PDFMAKE_REAL;
    100          
575             }
576              
577 3           int pdfmake_is_numeric(pdfmake_obj_t *obj) {
578 3 50         return obj && (obj->kind == PDFMAKE_INT || obj->kind == PDFMAKE_REAL);
    100          
    100          
579             }
580              
581 2           int pdfmake_is_name(pdfmake_obj_t *obj) {
582 2 50         return obj && obj->kind == PDFMAKE_NAME;
    100          
583             }
584              
585 3           int pdfmake_is_str(pdfmake_obj_t *obj) {
586 3 50         return obj && obj->kind == PDFMAKE_STR;
    100          
587             }
588              
589 3           int pdfmake_is_array(pdfmake_obj_t *obj) {
590 3 50         return obj && obj->kind == PDFMAKE_ARRAY;
    100          
591             }
592              
593 4           int pdfmake_is_dict(pdfmake_obj_t *obj) {
594 4 50         return obj && obj->kind == PDFMAKE_DICT;
    100          
595             }
596              
597 1           int pdfmake_is_stream(pdfmake_obj_t *obj) {
598 1 50         return obj && obj->kind == PDFMAKE_STREAM;
    50          
599             }
600              
601 1           int pdfmake_is_ref(pdfmake_obj_t *obj) {
602 1 50         return obj && obj->kind == PDFMAKE_REF;
    50          
603             }
604              
605 2           int pdfmake_get_bool(pdfmake_obj_t *obj) {
606 2 50         return (obj && obj->kind == PDFMAKE_BOOL) ? (int)obj->as.i : 0;
    50          
607             }
608              
609 7           int64_t pdfmake_get_int(pdfmake_obj_t *obj) {
610 7 50         if (!obj) return 0;
611 7 50         if (obj->kind == PDFMAKE_INT) return obj->as.i;
612 0 0         if (obj->kind == PDFMAKE_REAL) return (int64_t)obj->as.r;
613 0           return 0;
614             }
615              
616 14           double pdfmake_get_real(pdfmake_obj_t *obj) {
617 14 50         if (!obj) return 0.0;
618 14 100         if (obj->kind == PDFMAKE_REAL) return obj->as.r;
619 13 50         if (obj->kind == PDFMAKE_INT) return (double)obj->as.i;
620 0           return 0.0;
621             }
622              
623 13           double pdfmake_get_number(pdfmake_obj_t *obj) {
624 13           return pdfmake_get_real(obj);
625             }
626              
627 321           const char *pdfmake_get_name_bytes(pdfmake_arena_t *arena, pdfmake_obj_t *obj) {
628 321 50         if (!arena || !obj || obj->kind != PDFMAKE_NAME) return NULL;
    50          
    50          
629 321           return pdfmake_arena_name_bytes(arena, obj->as.name.id);
630             }
631              
632 66           const uint8_t *pdfmake_get_str_bytes(pdfmake_obj_t *obj, size_t *len_out) {
633 66 50         if (!obj || obj->kind != PDFMAKE_STR) {
    50          
634 0 0         if (len_out) *len_out = 0;
635 0           return NULL;
636             }
637 66 50         if (len_out) *len_out = obj->as.str.len;
638 66           return obj->as.str.bytes;
639             }
640              
641 0           int pdfmake_str_is_hex(pdfmake_obj_t *obj) {
642 0 0         return (obj && obj->kind == PDFMAKE_STR) ? obj->as.str.hex : 0;
    0          
643             }