… | |
… | |
335 | --enc->indent; |
335 | --enc->indent; |
336 | encode_indent (enc); encode_ch (enc, ']'); |
336 | encode_indent (enc); encode_ch (enc, ']'); |
337 | } |
337 | } |
338 | |
338 | |
339 | static void |
339 | static void |
340 | encode_he (enc_t *enc, HE *he) |
340 | encode_hk (enc_t *enc, HE *he) |
341 | { |
341 | { |
342 | encode_ch (enc, '"'); |
342 | encode_ch (enc, '"'); |
343 | |
343 | |
344 | if (HeKLEN (he) == HEf_SVKEY) |
344 | if (HeKLEN (he) == HEf_SVKEY) |
345 | { |
345 | { |
… | |
… | |
358 | encode_ch (enc, '"'); |
358 | encode_ch (enc, '"'); |
359 | |
359 | |
360 | if (enc->json.flags & F_SPACE_BEFORE) encode_space (enc); |
360 | if (enc->json.flags & F_SPACE_BEFORE) encode_space (enc); |
361 | encode_ch (enc, ':'); |
361 | encode_ch (enc, ':'); |
362 | if (enc->json.flags & F_SPACE_AFTER ) encode_space (enc); |
362 | if (enc->json.flags & F_SPACE_AFTER ) encode_space (enc); |
363 | encode_sv (enc, HeVAL (he)); |
|
|
364 | } |
363 | } |
365 | |
364 | |
366 | // compare hash entries, used when all keys are bytestrings |
365 | // compare hash entries, used when all keys are bytestrings |
367 | static int |
366 | static int |
368 | he_cmp_fast (const void *a_, const void *b_) |
367 | he_cmp_fast (const void *a_, const void *b_) |
… | |
… | |
373 | HE *b = *(HE **)b_; |
372 | HE *b = *(HE **)b_; |
374 | |
373 | |
375 | STRLEN la = HeKLEN (a); |
374 | STRLEN la = HeKLEN (a); |
376 | STRLEN lb = HeKLEN (b); |
375 | STRLEN lb = HeKLEN (b); |
377 | |
376 | |
378 | if (!(cmp = memcmp (HeKEY (a), HeKEY (b), la < lb ? la : lb))) |
377 | if (!(cmp = memcmp (HeKEY (b), HeKEY (a), lb < la ? lb : la))) |
379 | cmp = la - lb; |
378 | cmp = lb - la; |
380 | |
379 | |
381 | return cmp; |
380 | return cmp; |
382 | } |
381 | } |
383 | |
382 | |
384 | // compare hash entries, used when some keys are sv's or utf-x |
383 | // compare hash entries, used when some keys are sv's or utf-x |
385 | static int |
384 | static int |
386 | he_cmp_slow (const void *a, const void *b) |
385 | he_cmp_slow (const void *a, const void *b) |
387 | { |
386 | { |
388 | return sv_cmp (HeSVKEY_force (*(HE **)a), HeSVKEY_force (*(HE **)b)); |
387 | return sv_cmp (HeSVKEY_force (*(HE **)b), HeSVKEY_force (*(HE **)a)); |
389 | } |
388 | } |
390 | |
389 | |
391 | static void |
390 | static void |
392 | encode_hv (enc_t *enc, HV *hv) |
391 | encode_hv (enc_t *enc, HV *hv) |
393 | { |
392 | { |
|
|
393 | HE *he; |
394 | int count, i; |
394 | int count; |
395 | |
395 | |
396 | if (enc->indent >= enc->maxdepth) |
396 | if (enc->indent >= enc->maxdepth) |
397 | croak ("data structure too deep (hit recursion limit)"); |
397 | croak ("data structure too deep (hit recursion limit)"); |
398 | |
398 | |
399 | encode_ch (enc, '{'); encode_nl (enc); ++enc->indent; |
399 | encode_ch (enc, '{'); encode_nl (enc); ++enc->indent; |
400 | |
400 | |
401 | if ((count = hv_iterinit (hv))) |
|
|
402 | { |
|
|
403 | // for canonical output we have to sort by keys first |
401 | // for canonical output we have to sort by keys first |
404 | // actually, this is mostly due to the stupid so-called |
402 | // actually, this is mostly due to the stupid so-called |
405 | // security workaround added somewhere in 5.8.x. |
403 | // security workaround added somewhere in 5.8.x. |
406 | // that randomises hash orderings |
404 | // that randomises hash orderings |
407 | if (enc->json.flags & F_CANONICAL) |
405 | if (enc->json.flags & F_CANONICAL) |
|
|
406 | { |
|
|
407 | int count = hv_iterinit (hv); |
|
|
408 | |
|
|
409 | if (SvMAGICAL (hv)) |
408 | { |
410 | { |
|
|
411 | // need to count by iterating. could improve by dynamically building the vector below |
|
|
412 | // but I don't care for the speed of this special case. |
|
|
413 | // note also that we will run into undefined behaviour when the two iterations |
|
|
414 | // do not result in the same count, something I might care for in some later release. |
|
|
415 | |
|
|
416 | count = 0; |
|
|
417 | while (hv_iternext (hv)) |
|
|
418 | ++count; |
|
|
419 | |
|
|
420 | hv_iterinit (hv); |
|
|
421 | } |
|
|
422 | |
|
|
423 | if (count) |
|
|
424 | { |
409 | int fast = 1; |
425 | int i, fast = 1; |
410 | HE *he; |
|
|
411 | #if defined(__BORLANDC__) || defined(_MSC_VER) |
426 | #if defined(__BORLANDC__) || defined(_MSC_VER) |
412 | HE **hes = _alloca (count * sizeof (HE)); |
427 | HE **hes = _alloca (count * sizeof (HE)); |
413 | #else |
428 | #else |
414 | HE *hes [count]; // if your compiler dies here, you need to enable C99 mode |
429 | HE *hes [count]; // if your compiler dies here, you need to enable C99 mode |
415 | #endif |
430 | #endif |
… | |
… | |
442 | |
457 | |
443 | FREETMPS; |
458 | FREETMPS; |
444 | LEAVE; |
459 | LEAVE; |
445 | } |
460 | } |
446 | |
461 | |
447 | for (i = 0; i < count; ++i) |
462 | while (count--) |
448 | { |
463 | { |
449 | encode_indent (enc); |
464 | encode_indent (enc); |
|
|
465 | he = hes [count]; |
450 | encode_he (enc, hes [i]); |
466 | encode_hk (enc, he); |
|
|
467 | encode_sv (enc, SvMAGICAL (hv) ? hv_iterval (hv, he) : HeVAL (he)); |
451 | |
468 | |
452 | if (i < count - 1) |
469 | if (count) |
453 | encode_comma (enc); |
470 | encode_comma (enc); |
454 | } |
471 | } |
455 | |
|
|
456 | encode_nl (enc); |
|
|
457 | } |
472 | } |
|
|
473 | } |
458 | else |
474 | else |
459 | { |
475 | { |
|
|
476 | if (hv_iterinit (hv) || SvMAGICAL (hv)) |
460 | HE *he = hv_iternext (hv); |
477 | if ((he = hv_iternext (hv))) |
461 | |
|
|
462 | for (;;) |
478 | for (;;) |
463 | { |
479 | { |
464 | encode_indent (enc); |
480 | encode_indent (enc); |
465 | encode_he (enc, he); |
481 | encode_hk (enc, he); |
|
|
482 | encode_sv (enc, SvMAGICAL (hv) ? hv_iterval (hv, he) : HeVAL (he)); |
466 | |
483 | |
467 | if (!(he = hv_iternext (hv))) |
484 | if (!(he = hv_iternext (hv))) |
468 | break; |
485 | break; |
469 | |
486 | |
470 | encode_comma (enc); |
487 | encode_comma (enc); |
471 | } |
488 | } |
|
|
489 | } |
472 | |
490 | |
473 | encode_nl (enc); |
491 | encode_nl (enc); |
474 | } |
|
|
475 | } |
|
|
476 | |
492 | |
477 | --enc->indent; encode_indent (enc); encode_ch (enc, '}'); |
493 | --enc->indent; encode_indent (enc); encode_ch (enc, '}'); |
478 | } |
494 | } |
479 | |
495 | |
480 | // encode objects, arrays and special \0=false and \1=true values. |
496 | // encode objects, arrays and special \0=false and \1=true values. |