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    }

Impressum / About Us