Commit | Line | Data |
b295d113 |
1 | #include "EXTERN.h" |
2 | #include "perl.h" |
3 | #include "XSUB.h" |
e8edd1e6 |
4 | #include "byterun.h" |
b295d113 |
5 | |
059a8bb7 |
6 | /* Something arbitary for a buffer size */ |
7 | #define BYTELOADER_BUFFER 8096 |
33c2a728 |
8 | |
059a8bb7 |
9 | int |
10 | bl_getc(struct byteloader_fdata *data) |
33c2a728 |
11 | { |
12 | dTHX; |
7c436af3 |
13 | if (SvCUR(data->datasv) <= (STRLEN)data->next_out) { |
059a8bb7 |
14 | int result; |
15 | /* Run out of buffered data, so attempt to read some more */ |
16 | *(SvPV_nolen (data->datasv)) = '\0'; |
17 | SvCUR_set (data->datasv, 0); |
18 | data->next_out = 0; |
19 | result = FILTER_READ (data->idx + 1, data->datasv, BYTELOADER_BUFFER); |
20 | |
21 | /* Filter returned error, or we got EOF and no data, then return EOF. |
22 | Not sure if filter is allowed to return EOF and add data simultaneously |
23 | Think not, but will bullet proof against it. */ |
24 | if (result < 0 || SvCUR(data->datasv) == 0) |
25 | return EOF; |
26 | /* Else there must be at least one byte present, which is good enough */ |
27 | } |
28 | |
1df34986 |
29 | return *((U8 *) SvPV_nolen (data->datasv) + data->next_out++); |
33c2a728 |
30 | } |
d8ab9aa2 |
31 | |
059a8bb7 |
32 | int |
33 | bl_read(struct byteloader_fdata *data, char *buf, size_t size, size_t n) |
e8edd1e6 |
34 | { |
c5be433b |
35 | dTHX; |
059a8bb7 |
36 | char *start; |
37 | STRLEN len; |
38 | size_t wanted = size * n; |
39 | |
40 | start = SvPV (data->datasv, len); |
41 | if (len < (data->next_out + wanted)) { |
42 | int result; |
43 | |
44 | /* Shuffle data to start of buffer */ |
45 | len -= data->next_out; |
46 | if (len) { |
47 | memmove (start, start + data->next_out, len + 1); |
059a8bb7 |
48 | } else { |
49 | *start = '\0'; /* Avoid call to memmove. */ |
059a8bb7 |
50 | } |
4b31f138 |
51 | SvCUR_set(data->datasv, len); |
059a8bb7 |
52 | data->next_out = 0; |
53 | |
54 | /* Attempt to read more data. */ |
55 | do { |
56 | result = FILTER_READ (data->idx + 1, data->datasv, BYTELOADER_BUFFER); |
57 | |
58 | start = SvPV (data->datasv, len); |
59 | } while (result > 0 && len < wanted); |
60 | /* Loop while not (EOF || error) and short reads */ |
61 | |
62 | /* If not enough data read, truncate copy */ |
63 | if (wanted > len) |
64 | wanted = len; |
65 | } |
66 | |
67 | if (wanted > 0) { |
68 | memcpy (buf, start + data->next_out, wanted); |
69 | data->next_out += wanted; |
70 | wanted /= size; |
71 | } |
72 | return (int) wanted; |
e8edd1e6 |
73 | } |
b295d113 |
74 | |
75 | static I32 |
acfe0abc |
76 | byteloader_filter(pTHX_ int idx, SV *buf_sv, int maxlen) |
b295d113 |
77 | { |
78 | OP *saveroot = PL_main_root; |
79 | OP *savestart = PL_main_start; |
059a8bb7 |
80 | struct byteloader_state bstate; |
81 | struct byteloader_fdata data; |
1df34986 |
82 | int len; |
4b31f138 |
83 | (void)buf_sv; |
84 | (void)maxlen; |
059a8bb7 |
85 | |
86 | data.next_out = 0; |
87 | data.datasv = FILTER_DATA(idx); |
88 | data.idx = idx; |
b295d113 |
89 | |
059a8bb7 |
90 | bstate.bs_fdata = &data; |
91 | bstate.bs_obj_list = Null(void**); |
92 | bstate.bs_obj_list_fill = -1; |
93 | bstate.bs_sv = Nullsv; |
94 | bstate.bs_iv_overflows = 0; |
e8edd1e6 |
95 | |
1df34986 |
96 | /* KLUDGE */ |
97 | if (byterun(aTHX_ &bstate) |
98 | && (len = SvCUR(data.datasv) - (STRLEN)data.next_out)) |
99 | { |
100 | PerlIO_seek(PL_rsfp, -len, SEEK_CUR); |
101 | PL_rsfp = NULL; |
102 | } |
103 | filter_del(byteloader_filter); |
b295d113 |
104 | |
105 | if (PL_in_eval) { |
106 | OP *o; |
107 | |
108 | PL_eval_start = PL_main_start; |
109 | |
110 | o = newSVOP(OP_CONST, 0, newSViv(1)); |
111 | PL_eval_root = newLISTOP(OP_LINESEQ, 0, PL_main_root, o); |
112 | PL_main_root->op_next = o; |
113 | PL_eval_root = newUNOP(OP_LEAVEEVAL, 0, PL_eval_root); |
114 | o->op_next = PL_eval_root; |
115 | |
116 | PL_main_root = saveroot; |
117 | PL_main_start = savestart; |
118 | } |
119 | |
120 | return 0; |
121 | } |
122 | |
123 | MODULE = ByteLoader PACKAGE = ByteLoader |
124 | |
125 | PROTOTYPES: ENABLE |
126 | |
127 | void |
c6c619a9 |
128 | import(package="ByteLoader", ...) |
129 | char *package |
059a8bb7 |
130 | PREINIT: |
131 | SV *sv = newSVpvn ("", 0); |
b295d113 |
132 | PPCODE: |
059a8bb7 |
133 | if (!sv) |
134 | croak ("Could not allocate ByteLoader buffers"); |
135 | filter_add(byteloader_filter, sv); |