File Coverage

xs/parser.xs
Criterion Covered Total %
statement 63 87 72.4
branch 33 62 53.2
condition n/a
subroutine n/a
pod n/a
total 96 149 64.4


line stmt bran cond sub pod time code
1             MODULE = PDF::Make PACKAGE = PDF::Make::Parser
2             PROTOTYPES: ENABLE
3              
4             pdfmake_parser_xs_t *
5             from_bytes(class, bytes_sv, ...)
6             char *class
7             SV *bytes_sv
8             PREINIT:
9             STRLEN len;
10             const char *buf;
11             int i;
12             CODE:
13 26           buf = SvPV(bytes_sv, len);
14 26           Newxz(RETVAL, 1, pdfmake_parser_xs_t);
15 26           RETVAL->parser = pdfmake_parser_new((const uint8_t *)buf, len);
16 26 50         if (!RETVAL->parser) {
17 0           Safefree(RETVAL);
18 0           croak("PDF::Make::Parser: failed to create parser");
19             }
20 26           RETVAL->bytes_sv = SvREFCNT_inc(bytes_sv);
21 26           RETVAL->doc = NULL;
22 26           RETVAL->parsed = 0;
23              
24             /* Parse keyword args: repair => 1 */
25 51 100         for (i = 2; i < items - 1; i += 2) {
26 25           const char *key = SvPV_nolen(ST(i));
27 25 50         if (strEQ(key, "repair") && SvTRUE(ST(i + 1))) {
    50          
28 25           pdfmake_parser_set_repair(RETVAL->parser, 1);
29             }
30             }
31             OUTPUT:
32             RETVAL
33              
34             pdfmake_parser_xs_t *
35             from_file(class, path_sv, ...)
36             char *class
37             SV *path_sv
38             PREINIT:
39             const char *path;
40             FILE *fp;
41             long file_len;
42             SV *bytes_sv;
43             char *buf;
44             size_t nread;
45             int i;
46             CODE:
47 89           path = SvPV_nolen(path_sv);
48 89           fp = fopen(path, "rb");
49 89 100         if (!fp)
50 1           croak("PDF::Make::Parser: cannot open '%s': %s", path, strerror(errno));
51              
52 88 50         if (fseek(fp, 0, SEEK_END) != 0) {
53 0           fclose(fp);
54 0           croak("PDF::Make::Parser: cannot seek '%s'", path);
55             }
56 88           file_len = ftell(fp);
57 88 50         if (file_len < 0) {
58 0           fclose(fp);
59 0           croak("PDF::Make::Parser: cannot tell '%s'", path);
60             }
61 88           rewind(fp);
62              
63 88           bytes_sv = newSV(file_len);
64 88           SvPOK_on(bytes_sv);
65 88           SvCUR_set(bytes_sv, file_len);
66 88           buf = SvPVX(bytes_sv);
67              
68 88           nread = fread(buf, 1, (size_t)file_len, fp);
69 88           fclose(fp);
70 88 50         if ((long)nread != file_len) {
71 0           SvREFCNT_dec(bytes_sv);
72 0           croak("PDF::Make::Parser: short read on '%s'", path);
73             }
74              
75 88           Newxz(RETVAL, 1, pdfmake_parser_xs_t);
76 88           RETVAL->parser = pdfmake_parser_new((const uint8_t *)buf, (size_t)file_len);
77 88 50         if (!RETVAL->parser) {
78 0           SvREFCNT_dec(bytes_sv);
79 0           Safefree(RETVAL);
80 0           croak("PDF::Make::Parser: failed to create parser");
81             }
82 88           RETVAL->bytes_sv = bytes_sv; /* already has refcnt 1 from newSV */
83 88           RETVAL->doc = NULL;
84 88           RETVAL->parsed = 0;
85              
86             /* Parse keyword args: repair => 1 */
87 173 100         for (i = 2; i < items - 1; i += 2) {
88 85           const char *key = SvPV_nolen(ST(i));
89 85 50         if (strEQ(key, "repair") && SvTRUE(ST(i + 1))) {
    50          
90 85           pdfmake_parser_set_repair(RETVAL->parser, 1);
91             }
92             }
93             OUTPUT:
94             RETVAL
95              
96             SV *
97             parse(self)
98             pdfmake_parser_xs_t *self
99             PREINIT:
100             pdfmake_err_t err;
101             CODE:
102 113 50         if (!self->parsed) {
103 113           err = pdfmake_parser_run(self->parser, &self->doc);
104 113 50         if (err != PDFMAKE_OK) {
105 0           croak("PDF::Make::Parser: parse failed at offset %zu: %s",
106             pdfmake_parser_erroffset(self->parser),
107             pdfmake_parser_errmsg(self->parser));
108             }
109 113           self->parsed = 1;
110             }
111 113           RETVAL = SvREFCNT_inc(ST(0));
112             OUTPUT:
113             RETVAL
114              
115             pdfmake_doc_t *
116             document(self)
117             pdfmake_parser_xs_t *self
118             PREINIT:
119             pdfmake_err_t err;
120             CODE:
121 4 50         if (!self->parsed) {
122 0           err = pdfmake_parser_run(self->parser, &self->doc);
123 0 0         if (err != PDFMAKE_OK) {
124 0           croak("PDF::Make::Parser: parse failed at offset %zu: %s",
125             pdfmake_parser_erroffset(self->parser),
126             pdfmake_parser_errmsg(self->parser));
127             }
128 0           self->parsed = 1;
129             }
130 4 50         if (!self->doc)
131 0           croak("PDF::Make::Parser: no document after parse");
132 4           RETVAL = self->doc;
133             OUTPUT:
134             RETVAL
135              
136             void
137             set_repair(self, enable)
138             pdfmake_parser_xs_t *self
139             int enable
140             CODE:
141 0           pdfmake_parser_set_repair(self->parser, enable);
142              
143             UV
144             root_num(self)
145             pdfmake_parser_xs_t *self
146             CODE:
147 12 50         RETVAL = self->parser->root_num;
148             OUTPUT:
149             RETVAL
150              
151             UV
152             root_gen(self)
153             pdfmake_parser_xs_t *self
154             CODE:
155 11 50         RETVAL = self->parser->root_gen;
156             OUTPUT:
157             RETVAL
158              
159             UV
160             xref_size(self)
161             pdfmake_parser_xs_t *self
162             CODE:
163 3 50         RETVAL = self->parser->xref_size;
164             OUTPUT:
165             RETVAL
166              
167             SV *
168             resolve(self, num, gen = 0)
169             pdfmake_parser_xs_t *self
170             UV num
171             UV gen
172             PREINIT:
173             pdfmake_ref_t ref;
174             pdfmake_obj_t *obj;
175             pdfmake_err_t err;
176             CODE:
177 13 50         if (!self->parsed) {
178 0           err = pdfmake_parser_run(self->parser, &self->doc);
179 0 0         if (err != PDFMAKE_OK) {
180 0           croak("PDF::Make::Parser: parse failed at offset %zu: %s",
181             pdfmake_parser_erroffset(self->parser),
182             pdfmake_parser_errmsg(self->parser));
183             }
184 0           self->parsed = 1;
185             }
186 13           ref.num = (uint32_t)num;
187 13           ref.gen = (uint16_t)gen;
188 13           obj = pdfmake_parser_resolve(self->parser, ref);
189 13 100         if (!obj) {
190 1           RETVAL = &PL_sv_undef;
191             } else {
192             /* Return object kind for now - full conversion in later phase */
193 12           RETVAL = newSViv(obj->kind);
194             }
195             OUTPUT:
196             RETVAL
197              
198             const char *
199             errmsg(self)
200             pdfmake_parser_xs_t *self
201             CODE:
202 0           RETVAL = pdfmake_parser_errmsg(self->parser);
203             OUTPUT:
204             RETVAL
205              
206             UV
207             erroffset(self)
208             pdfmake_parser_xs_t *self
209             CODE:
210 0           RETVAL = pdfmake_parser_erroffset(self->parser);
211             OUTPUT:
212             RETVAL
213              
214             void
215             DESTROY(self)
216             pdfmake_parser_xs_t *self
217             CODE:
218             /* doc is owned by the parser - freed by pdfmake_parser_free */
219 114 50         if (self->parser)
220 114           pdfmake_parser_free(self->parser);
221 114 50         if (self->bytes_sv)
222 114           SvREFCNT_dec(self->bytes_sv);
223 114           Safefree(self);
224              
225             BOOT:
226             {
227 90           HV *stash = gv_stashpv("PDF::Make::Parser", GV_ADD);
228 90 50         PDFMAKE_REGISTER_INDIRECT_GETTER(stash, "root_num",
    50          
229             pdfmake_parser_xs_t, parser, pdfmake_parser_t, root_num, PDFMAKE_FIELD_UV);
230 90 50         PDFMAKE_REGISTER_INDIRECT_GETTER(stash, "root_gen",
    50          
231             pdfmake_parser_xs_t, parser, pdfmake_parser_t, root_gen, PDFMAKE_FIELD_UV);
232 90 50         PDFMAKE_REGISTER_INDIRECT_GETTER(stash, "xref_size",
    50          
233             pdfmake_parser_xs_t, parser, pdfmake_parser_t, xref_size, PDFMAKE_FIELD_UV);
234             }