X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=ext%2FByteLoader%2FByteLoader.xs;h=e71b7cdb9bbe5c36fb6d12b9fc8a3dffb592b44b;hb=01b509b0993b5dd659665407a96cb80ea8da0cab;hp=24c3ae8492ebf4c02d200e5a29c986dcf1d9e339;hpb=a6c403648ecd5cc72235fdb1e7535523a8ff2ac9;p=p5sagit%2Fp5-mst-13.2.git diff --git a/ext/ByteLoader/ByteLoader.xs b/ext/ByteLoader/ByteLoader.xs index 24c3ae8..e71b7cd 100644 --- a/ext/ByteLoader/ByteLoader.xs +++ b/ext/ByteLoader/ByteLoader.xs @@ -1,39 +1,105 @@ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" +#include "byterun.h" -#ifndef WIN32 -/* this is probably not needed manywhere */ -# include "byterun.c" -#endif +/* Something arbitary for a buffer size */ +#define BYTELOADER_BUFFER 8096 -/* defgv must be accessed differently under threaded perl */ -/* DEFSV et al are in 5.004_56 */ -#ifndef DEFSV -#define DEFSV GvSV(defgv) -#endif +int +bl_getc(struct byteloader_fdata *data) +{ + 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(int idx, SV *buf_sv, int maxlen) -#endif +byteloader_filter(pTHX_ int idx, SV *buf_sv, int maxlen) { - dTHR; OP *saveroot = PL_main_root; OP *savestart = PL_main_start; + struct byteloader_state bstate; + struct byteloader_fdata data; + int len; -#ifdef INDIRECT_BGET_MACROS - struct bytesream bs; + 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; -#else - byterun(PL_rsfp); -#endif + 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; @@ -58,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);