Skip to content

Commit 6977d68

Browse files
committed
Parse Infinity and -Infinity if JSONSL_PARSE_NAN defined
1 parent 9787ae5 commit 6977d68

File tree

5 files changed

+48
-13
lines changed

5 files changed

+48
-13
lines changed

README.pod

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -355,12 +355,14 @@ instead of the good 'ole C<char>. Of course you would need to
355355
handle processing the stream correctly to make sure the multibyte
356356
stream was complete.
357357

358-
=head2 NaN
358+
=head2 NaN, Infinity, -Infinity
359359

360-
By default, JSONSL does not consider an object like C<{"n": NaN}> to be valid
361-
syntax. Compile with C<JSONSL_PARSE_NAN> defined to parse NaN as "not-a-number".
360+
By default, JSONSL does not consider objects like C<{"n": NaN}>,
361+
C<{"n": Infinity}>, or C<{"n": -Infinity}> to be valid.
362+
Compile with C<JSONSL_PARSE_NAN> defined to parse these non-numbers.
362363
JSONSL will then execute your POP callback with C<state-E<gt>special_flags> set
363-
to C<JSONSL_SPECIALf_NUMNOINT | JSONSL_SPECIALf_NAN> when it parses a NaN.
364+
to C<JSONSL_SPECIALf_NAN> when it parses NaN, C<JSONSL_SPECIALf_INF> for
365+
Infinity, and C<JSONSL_SPECIALf_INF | JSONSL_SPECIALf_SIGNED> for -Infinity.
364366

365367
=head2 WINDOWS
366368

json_samples.tgz

826 Bytes
Binary file not shown.

jsonsl.c

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,11 @@ jsonsl_feed(jsonsl_t jsn, const jsonsl_char_t *bytes, size_t nbytes)
287287
INVOKE_ERROR(SPECIAL_EXPECTED); \
288288
}
289289

290+
#define VERIFY_SPECIAL_CI(lit) \
291+
if (tolower(CUR_CHAR) != (lit)[jsn->pos - state->pos_begin]) { \
292+
INVOKE_ERROR(SPECIAL_EXPECTED); \
293+
}
294+
290295
#define STATE_SPECIAL_LENGTH \
291296
(state)->nescapes
292297

@@ -350,6 +355,14 @@ jsonsl_feed(jsonsl_t jsn, const jsonsl_char_t *bytes, size_t nbytes)
350355
goto GT_SPECIAL_NUMERIC;
351356
}
352357
} else if (state->special_flags == JSONSL_SPECIALf_DASH) {
358+
#ifdef JSONSL_PARSE_NAN
359+
if (CUR_CHAR == 'I' || CUR_CHAR == 'i') {
360+
/* parsing -Infinity? */
361+
state->special_flags = JSONSL_SPECIALf_NEG_INF;
362+
CONTINUE_NEXT_CHAR();
363+
}
364+
#endif
365+
353366
if (!isdigit(CUR_CHAR)) {
354367
INVOKE_ERROR(INVALID_NUMBER);
355368
}
@@ -378,7 +391,8 @@ jsonsl_feed(jsonsl_t jsn, const jsonsl_char_t *bytes, size_t nbytes)
378391
goto GT_SPECIAL_NUMERIC;
379392
}
380393

381-
if (state->special_flags & JSONSL_SPECIALf_NUMERIC) {
394+
if ((state->special_flags & JSONSL_SPECIALf_NUMERIC) &&
395+
!(state->special_flags & JSONSL_SPECIALf_INF)) {
382396
GT_SPECIAL_NUMERIC:
383397
switch (CUR_CHAR) {
384398
CASE_DIGITS
@@ -430,11 +444,12 @@ jsonsl_feed(jsonsl_t jsn, const jsonsl_char_t *bytes, size_t nbytes)
430444
} else if (state->special_flags == JSONSL_SPECIALf_NULL) {
431445
VERIFY_SPECIAL("null");
432446
#ifdef JSONSL_PARSE_NAN
447+
} else if (state->special_flags == JSONSL_SPECIALf_POS_INF) {
448+
VERIFY_SPECIAL_CI("infinity");
449+
} else if (state->special_flags == JSONSL_SPECIALf_NEG_INF) {
450+
VERIFY_SPECIAL_CI("-infinity");
433451
} else if (state->special_flags == JSONSL_SPECIALf_NAN) {
434-
/* like VERIFY_SPECIAL but case-insensitive */
435-
if (tolower(CUR_CHAR) != "nan"[jsn->pos - state->pos_begin]) {
436-
INVOKE_ERROR(SPECIAL_EXPECTED);
437-
}
452+
VERIFY_SPECIAL_CI("nan");
438453
} else if (state->special_flags & JSONSL_SPECIALf_NULL ||
439454
state->special_flags & JSONSL_SPECIALf_NAN) {
440455
/* previous char was "n", are we parsing null or nan? */
@@ -462,6 +477,11 @@ jsonsl_feed(jsonsl_t jsn, const jsonsl_char_t *bytes, size_t nbytes)
462477
} else if (state->special_flags == JSONSL_SPECIALf_DASH) {
463478
/* Still in dash! */
464479
INVOKE_ERROR(INVALID_NUMBER);
480+
} else if (state->special_flags & JSONSL_SPECIALf_INF) {
481+
if (STATE_SPECIAL_LENGTH != 8) {
482+
INVOKE_ERROR(SPECIAL_INCOMPLETE);
483+
}
484+
state->nelem = 1;
465485
} else if (state->special_flags & JSONSL_SPECIALf_NUMERIC) {
466486
/* Check that we're not at the end of a token */
467487
if (STATE_NUM_LAST != '1') {
@@ -1446,11 +1466,15 @@ static unsigned short Special_Table[0x100] = {
14461466
/* 0x37 */ JSONSL_SPECIALf_UNSIGNED /* <7> */, /* 0x37 */
14471467
/* 0x38 */ JSONSL_SPECIALf_UNSIGNED /* <8> */, /* 0x38 */
14481468
/* 0x39 */ JSONSL_SPECIALf_UNSIGNED /* <9> */, /* 0x39 */
1449-
/* 0x3a */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x4d */
1469+
/* 0x3a */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x48 */
1470+
/* 0x49 */ JSONSL__INF_PROXY /* <I> */, /* 0x49 */
1471+
/* 0x4a */ 0,0,0,0, /* 0x4d */
14501472
/* 0x4e */ JSONSL__NAN_PROXY /* <N> */, /* 0x4e */
14511473
/* 0x4f */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x65 */
14521474
/* 0x66 */ JSONSL_SPECIALf_FALSE /* <f> */, /* 0x66 */
1453-
/* 0x67 */ 0,0,0,0,0,0,0, /* 0x6d */
1475+
/* 0x67 */ 0,0, /* 0x68 */
1476+
/* 0x69 */ JSONSL__INF_PROXY /* <i> */, /* 0x69 */
1477+
/* 0x6a */ 0,0,0,0, /* 0x6d */
14541478
/* 0x6e */ JSONSL_SPECIALf_NULL|JSONSL__NAN_PROXY /* <n> */, /* 0x6e */
14551479
/* 0x6f */ 0,0,0,0,0, /* 0x73 */
14561480
/* 0x74 */ JSONSL_SPECIALf_TRUE /* <t> */, /* 0x74 */

jsonsl.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,10 @@ typedef unsigned char jsonsl_uchar_t;
3333

3434
#ifdef JSONSL_PARSE_NAN
3535
#define JSONSL__NAN_PROXY JSONSL_SPECIALf_NAN
36+
#define JSONSL__INF_PROXY JSONSL_SPECIALf_INF
3637
#else
3738
#define JSONSL__NAN_PROXY 0
39+
#define JSONSL__INF_PROXY 0
3840
#endif
3941

4042
/* Stolen from http-parser.h, and possibly others */
@@ -150,7 +152,8 @@ typedef enum {
150152
X(FLOAT, 1<<5) \
151153
X(EXPONENT, 1<<6) \
152154
X(NONASCII, 1<<7) \
153-
X(NAN, 1<<8)
155+
X(NAN, 1<<8) \
156+
X(INF, 1<<9)
154157
typedef enum {
155158
#define X(o,b) \
156159
JSONSL_SPECIALf_##o = b,
@@ -164,6 +167,9 @@ typedef enum {
164167
JSONSL_SPECIALf_ZERO = 1 << 9 | JSONSL_SPECIALf_UNSIGNED,
165168
/** @private */
166169
JSONSL_SPECIALf_DASH = 1 << 10,
170+
/** @private */
171+
JSONSL_SPECIALf_POS_INF = (JSONSL_SPECIALf_INF),
172+
JSONSL_SPECIALf_NEG_INF = (JSONSL_SPECIALf_INF|JSONSL_SPECIALf_SIGNED),
167173

168174
/** Type is numeric */
169175
JSONSL_SPECIALf_NUMERIC = (JSONSL_SPECIALf_SIGNED| JSONSL_SPECIALf_UNSIGNED),
@@ -173,7 +179,8 @@ typedef enum {
173179

174180
/** Type is an "extended", not integral type (but numeric) */
175181
JSONSL_SPECIALf_NUMNOINT =
176-
(JSONSL_SPECIALf_FLOAT|JSONSL_SPECIALf_EXPONENT|JSONSL_SPECIALf_NAN)
182+
(JSONSL_SPECIALf_FLOAT|JSONSL_SPECIALf_EXPONENT|JSONSL_SPECIALf_NAN
183+
|JSONSL_SPECIALf_INF)
177184
} jsonsl_special_t;
178185

179186

srcutil/genchartables.pl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
################################################################################
1313
my @special_begin;
1414
$special_begin[ord('-')] = 'JSONSL_SPECIALf_DASH';
15+
$special_begin[ord('i')] = 'JSONSL__INF_PROXY';
16+
$special_begin[ord('I')] = 'JSONSL__INF_PROXY';
1517
$special_begin[ord('t')] = 'JSONSL_SPECIALf_TRUE';
1618
$special_begin[ord('f')] = 'JSONSL_SPECIALf_FALSE';
1719
$special_begin[ord('n')] = 'JSONSL_SPECIALf_NULL|JSONSL__NAN_PROXY';

0 commit comments

Comments
 (0)