--- JSON-XS/XS.xs 2007/08/13 16:19:13 1.60 +++ JSON-XS/XS.xs 2007/08/26 21:56:47 1.61 @@ -337,7 +337,7 @@ } static void -encode_he (enc_t *enc, HE *he) +encode_hk (enc_t *enc, HE *he) { encode_ch (enc, '"'); @@ -360,7 +360,6 @@ if (enc->json.flags & F_SPACE_BEFORE) encode_space (enc); encode_ch (enc, ':'); if (enc->json.flags & F_SPACE_AFTER ) encode_space (enc); - encode_sv (enc, HeVAL (he)); } // compare hash entries, used when all keys are bytestrings @@ -375,8 +374,8 @@ STRLEN la = HeKLEN (a); STRLEN lb = HeKLEN (b); - if (!(cmp = memcmp (HeKEY (a), HeKEY (b), la < lb ? la : lb))) - cmp = la - lb; + if (!(cmp = memcmp (HeKEY (b), HeKEY (a), lb < la ? lb : la))) + cmp = lb - la; return cmp; } @@ -385,29 +384,45 @@ static int he_cmp_slow (const void *a, const void *b) { - return sv_cmp (HeSVKEY_force (*(HE **)a), HeSVKEY_force (*(HE **)b)); + return sv_cmp (HeSVKEY_force (*(HE **)b), HeSVKEY_force (*(HE **)a)); } static void encode_hv (enc_t *enc, HV *hv) { - int count, i; + HE *he; + int count; if (enc->indent >= enc->maxdepth) croak ("data structure too deep (hit recursion limit)"); encode_ch (enc, '{'); encode_nl (enc); ++enc->indent; - if ((count = hv_iterinit (hv))) + // for canonical output we have to sort by keys first + // actually, this is mostly due to the stupid so-called + // security workaround added somewhere in 5.8.x. + // that randomises hash orderings + if (enc->json.flags & F_CANONICAL) { - // for canonical output we have to sort by keys first - // actually, this is mostly due to the stupid so-called - // security workaround added somewhere in 5.8.x. - // that randomises hash orderings - if (enc->json.flags & F_CANONICAL) + int count = hv_iterinit (hv); + + if (SvMAGICAL (hv)) { - int fast = 1; - HE *he; + // need to count by iterating. could improve by dynamically building the vector below + // but I don't care for the speed of this special case. + // note also that we will run into undefined behaviour when the two iterations + // do not result in the same count, something I might care for in some later release. + + count = 0; + while (hv_iternext (hv)) + ++count; + + hv_iterinit (hv); + } + + if (count) + { + int i, fast = 1; #if defined(__BORLANDC__) || defined(_MSC_VER) HE **hes = _alloca (count * sizeof (HE)); #else @@ -444,36 +459,37 @@ LEAVE; } - for (i = 0; i < count; ++i) + while (count--) { encode_indent (enc); - encode_he (enc, hes [i]); + he = hes [count]; + encode_hk (enc, he); + encode_sv (enc, SvMAGICAL (hv) ? hv_iterval (hv, he) : HeVAL (he)); - if (i < count - 1) + if (count) encode_comma (enc); } - - encode_nl (enc); } - else - { - HE *he = hv_iternext (hv); - + } + else + { + if (hv_iterinit (hv) || SvMAGICAL (hv)) + if ((he = hv_iternext (hv))) for (;;) { encode_indent (enc); - encode_he (enc, he); + encode_hk (enc, he); + encode_sv (enc, SvMAGICAL (hv) ? hv_iterval (hv, he) : HeVAL (he)); if (!(he = hv_iternext (hv))) break; encode_comma (enc); } - - encode_nl (enc); - } } + encode_nl (enc); + --enc->indent; encode_indent (enc); encode_ch (enc, '}'); }