summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jose Colon Rodriguez2024-03-28 10:06:00 -0400
committerGravatar Jose Colon Rodriguez2024-03-28 10:06:00 -0400
commit74be85ac145cc6de5d03348e07be8d982c2211cb (patch)
treeb3b5f2080235e5cf73d2be080fb70583567dfb2b /src
parentScriptsData and made all Datas const (diff)
downloadzg-74be85ac145cc6de5d03348e07be8d982c2211cb.tar.gz
zg-74be85ac145cc6de5d03348e07be8d982c2211cb.tar.xz
zg-74be85ac145cc6de5d03348e07be8d982c2211cb.zip
PropsData and errdefers for init fns
Diffstat (limited to 'src')
-rw-r--r--src/CanonData.zig10
-rw-r--r--src/CombiningData.zig2
-rw-r--r--src/CompatData.zig1
-rw-r--r--src/FoldData.zig8
-rw-r--r--src/GenCatData.zig3
-rw-r--r--src/GraphemeData.zig3
-rw-r--r--src/HangulData.zig2
-rw-r--r--src/NormData.zig31
-rw-r--r--src/NormPropsData.zig2
-rw-r--r--src/NumericData.zig10
-rw-r--r--src/PropsData.zig123
-rw-r--r--src/ScriptsData.zig3
-rw-r--r--src/WidthData.zig3
13 files changed, 179 insertions, 22 deletions
diff --git a/src/CanonData.zig b/src/CanonData.zig
index 9f1deb8..64d5555 100644
--- a/src/CanonData.zig
+++ b/src/CanonData.zig
@@ -24,6 +24,13 @@ pub fn init(allocator: mem.Allocator) !Self {
24 .nfd = try allocator.alloc([]u21, 0x110000), 24 .nfd = try allocator.alloc([]u21, 0x110000),
25 }; 25 };
26 26
27 var slices: usize = 0;
28 errdefer {
29 self.nfc.deinit();
30 for (self.nfd[0..slices]) |slice| self.allocator.free(slice);
31 self.allocator.free(self.nfd);
32 }
33
27 @memset(self.nfd, &.{}); 34 @memset(self.nfd, &.{});
28 35
29 while (true) { 36 while (true) {
@@ -31,6 +38,7 @@ pub fn init(allocator: mem.Allocator) !Self {
31 if (len == 0) break; 38 if (len == 0) break;
32 const cp = try reader.readInt(u24, endian); 39 const cp = try reader.readInt(u24, endian);
33 self.nfd[cp] = try allocator.alloc(u21, len - 1); 40 self.nfd[cp] = try allocator.alloc(u21, len - 1);
41 slices += 1;
34 for (0..len - 1) |i| { 42 for (0..len - 1) |i| {
35 self.nfd[cp][i] = @intCast(try reader.readInt(u24, endian)); 43 self.nfd[cp][i] = @intCast(try reader.readInt(u24, endian));
36 } 44 }
@@ -42,7 +50,7 @@ pub fn init(allocator: mem.Allocator) !Self {
42 return self; 50 return self;
43} 51}
44 52
45pub fn deinit(self: *const Self) void { 53pub fn deinit(self: *Self) void {
46 self.nfc.deinit(); 54 self.nfc.deinit();
47 for (self.nfd) |slice| self.allocator.free(slice); 55 for (self.nfd) |slice| self.allocator.free(slice);
48 self.allocator.free(self.nfd); 56 self.allocator.free(self.nfd);
diff --git a/src/CombiningData.zig b/src/CombiningData.zig
index c67638c..a40cbde 100644
--- a/src/CombiningData.zig
+++ b/src/CombiningData.zig
@@ -23,10 +23,12 @@ pub fn init(allocator: mem.Allocator) !Self {
23 23
24 const stage_1_len: u16 = try reader.readInt(u16, endian); 24 const stage_1_len: u16 = try reader.readInt(u16, endian);
25 self.s1 = try allocator.alloc(u16, stage_1_len); 25 self.s1 = try allocator.alloc(u16, stage_1_len);
26 errdefer allocator.free(self.s1);
26 for (0..stage_1_len) |i| self.s1[i] = try reader.readInt(u16, endian); 27 for (0..stage_1_len) |i| self.s1[i] = try reader.readInt(u16, endian);
27 28
28 const stage_2_len: u16 = try reader.readInt(u16, endian); 29 const stage_2_len: u16 = try reader.readInt(u16, endian);
29 self.s2 = try allocator.alloc(u8, stage_2_len); 30 self.s2 = try allocator.alloc(u8, stage_2_len);
31 errdefer allocator.free(self.s2);
30 _ = try reader.readAll(self.s2); 32 _ = try reader.readAll(self.s2);
31 33
32 return self; 34 return self;
diff --git a/src/CompatData.zig b/src/CompatData.zig
index 67c43e6..a931cb3 100644
--- a/src/CompatData.zig
+++ b/src/CompatData.zig
@@ -21,6 +21,7 @@ pub fn init(allocator: mem.Allocator) !Self {
21 .allocator = allocator, 21 .allocator = allocator,
22 .nfkd = try allocator.alloc([]u21, 0x110000), 22 .nfkd = try allocator.alloc([]u21, 0x110000),
23 }; 23 };
24 errdefer self.deinit();
24 25
25 @memset(self.nfkd, &.{}); 26 @memset(self.nfkd, &.{});
26 27
diff --git a/src/FoldData.zig b/src/FoldData.zig
index e387447..a06eefe 100644
--- a/src/FoldData.zig
+++ b/src/FoldData.zig
@@ -24,6 +24,13 @@ pub fn init(allocator: mem.Allocator) !Self {
24 .cwcf = try allocator.alloc(bool, 0x110000), 24 .cwcf = try allocator.alloc(bool, 0x110000),
25 }; 25 };
26 26
27 var slices: usize = 0;
28 errdefer {
29 for (self.fold[0..slices]) |slice| self.allocator.free(slice);
30 self.allocator.free(self.fold);
31 self.allocator.free(self.cwcf);
32 }
33
27 @memset(self.fold, &.{}); 34 @memset(self.fold, &.{});
28 @memset(self.cwcf, false); 35 @memset(self.cwcf, false);
29 36
@@ -32,6 +39,7 @@ pub fn init(allocator: mem.Allocator) !Self {
32 if (len == 0) break; 39 if (len == 0) break;
33 const cp = try reader.readInt(u24, endian); 40 const cp = try reader.readInt(u24, endian);
34 self.fold[cp >> 1] = try allocator.alloc(u21, len - 1); 41 self.fold[cp >> 1] = try allocator.alloc(u21, len - 1);
42 slices += 1;
35 for (0..len - 1) |i| { 43 for (0..len - 1) |i| {
36 self.fold[cp >> 1][i] = @intCast(try reader.readInt(u24, endian)); 44 self.fold[cp >> 1][i] = @intCast(try reader.readInt(u24, endian));
37 } 45 }
diff --git a/src/GenCatData.zig b/src/GenCatData.zig
index 37ae037..12501bf 100644
--- a/src/GenCatData.zig
+++ b/src/GenCatData.zig
@@ -58,14 +58,17 @@ pub fn init(allocator: mem.Allocator) !Self {
58 58
59 const s1_len: u16 = try reader.readInt(u16, endian); 59 const s1_len: u16 = try reader.readInt(u16, endian);
60 self.s1 = try allocator.alloc(u16, s1_len); 60 self.s1 = try allocator.alloc(u16, s1_len);
61 errdefer allocator.free(self.s1);
61 for (0..s1_len) |i| self.s1[i] = try reader.readInt(u16, endian); 62 for (0..s1_len) |i| self.s1[i] = try reader.readInt(u16, endian);
62 63
63 const s2_len: u16 = try reader.readInt(u16, endian); 64 const s2_len: u16 = try reader.readInt(u16, endian);
64 self.s2 = try allocator.alloc(u5, s2_len); 65 self.s2 = try allocator.alloc(u5, s2_len);
66 errdefer allocator.free(self.s2);
65 for (0..s2_len) |i| self.s2[i] = @intCast(try reader.readInt(u8, endian)); 67 for (0..s2_len) |i| self.s2[i] = @intCast(try reader.readInt(u8, endian));
66 68
67 const s3_len: u16 = try reader.readInt(u8, endian); 69 const s3_len: u16 = try reader.readInt(u8, endian);
68 self.s3 = try allocator.alloc(u5, s3_len); 70 self.s3 = try allocator.alloc(u5, s3_len);
71 errdefer allocator.free(self.s3);
69 for (0..s3_len) |i| self.s3[i] = @intCast(try reader.readInt(u8, endian)); 72 for (0..s3_len) |i| self.s3[i] = @intCast(try reader.readInt(u8, endian));
70 73
71 return self; 74 return self;
diff --git a/src/GraphemeData.zig b/src/GraphemeData.zig
index 971929a..500ffea 100644
--- a/src/GraphemeData.zig
+++ b/src/GraphemeData.zig
@@ -51,14 +51,17 @@ pub fn init(allocator: mem.Allocator) !Self {
51 51
52 const s1_len: u16 = try reader.readInt(u16, endian); 52 const s1_len: u16 = try reader.readInt(u16, endian);
53 self.s1 = try allocator.alloc(u16, s1_len); 53 self.s1 = try allocator.alloc(u16, s1_len);
54 errdefer allocator.free(self.s1);
54 for (0..s1_len) |i| self.s1[i] = try reader.readInt(u16, endian); 55 for (0..s1_len) |i| self.s1[i] = try reader.readInt(u16, endian);
55 56
56 const s2_len: u16 = try reader.readInt(u16, endian); 57 const s2_len: u16 = try reader.readInt(u16, endian);
57 self.s2 = try allocator.alloc(u16, s2_len); 58 self.s2 = try allocator.alloc(u16, s2_len);
59 errdefer allocator.free(self.s2);
58 for (0..s2_len) |i| self.s2[i] = try reader.readInt(u16, endian); 60 for (0..s2_len) |i| self.s2[i] = try reader.readInt(u16, endian);
59 61
60 const s3_len: u16 = try reader.readInt(u16, endian); 62 const s3_len: u16 = try reader.readInt(u16, endian);
61 self.s3 = try allocator.alloc(u8, s3_len); 63 self.s3 = try allocator.alloc(u8, s3_len);
64 errdefer allocator.free(self.s3);
62 _ = try reader.readAll(self.s3); 65 _ = try reader.readAll(self.s3);
63 66
64 return self; 67 return self;
diff --git a/src/HangulData.zig b/src/HangulData.zig
index ec360e9..99d91c1 100644
--- a/src/HangulData.zig
+++ b/src/HangulData.zig
@@ -32,10 +32,12 @@ pub fn init(allocator: mem.Allocator) !Self {
32 32
33 const stage_1_len: u16 = try reader.readInt(u16, endian); 33 const stage_1_len: u16 = try reader.readInt(u16, endian);
34 self.s1 = try allocator.alloc(u16, stage_1_len); 34 self.s1 = try allocator.alloc(u16, stage_1_len);
35 errdefer allocator.free(self.s1);
35 for (0..stage_1_len) |i| self.s1[i] = try reader.readInt(u16, endian); 36 for (0..stage_1_len) |i| self.s1[i] = try reader.readInt(u16, endian);
36 37
37 const stage_2_len: u16 = try reader.readInt(u16, endian); 38 const stage_2_len: u16 = try reader.readInt(u16, endian);
38 self.s2 = try allocator.alloc(u3, stage_2_len); 39 self.s2 = try allocator.alloc(u3, stage_2_len);
40 errdefer allocator.free(self.s2);
39 for (0..stage_2_len) |i| self.s2[i] = @intCast(try reader.readInt(u8, endian)); 41 for (0..stage_2_len) |i| self.s2[i] = @intCast(try reader.readInt(u8, endian));
40 42
41 return self; 43 return self;
diff --git a/src/NormData.zig b/src/NormData.zig
index 413619a..7ffe679 100644
--- a/src/NormData.zig
+++ b/src/NormData.zig
@@ -8,25 +8,30 @@ const FoldData = @import("FoldData");
8const HangulData = @import("HangulData"); 8const HangulData = @import("HangulData");
9const NormPropsData = @import("NormPropsData"); 9const NormPropsData = @import("NormPropsData");
10 10
11canon_data: CanonData, 11canon_data: CanonData = undefined,
12ccc_data: CccData, 12ccc_data: CccData = undefined,
13compat_data: CompatData, 13compat_data: CompatData = undefined,
14hangul_data: HangulData, 14hangul_data: HangulData = undefined,
15normp_data: NormPropsData, 15normp_data: NormPropsData = undefined,
16 16
17const Self = @This(); 17const Self = @This();
18 18
19pub fn init(allocator: std.mem.Allocator) !Self { 19pub fn init(allocator: std.mem.Allocator) !Self {
20 return Self{ 20 var self = Self{};
21 .canon_data = try CanonData.init(allocator), 21 self.canon_data = try CanonData.init(allocator);
22 .ccc_data = try CccData.init(allocator), 22 errdefer self.canon_data.deinit();
23 .compat_data = try CompatData.init(allocator), 23 self.ccc_data = try CccData.init(allocator);
24 .hangul_data = try HangulData.init(allocator), 24 errdefer self.ccc_data.deinit();
25 .normp_data = try NormPropsData.init(allocator), 25 self.compat_data = try CompatData.init(allocator);
26 }; 26 errdefer self.compat_data.deinit();
27 self.hangul_data = try HangulData.init(allocator);
28 errdefer self.hangul_data.deinit();
29 self.normp_data = try NormPropsData.init(allocator);
30
31 return self;
27} 32}
28 33
29pub fn deinit(self: *const Self) void { 34pub fn deinit(self: *Self) void {
30 self.canon_data.deinit(); 35 self.canon_data.deinit();
31 self.ccc_data.deinit(); 36 self.ccc_data.deinit();
32 self.compat_data.deinit(); 37 self.compat_data.deinit();
diff --git a/src/NormPropsData.zig b/src/NormPropsData.zig
index 893a8d0..86d497b 100644
--- a/src/NormPropsData.zig
+++ b/src/NormPropsData.zig
@@ -23,10 +23,12 @@ pub fn init(allocator: mem.Allocator) !Self {
23 23
24 const stage_1_len: u16 = try reader.readInt(u16, endian); 24 const stage_1_len: u16 = try reader.readInt(u16, endian);
25 self.s1 = try allocator.alloc(u16, stage_1_len); 25 self.s1 = try allocator.alloc(u16, stage_1_len);
26 errdefer allocator.free(self.s1);
26 for (0..stage_1_len) |i| self.s1[i] = try reader.readInt(u16, endian); 27 for (0..stage_1_len) |i| self.s1[i] = try reader.readInt(u16, endian);
27 28
28 const stage_2_len: u16 = try reader.readInt(u16, endian); 29 const stage_2_len: u16 = try reader.readInt(u16, endian);
29 self.s2 = try allocator.alloc(u4, stage_2_len); 30 self.s2 = try allocator.alloc(u4, stage_2_len);
31 errdefer allocator.free(self.s2);
30 for (0..stage_2_len) |i| self.s2[i] = @intCast(try reader.readInt(u8, endian)); 32 for (0..stage_2_len) |i| self.s2[i] = @intCast(try reader.readInt(u8, endian));
31 33
32 return self; 34 return self;
diff --git a/src/NumericData.zig b/src/NumericData.zig
index 210d623..28e8206 100644
--- a/src/NumericData.zig
+++ b/src/NumericData.zig
@@ -24,10 +24,12 @@ pub fn init(allocator: mem.Allocator) !Self {
24 24
25 const stage_1_len: u16 = try reader.readInt(u16, endian); 25 const stage_1_len: u16 = try reader.readInt(u16, endian);
26 self.s1 = try allocator.alloc(u16, stage_1_len); 26 self.s1 = try allocator.alloc(u16, stage_1_len);
27 errdefer allocator.free(self.s1);
27 for (0..stage_1_len) |i| self.s1[i] = try reader.readInt(u16, endian); 28 for (0..stage_1_len) |i| self.s1[i] = try reader.readInt(u16, endian);
28 29
29 const stage_2_len: u16 = try reader.readInt(u16, endian); 30 const stage_2_len: u16 = try reader.readInt(u16, endian);
30 self.s2 = try allocator.alloc(u8, stage_2_len); 31 self.s2 = try allocator.alloc(u8, stage_2_len);
32 errdefer allocator.free(self.s2);
31 _ = try reader.readAll(self.s2); 33 _ = try reader.readAll(self.s2);
32 34
33 return self; 35 return self;
@@ -38,11 +40,6 @@ pub fn deinit(self: *const Self) void {
38 self.allocator.free(self.s2); 40 self.allocator.free(self.s2);
39} 41}
40 42
41/// True if `cp` is any numeric type.
42pub fn isNumber(self: Self, cp: u21) bool {
43 return self.isNumeric(cp) or self.isDigit(cp) or self.isDecimal(cp);
44}
45
46/// True if `cp` is numeric. 43/// True if `cp` is numeric.
47pub inline fn isNumeric(self: Self, cp: u21) bool { 44pub inline fn isNumeric(self: Self, cp: u21) bool {
48 return self.s2[self.s1[cp >> 8] + (cp & 0xff)] & 1 == 1; 45 return self.s2[self.s1[cp >> 8] + (cp & 0xff)] & 1 == 1;
@@ -62,13 +59,10 @@ test "isDecimal" {
62 const self = try init(testing.allocator); 59 const self = try init(testing.allocator);
63 defer self.deinit(); 60 defer self.deinit();
64 61
65 try testing.expect(self.isNumber('\u{277f}'));
66 try testing.expect(self.isNumber('3'));
67 try testing.expect(self.isNumeric('\u{277f}')); 62 try testing.expect(self.isNumeric('\u{277f}'));
68 try testing.expect(self.isDigit('\u{2070}')); 63 try testing.expect(self.isDigit('\u{2070}'));
69 try testing.expect(self.isDecimal('3')); 64 try testing.expect(self.isDecimal('3'));
70 65
71 try testing.expect(!self.isNumber('z'));
72 try testing.expect(!self.isNumeric('1')); 66 try testing.expect(!self.isNumeric('1'));
73 try testing.expect(!self.isDigit('2')); 67 try testing.expect(!self.isDigit('2'));
74 try testing.expect(!self.isDecimal('g')); 68 try testing.expect(!self.isDecimal('g'));
diff --git a/src/PropsData.zig b/src/PropsData.zig
new file mode 100644
index 0000000..252462e
--- /dev/null
+++ b/src/PropsData.zig
@@ -0,0 +1,123 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const compress = std.compress;
4const mem = std.mem;
5const testing = std.testing;
6
7allocator: mem.Allocator,
8core_s1: []u16 = undefined,
9core_s2: []u8 = undefined,
10props_s1: []u16 = undefined,
11props_s2: []u8 = undefined,
12
13const Self = @This();
14
15pub fn init(allocator: mem.Allocator) !Self {
16 const decompressor = compress.deflate.decompressor;
17 const endian = builtin.cpu.arch.endian();
18
19 // Process DerivedCoreProperties.txt
20 const core_bytes = @embedFile("core_props");
21 var core_fbs = std.io.fixedBufferStream(core_bytes);
22 var core_decomp = try decompressor(allocator, core_fbs.reader(), null);
23 defer core_decomp.deinit();
24 var core_reader = core_decomp.reader();
25
26 var self = Self{ .allocator = allocator };
27
28 const core_stage_1_len: u16 = try core_reader.readInt(u16, endian);
29 self.core_s1 = try allocator.alloc(u16, core_stage_1_len);
30 errdefer allocator.free(self.core_s1);
31 for (0..core_stage_1_len) |i| self.core_s1[i] = try core_reader.readInt(u16, endian);
32
33 const core_stage_2_len: u16 = try core_reader.readInt(u16, endian);
34 self.core_s2 = try allocator.alloc(u8, core_stage_2_len);
35 errdefer allocator.free(self.core_s2);
36 _ = try core_reader.readAll(self.core_s2);
37
38 // Process PropList.txt
39 const props_bytes = @embedFile("props");
40 var props_fbs = std.io.fixedBufferStream(props_bytes);
41 var props_decomp = try decompressor(allocator, props_fbs.reader(), null);
42 defer props_decomp.deinit();
43 var props_reader = props_decomp.reader();
44
45 const stage_1_len: u16 = try props_reader.readInt(u16, endian);
46 self.props_s1 = try allocator.alloc(u16, stage_1_len);
47 errdefer allocator.free(self.props_s1);
48 for (0..stage_1_len) |i| self.props_s1[i] = try props_reader.readInt(u16, endian);
49
50 const stage_2_len: u16 = try props_reader.readInt(u16, endian);
51 self.props_s2 = try allocator.alloc(u8, stage_2_len);
52 errdefer allocator.free(self.props_s2);
53 _ = try props_reader.readAll(self.props_s2);
54
55 return self;
56}
57
58pub fn deinit(self: *const Self) void {
59 self.allocator.free(self.core_s1);
60 self.allocator.free(self.core_s2);
61 self.allocator.free(self.props_s1);
62 self.allocator.free(self.props_s2);
63}
64
65/// True if `cp` is a mathematical symbol.
66pub inline fn isMath(self: Self, cp: u21) bool {
67 return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 1 == 1;
68}
69
70/// True if `cp` is an alphabetic character.
71pub inline fn isAlphabetic(self: Self, cp: u21) bool {
72 return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 2 == 2;
73}
74
75/// True if `cp` is a valid identifier start character.
76pub inline fn isIdStart(self: Self, cp: u21) bool {
77 return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 4 == 4;
78}
79
80/// True if `cp` is a valid identifier continuation character.
81pub inline fn isIdContinue(self: Self, cp: u21) bool {
82 return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 8 == 8;
83}
84
85/// True if `cp` is a valid extended identifier start character.
86pub inline fn isXidStart(self: Self, cp: u21) bool {
87 return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 16 == 16;
88}
89
90/// True if `cp` is a valid extended identifier continuation character.
91pub inline fn isXidContinue(self: Self, cp: u21) bool {
92 return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 32 == 32;
93}
94
95/// True if `cp` is a whitespace character.
96pub inline fn isWhitespace(self: Self, cp: u21) bool {
97 return self.props_s2[self.props_s1[cp >> 8] + (cp & 0xff)] & 1 == 1;
98}
99
100/// True if `cp` is a hexadecimal digit.
101pub inline fn isHexDigit(self: Self, cp: u21) bool {
102 return self.props_s2[self.props_s1[cp >> 8] + (cp & 0xff)] & 2 == 2;
103}
104
105/// True if `cp` is a diacritic mark.
106pub inline fn isDiacritic(self: Self, cp: u21) bool {
107 return self.props_s2[self.props_s1[cp >> 8] + (cp & 0xff)] & 4 == 4;
108}
109
110test "Props" {
111 const self = try init(testing.allocator);
112 defer self.deinit();
113
114 try testing.expect(self.isHexDigit('F'));
115 try testing.expect(self.isHexDigit('a'));
116 try testing.expect(self.isHexDigit('8'));
117 try testing.expect(!self.isHexDigit('z'));
118
119 try testing.expect(self.isDiacritic('\u{301}'));
120 try testing.expect(self.isAlphabetic('A'));
121 try testing.expect(!self.isAlphabetic('3'));
122 try testing.expect(self.isMath('+'));
123}
diff --git a/src/ScriptsData.zig b/src/ScriptsData.zig
index ac1c46a..4e371bf 100644
--- a/src/ScriptsData.zig
+++ b/src/ScriptsData.zig
@@ -193,14 +193,17 @@ pub fn init(allocator: mem.Allocator) !Self {
193 193
194 const s1_len: u16 = try reader.readInt(u16, endian); 194 const s1_len: u16 = try reader.readInt(u16, endian);
195 self.s1 = try allocator.alloc(u16, s1_len); 195 self.s1 = try allocator.alloc(u16, s1_len);
196 errdefer allocator.free(self.s1);
196 for (0..s1_len) |i| self.s1[i] = try reader.readInt(u16, endian); 197 for (0..s1_len) |i| self.s1[i] = try reader.readInt(u16, endian);
197 198
198 const s2_len: u16 = try reader.readInt(u16, endian); 199 const s2_len: u16 = try reader.readInt(u16, endian);
199 self.s2 = try allocator.alloc(u8, s2_len); 200 self.s2 = try allocator.alloc(u8, s2_len);
201 errdefer allocator.free(self.s2);
200 _ = try reader.readAll(self.s2); 202 _ = try reader.readAll(self.s2);
201 203
202 const s3_len: u16 = try reader.readInt(u8, endian); 204 const s3_len: u16 = try reader.readInt(u8, endian);
203 self.s3 = try allocator.alloc(u8, s3_len); 205 self.s3 = try allocator.alloc(u8, s3_len);
206 errdefer allocator.free(self.s3);
204 _ = try reader.readAll(self.s3); 207 _ = try reader.readAll(self.s3);
205 208
206 return self; 209 return self;
diff --git a/src/WidthData.zig b/src/WidthData.zig
index d17f0cd..b9ef84e 100644
--- a/src/WidthData.zig
+++ b/src/WidthData.zig
@@ -27,13 +27,16 @@ pub fn init(allocator: mem.Allocator) !Self {
27 .allocator = allocator, 27 .allocator = allocator,
28 .g_data = try GraphemeData.init(allocator), 28 .g_data = try GraphemeData.init(allocator),
29 }; 29 };
30 errdefer self.g_data.deinit();
30 31
31 const stage_1_len: u16 = try reader.readInt(u16, endian); 32 const stage_1_len: u16 = try reader.readInt(u16, endian);
32 self.s1 = try allocator.alloc(u16, stage_1_len); 33 self.s1 = try allocator.alloc(u16, stage_1_len);
34 errdefer allocator.free(self.s1);
33 for (0..stage_1_len) |i| self.s1[i] = try reader.readInt(u16, endian); 35 for (0..stage_1_len) |i| self.s1[i] = try reader.readInt(u16, endian);
34 36
35 const stage_2_len: u16 = try reader.readInt(u16, endian); 37 const stage_2_len: u16 = try reader.readInt(u16, endian);
36 self.s2 = try allocator.alloc(i3, stage_2_len); 38 self.s2 = try allocator.alloc(i3, stage_2_len);
39 errdefer allocator.free(self.s2);
37 for (0..stage_2_len) |i| self.s2[i] = @intCast(try reader.readInt(i8, endian)); 40 for (0..stage_2_len) |i| self.s2[i] = @intCast(try reader.readInt(i8, endian));
38 41
39 return self; 42 return self;