diff options
author | Karel Zak | 2017-11-22 14:41:10 +0100 |
---|---|---|
committer | Karel Zak | 2017-11-22 14:41:10 +0100 |
commit | 365ed9f639be420aedf11500e6220a8ed0ebf5e8 (patch) | |
tree | 4d3859d660bc42dc9fa074eba36e7f0bb2ab9a75 /lib | |
parent | mount: add hint about -t and root perms to the man page (diff) | |
download | kernel-qcow2-util-linux-365ed9f639be420aedf11500e6220a8ed0ebf5e8.tar.gz kernel-qcow2-util-linux-365ed9f639be420aedf11500e6220a8ed0ebf5e8.tar.xz kernel-qcow2-util-linux-365ed9f639be420aedf11500e6220a8ed0ebf5e8.zip |
lib/mbsalign: add mbs_invalid_encode()
Like mbs_safe_encode(), but it does not care about control chars.
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/mbsalign.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/lib/mbsalign.c b/lib/mbsalign.c index b0e1004a0..78ab12a0d 100644 --- a/lib/mbsalign.c +++ b/lib/mbsalign.c @@ -194,6 +194,67 @@ char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf, const c return buf; } +/* + * Copy @s to @buf and replace broken sequences to \x?? hex sequence. The + * @width returns number of cells. The @safechars are not encoded. + * + * The @buf has to be big enough to store mbs_safe_encode_size(strlen(s))) + * bytes. + */ +char *mbs_invalid_encode_to_buffer(const char *s, size_t *width, char *buf) +{ + const char *p = s; + char *r; + size_t sz = s ? strlen(s) : 0; + +#ifdef HAVE_WIDECHAR + mbstate_t st; + memset(&st, 0, sizeof(st)); +#endif + if (!sz || !buf) + return NULL; + + r = buf; + *width = 0; + + while (p && *p) { +#ifdef HAVE_WIDECHAR + 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 (!isprint((unsigned char) *p)) { + sprintf(r, "\\x%02x", (unsigned char) *p); + r += 4; + *width += 4; + } else { + (*width)++; + *r++ = *p; + } + } else { + memcpy(r, p, len); + r += len; + *width += wcwidth(wc); + } + p += len; +#else + *r++ = *p++; + (*width)++; +#endif + } + + *r = '\0'; + return buf; +} + size_t mbs_safe_encode_size(size_t bytes) { return (bytes * 4) + 1; @@ -218,6 +279,25 @@ char *mbs_safe_encode(const char *s, size_t *width) return ret; } +/* + * Returns allocated string where all broken widechars chars are + * replaced with \x?? hex sequence. + */ +char *mbs_invalid_encode(const char *s, size_t *width) +{ + size_t sz = s ? strlen(s) : 0; + char *buf, *ret = NULL; + + if (!sz) + return NULL; + buf = malloc(mbs_safe_encode_size(sz)); + if (buf) + ret = mbs_invalid_encode_to_buffer(s, width, buf); + if (!ret) + free(buf); + return ret; +} + #ifdef HAVE_WIDECHAR static bool |