1 /* MIT (BSD) license - see LICENSE file for details */
2 #include <ccan/json_escape/json_escape.h>
5 struct json_escape *json_escape_string_(const tal_t *ctx,
6 const void *bytes, size_t len)
8 struct json_escape *esc;
10 esc = (void *)tal_arr_label(ctx, char, len + 1,
11 TAL_LABEL(struct json_escape, ""));
12 memcpy(esc->s, bytes, len);
17 bool json_escape_eq(const struct json_escape *a, const struct json_escape *b)
19 return streq(a->s, b->s);
22 bool json_escape_needed(const char *str, size_t len)
24 for (size_t i = 0; i < len; i++) {
25 if ((unsigned)str[i] < ' '
34 static struct json_escape *escape(const tal_t *ctx,
35 const char *str TAKES,
39 struct json_escape *esc;
42 /* Fast path: can steal, and nothing to escape. */
44 && tal_count(str) > len
45 && !json_escape_needed(str, len)) {
47 esc = (struct json_escape *)tal_steal(ctx, str);
52 /* Worst case: all \uXXXX */
53 esc = (struct json_escape *)tal_arr(ctx, char, len * 6 + 1);
55 for (i = n = 0; i < len; i++, n++) {
75 /* Don't double-escape standard escapes. */
89 && cisxdigit(str[i+2])
90 && cisxdigit(str[i+3])
91 && cisxdigit(str[i+4])
92 && cisxdigit(str[i+5])) {
93 memcpy(esc->s + n, str + i, 6);
103 if ((unsigned)str[i] < ' ' || str[i] == 127) {
104 snprintf(esc->s + n, 7, "\\u%04X", str[i]);
122 struct json_escape *json_partial_escape(const tal_t *ctx, const char *str TAKES)
124 return escape(ctx, str, strlen(str), true);
127 struct json_escape *json_escape(const tal_t *ctx, const char *str TAKES)
129 return escape(ctx, str, strlen(str), false);
132 struct json_escape *json_escape_len(const tal_t *ctx, const char *str TAKES,
135 return escape(ctx, str, len, false);
138 /* By policy, we don't handle \u. Use UTF-8. */
139 const char *json_escape_unescape(const tal_t *ctx, const struct json_escape *esc)
141 char *unesc = tal_arr(ctx, char, strlen(esc->s) + 1);
144 for (i = n = 0; esc->s[i]; i++, n++) {
145 if (esc->s[i] != '\\') {
146 unesc[n] = esc->s[i];
170 unesc[n] = esc->s[i];
173 return tal_free(unesc);