File Coverage

perlio.c
Criterion Covered Total %
statement 39 44 88.6
branch 10 16 62.5
condition n/a
subroutine n/a
pod n/a
total 49 60 81.6


line stmt bran cond sub pod time code
1             /* perlio.c - Imager's interface to PerlIO
2              
3             */
4             #define IMAGER_NO_CONTEXT
5             #include "imager.h"
6             #include "EXTERN.h"
7             #include "perl.h"
8             #include "imperlio.h"
9              
10              
11             static ssize_t
12             perlio_reader(void *handle, void *buf, size_t count);
13             static ssize_t
14             perlio_writer(void *handle, const void *buf, size_t count);
15             static off_t
16             perlio_seeker(void *handle, off_t offset, int whence);
17             static int
18             perlio_closer(void *handle);
19             static void
20             perlio_destroy(void *handle);
21             /* my_strerror is defined since perl 5.21.x */
22             #undef my_strerror
23             static const char *my_strerror(pTHX_ int err);
24              
25             #ifndef tTHX
26             #define tTHX PerlInterpreter *
27             #endif
28              
29             typedef struct {
30             PerlIO *handle;
31             pIMCTX;
32             #ifdef MULTIPLICITY
33             tTHX my_perl;
34             #endif
35             } im_perlio;
36              
37             #define dIMCTXperlio(state) dIMCTXctx(state->aIMCTX)
38              
39             /*
40             =item im_io_new_perlio(PerlIO *)
41              
42             Create a new perl I/O object that reads/writes/seeks on a PerlIO
43             handle.
44              
45             The close() handle flushes output but does not close the handle.
46              
47             =cut
48             */
49              
50             i_io_glue_t *
51 19           im_io_new_perlio(pTHX_ PerlIO *handle) {
52 19           im_perlio *state = mymalloc(sizeof(im_perlio));
53 19           dIMCTX;
54              
55 19           state->handle = handle;
56             #ifdef MULTIPLICITY
57             state->aTHX = aTHX;
58             #endif
59 19           state->aIMCTX = aIMCTX;
60              
61 19           return io_new_cb(state, perlio_reader, perlio_writer,
62             perlio_seeker, perlio_closer, perlio_destroy);
63             }
64              
65             static ssize_t
66 51           perlio_reader(void *ctx, void *buf, size_t count) {
67 51           im_perlio *state = ctx;
68             dTHXa(state->my_perl);
69 51           dIMCTXperlio(state);
70              
71 51           ssize_t result = PerlIO_read(state->handle, buf, count);
72 51 100         if (result == 0 && PerlIO_error(state->handle)) {
    100          
73 1           im_push_errorf(aIMCTX, errno, "read() failure (%s)", my_strerror(aTHX_ errno));
74 1           return -1;
75             }
76              
77 50           return result;
78             }
79              
80             static ssize_t
81 24           perlio_writer(void *ctx, const void *buf, size_t count) {
82 24           im_perlio *state = ctx;
83             dTHXa(state->my_perl);
84 24           dIMCTXperlio(state);
85             ssize_t result;
86              
87 24           result = PerlIO_write(state->handle, buf, count);
88              
89 24 100         if (result == 0) {
90 1           im_push_errorf(aIMCTX, errno, "write() failure (%s)", my_strerror(aTHX_ errno));
91             }
92              
93 24           return result;
94             }
95              
96             static off_t
97 2           perlio_seeker(void *ctx, off_t offset, int whence) {
98 2           im_perlio *state = ctx;
99             dTHXa(state->my_perl);
100 2           dIMCTXperlio(state);
101              
102 2 50         if (whence != SEEK_CUR || offset != 0) {
    0          
103 2 50         if (PerlIO_seek(state->handle, offset, whence) < 0) {
104 0           im_push_errorf(aIMCTX, errno, "seek() failure (%s)", my_strerror(aTHX_ errno));
105 0           return -1;
106             }
107             }
108              
109 2           return PerlIO_tell(state->handle);
110             }
111              
112             static int
113 6           perlio_closer(void *ctx) {
114 6           im_perlio *state = ctx;
115             dTHXa(state->my_perl);
116 6           dIMCTXperlio(state);
117              
118 6 50         if (PerlIO_flush(state->handle) < 0) {
119 0           im_push_errorf(aIMCTX, errno, "flush() failure (%s)", my_strerror(aTHX_ errno));
120 0           return -1;
121             }
122 6           return 0;
123             }
124              
125             static void
126 19           perlio_destroy(void *ctx) {
127 19           myfree(ctx);
128 19           }
129              
130             static
131 2           const char *my_strerror(pTHX_ int err) {
132 2           const char *result = strerror(err);
133            
134 2 50         if (!result)
135 0           result = "Unknown error";
136            
137 2           return result;
138             }
139