Skip to content

Commit 9f6c190

Browse files
author
Fabrice Bellard
committed
more efficient handling of strings in JSON.stringify()
1 parent 8a0a6e9 commit 9f6c190

File tree

1 file changed

+68
-78
lines changed

1 file changed

+68
-78
lines changed

quickjs.c

Lines changed: 68 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -13002,73 +13002,6 @@ static JSValue JS_ToStringCheckObject(JSContext *ctx, JSValueConst val)
1300213002
return JS_ToString(ctx, val);
1300313003
}
1300413004

13005-
static JSValue JS_ToQuotedString(JSContext *ctx, JSValueConst val1)
13006-
{
13007-
JSValue val;
13008-
JSString *p;
13009-
int i;
13010-
uint32_t c;
13011-
StringBuffer b_s, *b = &b_s;
13012-
char buf[16];
13013-
13014-
val = JS_ToStringCheckObject(ctx, val1);
13015-
if (JS_IsException(val))
13016-
return val;
13017-
p = JS_VALUE_GET_STRING(val);
13018-
13019-
if (string_buffer_init(ctx, b, p->len + 2))
13020-
goto fail;
13021-
13022-
if (string_buffer_putc8(b, '\"'))
13023-
goto fail;
13024-
for(i = 0; i < p->len; ) {
13025-
c = string_getc(p, &i);
13026-
switch(c) {
13027-
case '\t':
13028-
c = 't';
13029-
goto quote;
13030-
case '\r':
13031-
c = 'r';
13032-
goto quote;
13033-
case '\n':
13034-
c = 'n';
13035-
goto quote;
13036-
case '\b':
13037-
c = 'b';
13038-
goto quote;
13039-
case '\f':
13040-
c = 'f';
13041-
goto quote;
13042-
case '\"':
13043-
case '\\':
13044-
quote:
13045-
if (string_buffer_putc8(b, '\\'))
13046-
goto fail;
13047-
if (string_buffer_putc8(b, c))
13048-
goto fail;
13049-
break;
13050-
default:
13051-
if (c < 32 || is_surrogate(c)) {
13052-
snprintf(buf, sizeof(buf), "\\u%04x", c);
13053-
if (string_buffer_puts8(b, buf))
13054-
goto fail;
13055-
} else {
13056-
if (string_buffer_putc(b, c))
13057-
goto fail;
13058-
}
13059-
break;
13060-
}
13061-
}
13062-
if (string_buffer_putc8(b, '\"'))
13063-
goto fail;
13064-
JS_FreeValue(ctx, val);
13065-
return string_buffer_end(b);
13066-
fail:
13067-
JS_FreeValue(ctx, val);
13068-
string_buffer_free(b);
13069-
return JS_EXCEPTION;
13070-
}
13071-
1307213005
#define JS_PRINT_MAX_DEPTH 8
1307313006

1307413007
typedef struct {
@@ -46699,10 +46632,72 @@ typedef struct JSONStringifyContext {
4669946632
StringBuffer *b;
4670046633
} JSONStringifyContext;
4670146634

46702-
static JSValue JS_ToQuotedStringFree(JSContext *ctx, JSValue val) {
46703-
JSValue r = JS_ToQuotedString(ctx, val);
46635+
static int JS_ToQuotedString(JSContext *ctx, StringBuffer *b, JSValueConst val1)
46636+
{
46637+
JSValue val;
46638+
JSString *p;
46639+
int i;
46640+
uint32_t c;
46641+
char buf[16];
46642+
46643+
val = JS_ToStringCheckObject(ctx, val1);
46644+
if (JS_IsException(val))
46645+
return -1;
46646+
p = JS_VALUE_GET_STRING(val);
46647+
46648+
if (string_buffer_putc8(b, '\"'))
46649+
goto fail;
46650+
for(i = 0; i < p->len; ) {
46651+
c = string_getc(p, &i);
46652+
switch(c) {
46653+
case '\t':
46654+
c = 't';
46655+
goto quote;
46656+
case '\r':
46657+
c = 'r';
46658+
goto quote;
46659+
case '\n':
46660+
c = 'n';
46661+
goto quote;
46662+
case '\b':
46663+
c = 'b';
46664+
goto quote;
46665+
case '\f':
46666+
c = 'f';
46667+
goto quote;
46668+
case '\"':
46669+
case '\\':
46670+
quote:
46671+
if (string_buffer_putc8(b, '\\'))
46672+
goto fail;
46673+
if (string_buffer_putc8(b, c))
46674+
goto fail;
46675+
break;
46676+
default:
46677+
if (c < 32 || is_surrogate(c)) {
46678+
snprintf(buf, sizeof(buf), "\\u%04x", c);
46679+
if (string_buffer_puts8(b, buf))
46680+
goto fail;
46681+
} else {
46682+
if (string_buffer_putc(b, c))
46683+
goto fail;
46684+
}
46685+
break;
46686+
}
46687+
}
46688+
if (string_buffer_putc8(b, '\"'))
46689+
goto fail;
4670446690
JS_FreeValue(ctx, val);
46705-
return r;
46691+
return 0;
46692+
fail:
46693+
JS_FreeValue(ctx, val);
46694+
return -1;
46695+
}
46696+
46697+
static int JS_ToQuotedStringFree(JSContext *ctx, StringBuffer *b, JSValue val) {
46698+
int ret = JS_ToQuotedString(ctx, b, val);
46699+
JS_FreeValue(ctx, val);
46700+
return ret;
4670646701
}
4670746702

4670846703
static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
@@ -46885,13 +46880,11 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
4688546880
if (!JS_IsUndefined(v)) {
4688646881
if (has_content)
4688746882
string_buffer_putc8(jsc->b, ',');
46888-
prop = JS_ToQuotedStringFree(ctx, prop);
46889-
if (JS_IsException(prop)) {
46883+
string_buffer_concat_value(jsc->b, sep);
46884+
if (JS_ToQuotedString(ctx, jsc->b, prop)) {
4689046885
JS_FreeValue(ctx, v);
4689146886
goto exception;
4689246887
}
46893-
string_buffer_concat_value(jsc->b, sep);
46894-
string_buffer_concat_value(jsc->b, prop);
4689546888
string_buffer_putc8(jsc->b, ':');
4689646889
string_buffer_concat_value(jsc->b, sep1);
4689746890
if (js_json_to_str(ctx, jsc, val, v, indent1))
@@ -46919,10 +46912,7 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
4691946912
switch (JS_VALUE_GET_NORM_TAG(val)) {
4692046913
case JS_TAG_STRING:
4692146914
case JS_TAG_STRING_ROPE:
46922-
val = JS_ToQuotedStringFree(ctx, val);
46923-
if (JS_IsException(val))
46924-
goto exception;
46925-
goto concat_value;
46915+
return JS_ToQuotedStringFree(ctx, jsc->b, val);
4692646916
case JS_TAG_FLOAT64:
4692746917
if (!isfinite(JS_VALUE_GET_FLOAT64(val))) {
4692846918
val = JS_NULL;

0 commit comments

Comments
 (0)