
On Thu, Aug 16, 2018 at 02:05:45PM +0200, Ján Tomko wrote:
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@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); + }
Whatever solution you use for converting a multi-byte string to a maximum count of characters, please put it in a separate function. That would make this function more readable.
Note that unfortnately libunistring is "GPLv2+ or LGPLv3+", so is not compatible with libvirt.so It is fine to use it from virsh since that's free to be GPLv2+ only, but we mustn't link libunistring to libvirt.so. So any helper func would have to stay in the tools dir just for virsh/virt-admin 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 :|