This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
ext/ + -Wall
[perl5.git] / ext / ByteLoader / ByteLoader.xs
CommitLineData
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
10int
11bl_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
33int
34bl_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
77static I32
0cb96387 78byteloader_filter(pTHXo_ 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
059a8bb7 95 byterun(aTHXo_ &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
115MODULE = ByteLoader PACKAGE = ByteLoader
116
117PROTOTYPES: ENABLE
118
119void
c6c619a9
DM
120import(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
129void
c6c619a9
DM
130unimport(package="ByteLoader", ...)
131 char *package
b295d113
TH
132 PPCODE:
133 filter_del(byteloader_filter);