summaryrefslogtreecommitdiff
path: root/src/GeneralCategories.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/GeneralCategories.zig')
-rw-r--r--src/GeneralCategories.zig79
1 files changed, 49 insertions, 30 deletions
diff --git a/src/GeneralCategories.zig b/src/GeneralCategories.zig
index b7c82c0..3e76d82 100644
--- a/src/GeneralCategories.zig
+++ b/src/GeneralCategories.zig
@@ -46,7 +46,16 @@ pub fn init(allocator: Allocator) Allocator.Error!GeneralCategories {
46 return gencat; 46 return gencat;
47} 47}
48 48
49pub fn setup(self: *GeneralCategories, allocator: Allocator) Allocator.Error!void { 49pub fn setup(gencat: *GeneralCategories, allocator: Allocator) Allocator.Error!void {
50 gencat.setupInner(allocator) catch |err| {
51 switch (err) {
52 error.OutOfMemory => |e| return e,
53 else => unreachable,
54 }
55 };
56}
57
58inline fn setupInner(gencat: *GeneralCategories, allocator: Allocator) !void {
50 const decompressor = compress.flate.inflate.decompressor; 59 const decompressor = compress.flate.inflate.decompressor;
51 const in_bytes = @embedFile("gencat"); 60 const in_bytes = @embedFile("gencat");
52 var in_fbs = std.io.fixedBufferStream(in_bytes); 61 var in_fbs = std.io.fixedBufferStream(in_bytes);
@@ -56,35 +65,35 @@ pub fn setup(self: *GeneralCategories, allocator: Allocator) Allocator.Error!voi
56 const endian = builtin.cpu.arch.endian(); 65 const endian = builtin.cpu.arch.endian();
57 66
58 const s1_len: u16 = reader.readInt(u16, endian) catch unreachable; 67 const s1_len: u16 = reader.readInt(u16, endian) catch unreachable;
59 self.s1 = try allocator.alloc(u16, s1_len); 68 gencat.s1 = try allocator.alloc(u16, s1_len);
60 errdefer allocator.free(self.s1); 69 errdefer allocator.free(gencat.s1);
61 for (0..s1_len) |i| self.s1[i] = try reader.readInt(u16, endian); 70 for (0..s1_len) |i| gencat.s1[i] = try reader.readInt(u16, endian);
62 71
63 const s2_len: u16 = reader.readInt(u16, endian) catch unreachable; 72 const s2_len: u16 = reader.readInt(u16, endian) catch unreachable;
64 self.s2 = try allocator.alloc(u5, s2_len); 73 gencat.s2 = try allocator.alloc(u5, s2_len);
65 errdefer allocator.free(self.s2); 74 errdefer allocator.free(gencat.s2);
66 for (0..s2_len) |i| self.s2[i] = @intCast(reader.readInt(u8, endian) catch unreachable); 75 for (0..s2_len) |i| gencat.s2[i] = @intCast(reader.readInt(u8, endian) catch unreachable);
67 76
68 const s3_len: u16 = reader.readInt(u8, endian) catch unreachable; 77 const s3_len: u16 = reader.readInt(u8, endian) catch unreachable;
69 self.s3 = try allocator.alloc(u5, s3_len); 78 gencat.s3 = try allocator.alloc(u5, s3_len);
70 errdefer allocator.free(self.s3); 79 errdefer allocator.free(gencat.s3);
71 for (0..s3_len) |i| self.s3[i] = @intCast(reader.readInt(u8, endian) catch unreachable); 80 for (0..s3_len) |i| gencat.s3[i] = @intCast(reader.readInt(u8, endian) catch unreachable);
72} 81}
73 82
74pub fn deinit(self: *const GeneralCategories, allocator: mem.Allocator) void { 83pub fn deinit(gencat: *const GeneralCategories, allocator: mem.Allocator) void {
75 allocator.free(self.s1); 84 allocator.free(gencat.s1);
76 allocator.free(self.s2); 85 allocator.free(gencat.s2);
77 allocator.free(self.s3); 86 allocator.free(gencat.s3);
78} 87}
79 88
80/// Lookup the General Category for `cp`. 89/// Lookup the General Category for `cp`.
81pub fn gc(self: GeneralCategories, cp: u21) Gc { 90pub fn gc(gencat: GeneralCategories, cp: u21) Gc {
82 return @enumFromInt(self.s3[self.s2[self.s1[cp >> 8] + (cp & 0xff)]]); 91 return @enumFromInt(gencat.s3[gencat.s2[gencat.s1[cp >> 8] + (cp & 0xff)]]);
83} 92}
84 93
85/// True if `cp` has an C general category. 94/// True if `cp` has an C general category.
86pub fn isControl(self: GeneralCategories, cp: u21) bool { 95pub fn isControl(gencat: GeneralCategories, cp: u21) bool {
87 return switch (self.gc(cp)) { 96 return switch (gencat.gc(cp)) {
88 .Cc, 97 .Cc,
89 .Cf, 98 .Cf,
90 .Cn, 99 .Cn,
@@ -96,8 +105,8 @@ pub fn isControl(self: GeneralCategories, cp: u21) bool {
96} 105}
97 106
98/// True if `cp` has an L general category. 107/// True if `cp` has an L general category.
99pub fn isLetter(self: GeneralCategories, cp: u21) bool { 108pub fn isLetter(gencat: GeneralCategories, cp: u21) bool {
100 return switch (self.gc(cp)) { 109 return switch (gencat.gc(cp)) {
101 .Ll, 110 .Ll,
102 .Lm, 111 .Lm,
103 .Lo, 112 .Lo,
@@ -109,8 +118,8 @@ pub fn isLetter(self: GeneralCategories, cp: u21) bool {
109} 118}
110 119
111/// True if `cp` has an M general category. 120/// True if `cp` has an M general category.
112pub fn isMark(self: GeneralCategories, cp: u21) bool { 121pub fn isMark(gencat: GeneralCategories, cp: u21) bool {
113 return switch (self.gc(cp)) { 122 return switch (gencat.gc(cp)) {
114 .Mc, 123 .Mc,
115 .Me, 124 .Me,
116 .Mn, 125 .Mn,
@@ -120,8 +129,8 @@ pub fn isMark(self: GeneralCategories, cp: u21) bool {
120} 129}
121 130
122/// True if `cp` has an N general category. 131/// True if `cp` has an N general category.
123pub fn isNumber(self: GeneralCategories, cp: u21) bool { 132pub fn isNumber(gencat: GeneralCategories, cp: u21) bool {
124 return switch (self.gc(cp)) { 133 return switch (gencat.gc(cp)) {
125 .Nd, 134 .Nd,
126 .Nl, 135 .Nl,
127 .No, 136 .No,
@@ -131,8 +140,8 @@ pub fn isNumber(self: GeneralCategories, cp: u21) bool {
131} 140}
132 141
133/// True if `cp` has an P general category. 142/// True if `cp` has an P general category.
134pub fn isPunctuation(self: GeneralCategories, cp: u21) bool { 143pub fn isPunctuation(gencat: GeneralCategories, cp: u21) bool {
135 return switch (self.gc(cp)) { 144 return switch (gencat.gc(cp)) {
136 .Pc, 145 .Pc,
137 .Pd, 146 .Pd,
138 .Pe, 147 .Pe,
@@ -146,8 +155,8 @@ pub fn isPunctuation(self: GeneralCategories, cp: u21) bool {
146} 155}
147 156
148/// True if `cp` has an S general category. 157/// True if `cp` has an S general category.
149pub fn isSymbol(self: GeneralCategories, cp: u21) bool { 158pub fn isSymbol(gencat: GeneralCategories, cp: u21) bool {
150 return switch (self.gc(cp)) { 159 return switch (gencat.gc(cp)) {
151 .Sc, 160 .Sc,
152 .Sk, 161 .Sk,
153 .Sm, 162 .Sm,
@@ -158,8 +167,8 @@ pub fn isSymbol(self: GeneralCategories, cp: u21) bool {
158} 167}
159 168
160/// True if `cp` has an Z general category. 169/// True if `cp` has an Z general category.
161pub fn isSeparator(self: GeneralCategories, cp: u21) bool { 170pub fn isSeparator(gencat: GeneralCategories, cp: u21) bool {
162 return switch (self.gc(cp)) { 171 return switch (gencat.gc(cp)) {
163 .Zl, 172 .Zl,
164 .Zp, 173 .Zp,
165 .Zs, 174 .Zs,
@@ -168,8 +177,18 @@ pub fn isSeparator(self: GeneralCategories, cp: u21) bool {
168 }; 177 };
169} 178}
170 179
180fn testAllocator(allocator: Allocator) !void {
181 var gen_cat = try GeneralCategories.init(allocator);
182 gen_cat.deinit(allocator);
183}
184
185test "Allocation failure" {
186 try testing.checkAllAllocationFailures(testing.allocator, testAllocator, .{});
187}
188
171const std = @import("std"); 189const std = @import("std");
172const builtin = @import("builtin"); 190const builtin = @import("builtin");
173const compress = std.compress; 191const compress = std.compress;
174const mem = std.mem; 192const mem = std.mem;
193const testing = std.testing;
175const Allocator = mem.Allocator; 194const Allocator = mem.Allocator;