skip to content
==> tests/width.c <==
1/* Widths against Rust's unicode-width 0.2.2: every scalar value's single-character width hashes
2 * to what Rust computed (None as 255), and strings with the sequences it special-cases. */
3#include "mesh/check.h"
4#include "tui/unicode_width.h"
5
6#include <stdint.h>
7#include <string.h>
8
9#define W(s) tui_str_width((s), sizeof(s) - 1)
10
11int main(void) {
12    uint64_t h = 0xcbf29ce484222325u;
13    for (uint32_t cp = 0; cp <= 0x10FFFF; cp++) {
14        if (cp >= 0xD800 && cp <= 0xDFFF) continue;
15        int w = tui_char_width(cp);
16        h ^= (uint64_t)(w < 0 ? 255 : w);
17        h *= 0x100000001b3u;
18    }
19    CHECK_U(h, 0x2f2b849f2972fccbu);
20    CHECK_U(W(""), 0);
21    CHECK_U(W("abc"), 3);
22    CHECK_U(W("a\tb"), 3);
23    CHECK_U(W("\r\n"), 1);
24    CHECK_U(W("a\r"), 2);
25    CHECK_U(W("\xE2\x86\x92\xE2\x86\x93\xE2\x86\x91"), 3);                          /* arrows */
26    CHECK_U(W("\xC2\xB5s"), 2);                                                     /* µs */
27    CHECK_U(W("\xE6\x97\xA5\xE6\x9C\xAC\xE8\xAA\x9E"), 6);                          /* CJK */
28    CHECK_U(W("e\xCC\x81"), 1);
29    CHECK_U(W("\xF0\x9F\x91\x8D"), 2);
30    CHECK_U(W("\xF0\x9F\x91\x8D\xF0\x9F\x8F\xBD"), 2);
31    CHECK_U(W("\xF0\x9F\x91\xA8\xE2\x80\x8D\xF0\x9F\x91\xA9\xE2\x80\x8D\xF0\x9F\x91\xA7"), 2);
32    CHECK_U(W("\xF0\x9F\x87\xA6\xF0\x9F\x87\xBA"), 2);
33    CHECK_U(W("\xF0\x9F\x87\xA6\xF0\x9F\x87\xBA\xF0\x9F\x87\xB3"), 3);
34    CHECK_U(W("#\xEF\xB8\x8F\xE2\x83\xA3"), 2);
35    CHECK_U(W("\xE2\x98\xBA\xEF\xB8\x8F"), 2);
36    CHECK_U(W("\xE2\x98\xBA\xEF\xB8\x8E"), 1);
37    CHECK_U(W("\xE2\x8C\x9A\xEF\xB8\x8E"), 1);
38    CHECK_U(W("\xD9\x84\xD8\xA2"), 1);                                              /* lam alef */
39    CHECK_U(W("\xF0\x9F\x8F\xB4\xF3\xA0\x81\xA7\xF3\xA0\x81\xA2\xF3\xA0\x81\xA5\xF3\xA0\x81\xAE\xF3\xA0\x81\xA7\xF3\xA0\x81\xBF"), 2);
40    CHECK_U(W("x\xE2\x80\x8By"), 2);
41    CHECK_U(W("\xC2\xAD"), 0);
42    CHECK_U(W("\xE1\x84\x80\xE1\x85\xA1"), 2);
43    CHECK_U(W("\xEF\xBD\xB1\xEF\xBE\x9E"), 1);
44    CHECK_U(W("\x7F"), 1);
45    CHECK_U(W("\xC2\xA0"), 1);
46    CHECK_U(W("a\xE2\x80\x8D" "b"), 2);
47    CHECK_U(W("\xE1\x9F\x92\xE1\x9E\x80"), 0);
48    CHECK_U(W("\xE2\xA3\xBF\xE2\xA1\x80"), 2);
49    CHECK_U(W("\xE2\x96\x88\xE2\x96\x80\xE2\x96\x84"), 3);
50    CHECK_U(W("\xE2\x94\x81\xE2\x94\x82\xE2\x95\xAD\xE2\x95\xAE\xE2\x95\xB0\xE2\x95\xAF"), 6);
51    CHECK_U(W("\xE2\x80\xA6\xC2\xB7\xE2\x80\xA2"), 3);
52    CHECK_U(W("\xC2\xB0" "C\xC3\x97"), 3);
53    CHECK_U(W("\xEF\xBF\xBD"), 1);
54    CHECK_I(tui_char_width('\t'), -1);
55    CHECK_I(tui_char_width(0x85), -1);
56    CHECK_I(tui_char_width(0x4E00), 2);
57    CHECK_U(tui_cstr_width("p50 \xC2\xB5s"), 6);
58    return mesh_check_done();
59}