summaryrefslogtreecommitdiff
path: root/libmisc/fmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmisc/fmt.c')
-rw-r--r--libmisc/fmt.c34
1 files changed, 13 insertions, 21 deletions
diff --git a/libmisc/fmt.c b/libmisc/fmt.c
index 33788b6..6cf1d8d 100644
--- a/libmisc/fmt.c
+++ b/libmisc/fmt.c
@@ -6,6 +6,8 @@
#include <string.h> /* for strnlen() */
+#include <libmisc/utf8.h>
+
#include <libmisc/fmt.h>
static const char *const hexdig = "0123456789ABCDEF";
@@ -67,19 +69,18 @@ void fmt_print_qmem(lo_interface fmt_dest w, const void *_str, size_t size) {
fmt_print_byte(w, '"');
for (size_t pos = 0; pos < size;) {
uint32_t ch;
- uint8_t chlen;
- if ((str[pos] & 0b10000000) == 0b00000000) { ch = str[pos] & 0b01111111; chlen = 1; }
- else if ((str[pos] & 0b11100000) == 0b11000000) { ch = str[pos] & 0b00011111; chlen = 2; }
- else if ((str[pos] & 0b11110000) == 0b11100000) { ch = str[pos] & 0b00001111; chlen = 3; }
- else if ((str[pos] & 0b11111000) == 0b11110000) { ch = str[pos] & 0b00000111; chlen = 4; }
- else goto invalid_utf8;
- if ((ch == 0 && chlen != 1) || pos + chlen > size) goto invalid_utf8;
- for (uint8_t i = 1; i < chlen; i++) {
- if ((str[pos+i] & 0b11000000) != 0b10000000) goto invalid_utf8;
- ch = (ch << 6) | (str[pos+i] & 0b00111111);
+ uint8_t chlen;
+ utf8_decode_codepoint(&str[pos], size-pos, &ch, &chlen);
+ if (!chlen) {
+ /* invalid UTF-8 */
+ /* \xAB */
+ fmt_print_byte(w, '\\');
+ fmt_print_byte(w, 'x');
+ fmt_print_byte(w, hexdig[(str[pos] >> 4) & 0xF]);
+ fmt_print_byte(w, hexdig[(str[pos] >> 0) & 0xF]);
+ pos++;
+ continue;
}
- if (ch > 0x10FFFF) goto invalid_utf8;
-
if (ch == '\0' ||
ch == '\b' ||
ch == '\f' ||
@@ -132,15 +133,6 @@ void fmt_print_qmem(lo_interface fmt_dest w, const void *_str, size_t size) {
fmt_print_byte(w, hexdig[(ch >> 0) & 0xF]);
}
pos += chlen;
- continue;
-
- invalid_utf8:
- /* \xAB */
- fmt_print_byte(w, '\\');
- fmt_print_byte(w, 'x');
- fmt_print_byte(w, hexdig[(str[pos] >> 4) & 0xF]);
- fmt_print_byte(w, hexdig[(str[pos] >> 0) & 0xF]);
- pos++;
}
fmt_print_byte(w, '"');
}