--- JSON-XS/XS.xs 2016/02/21 15:37:53 1.125 +++ JSON-XS/XS.xs 2016/02/21 16:18:19 1.126 @@ -81,16 +81,18 @@ #ifdef USE_ITHREADS # define JSON_SLOW 1 # define JSON_STASH (json_stash ? json_stash : gv_stashpv ("JSON::XS", 1)) +# define BOOL_STASH (bool_stash ? bool_stash : gv_stashpv ("Types::Serialiser::Boolean", 1)) #else # define JSON_SLOW 0 # define JSON_STASH json_stash +# define BOOL_STASH bool_stash #endif // the amount of HEs to allocate on the stack, when sorting keys #define STACK_HES 64 -static HV *json_stash, *types_boolean_stash; // JSON::XS:: -static SV *types_true, *types_false, *sv_json; +static HV *json_stash, *bool_stash; // JSON::XS::, Types::Serialiser::Boolean:: +static SV *bool_true, *bool_false, *sv_json; enum { INCR_M_WS = 0, // initial whitespace skipping, must be 0 @@ -301,6 +303,47 @@ return neg ? -accum : accum; } + +// target of scalar reference is bool? -1 == nope, 0 == false, 1 == true +static int +ref_bool_type (SV *sv) +{ + svtype svt = SvTYPE (sv); + + if (svt < SVt_PVAV) + { + STRLEN len = 0; + char *pv = svt ? SvPV (sv, len) : 0; + + if (len == 1) + if (*pv == '1') + return 1; + else if (*pv == '0') + return 0; + + } + + return -1; +} + +// returns whether scalar is not a reference in the sense of allow_nonref +static int +json_nonref (SV *scalar) +{ + if (!SvROK (scalar)) + return 1; + + scalar = SvRV (scalar); + + if (SvSTASH (scalar) == bool_stash) + return 1; + + if (!SvOBJECT (scalar) && ref_bool_type (scalar) >= 0) + return 1; + + return 0; +} + ///////////////////////////////////////////////////////////////////////////// // encoder @@ -703,12 +746,9 @@ if (expect_false (SvOBJECT (sv))) { - HV *boolean_stash = !JSON_SLOW || types_boolean_stash - ? types_boolean_stash - : gv_stashpv ("Types::Serialiser::Boolean", 1); HV *stash = SvSTASH (sv); - if (stash == boolean_stash) + if (stash == bool_stash) { if (SvIV (sv)) encode_str (enc, "true", 4, 0); @@ -792,12 +832,11 @@ encode_av (enc, (AV *)sv); else if (svt < SVt_PVAV) { - STRLEN len = 0; - char *pv = svt ? SvPV (sv, len) : 0; + int bool_type = ref_bool_type (sv); - if (len == 1 && *pv == '1') + if (bool_type == 1) encode_str (enc, "true", 4, 0); - else if (len == 1 && *pv == '0') + else if (bool_type == 0) encode_str (enc, "false", 5, 0); else if (enc->json.flags & F_ALLOW_UNKNOWN) encode_str (enc, "null", 4, 0); @@ -885,20 +924,12 @@ SvPV_nolen (sv), (unsigned int)SvFLAGS (sv)); } -static int -json_scalar (SV *scalar) -{ - return 0;//D - if (!SvROK (scalar)) - return 1; -} - static SV * encode_json (SV *scalar, JSON *json) { enc_t enc; - if (!(json->flags & F_ALLOW_NONREF) && json_scalar (scalar)) + if (!(json->flags & F_ALLOW_NONREF) && json_nonref (scalar)) croak ("hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)"); enc.json = *json; @@ -1614,9 +1645,9 @@ { dec->cur += 4; #if JSON_SLOW - types_true = get_bool ("Types::Serialiser::true"); + bool_true = get_bool ("Types::Serialiser::true"); #endif - return newSVsv (types_true); + return newSVsv (bool_true); } else ERR ("'true' expected"); @@ -1628,9 +1659,9 @@ { dec->cur += 5; #if JSON_SLOW - types_false = get_bool ("Types::Serialiser::false"); + bool_false = get_bool ("Types::Serialiser::false"); #endif - return newSVsv (types_false); + return newSVsv (bool_false); } else ERR ("'false' expected"); @@ -1754,7 +1785,7 @@ sv = sv_2mortal (sv); - if (!(dec.json.flags & F_ALLOW_NONREF) && !SvROK (sv)) + if (!(dec.json.flags & F_ALLOW_NONREF) && json_nonref (sv)) croak ("JSON text must be an object or array (but found number, string, true, false or null, use allow_nonref to allow this)"); return sv; @@ -1934,11 +1965,10 @@ : i >= 'A' && i <= 'F' ? i - 'A' + 10 : -1; - json_stash = gv_stashpv ("JSON::XS" , 1); - types_boolean_stash = gv_stashpv ("Types::Serialiser::Boolean", 1); - - types_true = get_bool ("Types::Serialiser::true"); - types_false = get_bool ("Types::Serialiser::false"); + json_stash = gv_stashpv ("JSON::XS" , 1); + bool_stash = gv_stashpv ("Types::Serialiser::Boolean", 1); + bool_true = get_bool ("Types::Serialiser::true"); + bool_false = get_bool ("Types::Serialiser::false"); sv_json = newSVpv ("JSON", 0); SvREADONLY_on (sv_json); @@ -1950,8 +1980,8 @@ void CLONE (...) CODE: - json_stash = 0; - types_boolean_stash = 0; + json_stash = 0; + bool_stash = 0; void new (char *klass) PPCODE: