[libvirt] [PATCH v3 1/3] vsh: Add API for printing tables.

Daniel P. Berrangé berrange at redhat.com
Thu Aug 16 11:28:45 UTC 2018


On Thu, Aug 16, 2018 at 12:56:24PM +0200, 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 at redhat.com>
> ---
>  tools/Makefile.am |   4 +-
>  tools/vsh-table.c | 413 ++++++++++++++++++++++++++++++++++++++++++++++
>  tools/vsh-table.h |  42 +++++
>  3 files changed, 458 insertions(+), 1 deletion(-)
>  create mode 100644 tools/vsh-table.c
>  create mode 100644 tools/vsh-table.h
> 


> +/**
> + * vshTableGetColumnsWidths:
> + * @table: table
> + * @maxwidths: maximum count of characters for each columns
> + * @widths: count of characters for each cell in the table
> + *
> + * Fill passed @maxwidths and @widths arrays with maximum number
> + * of characters for columns and number of character per each
> + * table cell, respectively.
> + *
> + * Handle unicode strings (user must have multibyte locale)
> + */
> +static int
> +vshTableGetColumnsWidths(vshTablePtr table,
> +                         size_t *maxwidths,
> +                         size_t **widths,
> +                         bool header)
> +{
> +    int ret = -1;
> +    size_t i = 1;
> +    size_t j;
> +    size_t len;
> +    int tmp;
> +    wchar_t *wstr = NULL;
> +    size_t wstrlen;
> +
> +    if (header)
> +        i = 0;
> +    else
> +        i = 1;
> +    for (; i < table->nrows; i++) {
> +        vshTableRowPtr row = table->rows[i];
> +
> +        for (j = 0; j < row->ncells; j++) {
> +            /* strlen should return maximum possible length needed */
> +            wstrlen = strlen(row->cells[j]);
> +            VIR_FREE(wstr);
> +            if (VIR_ALLOC_N(wstr, wstrlen) < 0)
> +                goto cleanup;
> +            /* mbstowcs fails if machine is using singlebyte locale
> +             * and user tries to convert unicode(multibyte)
> +             * */
> +            if (mbstowcs(wstr, row->cells[j], wstrlen) ==
> +                (size_t) -1) {
> +                len = wstrlen;
> +            } else {
> +                tmp = wcswidth(wstr, wstrlen);
> +                if (tmp < 0)
> +                    goto cleanup;
> +                len = (size_t)((unsigned)tmp);
> +            }
> +            widths[i][j] = len;
> +            if (len > maxwidths[j])
> +                maxwidths[j] = len;

After asking around I have found the right solution that we need to use
for measuring string width.  mbstowcs()/wcswidth() will get the answer
wrong wrt zero-width characters, combining characters, non-printable
characters, etc. We need to use the libunistring library:

  https://www.gnu.org/software/libunistring/manual/libunistring.html#uniwidth_002eh


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|




More information about the libvir-list mailing list