aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/ext_ffi_api.html4
-rw-r--r--doc/extensions.html2
-rw-r--r--src/lj_strscan.c57
3 files changed, 56 insertions, 7 deletions
diff --git a/doc/ext_ffi_api.html b/doc/ext_ffi_api.html
index 8cf48dc3..b095c05f 100644
--- a/doc/ext_ffi_api.html
+++ b/doc/ext_ffi_api.html
@@ -546,8 +546,8 @@ corresponding ctype.
546The parser for Lua source code treats numeric literals with the 546The parser for Lua source code treats numeric literals with the
547suffixes <tt>LL</tt> or <tt>ULL</tt> as signed or unsigned 64&nbsp;bit 547suffixes <tt>LL</tt> or <tt>ULL</tt> as signed or unsigned 64&nbsp;bit
548integers. Case doesn't matter, but uppercase is recommended for 548integers. Case doesn't matter, but uppercase is recommended for
549readability. It handles both decimal (<tt>42LL</tt>) and hexadecimal 549readability. It handles decimal (<tt>42LL</tt>), hexadecimal
550(<tt>0x2aLL</tt>) literals. 550(<tt>0x2aLL</tt>) and binary (<tt>0b101010LL</tt>) literals.
551</p> 551</p>
552<p> 552<p>
553The imaginary part of complex numbers can be specified by suffixing 553The imaginary part of complex numbers can be specified by suffixing
diff --git a/doc/extensions.html b/doc/extensions.html
index d2f8d7ba..3122051d 100644
--- a/doc/extensions.html
+++ b/doc/extensions.html
@@ -183,7 +183,7 @@ in <tt>"-inf"</tt>.
183<h3 id="tonumber"><tt>tonumber()</tt> etc. use builtin string to number conversion</h3> 183<h3 id="tonumber"><tt>tonumber()</tt> etc. use builtin string to number conversion</h3>
184<p> 184<p>
185All string-to-number conversions consistently convert integer and 185All string-to-number conversions consistently convert integer and
186floating-point inputs in decimal and hexadecimal on all platforms. 186floating-point inputs in decimal, hexadecimal and binary on all platforms.
187<tt>strtod()</tt> is <em>not</em> used anymore, which avoids numerous 187<tt>strtod()</tt> is <em>not</em> used anymore, which avoids numerous
188problems with poor C library implementations. The builtin conversion 188problems with poor C library implementations. The builtin conversion
189function provides full precision according to the IEEE-754 standard, it 189function provides full precision according to the IEEE-754 standard, it
diff --git a/src/lj_strscan.c b/src/lj_strscan.c
index 568f647d..d3c5ba91 100644
--- a/src/lj_strscan.c
+++ b/src/lj_strscan.c
@@ -140,7 +140,7 @@ static StrScanFmt strscan_hex(const uint8_t *p, TValue *o,
140 break; 140 break;
141 } 141 }
142 142
143 /* Reduce range then convert to double. */ 143 /* Reduce range, then convert to double. */
144 if ((x & U64x(c0000000,0000000))) { x = (x >> 2) | (x & 3); ex2 += 2; } 144 if ((x & U64x(c0000000,0000000))) { x = (x >> 2) | (x & 3); ex2 += 2; }
145 strscan_double(x, o, ex2, neg); 145 strscan_double(x, o, ex2, neg);
146 return fmt; 146 return fmt;
@@ -326,6 +326,49 @@ static StrScanFmt strscan_dec(const uint8_t *p, TValue *o,
326 return fmt; 326 return fmt;
327} 327}
328 328
329/* Parse binary number. */
330static StrScanFmt strscan_bin(const uint8_t *p, TValue *o,
331 StrScanFmt fmt, uint32_t opt,
332 int32_t ex2, int32_t neg, uint32_t dig)
333{
334 uint64_t x = 0;
335 uint32_t i;
336
337 if (ex2 || dig > 64) return STRSCAN_ERROR;
338
339 /* Scan binary digits. */
340 for (i = dig; i; i--, p++) {
341 if ((*p & ~1) != '0') return STRSCAN_ERROR;
342 x = (x << 1) | (*p & 1);
343 }
344
345 /* Format-specific handling. */
346 switch (fmt) {
347 case STRSCAN_INT:
348 if (!(opt & STRSCAN_OPT_TONUM) && x < 0x80000000u+neg) {
349 o->i = neg ? -(int32_t)x : (int32_t)x;
350 return STRSCAN_INT; /* Fast path for 32 bit integers. */
351 }
352 if (!(opt & STRSCAN_OPT_C)) { fmt = STRSCAN_NUM; break; }
353 /* fallthrough */
354 case STRSCAN_U32:
355 if (dig > 32) return STRSCAN_ERROR;
356 o->i = neg ? -(int32_t)x : (int32_t)x;
357 return STRSCAN_U32;
358 case STRSCAN_I64:
359 case STRSCAN_U64:
360 o->u64 = neg ? (uint64_t)-(int64_t)x : x;
361 return fmt;
362 default:
363 break;
364 }
365
366 /* Reduce range, then convert to double. */
367 if ((x & U64x(c0000000,0000000))) { x = (x >> 2) | (x & 3); ex2 += 2; }
368 strscan_double(x, o, ex2, neg);
369 return fmt;
370}
371
329/* Scan string containing a number. Returns format. Returns value in o. */ 372/* Scan string containing a number. Returns format. Returns value in o. */
330StrScanFmt lj_strscan_scan(const uint8_t *p, TValue *o, uint32_t opt) 373StrScanFmt lj_strscan_scan(const uint8_t *p, TValue *o, uint32_t opt)
331{ 374{
@@ -364,8 +407,12 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, TValue *o, uint32_t opt)
364 407
365 /* Determine base and skip leading zeros. */ 408 /* Determine base and skip leading zeros. */
366 if (LJ_UNLIKELY(*p <= '0')) { 409 if (LJ_UNLIKELY(*p <= '0')) {
367 if (*p == '0' && casecmp(p[1], 'x')) 410 if (*p == '0') {
368 base = 16, cmask = LJ_CHAR_XDIGIT, p += 2; 411 if (casecmp(p[1], 'x'))
412 base = 16, cmask = LJ_CHAR_XDIGIT, p += 2;
413 else if (casecmp(p[1], 'b'))
414 base = 2, cmask = LJ_CHAR_DIGIT, p += 2;
415 }
369 for ( ; ; p++) { 416 for ( ; ; p++) {
370 if (*p == '0') { 417 if (*p == '0') {
371 hasdig = 1; 418 hasdig = 1;
@@ -403,7 +450,7 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, TValue *o, uint32_t opt)
403 } 450 }
404 451
405 /* Parse exponent. */ 452 /* Parse exponent. */
406 if (casecmp(*p, (uint32_t)(base == 16 ? 'p' : 'e'))) { 453 if (base >= 10 && casecmp(*p, (uint32_t)(base == 16 ? 'p' : 'e'))) {
407 uint32_t xx; 454 uint32_t xx;
408 int negx = 0; 455 int negx = 0;
409 fmt = STRSCAN_NUM; p++; 456 fmt = STRSCAN_NUM; p++;
@@ -460,6 +507,8 @@ StrScanFmt lj_strscan_scan(const uint8_t *p, TValue *o, uint32_t opt)
460 return strscan_oct(sp, o, fmt, neg, dig); 507 return strscan_oct(sp, o, fmt, neg, dig);
461 if (base == 16) 508 if (base == 16)
462 fmt = strscan_hex(sp, o, fmt, opt, ex, neg, dig); 509 fmt = strscan_hex(sp, o, fmt, opt, ex, neg, dig);
510 else if (base == 2)
511 fmt = strscan_bin(sp, o, fmt, opt, ex, neg, dig);
463 else 512 else
464 fmt = strscan_dec(sp, o, fmt, opt, ex, neg, dig); 513 fmt = strscan_dec(sp, o, fmt, opt, ex, neg, dig);
465 514