summaryrefslogtreecommitdiff
path: root/src/WidthData.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/WidthData.zig')
-rw-r--r--src/WidthData.zig102
1 files changed, 0 insertions, 102 deletions
diff --git a/src/WidthData.zig b/src/WidthData.zig
deleted file mode 100644
index ca7eaf0..0000000
--- a/src/WidthData.zig
+++ /dev/null
@@ -1,102 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compress = std.compress;
4const mem = std.mem;
5const testing = std.testing;
6
7const Graphemes = @import("Graphemes");
8
9g_data: Graphemes,
10s1: []u16 = undefined,
11s2: []i4 = undefined,
12owns_gdata: bool,
13
14const Self = @This();
15
16pub fn init(allocator: mem.Allocator) mem.Allocator.Error!Self {
17 var self: Self = try Self.setup(allocator);
18 errdefer {
19 allocator.free(self.s1);
20 allocator.free(self.s2);
21 }
22 self.owns_gdata = true;
23 self.g_data = try Graphemes.init(allocator);
24 errdefer self.g_data.deinit(allocator);
25 return self;
26}
27
28pub fn initWithGraphemeData(allocator: mem.Allocator, g_data: Graphemes) mem.Allocator.Error!Self {
29 var self = try Self.setup(allocator);
30 self.g_data = g_data;
31 self.owns_gdata = false;
32 return self;
33}
34
35// Sets up the DisplayWidthData, leaving the GraphemeData undefined.
36fn setup(allocator: mem.Allocator) mem.Allocator.Error!Self {
37 const decompressor = compress.flate.inflate.decompressor;
38 const in_bytes = @embedFile("dwp");
39 var in_fbs = std.io.fixedBufferStream(in_bytes);
40 var in_decomp = decompressor(.raw, in_fbs.reader());
41 var reader = in_decomp.reader();
42
43 const endian = builtin.cpu.arch.endian();
44
45 var self: Self = undefined;
46
47 const stage_1_len: u16 = reader.readInt(u16, endian) catch unreachable;
48 self.s1 = try allocator.alloc(u16, stage_1_len);
49 errdefer allocator.free(self.s1);
50 for (0..stage_1_len) |i| self.s1[i] = reader.readInt(u16, endian) catch unreachable;
51
52 const stage_2_len: u16 = reader.readInt(u16, endian) catch unreachable;
53 self.s2 = try allocator.alloc(i4, stage_2_len);
54 errdefer allocator.free(self.s2);
55 for (0..stage_2_len) |i| self.s2[i] = @intCast(reader.readInt(i8, endian) catch unreachable);
56
57 return self;
58}
59
60pub fn deinit(self: *const Self, allocator: mem.Allocator) void {
61 allocator.free(self.s1);
62 allocator.free(self.s2);
63 if (self.owns_gdata) self.g_data.deinit(allocator);
64}
65
66/// codePointWidth returns the number of cells `cp` requires when rendered
67/// in a fixed-pitch font (i.e. a terminal screen). This can range from -1 to
68/// 3, where BACKSPACE and DELETE return -1 and 3-em-dash returns 3. C0/C1
69/// control codes return 0. If `cjk` is true, ambiguous code points return 2,
70/// otherwise they return 1.
71pub fn codePointWidth(self: Self, cp: u21) i4 {
72 return self.s2[self.s1[cp >> 8] + (cp & 0xff)];
73}
74
75test "codePointWidth" {
76 const wd = try Self.init(std.testing.allocator);
77 defer wd.deinit(std.testing.allocator);
78 try testing.expectEqual(@as(i4, 0), wd.codePointWidth(0x0000)); // null
79 try testing.expectEqual(@as(i4, -1), wd.codePointWidth(0x8)); // \b
80 try testing.expectEqual(@as(i4, -1), wd.codePointWidth(0x7f)); // DEL
81 try testing.expectEqual(@as(i4, 0), wd.codePointWidth(0x0005)); // Cf
82 try testing.expectEqual(@as(i4, 0), wd.codePointWidth(0x0007)); // \a BEL
83 try testing.expectEqual(@as(i4, 0), wd.codePointWidth(0x000A)); // \n LF
84 try testing.expectEqual(@as(i4, 0), wd.codePointWidth(0x000B)); // \v VT
85 try testing.expectEqual(@as(i4, 0), wd.codePointWidth(0x000C)); // \f FF
86 try testing.expectEqual(@as(i4, 0), wd.codePointWidth(0x000D)); // \r CR
87 try testing.expectEqual(@as(i4, 0), wd.codePointWidth(0x000E)); // SQ
88 try testing.expectEqual(@as(i4, 0), wd.codePointWidth(0x000F)); // SI
89
90 try testing.expectEqual(@as(i4, 0), wd.codePointWidth(0x070F)); // Cf
91 try testing.expectEqual(@as(i4, 1), wd.codePointWidth(0x0603)); // Cf Arabic
92
93 try testing.expectEqual(@as(i4, 1), wd.codePointWidth(0x00AD)); // soft-hyphen
94 try testing.expectEqual(@as(i4, 2), wd.codePointWidth(0x2E3A)); // two-em dash
95 try testing.expectEqual(@as(i4, 3), wd.codePointWidth(0x2E3B)); // three-em dash
96
97 try testing.expectEqual(@as(i4, 1), wd.codePointWidth(0x00BD)); // ambiguous halfwidth
98
99 try testing.expectEqual(@as(i4, 1), wd.codePointWidth('é'));
100 try testing.expectEqual(@as(i4, 2), wd.codePointWidth('😊'));
101 try testing.expectEqual(@as(i4, 2), wd.codePointWidth('统'));
102}