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.18 by root, Wed Nov 20 01:09:46 2013 UTC vs.
Revision 1.19 by root, Wed Nov 20 02:03:09 2013 UTC

26enum cbor_tag 26enum cbor_tag
27{ 27{
28 // inofficial extensions (pending iana registration) 28 // inofficial extensions (pending iana registration)
29 CBOR_TAG_PERL_OBJECT = 24, // http://cbor.schmorp.de/perl-object 29 CBOR_TAG_PERL_OBJECT = 24, // http://cbor.schmorp.de/perl-object
30 CBOR_TAG_GENERIC_OBJECT = 25, // http://cbor.schmorp.de/generic-object 30 CBOR_TAG_GENERIC_OBJECT = 25, // http://cbor.schmorp.de/generic-object
31 CBOR_TAG_VALUE_SHARABLE = 26, // http://cbor.schmorp.de/value-sharing 31 CBOR_TAG_VALUE_SHAREABLE = 26, // http://cbor.schmorp.de/value-sharing
32 CBOR_TAG_VALUE_SHAREDREF = 27, // http://cbor.schmorp.de/value-sharing 32 CBOR_TAG_VALUE_SHAREDREF = 27, // http://cbor.schmorp.de/value-sharing
33 CBOR_TAG_STRINGREF_NAMESPACE = 65537, // http://cbor.schmorp.de/stringref 33 CBOR_TAG_STRINGREF_NAMESPACE = 65537, // http://cbor.schmorp.de/stringref
34 CBOR_TAG_STRINGREF = 28, // http://cbor.schmorp.de/stringref 34 CBOR_TAG_STRINGREF = 28, // http://cbor.schmorp.de/stringref
35 CBOR_TAG_INDIRECTION = 22098, // http://cbor.schmorp.de/indirection 35 CBOR_TAG_INDIRECTION = 22098, // http://cbor.schmorp.de/indirection
36 36
136 char *end; // SvEND (sv) 136 char *end; // SvEND (sv)
137 SV *sv; // result scalar 137 SV *sv; // result scalar
138 CBOR cbor; 138 CBOR cbor;
139 U32 depth; // recursion level 139 U32 depth; // recursion level
140 HV *stringref; // string => index, or 0 140 HV *stringref; // string => index, or 0
141 HV *sharable; // ptr => index, or 0 141 HV *shareable; // ptr => index, or 0
142 HV *sharable_idx; 142 UV shareable_idx;
143} enc_t; 143} enc_t;
144 144
145ecb_inline void 145ecb_inline void
146need (enc_t *enc, STRLEN len) 146need (enc_t *enc, STRLEN len)
147{ 147{
214encode_tag (enc_t *enc, UV tag) 214encode_tag (enc_t *enc, UV tag)
215{ 215{
216 encode_uint (enc, 0xc0, tag); 216 encode_uint (enc, 0xc0, tag);
217} 217}
218 218
219static int
220encode_sharable2 (enc_t *enc, SV *sv)
221{
222 if (!enc->sharable)
223 enc->sharable = (HV *)sv_2mortal ((SV *)newHV ());
224
225 SV **svp = hv_fetch (enc->sharable, &sv, sizeof (sv), 1);
226
227 if (SvOK (*svp))
228 {
229 encode_tag (enc, CBOR_TAG_VALUE_SHAREDREF);
230 encode_uint (enc, 0x00, SvUV (*svp));
231
232 return 1;
233 }
234 else
235 {
236 sv_setuv (*svp, enc->sharable_idx++);
237 encode_tag (enc, CBOR_TAG_VALUE_SHARABLE);
238
239 return 0;
240 }
241}
242
243ecb_inline int
244encode_sharable (enc_t *enc, SV *sv)
245{
246 if (ecb_expect_false (enc->cbor.flags & F_ALLOW_SHARING)
247 && ecb_expect_false (SvREFCNT (sv) > 1))
248 return encode_sharable2 (enc, sv);
249
250 return 0;
251}
252
253static void encode_sv (enc_t *enc, SV *sv); 219static void encode_sv (enc_t *enc, SV *sv);
254 220
255static void 221static void
256encode_av (enc_t *enc, AV *av) 222encode_av (enc_t *enc, AV *av)
257{ 223{
309 275
310// encode objects, arrays and special \0=false and \1=true values. 276// encode objects, arrays and special \0=false and \1=true values.
311static void 277static void
312encode_rv (enc_t *enc, SV *sv) 278encode_rv (enc_t *enc, SV *sv)
313{ 279{
314 svtype svt;
315
316 SvGETMAGIC (sv); 280 SvGETMAGIC (sv);
281
282 if (ecb_expect_false (enc->cbor.flags & F_ALLOW_SHARING)
283 && ecb_expect_false (SvREFCNT (sv) > 1))
284 {
285 if (!enc->shareable)
286 enc->shareable = (HV *)sv_2mortal ((SV *)newHV ());
287
288 SV **svp = hv_fetch (enc->shareable, (char *)&sv, sizeof (sv), 1);
289
290 if (SvOK (*svp))
291 {
292 encode_tag (enc, CBOR_TAG_VALUE_SHAREDREF);
293 encode_uint (enc, 0x00, SvUV (*svp));
294 return;
295 }
296 else
297 {
298 sv_setuv (*svp, enc->shareable_idx);
299 ++enc->shareable_idx;
300 encode_tag (enc, CBOR_TAG_VALUE_SHAREABLE);
301 }
302 }
303
317 svt = SvTYPE (sv); 304 svtype svt = SvTYPE (sv);
318
319 if (encode_sharable (enc, sv))
320 return;
321 305
322 if (ecb_expect_false (SvOBJECT (sv))) 306 if (ecb_expect_false (SvOBJECT (sv)))
323 { 307 {
324 HV *boolean_stash = !CBOR_SLOW || types_boolean_stash 308 HV *boolean_stash = !CBOR_SLOW || types_boolean_stash
325 ? types_boolean_stash 309 ? types_boolean_stash
452static void 436static void
453encode_sv (enc_t *enc, SV *sv) 437encode_sv (enc_t *enc, SV *sv)
454{ 438{
455 SvGETMAGIC (sv); 439 SvGETMAGIC (sv);
456 440
457 if (encode_sharable (enc, sv))
458 return;
459
460 if (SvPOKp (sv)) 441 if (SvPOKp (sv))
461 { 442 {
462 STRLEN len; 443 STRLEN len;
463 char *str = SvPV (sv, len); 444 char *str = SvPV (sv, len);
464 encode_str (enc, SvUTF8 (sv), str, len); 445 encode_str (enc, SvUTF8 (sv), str, len);
517 U8 *end; // end of input string 498 U8 *end; // end of input string
518 const char *err; // parse error, if != 0 499 const char *err; // parse error, if != 0
519 CBOR cbor; 500 CBOR cbor;
520 U32 depth; // recursion depth 501 U32 depth; // recursion depth
521 U32 maxdepth; // recursion depth limit 502 U32 maxdepth; // recursion depth limit
522 AV *sharable; 503 AV *shareable;
523} dec_t; 504} dec_t;
524 505
525#define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE 506#define ERR(reason) SB if (!dec->err) dec->err = reason; goto fail; SE
526 507
527#define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data") 508#define WANT(len) if (ecb_expect_false (dec->cur + len > dec->end)) ERR ("unexpected end of CBOR data")
743} 724}
744 725
745static SV * 726static SV *
746decode_tagged (dec_t *dec) 727decode_tagged (dec_t *dec)
747{ 728{
729 SV *sv = 0;
748 UV tag = decode_uint (dec); 730 UV tag = decode_uint (dec);
749 SV *sv = decode_sv (dec); 731
732 WANT (1);
750 733
751 switch (tag) 734 switch (tag)
752 { 735 {
753 case CBOR_TAG_MAGIC: 736 case CBOR_TAG_MAGIC:
754 return sv; 737 return decode_sv (dec);
755 738
756 case CBOR_TAG_INDIRECTION: 739 case CBOR_TAG_INDIRECTION:
757 return newRV_noinc (sv); 740 return newRV_noinc (decode_sv (dec));
758 741
759 case CBOR_TAG_VALUE_SHARABLE: 742 case CBOR_TAG_VALUE_SHAREABLE:
743 {
760 if (ecb_expect_false (!dec->sharable)) 744 if (ecb_expect_false (!dec->shareable))
761 dec->sharable = (AV *)sv_2mortal ((SV *)newAV ()); 745 dec->shareable = (AV *)sv_2mortal ((SV *)newAV ());
762 746
747 sv = newSV (0);
763 av_push (dec->sharable, SvREFCNT_inc_NN (sv)); 748 av_push (dec->shareable, SvREFCNT_inc_NN (sv));
749
750 SV *osv = decode_sv (dec);
751 sv_setsv (sv, osv);
752 SvREFCNT_dec_NN (osv);
753 }
764 754
765 return sv; 755 return sv;
766 756
767 case CBOR_TAG_VALUE_SHAREDREF: 757 case CBOR_TAG_VALUE_SHAREDREF:
768 { 758 {
769 // TODO: should verify that the sv atcually was a CBOR unsigned integer 759 if ((*dec->cur >> 5) != 0)
770 UV idx = SvUV (sv); 760 ERR ("corrupted CBOR data (sharedref index not an unsigned integer)");
771 761
762 UV idx = decode_uint (dec);
763
772 if (!dec->sharable || idx > AvFILLp (dec->sharable)) 764 if (!dec->shareable || idx > AvFILLp (dec->shareable))
773 ERR ("corrupted CBOR data (sharedref index out of bounds)"); 765 ERR ("corrupted CBOR data (sharedref index out of bounds)");
774 766
775 SvREFCNT_dec (sv);
776
777 return SvREFCNT_inc_NN (AvARRAY (dec->sharable)[idx]); 767 return SvREFCNT_inc_NN (AvARRAY (dec->shareable)[idx]);
778 } 768 }
779 769
780 case CBOR_TAG_PERL_OBJECT: 770 case CBOR_TAG_PERL_OBJECT:
781 { 771 {
772 sv = decode_sv (dec);
773
782 if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV) 774 if (!SvROK (sv) || SvTYPE (SvRV (sv)) != SVt_PVAV)
783 ERR ("corrupted CBOR data (non-array perl object)"); 775 ERR ("corrupted CBOR data (non-array perl object)");
784 776
785 AV *av = (AV *)SvRV (sv); 777 AV *av = (AV *)SvRV (sv);
786 int len = av_len (av) + 1; 778 int len = av_len (av) + 1;
827 return sv; 819 return sv;
828 } 820 }
829 821
830 default: 822 default:
831 { 823 {
824 sv = decode_sv (dec);
825
832 AV *av = newAV (); 826 AV *av = newAV ();
833 av_push (av, newSVuv (tag)); 827 av_push (av, newSVuv (tag));
834 av_push (av, sv); 828 av_push (av, sv);
835 829
836 HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash 830 HV *tagged_stash = !CBOR_SLOW || cbor_tagged_stash

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines