X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FByteLoader%2FByteLoader.xs;h=4588b02ef09344cdb1e24657e2a17d16389161f1;hb=65575be5af9681bf691b8b72b0e5b7f432a867bf;hp=e927d16f31770bf02a5d194df8621f6f97f528d2;hpb=cea2e8a9dd23747fd2b66edc86c58c64e9970321;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/ByteLoader/ByteLoader.xs b/ext/ByteLoader/ByteLoader.xs index e927d16..4588b02 100644 --- a/ext/ByteLoader/ByteLoader.xs +++ b/ext/ByteLoader/ByteLoader.xs @@ -1,35 +1,98 @@ +#define PERL_NO_GET_CONTEXT #include "EXTERN.h" #include "perl.h" #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 *((char *) 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; + + data.next_out = 0; + data.datasv = FILTER_DATA(idx); + data.idx = idx; - bs.data = PL_rsfp; - bs.fgetc = (int(*) (void*))fgetc; - bs.fread = (int(*) (char*,size_t,size_t,void*))fread; - bs.freadpv = freadpv; + 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; - byterun(bs); + byterun(aTHX_ &bstate); if (PL_in_eval) { OP *o; @@ -54,11 +117,17 @@ MODULE = ByteLoader PACKAGE = ByteLoader PROTOTYPES: ENABLE void -import(...) +import(package="ByteLoader", ...) + char *package + PREINIT: + SV *sv = newSVpvn ("", 0); PPCODE: - filter_add(byteloader_filter, NULL); + if (!sv) + croak ("Could not allocate ByteLoader buffers"); + filter_add(byteloader_filter, sv); void -unimport(...) +unimport(package="ByteLoader", ...) + char *package PPCODE: filter_del(byteloader_filter);