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.23 by root, Wed Nov 20 16:19:47 2013 UTC vs.
Revision 1.28 by root, Sat Nov 23 18:30:59 2013 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines