|
27 | 27 | // Color table. See https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
|
28 | 28 | // for how to choose these. The order is same as jv_kind definition, and
|
29 | 29 | // the last color is used for object keys.
|
30 |
| -static char color_bufs[8][16]; |
31 |
| -static const char *color_bufps[8]; |
32 |
| -static const char *const def_colors[] = |
33 |
| - {COL("0;90"), COL("0;39"), COL("0;39"), COL("0;39"), |
| 30 | +#define DEF_COLORS \ |
| 31 | + {COL("0;90"), COL("0;39"), COL("0;39"), COL("0;39"),\ |
34 | 32 | COL("0;32"), COL("1;39"), COL("1;39"), COL("1;34")};
|
| 33 | +static const char *const def_colors[] = DEF_COLORS; |
| 34 | +static const char *colors[] = DEF_COLORS; |
| 35 | +#define COLORS_LEN (sizeof(colors) / sizeof(colors[0])) |
35 | 36 | #define FIELD_COLOR (colors[7])
|
36 | 37 |
|
37 |
| -static const char *const *colors = def_colors; |
38 |
| - |
39 |
| -int |
40 |
| -jq_set_colors(const char *c) |
41 |
| -{ |
42 |
| - const char *e; |
43 |
| - size_t i; |
44 |
| - |
| 38 | +static char *colors_buf = NULL; |
| 39 | +int jq_set_colors(const char *c) { |
45 | 40 | if (c == NULL)
|
46 | 41 | return 1;
|
47 |
| - colors = def_colors; |
48 |
| - memset(color_bufs, 0, sizeof(color_bufs)); |
49 |
| - for (i = 0; i < sizeof(def_colors) / sizeof(def_colors[0]); i++) |
50 |
| - color_bufps[i] = def_colors[i]; |
51 |
| - for (i = 0; i < sizeof(def_colors) / sizeof(def_colors[0]) && *c != '\0'; i++, c = e) { |
52 |
| - if ((e = strchr(c, ':')) == NULL) |
53 |
| - e = c + strlen(c); |
54 |
| - if ((size_t)(e - c) > sizeof(color_bufs[i]) - 4 /* ESC [ m NUL */) |
55 |
| - return 0; |
56 |
| - color_bufs[i][0] = ESC[0]; |
57 |
| - color_bufs[i][1] = '['; |
58 |
| - (void) strncpy(&color_bufs[i][2], c, e - c); |
59 |
| - if (strspn(&color_bufs[i][2], "0123456789;") < strlen(&color_bufs[i][2])) |
| 42 | + const char *offsets[COLORS_LEN + 1]; // extra item for the end of the last string |
| 43 | + |
| 44 | + size_t cl = 0; |
| 45 | + size_t cn = 0; |
| 46 | + |
| 47 | + while (cl < COLORS_LEN) { |
| 48 | + offsets[cl++] = c; |
| 49 | + // gcc won't optimize out strspn |
| 50 | + letter: |
| 51 | + switch (c++[0]) { |
| 52 | + // technically posix doesn't specify ascii so a range wouldn't be portable |
| 53 | + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case ';': |
| 54 | + goto letter; |
| 55 | + case ':': |
| 56 | + continue; |
| 57 | + case '\0': |
| 58 | + goto var_end; |
| 59 | + default: |
60 | 60 | return 0;
|
61 |
| - color_bufs[i][2 + (e - c)] = 'm'; |
62 |
| - color_bufps[i] = color_bufs[i]; |
63 |
| - if (e[0] == ':') |
64 |
| - e++; |
| 61 | + } |
| 62 | + } |
| 63 | + var_end: |
| 64 | + // don't override last color on empty variable or trailing : |
| 65 | + if (offsets[--cl] != c - 1) { |
| 66 | + offsets[++cl] = c; |
| 67 | + } else if (cl == 0) { |
| 68 | + if (colors_buf != NULL) { |
| 69 | + jv_mem_free(colors_buf); |
| 70 | + colors_buf = NULL; |
| 71 | + } |
| 72 | + goto reset; |
| 73 | + } |
| 74 | + |
| 75 | + colors_buf = jv_mem_realloc( |
| 76 | + colors_buf, |
| 77 | + // add ESC '[' 'm' to each string |
| 78 | + // '\0' is already included in difference of offsets |
| 79 | + offsets[cl] - offsets[0] + 3 * cl |
| 80 | + ); |
| 81 | + char *cb = colors_buf; |
| 82 | + for (; cn < cl; cn++) { |
| 83 | + colors[cn] = cb; |
| 84 | + cb[0] = ESC[0]; |
| 85 | + cb[1] = '['; |
| 86 | + size_t len = offsets[cn + 1] - 1 - offsets[cn]; |
| 87 | + memcpy(cb + 2, offsets[cn], len); |
| 88 | + cb[len + 2] = 'm'; |
| 89 | + cb[len + 3] = '\0'; |
| 90 | + cb += len + 4; |
65 | 91 | }
|
66 |
| - colors = color_bufps; |
| 92 | + reset: |
| 93 | + for (; cn < COLORS_LEN; cn++) |
| 94 | + colors[cn] = def_colors[cn]; |
67 | 95 | return 1;
|
68 | 96 | }
|
69 | 97 |
|
|
0 commit comments