On 08/23/2018 05:53 PM, Simon Kobyda wrote: > It solves problems with alignment of columns. Width of each column > is calculated by its biggest cell. Should solve unicode bug. > In future, it may be implemented in virsh, virt-admin... > > This API has 5 public functions: > - vshTableNew - adds new table and defines its header > - vshTableRowAppend - appends new row (for same number of columns as in > header) > - vshTablePrintToStdout > - vshTablePrintToString > - vshTableFree > > https://bugzilla.redhat.com/show_bug.cgi?id=1574624 > https://bugzilla.redhat.com/show_bug.cgi?id=1584630 > > Signed-off-by: Simon Kobyda <skobyda@xxxxxxxxxx> > --- > tools/Makefile.am | 4 +- > tools/vsh-table.c | 449 ++++++++++++++++++++++++++++++++++++++++++++++ > tools/vsh-table.h | 42 +++++ > 3 files changed, 494 insertions(+), 1 deletion(-) > create mode 100644 tools/vsh-table.c > create mode 100644 tools/vsh-table.h > > diff --git a/tools/vsh-table.c b/tools/vsh-table.c > new file mode 100644 > index 0000000000..ca4e9265c5 > --- /dev/null > +++ b/tools/vsh-table.c > +/** > + * Function pulled from util-linux > + * > + * Function's name in util-linux: mbs_safe_encode_to_buffer > + * > + * Returns allocated string where all control and non-printable chars are > + * replaced with \x?? hex sequence, or NULL. > + */ > +static char * > +vshTableSafeEncode(const char *s, size_t *width) > +{ > + const char *p = s; > + size_t sz = s ? strlen(s) : 0; > + char *buf; > + char *ret; > + mbstate_t st; > + > + memset(&st, 0, sizeof(st)); > + > + if (VIR_ALLOC_N(buf, (sz * HEX_ENCODE_LENGTH) + 1) < 0) > + return NULL; > + > + if (!sz) > + return NULL; You need to swap these two lines otherwise @buf is leaked. > + > + ret = buf; > + *width = 0; > + > + while (p && *p) { > + if ((*p == '\\' && *(p + 1) == 'x') || > + c_iscntrl(*p)) { > + snprintf(buf, HEX_ENCODE_LENGTH + 1, "\\x%02x", *p); > + buf += HEX_ENCODE_LENGTH; > + *width += HEX_ENCODE_LENGTH; > + p++; > + } else { > + wchar_t wc; > + size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st); > + > + if (len == 0) > + break; /* end of string */ > + > + if (len == (size_t) -1 || len == (size_t) -2) { > + len = 1; > + /* > + * Not valid multibyte sequence -- maybe it's > + * printable char according to the current locales. > + */ > + if (!c_isprint(*p)) { > + snprintf(buf, HEX_ENCODE_LENGTH + 1, "\\x%02x", *p); > + buf += HEX_ENCODE_LENGTH; > + *width += HEX_ENCODE_LENGTH; > + } else { > + (*width)++; > + *buf++ = *p; > + } > + } else if (!iswprint(wc)) { > + size_t i; > + for (i = 0; i < len; i++) { > + snprintf(buf, HEX_ENCODE_LENGTH + 1, "\\x%02x", p[i]); > + buf += HEX_ENCODE_LENGTH; > + *width += HEX_ENCODE_LENGTH; > + } > + } else { > + memcpy(buf, p, len); > + buf += len; > + *width += wcwidth(wc); > + } > + p += len; > + } > + } > + > + *buf = '\0'; > + return ret; > +} > + ACK Michal -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list