diff options
author | Bobby Powers <bobbypowers@gmail.com> | 2011-10-04 17:35:08 -0400 |
---|---|---|
committer | Bobby Powers <bobbypowers@gmail.com> | 2011-10-04 23:20:06 -0400 |
commit | b8f76ff2ca777559961a2cf2ae34252c10b5beb1 (patch) | |
tree | 83c763a3bb17c28c79b56a3226f52c865d16827d | |
parent | b61bf79512e705482ec30f57b5a11170e4eb72f5 (diff) | |
download | yajl-b8f76ff2ca777559961a2cf2ae34252c10b5beb1.tar.gz |
encode: don't check specific cases when the current char is large
Most characters don't get escaped. According to the RFC, the only
character greater than '/' that gets escaped is '/'. Test for this
common case first, and only if the char is a candidate for escaping
check for the other escape cases.
This cuts an additional 29% off the runtime of yajl_string_encode
-rw-r--r-- | src/yajl_encode.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/src/yajl_encode.c b/src/yajl_encode.c index 4aeda9d..9770df0 100644 --- a/src/yajl_encode.c +++ b/src/yajl_encode.c @@ -46,29 +46,41 @@ yajl_string_encode(const yajl_print_t print, hexBuf[6] = 0; while (end < len) { + const unsigned char chr = str[end]; const char * escaped = NULL; escBuf[1] = 0; - switch (str[end]) { - case '\r': escBuf[1] = 'r'; break; - case '\n': escBuf[1] = 'n'; break; - case '\\': escBuf[1] = '\\'; break; + /* 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) escBuf[1] = '/'; break; - case '"': escBuf[1] = '"'; 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 '\t': escBuf[1] = 't'; 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; |