# HG changeset patch # User jbe # Date 1406805755 -7200 # Node ID d476b3c8960df4ff0b72b4d0acc99e8f0e4c373a # Parent d5e5e8a9b79a86dab257a013a42d5ccd478ea8db Speed up JSON library by better approximation of required buffer length when parsing string values diff -r d5e5e8a9b79a -r d476b3c8960d libraries/json/json.c --- a/libraries/json/json.c Thu Jul 31 03:57:11 2014 +0200 +++ b/libraries/json/json.c Thu Jul 31 13:22:35 2014 +0200 @@ -297,62 +297,80 @@ case '"': // consume quote character: pos++; - // prepare buffer to decode string (with maximum possible length) and set write position to zero: - cbuf = luaL_buffinitsize(L, &luabuf, total-pos); - writepos = 0; - // loop through the characters until encountering end quote: - while ((c = str[pos++]) != '"') { - if (c == 0) { - // handle unexpected end of JSON document: - goto json_import_unexpected_eof; - } else if (c < 32 || c == 127) { - // do not allow ASCII control characters: - // NOTE: illegal UTF-8 sequences and extended control characters are not sanitized - // by this parser to allow different encodings than Unicode - lua_pushnil(L); - lua_pushliteral(L, "Unexpected control character in JSON string"); - return 2; - } else if (c == '\\') { - // read next char after backslash escape: - c = str[pos++]; - switch (c) { - // unexpected end-of-string: - case 0: + // determine buffer length: + writepos = pos; + while ((c = str[writepos]) != '"') { + // consume one character: + writepos++; + // handle unexpected end of JSON document: + if (c == 0) goto json_import_unexpected_eof; + // consume one extra character when encountering an escaped quote: + else if (c == '\\' && str[writepos] == '"') writepos++; + } + writepos -= pos; + // check if string is non empty: + if (writepos) { + // prepare buffer to decode string (with maximum possible length) and set write position to zero: + cbuf = luaL_buffinitsize(L, &luabuf, writepos); + writepos = 0; + // loop through the characters until encountering end quote: + while ((c = str[pos++]) != '"') { + if (c == 0) { + // handle unexpected end of JSON document: goto json_import_unexpected_eof; - // unescaping of quotation mark, slash, and backslash: - case '"': - case '/': - case '\\': + } else if (c < 32 || c == 127) { + // do not allow ASCII control characters: + // NOTE: illegal UTF-8 sequences and extended control characters are not sanitized + // by this parser to allow different encodings than Unicode + lua_pushnil(L); + lua_pushliteral(L, "Unexpected control character in JSON string"); + return 2; + } else if (c == '\\') { + // read next char after backslash escape: + c = str[pos++]; + switch (c) { + // unexpected end-of-string: + case 0: + goto json_import_unexpected_eof; + // unescaping of quotation mark, slash, and backslash: + case '"': + case '/': + case '\\': + cbuf[writepos++] = c; + break; + // unescaping of backspace: + case 'b': cbuf[writepos++] = '\b'; break; + // unescaping of form-feed: + case 'f': cbuf[writepos++] = '\f'; break; + // unescaping of new-line: + case 'n': cbuf[writepos++] = '\n'; break; + // unescaping of carriage-return: + case 'r': cbuf[writepos++] = '\r'; break; + // unescaping of tabulator: + case 't': cbuf[writepos++] = '\t'; break; + // unescaping of UTF-16 characters + case 'u': + lua_pushnil(L); + lua_pushliteral(L, "JSON unicode escape sequences are not implemented yet"); // TODO + return 2; + // unexpected escape sequence: + default: + lua_pushnil(L); + lua_pushliteral(L, "Unexpected string escape sequence in JSON document"); + return 2; + } + } else { + // normal character: cbuf[writepos++] = c; - break; - // unescaping of backspace: - case 'b': cbuf[writepos++] = '\b'; break; - // unescaping of form-feed: - case 'f': cbuf[writepos++] = '\f'; break; - // unescaping of new-line: - case 'n': cbuf[writepos++] = '\n'; break; - // unescaping of carriage-return: - case 'r': cbuf[writepos++] = '\r'; break; - // unescaping of tabulator: - case 't': cbuf[writepos++] = '\t'; break; - // unescaping of UTF-16 characters - case 'u': - lua_pushnil(L); - lua_pushliteral(L, "JSON unicode escape sequences are not implemented yet"); // TODO - return 2; - // unexpected escape sequence: - default: - lua_pushnil(L); - lua_pushliteral(L, "Unexpected string escape sequence in JSON document"); - return 2; } - } else { - // normal character: - cbuf[writepos++] = c; } + // process buffer to Lua string: + luaL_pushresultsize(&luabuf, writepos); + } else { + // if JSON string is empty, + // push empty Lua string: + lua_pushliteral(L, ""); } - // process buffer to Lua string: - luaL_pushresultsize(&luabuf, writepos); // continue with processing of decoded string: goto json_import_process_value; }