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

Comparing JSON-XS/XS.xs (file contents):
Revision 1.130 by root, Sat Nov 26 06:09:29 2016 UTC vs.
Revision 1.131 by root, Thu Aug 17 01:42:20 2017 UTC

155 SvPV_renew (sv, SvCUR (sv) + 1); 155 SvPV_renew (sv, SvCUR (sv) + 1);
156#endif 156#endif
157 } 157 }
158} 158}
159 159
160/* adds two STRLENs together, slow, and with paranoia */
161STRLEN
162strlen_sum (STRLEN l1, STRLEN l2)
163{
164 size_t sum = l1 + l2;
165
166 if (sum < (size_t)l2 || sum != (size_t)(STRLEN)sum)
167 croak ("JSON::XS: string size overflow");
168
169 return sum;
170}
171
172/* similar to SvGROW, but somewhat safer and guarantees exponential realloc strategy */
173static char *
174json_sv_grow (SV *sv, size_t len1, size_t len2)
175{
176 len1 = strlen_sum (len1, len2);
177 len1 = strlen_sum (len1, len1 >> 1);
178
179 if (len1 > 4096 - 24)
180 len1 = (len1 | 4095) - 24;
181
182 return SvGROW (sv, len1);
183}
184
160// decode an utf-8 character and return it, or (UV)-1 in 185// decode an utf-8 character and return it, or (UV)-1 in
161// case of an error. 186// case of an error.
162// we special-case "safe" characters from U+80 .. U+7FF, 187// we special-case "safe" characters from U+80 .. U+7FF,
163// but use the very good perl function to parse anything else. 188// but use the very good perl function to parse anything else.
164// note that we never call this function for a ascii codepoints 189// note that we never call this function for a ascii codepoints
365need (enc_t *enc, STRLEN len) 390need (enc_t *enc, STRLEN len)
366{ 391{
367 if (expect_false ((uintptr_t)(enc->end - enc->cur) < len)) 392 if (expect_false ((uintptr_t)(enc->end - enc->cur) < len))
368 { 393 {
369 STRLEN cur = enc->cur - (char *)SvPVX (enc->sv); 394 STRLEN cur = enc->cur - (char *)SvPVX (enc->sv);
370 SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 395 char *buf = json_sv_grow (enc->sv, cur, len);
371 enc->cur = SvPVX (enc->sv) + cur; 396 enc->cur = buf + cur;
372 enc->end = SvPVX (enc->sv) + SvLEN (enc->sv) - 1; 397 enc->end = buf + SvLEN (enc->sv) - 1;
373 } 398 }
374} 399}
375 400
376INLINE void 401INLINE void
377encode_ch (enc_t *enc, char ch) 402encode_ch (enc_t *enc, char ch)
393 418
394 if (expect_true (ch >= 0x20 && ch < 0x80)) // most common case 419 if (expect_true (ch >= 0x20 && ch < 0x80)) // most common case
395 { 420 {
396 if (expect_false (ch == '"')) // but with slow exceptions 421 if (expect_false (ch == '"')) // but with slow exceptions
397 { 422 {
398 need (enc, len += 1); 423 need (enc, len + 1);
399 *enc->cur++ = '\\'; 424 *enc->cur++ = '\\';
400 *enc->cur++ = '"'; 425 *enc->cur++ = '"';
401 } 426 }
402 else if (expect_false (ch == '\\')) 427 else if (expect_false (ch == '\\'))
403 { 428 {
404 need (enc, len += 1); 429 need (enc, len + 1);
405 *enc->cur++ = '\\'; 430 *enc->cur++ = '\\';
406 *enc->cur++ = '\\'; 431 *enc->cur++ = '\\';
407 } 432 }
408 else 433 else
409 *enc->cur++ = ch; 434 *enc->cur++ = ch;
412 } 437 }
413 else 438 else
414 { 439 {
415 switch (ch) 440 switch (ch)
416 { 441 {
417 case '\010': need (enc, len += 1); *enc->cur++ = '\\'; *enc->cur++ = 'b'; ++str; break; 442 case '\010': need (enc, len + 1); *enc->cur++ = '\\'; *enc->cur++ = 'b'; ++str; break;
418 case '\011': need (enc, len += 1); *enc->cur++ = '\\'; *enc->cur++ = 't'; ++str; break; 443 case '\011': need (enc, len + 1); *enc->cur++ = '\\'; *enc->cur++ = 't'; ++str; break;
419 case '\012': need (enc, len += 1); *enc->cur++ = '\\'; *enc->cur++ = 'n'; ++str; break; 444 case '\012': need (enc, len + 1); *enc->cur++ = '\\'; *enc->cur++ = 'n'; ++str; break;
420 case '\014': need (enc, len += 1); *enc->cur++ = '\\'; *enc->cur++ = 'f'; ++str; break; 445 case '\014': need (enc, len + 1); *enc->cur++ = '\\'; *enc->cur++ = 'f'; ++str; break;
421 case '\015': need (enc, len += 1); *enc->cur++ = '\\'; *enc->cur++ = 'r'; ++str; break; 446 case '\015': need (enc, len + 1); *enc->cur++ = '\\'; *enc->cur++ = 'r'; ++str; break;
422 447
423 default: 448 default:
424 { 449 {
425 STRLEN clen; 450 STRLEN clen;
426 UV uch; 451 UV uch;
442 if (uch >= 0x10000UL) 467 if (uch >= 0x10000UL)
443 { 468 {
444 if (uch >= 0x110000UL) 469 if (uch >= 0x110000UL)
445 croak ("out of range codepoint (0x%lx) encountered, unrepresentable in JSON", (unsigned long)uch); 470 croak ("out of range codepoint (0x%lx) encountered, unrepresentable in JSON", (unsigned long)uch);
446 471
447 need (enc, len += 11); 472 need (enc, len + 11);
448 sprintf (enc->cur, "\\u%04x\\u%04x", 473 sprintf (enc->cur, "\\u%04x\\u%04x",
449 (int)((uch - 0x10000) / 0x400 + 0xD800), 474 (int)((uch - 0x10000) / 0x400 + 0xD800),
450 (int)((uch - 0x10000) % 0x400 + 0xDC00)); 475 (int)((uch - 0x10000) % 0x400 + 0xDC00));
451 enc->cur += 12; 476 enc->cur += 12;
452 } 477 }
453 else 478 else
454 { 479 {
455 need (enc, len += 5); 480 need (enc, len + 5);
456 *enc->cur++ = '\\'; 481 *enc->cur++ = '\\';
457 *enc->cur++ = 'u'; 482 *enc->cur++ = 'u';
458 *enc->cur++ = PL_hexdigit [ uch >> 12 ]; 483 *enc->cur++ = PL_hexdigit [ uch >> 12 ];
459 *enc->cur++ = PL_hexdigit [(uch >> 8) & 15]; 484 *enc->cur++ = PL_hexdigit [(uch >> 8) & 15];
460 *enc->cur++ = PL_hexdigit [(uch >> 4) & 15]; 485 *enc->cur++ = PL_hexdigit [(uch >> 4) & 15];
468 *enc->cur++ = uch; 493 *enc->cur++ = uch;
469 str += clen; 494 str += clen;
470 } 495 }
471 else if (is_utf8) 496 else if (is_utf8)
472 { 497 {
473 need (enc, len += clen); 498 need (enc, len + clen);
474 do 499 do
475 { 500 {
476 *enc->cur++ = *str++; 501 *enc->cur++ = *str++;
477 } 502 }
478 while (--clen); 503 while (--clen);
479 } 504 }
480 else 505 else
481 { 506 {
482 need (enc, len += UTF8_MAXBYTES - 1); // never more than 11 bytes needed 507 need (enc, len + UTF8_MAXBYTES - 1); // never more than 11 bytes needed
483 enc->cur = encode_utf8 (enc->cur, uch); 508 enc->cur = encode_utf8 (enc->cur, uch);
484 ++str; 509 ++str;
485 } 510 }
486 } 511 }
487 } 512 }
1168 1193
1169 if (sv) 1194 if (sv)
1170 { 1195 {
1171 STRLEN cur = SvCUR (sv); 1196 STRLEN cur = SvCUR (sv);
1172 1197
1173 if (SvLEN (sv) <= cur + len) 1198 if (SvLEN (sv) - cur <= len)
1174 SvGROW (sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 1199 json_sv_grow (sv, cur, len);
1175 1200
1176 memcpy (SvPVX (sv) + SvCUR (sv), buf, len); 1201 memcpy (SvPVX (sv) + SvCUR (sv), buf, len);
1177 SvCUR_set (sv, SvCUR (sv) + len); 1202 SvCUR_set (sv, SvCUR (sv) + len);
1178 } 1203 }
1179 else 1204 else
2159 { 2184 {
2160 STRLEN len; 2185 STRLEN len;
2161 const char *str = SvPV (jsonstr, len); 2186 const char *str = SvPV (jsonstr, len);
2162 STRLEN cur = SvCUR (self->incr_text); 2187 STRLEN cur = SvCUR (self->incr_text);
2163 2188
2164 if (SvLEN (self->incr_text) <= cur + len) 2189 if (SvLEN (self->incr_text) - cur <= len)
2165 SvGROW (self->incr_text, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 2190 json_sv_grow (self->incr_text, cur, len);
2166 2191
2167 Move (str, SvEND (self->incr_text), len, char); 2192 Move (str, SvEND (self->incr_text), len, char);
2168 SvCUR_set (self->incr_text, SvCUR (self->incr_text) + len); 2193 SvCUR_set (self->incr_text, SvCUR (self->incr_text) + len);
2169 *SvEND (self->incr_text) = 0; // this should basically be a nop, too, but make sure it's there 2194 *SvEND (self->incr_text) = 0; // this should basically be a nop, too, but make sure it's there
2170 } 2195 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines