Skip to content

Commit 50af9eb

Browse files
committed
Optimize parsing JSON number.
1 parent 6640170 commit 50af9eb

File tree

2 files changed

+88
-19
lines changed

2 files changed

+88
-19
lines changed

Makefile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
CFLAGS = -g -Wall -std=c99
2-
LDFLAGS = -lm
32
ifeq ($(DEBUG), y)
43
CFLAGS += -O0
54
else
@@ -13,10 +12,10 @@ all: test_speed parse_json
1312
json_parser.o: json_parser.c json_parser.h list.h rbtree.h
1413

1514
test_speed: json_parser.o rbtree.o test_speed.o
16-
$(LD) -o test_speed $^ $(LDFLAGS)
15+
$(LD) -o test_speed $^
1716

1817
parse_json: json_parser.o rbtree.o test.o
19-
$(LD) -o parse_json $^ $(LDFLAGS)
18+
$(LD) -o parse_json $^
2019

2120
clean:
2221
rm -f parse_json test_speed *.o

json_parser.c

Lines changed: 86 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,71 @@ static int __parse_json_string(const char *cursor, const char **end,
252252
return 0;
253253
}
254254

255+
static const double __power_of_10[309] = {
256+
1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4,
257+
1.0e5, 1.0e6, 1.0e7, 1.0e8, 1.0e9,
258+
1.0e10, 1.0e11, 1.0e12, 1.0e13, 1.0e14,
259+
1.0e15, 1.0e16, 1.0e17, 1.0e18, 1.0e19,
260+
1.0e20, 1.0e21, 1.0e22, 1.0e23, 1.0e24,
261+
1.0e25, 1.0e26, 1.0e27, 1.0e28, 1.0e29,
262+
1.0e30, 1.0e31, 1.0e32, 1.0e33, 1.0e34,
263+
1.0e35, 1.0e36, 1.0e37, 1.0e38, 1.0e39,
264+
1.0e40, 1.0e41, 1.0e42, 1.0e43, 1.0e44,
265+
1.0e45, 1.0e46, 1.0e47, 1.0e48, 1.0e49,
266+
1.0e50, 1.0e51, 1.0e52, 1.0e53, 1.0e54,
267+
1.0e55, 1.0e56, 1.0e57, 1.0e58, 1.0e59,
268+
1.0e60, 1.0e61, 1.0e62, 1.0e63, 1.0e64,
269+
1.0e65, 1.0e66, 1.0e67, 1.0e68, 1.0e69,
270+
1.0e70, 1.0e71, 1.0e72, 1.0e73, 1.0e74,
271+
1.0e75, 1.0e76, 1.0e77, 1.0e78, 1.0e79,
272+
1.0e80, 1.0e81, 1.0e82, 1.0e83, 1.0e84,
273+
1.0e85, 1.0e86, 1.0e87, 1.0e88, 1.0e89,
274+
1.0e90, 1.0e91, 1.0e92, 1.0e93, 1.0e94,
275+
1.0e95, 1.0e96, 1.0e97, 1.0e98, 1.0e99,
276+
1.0e100, 1.0e101, 1.0e102, 1.0e103, 1.0e104,
277+
1.0e105, 1.0e106, 1.0e107, 1.0e108, 1.0e109,
278+
1.0e110, 1.0e111, 1.0e112, 1.0e113, 1.0e114,
279+
1.0e115, 1.0e116, 1.0e117, 1.0e118, 1.0e119,
280+
1.0e120, 1.0e121, 1.0e122, 1.0e123, 1.0e124,
281+
1.0e125, 1.0e126, 1.0e127, 1.0e128, 1.0e129,
282+
1.0e130, 1.0e131, 1.0e132, 1.0e133, 1.0e134,
283+
1.0e135, 1.0e136, 1.0e137, 1.0e138, 1.0e139,
284+
1.0e140, 1.0e141, 1.0e142, 1.0e143, 1.0e144,
285+
1.0e145, 1.0e146, 1.0e147, 1.0e148, 1.0e149,
286+
1.0e150, 1.0e151, 1.0e152, 1.0e153, 1.0e154,
287+
1.0e155, 1.0e156, 1.0e157, 1.0e158, 1.0e159,
288+
1.0e160, 1.0e161, 1.0e162, 1.0e163, 1.0e164,
289+
1.0e165, 1.0e166, 1.0e167, 1.0e168, 1.0e169,
290+
1.0e170, 1.0e171, 1.0e172, 1.0e173, 1.0e174,
291+
1.0e175, 1.0e176, 1.0e177, 1.0e178, 1.0e179,
292+
1.0e180, 1.0e181, 1.0e182, 1.0e183, 1.0e184,
293+
1.0e185, 1.0e186, 1.0e187, 1.0e188, 1.0e189,
294+
1.0e190, 1.0e191, 1.0e192, 1.0e193, 1.0e194,
295+
1.0e195, 1.0e196, 1.0e197, 1.0e198, 1.0e199,
296+
1.0e200, 1.0e201, 1.0e202, 1.0e203, 1.0e204,
297+
1.0e205, 1.0e206, 1.0e207, 1.0e208, 1.0e209,
298+
1.0e210, 1.0e211, 1.0e212, 1.0e213, 1.0e214,
299+
1.0e215, 1.0e216, 1.0e217, 1.0e218, 1.0e219,
300+
1.0e220, 1.0e221, 1.0e222, 1.0e223, 1.0e224,
301+
1.0e225, 1.0e226, 1.0e227, 1.0e228, 1.0e229,
302+
1.0e230, 1.0e231, 1.0e232, 1.0e233, 1.0e234,
303+
1.0e235, 1.0e236, 1.0e237, 1.0e238, 1.0e239,
304+
1.0e240, 1.0e241, 1.0e242, 1.0e243, 1.0e244,
305+
1.0e245, 1.0e246, 1.0e247, 1.0e248, 1.0e249,
306+
1.0e250, 1.0e251, 1.0e252, 1.0e253, 1.0e254,
307+
1.0e255, 1.0e256, 1.0e257, 1.0e258, 1.0e259,
308+
1.0e260, 1.0e261, 1.0e262, 1.0e263, 1.0e264,
309+
1.0e265, 1.0e266, 1.0e267, 1.0e268, 1.0e269,
310+
1.0e270, 1.0e271, 1.0e272, 1.0e273, 1.0e274,
311+
1.0e275, 1.0e276, 1.0e277, 1.0e278, 1.0e279,
312+
1.0e280, 1.0e281, 1.0e282, 1.0e283, 1.0e284,
313+
1.0e285, 1.0e286, 1.0e287, 1.0e288, 1.0e289,
314+
1.0e290, 1.0e291, 1.0e292, 1.0e293, 1.0e294,
315+
1.0e295, 1.0e296, 1.0e297, 1.0e298, 1.0e299,
316+
1.0e300, 1.0e301, 1.0e302, 1.0e303, 1.0e304,
317+
1.0e305, 1.0e306, 1.0e307, 1.0e308
318+
};
319+
255320
static double __evaluate_json_number(const char *integer,
256321
const char *fraction,
257322
int exp)
@@ -269,16 +334,17 @@ static double __evaluate_json_number(const char *integer,
269334
{
270335
figures++;
271336
mant = *integer - '0';
272-
while (isdigit(*++integer))
337+
while (isdigit(*++integer) && figures < 18)
273338
{
274-
if (figures < 18)
275-
{
276-
figures++;
277-
mant *= 10;
278-
mant += *integer - '0';
279-
}
280-
else
281-
exp++;
339+
figures++;
340+
mant *= 10;
341+
mant += *integer - '0';
342+
}
343+
344+
while (isdigit(*integer))
345+
{
346+
exp++;
347+
integer++;
282348
}
283349
}
284350
else
@@ -303,15 +369,19 @@ static double __evaluate_json_number(const char *integer,
303369
num = mant;
304370
if (exp != 0 && figures != 0)
305371
{
306-
if (exp > 0)
307-
num *= pow(10, exp);
308-
else if (exp >= -308)
309-
num /= pow(10, -exp);
310-
else
372+
if (exp > 309 - figures)
373+
num = INFINITY;
374+
else if (exp > 0)
375+
num *= __power_of_10[exp];
376+
else if (exp > -309)
377+
num /= __power_of_10[-exp];
378+
else if (exp > -324 - figures)
311379
{
312-
num /= pow(10, -exp - 308);
313-
num /= 1.0e308;
380+
num /= __power_of_10[-exp - 308];
381+
num /= __power_of_10[308];
314382
}
383+
else
384+
num = 0.0;
315385
}
316386

317387
return sign ? -num : num;

0 commit comments

Comments
 (0)