JSON-SIMD

 view release on metacpan or  search on metacpan

SIMD.xs  view on Meta::CPAN


      encode_str (enc, str, len, SvUTF8 (sv));
    }
  else
    encode_str (enc, HeKEY (he), HeKLEN (he), HeKUTF8 (he));

  encode_ch (enc, '"');

  if (enc->json.flags & F_SPACE_BEFORE) encode_space (enc);
  encode_ch (enc, ':');
  if (enc->json.flags & F_SPACE_AFTER ) encode_space (enc);
}

// compare hash entries, used when all keys are bytestrings
static int
he_cmp_fast (const void *a_, const void *b_)
{
  int cmp;

  HE *a = *(HE **)a_;
  HE *b = *(HE **)b_;

  STRLEN la = HeKLEN (a);
  STRLEN lb = HeKLEN (b);

  if (!(cmp = memcmp (HeKEY (b), HeKEY (a), lb < la ? lb : la)))
    cmp = lb - la;

  return cmp;
}

// compare hash entries, used when some keys are sv's or utf-x
static int
he_cmp_slow (const void *a, const void *b)
{
  return sv_cmp (HeSVKEY_force (*(HE **)b), HeSVKEY_force (*(HE **)a));
}

static void
encode_hv (enc_t *enc, HV *hv)
{
  HE *he;

  if (enc->indent >= enc->json.max_depth)
    croak (ERR_NESTING_EXCEEDED);

  encode_ch (enc, '{');

  // 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 && !SvRMAGICAL (hv))
    {
      int count = hv_iterinit (hv);

      if (SvMAGICAL (hv))
        {
          // 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;
          HE *hes_stack [STACK_HES];
          HE **hes = hes_stack;

          // allocate larger arrays on the heap
          if (count > STACK_HES)
            {
              SV *sv = sv_2mortal (NEWSV (0, count * sizeof (*hes)));
              hes = (HE **)SvPVX (sv);
            }

          i = 0;
          while ((he = hv_iternext (hv)))
            {
              hes [i++] = he;
              if (HeKLEN (he) < 0 || HeKUTF8 (he))
                fast = 0;
            }

          assert (i == count);

          if (fast)
            qsort (hes, count, sizeof (HE *), he_cmp_fast);
          else
            {
              // hack to forcefully disable "use bytes"
              COP cop = *PL_curcop;
              cop.op_private = 0;

              ENTER;
              SAVETMPS;

              SAVEVPTR (PL_curcop);
              PL_curcop = &cop;

              qsort (hes, count, sizeof (HE *), he_cmp_slow);

              FREETMPS;
              LEAVE;
            }

          encode_nl (enc); ++enc->indent;

          while (count--)
            {
              encode_indent (enc);
              he = hes [count];
              encode_hk (enc, he);
              encode_sv (enc, expect_false (SvMAGICAL (hv)) ? hv_iterval (hv, he) : HeVAL (he));



( run in 1.759 second using v1.01-cache-2.11-cpan-71847e10f99 )