ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/CBOR-XS/XS.xs
(Generate patch)

Comparing CBOR-XS/XS.xs (file contents):
Revision 1.22 by root, Wed Nov 20 15:05:46 2013 UTC vs.
Revision 1.27 by root, Fri Nov 22 15:28:38 2013 UTC

54 CBOR_TAG_MIME = 36, // mime message rfc2045, utf-8 54 CBOR_TAG_MIME = 36, // mime message rfc2045, utf-8
55 55
56 CBOR_TAG_MAGIC = 55799 // self-describe cbor 56 CBOR_TAG_MAGIC = 55799 // self-describe cbor
57}; 57};
58 58
59#define F_SHRINK 0x00000001UL 59#define F_SHRINK 0x00000001UL
60#define F_ALLOW_UNKNOWN 0x00000002UL 60#define F_ALLOW_UNKNOWN 0x00000002UL
61#define F_ALLOW_SHARING 0x00000004UL //TODO 61#define F_ALLOW_SHARING 0x00000004UL //TODO
62#define F_DEDUP_STRINGS 0x00000008UL //TODO 62#define F_ALLOW_STRINGREF 0x00000008UL //TODO
63 63
64#define INIT_SIZE 32 // initial scalar size to be allocated 64#define INIT_SIZE 32 // initial scalar size to be allocated
65 65
66#define SB do { 66#define SB do {
67#define SE } while (0) 67#define SE } while (0)
79# define CBOR_SLOW 0 79# define CBOR_SLOW 0
80# define CBOR_STASH cbor_stash 80# define CBOR_STASH cbor_stash
81#endif 81#endif
82 82
83static HV *cbor_stash, *types_boolean_stash, *types_error_stash, *cbor_tagged_stash; // CBOR::XS:: 83static HV *cbor_stash, *types_boolean_stash, *types_error_stash, *cbor_tagged_stash; // CBOR::XS::
84static SV *types_true, *types_false, *types_error, *sv_cbor; 84static SV *types_true, *types_false, *types_error, *sv_cbor, *default_filter;
85 85
86typedef struct { 86typedef struct {
87 U32 flags; 87 U32 flags;
88 U32 max_depth; 88 U32 max_depth;
89 STRLEN max_size; 89 STRLEN max_size;
90 SV *filter;
90} CBOR; 91} CBOR;
91 92
92ecb_inline void 93ecb_inline void
93cbor_init (CBOR *cbor) 94cbor_init (CBOR *cbor)
94{ 95{
95 Zero (cbor, 1, CBOR); 96 Zero (cbor, 1, CBOR);
96 cbor->max_depth = 512; 97 cbor->max_depth = 512;
98}
99
100ecb_inline void
101cbor_free (CBOR *cbor)
102{
103 SvREFCNT_dec (cbor->filter);
97} 104}
98 105
99///////////////////////////////////////////////////////////////////////////// 106/////////////////////////////////////////////////////////////////////////////
100// utility functions 107// utility functions
101 108
223} 230}
224 231
225static void 232static void
226encode_str (enc_t *enc, int utf8, char *str, STRLEN len) 233encode_str (enc_t *enc, int utf8, char *str, STRLEN len)
227{ 234{
228 if (ecb_expect_false (enc->cbor.flags & F_DEDUP_STRINGS)) 235 if (ecb_expect_false (enc->cbor.flags & F_ALLOW_STRINGREF))
229 { 236 {
230 SV **svp = hv_fetch (enc->stringref[!!utf8], str, len, 1); 237 SV **svp = hv_fetch (enc->stringref[!!utf8], str, len, 1);
231 238
232 if (SvOK (*svp)) 239 if (SvOK (*svp))
233 { 240 {
269 SV **svp = av_fetch (av, i, 0); 276 SV **svp = av_fetch (av, i, 0);
270 encode_sv (enc, svp ? *svp : &PL_sv_undef); 277 encode_sv (enc, svp ? *svp : &PL_sv_undef);
271 } 278 }
272 279
273 --enc->depth; 280 --enc->depth;
274}
275
276ecb_inline void
277encode_he (enc_t *enc, HE *he)
278{
279} 281}
280 282
281static void 283static void
282encode_hv (enc_t *enc, HV *hv) 284encode_hv (enc_t *enc, HV *hv)
283{ 285{
515 enc.cur = SvPVX (enc.sv); 517 enc.cur = SvPVX (enc.sv);
516 enc.end = SvEND (enc.sv); 518 enc.end = SvEND (enc.sv);
517 519
518 SvPOK_only (enc.sv); 520 SvPOK_only (enc.sv);
519 521
520 if (cbor->flags & F_DEDUP_STRINGS) 522 if (cbor->flags & F_ALLOW_STRINGREF)
521 { 523 {
522 encode_tag (&enc, CBOR_TAG_STRINGREF_NAMESPACE); 524 encode_tag (&enc, CBOR_TAG_STRINGREF_NAMESPACE);
523 enc.stringref[0]= (HV *)sv_2mortal ((SV *)newHV ()); 525 enc.stringref[0]= (HV *)sv_2mortal ((SV *)newHV ());
524 enc.stringref[1]= (HV *)sv_2mortal ((SV *)newHV ()); 526 enc.stringref[1]= (HV *)sv_2mortal ((SV *)newHV ());
525 } 527 }
547 CBOR cbor; 549 CBOR cbor;
548 U32 depth; // recursion depth 550 U32 depth; // recursion depth
549 U32 maxdepth; // recursion depth limit 551 U32 maxdepth; // recursion depth limit
550 AV *shareable; 552 AV *shareable;
551 AV *stringref; 553 AV *stringref;
554 SV *decode_tagged;
552} dec_t; 555} dec_t;
553 556
554#define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE 557#define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE
555 558
556#define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data") 559#define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data")
656decode_he (dec_t *dec, HV *hv) 659decode_he (dec_t *dec, HV *hv)
657{ 660{
658 // for speed reasons, we specialcase single-string 661 // for speed reasons, we specialcase single-string
659 // byte or utf-8 strings as keys, but only when !stringref 662 // byte or utf-8 strings as keys, but only when !stringref
660 663
661 if (expect_true (!dec->stringref)) 664 if (ecb_expect_true (!dec->stringref))
662 if (*dec->cur >= 0x40 && *dec->cur <= 0x40 + 27) 665 if (*dec->cur >= 0x40 && *dec->cur <= 0x40 + 27)
663 { 666 {
664 I32 len = decode_uint (dec); 667 I32 len = decode_uint (dec);
665 char *key = (char *)dec->cur; 668 char *key = (char *)dec->cur;
666 669
766 STRLEN len = decode_uint (dec); 769 STRLEN len = decode_uint (dec);
767 770
768 WANT (len); 771 WANT (len);
769 sv = newSVpvn (dec->cur, len); 772 sv = newSVpvn (dec->cur, len);
770 dec->cur += len; 773 dec->cur += len;
774
775 if (ecb_expect_false (dec->stringref)
776 && SvCUR (sv) >= minimum_string_length (AvFILLp (dec->stringref) + 1))
777 av_push (dec->stringref, SvREFCNT_inc_NN (sv));
771 } 778 }
772 779
773 if (utf8) 780 if (utf8)
774 SvUTF8_on (sv); 781 SvUTF8_on (sv);
775
776 if (ecb_expect_false (dec->stringref)
777 && SvCUR (sv) >= minimum_string_length (AvFILLp (dec->stringref) + 1))
778 av_push (dec->stringref, SvREFCNT_inc_NN (sv));
779 782
780 return sv; 783 return sv;
781 784
782fail: 785fail:
783 SvREFCNT_dec (sv); 786 SvREFCNT_dec (sv);
910 913
911 default: 914 default:
912 { 915 {
913 sv = decode_sv (dec); 916 sv = decode_sv (dec);
914 917
918 dSP;
919 ENTER; SAVETMPS; PUSHMARK (SP);
920 EXTEND (SP, 2);
921 PUSHs (newSVuv (tag));
922 PUSHs (sv);
923
924 PUTBACK;
925 int count = call_sv (dec->cbor.filter ? dec->cbor.filter : default_filter, G_ARRAY | G_EVAL);
926 SPAGAIN;
927
928 if (SvTRUE (ERRSV))
929 {
930 FREETMPS; LEAVE;
931 ERR (SvPVutf8_nolen (sv_2mortal (SvREFCNT_inc (ERRSV))));
932 }
933
934 if (count)
935 {
936 SvREFCNT_dec (sv);
937 sv = SvREFCNT_inc (POPs);
938 }
939 else
940 {
915 AV *av = newAV (); 941 AV *av = newAV ();
916 av_push (av, newSVuv (tag)); 942 av_push (av, newSVuv (tag));
917 av_push (av, sv); 943 av_push (av, sv);
918 944
919 HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash 945 HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash
920 ? cbor_tagged_stash 946 ? cbor_tagged_stash
921 : gv_stashpv ("CBOR::XS::Tagged" , 1); 947 : gv_stashpv ("CBOR::XS::Tagged" , 1);
922
923 sv = sv_bless (newRV_noinc ((SV *)av), tagged_stash); 948 sv = sv_bless (newRV_noinc ((SV *)av), tagged_stash);
949 }
950
951 PUTBACK;
952
953 FREETMPS; LEAVE;
924 } 954 }
925 break; 955 break;
926 } 956 }
927 957
928 return sv; 958 return sv;
1074 1104
1075 types_true = get_bool ("Types::Serialiser::true" ); 1105 types_true = get_bool ("Types::Serialiser::true" );
1076 types_false = get_bool ("Types::Serialiser::false"); 1106 types_false = get_bool ("Types::Serialiser::false");
1077 types_error = get_bool ("Types::Serialiser::error"); 1107 types_error = get_bool ("Types::Serialiser::error");
1078 1108
1109 default_filter = newSVpv ("CBOR::XS::default_filter", 0);
1110
1079 sv_cbor = newSVpv ("CBOR", 0); 1111 sv_cbor = newSVpv ("CBOR", 0);
1080 SvREADONLY_on (sv_cbor); 1112 SvREADONLY_on (sv_cbor);
1081} 1113}
1082 1114
1083PROTOTYPES: DISABLE 1115PROTOTYPES: DISABLE
1104void shrink (CBOR *self, int enable = 1) 1136void shrink (CBOR *self, int enable = 1)
1105 ALIAS: 1137 ALIAS:
1106 shrink = F_SHRINK 1138 shrink = F_SHRINK
1107 allow_unknown = F_ALLOW_UNKNOWN 1139 allow_unknown = F_ALLOW_UNKNOWN
1108 allow_sharing = F_ALLOW_SHARING 1140 allow_sharing = F_ALLOW_SHARING
1109 dedup_strings = F_DEDUP_STRINGS 1141 allow_stringref = F_ALLOW_STRINGREF
1110 PPCODE: 1142 PPCODE:
1111{ 1143{
1112 if (enable) 1144 if (enable)
1113 self->flags |= ix; 1145 self->flags |= ix;
1114 else 1146 else
1120void get_shrink (CBOR *self) 1152void get_shrink (CBOR *self)
1121 ALIAS: 1153 ALIAS:
1122 get_shrink = F_SHRINK 1154 get_shrink = F_SHRINK
1123 get_allow_unknown = F_ALLOW_UNKNOWN 1155 get_allow_unknown = F_ALLOW_UNKNOWN
1124 get_allow_sharing = F_ALLOW_SHARING 1156 get_allow_sharing = F_ALLOW_SHARING
1125 get_dedup_strings = F_DEDUP_STRINGS 1157 get_allow_stringref = F_ALLOW_STRINGREF
1126 PPCODE: 1158 PPCODE:
1127 XPUSHs (boolSV (self->flags & ix)); 1159 XPUSHs (boolSV (self->flags & ix));
1128 1160
1129void max_depth (CBOR *self, U32 max_depth = 0x80000000UL) 1161void max_depth (CBOR *self, U32 max_depth = 0x80000000UL)
1130 PPCODE: 1162 PPCODE:
1143 XPUSHs (ST (0)); 1175 XPUSHs (ST (0));
1144 1176
1145int get_max_size (CBOR *self) 1177int get_max_size (CBOR *self)
1146 CODE: 1178 CODE:
1147 RETVAL = self->max_size; 1179 RETVAL = self->max_size;
1180 OUTPUT:
1181 RETVAL
1182
1183void filter (CBOR *self, SV *filter = 0)
1184 PPCODE:
1185 SvREFCNT_dec (self->filter);
1186 self->filter = filter ? newSVsv (filter) : filter;
1187 XPUSHs (ST (0));
1188
1189SV *get_filter (CBOR *self)
1190 CODE:
1191 RETVAL = self->filter ? self->filter : NEWSV (0, 0);
1148 OUTPUT: 1192 OUTPUT:
1149 RETVAL 1193 RETVAL
1150 1194
1151void encode (CBOR *self, SV *scalar) 1195void encode (CBOR *self, SV *scalar)
1152 PPCODE: 1196 PPCODE:
1167 EXTEND (SP, 2); 1211 EXTEND (SP, 2);
1168 PUSHs (sv); 1212 PUSHs (sv);
1169 PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr)))); 1213 PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr))));
1170} 1214}
1171 1215
1216void DESTROY (CBOR *self)
1217 PPCODE:
1218 cbor_free (self);
1219
1172PROTOTYPES: ENABLE 1220PROTOTYPES: ENABLE
1173 1221
1174void encode_cbor (SV *scalar) 1222void encode_cbor (SV *scalar)
1175 PPCODE: 1223 PPCODE:
1176{ 1224{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines