source: trunk/essentials/dev-lang/perl/ext/ByteLoader/ByteLoader.xs

Last change on this file was 3181, checked in by bird, 18 years ago

perl 5.8.8

File size: 3.3 KB
Line 
1#include "EXTERN.h"
2#include "perl.h"
3#include "XSUB.h"
4#include "byterun.h"
5
6/* Something arbitary for a buffer size */
7#define BYTELOADER_BUFFER 8096
8
9int
10bl_getc(struct byteloader_fdata *data)
11{
12 dTHX;
13 if (SvCUR(data->datasv) <= (STRLEN)data->next_out) {
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
29 return *((U8 *) SvPV_nolen (data->datasv) + data->next_out++);
30}
31
32int
33bl_read(struct byteloader_fdata *data, char *buf, size_t size, size_t n)
34{
35 dTHX;
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);
48 } else {
49 *start = '\0'; /* Avoid call to memmove. */
50 }
51 SvCUR_set(data->datasv, len);
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;
73}
74
75static I32
76byteloader_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
77{
78 OP *saveroot = PL_main_root;
79 OP *savestart = PL_main_start;
80 struct byteloader_state bstate;
81 struct byteloader_fdata data;
82 int len;
83 (void)buf_sv;
84 (void)maxlen;
85
86 data.next_out = 0;
87 data.datasv = FILTER_DATA(idx);
88 data.idx = idx;
89
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;
95
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);
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
123MODULE = ByteLoader PACKAGE = ByteLoader
124
125PROTOTYPES: ENABLE
126
127void
128import(package="ByteLoader", ...)
129 char *package
130 PREINIT:
131 SV *sv = newSVpvn ("", 0);
132 PPCODE:
133 if (!sv)
134 croak ("Could not allocate ByteLoader buffers");
135 filter_add(byteloader_filter, sv);
Note: See TracBrowser for help on using the repository browser.