383
395
int undef_unknown = 0;
384
396
int compression_format = 0;
385
397
/* SRL_F_SHARED_HASHKEYS on by default */
386
svp = hv_fetchs(opt, "no_shared_hashkeys", 0);
387
if ( !svp || !SvTRUE(*svp) )
398
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_NO_SHARED_HASHKEYS);
399
if ( !val || !SvTRUE(val) )
388
400
SRL_ENC_SET_OPTION(enc, SRL_F_SHARED_HASHKEYS);
390
402
/* Needs to be before the snappy options */
391
403
/* enc->protocol_version defaults to SRL_PROTOCOL_VERSION. */
392
svp = hv_fetchs(opt, "protocol_version", 0);
393
if (svp && SvOK(*svp)) {
394
enc->protocol_version = SvUV(*svp);
404
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_PROTOCOL_VERSION);
405
if (val && SvOK(val)) {
406
enc->protocol_version = SvUV(val);
395
407
if (enc->protocol_version < 1
396
408
|| enc->protocol_version > SRL_PROTOCOL_VERSION)
398
croak("Specified Sereal protocol version ('%lu') is invalid",
399
(unsigned long)enc->protocol_version);
410
croak("Specified Sereal protocol version ('%"UVuf") is invalid",
411
(UV)enc->protocol_version);
403
415
/* Compatibility with the old way to specify older protocol version */
404
svp = hv_fetchs(opt, "use_protocol_v1", 0);
405
if ( svp && SvTRUE(*svp) )
416
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_USE_PROTOCOL_V1);
417
if ( val && SvTRUE(val) )
406
418
enc->protocol_version = 1;
409
svp = hv_fetchs(opt, "croak_on_bless", 0);
410
if ( svp && SvTRUE(*svp) )
421
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_CROAK_ON_BLESS);
422
if ( val && SvTRUE(val) )
411
423
SRL_ENC_SET_OPTION(enc, SRL_F_CROAK_ON_BLESS);
413
svp = hv_fetchs(opt, "no_bless_objects", 0);
414
if ( svp && SvTRUE(*svp) )
425
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_NO_BLESS_OBJECTS);
426
if ( val && SvTRUE(val) )
415
427
SRL_ENC_SET_OPTION(enc, SRL_F_NO_BLESS_OBJECTS);
417
svp = hv_fetchs(opt, "freeze_callbacks", 0);
418
if ( svp && SvTRUE(*svp) ) {
429
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_FREEZE_CALLBACKS);
430
if ( val && SvTRUE(val) ) {
419
431
if (SRL_ENC_HAVE_OPTION(enc, SRL_F_NO_BLESS_OBJECTS))
420
432
croak("The no_bless_objects and freeze_callback_support "
421
433
"options are mutually exclusive");
477
svp = hv_fetchs(opt, "undef_unknown", 0);
478
if ( svp && SvTRUE(*svp) ) {
489
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_UNDEF_UNKNOWN);
490
if ( val && SvTRUE(val) ) {
479
491
undef_unknown = 1;
480
492
SRL_ENC_SET_OPTION(enc, SRL_F_UNDEF_UNKNOWN);
483
svp = hv_fetchs(opt, "sort_keys", 0);
485
svp = hv_fetchs(opt, "canonical",0);
486
if ( svp && SvTRUE(*svp) )
495
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_SORT_KEYS);
497
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_CANONICAL);
498
if ( val && SvTRUE(val) )
487
499
SRL_ENC_SET_OPTION(enc, SRL_F_SORT_KEYS);
489
svp = hv_fetchs(opt, "canonical_refs", 0);
491
svp = hv_fetchs(opt, "canonical",0);
492
if ( svp && SvTRUE(*svp) )
501
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_CANONICAL_REFS);
503
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_CANONICAL);
504
if ( val && SvTRUE(val) )
493
505
SRL_ENC_SET_OPTION(enc, SRL_F_CANONICAL_REFS);
495
svp = hv_fetchs(opt, "aliased_dedupe_strings", 0);
496
if ( svp && SvTRUE(*svp) )
507
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_ALIASED_DEDUPE_STRINGS);
508
if ( val && SvTRUE(val) )
497
509
SRL_ENC_SET_OPTION(enc, SRL_F_ALIASED_DEDUPE_STRINGS | SRL_F_DEDUPE_STRINGS);
499
svp = hv_fetchs(opt, "dedupe_strings", 0);
500
if ( svp && SvTRUE(*svp) )
511
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_DEDUPE_STRINGS);
512
if ( val && SvTRUE(val) )
501
513
SRL_ENC_SET_OPTION(enc, SRL_F_DEDUPE_STRINGS);
504
svp = hv_fetchs(opt, "stringify_unknown", 0);
505
if ( svp && SvTRUE(*svp) ) {
516
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_STRINGIFY_UNKNOWN);
517
if ( val && SvTRUE(val) ) {
506
518
if (expect_false( undef_unknown ))
507
519
croak("'undef_unknown' and 'stringify_unknown' "
508
520
"options are mutually exclusive");
509
521
SRL_ENC_SET_OPTION(enc, SRL_F_STRINGIFY_UNKNOWN);
512
svp = hv_fetchs(opt, "warn_unknown", 0);
513
if ( svp && SvTRUE(*svp) ) {
524
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_WARN_UNKNOWN);
525
if ( val && SvTRUE(val) ) {
514
526
SRL_ENC_SET_OPTION(enc, SRL_F_WARN_UNKNOWN);
516
528
SRL_ENC_SET_OPTION(enc, SRL_F_NOWARN_UNKNOWN_OVERLOAD);
520
531
if (compression_format) {
521
532
enc->compress_threshold = 1024;
522
svp = hv_fetchs(opt, "compress_threshold", 0);
523
if ( svp && SvOK(*svp) )
524
enc->compress_threshold = SvIV(*svp);
533
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_COMPRESS_THRESHOLD);
534
if ( val && SvOK(val) )
535
enc->compress_threshold = SvIV(val);
525
536
else if (compression_format == 1) {
526
537
/* compression_format==1 is some sort of Snappy */
527
svp = hv_fetchs(opt, "snappy_threshold", 0);
528
if ( svp && SvOK(*svp) )
529
enc->compress_threshold = SvIV(*svp);
538
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_SNAPPY_THRESHOLD);
539
if ( val && SvOK(val) )
540
enc->compress_threshold = SvIV(val);
533
svp = hv_fetchs(opt, "max_recursion_depth", 0);
534
if ( svp && SvTRUE(*svp))
535
enc->max_recursion_depth = SvUV(*svp);
544
my_hv_fetchs(he, val, opt, SRL_ENC_OPT_IDX_MAX_RECURSION_DEPTH);
545
if ( val && SvTRUE(val) )
546
enc->max_recursion_depth = SvUV(val);
538
549
/* SRL_F_SHARED_HASHKEYS on by default */
539
550
SRL_ENC_SET_OPTION(enc, SRL_F_SHARED_HASHKEYS);
542
DEBUG_ASSERT_BUF_SANE(enc);
553
DEBUG_ASSERT_BUF_SANE(&enc->buf);
598
609
return enc->string_deduper_hv;
601
/* Lazy working buffer alloc */
602
SRL_STATIC_INLINE void
603
srl_init_snappy_workmem(pTHX_ srl_encoder_t *enc)
605
/* Lazy working buffer alloc */
606
if (expect_false( enc->snappy_workmem == NULL )) {
607
/* Cleaned up automatically by the cleanup handler */
608
Newx(enc->snappy_workmem, CSNAPPY_WORKMEM_BYTES, char);
609
if (enc->snappy_workmem == NULL)
610
croak("Out of memory!");
616
srl_write_header(pTHX_ srl_encoder_t *enc, SV *user_header_src)
614
srl_write_header(pTHX_ srl_encoder_t *enc, SV *user_header_src, const U32 compress_flags)
618
616
/* 4th to 8th bit are flags. Using 4th for snappy flag. FIXME needs to go in spec. */
620
SRL_ENC_HAVE_OPTION(enc, SRL_F_COMPRESS_SNAPPY)
621
? SRL_PROTOCOL_ENCODING_SNAPPY
622
: SRL_ENC_HAVE_OPTION(enc, SRL_F_COMPRESS_SNAPPY_INCREMENTAL)
623
? SRL_PROTOCOL_ENCODING_SNAPPY_INCREMENTAL
624
: SRL_ENC_HAVE_OPTION(enc, SRL_F_COMPRESS_ZLIB)
625
? SRL_PROTOCOL_ENCODING_ZLIB
626
: SRL_PROTOCOL_ENCODING_RAW
618
U8 flags= SRL_F_COMPRESS_FLAGS_TO_PROTOCOL_ENCODING[ compress_flags >> SRL_F_COMPRESS_FLAGS_SHIFT ];
628
619
const U8 version_and_flags = (U8)enc->protocol_version | flags;
630
621
/* 4 byte magic string + proto version
631
622
* + potentially uncompressed size varint
632
623
* + 1 byte varint that indicates zero-length header */
633
BUF_SIZE_ASSERT(enc, sizeof(SRL_MAGIC_STRING) + 1 + 1);
624
BUF_SIZE_ASSERT(&enc->buf, sizeof(SRL_MAGIC_STRING) + 1 + 1);
634
625
if (LIKELY( enc->protocol_version > 2 ))
635
srl_buf_cat_str_s_nocheck(enc, SRL_MAGIC_STRING_HIGHBIT);
626
srl_buf_cat_str_s_nocheck(&enc->buf, SRL_MAGIC_STRING_HIGHBIT);
637
srl_buf_cat_str_s_nocheck(enc, SRL_MAGIC_STRING);
638
srl_buf_cat_char_nocheck(enc, version_and_flags);
628
srl_buf_cat_str_s_nocheck(&enc->buf, SRL_MAGIC_STRING);
629
srl_buf_cat_char_nocheck(&enc->buf, version_and_flags);
639
630
if (user_header_src == NULL) {
640
srl_buf_cat_char_nocheck(enc, '\0'); /* variable header length (0 right now) */
631
srl_buf_cat_char_nocheck(&enc->buf, '\0'); /* variable header length (0 right now) */
643
634
STRLEN user_data_len;
653
644
/* Write document body (for header) into separate buffer */
654
645
srl_buf_swap_buffer(aTHX_ &enc->tmp_buf, &enc->buf);
655
SRL_UPDATE_BODY_POS(enc);
646
SRL_ENC_UPDATE_BODY_POS(enc);
656
647
srl_dump_sv(aTHX_ enc, user_header_src);
657
648
srl_fixup_weakrefs(aTHX_ enc); /* more bodies to follow */
658
649
srl_clear_seen_hashes(aTHX_ enc); /* more bodies to follow */
660
651
/* Swap main buffer back in, encode header length&bitfield, copy user header data */
661
user_data_len = BUF_POS_OFS(enc->buf);
652
user_data_len = BUF_POS_OFS(&enc->buf);
662
653
srl_buf_swap_buffer(aTHX_ &enc->buf, &enc->tmp_buf);
664
BUF_SIZE_ASSERT(enc, user_data_len + 1 + SRL_MAX_VARINT_LENGTH); /* +1 for bit field, +X for header len */
655
BUF_SIZE_ASSERT(&enc->buf, user_data_len + 1 + SRL_MAX_VARINT_LENGTH); /* +1 for bit field, +X for header len */
666
657
/* Encode header length */
667
srl_buf_cat_varint_nocheck(aTHX_ enc, 0, (UV)(user_data_len + 1)); /* +1 for bit field */
658
srl_buf_cat_varint_nocheck(aTHX_ &enc->buf, 0, (UV)(user_data_len + 1)); /* +1 for bit field */
668
659
/* Encode bitfield */
669
srl_buf_cat_char_nocheck(enc, '\1');
660
srl_buf_cat_char_nocheck(&enc->buf, '\1');
670
661
/* Copy user header data */
671
662
Copy(enc->tmp_buf.start, enc->buf.pos, user_data_len, char);
672
663
enc->buf.pos += user_data_len;
711
702
MS_VC6_WORKAROUND_VOLATILE double d= (double)nv;
712
703
/* TODO: this logic could be reworked to not duplicate so much code, which will help on win32 */
713
704
if ( f == nv || nv != nv ) {
714
BUF_SIZE_ASSERT(enc, 1 + sizeof(f)); /* heuristic: header + string + simple value */
715
srl_buf_cat_char_nocheck(enc,SRL_HDR_FLOAT);
705
BUF_SIZE_ASSERT(&enc->buf, 1 + sizeof(f)); /* heuristic: header + string + simple value */
706
srl_buf_cat_char_nocheck(&enc->buf, SRL_HDR_FLOAT);
716
707
Copy((char *)&f, enc->buf.pos, sizeof(f), char);
717
708
enc->buf.pos += sizeof(f);
718
709
} else if (d == nv) {
719
BUF_SIZE_ASSERT(enc, 1 + sizeof(d)); /* heuristic: header + string + simple value */
720
srl_buf_cat_char_nocheck(enc,SRL_HDR_DOUBLE);
710
BUF_SIZE_ASSERT(&enc->buf, 1 + sizeof(d)); /* heuristic: header + string + simple value */
711
srl_buf_cat_char_nocheck(&enc->buf, SRL_HDR_DOUBLE);
721
712
Copy((char *)&d, enc->buf.pos, sizeof(d), char);
722
713
enc->buf.pos += sizeof(d);
724
BUF_SIZE_ASSERT(enc, 1 + sizeof(nv)); /* heuristic: header + string + simple value */
725
srl_buf_cat_char_nocheck(enc,SRL_HDR_LONG_DOUBLE);
715
BUF_SIZE_ASSERT(&enc->buf, 1 + sizeof(nv)); /* heuristic: header + string + simple value */
716
srl_buf_cat_char_nocheck(&enc->buf, SRL_HDR_LONG_DOUBLE);
726
717
Copy((char *)&nv, enc->buf.pos, sizeof(nv), char);
727
718
#if SRL_EXTENDED_PRECISION_LONG_DOUBLE
728
719
/* x86 uses an 80 bit extended precision. on 64 bit machines
911
/* Update a varint anywhere in the output stream with defined start and end
912
* positions. This can produce non-canonical varints and is useful for filling
913
* pre-allocated varints. */
914
SRL_STATIC_INLINE void
915
srl_update_varint_from_to(pTHX_ char *varint_start, char *varint_end, UV number)
917
while (number >= 0x80) { /* while we are larger than 7 bits long */
918
*varint_start++ = (number & 0x7f) | 0x80; /* write out the least significant 7 bits, set the high bit */
919
number = number >> 7; /* shift off the 7 least significant bits */
921
/* if it is the same size we can use a canonical varint */
922
if ( varint_start == varint_end ) {
923
*varint_start = number; /* encode the last 7 bits without the high bit being set */
925
/* if not we produce a non-canonical varint, basically we stuff
926
* 0 bits (via 0x80) into the "tail" of the varint, until we can
927
* stick in a null to terminate the sequence. This means that the
928
* varint is effectively "self-padding", and we only need special
929
* logic in the encoder - a decoder will happily process a non-canonical
930
* varint with no problem */
931
*varint_start++ = (number & 0x7f) | 0x80;
932
while ( varint_start < varint_end )
933
*varint_start++ = 0x80;
939
/* Resets the compression header flag to OFF.
940
* Obviously requires that a Sereal header was already written to the
941
* encoder's output buffer. */
942
SRL_STATIC_INLINE void
943
srl_reset_compression_header_flag(srl_encoder_t *enc)
945
/* sizeof(const char *) includes a count of \0 */
946
char *flags_and_version_byte = enc->buf.start + sizeof(SRL_MAGIC_STRING) - 1;
947
/* disable snappy flag in header */
948
*flags_and_version_byte = SRL_PROTOCOL_ENCODING_RAW |
949
(*flags_and_version_byte & SRL_PROTOCOL_VERSION_MASK);
952
901
SRL_STATIC_INLINE srl_encoder_t *
953
902
srl_dump_data_structure(pTHX_ srl_encoder_t *enc, SV *src, SV *user_header_src)
955
906
enc = srl_prepare_encoder(aTHX_ enc);
907
compress_flags= SRL_ENC_HAVE_OPTION(enc, SRL_F_COMPRESS_FLAGS_MASK);
958
!SRL_ENC_HAVE_OPTION(enc, ( SRL_F_COMPRESS_SNAPPY
959
| SRL_F_COMPRESS_SNAPPY_INCREMENTAL
960
| SRL_F_COMPRESS_ZLIB))
963
srl_write_header(aTHX_ enc, user_header_src);
964
SRL_UPDATE_BODY_POS(enc);
965
srl_dump_sv(aTHX_ enc, src);
966
srl_fixup_weakrefs(aTHX_ enc);
968
else { /* Have some sort of compression */
909
if (expect_false(compress_flags))
910
{ /* Have some sort of compression */
969
911
ptrdiff_t sereal_header_len;
970
912
STRLEN uncompressed_body_length;
972
914
/* Alas, have to write entire packet first since the header length
973
915
* will determine offsets. */
974
srl_write_header(aTHX_ enc, user_header_src);
975
sereal_header_len = BUF_POS_OFS(enc->buf);
976
SRL_UPDATE_BODY_POS(enc);
916
srl_write_header(aTHX_ enc, user_header_src, compress_flags);
917
sereal_header_len = BUF_POS_OFS(&enc->buf);
918
SRL_ENC_UPDATE_BODY_POS(enc);
977
919
srl_dump_sv(aTHX_ enc, src);
978
920
srl_fixup_weakrefs(aTHX_ enc);
979
assert(BUF_POS_OFS(enc->buf) > sereal_header_len);
980
uncompressed_body_length = BUF_POS_OFS(enc->buf) - sereal_header_len;
921
assert(BUF_POS_OFS(&enc->buf) > sereal_header_len);
922
uncompressed_body_length = BUF_POS_OFS(&enc->buf) - sereal_header_len;
982
if (uncompressed_body_length < (STRLEN)enc->compress_threshold)
924
if (uncompressed_body_length < (STRLEN)enc->compress_threshold) {
984
925
/* Don't bother with compression at all if we have less than $threshold bytes of payload */
985
srl_reset_compression_header_flag(enc);
926
srl_reset_compression_header_flag(&enc->buf);
987
928
else { /* Do Snappy or zlib compression of body */
989
= SRL_ENC_HAVE_OPTION(enc, ( SRL_F_COMPRESS_SNAPPY
990
| SRL_F_COMPRESS_SNAPPY_INCREMENTAL));
991
/* !is_snappy is the same as "is zlib" right now */
993
const int is_traditional_snappy
994
= (SRL_ENC_HAVE_OPTION(enc, SRL_F_COMPRESS_SNAPPY));
996
srl_buffer_t old_buf; /* TODO can we use the enc->tmp_buf here to avoid allocations? */
997
char *varint_start= NULL;
998
char *varint_end= NULL;
1001
/* Get uncompressed payload and total packet output (after compression) lengths */
1002
dest_len = sereal_header_len + 1
1003
+ ( is_snappy ? (size_t)csnappy_max_compressed_length(uncompressed_body_length)
1004
: (size_t)mz_compressBound(uncompressed_body_length)+SRL_MAX_VARINT_LENGTH );
1006
/* Will have to embed compressed packet length as varint if not
1007
* in traditional Snappy mode. (So needs to be added for any of
1008
* ZLIB, or incremental Snappy.) */
1009
if ( !is_traditional_snappy )
1010
dest_len += SRL_MAX_VARINT_LENGTH;
1013
srl_init_snappy_workmem(aTHX_ enc);
1015
/* Back up old buffer and allocate new one with correct size */
1016
srl_buf_copy_buffer(aTHX_ &enc->buf, &old_buf);
1017
srl_buf_init_buffer(aTHX_ &enc->buf, dest_len);
1019
/* Copy Sereal header */
1020
Copy(old_buf.start, enc->buf.pos, sereal_header_len, char);
1021
enc->buf.pos += sereal_header_len;
1022
SRL_UPDATE_BODY_POS(enc); /* will do the right thing wrt. protocol V1 / V2 */
1024
/* Embed compressed packet length if Zlib */
1026
srl_buf_cat_varint_nocheck(aTHX_ enc, 0, uncompressed_body_length);
1028
/* Embed compressed packet length if incr. Snappy or Zlib*/
1029
if (expect_true( !is_traditional_snappy )) {
1030
varint_start= enc->buf.pos;
1031
srl_buf_cat_varint_nocheck(aTHX_ enc, 0, dest_len);
1032
varint_end= enc->buf.pos - 1;
1036
uint32_t len = (uint32_t)dest_len;
1037
csnappy_compress(old_buf.start + sereal_header_len, (uint32_t)uncompressed_body_length, enc->buf.pos, &len,
1038
enc->snappy_workmem, CSNAPPY_WORKMEM_BYTES_POWER_OF_TWO);
1039
dest_len = (size_t)len;
1042
mz_ulong dl = (mz_ulong)dest_len;
1043
int status = mz_compress2(
1044
(unsigned char *)enc->buf.pos,
1046
(const unsigned char *)(old_buf.start + sereal_header_len),
1047
(mz_ulong)uncompressed_body_length,
1051
assert(status == Z_OK);
1052
dest_len = (size_t)dl;
1055
assert(dest_len != 0);
1057
/* If compression didn't help, swap back to old, uncompressed buffer */
1058
if (dest_len >= uncompressed_body_length) {
1059
/* swap in old, uncompressed buffer */
1060
srl_buf_swap_buffer(aTHX_ &enc->buf, &old_buf);
1061
/* disable compression flag */
1062
srl_reset_compression_header_flag(enc);
1064
else { /* go ahead with Snappy and do final fixups */
1065
/* overwrite the max size varint with the real size of the compressed data */
1067
srl_update_varint_from_to(aTHX_ varint_start, varint_end, dest_len);
1068
enc->buf.pos += dest_len;
1071
srl_buf_free_buffer(aTHX_ &old_buf);
1072
assert(enc->buf.pos <= enc->buf.end);
1073
} /* End of "actually do compression" */
929
srl_compress_body(aTHX_ &enc->buf, sereal_header_len,
930
compress_flags, enc->compress_level,
931
&enc->snappy_workmem);
933
SRL_ENC_UPDATE_BODY_POS(enc);
934
DEBUG_ASSERT_BUF_SANE(&enc->buf);
1074
936
} /* End of "want compression?" */
939
srl_write_header(aTHX_ enc, user_header_src, compress_flags);
940
SRL_ENC_UPDATE_BODY_POS(enc);
941
srl_dump_sv(aTHX_ enc, src);
942
srl_fixup_weakrefs(aTHX_ enc);
1077
946
* SRL_ENC_RESET_OPER_FLAG(enc, SRL_OF_ENCODER_DIRTY);
1549
1428
if (expect_false(oldoffset)) {
1550
1429
/* we have seen it before, so we do not need to bless it again */
1551
1430
if (ref_rewrite_pos) {
1552
if (DEBUGHACK) warn("ref to %p as %lu", src, (long unsigned int)oldoffset);
1431
if (DEBUGHACK) warn("ref to %p as %"UVuf, src, (UV)oldoffset);
1553
1432
enc->buf.pos= enc->buf.body_pos + ref_rewrite_pos;
1554
srl_buf_cat_varint(aTHX_ enc, SRL_HDR_REFP, (UV)oldoffset);
1433
srl_buf_cat_varint(aTHX_ &enc->buf, SRL_HDR_REFP, (UV)oldoffset);
1556
if (DEBUGHACK) warn("alias to %p as %lu", src, (long unsigned int)oldoffset);
1557
srl_buf_cat_varint(aTHX_ enc, SRL_HDR_ALIAS, (UV)oldoffset);
1435
if (DEBUGHACK) warn("alias to %p as %"UVuf, src, (UV)oldoffset);
1436
srl_buf_cat_varint(aTHX_ &enc->buf, SRL_HDR_ALIAS, (UV)oldoffset);
1559
1438
SRL_SET_TRACK_FLAG(*(enc->buf.body_pos + oldoffset));
1560
1439
--enc->recursion_depth;
1563
if (DEBUGHACK) warn("storing %p as %lu", src, (long unsigned int)BODY_POS_OFS(enc->buf));
1564
PTABLE_store(ref_seenhash, src, INT2PTR(void *, BODY_POS_OFS(enc->buf)));
1442
if (DEBUGHACK) warn("storing %p as %"UVuf, src, (UV)BODY_POS_OFS(&enc->buf));
1443
PTABLE_store(ref_seenhash, src, INT2PTR(void *, BODY_POS_OFS(&enc->buf)));
1567
1447
if (expect_false( weakref_ofs != 0 )) {
1569
croak("Corrupted weakref? weakref_ofs=0 (this should not happen)");
1449
croak("Corrupted weakref? weakref_ofs should be 0, but got %"UVuf" (this should not happen)", weakref_ofs);
1571
1452
if (replacement) {
1572
1453
if (SvROK(replacement)) {
1573
1454
src= SvRV(replacement);