Commit 3ceb24bf authored by Rusty Russell's avatar Rusty Russell

json_escape: add fast-path for when we don't need to escape.

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 45f9ce17
...@@ -19,6 +19,18 @@ bool json_escape_eq(const struct json_escape *a, const struct json_escape *b) ...@@ -19,6 +19,18 @@ bool json_escape_eq(const struct json_escape *a, const struct json_escape *b)
return streq(a->s, b->s); return streq(a->s, b->s);
} }
bool json_escape_needed(const char *str, size_t len)
{
for (size_t i = 0; i < len; i++) {
if ((unsigned)str[i] < ' '
|| str[i] == 127
|| str[i] == '"'
|| str[i] == '\\')
return true;
}
return false;
}
static struct json_escape *escape(const tal_t *ctx, static struct json_escape *escape(const tal_t *ctx,
const char *str TAKES, const char *str TAKES,
size_t len, size_t len,
...@@ -27,6 +39,16 @@ static struct json_escape *escape(const tal_t *ctx, ...@@ -27,6 +39,16 @@ static struct json_escape *escape(const tal_t *ctx,
struct json_escape *esc; struct json_escape *esc;
size_t i, n; size_t i, n;
/* Fast path: can steal, and nothing to escape. */
if (is_taken(str)
&& tal_count(str) > len
&& !json_escape_needed(str, len)) {
taken(str);
esc = (struct json_escape *)tal_steal(ctx, str);
esc->s[len] = '\0';
return esc;
}
/* Worst case: all \uXXXX */ /* Worst case: all \uXXXX */
esc = (struct json_escape *)tal_arr(ctx, char, len * 6 + 1); esc = (struct json_escape *)tal_arr(ctx, char, len * 6 + 1);
......
...@@ -27,7 +27,8 @@ struct json_escape *json_escape_len(const tal_t *ctx, ...@@ -27,7 +27,8 @@ struct json_escape *json_escape_len(const tal_t *ctx,
struct json_escape *json_partial_escape(const tal_t *ctx, struct json_escape *json_partial_escape(const tal_t *ctx,
const char *str TAKES); const char *str TAKES);
/* Extract a JSON-escaped string. */ /* Do we need to escape this str? */
bool json_escape_needed(const char *str, size_t len);
/* Are two escape json strings identical? */ /* Are two escape json strings identical? */
bool json_escape_eq(const struct json_escape *a, bool json_escape_eq(const struct json_escape *a,
......
#include <ccan/json_escape/json_escape.h>
/* Include the C files directly. */
#include <ccan/json_escape/json_escape.c>
#include <ccan/tap/tap.h>
int main(void)
{
const tal_t *ctx = tal(NULL, char);
struct json_escape *e;
char *p;
/* This is how many tests you plan to run */
plan_tests(5);
/* This should simply be tal_steal */
p = tal_dup_arr(NULL, char, "Hello", 6, 0);
e = json_escape(ctx, take(p));
ok1(!strcmp(e->s, "Hello"));
ok1((void *)e == (void *)p);
ok1(tal_parent(e) == ctx);
/* This can't be tal_steal, but still should be freed. */
p = tal_dup_arr(NULL, char,
"\\\b\f\n\r\t\""
"\\\\\\b\\f\\n\\r\\t\\\"", 22, 0);
e = json_escape(ctx, take(p));
ok1(tal_parent(e) == ctx);
ok1(!strcmp(e->s,
"\\\\\\b\\f\\n\\r\\t\\\""
"\\\\\\\\\\\\b\\\\f\\\\n\\\\r\\\\t\\\\\\\""));
tal_free(ctx);
/* This exits depending on whether all tests passed */
return exit_status();
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment