| 33 | } |
| 34 | |
| 35 | static struct json_escape *escape(const tal_t *ctx, |
| 36 | const char *str TAKES, |
| 37 | size_t len, |
| 38 | bool partial) |
| 39 | { |
| 40 | struct json_escape *esc; |
| 41 | size_t i, n; |
| 42 | |
| 43 | /* Fast path: can steal, and nothing to escape. */ |
| 44 | if (is_taken(str) |
| 45 | && tal_count(str) > len |
| 46 | && !json_escape_needed(str, len)) { |
| 47 | taken(str); |
| 48 | esc = (struct json_escape *)tal_steal(ctx, str); |
| 49 | esc->s[len] = '\0'; |
| 50 | return esc; |
| 51 | } |
| 52 | |
| 53 | /* Worst case: all \uXXXX */ |
| 54 | esc = (struct json_escape *)tal_arr(ctx, char, len * 6 + 1); |
| 55 | |
| 56 | for (i = n = 0; i < len; i++, n++) { |
| 57 | char escape = 0; |
| 58 | switch (str[i]) { |
| 59 | case '\n': |
| 60 | escape = 'n'; |
| 61 | break; |
| 62 | case '\b': |
| 63 | escape = 'b'; |
| 64 | break; |
| 65 | case '\f': |
| 66 | escape = 'f'; |
| 67 | break; |
| 68 | case '\t': |
| 69 | escape = 't'; |
| 70 | break; |
| 71 | case '\r': |
| 72 | escape = 'r'; |
| 73 | break; |
| 74 | case '\\': |
| 75 | if (partial) { |
| 76 | /* Don't double-escape standard escapes. */ |
| 77 | if (str[i+1] == 'n' |
| 78 | || str[i+1] == 'b' |
| 79 | || str[i+1] == 'f' |
| 80 | || str[i+1] == 't' |
| 81 | || str[i+1] == 'r' |
| 82 | || str[i+1] == '/' |
| 83 | || str[i+1] == '\\' |
| 84 | || str[i+1] == '"') { |
| 85 | escape = str[i+1]; |
| 86 | i++; |
| 87 | break; |
| 88 | } |
| 89 | if (str[i+1] == 'u' |
| 90 | && cisxdigit(str[i+2]) |
| 91 | && cisxdigit(str[i+3]) |
| 92 | && cisxdigit(str[i+4]) |
no test coverage detected