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.39 by root, Sun Dec 1 14:45:03 2013 UTC vs.
Revision 1.49 by root, Mon Feb 8 04:11:11 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
570} 584}
571 585
572static SV * 586static SV *
573encode_cbor (SV *scalar, CBOR *cbor) 587encode_cbor (SV *scalar, CBOR *cbor)
574{ 588{
575 enc_t enc = { }; 589 enc_t enc = { 0 };
576 590
577 enc.cbor = *cbor; 591 enc.cbor = *cbor;
578 enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE)); 592 enc.sv = sv_2mortal (NEWSV (0, INIT_SIZE));
579 enc.cur = SvPVX (enc.sv); 593 enc.cur = SvPVX (enc.sv);
580 enc.end = SvEND (enc.sv); 594 enc.end = SvEND (enc.sv);
730{ 744{
731 // for speed reasons, we specialcase single-string 745 // for speed reasons, we specialcase single-string
732 // byte or utf-8 strings as keys, but only when !stringref 746 // byte or utf-8 strings as keys, but only when !stringref
733 747
734 if (ecb_expect_true (!dec->stringref)) 748 if (ecb_expect_true (!dec->stringref))
735 if (ecb_expect_true ((*dec->cur - MAJOR_BYTES) <= LENGTH_EXT8)) 749 if (ecb_expect_true ((U8)(*dec->cur - MAJOR_BYTES) <= LENGTH_EXT8))
736 { 750 {
737 I32 len = decode_uint (dec); 751 I32 len = decode_uint (dec);
738 char *key = (char *)dec->cur; 752 char *key = (char *)dec->cur;
739 753
754 WANT (len);
740 dec->cur += len; 755 dec->cur += len;
741 756
742 hv_store (hv, key, len, decode_sv (dec), 0); 757 hv_store (hv, key, len, decode_sv (dec), 0);
743 758
744 return; 759 return;
745 } 760 }
746 else if (ecb_expect_true ((*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8)) 761 else if (ecb_expect_true ((U8)(*dec->cur - MAJOR_TEXT) <= LENGTH_EXT8))
747 { 762 {
748 I32 len = decode_uint (dec); 763 I32 len = decode_uint (dec);
749 char *key = (char *)dec->cur; 764 char *key = (char *)dec->cur;
750 765
766 WANT (len);
751 dec->cur += len; 767 dec->cur += len;
752 768
753 if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8)) 769 if (ecb_expect_false (dec->cbor.flags & F_VALIDATE_UTF8))
754 if (!is_utf8_string (key, len)) 770 if (!is_utf8_string (key, len))
755 ERR ("corrupted CBOR data (invalid UTF-8 in map key)"); 771 ERR ("corrupted CBOR data (invalid UTF-8 in map key)");
1132 1148
1133 return newSVnv (ecb_binary64_to_double (fp)); 1149 return newSVnv (ecb_binary64_to_double (fp));
1134 } 1150 }
1135 1151
1136 // 0..19 unassigned simple 1152 // 0..19 unassigned simple
1137 // 24 reserved + unassigned (reserved values are not encodable) 1153 // 24 reserved + unassigned simple (reserved values are not encodable)
1154 // 28-30 unassigned misc
1155 // 31 break code
1138 default: 1156 default:
1139 ERR ("corrupted CBOR data (reserved/unassigned major 7 value)"); 1157 ERR ("corrupted CBOR data (reserved/unassigned/unexpected major 7 value)");
1140 } 1158 }
1141 1159
1142 break; 1160 break;
1143 } 1161 }
1144 1162
1147} 1165}
1148 1166
1149static SV * 1167static SV *
1150decode_cbor (SV *string, CBOR *cbor, char **offset_return) 1168decode_cbor (SV *string, CBOR *cbor, char **offset_return)
1151{ 1169{
1152 dec_t dec = { }; 1170 dec_t dec = { 0 };
1153 SV *sv; 1171 SV *sv;
1154 STRLEN len; 1172 STRLEN len;
1155 char *data = SvPVbyte (string, len); 1173 char *data = SvPVbyte (string, len);
1156 1174
1157 if (len > cbor->max_size && cbor->max_size) 1175 if (len > cbor->max_size && cbor->max_size)
1191 sv = sv_2mortal (sv); 1209 sv = sv_2mortal (sv);
1192 1210
1193 return sv; 1211 return sv;
1194} 1212}
1195 1213
1214/////////////////////////////////////////////////////////////////////////////
1215// incremental parser
1216
1217#define INCR_DONE(cbor) (AvFILLp (cbor->incr_count) < 0)
1218
1219// returns 0 for notyet, 1 for success or error
1220static int
1221incr_parse (CBOR *self, SV *cborstr)
1222{
1223 STRLEN cur;
1224 SvPV (cborstr, cur);
1225
1226 while (ecb_expect_true (self->incr_need <= cur))
1227 {
1228 // table of integer count bytes
1229 static I8 incr_len[MINOR_MASK + 1] = {
1230 0, 0, 0, 0, 0, 0, 0, 0,
1231 0, 0, 0, 0, 0, 0, 0, 0,
1232 0, 0, 0, 0, 0, 0, 0, 0,
1233 1, 2, 4, 8,-1,-1,-1,-2
1234 };
1235
1236 const U8 *p = SvPVX (cborstr) + self->incr_pos;
1237 U8 m = *p & MINOR_MASK;
1238 IV count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1239 I8 ilen = incr_len[m];
1240
1241 self->incr_need = self->incr_pos + 1;
1242
1243 if (ecb_expect_false (ilen < 0))
1244 {
1245 if (m != MINOR_INDEF)
1246 return 1; // error
1247
1248 if (*p == (MAJOR_MISC | MINOR_INDEF))
1249 {
1250 if (count >= 0)
1251 return 1; // error
1252
1253 count = 1;
1254 }
1255 else
1256 {
1257 av_push (self->incr_count, newSViv (-1)); //TODO: nest
1258 count = -1;
1259 }
1260 }
1261 else
1262 {
1263 self->incr_need += ilen;
1264 if (ecb_expect_false (self->incr_need > cur))
1265 return 0;
1266
1267 int major = *p >> MAJOR_SHIFT;
1268
1269 switch (major)
1270 {
1271 case MAJOR_TAG >> MAJOR_SHIFT:
1272 ++count; // tags merely prefix another value
1273 break;
1274
1275 case MAJOR_BYTES >> MAJOR_SHIFT:
1276 case MAJOR_TEXT >> MAJOR_SHIFT:
1277 case MAJOR_ARRAY >> MAJOR_SHIFT:
1278 case MAJOR_MAP >> MAJOR_SHIFT:
1279 {
1280 UV len;
1281
1282 if (ecb_expect_false (ilen))
1283 {
1284 len = 0;
1285
1286 do {
1287 len = (len << 8) | *++p;
1288 } while (--ilen);
1289 }
1290 else
1291 len = m;
1292
1293 switch (major)
1294 {
1295 case MAJOR_BYTES >> MAJOR_SHIFT:
1296 case MAJOR_TEXT >> MAJOR_SHIFT:
1297 self->incr_need += len;
1298 if (ecb_expect_false (self->incr_need > cur))
1299 return 0;
1300
1301 break;
1302
1303 case MAJOR_MAP >> MAJOR_SHIFT:
1304 len <<= 1;
1305 case MAJOR_ARRAY >> MAJOR_SHIFT:
1306 if (len)
1307 {
1308 av_push (self->incr_count, newSViv (len + 1)); //TODO: nest
1309 count = len + 1;
1310 }
1311 break;
1312 }
1313 }
1314 }
1315 }
1316
1317 self->incr_pos = self->incr_need;
1318
1319 if (count > 0)
1320 {
1321 while (!--count)
1322 {
1323 if (!AvFILLp (self->incr_count))
1324 return 1; // done
1325
1326 SvREFCNT_dec_NN (av_pop (self->incr_count));
1327 count = SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]);
1328 }
1329
1330 SvIVX (AvARRAY (self->incr_count)[AvFILLp (self->incr_count)]) = count;
1331 }
1332 }
1333
1334 return 0;
1335}
1336
1337
1196///////////////////////////////////////////////////////////////////////////// 1338/////////////////////////////////////////////////////////////////////////////
1197// XS interface functions 1339// XS interface functions
1198 1340
1199MODULE = CBOR::XS PACKAGE = CBOR::XS 1341MODULE = CBOR::XS PACKAGE = CBOR::XS
1200 1342
1319 EXTEND (SP, 2); 1461 EXTEND (SP, 2);
1320 PUSHs (sv); 1462 PUSHs (sv);
1321 PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr)))); 1463 PUSHs (sv_2mortal (newSVuv (offset - SvPVX (cborstr))));
1322} 1464}
1323 1465
1466void incr_parse (CBOR *self, SV *cborstr)
1467 ALIAS:
1468 incr_parse_multiple = 1
1469 PPCODE:
1470{
1471 if (SvUTF8 (cborstr))
1472 sv_utf8_downgrade (cborstr, 0);
1473
1474 if (!self->incr_count)
1475 {
1476 self->incr_count = newAV ();
1477 self->incr_pos = 0;
1478 self->incr_need = 1;
1479
1480 av_push (self->incr_count, newSViv (1));
1481 }
1482
1483 do
1484 {
1485 if (!incr_parse (self, cborstr))
1486 {
1487 if (self->incr_need > self->max_size && self->max_size)
1488 croak ("attempted decode of CBOR text of %lu bytes size, but max_size is set to %lu",
1489 (unsigned long)self->incr_need, (unsigned long)self->max_size);
1490
1491 break;
1492 }
1493
1494 SV *sv;
1495 char *offset;
1496
1497 PUTBACK; sv = decode_cbor (cborstr, self, &offset); SPAGAIN;
1498 XPUSHs (sv);
1499
1500 sv_chop (cborstr, offset);
1501
1502 av_clear (self->incr_count);
1503 av_push (self->incr_count, newSViv (1));
1504
1505 self->incr_pos = 0;
1506 self->incr_need = self->incr_pos + 1;
1507 }
1508 while (ix);
1509}
1510
1511void incr_reset (CBOR *self)
1512 CODE:
1513{
1514 SvREFCNT_dec (self->incr_count);
1515 self->incr_count = 0;
1516}
1517
1324void DESTROY (CBOR *self) 1518void DESTROY (CBOR *self)
1325 PPCODE: 1519 PPCODE:
1326 cbor_free (self); 1520 cbor_free (self);
1327 1521
1328PROTOTYPES: ENABLE 1522PROTOTYPES: ENABLE

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines