--- JSON-XS/XS.xs 2007/07/01 22:20:00 1.48 +++ JSON-XS/XS.xs 2007/07/01 23:40:07 1.49 @@ -27,11 +27,12 @@ #define F_ALLOW_NONREF 0x00000100UL #define F_SHRINK 0x00000200UL #define F_ALLOW_BLESSED 0x00000400UL -#define F_CONV_BLESSED 0x00000800UL // NYI +#define F_CONV_BLESSED 0x00000800UL #define F_MAXDEPTH 0xf8000000UL #define S_MAXDEPTH 27 #define F_MAXSIZE 0x01f00000UL #define S_MAXSIZE 20 +#define F_HOOK 0x00080000UL // some hooks exist, so slow-path processing #define DEC_DEPTH(flags) (1UL << ((flags & F_MAXDEPTH) >> S_MAXDEPTH)) #define DEC_SIZE(flags) (1UL << ((flags & F_MAXSIZE ) >> S_MAXSIZE )) @@ -63,6 +64,7 @@ typedef struct { U32 flags; + SV *cb_object, *cb_sk_object; } JSON; ///////////////////////////////////////////////////////////////////////////// @@ -492,10 +494,7 @@ if (to_json) { - dSP; - ENTER; - SAVETMPS; - PUSHMARK (SP); + dSP; ENTER; SAVETMPS; PUSHMARK (SP); XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), SvSTASH (sv))); // calling with G_SCALAR ensures that we always get a 1 reutrn value @@ -506,8 +505,7 @@ encode_sv (enc, POPs); - FREETMPS; - LEAVE; + FREETMPS; LEAVE; } else if (enc->json.flags & F_ALLOW_BLESSED) encode_str (enc, "null", 4, 0); @@ -1010,6 +1008,7 @@ static SV * decode_hv (dec_t *dec) { + SV *sv; HV *hv = newHV (); DEC_INC_DEPTH; @@ -1093,6 +1092,46 @@ } DEC_DEC_DEPTH; + sv = newRV_noinc ((SV *)hv); + + // check filter callbacks + if (dec->json.flags & F_HOOK) + { + ENTER; SAVETMPS; + + if (HvKEYS (hv) == 1 && dec->json.cb_sk_object) + { + int count; + + dSP; PUSHMARK (SP); + XPUSHs (sv_2mortal (sv)); + + PUTBACK; count = call_sv (dec->json.cb_sk_object, G_ARRAY); SPAGAIN; + + if (count == 1) + sv = newSVsv (POPs); + else + SvREFCNT_inc (sv); + } + + if (dec->json.cb_object) + { + int count; + + dSP; ENTER; SAVETMPS; PUSHMARK (SP); + XPUSHs (sv_2mortal (sv)); + + PUTBACK; count = call_sv (dec->json.cb_object, G_ARRAY); SPAGAIN; + + if (count == 1) + sv = newSVsv (POPs); + else + SvREFCNT_inc (sv); + } + + FREETMPS; LEAVE; + } + return newRV_noinc ((SV *)hv); fail: @@ -1189,6 +1228,9 @@ dec.depth = 0; dec.maxdepth = DEC_DEPTH (dec.json.flags); + if (dec.json.cb_object || dec.json.cb_sk_object) + dec.json.flags |= F_HOOK; + *dec.end = 0; // this should basically be a nop, too, but make sure it's there sv = decode_sv (&dec); @@ -1272,7 +1314,7 @@ { SV *pv = NEWSV (0, sizeof (JSON)); SvPOK_only (pv); - Zero (SvPVX (pv), 1, sizeof (JSON)); + Zero (SvPVX (pv), 1, JSON); ((JSON *)SvPVX (pv))->flags = F_DEFAULT; XPUSHs (sv_2mortal (sv_bless (newRV_noinc (pv), json_stash))); } @@ -1331,6 +1373,23 @@ XPUSHs (ST (0)); } + +void filter_json_objects (JSON *self, SV *cb = &PL_sv_undef) + ALIAS: + filter_sk_json_objects = 1 + PPCODE: +{ + if (!SvOK (cb)) + cb = 0; + + switch (ix) + { + case 0: self->cb_object = cb; break; + case 1: self->cb_sk_object = cb; break; + } + + XPUSHs (ST (0)); +} void encode (JSON *self, SV *scalar) PPCODE: