--- Compress-LZF/LZF.xs 2001/09/27 18:36:34 1.1 +++ Compress-LZF/LZF.xs 2002/03/03 04:45:18 1.9 @@ -10,6 +10,9 @@ static STRLEN nolen_na; # define SvPV_nolen(sv) SvPV ((sv), nolen_na) #endif +#if PATCHLEVEL < 6 +# define call_sv perl_call_sv +#endif #include "lzf_c.c" #include "lzf_d.c" @@ -18,8 +21,11 @@ #define MAGIC_LO 0 #define MAGIC_U 0 /* uncompressed data follows */ #define MAGIC_C 1 /* compressed data follows */ -#define MAGIC_R 4 /* storable (reference, freeze) */ +#define MAGIC_undef 2 /* the special value undef */ #define MAGIC_CR 3 /* storable (reference, freeze), compressed */ +#define MAGIC_R 4 /* storable (reference, freeze) */ +#define MAGIC_CR_deref 5 /* storable (NO reference, freeze), compressed */ +#define MAGIC_R_deref 6 /* storable NO (reference, freeze) */ #define MAGIC_HI 7 /* room for one higher storable major */ #define IN_RANGE(v,l,h) ((unsigned int)((unsigned)(v) - (unsigned)(l)) <= (unsigned)(h) - (unsigned)(l)) @@ -187,7 +193,11 @@ static void need_storable(void) { +#if PATCHLEVEL < 6 + perl_eval_pv ("require Storable;", 1); +#else load_module (PERL_LOADMOD_NOIMPORT, newSVpv ("Storable", 0), Nullsv); +#endif storable_mstore = GvCV (gv_fetchpv ("Storable::mstore" , TRUE, SVt_PVCV)); storable_mretrieve = GvCV (gv_fetchpv ("Storable::mretrieve", TRUE, SVt_PVCV)); @@ -218,11 +228,20 @@ PROTOTYPE: $ PPCODE: - if (SvROK (sv)) /* mstore */ + if (!SvOK (sv)) + XPUSHs (sv_2mortal (newSVpvn ("\02", 1))); /* 02 == MAGIC_undef */ + else if (SvTYPE(sv) != SVt_IV + && SvTYPE(sv) != SVt_NV + && SvTYPE(sv) != SVt_PV) /* mstore */ { + int deref = !SvROK (sv); + if (!storable_mstore) need_storable (); + if (deref) + sv = newRV_noinc (sv); + PUSHMARK (SP); XPUSHs (sv); PUTBACK; @@ -238,11 +257,16 @@ croak ("Storable format changed, need newer version of Compress::LZF"); if (ix) /* compress */ - XPUSHs (sv_2mortal (compress_sv (sv, MAGIC_CR, 0))); + XPUSHs (sv_2mortal (compress_sv (sv, deref ? MAGIC_CR_deref : MAGIC_CR, 0))); else - XPUSHs (sv); + { + if (deref) + SvPVX (sv)[0] = MAGIC_R_deref; + + XPUSHs (sv); + } } - else if (IN_RANGE (SvPVX (sv)[0], MAGIC_LO, MAGIC_HI)) + else if (sv && IN_RANGE (SvPVX (sv)[0], MAGIC_LO, MAGIC_HI)) XPUSHs (sv_2mortal (compress_sv (sv, MAGIC_C, 1))); /* need to prefix only */ else if (ix == 2) /* compress always */ XPUSHs (sv_2mortal (compress_sv (sv, MAGIC_C, 0))); @@ -254,12 +278,18 @@ SV * sv PROTOTYPE: $ PPCODE: - char hdr = SvPVX (sv)[0]; - if (IN_RANGE (hdr, MAGIC_LO, MAGIC_HI)) + int deref = 0; + + SvGETMAGIC (sv); + if (SvPOK (sv) && IN_RANGE (SvPV_nolen (sv)[0], MAGIC_LO, MAGIC_HI)) { switch (SvPVX (sv)[0]) { + case MAGIC_undef: + XPUSHs (sv_2mortal (NEWSV (0, 0))); + break; + case MAGIC_U: XPUSHs (sv_2mortal (decompress_sv (sv, 0))); break; @@ -268,8 +298,16 @@ XPUSHs (sv_2mortal (decompress_sv (sv, 1))); break; + case MAGIC_CR_deref: + deref = 1; case MAGIC_CR: sv = sv_2mortal (decompress_sv (sv, 1)); /* mortal could be optimized */ + case MAGIC_R_deref: + if (SvPVX (sv)[0] == MAGIC_R_deref) + { + deref = 1; + SvPVX (sv)[0] = MAGIC_R; + } case MAGIC_R: if (!storable_mstore) need_storable (); @@ -283,7 +321,18 @@ SPAGAIN; - /*XPUSHs (POPs);*/ + if (deref) + { + SV *ref = SvREFCNT_inc (SvRV (TOPs)); + + SvREFCNT_dec (TOPs); /* destroy superfluous ref */ + SETs (ref); + + if (SvPVX (sv)[0] == MAGIC_R) + SvPVX (sv)[0] = MAGIC_R; + } + + XPUSHs (POPs); /* this is a nop, hopefully */ break;