SYN SYN
[p5sagit/p5-mst-13.2.git] / ext / ByteLoader / ByteLoader.xs
CommitLineData
c5be433b 1#define PERL_NO_GET_CONTEXT
b295d113 2#include "EXTERN.h"
3#include "perl.h"
4#include "XSUB.h"
e8edd1e6 5#include "byterun.h"
b295d113 6
22d4bb9c 7/* Something arbitary for a buffer size */
8#define BYTELOADER_BUFFER 8096
146174a9 9
22d4bb9c 10int
11bl_getc(struct byteloader_fdata *data)
146174a9 12{
13 dTHX;
22d4bb9c 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++);
146174a9 31}
d8ab9aa2 32
22d4bb9c 33int
34bl_read(struct byteloader_fdata *data, char *buf, size_t size, size_t n)
e8edd1e6 35{
c5be433b 36 dTHX;
22d4bb9c 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 76
77static I32
0cb96387 78byteloader_filter(pTHXo_ int idx, SV *buf_sv, int maxlen)
b295d113 79{
a6c40364 80 dTHR;
b295d113 81 OP *saveroot = PL_main_root;
82 OP *savestart = PL_main_start;
22d4bb9c 83 struct byteloader_state bstate;
84 struct byteloader_fdata data;
85
86 data.next_out = 0;
87 data.datasv = FILTER_DATA(idx);
88 data.idx = idx;
b295d113 89
22d4bb9c 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
22d4bb9c 96 byterun(aTHXo_ &bstate);
b295d113 97
98 if (PL_in_eval) {
99 OP *o;
100
101 PL_eval_start = PL_main_start;
102
103 o = newSVOP(OP_CONST, 0, newSViv(1));
104 PL_eval_root = newLISTOP(OP_LINESEQ, 0, PL_main_root, o);
105 PL_main_root->op_next = o;
106 PL_eval_root = newUNOP(OP_LEAVEEVAL, 0, PL_eval_root);
107 o->op_next = PL_eval_root;
108
109 PL_main_root = saveroot;
110 PL_main_start = savestart;
111 }
112
113 return 0;
114}
115
116MODULE = ByteLoader PACKAGE = ByteLoader
117
118PROTOTYPES: ENABLE
119
120void
121import(...)
22d4bb9c 122 PREINIT:
123 SV *sv = newSVpvn ("", 0);
b295d113 124 PPCODE:
22d4bb9c 125 if (!sv)
126 croak ("Could not allocate ByteLoader buffers");
127 filter_add(byteloader_filter, sv);
b295d113 128
129void
130unimport(...)
131 PPCODE:
132 filter_del(byteloader_filter);