… | |
… | |
57 | # define inline static |
57 | # define inline static |
58 | #endif |
58 | #endif |
59 | |
59 | |
60 | #define expect_false(expr) expect ((expr) != 0, 0) |
60 | #define expect_false(expr) expect ((expr) != 0, 0) |
61 | #define expect_true(expr) expect ((expr) != 0, 1) |
61 | #define expect_true(expr) expect ((expr) != 0, 1) |
|
|
62 | |
|
|
63 | #ifdef USE_ITHREADS |
|
|
64 | # define JSON_SLOW 1 |
|
|
65 | # define JSON_STASH (json_stash ? json_stash : gv_stashpv ("JSON::XS", 1)) |
|
|
66 | #else |
|
|
67 | # define JSON_SLOW 0 |
|
|
68 | # define JSON_STASH json_stash |
|
|
69 | #endif |
62 | |
70 | |
63 | static HV *json_stash, *json_boolean_stash; // JSON::XS:: |
71 | static HV *json_stash, *json_boolean_stash; // JSON::XS:: |
64 | static SV *json_true, *json_false; |
72 | static SV *json_true, *json_false; |
65 | |
73 | |
66 | typedef struct { |
74 | typedef struct { |
… | |
… | |
327 | --enc->indent; |
335 | --enc->indent; |
328 | encode_indent (enc); encode_ch (enc, ']'); |
336 | encode_indent (enc); encode_ch (enc, ']'); |
329 | } |
337 | } |
330 | |
338 | |
331 | static void |
339 | static void |
332 | encode_he (enc_t *enc, HE *he) |
340 | encode_hk (enc_t *enc, HE *he) |
333 | { |
341 | { |
334 | encode_ch (enc, '"'); |
342 | encode_ch (enc, '"'); |
335 | |
343 | |
336 | if (HeKLEN (he) == HEf_SVKEY) |
344 | if (HeKLEN (he) == HEf_SVKEY) |
337 | { |
345 | { |
… | |
… | |
350 | encode_ch (enc, '"'); |
358 | encode_ch (enc, '"'); |
351 | |
359 | |
352 | if (enc->json.flags & F_SPACE_BEFORE) encode_space (enc); |
360 | if (enc->json.flags & F_SPACE_BEFORE) encode_space (enc); |
353 | encode_ch (enc, ':'); |
361 | encode_ch (enc, ':'); |
354 | if (enc->json.flags & F_SPACE_AFTER ) encode_space (enc); |
362 | if (enc->json.flags & F_SPACE_AFTER ) encode_space (enc); |
355 | encode_sv (enc, HeVAL (he)); |
|
|
356 | } |
363 | } |
357 | |
364 | |
358 | // compare hash entries, used when all keys are bytestrings |
365 | // compare hash entries, used when all keys are bytestrings |
359 | static int |
366 | static int |
360 | he_cmp_fast (const void *a_, const void *b_) |
367 | he_cmp_fast (const void *a_, const void *b_) |
… | |
… | |
365 | HE *b = *(HE **)b_; |
372 | HE *b = *(HE **)b_; |
366 | |
373 | |
367 | STRLEN la = HeKLEN (a); |
374 | STRLEN la = HeKLEN (a); |
368 | STRLEN lb = HeKLEN (b); |
375 | STRLEN lb = HeKLEN (b); |
369 | |
376 | |
370 | if (!(cmp = memcmp (HeKEY (a), HeKEY (b), la < lb ? la : lb))) |
377 | if (!(cmp = memcmp (HeKEY (b), HeKEY (a), lb < la ? lb : la))) |
371 | cmp = la - lb; |
378 | cmp = lb - la; |
372 | |
379 | |
373 | return cmp; |
380 | return cmp; |
374 | } |
381 | } |
375 | |
382 | |
376 | // 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 |
377 | static int |
384 | static int |
378 | he_cmp_slow (const void *a, const void *b) |
385 | he_cmp_slow (const void *a, const void *b) |
379 | { |
386 | { |
380 | return sv_cmp (HeSVKEY_force (*(HE **)a), HeSVKEY_force (*(HE **)b)); |
387 | return sv_cmp (HeSVKEY_force (*(HE **)b), HeSVKEY_force (*(HE **)a)); |
381 | } |
388 | } |
382 | |
389 | |
383 | static void |
390 | static void |
384 | encode_hv (enc_t *enc, HV *hv) |
391 | encode_hv (enc_t *enc, HV *hv) |
385 | { |
392 | { |
|
|
393 | HE *he; |
386 | int count, i; |
394 | int count; |
387 | |
395 | |
388 | if (enc->indent >= enc->maxdepth) |
396 | if (enc->indent >= enc->maxdepth) |
389 | croak ("data structure too deep (hit recursion limit)"); |
397 | croak ("data structure too deep (hit recursion limit)"); |
390 | |
398 | |
391 | encode_ch (enc, '{'); encode_nl (enc); ++enc->indent; |
399 | encode_ch (enc, '{'); encode_nl (enc); ++enc->indent; |
392 | |
400 | |
393 | if ((count = hv_iterinit (hv))) |
|
|
394 | { |
|
|
395 | // for canonical output we have to sort by keys first |
401 | // for canonical output we have to sort by keys first |
396 | // actually, this is mostly due to the stupid so-called |
402 | // actually, this is mostly due to the stupid so-called |
397 | // security workaround added somewhere in 5.8.x. |
403 | // security workaround added somewhere in 5.8.x. |
398 | // that randomises hash orderings |
404 | // that randomises hash orderings |
399 | 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)) |
400 | { |
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 | { |
401 | int fast = 1; |
425 | int i, fast = 1; |
402 | HE *he; |
|
|
403 | #if defined(__BORLANDC__) || defined(_MSC_VER) |
426 | #if defined(__BORLANDC__) || defined(_MSC_VER) |
404 | HE **hes = _alloca (count * sizeof (HE)); |
427 | HE **hes = _alloca (count * sizeof (HE)); |
405 | #else |
428 | #else |
406 | 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 |
407 | #endif |
430 | #endif |
… | |
… | |
434 | |
457 | |
435 | FREETMPS; |
458 | FREETMPS; |
436 | LEAVE; |
459 | LEAVE; |
437 | } |
460 | } |
438 | |
461 | |
439 | for (i = 0; i < count; ++i) |
462 | while (count--) |
440 | { |
463 | { |
441 | encode_indent (enc); |
464 | encode_indent (enc); |
|
|
465 | he = hes [count]; |
442 | encode_he (enc, hes [i]); |
466 | encode_hk (enc, he); |
|
|
467 | encode_sv (enc, expect_false (SvMAGICAL (hv)) ? hv_iterval (hv, he) : HeVAL (he)); |
443 | |
468 | |
444 | if (i < count - 1) |
469 | if (count) |
445 | encode_comma (enc); |
470 | encode_comma (enc); |
446 | } |
471 | } |
447 | |
|
|
448 | encode_nl (enc); |
|
|
449 | } |
472 | } |
|
|
473 | } |
450 | else |
474 | else |
451 | { |
475 | { |
|
|
476 | if (hv_iterinit (hv) || SvMAGICAL (hv)) |
452 | HE *he = hv_iternext (hv); |
477 | if ((he = hv_iternext (hv))) |
453 | |
|
|
454 | for (;;) |
478 | for (;;) |
455 | { |
479 | { |
456 | encode_indent (enc); |
480 | encode_indent (enc); |
457 | encode_he (enc, he); |
481 | encode_hk (enc, he); |
|
|
482 | encode_sv (enc, expect_false (SvMAGICAL (hv)) ? hv_iterval (hv, he) : HeVAL (he)); |
458 | |
483 | |
459 | if (!(he = hv_iternext (hv))) |
484 | if (!(he = hv_iternext (hv))) |
460 | break; |
485 | break; |
461 | |
486 | |
462 | encode_comma (enc); |
487 | encode_comma (enc); |
463 | } |
488 | } |
|
|
489 | } |
464 | |
490 | |
465 | encode_nl (enc); |
491 | encode_nl (enc); |
466 | } |
|
|
467 | } |
|
|
468 | |
492 | |
469 | --enc->indent; encode_indent (enc); encode_ch (enc, '}'); |
493 | --enc->indent; encode_indent (enc); encode_ch (enc, '}'); |
470 | } |
494 | } |
471 | |
495 | |
472 | // encode objects, arrays and special \0=false and \1=true values. |
496 | // encode objects, arrays and special \0=false and \1=true values. |
… | |
… | |
478 | SvGETMAGIC (sv); |
502 | SvGETMAGIC (sv); |
479 | svt = SvTYPE (sv); |
503 | svt = SvTYPE (sv); |
480 | |
504 | |
481 | if (expect_false (SvOBJECT (sv))) |
505 | if (expect_false (SvOBJECT (sv))) |
482 | { |
506 | { |
|
|
507 | HV *stash = !JSON_SLOW || json_boolean_stash |
|
|
508 | ? json_boolean_stash |
|
|
509 | : gv_stashpv ("JSON::XS::Boolean", 1); |
|
|
510 | |
483 | if (SvSTASH (sv) == json_boolean_stash) |
511 | if (SvSTASH (sv) == stash) |
484 | { |
512 | { |
485 | if (SvIV (sv)) |
513 | if (SvIV (sv)) |
486 | encode_str (enc, "true", 4, 0); |
514 | encode_str (enc, "true", 4, 0); |
487 | else |
515 | else |
488 | encode_str (enc, "false", 5, 0); |
516 | encode_str (enc, "false", 5, 0); |
… | |
… | |
500 | // we re-bless the reference to get overload and other niceties right |
528 | // we re-bless the reference to get overload and other niceties right |
501 | GV *to_json = gv_fetchmethod_autoload (SvSTASH (sv), "TO_JSON", 0); |
529 | GV *to_json = gv_fetchmethod_autoload (SvSTASH (sv), "TO_JSON", 0); |
502 | |
530 | |
503 | if (to_json) |
531 | if (to_json) |
504 | { |
532 | { |
505 | int count; |
|
|
506 | dSP; |
533 | dSP; |
507 | |
534 | |
508 | ENTER; SAVETMPS; PUSHMARK (SP); |
535 | ENTER; SAVETMPS; PUSHMARK (SP); |
509 | XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), SvSTASH (sv))); |
536 | XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), SvSTASH (sv))); |
510 | |
537 | |
… | |
… | |
1214 | |
1241 | |
1215 | case 't': |
1242 | case 't': |
1216 | if (dec->end - dec->cur >= 4 && !memcmp (dec->cur, "true", 4)) |
1243 | if (dec->end - dec->cur >= 4 && !memcmp (dec->cur, "true", 4)) |
1217 | { |
1244 | { |
1218 | dec->cur += 4; |
1245 | dec->cur += 4; |
|
|
1246 | #if JSON_SLOW |
|
|
1247 | json_true = get_sv ("JSON::XS::true", 1); SvREADONLY_on (json_true); |
|
|
1248 | #endif |
1219 | return SvREFCNT_inc (json_true); |
1249 | return SvREFCNT_inc (json_true); |
1220 | } |
1250 | } |
1221 | else |
1251 | else |
1222 | ERR ("'true' expected"); |
1252 | ERR ("'true' expected"); |
1223 | |
1253 | |
… | |
… | |
1225 | |
1255 | |
1226 | case 'f': |
1256 | case 'f': |
1227 | if (dec->end - dec->cur >= 5 && !memcmp (dec->cur, "false", 5)) |
1257 | if (dec->end - dec->cur >= 5 && !memcmp (dec->cur, "false", 5)) |
1228 | { |
1258 | { |
1229 | dec->cur += 5; |
1259 | dec->cur += 5; |
|
|
1260 | #if JSON_SLOW |
|
|
1261 | json_false = get_sv ("JSON::XS::false", 1); SvREADONLY_on (json_false); |
|
|
1262 | #endif |
1230 | return SvREFCNT_inc (json_false); |
1263 | return SvREFCNT_inc (json_false); |
1231 | } |
1264 | } |
1232 | else |
1265 | else |
1233 | ERR ("'false' expected"); |
1266 | ERR ("'false' expected"); |
1234 | |
1267 | |
… | |
… | |
1361 | json_false = get_sv ("JSON::XS::false", 1); SvREADONLY_on (json_false); |
1394 | json_false = get_sv ("JSON::XS::false", 1); SvREADONLY_on (json_false); |
1362 | } |
1395 | } |
1363 | |
1396 | |
1364 | PROTOTYPES: DISABLE |
1397 | PROTOTYPES: DISABLE |
1365 | |
1398 | |
|
|
1399 | void CLONE (...) |
|
|
1400 | CODE: |
|
|
1401 | json_stash = 0; |
|
|
1402 | json_boolean_stash = 0; |
|
|
1403 | |
1366 | void new (char *klass) |
1404 | void new (char *klass) |
1367 | PPCODE: |
1405 | PPCODE: |
1368 | { |
1406 | { |
1369 | SV *pv = NEWSV (0, sizeof (JSON)); |
1407 | SV *pv = NEWSV (0, sizeof (JSON)); |
1370 | SvPOK_only (pv); |
1408 | SvPOK_only (pv); |
1371 | Zero (SvPVX (pv), 1, JSON); |
1409 | Zero (SvPVX (pv), 1, JSON); |
1372 | ((JSON *)SvPVX (pv))->flags = F_DEFAULT; |
1410 | ((JSON *)SvPVX (pv))->flags = F_DEFAULT; |
1373 | XPUSHs (sv_2mortal (sv_bless (newRV_noinc (pv), json_stash))); |
1411 | XPUSHs (sv_2mortal (sv_bless (newRV_noinc (pv), JSON_STASH))); |
1374 | } |
1412 | } |
1375 | |
1413 | |
1376 | void ascii (JSON *self, int enable = 1) |
1414 | void ascii (JSON *self, int enable = 1) |
1377 | ALIAS: |
1415 | ALIAS: |
1378 | ascii = F_ASCII |
1416 | ascii = F_ASCII |