[flori/json] Refactor json_string_unescape

https://github.com/flori/json/commit/f398769332
This commit is contained in:
Jean Boussier 2020-11-18 11:33:42 +01:00 committed by Hiroshi SHIBATA
parent 8a974dc83c
commit 1d2b4ccaf2
No known key found for this signature in database
GPG Key ID: F9CF13417264FAC2
3 changed files with 2980 additions and 1795 deletions

File diff suppressed because it is too large Load Diff

View File

@ -63,7 +63,7 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result); static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result); static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting); static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd); static VALUE json_string_unescape(char *string, char *stringEnd);
static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result); static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
static VALUE convert_encoding(VALUE source); static VALUE convert_encoding(VALUE source);
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self); static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self);

View File

@ -452,17 +452,30 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
} }
} }
static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd) static const size_t MAX_STACK_BUFFER_SIZE = 128;
static VALUE json_string_unescape(char *string, char *stringEnd)
{ {
char *p = string, *pe = string, *unescape; VALUE result = Qnil;
size_t bufferSize = stringEnd - string;
char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
int unescape_len; int unescape_len;
char buf[4]; char buf[4];
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
buffer = xmalloc(bufferSize);
bufferStart = buffer;
} else {
bufferStart = buffer = alloca(bufferSize);
}
while (pe < stringEnd) { while (pe < stringEnd) {
if (*pe == '\\') { if (*pe == '\\') {
unescape = (char *) "?"; unescape = (char *) "?";
unescape_len = 1; unescape_len = 1;
if (pe > p) rb_str_buf_cat(result, p, pe - p); if (pe > p) {
MEMCPY(buffer, p, char, pe - p);
buffer += pe - p;
}
switch (*++pe) { switch (*++pe) {
case 'n': case 'n':
unescape = (char *) "\n"; unescape = (char *) "\n";
@ -487,6 +500,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
break; break;
case 'u': case 'u':
if (pe > stringEnd - 4) { if (pe > stringEnd - 4) {
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
free(bufferStart);
}
rb_enc_raise( rb_enc_raise(
EXC_ENCODING eParserError, EXC_ENCODING eParserError,
"%u: incomplete unicode character escape sequence at '%s'", __LINE__, p "%u: incomplete unicode character escape sequence at '%s'", __LINE__, p
@ -497,6 +513,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
if (UNI_SUR_HIGH_START == (ch & 0xFC00)) { if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
pe++; pe++;
if (pe > stringEnd - 6) { if (pe > stringEnd - 6) {
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
free(bufferStart);
}
rb_enc_raise( rb_enc_raise(
EXC_ENCODING eParserError, EXC_ENCODING eParserError,
"%u: incomplete surrogate pair at '%s'", __LINE__, p "%u: incomplete surrogate pair at '%s'", __LINE__, p
@ -520,13 +539,28 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
p = pe; p = pe;
continue; continue;
} }
rb_str_buf_cat(result, unescape, unescape_len); MEMCPY(buffer, unescape, char, unescape_len);
buffer += unescape_len;
p = ++pe; p = ++pe;
} else { } else {
pe++; pe++;
} }
} }
rb_str_buf_cat(result, p, pe - p);
if (pe > p) {
MEMCPY(buffer, p, char, pe - p);
buffer += pe - p;
}
#ifdef HAVE_RUBY_ENCODING_H
result = rb_utf8_str_new(bufferStart, buffer - bufferStart);
#else
result = rb_str_new(bufferStart, buffer - bufferStart);
#endif
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
free(bufferStart);
}
return result; return result;
} }
@ -537,12 +571,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
write data; write data;
action parse_string { action parse_string {
*result = json_string_unescape(*result, json->memo + 1, p); *result = json_string_unescape(json->memo + 1, p);
if (NIL_P(*result)) { if (NIL_P(*result)) {
fhold; fhold;
fbreak; fbreak;
} else { } else {
FORCE_UTF8(*result);
fexec p + 1; fexec p + 1;
} }
} }
@ -569,7 +602,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
int cs = EVIL; int cs = EVIL;
VALUE match_string; VALUE match_string;
*result = rb_str_buf_new(0);
%% write init; %% write init;
json->memo = p; json->memo = p;
%% write exec; %% write exec;