--- JSON-XS/XS.xs 2007/07/02 00:48:18 1.51 +++ JSON-XS/XS.xs 2007/07/02 02:57:11 1.52 @@ -64,7 +64,8 @@ typedef struct { U32 flags; - SV *cb_object, *cb_sk_object; + SV *cb_object; + HV *cb_sk_object; } JSON; ///////////////////////////////////////////////////////////////////////////// @@ -1100,29 +1101,43 @@ // check filter callbacks if (dec->json.flags & F_HOOK) { - ENTER; SAVETMPS; - if (dec->json.cb_sk_object && HvKEYS (hv) == 1) { - int count; + HE *cb, *he; - dSP; PUSHMARK (SP); - XPUSHs (sv_2mortal (sv)); + hv_iterinit (hv); + he = hv_iternext (hv); + hv_iterinit (hv); - PUTBACK; count = call_sv (dec->json.cb_sk_object, G_ARRAY); SPAGAIN; + // the next line creates a mortal sv each time its called. + // might want to optimise this for common cases. + cb = hv_fetch_ent (dec->json.cb_sk_object, hv_iterkeysv (he), 0, 0); - if (count == 1) + if (cb) { - sv = newSVsv (POPs); - goto filter_ok; - } + int count; + ENTER; SAVETMPS; - SvREFCNT_inc (sv); + dSP; PUSHMARK (SP); + XPUSHs (HeVAL (he)); + + PUTBACK; count = call_sv (HeVAL (cb), G_ARRAY); SPAGAIN; + + if (count == 1) + { + sv = newSVsv (POPs); + FREETMPS; LEAVE; + return sv; + } + + FREETMPS; LEAVE; + } } if (dec->json.cb_object) { int count; + ENTER; SAVETMPS; dSP; ENTER; SAVETMPS; PUSHMARK (SP); XPUSHs (sv_2mortal (sv)); @@ -1132,14 +1147,13 @@ if (count == 1) { sv = newSVsv (POPs); - goto filter_ok; + FREETMPS; LEAVE; + return sv; } SvREFCNT_inc (sv); + FREETMPS; LEAVE; } - -filter_ok: - FREETMPS; LEAVE; } return sv; @@ -1385,27 +1399,32 @@ } void filter_json_object (JSON *self, SV *cb = &PL_sv_undef) - ALIAS: - filter_json_single_key_object = 1 PPCODE: { - SV **svp; + SvREFCNT_dec (self->cb_object); + self->cb_object = SvOK (cb) ? newSVsv (cb) : 0; - if (!SvOK (cb)) - cb = 0; - else - cb = newSVsv (cb); + XPUSHs (ST (0)); +} - switch (ix) - { - case 0: svp = &self->cb_object ; break; - case 1: svp = &self->cb_sk_object; break; - } +void filter_json_single_key_object (JSON *self, SV *key, SV *cb = &PL_sv_undef) + PPCODE: +{ + if (!self->cb_sk_object) + self->cb_sk_object = newHV (); - if (*svp) - SvREFCNT_dec (*svp); + if (SvOK (cb)) + hv_store_ent (self->cb_sk_object, key, newSVsv (cb), 0); + else + { + hv_delete_ent (self->cb_sk_object, key, G_DISCARD, 0); - *svp = cb; + if (!HvKEYS (self->cb_sk_object)) + { + SvREFCNT_dec (self->cb_sk_object); + self->cb_sk_object = 0; + } + } XPUSHs (ST (0)); } @@ -1427,6 +1446,11 @@ PUSHs (sv_2mortal (newSVuv (offset))); } +void DESTROY (JSON *self) + CODE: + SvREFCNT_dec (self->cb_sk_object); + SvREFCNT_dec (self->cb_object); + PROTOTYPES: ENABLE void to_json (SV *scalar)