diff options
author | Lloyd Hilaiel <lloyd@hilaiel.com> | 2011-11-28 12:45:52 -0700 |
---|---|---|
committer | Lloyd Hilaiel <lloyd@hilaiel.com> | 2011-11-28 12:45:52 -0700 |
commit | d2d848936c79833a69d09bb73dc068f15cbc6cba (patch) | |
tree | f641f96539f1504e421e1891a67e26b8668c149d | |
parent | 84fe4e84115099eed3a318337b33141875033676 (diff) | |
parent | b8f76ff2ca777559961a2cf2ae34252c10b5beb1 (diff) | |
download | yajl-d2d848936c79833a69d09bb73dc068f15cbc6cba.tar.gz |
Merge branch 'encode-speedup' of https://github.com/bpowers/yajl into 2.1.0
-rw-r--r-- | src/yajl_encode.c | 48 |
1 files changed, 35 insertions, 13 deletions
diff --git a/src/yajl_encode.c b/src/yajl_encode.c index 9dc9a3e..9770df0 100644 --- a/src/yajl_encode.c +++ b/src/yajl_encode.c @@ -23,7 +23,7 @@ static void CharToHex(unsigned char c, char * hexBuf) { - const char * hexchar = "0123456789ABCDEF"; + static const char * hexchar = "0123456789ABCDEF"; hexBuf[0] = hexchar[c >> 4]; hexBuf[1] = hexchar[c & 0x0F]; } @@ -37,36 +37,58 @@ yajl_string_encode(const yajl_print_t print, { size_t beg = 0; size_t end = 0; + size_t escaped_len; + char escBuf[3]; char hexBuf[7]; + escBuf[0] = '\\'; + escBuf[2] = 0; hexBuf[0] = '\\'; hexBuf[1] = 'u'; hexBuf[2] = '0'; hexBuf[3] = '0'; hexBuf[6] = 0; while (end < len) { + const unsigned char chr = str[end]; const char * escaped = NULL; - switch (str[end]) { - case '\r': escaped = "\\r"; break; - case '\n': escaped = "\\n"; break; - case '\\': escaped = "\\\\"; break; + escBuf[1] = 0; + /* we're not going to be escaping most characters, so first + * check for this common case (of doing nothing). Doing so + * decreases the runtime of this function by around 30%. + */ + if (chr > '/') { /* it is not required to escape a solidus in JSON: * read sec. 2.5: http://www.ietf.org/rfc/rfc4627.txt * specifically, this production from the grammar: * unescaped = %x20-21 / %x23-5B / %x5D-10FFFF */ - case '/': if (escape_solidus) escaped = "\\/"; break; - case '"': escaped = "\\\""; break; - case '\f': escaped = "\\f"; break; - case '\b': escaped = "\\b"; break; - case '\t': escaped = "\\t"; break; + if (chr == '\\') { + escBuf[1] = '\\'; + } + } else if (chr == ' ' || (chr < '/' && chr > ')')) { + /* skip these fairly common cases */ + } else { + switch (chr) { + case '\r': escBuf[1] = 'r'; break; + case '\n': escBuf[1] = 'n'; break; + case '"': escBuf[1] = '"'; break; + case '\t': escBuf[1] = 't'; break; + case '\f': escBuf[1] = 'f'; break; + case '\b': escBuf[1] = 'b'; break; + case '/': if (escape_solidus) escBuf[1] = '/'; break; default: - if ((unsigned char) str[end] < 32) { - CharToHex(str[end], hexBuf + 4); + if (chr < 32) { + CharToHex(chr, hexBuf + 4); escaped = hexBuf; + escaped_len = 6; } break; + } + } + if (escBuf[1] != 0) { + escaped = escBuf; + escaped_len = 2; } if (escaped != NULL) { print(ctx, (const char *) (str + beg), end - beg); - print(ctx, escaped, (unsigned int)strlen(escaped)); + print(ctx, escaped, escaped_len); beg = ++end; } else { ++end; |