dte test coverage


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 50.0% high: ≥ 85.0%
Coverage Exec / Excl / Total
Lines: 100.0% 16 / 0 / 16
Functions: 100.0% 3 / 0 / 3
Branches: 100.0% 12 / 2 / 14

src/util/utf8.h
Line Branch Exec Source
1 #ifndef UTIL_UTF8_H
2 #define UTIL_UTF8_H
3
4 #include <stddef.h>
5 #include "debug.h"
6 #include "macros.h"
7 #include "string-view.h"
8 #include "unicode.h"
9
10 // Minimum `dest_len` value needed by u_make_printable() to guarantee
11 // truncation cannot occur
12 #define U_MAKE_PRINTABLE_MAXLEN(src_len) ((U_SET_CHAR_MAXLEN * src_len) + 1)
13
14 enum {
15 // Longest UTF-8 sequence (in bytes) permitted by RFC 3629
16 // (maximum number of bytes written by u_set_char_raw())
17 UTF8_MAX_SEQ_LEN = 4, // STRLEN(u8"\U0001F44D")
18
19 // Number of bytes written by u_set_hex()
20 U_SET_HEX_LEN = 4, // STRLEN("<ff>")
21
22 // Maximum number of bytes written by u_set_char()
23 U_SET_CHAR_MAXLEN = 4, // MAX(UTF8_MAX_SEQ_LEN, U_SET_HEX_LEN)
24 };
25
26 typedef enum {
27 // Replace C0 control characters with Unicode "control picture"
28 // symbols, instead of using caret notation (which can become
29 // quite ambiguous when formatting terminal escape sequences)
30 MPF_C0_SYMBOLS = 1 << 0,
31 } MakePrintableFlags;
32
33 size_t u_str_width(const char *str) NONNULL_ARGS;
34 size_t u_skip_chars(const char *str, unsigned int skip_width) NONNULL_ARGS;
35 CodePoint u_prev_char(const char *str, size_t *idx) NONNULL_ARGS READWRITE(2);
36 CodePoint u_get_char(const char *str, size_t size, size_t *idx) NONNULL_ARGS READWRITE(3);
37 CodePoint u_get_nonascii(const char *str, size_t size, size_t *idx) NONNULL_ARGS READWRITE(3);
38 size_t u_set_char_raw(char *buf, CodePoint u) NONNULL_ARGS;
39 size_t u_set_char(char *buf, CodePoint u) NONNULL_ARGS;
40 size_t u_set_hex(char buf[static U_SET_HEX_LEN], CodePoint u) NONNULL_ARGS;
41
42 402 static inline CodePoint u_str_get_char(const char *str, size_t *idx)
43 {
44 // We can use a dummy size here, since the null terminator in `str`
45 // guarantees u_get_char() won't read past the end
46 402 return u_get_char(str, *idx + UTF8_MAX_SEQ_LEN, idx);
47 }
48
49 // Return the number of bytes needed to encode Unicode codepoint `u`
50 // in UTF-8, or 1 for codepoints exceeding UNICODE_MAX_VALID_CODEPOINT.
51 // Those in the latter category may have originated as values returned
52 // by u_get_nonascii() or u_prev_char() (i.e. invalid bytes in a
53 // sequence that have been negated).
54 258 static inline size_t u_char_size(CodePoint u)
55 {
56 // If `u` is invalid, set `adj` to 3 and use to adjust the calculation
57 // so that 1 is returned
58 258 size_t inv = (u > UNICODE_MAX_VALID_CODEPOINT);
59 258 size_t adj = inv | (inv << 1);
60
61
2/2
✓ Branch 2 → 3 taken 169 times.
✓ Branch 2 → 4 taken 89 times.
258 return 1 + (u > 0x7F) + (u > 0x7FF) + (u > 0xFFFF) - adj;
62 }
63
64 /*
65 * Copy into `dest` the printable representation of `src`, escaping
66 * control characters and other unprintable sequences as necessary.
67 * Bytes >= 0x80 are assumed to be the start of a UTF-8 multi-byte
68 * sequence, if subsequent bytes result in a valid encoding, or are
69 * otherwise byte-wise escaped. This is similar in purpose to the
70 * BSD strnvisx(3) function, but produces a truncated string if the
71 * destination buffer has insufficient space. If `dest_len` is at
72 * least `U_MAKE_PRINTABLE_MAXLEN(src_len)`, truncation can never
73 * happen.
74 */
75 13 static inline size_t u_make_printable (
76 StringView src,
77 char *restrict dest,
78 size_t dest_len,
79 MakePrintableFlags flags
80 ) {
81 13 BUG_ON(dest_len == 0);
82 13 size_t len = 0;
83
84
4/4
✓ Branch 13 → 14 taken 8215 times.
✓ Branch 13 → 15 taken 3 times.
✓ Branch 14 → 5 taken 8205 times.
✓ Branch 14 → 15 taken 10 times.
8218 for (size_t i = 0; i < src.length && len + U_SET_CHAR_MAXLEN < dest_len; ) {
85 8205 CodePoint u = u_get_char(src.data, src.length, &i);
86
2/2
✓ Branch 6 → 7 taken 5 times.
✓ Branch 6 → 11 taken 8200 times.
8205 if (flags & MPF_C0_SYMBOLS) {
87
4/4
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 9 taken 4 times.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 11 taken 3 times.
5 u = (u < 0x20) ? u + 0x2400 : (u == 0x7F ? 0x2421 : u);
88 }
89 8205 len += u_set_char(dest + len, u);
90 }
91
92 13 dest[len] = '\0';
93 13 return len;
94 }
95
96 #endif
97