On Fri, Jun 17, 2022 at 05:46:20PM +0800, Chengwen Feng wrote: > This patch supports escape special characters (including: \",\\,/,\b, > /f,/n,/r,/t) when telemetry string. > This patch is used to support telemetry xxx-dump commands which the > string may include special characters. > > Signed-off-by: Chengwen Feng <fengcheng...@huawei.com> > --- > lib/telemetry/telemetry.c | 96 +++++++++++++++++++++++++++++++++++++-- > 1 file changed, 93 insertions(+), 3 deletions(-) > > diff --git a/lib/telemetry/telemetry.c b/lib/telemetry/telemetry.c > index c6fd03a5ab..0f762f633e 100644 > --- a/lib/telemetry/telemetry.c > +++ b/lib/telemetry/telemetry.c > @@ -215,6 +215,94 @@ container_to_json(const struct rte_tel_data *d, char > *out_buf, size_t buf_len) > return used; > } > > +static bool > +json_is_special_char(char ch) > +{ > + static unsigned char is_spec[256] = { 0 }; > + static bool init_once; > + > + if (!init_once) { > + is_spec['\"'] = 1; > + is_spec['\\'] = 1; > + is_spec['/'] = 1; > + is_spec['\b'] = 1; > + is_spec['\f'] = 1; > + is_spec['\n'] = 1; > + is_spec['\r'] = 1; > + is_spec['\t'] = 1; > + init_once = true; > + } > + > + return (bool)is_spec[(unsigned char)ch]; > +} > + > +static size_t > +json_escape_special_char(char *buf, const char ch) > +{ > + size_t used = 0; > + > + switch (ch) { > + case '\"': > + buf[used++] = '\\'; > + buf[used++] = '\"'; > + break; > + case '\\': > + buf[used++] = '\\'; > + buf[used++] = '\\'; > + break; > + case '/': > + buf[used++] = '\\'; > + buf[used++] = '/'; > + break; > + case '\b': > + buf[used++] = '\\'; > + buf[used++] = 'b'; > + break; > + case '\f': > + buf[used++] = '\\'; > + buf[used++] = 'f'; > + break; > + case '\n': > + buf[used++] = '\\'; > + buf[used++] = 'n'; > + break; > + case '\r': > + buf[used++] = '\\'; > + buf[used++] = 'r'; > + break; > + case '\t': > + buf[used++] = '\\'; > + buf[used++] = 't'; > + break; > + default: > + break; > + } > + > + return used; > +} > + > +static size_t > +json_format_string(char *buf, size_t len, const char *str) > +{ > + size_t used = 0; > + > + while (*str) { > + if (unlikely(len < used + 2)) { > + TMTY_LOG(WARNING, "Insufficient buffer when json format > string\n"); > + break; > + } > + > + if (json_is_special_char(*str)) > + used += json_escape_special_char(buf + used, *str); > + else > + buf[used++] = *str; > + > + str++; > + } > + > + return used; > +} > + > static void > output_json(const char *cmd, const struct rte_tel_data *d, int s) > { > @@ -232,9 +320,11 @@ output_json(const char *cmd, const struct rte_tel_data > *d, int s) > MAX_CMD_LEN, cmd ? cmd : "none"); > break; > case RTE_TEL_STRING: > - used = snprintf(out_buf, sizeof(out_buf), "{\"%.*s\":\"%.*s\"}", > - MAX_CMD_LEN, cmd, > - RTE_TEL_MAX_SINGLE_STRING_LEN, d->data.str); > + used = snprintf(out_buf, sizeof(out_buf), "{\"%.*s\":\"", > + MAX_CMD_LEN, cmd); > + used += json_format_string(out_buf + used, > + sizeof(out_buf) - used - 3, d->data.str); > + used += snprintf(out_buf + used, sizeof(out_buf) - used, "\"}"); > break; > case RTE_TEL_DICT: > prefix_used = snprintf(out_buf, sizeof(out_buf), "{\"%.*s\":", > --
I think it might be worthwhile to write a general json_str_printf function to do the snprintf and the escaping in one go. Then that might be more able to be used in other places where we output strings. /Bruce