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.128 by root, Fri Oct 7 05:18:48 2016 UTC vs.
Revision 1.131 by root, Thu Aug 17 01:42:20 2017 UTC

6#include <string.h> 6#include <string.h>
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#include <inttypes.h>
11 12
12#if defined(__BORLANDC__) || defined(_MSC_VER) 13#if defined(__BORLANDC__) || defined(_MSC_VER)
13# define snprintf _snprintf // C compilers have this in stdio.h 14# define snprintf _snprintf // C compilers have this in stdio.h
14#endif 15#endif
15 16
154 SvPV_renew (sv, SvCUR (sv) + 1); 155 SvPV_renew (sv, SvCUR (sv) + 1);
155#endif 156#endif
156 } 157 }
157} 158}
158 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
159// 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
160// case of an error. 186// case of an error.
161// we special-case "safe" characters from U+80 .. U+7FF, 187// we special-case "safe" characters from U+80 .. U+7FF,
162// but use the very good perl function to parse anything else. 188// but use the very good perl function to parse anything else.
163// note that we never call this function for a ascii codepoints 189// note that we never call this function for a ascii codepoints
361} enc_t; 387} enc_t;
362 388
363INLINE void 389INLINE void
364need (enc_t *enc, STRLEN len) 390need (enc_t *enc, STRLEN len)
365{ 391{
366 if (expect_false (enc->cur + len >= enc->end)) 392 if (expect_false ((uintptr_t)(enc->end - enc->cur) < len))
367 { 393 {
368 STRLEN cur = enc->cur - (char *)SvPVX (enc->sv); 394 STRLEN cur = enc->cur - (char *)SvPVX (enc->sv);
369 SvGROW (enc->sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 395 char *buf = json_sv_grow (enc->sv, cur, len);
370 enc->cur = SvPVX (enc->sv) + cur; 396 enc->cur = buf + cur;
371 enc->end = SvPVX (enc->sv) + SvLEN (enc->sv) - 1; 397 enc->end = buf + SvLEN (enc->sv) - 1;
372 } 398 }
373} 399}
374 400
375INLINE void 401INLINE void
376encode_ch (enc_t *enc, char ch) 402encode_ch (enc_t *enc, char ch)
392 418
393 if (expect_true (ch >= 0x20 && ch < 0x80)) // most common case 419 if (expect_true (ch >= 0x20 && ch < 0x80)) // most common case
394 { 420 {
395 if (expect_false (ch == '"')) // but with slow exceptions 421 if (expect_false (ch == '"')) // but with slow exceptions
396 { 422 {
397 need (enc, len += 1); 423 need (enc, len + 1);
398 *enc->cur++ = '\\'; 424 *enc->cur++ = '\\';
399 *enc->cur++ = '"'; 425 *enc->cur++ = '"';
400 } 426 }
401 else if (expect_false (ch == '\\')) 427 else if (expect_false (ch == '\\'))
402 { 428 {
403 need (enc, len += 1); 429 need (enc, len + 1);
404 *enc->cur++ = '\\'; 430 *enc->cur++ = '\\';
405 *enc->cur++ = '\\'; 431 *enc->cur++ = '\\';
406 } 432 }
407 else 433 else
408 *enc->cur++ = ch; 434 *enc->cur++ = ch;
411 } 437 }
412 else 438 else
413 { 439 {
414 switch (ch) 440 switch (ch)
415 { 441 {
416 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;
417 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;
418 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;
419 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;
420 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;
421 447
422 default: 448 default:
423 { 449 {
424 STRLEN clen; 450 STRLEN clen;
425 UV uch; 451 UV uch;
441 if (uch >= 0x10000UL) 467 if (uch >= 0x10000UL)
442 { 468 {
443 if (uch >= 0x110000UL) 469 if (uch >= 0x110000UL)
444 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);
445 471
446 need (enc, len += 11); 472 need (enc, len + 11);
447 sprintf (enc->cur, "\\u%04x\\u%04x", 473 sprintf (enc->cur, "\\u%04x\\u%04x",
448 (int)((uch - 0x10000) / 0x400 + 0xD800), 474 (int)((uch - 0x10000) / 0x400 + 0xD800),
449 (int)((uch - 0x10000) % 0x400 + 0xDC00)); 475 (int)((uch - 0x10000) % 0x400 + 0xDC00));
450 enc->cur += 12; 476 enc->cur += 12;
451 } 477 }
452 else 478 else
453 { 479 {
454 need (enc, len += 5); 480 need (enc, len + 5);
455 *enc->cur++ = '\\'; 481 *enc->cur++ = '\\';
456 *enc->cur++ = 'u'; 482 *enc->cur++ = 'u';
457 *enc->cur++ = PL_hexdigit [ uch >> 12 ]; 483 *enc->cur++ = PL_hexdigit [ uch >> 12 ];
458 *enc->cur++ = PL_hexdigit [(uch >> 8) & 15]; 484 *enc->cur++ = PL_hexdigit [(uch >> 8) & 15];
459 *enc->cur++ = PL_hexdigit [(uch >> 4) & 15]; 485 *enc->cur++ = PL_hexdigit [(uch >> 4) & 15];
467 *enc->cur++ = uch; 493 *enc->cur++ = uch;
468 str += clen; 494 str += clen;
469 } 495 }
470 else if (is_utf8) 496 else if (is_utf8)
471 { 497 {
472 need (enc, len += clen); 498 need (enc, len + clen);
473 do 499 do
474 { 500 {
475 *enc->cur++ = *str++; 501 *enc->cur++ = *str++;
476 } 502 }
477 while (--clen); 503 while (--clen);
478 } 504 }
479 else 505 else
480 { 506 {
481 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
482 enc->cur = encode_utf8 (enc->cur, uch); 508 enc->cur = encode_utf8 (enc->cur, uch);
483 ++str; 509 ++str;
484 } 510 }
485 } 511 }
486 } 512 }
1167 1193
1168 if (sv) 1194 if (sv)
1169 { 1195 {
1170 STRLEN cur = SvCUR (sv); 1196 STRLEN cur = SvCUR (sv);
1171 1197
1172 if (SvLEN (sv) <= cur + len) 1198 if (SvLEN (sv) - cur <= len)
1173 SvGROW (sv, cur + (len < (cur >> 2) ? cur >> 2 : len) + 1); 1199 json_sv_grow (sv, cur, len);
1174 1200
1175 memcpy (SvPVX (sv) + SvCUR (sv), buf, len); 1201 memcpy (SvPVX (sv) + SvCUR (sv), buf, len);
1176 SvCUR_set (sv, SvCUR (sv) + len); 1202 SvCUR_set (sv, SvCUR (sv) + len);
1177 } 1203 }
1178 else 1204 else
1689fail: 1715fail:
1690 return 0; 1716 return 0;
1691} 1717}
1692 1718
1693static SV * 1719static SV *
1694decode_json (SV *string, JSON *json, char **offset_return) 1720decode_json (SV *string, JSON *json, STRLEN *offset_return)
1695{ 1721{
1696 dec_t dec; 1722 dec_t dec;
1697 SV *sv; 1723 SV *sv;
1698 1724
1699 /* work around bugs in 5.10 where manipulating magic values 1725 /* work around bugs in 5.10 where manipulating magic values
1752 1778
1753 decode_ws (&dec); 1779 decode_ws (&dec);
1754 sv = decode_sv (&dec); 1780 sv = decode_sv (&dec);
1755 1781
1756 if (offset_return) 1782 if (offset_return)
1757 *offset_return = dec.cur; 1783 *offset_return = dec.cur - SvPVX (string);
1758 1784 else if (sv)
1759 if (!(offset_return || !sv))
1760 { 1785 {
1761 // check for trailing garbage 1786 // check for trailing garbage
1762 decode_ws (&dec); 1787 decode_ws (&dec);
1763 1788
1764 if (*dec.cur) 1789 if (*dec.cur)
2111 2136
2112void decode_prefix (JSON *self, SV *jsonstr) 2137void decode_prefix (JSON *self, SV *jsonstr)
2113 PPCODE: 2138 PPCODE:
2114{ 2139{
2115 SV *sv; 2140 SV *sv;
2116 char *offset; 2141 STRLEN offset;
2117 PUTBACK; sv = decode_json (jsonstr, self, &offset); SPAGAIN; 2142 PUTBACK; sv = decode_json (jsonstr, self, &offset); SPAGAIN;
2118 EXTEND (SP, 2); 2143 EXTEND (SP, 2);
2119 PUSHs (sv); 2144 PUSHs (sv);
2120 PUSHs (sv_2mortal (newSVuv (ptr_to_index (jsonstr, offset)))); 2145 PUSHs (sv_2mortal (newSVuv (ptr_to_index (jsonstr, SvPV_nolen (jsonstr) + offset))));
2121} 2146}
2122 2147
2123void incr_parse (JSON *self, SV *jsonstr = 0) 2148void incr_parse (JSON *self, SV *jsonstr = 0)
2124 PPCODE: 2149 PPCODE:
2125{ 2150{
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 }
2172 2197
2173 if (GIMME_V != G_VOID) 2198 if (GIMME_V != G_VOID)
2174 do 2199 do
2175 { 2200 {
2176 SV *sv; 2201 SV *sv;
2177 char *offset; 2202 STRLEN offset;
2178 2203
2179 if (!INCR_DONE (self)) 2204 if (!INCR_DONE (self))
2180 { 2205 {
2181 incr_parse (self); 2206 incr_parse (self);
2182 2207
2198 } 2223 }
2199 2224
2200 PUTBACK; sv = decode_json (self->incr_text, self, &offset); SPAGAIN; 2225 PUTBACK; sv = decode_json (self->incr_text, self, &offset); SPAGAIN;
2201 XPUSHs (sv); 2226 XPUSHs (sv);
2202 2227
2203 self->incr_pos -= offset - SvPVX (self->incr_text); 2228 self->incr_pos -= offset;
2204 self->incr_nest = 0; 2229 self->incr_nest = 0;
2205 self->incr_mode = 0; 2230 self->incr_mode = 0;
2206 2231
2207 sv_chop (self->incr_text, offset); 2232 sv_chop (self->incr_text, SvPVX (self->incr_text) + offset);
2208 } 2233 }
2209 while (GIMME_V == G_ARRAY); 2234 while (GIMME_V == G_ARRAY);
2210} 2235}
2211 2236
2212SV *incr_text (JSON *self) 2237SV *incr_text (JSON *self)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines