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