webmcp
changeset 161:d476b3c8960d
Speed up JSON library by better approximation of required buffer length when parsing string values
author | jbe |
---|---|
date | Thu Jul 31 13:22:35 2014 +0200 (2014-07-31) |
parents | d5e5e8a9b79a |
children | 3b8c1e2aef9c |
files | libraries/json/json.c |
line diff
1.1 --- a/libraries/json/json.c Thu Jul 31 03:57:11 2014 +0200 1.2 +++ b/libraries/json/json.c Thu Jul 31 13:22:35 2014 +0200 1.3 @@ -297,62 +297,80 @@ 1.4 case '"': 1.5 // consume quote character: 1.6 pos++; 1.7 - // prepare buffer to decode string (with maximum possible length) and set write position to zero: 1.8 - cbuf = luaL_buffinitsize(L, &luabuf, total-pos); 1.9 - writepos = 0; 1.10 - // loop through the characters until encountering end quote: 1.11 - while ((c = str[pos++]) != '"') { 1.12 - if (c == 0) { 1.13 - // handle unexpected end of JSON document: 1.14 - goto json_import_unexpected_eof; 1.15 - } else if (c < 32 || c == 127) { 1.16 - // do not allow ASCII control characters: 1.17 - // NOTE: illegal UTF-8 sequences and extended control characters are not sanitized 1.18 - // by this parser to allow different encodings than Unicode 1.19 - lua_pushnil(L); 1.20 - lua_pushliteral(L, "Unexpected control character in JSON string"); 1.21 - return 2; 1.22 - } else if (c == '\\') { 1.23 - // read next char after backslash escape: 1.24 - c = str[pos++]; 1.25 - switch (c) { 1.26 - // unexpected end-of-string: 1.27 - case 0: 1.28 + // determine buffer length: 1.29 + writepos = pos; 1.30 + while ((c = str[writepos]) != '"') { 1.31 + // consume one character: 1.32 + writepos++; 1.33 + // handle unexpected end of JSON document: 1.34 + if (c == 0) goto json_import_unexpected_eof; 1.35 + // consume one extra character when encountering an escaped quote: 1.36 + else if (c == '\\' && str[writepos] == '"') writepos++; 1.37 + } 1.38 + writepos -= pos; 1.39 + // check if string is non empty: 1.40 + if (writepos) { 1.41 + // prepare buffer to decode string (with maximum possible length) and set write position to zero: 1.42 + cbuf = luaL_buffinitsize(L, &luabuf, writepos); 1.43 + writepos = 0; 1.44 + // loop through the characters until encountering end quote: 1.45 + while ((c = str[pos++]) != '"') { 1.46 + if (c == 0) { 1.47 + // handle unexpected end of JSON document: 1.48 goto json_import_unexpected_eof; 1.49 - // unescaping of quotation mark, slash, and backslash: 1.50 - case '"': 1.51 - case '/': 1.52 - case '\\': 1.53 + } else if (c < 32 || c == 127) { 1.54 + // do not allow ASCII control characters: 1.55 + // NOTE: illegal UTF-8 sequences and extended control characters are not sanitized 1.56 + // by this parser to allow different encodings than Unicode 1.57 + lua_pushnil(L); 1.58 + lua_pushliteral(L, "Unexpected control character in JSON string"); 1.59 + return 2; 1.60 + } else if (c == '\\') { 1.61 + // read next char after backslash escape: 1.62 + c = str[pos++]; 1.63 + switch (c) { 1.64 + // unexpected end-of-string: 1.65 + case 0: 1.66 + goto json_import_unexpected_eof; 1.67 + // unescaping of quotation mark, slash, and backslash: 1.68 + case '"': 1.69 + case '/': 1.70 + case '\\': 1.71 + cbuf[writepos++] = c; 1.72 + break; 1.73 + // unescaping of backspace: 1.74 + case 'b': cbuf[writepos++] = '\b'; break; 1.75 + // unescaping of form-feed: 1.76 + case 'f': cbuf[writepos++] = '\f'; break; 1.77 + // unescaping of new-line: 1.78 + case 'n': cbuf[writepos++] = '\n'; break; 1.79 + // unescaping of carriage-return: 1.80 + case 'r': cbuf[writepos++] = '\r'; break; 1.81 + // unescaping of tabulator: 1.82 + case 't': cbuf[writepos++] = '\t'; break; 1.83 + // unescaping of UTF-16 characters 1.84 + case 'u': 1.85 + lua_pushnil(L); 1.86 + lua_pushliteral(L, "JSON unicode escape sequences are not implemented yet"); // TODO 1.87 + return 2; 1.88 + // unexpected escape sequence: 1.89 + default: 1.90 + lua_pushnil(L); 1.91 + lua_pushliteral(L, "Unexpected string escape sequence in JSON document"); 1.92 + return 2; 1.93 + } 1.94 + } else { 1.95 + // normal character: 1.96 cbuf[writepos++] = c; 1.97 - break; 1.98 - // unescaping of backspace: 1.99 - case 'b': cbuf[writepos++] = '\b'; break; 1.100 - // unescaping of form-feed: 1.101 - case 'f': cbuf[writepos++] = '\f'; break; 1.102 - // unescaping of new-line: 1.103 - case 'n': cbuf[writepos++] = '\n'; break; 1.104 - // unescaping of carriage-return: 1.105 - case 'r': cbuf[writepos++] = '\r'; break; 1.106 - // unescaping of tabulator: 1.107 - case 't': cbuf[writepos++] = '\t'; break; 1.108 - // unescaping of UTF-16 characters 1.109 - case 'u': 1.110 - lua_pushnil(L); 1.111 - lua_pushliteral(L, "JSON unicode escape sequences are not implemented yet"); // TODO 1.112 - return 2; 1.113 - // unexpected escape sequence: 1.114 - default: 1.115 - lua_pushnil(L); 1.116 - lua_pushliteral(L, "Unexpected string escape sequence in JSON document"); 1.117 - return 2; 1.118 } 1.119 - } else { 1.120 - // normal character: 1.121 - cbuf[writepos++] = c; 1.122 } 1.123 + // process buffer to Lua string: 1.124 + luaL_pushresultsize(&luabuf, writepos); 1.125 + } else { 1.126 + // if JSON string is empty, 1.127 + // push empty Lua string: 1.128 + lua_pushliteral(L, ""); 1.129 } 1.130 - // process buffer to Lua string: 1.131 - luaL_pushresultsize(&luabuf, writepos); 1.132 // continue with processing of decoded string: 1.133 goto json_import_process_value; 1.134 }