… | |
… | |
9 | #include <limits.h> |
9 | #include <limits.h> |
10 | #include <float.h> |
10 | #include <float.h> |
11 | |
11 | |
12 | #include "ecb.h" |
12 | #include "ecb.h" |
13 | |
13 | |
14 | // known tags, rfc7049 |
14 | // known tags |
15 | enum cbor_tag |
15 | enum cbor_tag |
16 | { |
16 | { |
|
|
17 | // inofficial extensions (pending iana registration) |
|
|
18 | CBOR_TAG_PERL_OBJECT = 256, |
|
|
19 | CBOR_TAG_GENERIC_OBJECT = 257, |
|
|
20 | |
|
|
21 | // rfc7049 |
17 | CBOR_TAG_DATETIME = 0, // rfc4287, utf-8 |
22 | CBOR_TAG_DATETIME = 0, // rfc4287, utf-8 |
18 | CBOR_TAG_TIMESTAMP = 1, // unix timestamp, any |
23 | CBOR_TAG_TIMESTAMP = 1, // unix timestamp, any |
19 | CBOR_TAG_POS_BIGNUM = 2, // byte string |
24 | CBOR_TAG_POS_BIGNUM = 2, // byte string |
20 | CBOR_TAG_NEG_BIGNUM = 3, // byte string |
25 | CBOR_TAG_NEG_BIGNUM = 3, // byte string |
21 | CBOR_TAG_DECIMAL = 4, // decimal fraction, array |
26 | CBOR_TAG_DECIMAL = 4, // decimal fraction, array |
22 | CBOR_TAG_BIGFLOAT = 5, // array |
27 | CBOR_TAG_BIGFLOAT = 5, // array |
23 | |
28 | |
24 | CBOR_TAG_CONV_B64U = 21, // base64url, any |
29 | CBOR_TAG_CONV_B64U = 21, // base64url, any |
25 | CBOR_TAG_CONV_B64 = 22, // base64, any |
30 | CBOR_TAG_CONV_B64 = 22, // base64, any |
26 | CBOR_TAG_CONV_HEX = 23, // base16, any |
31 | CBOR_TAG_CONV_HEX = 23, // base16, any |
27 | CBOR_TAG_CBOR = 24, // embedded cbor, byte string |
32 | CBOR_TAG_CBOR = 24, // embedded cbor, byte string |
28 | |
33 | |
29 | CBOR_TAG_URI = 32, // URI rfc3986, utf-8 |
34 | CBOR_TAG_URI = 32, // URI rfc3986, utf-8 |
30 | CBOR_TAG_B64U = 33, // base64url rfc4648, utf-8 |
35 | CBOR_TAG_B64U = 33, // base64url rfc4648, utf-8 |
31 | CBOR_TAG_B64 = 34, // base6 rfc46484, utf-8 |
36 | CBOR_TAG_B64 = 34, // base6 rfc46484, utf-8 |
32 | CBOR_TAG_REGEX = 35, // regex pcre/ecma262, utf-8 |
37 | CBOR_TAG_REGEX = 35, // regex pcre/ecma262, utf-8 |
33 | CBOR_TAG_MIME = 36, // mime message rfc2045, utf-8 |
38 | CBOR_TAG_MIME = 36, // mime message rfc2045, utf-8 |
34 | |
39 | |
35 | CBOR_TAG_MAGIC = 55799 |
40 | CBOR_TAG_MAGIC = 55799 // self-describe cbor |
36 | }; |
41 | }; |
37 | |
42 | |
38 | #define F_SHRINK 0x00000200UL |
43 | #define F_SHRINK 0x00000200UL |
39 | #define F_ALLOW_UNKNOWN 0x00002000UL |
44 | #define F_ALLOW_UNKNOWN 0x00002000UL |
40 | |
45 | |
… | |
… | |
55 | #else |
60 | #else |
56 | # define CBOR_SLOW 0 |
61 | # define CBOR_SLOW 0 |
57 | # define CBOR_STASH cbor_stash |
62 | # define CBOR_STASH cbor_stash |
58 | #endif |
63 | #endif |
59 | |
64 | |
60 | static HV *cbor_stash, *cbor_boolean_stash, *cbor_tagged_stash; // CBOR::XS:: |
65 | static HV *cbor_stash, *types_boolean_stash, *types_error_stash, *cbor_tagged_stash; // CBOR::XS:: |
61 | static SV *cbor_true, *cbor_false; |
66 | static SV *types_true, *types_false, *types_error; |
62 | |
67 | |
63 | typedef struct { |
68 | typedef struct { |
64 | U32 flags; |
69 | U32 flags; |
65 | U32 max_depth; |
70 | U32 max_depth; |
66 | STRLEN max_size; |
71 | STRLEN max_size; |
… | |
… | |
254 | SvGETMAGIC (sv); |
259 | SvGETMAGIC (sv); |
255 | svt = SvTYPE (sv); |
260 | svt = SvTYPE (sv); |
256 | |
261 | |
257 | if (ecb_expect_false (SvOBJECT (sv))) |
262 | if (ecb_expect_false (SvOBJECT (sv))) |
258 | { |
263 | { |
259 | HV *boolean_stash = !CBOR_SLOW || cbor_boolean_stash |
264 | HV *boolean_stash = !CBOR_SLOW || types_boolean_stash |
260 | ? cbor_boolean_stash |
265 | ? types_boolean_stash |
261 | : gv_stashpv ("CBOR::XS::Boolean", 1); |
266 | : gv_stashpv ("Types::Serialiser::Boolean", 1); |
|
|
267 | HV *error_stash = !CBOR_SLOW || types_error_stash |
|
|
268 | ? types_error_stash |
|
|
269 | : gv_stashpv ("Types::Serialiser::Error", 1); |
262 | HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash |
270 | HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash |
263 | ? cbor_tagged_stash |
271 | ? cbor_tagged_stash |
264 | : gv_stashpv ("CBOR::XS::Tagged" , 1); |
272 | : gv_stashpv ("CBOR::XS::Tagged" , 1); |
265 | |
273 | |
266 | if (SvSTASH (sv) == boolean_stash) |
274 | if (SvSTASH (sv) == boolean_stash) |
267 | encode_ch (enc, SvIV (sv) ? 0xe0 | 21 : 0xe0 | 20); |
275 | encode_ch (enc, SvIV (sv) ? 0xe0 | 21 : 0xe0 | 20); |
|
|
276 | else if (SvSTASH (sv) == error_stash) |
|
|
277 | encode_ch (enc, 0xe0 | 23); |
268 | else if (SvSTASH (sv) == tagged_stash) |
278 | else if (SvSTASH (sv) == tagged_stash) |
269 | { |
279 | { |
270 | if (svt != SVt_PVAV) |
280 | if (svt != SVt_PVAV) |
271 | croak ("encountered CBOR::XS::Tagged object that isn't an array"); |
281 | croak ("encountered CBOR::XS::Tagged object that isn't an array"); |
272 | |
282 | |
… | |
… | |
636 | decode_tagged (dec_t *dec) |
646 | decode_tagged (dec_t *dec) |
637 | { |
647 | { |
638 | UV tag = decode_uint (dec); |
648 | UV tag = decode_uint (dec); |
639 | SV *sv = decode_sv (dec); |
649 | SV *sv = decode_sv (dec); |
640 | |
650 | |
641 | if (tag == CBOR_TAG_MAGIC) // 2.4.5 Self-Describe CBOR |
651 | if (tag == CBOR_TAG_MAGIC) |
642 | return sv; |
652 | return sv; |
|
|
653 | |
|
|
654 | if (tag == CBOR_TAG_PERL_OBJECT) |
|
|
655 | { |
|
|
656 | if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV) |
|
|
657 | ERR ("corrupted CBOR data (non-array perl object)"); |
|
|
658 | |
|
|
659 | // TODO |
|
|
660 | } |
643 | |
661 | |
644 | AV *av = newAV (); |
662 | AV *av = newAV (); |
645 | av_push (av, newSVuv (tag)); |
663 | av_push (av, newSVuv (tag)); |
646 | av_push (av, sv); |
664 | av_push (av, sv); |
647 | |
665 | |
648 | HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash |
666 | HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash |
649 | ? cbor_tagged_stash |
667 | ? cbor_tagged_stash |
650 | : gv_stashpv ("CBOR::XS::Tagged" , 1); |
668 | : gv_stashpv ("CBOR::XS::Tagged" , 1); |
651 | |
669 | |
652 | return sv_bless (newRV_noinc ((SV *)av), tagged_stash); |
670 | return sv_bless (newRV_noinc ((SV *)av), tagged_stash); |
|
|
671 | |
|
|
672 | fail: |
|
|
673 | SvREFCNT_dec (sv); |
|
|
674 | return &PL_sv_undef; |
653 | } |
675 | } |
654 | |
676 | |
655 | static SV * |
677 | static SV * |
656 | decode_sv (dec_t *dec) |
678 | decode_sv (dec_t *dec) |
657 | { |
679 | { |
… | |
… | |
676 | case 7: // misc |
698 | case 7: // misc |
677 | switch (*dec->cur++ & 31) |
699 | switch (*dec->cur++ & 31) |
678 | { |
700 | { |
679 | case 20: |
701 | case 20: |
680 | #if CBOR_SLOW |
702 | #if CBOR_SLOW |
681 | cbor_false = get_bool ("CBOR::XS::false"); |
703 | types_false = get_bool ("Types::Serialiser::false"); |
682 | #endif |
704 | #endif |
683 | return newSVsv (cbor_false); |
705 | return newSVsv (types_false); |
684 | case 21: |
706 | case 21: |
685 | #if CBOR_SLOW |
707 | #if CBOR_SLOW |
686 | cbor_true = get_bool ("CBOR::XS::true"); |
708 | types_true = get_bool ("Types::Serialiser::true"); |
687 | #endif |
709 | #endif |
688 | return newSVsv (cbor_true); |
710 | return newSVsv (types_true); |
689 | case 22: |
711 | case 22: |
690 | return newSVsv (&PL_sv_undef); |
712 | return newSVsv (&PL_sv_undef); |
|
|
713 | case 23: |
|
|
714 | #if CBOR_SLOW |
|
|
715 | types_error = get_bool ("Types::Serialiser::error"); |
|
|
716 | #endif |
|
|
717 | return newSVsv (types_error); |
691 | |
718 | |
692 | case 25: |
719 | case 25: |
693 | { |
720 | { |
694 | WANT (2); |
721 | WANT (2); |
695 | |
722 | |
… | |
… | |
811 | MODULE = CBOR::XS PACKAGE = CBOR::XS |
838 | MODULE = CBOR::XS PACKAGE = CBOR::XS |
812 | |
839 | |
813 | BOOT: |
840 | BOOT: |
814 | { |
841 | { |
815 | cbor_stash = gv_stashpv ("CBOR::XS" , 1); |
842 | cbor_stash = gv_stashpv ("CBOR::XS" , 1); |
816 | cbor_boolean_stash = gv_stashpv ("CBOR::XS::Boolean", 1); |
|
|
817 | cbor_tagged_stash = gv_stashpv ("CBOR::XS::Tagged" , 1); |
843 | cbor_tagged_stash = gv_stashpv ("CBOR::XS::Tagged" , 1); |
818 | |
844 | |
819 | cbor_true = get_bool ("CBOR::XS::true"); |
845 | types_boolean_stash = gv_stashpv ("Types::Serialiser::Boolean", 1); |
820 | cbor_false = get_bool ("CBOR::XS::false"); |
846 | types_error_stash = gv_stashpv ("Types::Serialiser::Error" , 1); |
|
|
847 | |
|
|
848 | types_true = get_bool ("Types::Serialiser::true" ); |
|
|
849 | types_false = get_bool ("Types::Serialiser::false"); |
|
|
850 | types_error = get_bool ("Types::Serialiser::error"); |
821 | } |
851 | } |
822 | |
852 | |
823 | PROTOTYPES: DISABLE |
853 | PROTOTYPES: DISABLE |
824 | |
854 | |
825 | void CLONE (...) |
855 | void CLONE (...) |
826 | CODE: |
856 | CODE: |
827 | cbor_stash = 0; |
857 | cbor_stash = 0; |
828 | cbor_boolean_stash = 0; |
|
|
829 | cbor_tagged_stash = 0; |
858 | cbor_tagged_stash = 0; |
|
|
859 | types_error_stash = 0; |
|
|
860 | types_boolean_stash = 0; |
830 | |
861 | |
831 | void new (char *klass) |
862 | void new (char *klass) |
832 | PPCODE: |
863 | PPCODE: |
833 | { |
864 | { |
834 | SV *pv = NEWSV (0, sizeof (CBOR)); |
865 | SV *pv = NEWSV (0, sizeof (CBOR)); |