[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 коммит произвёл Hiroshi SHIBATA
Родитель 8a974dc83c
Коммит 1d2b4ccaf2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: F9CF13417264FAC2
3 изменённых файлов: 2980 добавлений и 1795 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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_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 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 VALUE convert_encoding(VALUE source);
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self);

Просмотреть файл

@ -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;
char buf[4];
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
buffer = xmalloc(bufferSize);
bufferStart = buffer;
} else {
bufferStart = buffer = alloca(bufferSize);
}
while (pe < stringEnd) {
if (*pe == '\\') {
unescape = (char *) "?";
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) {
case 'n':
unescape = (char *) "\n";
@ -487,6 +500,9 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
break;
case 'u':
if (pe > stringEnd - 4) {
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
free(bufferStart);
}
rb_enc_raise(
EXC_ENCODING eParserError,
"%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)) {
pe++;
if (pe > stringEnd - 6) {
if (bufferSize > MAX_STACK_BUFFER_SIZE) {
free(bufferStart);
}
rb_enc_raise(
EXC_ENCODING eParserError,
"%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;
continue;
}
rb_str_buf_cat(result, unescape, unescape_len);
MEMCPY(buffer, unescape, char, unescape_len);
buffer += unescape_len;
p = ++pe;
} else {
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;
}
@ -537,12 +571,11 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
write data;
action parse_string {
*result = json_string_unescape(*result, json->memo + 1, p);
*result = json_string_unescape(json->memo + 1, p);
if (NIL_P(*result)) {
fhold;
fbreak;
} else {
FORCE_UTF8(*result);
fexec p + 1;
}
}
@ -569,7 +602,6 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
int cs = EVIL;
VALUE match_string;
*result = rb_str_buf_new(0);
%% write init;
json->memo = p;
%% write exec;