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.38 by root, Sun Dec 1 14:30:52 2013 UTC vs.
Revision 1.50 by root, Thu Feb 25 02:29:22 2016 UTC

7#include <stdlib.h> 7#include <stdlib.h>
8#include <stdio.h> 8#include <stdio.h>
9#include <limits.h> 9#include <limits.h>
10#include <float.h> 10#include <float.h>
11 11
12#define ECB_NO_THREADS 1
12#include "ecb.h" 13#include "ecb.h"
13 14
14// compatibility with perl <5.18 15// compatibility with perl <5.18
15#ifndef HvNAMELEN_get 16#ifndef HvNAMELEN_get
16# define HvNAMELEN_get(hv) strlen (HvNAME (hv)) 17# define HvNAMELEN_get(hv) strlen (HvNAME (hv))
128typedef struct { 129typedef struct {
129 U32 flags; 130 U32 flags;
130 U32 max_depth; 131 U32 max_depth;
131 STRLEN max_size; 132 STRLEN max_size;
132 SV *filter; 133 SV *filter;
134
135 // for the incremental parser
136 STRLEN incr_pos; // the current offset into the text
137 STRLEN incr_need; // minimum bytes needed to decode
138 AV *incr_count; // for every nesting level, the number of outstanding values, or -1 for indef.
133} CBOR; 139} CBOR;
134 140
135ecb_inline void 141ecb_inline void
136cbor_init (CBOR *cbor) 142cbor_init (CBOR *cbor)
137{ 143{
141 147
142ecb_inline void 148ecb_inline void
143cbor_free (CBOR *cbor) 149cbor_free (CBOR *cbor)
144{ 150{
145 SvREFCNT_dec (cbor->filter); 151 SvREFCNT_dec (cbor->filter);
152 SvREFCNT_dec (cbor->incr_count);
146} 153}
147 154
148///////////////////////////////////////////////////////////////////////////// 155/////////////////////////////////////////////////////////////////////////////
149// utility functions 156// utility functions
150 157
317 324
318 ++enc->depth; 325 ++enc->depth;
319 326
320 encode_uint (enc, MAJOR_ARRAY, len + 1); 327 encode_uint (enc, MAJOR_ARRAY, len + 1);
321 328
329 if (SvMAGICAL (av))
322 for (i = 0; i <= len; ++i) 330 for (i = 0; i <= len; ++i)
323 { 331 {
324 SV **svp = av_fetch (av, i, 0); 332 SV **svp = av_fetch (av, i, 0);
325 encode_sv (enc, svp ? *svp : &PL_sv_undef); 333 encode_sv (enc, svp ? *svp : &PL_sv_undef);
326 } 334 }
335 else
336 for (i = 0; i <= len; ++i)
337 {
338 SV *sv = AvARRAY (av)[i];
339 encode_sv (enc, sv ? sv : &PL_sv_undef);
340 }
327 341
328 --enc->depth; 342 --enc->depth;
329} 343}
330 344
331static void 345static void
435 449
436 if ((method = gv_fetchmethod_autoload (stash, "TO_CBOR", 0))) 450 if ((method = gv_fetchmethod_autoload (stash, "TO_CBOR", 0)))
437 { 451 {
438 dSP; 452 dSP;
439 453
440 ENTER; SAVETMPS; PUSHMARK (SP); 454 ENTER; SAVETMPS;
455 PUSHMARK (SP);
441 // we re-bless the reference to get overload and other niceties right 456 // we re-bless the reference to get overload and other niceties right
442 XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); 457 XPUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash));
443 458
444 PUTBACK; 459 PUTBACK;
445 // G_SCALAR ensures that return value is 1 460 // G_SCALAR ensures that return value is 1
458 } 473 }
459 else if ((method = gv_fetchmethod_autoload (stash, "FREEZE", 0)) != 0) 474 else if ((method = gv_fetchmethod_autoload (stash, "FREEZE", 0)) != 0)
460 { 475 {
461 dSP; 476 dSP;
462 477
463 ENTER; SAVETMPS; PUSHMARK (SP); 478 ENTER; SAVETMPS;
479 SAVESTACK_POS ();
480 PUSHMARK (SP);
464 EXTEND (SP, 2); 481 EXTEND (SP, 2);
465 // we re-bless the reference to get overload and other niceties right 482 // we re-bless the reference to get overload and other niceties right
466 PUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash)); 483 PUSHs (sv_bless (sv_2mortal (newRV_inc (sv)), stash));
467 PUSHs (sv_cbor); 484 PUSHs (sv_cbor);
468 485
570} 587}
571 588
572static SV * 589static SV *
573encode_cbor (SV *scalar, CBOR *cbor) 590encode_cbor (SV *scalar, CBOR *cbor)
574{ 591{
575 enc_t enc = { }; 592 enc_t enc = { 0 };
576 593
577 enc.cbor = *cbor; 594 enc.cbor = *cbor;
578 enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); 595 enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE));
579 enc.cur = SvPVX (enc.sv); 596 enc.cur = SvPVX (enc.sv);
580 enc.end = SvEND (enc.sv); 597 enc.end = SvEND (enc.sv);
730{ 747{
731 // for speed reasons, we specialcase single-string 748 // for speed reasons, we specialcase single-string
732 // byte or utf-8 strings as keys, but only when !stringref 749 // byte or utf-8 strings as keys, but only when !stringref
733 750
734 if (ecb_expect_true (!dec->stringref)) 751 if (ecb_expect_true (!dec->stringref))
735 if (ecb_expect_true ((*dec->cur - MAJOR_BYTES) <= LENGTH_EXT8)) 752 if (ecb_expect_true ((U8)(*dec->cur - MAJOR_BYTES) <= LENGTH_EXT8))
736 { 753 {
737 I32 len = decode_uint (dec); 754 I32 len = decode_uint (dec);
738 char *key = (char *)dec->cur; 755 char *key = (char *)dec->cur;
739 756
757 WANT (len);
740 dec->cur += len; 758 dec->cur += len;
741 759
742 hv_store (hv, key, len, decode_sv (dec), 0); 760 hv_store (hv, key, len, decode_sv (dec), 0);
743 761
744 return; 762 return;
745 } 763 }
746 else if (ecb_expect_true ((*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8)) 764 else if (ecb_expect_true ((U8)(*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8))
747 { 765 {
748 I32 len = decode_uint (dec); 766 I32 len = decode_uint (dec);
749 char *key = (char *)dec->cur; 767 char *key = (char *)dec->cur;
750 768
769 WANT (len);
751 dec->cur += len; 770 dec->cur += len;
752 771
753 if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8)) 772 if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
754 if (!is_utf8_string (key, len)) 773 if (!is_utf8_string (key, len))
755 ERR ("corrupted CBOR data (invalid UTF-8 in map key)"); 774 ERR ("corrupted CBOR data (invalid UTF-8 in map key)");
978 if (!method) 997 if (!method)
979 ERR ("cannot decode perl-object (package does not have a THAW method)"); 998 ERR ("cannot decode perl-object (package does not have a THAW method)");
980 999
981 dSP; 1000 dSP;
982 1001
983 ENTER; SAVETMPS; PUSHMARK (SP); 1002 ENTER; SAVETMPS;
1003 PUSHMARK (SP);
984 EXTEND (SP, len + 1); 1004 EXTEND (SP, len + 1);
985 // we re-bless the reference to get overload and other niceties right 1005 // we re-bless the reference to get overload and other niceties right
986 PUSHs (*av_fetch (av, 0, 1)); 1006 PUSHs (*av_fetch (av, 0, 1));
987 PUSHs (sv_cbor); 1007 PUSHs (sv_cbor);
988 1008
1013 default: 1033 default:
1014 { 1034 {
1015 sv = decode_sv (dec); 1035 sv = decode_sv (dec);
1016 1036
1017 dSP; 1037 dSP;
1018 ENTER; SAVETMPS; PUSHMARK (SP); 1038 ENTER; SAVETMPS;
1039 SAVESTACK_POS ();
1040 PUSHMARK (SP);
1019 EXTEND (SP, 2); 1041 EXTEND (SP, 2);
1020 PUSHs (newSVuv (tag)); 1042 PUSHs (newSVuv (tag));
1021 PUSHs (sv); 1043 PUSHs (sv);
1022 1044
1023 PUTBACK; 1045 PUTBACK;
1132 1154
1133 return newSVnv (ecb_binary64_to_double (fp)); 1155 return newSVnv (ecb_binary64_to_double (fp));
1134 } 1156 }
1135 1157
1136 // 0..19 unassigned simple 1158 // 0..19 unassigned simple
1137 // 24 reserved + unassigned (reserved values are not encodable) 1159 // 24 reserved + unassigned simple (reserved values are not encodable)
1160 // 28-30 unassigned misc
1161 // 31 break code
1138 default: 1162 default:
1139 ERR ("corrupted CBOR data (reserved/unassigned major 7 value)"); 1163 ERR ("corrupted CBOR data (reserved/unassigned/unexpected major 7 value)");
1140 } 1164 }
1141 1165
1142 break; 1166 break;
1143 } 1167 }
1144 1168
1147} 1171}
1148 1172
1149static SV * 1173static SV *
1150decode_cbor (SV *string, CBOR *cbor, char **offset_return) 1174decode_cbor (SV *string, CBOR *cbor, char **offset_return)
1151{ 1175{
1152 dec_t dec = { }; 1176 dec_t dec = { 0 };
1153 SV *sv; 1177 SV *sv;
1154 STRLEN len; 1178 STRLEN len;
1155 char *data = SvPVbyte (string, len); 1179 char *data = SvPVbyte (string, len);
1156 1180
1157 if (len > cbor->max_size && cbor->max_size) 1181 if (len > cbor->max_size && cbor->max_size)
1171 if (dec.cur != dec.end && !dec.err) 1195 if (dec.cur != dec.end && !dec.err)
1172 dec.err = "garbage after CBOR object"; 1196 dec.err = "garbage after CBOR object";
1173 1197
1174 if (dec.err) 1198 if (dec.err)
1175 { 1199 {
1200 if (dec.shareable)
1201 {
1202 // need to break cyclic links, which whould all be in shareable
1203 int i;
1204 SV **svp;
1205
1206 for (i = av_len (dec.shareable) + 1; i--; )
1207 if ((svp = av_fetch (dec.shareable, i, 0)))
1208 sv_setsv (*svp, &PL_sv_undef);
1209 }
1210
1176 SvREFCNT_dec (sv); 1211 SvREFCNT_dec (sv);
1177 croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur); 1212 croak ("%s, at offset %d (octet 0x%02x)", dec.err, dec.cur - (U8 *)data, (int)(uint8_t)*dec.cur);
1178 } 1213 }
1179 1214
1180 sv = sv_2mortal (sv); 1215 sv = sv_2mortal (sv);
1181 1216
1182 return sv; 1217 return sv;
1183} 1218}
1184 1219
1220/////////////////////////////////////////////////////////////////////////////
1221// incremental parser
1222
1223#define INCR_DONE(cbor) (AvFILLp (cbor->incr_count) < 0)
1224
1225// returns 0 for notyet, 1 for success or error
1226static int
1227incr_parse (CBOR *self, SV *cborstr)
1228{
1229 STRLEN cur;
1230 SvPV (cborstr, cur);
1231
1232 while (ecb_expect_true (self->incr_need <= cur))
1233 {
1234 // table of integer count bytes
1235 static I8 incr_len[MINOR_MASK + 1] = {
1236 0, 0, 0, 0, 0, 0, 0, 0,
1237 0, 0, 0, 0, 0, 0, 0, 0,
1238 0, 0, 0, 0, 0, 0, 0, 0,
1239 1, 2, 4, 8,-1,-1,-1,-2
1240 };
1241
1242 const U8 *p = SvPVX (cborstr) + self->incr_pos;
1243 U8 m = *p & MINOR_MASK;
1244 IV count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1245 I8 ilen = incr_len[m];
1246
1247 self->incr_need = self->incr_pos + 1;
1248
1249 if (ecb_expect_false (ilen < 0))
1250 {
1251 if (m != MINOR_INDEF)
1252 return 1; // error
1253
1254 if (*p == (MAJOR_MISC | MINOR_INDEF))
1255 {
1256 if (count >= 0)
1257 return 1; // error
1258
1259 count = 1;
1260 }
1261 else
1262 {
1263 av_push (self->incr_count, newSViv (-1)); //TODO: nest
1264 count = -1;
1265 }
1266 }
1267 else
1268 {
1269 self->incr_need += ilen;
1270 if (ecb_expect_false (self->incr_need > cur))
1271 return 0;
1272
1273 int major = *p >> MAJOR_SHIFT;
1274
1275 switch (major)
1276 {
1277 case MAJOR_TAG >> MAJOR_SHIFT:
1278 ++count; // tags merely prefix another value
1279 break;
1280
1281 case MAJOR_BYTES >> MAJOR_SHIFT:
1282 case MAJOR_TEXT >> MAJOR_SHIFT:
1283 case MAJOR_ARRAY >> MAJOR_SHIFT:
1284 case MAJOR_MAP >> MAJOR_SHIFT:
1285 {
1286 UV len;
1287
1288 if (ecb_expect_false (ilen))
1289 {
1290 len = 0;
1291
1292 do {
1293 len = (len << 8) | *++p;
1294 } while (--ilen);
1295 }
1296 else
1297 len = m;
1298
1299 switch (major)
1300 {
1301 case MAJOR_BYTES >> MAJOR_SHIFT:
1302 case MAJOR_TEXT >> MAJOR_SHIFT:
1303 self->incr_need += len;
1304 if (ecb_expect_false (self->incr_need > cur))
1305 return 0;
1306
1307 break;
1308
1309 case MAJOR_MAP >> MAJOR_SHIFT:
1310 len <<= 1;
1311 case MAJOR_ARRAY >> MAJOR_SHIFT:
1312 if (len)
1313 {
1314 av_push (self->incr_count, newSViv (len + 1)); //TODO: nest
1315 count = len + 1;
1316 }
1317 break;
1318 }
1319 }
1320 }
1321 }
1322
1323 self->incr_pos = self->incr_need;
1324
1325 if (count > 0)
1326 {
1327 while (!--count)
1328 {
1329 if (!AvFILLp (self->incr_count))
1330 return 1; // done
1331
1332 SvREFCNT_dec_NN (av_pop (self->incr_count));
1333 count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1334 }
1335
1336 SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]) = count;
1337 }
1338 }
1339
1340 return 0;
1341}
1342
1343
1185///////////////////////////////////////////////////////////////////////////// 1344/////////////////////////////////////////////////////////////////////////////
1186// XS interface functions 1345// XS interface functions
1187 1346
1188MODULE = CBOR::XS PACKAGE = CBOR::XS 1347MODULE = CBOR::XS PACKAGE = CBOR::XS
1189 1348
1308 EXTEND (SP, 2); 1467 EXTEND (SP, 2);
1309 PUSHs (sv); 1468 PUSHs (sv);
1310 PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr)))); 1469 PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr))));
1311} 1470}
1312 1471
1472void incr_parse (CBOR *self, SV *cborstr)
1473 ALIAS:
1474 incr_parse_multiple = 1
1475 PPCODE:
1476{
1477 if (SvUTF8 (cborstr))
1478 sv_utf8_downgrade (cborstr, 0);
1479
1480 if (!self->incr_count)
1481 {
1482 self->incr_count = newAV ();
1483 self->incr_pos = 0;
1484 self->incr_need = 1;
1485
1486 av_push (self->incr_count, newSViv (1));
1487 }
1488
1489 do
1490 {
1491 if (!incr_parse (self, cborstr))
1492 {
1493 if (self->incr_need > self->max_size && self->max_size)
1494 croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
1495 (unsigned long)self->incr_need, (unsigned long)self->max_size);
1496
1497 break;
1498 }
1499
1500 SV *sv;
1501 char *offset;
1502
1503 PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1504 XPUSHs (sv);
1505
1506 sv_chop (cborstr, offset);
1507
1508 av_clear (self->incr_count);
1509 av_push (self->incr_count, newSViv (1));
1510
1511 self->incr_pos = 0;
1512 self->incr_need = self->incr_pos + 1;
1513 }
1514 while (ix);
1515}
1516
1517void incr_reset (CBOR *self)
1518 CODE:
1519{
1520 SvREFCNT_dec (self->incr_count);
1521 self->incr_count = 0;
1522}
1523
1313void DESTROY (CBOR *self) 1524void DESTROY (CBOR *self)
1314 PPCODE: 1525 PPCODE:
1315 cbor_free (self); 1526 cbor_free (self);
1316 1527
1317PROTOTYPES: ENABLE 1528PROTOTYPES: ENABLE

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines