Optimize unescape

This commit is contained in:
Arun Prakash Jana 2020-02-26 00:33:54 +05:30
parent ae1d656a27
commit 71bac356d6
No known key found for this signature in database
GPG key ID: A75979F35C080412

View file

@ -2972,16 +2972,8 @@ static void resetdircolor(int flags)
* Replace escape characters in a string with '?' * Replace escape characters in a string with '?'
* Adjust string length to maxcols if > 0; * Adjust string length to maxcols if > 0;
* Max supported str length: NAME_MAX; * Max supported str length: NAME_MAX;
*
* Interestingly, note that unescape() uses g_buf. What happens if
* str also points to g_buf? In this case we assume that the caller
* acknowledges that it's OK to lose the data in g_buf after this
* call to unescape().
* The API, on its part, first converts str to multibyte (after which
* it doesn't touch str anymore). Only after that it starts modifying
* g_buf. This is a phased operation.
*/ */
static char *unescape(const char *str, uint maxcols, wchar_t **wstr) static wchar_t *unescape(const char *str, uint maxcols)
{ {
static wchar_t wbuf[NAME_MAX + 1] __attribute__ ((aligned)); static wchar_t wbuf[NAME_MAX + 1] __attribute__ ((aligned));
wchar_t *buf = wbuf; wchar_t *buf = wbuf;
@ -2994,6 +2986,10 @@ static char *unescape(const char *str, uint maxcols, wchar_t **wstr)
/* Convert multi-byte to wide char */ /* Convert multi-byte to wide char */
size_t len = mbstowcs(wbuf, str, NAME_MAX); size_t len = mbstowcs(wbuf, str, NAME_MAX);
len = wcswidth(wbuf, len);
/* Reduce number of wide chars to max columns */
if (len > maxcols) {
while (*buf && lencount <= maxcols) { while (*buf && lencount <= maxcols) {
if (*buf <= '\x1f' || *buf == '\x7f') if (*buf <= '\x1f' || *buf == '\x7f')
*buf = '\?'; *buf = '\?';
@ -3002,27 +2998,22 @@ static char *unescape(const char *str, uint maxcols, wchar_t **wstr)
++lencount; ++lencount;
} }
len = lencount = wcswidth(wbuf, len);
/* Reduce number of wide chars to max columns */
if (len > maxcols) {
lencount = maxcols + 1; lencount = maxcols + 1;
/* Reduce wide chars one by one till it fits */ /* Reduce wide chars one by one till it fits */
while (len > maxcols) do
len = wcswidth(wbuf, --lencount); len = wcswidth(wbuf, --lencount);
while (len > maxcols);
wbuf[lencount] = L'\0'; wbuf[lencount] = L'\0';
} else {
do /* We do not expect a NULL string */
if (*buf <= '\x1f' || *buf == '\x7f')
*buf = '\?';
while (*++buf);
} }
if (wstr) { return wbuf;
*wstr = wbuf;
return NULL;
}
/* Convert wide char to multi-byte */
wcstombs(g_buf, wbuf, NAME_MAX);
return g_buf;
} }
static char *coolsize(off_t size) static char *coolsize(off_t size)
@ -3151,7 +3142,6 @@ static char *get_lsperms(mode_t mode)
static void printent(const struct entry *ent, uint namecols, bool sel) static void printent(const struct entry *ent, uint namecols, bool sel)
{ {
wchar_t *wstr;
char hln = '\0'; char hln = '\0';
char ind = get_ind(ent->mode, FALSE); char ind = get_ind(ent->mode, FALSE);
@ -3163,30 +3153,26 @@ static void printent(const struct entry *ent, uint namecols, bool sel)
if (!ind) if (!ind)
++namecols; ++namecols;
unescape(ent->name, namecols, &wstr);
/* Directories are always shown on top */ /* Directories are always shown on top */
resetdircolor(ent->flags); resetdircolor(ent->flags);
addch((ent->flags & FILE_SELECTED) ? '+' : ' ');
if (sel) if (sel)
attron(A_REVERSE); attron(A_REVERSE);
addwstr(unescape(ent->name, namecols));
addch((ent->flags & FILE_SELECTED) ? '+' : ' '); if (sel)
addwstr(wstr); attroff(A_REVERSE);
if (ind) if (ind)
addch(ind); addch(ind);
if (hln) if (hln)
addch(hln); addch(hln);
addch('\n'); addch('\n');
if (sel)
attroff(A_REVERSE);
} }
static void printent_long(const struct entry *ent, uint namecols, bool sel) static void printent_long(const struct entry *ent, uint namecols, bool sel)
{ {
char timebuf[24], permbuf[4], ind1 = '\0', ind2 = '\0'; char timebuf[24], permbuf[4], ind1 = '\0', ind2 = '\0';
const char cp = (ent->flags & FILE_SELECTED) ? '+' : ' ';
/* Timestamp */ /* Timestamp */
strftime(timebuf, sizeof(timebuf), "%F %R", localtime(&ent->t)); strftime(timebuf, sizeof(timebuf), "%F %R", localtime(&ent->t));
@ -3202,12 +3188,11 @@ static void printent_long(const struct entry *ent, uint namecols, bool sel)
if (S_ISREG(ent->mode) && !(ent->mode & 0100)) if (S_ISREG(ent->mode) && !(ent->mode & 0100))
++namecols; ++namecols;
/* Trim escape chars from name */
const char *pname = unescape(ent->name, namecols, NULL);
/* Directories are always shown on top */ /* Directories are always shown on top */
resetdircolor(ent->flags); resetdircolor(ent->flags);
addch((ent->flags & FILE_SELECTED) ? '+' : ' ');
if (sel) if (sel)
attron(A_REVERSE); attron(A_REVERSE);
@ -3222,9 +3207,8 @@ static void printent_long(const struct entry *ent, uint namecols, bool sel)
ind2 = '/'; ind2 = '/';
} }
printw("%c%-16.16s %s %8.8s%c %s%c", cp, timebuf, permbuf, printw("%-16.16s %s %8.8s%c ", timebuf, permbuf,
coolsize(cfg.blkorder ? ent->blocks << blk_shift : ent->size), coolsize(cfg.blkorder ? ent->blocks << blk_shift : ent->size), ind1);
ind1, pname, ind2);
break; break;
case S_IFLNK: case S_IFLNK:
ind1 = ind2 = '@'; // fallthrough ind1 = ind2 = '@'; // fallthrough
@ -3243,14 +3227,16 @@ static void printent_long(const struct entry *ent, uint namecols, bool sel)
default: default:
if (!ind1) if (!ind1)
ind1 = ind2 = '?'; ind1 = ind2 = '?';
printw("%c%-16.16s %s %c %s%c", cp, timebuf, permbuf, ind1, pname, ind2); printw("%-16.16s %s %c ", timebuf, permbuf, ind1);
break; break;
} }
addch('\n'); addwstr(unescape(ent->name, namecols));
if (sel) if (sel)
attroff(A_REVERSE); attroff(A_REVERSE);
if (ind2)
addch(ind2);
addch('\n');
} }
static void (*printptr)(const struct entry *ent, uint namecols, bool sel) = &printent; static void (*printptr)(const struct entry *ent, uint namecols, bool sel) = &printent;