X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FByteLoader%2FByteLoader.xs;h=e71b7cdb9bbe5c36fb6d12b9fc8a3dffb592b44b;hb=01b509b0993b5dd659665407a96cb80ea8da0cab;hp=34002f12b2a84c5fe68d5bcbadb80e92b3d73033;hpb=4f63d0249796d635a70b03245ad972152a3eba76;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/ByteLoader/ByteLoader.xs b/ext/ByteLoader/ByteLoader.xs index 34002f1..e71b7cd 100644 --- a/ext/ByteLoader/ByteLoader.xs +++ b/ext/ByteLoader/ByteLoader.xs @@ -3,33 +3,103 @@ #include "XSUB.h" #include "byterun.h" -static void -freadpv(U32 len, void *data, XPV *pv) +/* Something arbitary for a buffer size */ +#define BYTELOADER_BUFFER 8096 + +int +bl_getc(struct byteloader_fdata *data) { - New(666, pv->xpv_pv, len, char); - fread(pv->xpv_pv, 1, len, (FILE*)data); - pv->xpv_len = len; - pv->xpv_cur = len - 1; + dTHX; + if (SvCUR(data->datasv) <= (STRLEN)data->next_out) { + int result; + /* Run out of buffered data, so attempt to read some more */ + *(SvPV_nolen (data->datasv)) = '\0'; + SvCUR_set (data->datasv, 0); + data->next_out = 0; + result = FILTER_READ (data->idx + 1, data->datasv, BYTELOADER_BUFFER); + + /* Filter returned error, or we got EOF and no data, then return EOF. + Not sure if filter is allowed to return EOF and add data simultaneously + Think not, but will bullet proof against it. */ + if (result < 0 || SvCUR(data->datasv) == 0) + return EOF; + /* Else there must be at least one byte present, which is good enough */ + } + + return *((U8 *) SvPV_nolen (data->datasv) + data->next_out++); +} + +int +bl_read(struct byteloader_fdata *data, char *buf, size_t size, size_t n) +{ + dTHX; + char *start; + STRLEN len; + size_t wanted = size * n; + + start = SvPV (data->datasv, len); + if (len < (data->next_out + wanted)) { + int result; + + /* Shuffle data to start of buffer */ + len -= data->next_out; + if (len) { + memmove (start, start + data->next_out, len + 1); + SvCUR_set (data->datasv, len); + } else { + *start = '\0'; /* Avoid call to memmove. */ + SvCUR_set (data->datasv, 0); + } + data->next_out = 0; + + /* Attempt to read more data. */ + do { + result = FILTER_READ (data->idx + 1, data->datasv, BYTELOADER_BUFFER); + + start = SvPV (data->datasv, len); + } while (result > 0 && len < wanted); + /* Loop while not (EOF || error) and short reads */ + + /* If not enough data read, truncate copy */ + if (wanted > len) + wanted = len; + } + + if (wanted > 0) { + memcpy (buf, start + data->next_out, wanted); + data->next_out += wanted; + wanted /= size; + } + return (int) wanted; } static I32 -#ifdef PERL_OBJECT -byteloader_filter(CPerlObj *pPerl, int idx, SV *buf_sv, int maxlen) -#else byteloader_filter(pTHX_ int idx, SV *buf_sv, int maxlen) -#endif { - dTHR; OP *saveroot = PL_main_root; OP *savestart = PL_main_start; - struct bytestream bs; + struct byteloader_state bstate; + struct byteloader_fdata data; + int len; - bs.data = PL_rsfp; - bs.pfgetc = (int(*) (void*))fgetc; - bs.pfread = (int(*) (char*,size_t,size_t,void*))fread; - bs.pfreadpv = freadpv; + data.next_out = 0; + data.datasv = FILTER_DATA(idx); + data.idx = idx; - byterun(bs); + bstate.bs_fdata = &data; + bstate.bs_obj_list = Null(void**); + bstate.bs_obj_list_fill = -1; + bstate.bs_sv = Nullsv; + bstate.bs_iv_overflows = 0; + +/* KLUDGE */ + if (byterun(aTHX_ &bstate) + && (len = SvCUR(data.datasv) - (STRLEN)data.next_out)) + { + PerlIO_seek(PL_rsfp, -len, SEEK_CUR); + PL_rsfp = NULL; + } + filter_del(byteloader_filter); if (PL_in_eval) { OP *o; @@ -54,11 +124,11 @@ MODULE = ByteLoader PACKAGE = ByteLoader PROTOTYPES: ENABLE void -import(...) +import(package="ByteLoader", ...) + char *package + PREINIT: + SV *sv = newSVpvn ("", 0); PPCODE: - filter_add(byteloader_filter, NULL); - -void -unimport(...) - PPCODE: - filter_del(byteloader_filter); + if (!sv) + croak ("Could not allocate ByteLoader buffers"); + filter_add(byteloader_filter, sv);