summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKarel Zak2017-11-22 14:41:10 +0100
committerKarel Zak2017-11-22 14:41:10 +0100
commit365ed9f639be420aedf11500e6220a8ed0ebf5e8 (patch)
tree4d3859d660bc42dc9fa074eba36e7f0bb2ab9a75 /lib
parentmount: add hint about -t and root perms to the man page (diff)
downloadkernel-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.c80
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