From d2d42bf3ef5490f6fdec73508c2493a666ecee41 Mon Sep 17 00:00:00 2001 From: Sam Atman Date: Wed, 30 Apr 2025 16:48:07 -0400 Subject: Setup variants for all allocating modules This harmonizes the allocating modules in a couple of ways. All can now be constructed by pointer, and all treat various miscellaneous read failures as `unreachable`, which indeed they should be. The README has been updated to inform users of this option. --- src/Properties.zig | 98 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 56 insertions(+), 42 deletions(-) (limited to 'src/Properties.zig') diff --git a/src/Properties.zig b/src/Properties.zig index 46920be..f7e57ec 100644 --- a/src/Properties.zig +++ b/src/Properties.zig @@ -1,8 +1,4 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const compress = std.compress; -const mem = std.mem; -const testing = std.testing; +//! Properties module core_s1: []u16 = undefined, core_s2: []u8 = undefined, @@ -11,9 +7,24 @@ props_s2: []u8 = undefined, num_s1: []u16 = undefined, num_s2: []u8 = undefined, -const Self = @This(); +const Properties = @This(); + +pub fn init(allocator: Allocator) Allocator.Error!Properties { + var props = Properties{}; + try props.setup(allocator); + return props; +} + +pub fn setup(props: *Properties, allocator: Allocator) Allocator.Error!void { + props.setupInner(allocator) catch |err| { + switch (err) { + error.OutOfMemory => |e| return e, + else => unreachable, + } + }; +} -pub fn init(allocator: mem.Allocator) !Self { +inline fn setupInner(props: *Properties, allocator: Allocator) !void { const decompressor = compress.flate.inflate.decompressor; const endian = builtin.cpu.arch.endian(); @@ -23,17 +34,15 @@ pub fn init(allocator: mem.Allocator) !Self { var core_decomp = decompressor(.raw, core_fbs.reader()); var core_reader = core_decomp.reader(); - var self = Self{}; - const core_stage_1_len: u16 = try core_reader.readInt(u16, endian); - self.core_s1 = try allocator.alloc(u16, core_stage_1_len); - errdefer allocator.free(self.core_s1); - for (0..core_stage_1_len) |i| self.core_s1[i] = try core_reader.readInt(u16, endian); + props.core_s1 = try allocator.alloc(u16, core_stage_1_len); + errdefer allocator.free(props.core_s1); + for (0..core_stage_1_len) |i| props.core_s1[i] = try core_reader.readInt(u16, endian); const core_stage_2_len: u16 = try core_reader.readInt(u16, endian); - self.core_s2 = try allocator.alloc(u8, core_stage_2_len); - errdefer allocator.free(self.core_s2); - _ = try core_reader.readAll(self.core_s2); + props.core_s2 = try allocator.alloc(u8, core_stage_2_len); + errdefer allocator.free(props.core_s2); + _ = try core_reader.readAll(props.core_s2); // Process PropList.txt const props_bytes = @embedFile("props"); @@ -42,14 +51,14 @@ pub fn init(allocator: mem.Allocator) !Self { var props_reader = props_decomp.reader(); const stage_1_len: u16 = try props_reader.readInt(u16, endian); - self.props_s1 = try allocator.alloc(u16, stage_1_len); - errdefer allocator.free(self.props_s1); - for (0..stage_1_len) |i| self.props_s1[i] = try props_reader.readInt(u16, endian); + props.props_s1 = try allocator.alloc(u16, stage_1_len); + errdefer allocator.free(props.props_s1); + for (0..stage_1_len) |i| props.props_s1[i] = try props_reader.readInt(u16, endian); const stage_2_len: u16 = try props_reader.readInt(u16, endian); - self.props_s2 = try allocator.alloc(u8, stage_2_len); - errdefer allocator.free(self.props_s2); - _ = try props_reader.readAll(self.props_s2); + props.props_s2 = try allocator.alloc(u8, stage_2_len); + errdefer allocator.free(props.props_s2); + _ = try props_reader.readAll(props.props_s2); // Process DerivedNumericType.txt const num_bytes = @embedFile("numeric"); @@ -58,19 +67,17 @@ pub fn init(allocator: mem.Allocator) !Self { var num_reader = num_decomp.reader(); const num_stage_1_len: u16 = try num_reader.readInt(u16, endian); - self.num_s1 = try allocator.alloc(u16, num_stage_1_len); - errdefer allocator.free(self.num_s1); - for (0..num_stage_1_len) |i| self.num_s1[i] = try num_reader.readInt(u16, endian); + props.num_s1 = try allocator.alloc(u16, num_stage_1_len); + errdefer allocator.free(props.num_s1); + for (0..num_stage_1_len) |i| props.num_s1[i] = try num_reader.readInt(u16, endian); const num_stage_2_len: u16 = try num_reader.readInt(u16, endian); - self.num_s2 = try allocator.alloc(u8, num_stage_2_len); - errdefer allocator.free(self.num_s2); - _ = try num_reader.readAll(self.num_s2); - - return self; + props.num_s2 = try allocator.alloc(u8, num_stage_2_len); + errdefer allocator.free(props.num_s2); + _ = try num_reader.readAll(props.num_s2); } -pub fn deinit(self: *const Self, allocator: mem.Allocator) void { +pub fn deinit(self: *const Properties, allocator: Allocator) void { allocator.free(self.core_s1); allocator.free(self.core_s2); allocator.free(self.props_s1); @@ -80,62 +87,62 @@ pub fn deinit(self: *const Self, allocator: mem.Allocator) void { } /// True if `cp` is a mathematical symbol. -pub fn isMath(self: Self, cp: u21) bool { +pub fn isMath(self: Properties, cp: u21) bool { return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 1 == 1; } /// True if `cp` is an alphabetic character. -pub fn isAlphabetic(self: Self, cp: u21) bool { +pub fn isAlphabetic(self: Properties, cp: u21) bool { return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 2 == 2; } /// True if `cp` is a valid identifier start character. -pub fn isIdStart(self: Self, cp: u21) bool { +pub fn isIdStart(self: Properties, cp: u21) bool { return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 4 == 4; } /// True if `cp` is a valid identifier continuation character. -pub fn isIdContinue(self: Self, cp: u21) bool { +pub fn isIdContinue(self: Properties, cp: u21) bool { return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 8 == 8; } /// True if `cp` is a valid extended identifier start character. -pub fn isXidStart(self: Self, cp: u21) bool { +pub fn isXidStart(self: Properties, cp: u21) bool { return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 16 == 16; } /// True if `cp` is a valid extended identifier continuation character. -pub fn isXidContinue(self: Self, cp: u21) bool { +pub fn isXidContinue(self: Properties, cp: u21) bool { return self.core_s2[self.core_s1[cp >> 8] + (cp & 0xff)] & 32 == 32; } /// True if `cp` is a whitespace character. -pub fn isWhitespace(self: Self, cp: u21) bool { +pub fn isWhitespace(self: Properties, cp: u21) bool { return self.props_s2[self.props_s1[cp >> 8] + (cp & 0xff)] & 1 == 1; } /// True if `cp` is a hexadecimal digit. -pub fn isHexDigit(self: Self, cp: u21) bool { +pub fn isHexDigit(self: Properties, cp: u21) bool { return self.props_s2[self.props_s1[cp >> 8] + (cp & 0xff)] & 2 == 2; } /// True if `cp` is a diacritic mark. -pub fn isDiacritic(self: Self, cp: u21) bool { +pub fn isDiacritic(self: Properties, cp: u21) bool { return self.props_s2[self.props_s1[cp >> 8] + (cp & 0xff)] & 4 == 4; } /// True if `cp` is numeric. -pub fn isNumeric(self: Self, cp: u21) bool { +pub fn isNumeric(self: Properties, cp: u21) bool { return self.num_s2[self.num_s1[cp >> 8] + (cp & 0xff)] & 1 == 1; } /// True if `cp` is a digit. -pub fn isDigit(self: Self, cp: u21) bool { +pub fn isDigit(self: Properties, cp: u21) bool { return self.num_s2[self.num_s1[cp >> 8] + (cp & 0xff)] & 2 == 2; } /// True if `cp` is decimal. -pub fn isDecimal(self: Self, cp: u21) bool { +pub fn isDecimal(self: Properties, cp: u21) bool { return self.num_s2[self.num_s1[cp >> 8] + (cp & 0xff)] & 4 == 4; } @@ -161,3 +168,10 @@ test "Props" { try testing.expect(!self.isDigit('2')); try testing.expect(!self.isDecimal('g')); } + +const std = @import("std"); +const builtin = @import("builtin"); +const compress = std.compress; +const mem = std.mem; +const Allocator = mem.Allocator; +const testing = std.testing; -- cgit v1.2.3