• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tarantool / luajit / 7262987147

19 Dec 2023 02:10PM UTC coverage: 88.225% (-0.4%) from 88.616%
7262987147

push

github

fckxorg
test: add tests for debugging extensions

This patch adds tests for LuaJIT debugging
extensions for lldb and gdb.

5336 of 5969 branches covered (0.0%)

Branch coverage included in aggregate %.

20475 of 23287 relevant lines covered (87.92%)

1285545.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.86
/src/lj_strscan.c
1
/*
2
** String scanning.
3
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
4
*/
5

6
#include <math.h>
7

8
#define lj_strscan_c
9
#define LUA_CORE
10

11
#include "lj_obj.h"
12
#include "lj_char.h"
13
#include "lj_strscan.h"
14

15
/* -- Scanning numbers ---------------------------------------------------- */
16

17
/*
18
** Rationale for the builtin string to number conversion library:
19
**
20
** It removes a dependency on libc's strtod(), which is a true portability
21
** nightmare. Mainly due to the plethora of supported OS and toolchain
22
** combinations. Sadly, the various implementations
23
** a) are often buggy, incomplete (no hex floats) and/or imprecise,
24
** b) sometimes crash or hang on certain inputs,
25
** c) return non-standard NaNs that need to be filtered out, and
26
** d) fail if the locale-specific decimal separator is not a dot,
27
**    which can only be fixed with atrocious workarounds.
28
**
29
** Also, most of the strtod() implementations are hopelessly bloated,
30
** which is not just an I-cache hog, but a problem for static linkage
31
** on embedded systems, too.
32
**
33
** OTOH the builtin conversion function is very compact. Even though it
34
** does a lot more, like parsing long longs, octal or imaginary numbers
35
** and returning the result in different formats:
36
** a) It needs less than 3 KB (!) of machine code (on x64 with -Os),
37
** b) it doesn't perform any dynamic allocation and,
38
** c) it needs only around 600 bytes of stack space.
39
**
40
** The builtin function is faster than strtod() for typical inputs, e.g.
41
** "123", "1.5" or "1e6". Arguably, it's slower for very large exponents,
42
** which are not very common (this could be fixed, if needed).
43
**
44
** And most importantly, the builtin function is equally precise on all
45
** platforms. It correctly converts and rounds any input to a double.
46
** If this is not the case, please send a bug report -- but PLEASE verify
47
** that the implementation you're comparing to is not the culprit!
48
**
49
** The implementation quickly pre-scans the entire string first and
50
** handles simple integers on-the-fly. Otherwise, it dispatches to the
51
** base-specific parser. Hex and octal is straightforward.
52
**
53
** Decimal to binary conversion uses a fixed-length circular buffer in
54
** base 100. Some simple cases are handled directly. For other cases, the
55
** number in the buffer is up-scaled or down-scaled until the integer part
56
** is in the proper range. Then the integer part is rounded and converted
57
** to a double which is finally rescaled to the result. Denormals need
58
** special treatment to prevent incorrect 'double rounding'.
59
*/
60

61
/* Definitions for circular decimal digit buffer (base 100 = 2 digits/byte). */
62
#define STRSCAN_DIG        1024
63
#define STRSCAN_MAXDIG        800                /* 772 + extra are sufficient. */
64
#define STRSCAN_DDIG        (STRSCAN_DIG/2)
65
#define STRSCAN_DMASK        (STRSCAN_DDIG-1)
66

67
/* Helpers for circular buffer. */
68
#define DNEXT(a)        (((a)+1) & STRSCAN_DMASK)
69
#define DPREV(a)        (((a)-1) & STRSCAN_DMASK)
70
#define DLEN(lo, hi)        ((int32_t)(((lo)-(hi)) & STRSCAN_DMASK))
71

72
#define casecmp(c, k)        (((c) | 0x20) == k)
73

74
/* Final conversion to double. */
75
static void strscan_double(uint64_t x, TValue *o, int32_t ex2, int32_t neg)
76
{
77
  double n;
78

79
  /* Avoid double rounding for denormals. */
80
  if (LJ_UNLIKELY(ex2 <= -1075 && x != 0)) {
81
    /* NYI: all of this generates way too much code on 32 bit CPUs. */
82
#if defined(__GNUC__) && LJ_64
83
    int32_t b = (int32_t)(__builtin_clzll(x)^63);
84
#else
85
    int32_t b = (x>>32) ? 32+(int32_t)lj_fls((uint32_t)(x>>32)) :
86
                          (int32_t)lj_fls((uint32_t)x);
87
#endif
88
    if ((int32_t)b + ex2 <= -1023 && (int32_t)b + ex2 >= -1075) {
89
      uint64_t rb = (uint64_t)1 << (-1075-ex2);
90
      if ((x & rb) && ((x & (rb+rb+rb-1)))) x += rb+rb;
91
      x = (x & ~(rb+rb-1));
92
    }
93
  }
94

95
  /* Convert to double using a signed int64_t conversion, then rescale. */
96
  lj_assertX((int64_t)x >= 0, "bad double conversion");
97
  n = (double)(int64_t)x;
98
  if (neg) n = -n;
99
  if (ex2) n = ldexp(n, ex2);
100
  o->n = n;
101
}
102

103
/* Parse hexadecimal number. */
104
static StrScanFmt strscan_hex(const uint8_t *p, TValue *o,
853✔
105
                              StrScanFmt fmt, uint32_t opt,
106
                              int32_t ex2, int32_t neg, uint32_t dig)
107
{
108
  uint64_t x = 0;
853✔
109
  uint32_t i;
853✔
110

111
  /* Scan hex digits. */
112
  for (i = dig > 16 ? 16 : dig ; i; i--, p++) {
7,578✔
113
    uint32_t d = (*p != '.' ? *p : *++p); if (d > '9') d += 9;
6,725✔
114
    x = (x << 4) + (d & 15);
6,725✔
115
  }
116

117
  /* Summarize rounding-effect of excess digits. */
118
  for (i = 16; i < dig; i++, p++)
853✔
119
    x |= ((*p != '.' ? *p : *++p) != '0'), ex2 += 4;
×
120

121
  /* Format-specific handling. */
122
  switch (fmt) {
853✔
123
  case STRSCAN_INT:
762✔
124
    if (!(opt & STRSCAN_OPT_TONUM) && x < 0x80000000u+neg &&
762✔
125
        !(x == 0 && neg)) {
×
126
      o->i = neg ? -(int32_t)x : (int32_t)x;
×
127
      return STRSCAN_INT;  /* Fast path for 32 bit integers. */
×
128
    }
129
    if (!(opt & STRSCAN_OPT_C)) { fmt = STRSCAN_NUM; break; }
762✔
130
    /* fallthrough */
131
  case STRSCAN_U32:
132
    if (dig > 8) return STRSCAN_ERROR;
×
133
    o->i = neg ? -(int32_t)x : (int32_t)x;
×
134
    return STRSCAN_U32;
×
135
  case STRSCAN_I64:
52✔
136
  case STRSCAN_U64:
137
    if (dig > 16) return STRSCAN_ERROR;
52✔
138
    o->u64 = neg ? (uint64_t)-(int64_t)x : x;
52✔
139
    return fmt;
52✔
140
  default:
141
    break;
142
  }
143

144
  /* Reduce range, then convert to double. */
145
  if ((x & U64x(c0000000,0000000))) { x = (x >> 2) | (x & 3); ex2 += 2; }
801✔
146
  strscan_double(x, o, ex2, neg);
801✔
147
  return fmt;
801✔
148
}
149

150
/* Parse octal number. */
151
static StrScanFmt strscan_oct(const uint8_t *p, TValue *o,
×
152
                              StrScanFmt fmt, int32_t neg, uint32_t dig)
153
{
154
  uint64_t x = 0;
×
155

156
  /* Scan octal digits. */
157
  if (dig > 22 || (dig == 22 && *p > '1')) return STRSCAN_ERROR;
×
158
  while (dig-- > 0) {
×
159
    if (!(*p >= '0' && *p <= '7')) return STRSCAN_ERROR;
×
160
    x = (x << 3) + (*p++ & 7);
×
161
  }
162

163
  /* Format-specific handling. */
164
  switch (fmt) {
×
165
  case STRSCAN_INT:
×
166
    if (x >= 0x80000000u+neg) fmt = STRSCAN_U32;
×
167
    /* fallthrough */
168
  case STRSCAN_U32:
169
    if ((x >> 32)) return STRSCAN_ERROR;
×
170
    o->i = neg ? -(int32_t)x : (int32_t)x;
×
171
    break;
×
172
  default:
×
173
  case STRSCAN_I64:
174
  case STRSCAN_U64:
175
    o->u64 = neg ? (uint64_t)-(int64_t)x : x;
×
176
    break;
×
177
  }
178
  return fmt;
179
}
180

181
/* Parse decimal number. */
182
static StrScanFmt strscan_dec(const uint8_t *p, TValue *o,
217,737✔
183
                              StrScanFmt fmt, uint32_t opt,
184
                              int32_t ex10, int32_t neg, uint32_t dig)
185
{
186
  uint8_t xi[STRSCAN_DDIG], *xip = xi;
217,737✔
187

188
  if (dig) {
217,737✔
189
    uint32_t i = dig;
217,670✔
190
    if (i > STRSCAN_MAXDIG) {
217,670✔
191
      ex10 += (int32_t)(i - STRSCAN_MAXDIG);
×
192
      i = STRSCAN_MAXDIG;
×
193
    }
194
    /* Scan unaligned leading digit. */
195
    if (((ex10^i) & 1))
217,670✔
196
      *xip++ = ((*p != '.' ? *p : *++p) & 15), i--, p++;
164,941✔
197
    /* Scan aligned double-digits. */
198
    for ( ; i > 1; i -= 2) {
622,705✔
199
      uint32_t d = 10 * ((*p != '.' ? *p : *++p) & 15); p++;
405,035✔
200
      *xip++ = d + ((*p != '.' ? *p : *++p) & 15); p++;
405,035✔
201
    }
202
    /* Scan and realign trailing digit. */
203
    if (i) *xip++ = 10 * ((*p != '.' ? *p : *++p) & 15), ex10--, dig++, p++;
217,670✔
204

205
    /* Summarize rounding-effect of excess digits. */
206
    if (dig > STRSCAN_MAXDIG) {
217,670✔
207
      do {
×
208
        if ((*p != '.' ? *p : *++p) != '0') { xip[-1] |= 1; break; }
×
209
        p++;
×
210
      } while (--dig > STRSCAN_MAXDIG);
×
211
      dig = STRSCAN_MAXDIG;
212
    } else {  /* Simplify exponent. */
213
      while (ex10 > 0 && dig <= 18) *xip++ = 0, ex10 -= 2, dig += 2;
270,198✔
214
    }
215
  } else {  /* Only got zeros. */
216
    ex10 = 0;
67✔
217
    xi[0] = 0;
67✔
218
  }
219

220
  /* Fast path for numbers in integer format (but handles e.g. 1e6, too). */
221
  if (dig <= 20 && ex10 == 0) {
217,737✔
222
    uint8_t *xis;
1,536✔
223
    uint64_t x = xi[0];
1,536✔
224
    double n;
1,536✔
225
    for (xis = xi+1; xis < xip; xis++) x = x * 100 + *xis;
5,612✔
226
    if (!(dig == 20 && (xi[0] > 18 || (int64_t)x >= 0))) {  /* No overflow? */
1,536✔
227
      /* Format-specific handling. */
228
      switch (fmt) {
1,536✔
229
      case STRSCAN_INT:
35✔
230
        if (!(opt & STRSCAN_OPT_TONUM) && x < 0x80000000u+neg) {
35✔
231
          o->i = neg ? -(int32_t)x : (int32_t)x;
×
232
          return STRSCAN_INT;  /* Fast path for 32 bit integers. */
×
233
        }
234
        if (!(opt & STRSCAN_OPT_C)) { fmt = STRSCAN_NUM; goto plainnumber; }
35✔
235
        /* fallthrough */
236
      case STRSCAN_U32:
237
        if ((x >> 32) != 0) return STRSCAN_ERROR;
×
238
        o->i = neg ? -(int32_t)x : (int32_t)x;
×
239
        return STRSCAN_U32;
×
240
      case STRSCAN_I64:
78✔
241
      case STRSCAN_U64:
242
        o->u64 = neg ? (uint64_t)-(int64_t)x : x;
78✔
243
        return fmt;
78✔
244
      default:
245
      plainnumber:  /* Fast path for plain numbers < 2^63. */
1,458✔
246
        if ((int64_t)x < 0) break;
1,458✔
247
        n = (double)(int64_t)x;
1,443✔
248
        if (neg) n = -n;
1,443✔
249
        o->n = n;
1,443✔
250
        return fmt;
1,443✔
251
      }
252
    }
216,216✔
253
  }
254

255
  /* Slow non-integer path. */
256
  if (fmt == STRSCAN_INT) {
216,216✔
257
    if ((opt & STRSCAN_OPT_C)) return STRSCAN_ERROR;
×
258
    fmt = STRSCAN_NUM;
259
  } else if (fmt > STRSCAN_INT) {
216,216✔
260
    return STRSCAN_ERROR;
261
  }
262
  {
263
    uint32_t hi = 0, lo = (uint32_t)(xip-xi);
216,216✔
264
    int32_t ex2 = 0, idig = (int32_t)lo + (ex10 >> 1);
216,216✔
265

266
    lj_assertX(lo > 0 && (ex10 & 1) == 0, "bad lo %d ex10 %d", lo, ex10);
216,216✔
267

268
    /* Handle simple overflow/underflow. */
269
    if (idig > 310/2) { if (neg) setminfV(o); else setpinfV(o); return fmt; }
216,216✔
270
    else if (idig < -326/2) { o->n = neg ? -0.0 : 0.0; return fmt; }
216,214✔
271

272
    /* Scale up until we have at least 17 or 18 integer part digits. */
273
    while (idig < 9 && idig < DLEN(lo, hi)) {
1,138,995✔
274
      uint32_t i, cy = 0;
922,781✔
275
      ex2 -= 6;
922,781✔
276
      for (i = DPREV(lo); ; i = DPREV(i)) {
31,173,623✔
277
        uint32_t d = (xi[i] << 6) + cy;
31,173,623✔
278
        cy = (((d >> 2) * 5243) >> 17); d = d - cy * 100;  /* Div/mod 100. */
31,173,623✔
279
        xi[i] = (uint8_t)d;
31,173,623✔
280
        if (i == hi) break;
31,173,623✔
281
        if (d == 0 && i == DPREV(lo)) lo = i;
30,250,842✔
282
      }
283
      if (cy) {
922,781✔
284
        hi = DPREV(hi);
829,035✔
285
        if (xi[DPREV(lo)] == 0) lo = DPREV(lo);
829,035✔
286
        else if (hi == lo) { lo = DPREV(lo); xi[DPREV(lo)] |= xi[lo]; }
828,698✔
287
        xi[hi] = (uint8_t)cy; idig++;
829,035✔
288
      }
289
    }
290

291
    /* Scale down until no more than 17 or 18 integer part digits remain. */
292
    while (idig > 9) {
622,719✔
293
      uint32_t i = hi, cy = 0;
406,505✔
294
      ex2 += 6;
406,505✔
295
      do {
42,878,851✔
296
        cy += xi[i];
42,878,851✔
297
        xi[i] = (cy >> 6);
42,878,851✔
298
        cy = 100 * (cy & 0x3f);
42,878,851✔
299
        if (xi[i] == 0 && i == hi) hi = DNEXT(hi), idig--;
42,878,851✔
300
        i = DNEXT(i);
42,878,851✔
301
      } while (i != lo);
42,878,851✔
302
      while (cy) {
1,577,264✔
303
        if (hi == lo) { xi[DPREV(lo)] |= 1; break; }
1,170,759✔
304
        xi[lo] = (cy >> 6); lo = DNEXT(lo);
1,170,759✔
305
        cy = 100 * (cy & 0x3f);
1,170,759✔
306
      }
307
    }
308

309
    /* Collect integer part digits and convert to rescaled double. */
310
    {
311
      uint64_t x = xi[hi];
216,214✔
312
      uint32_t i;
216,214✔
313
      for (i = DNEXT(hi); --idig > 0 && i != lo; i = DNEXT(i))
912,636✔
314
        x = x * 100 + xi[i];
696,422✔
315
      if (i == lo) {
216,214✔
316
        while (--idig >= 0) x = x * 100;
200,115✔
317
      } else {  /* Gather round bit from remaining digits. */
318
        x <<= 1; ex2--;
24,167✔
319
        do {
24,243✔
320
          if (xi[i]) { x |= 1; break; }
24,243✔
321
          i = DNEXT(i);
76✔
322
        } while (i != lo);
76✔
323
      }
324
      strscan_double(x, o, ex2, neg);
216,214✔
325
    }
326
  }
327
  return fmt;
216,214✔
328
}
329

330
/* Parse binary number. */
331
static StrScanFmt strscan_bin(const uint8_t *p, TValue *o,
×
332
                              StrScanFmt fmt, uint32_t opt,
333
                              int32_t ex2, int32_t neg, uint32_t dig)
334
{
335
  uint64_t x = 0;
×
336
  uint32_t i;
×
337

338
  if (ex2 || dig > 64) return STRSCAN_ERROR;
×
339

340
  /* Scan binary digits. */
341
  for (i = dig; i; i--, p++) {
×
342
    if ((*p & ~1) != '0') return STRSCAN_ERROR;
×
343
    x = (x << 1) | (*p & 1);
×
344
  }
345

346
  /* Format-specific handling. */
347
  switch (fmt) {
×
348
  case STRSCAN_INT:
×
349
    if (!(opt & STRSCAN_OPT_TONUM) && x < 0x80000000u+neg) {
×
350
      o->i = neg ? -(int32_t)x : (int32_t)x;
×
351
      return STRSCAN_INT;  /* Fast path for 32 bit integers. */
×
352
    }
353
    if (!(opt & STRSCAN_OPT_C)) { fmt = STRSCAN_NUM; break; }
×
354
    /* fallthrough */
355
  case STRSCAN_U32:
356
    if (dig > 32) return STRSCAN_ERROR;
×
357
    o->i = neg ? -(int32_t)x : (int32_t)x;
×
358
    return STRSCAN_U32;
×
359
  case STRSCAN_I64:
×
360
  case STRSCAN_U64:
361
    o->u64 = neg ? (uint64_t)-(int64_t)x : x;
×
362
    return fmt;
×
363
  default:
364
    break;
365
  }
366

367
  /* Reduce range, then convert to double. */
368
  if ((x & U64x(c0000000,0000000))) { x = (x >> 2) | (x & 3); ex2 += 2; }
×
369
  strscan_double(x, o, ex2, neg);
×
370
  return fmt;
×
371
}
372

373
/* Scan string containing a number. Returns format. Returns value in o. */
374
StrScanFmt lj_strscan_scan(const uint8_t *p, MSize len, TValue *o,
714,739✔
375
                           uint32_t opt)
376
{
377
  int32_t neg = 0;
714,739✔
378
  const uint8_t *pe = p + len;
714,739✔
379

380
  /* Remove leading space, parse sign and non-numbers. */
381
  if (LJ_UNLIKELY(!lj_char_isdigit(*p))) {
714,739✔
382
    while (lj_char_isspace(*p)) p++;
343✔
383
    if (*p == '+' || *p == '-') neg = (*p++ == '-');
315✔
384
    if (LJ_UNLIKELY(*p >= 'A')) {  /* Parse "inf", "infinity" or "nan". */
315✔
385
      TValue tmp;
48✔
386
      setnanV(&tmp);
48✔
387
      if (casecmp(p[0],'i') && casecmp(p[1],'n') && casecmp(p[2],'f')) {
48✔
388
        if (neg) setminfV(&tmp); else setpinfV(&tmp);
×
389
        p += 3;
×
390
        if (casecmp(p[0],'i') && casecmp(p[1],'n') && casecmp(p[2],'i') &&
×
391
            casecmp(p[3],'t') && casecmp(p[4],'y')) p += 5;
×
392
      } else if (casecmp(p[0],'n') && casecmp(p[1],'a') && casecmp(p[2],'n')) {
48✔
393
        p += 3;
×
394
      }
395
      while (lj_char_isspace(*p)) p++;
48✔
396
      if (*p || p < pe) return STRSCAN_ERROR;
48✔
397
      o->u64 = tmp.u64;
×
398
      return STRSCAN_NUM;
×
399
    }
400
  }
401

402
  /* Parse regular number. */
403
  {
404
    StrScanFmt fmt = STRSCAN_INT;
714,691✔
405
    int cmask = LJ_CHAR_DIGIT;
714,691✔
406
    int base = (opt & STRSCAN_OPT_C) && *p == '0' ? 0 : 10;
714,691✔
407
    const uint8_t *sp, *dp = NULL;
714,691✔
408
    uint32_t dig = 0, hasdig = 0, x = 0;
714,691✔
409
    int32_t ex = 0;
714,691✔
410

411
    /* Determine base and skip leading zeros. */
412
    if (LJ_UNLIKELY(*p <= '0')) {
714,691✔
413
      if (*p == '0') {
13,588✔
414
        if (casecmp(p[1], 'x'))
13,371✔
415
          base = 16, cmask = LJ_CHAR_XDIGIT, p += 2;
853✔
416
        else if (casecmp(p[1], 'b'))
12,518✔
417
          base = 2, cmask = LJ_CHAR_DIGIT, p += 2;
2✔
418
      }
419
      for ( ; ; p++) {
20,517✔
420
        if (*p == '0') {
34,105✔
421
          hasdig = 1;
422
        } else if (*p == '.') {
21,129✔
423
          if (dp) return STRSCAN_ERROR;
7,541✔
424
          dp = p;
425
        } else {
426
          break;
427
        }
428
      }
429
    }
430

431
    /* Preliminary digit and decimal point scan. */
432
    for (sp = p; ; p++) {
2,843,688✔
433
      if (LJ_LIKELY(lj_char_isa(*p, cmask))) {
2,843,688✔
434
        x = x * 10 + (*p & 15);  /* For fast path below. */
1,934,669✔
435
        dig++;
1,934,669✔
436
      } else if (*p == '.') {
909,019✔
437
        if (dp) return STRSCAN_ERROR;
194,329✔
438
        dp = p;
439
      } else {
440
        break;
441
      }
442
    }
443
    if (!(hasdig | dig)) return STRSCAN_ERROR;
714,690✔
444

445
    /* Handle decimal point. */
446
    if (dp) {
714,685✔
447
      if (base == 2) return STRSCAN_ERROR;
201,866✔
448
      fmt = STRSCAN_NUM;
201,864✔
449
      if (dig) {
201,864✔
450
        ex = (int32_t)(dp-(p-1)); dp = p-1;
201,813✔
451
        while (ex < 0 && *dp-- == '0') ex++, dig--;  /* Skip trailing zeros. */
201,994✔
452
        if (base == 16) ex *= 4;
201,813✔
453
      }
454
    }
455

456
    /* Parse exponent. */
457
    if (base >= 10 && casecmp(*p, (uint32_t)(base == 16 ? 'p' : 'e'))) {
1,428,513✔
458
      uint32_t xx;
18,442✔
459
      int negx = 0;
18,442✔
460
      fmt = STRSCAN_NUM; p++;
18,442✔
461
      if (*p == '+' || *p == '-') negx = (*p++ == '-');
18,442✔
462
      if (!lj_char_isdigit(*p)) return STRSCAN_ERROR;
18,442✔
463
      xx = (*p++ & 15);
18,386✔
464
      while (lj_char_isdigit(*p)) {
46,232✔
465
        if (xx < 65536) xx = xx * 10 + (*p & 15);
27,846✔
466
        p++;
27,846✔
467
      }
468
      ex += negx ? -(int32_t)xx : (int32_t)xx;
18,386✔
469
    }
470

471
    /* Parse suffix. */
472
    if (*p) {
714,627✔
473
      /* I (IMAG), U (U32), LL (I64), ULL/LLU (U64), L (long), UL/LU (ulong). */
474
      /* NYI: f (float). Not needed until cp_number() handles non-integers. */
475
      if (casecmp(*p, 'i')) {
158✔
476
        if (!(opt & STRSCAN_OPT_IMAG)) return STRSCAN_ERROR;
10✔
477
        p++; fmt = STRSCAN_IMAG;
9✔
478
      } else if (fmt == STRSCAN_INT) {
148✔
479
        if (casecmp(*p, 'u')) p++, fmt = STRSCAN_U32;
138✔
480
        if (casecmp(*p, 'l')) {
138✔
481
          p++;
130✔
482
          if (casecmp(*p, 'l')) p++, fmt += STRSCAN_I64 - STRSCAN_INT;
130✔
483
          else if (!(opt & STRSCAN_OPT_C)) return STRSCAN_ERROR;
×
484
          else if (sizeof(long) == 8) fmt += STRSCAN_I64 - STRSCAN_INT;
×
485
        }
486
        if (casecmp(*p, 'u') && (fmt == STRSCAN_INT || fmt == STRSCAN_I64))
138✔
487
          p++, fmt += STRSCAN_U32 - STRSCAN_INT;
×
488
        if ((fmt == STRSCAN_U32 && !(opt & STRSCAN_OPT_C)) ||
138✔
489
            (fmt >= STRSCAN_I64 && !(opt & STRSCAN_OPT_LL)))
130✔
490
          return STRSCAN_ERROR;
491
      }
492
      while (lj_char_isspace(*p)) p++;
181✔
493
      if (*p) return STRSCAN_ERROR;
157✔
494
    }
495
    if (p < pe) return STRSCAN_ERROR;
714,623✔
496

497
    /* Fast path for decimal 32 bit integers. */
498
    if (fmt == STRSCAN_INT && base == 10 &&
714,622✔
499
        (dig < 10 || (dig == 10 && *sp <= '2' && x < 0x80000000u+neg))) {
103✔
500
      if ((opt & STRSCAN_OPT_TONUM)) {
496,032✔
501
        o->n = neg ? -(double)x : (double)x;
495,913✔
502
        return STRSCAN_NUM;
495,913✔
503
      } else if (x == 0 && neg) {
119✔
504
        o->n = -0.0;
×
505
        return STRSCAN_NUM;
×
506
      } else {
507
        o->i = neg ? -(int32_t)x : (int32_t)x;
119✔
508
        return STRSCAN_INT;
119✔
509
      }
510
    }
511

512
    /* Dispatch to base-specific parser. */
513
    if (base == 0 && !(fmt == STRSCAN_NUM || fmt == STRSCAN_IMAG))
218,590✔
514
      return strscan_oct(sp, o, fmt, neg, dig);
×
515
    if (base == 16)
218,590✔
516
      fmt = strscan_hex(sp, o, fmt, opt, ex, neg, dig);
853✔
517
    else if (base == 2)
217,737✔
518
      fmt = strscan_bin(sp, o, fmt, opt, ex, neg, dig);
×
519
    else
520
      fmt = strscan_dec(sp, o, fmt, opt, ex, neg, dig);
217,737✔
521

522
    /* Try to convert number to integer, if requested. */
523
    if (fmt == STRSCAN_NUM && (opt & STRSCAN_OPT_TOINT) && !tvismzero(o)) {
218,590✔
524
      double n = o->n;
×
525
      int32_t i = lj_num2int(n);
×
526
      if (n == (lua_Number)i) { o->i = i; return STRSCAN_INT; }
×
527
    }
528
    return fmt;
529
  }
530
}
531

532
int LJ_FASTCALL lj_strscan_num(GCstr *str, TValue *o)
22,366✔
533
{
534
  StrScanFmt fmt = lj_strscan_scan((const uint8_t *)strdata(str), str->len, o,
22,366✔
535
                                   STRSCAN_OPT_TONUM);
536
  lj_assertX(fmt == STRSCAN_ERROR || fmt == STRSCAN_NUM, "bad scan format");
22,366✔
537
  return (fmt != STRSCAN_ERROR);
22,366✔
538
}
539

540
#if LJ_DUALNUM
541
int LJ_FASTCALL lj_strscan_number(GCstr *str, TValue *o)
542
{
543
  StrScanFmt fmt = lj_strscan_scan((const uint8_t *)strdata(str), str->len, o,
544
                                   STRSCAN_OPT_TOINT);
545
  lj_assertX(fmt == STRSCAN_ERROR || fmt == STRSCAN_NUM || fmt == STRSCAN_INT,
546
             "bad scan format");
547
  if (fmt == STRSCAN_INT) setitype(o, LJ_TISNUM);
548
  return (fmt != STRSCAN_ERROR);
549
}
550
#endif
551

552
#undef DNEXT
553
#undef DPREV
554
#undef DLEN
555

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc