From 9f2e3bf4b48767a7c42bc77e609845a7b285b23c Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 12 Feb 2025 18:09:14 +0100 Subject: [PATCH 1/2] fix: load case data early on startup instead of on demand This is to avoid an issue with the decompressor causing heap corruption on macos. closes #169 --- build.zig | 4 +++- src/buffer/unicode.zig | 10 ++++++++++ src/main.zig | 2 ++ src/tui/editor.zig | 18 ++++-------------- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/build.zig b/build.zig index e6af465..99e798e 100644 --- a/build.zig +++ b/build.zig @@ -293,6 +293,7 @@ pub fn build_exe( .imports = &.{ .{ .name = "cbor", .module = cbor_mod }, .{ .name = "thespian", .module = thespian_mod }, + .{ .name = "CaseData", .module = zg_dep.module("CaseData") }, }, }); @@ -476,7 +477,6 @@ pub fn build_exe( .{ .name = "color", .module = color_mod }, .{ .name = "diff", .module = diff_mod }, .{ .name = "help.md", .module = help_mod }, - .{ .name = "CaseData", .module = zg_dep.module("CaseData") }, .{ .name = "fuzzig", .module = fuzzig_dep.module("fuzzig") }, .{ .name = "zeit", .module = zeit_mod }, }, @@ -502,6 +502,7 @@ pub fn build_exe( exe.root_module.addImport("flags", flags_dep.module("flags")); exe.root_module.addImport("cbor", cbor_mod); exe.root_module.addImport("config", config_mod); + exe.root_module.addImport("Buffer", Buffer_mod); exe.root_module.addImport("tui", tui_mod); exe.root_module.addImport("thespian", thespian_mod); exe.root_module.addImport("log", log_mod); @@ -543,6 +544,7 @@ pub fn build_exe( check_exe.root_module.addImport("flags", flags_dep.module("flags")); check_exe.root_module.addImport("cbor", cbor_mod); check_exe.root_module.addImport("config", config_mod); + check_exe.root_module.addImport("Buffer", Buffer_mod); check_exe.root_module.addImport("tui", tui_mod); check_exe.root_module.addImport("thespian", thespian_mod); check_exe.root_module.addImport("log", log_mod); diff --git a/src/buffer/unicode.zig b/src/buffer/unicode.zig index 8d0bb63..60bf389 100644 --- a/src/buffer/unicode.zig +++ b/src/buffer/unicode.zig @@ -59,3 +59,13 @@ pub fn utf8_sanitize(allocator: std.mem.Allocator, input: []const u8) error{ for (input) |byte| try writer.writeAll(try raw_byte_to_utf8(byte, &buf)); return output.toOwnedSlice(allocator); } + +pub const CaseData = @import("CaseData"); +var case_data: ?CaseData = null; +var case_data_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + +pub fn get_case_data() *CaseData { + if (case_data) |*cd| return cd; + case_data = CaseData.init(case_data_arena.allocator()) catch @panic("CaseData.init"); + return &case_data.?; +} diff --git a/src/main.zig b/src/main.zig index acf34d4..e7adc38 100644 --- a/src/main.zig +++ b/src/main.zig @@ -41,6 +41,8 @@ pub fn main() anyerror!void { } const a = std.heap.c_allocator; + const case_data = @import("Buffer").unicode.get_case_data(); + _ = case_data; // no need to free case_data as it is globally static const Flags = struct { pub const description = diff --git a/src/tui/editor.zig b/src/tui/editor.zig index 3d4780e..59fa97c 100644 --- a/src/tui/editor.zig +++ b/src/tui/editor.zig @@ -9,7 +9,6 @@ const tracy = @import("tracy"); const text_manip = @import("text_manip"); const syntax = @import("syntax"); const project_manager = @import("project_manager"); -const CaseData = @import("CaseData"); const root_mod = @import("root"); const Plane = @import("renderer").Plane; @@ -350,8 +349,6 @@ pub const Editor = struct { } = null, } = null, - case_data: ?CaseData = null, - const WhitespaceMode = enum { indent, leading, eol, tabs, visible, full, none }; const StyleCache = std.AutoHashMap(u32, ?Widget.Theme.Token); @@ -468,7 +465,6 @@ pub const Editor = struct { self.handlers.deinit(); self.logger.deinit(); if (self.buffer) |p| self.buffer_manager.retire(p, meta.items); - if (self.case_data) |cd| cd.deinit(); } fn from_whitespace_mode(whitespace_mode: []const u8) WhitespaceMode { @@ -492,12 +488,6 @@ pub const Editor = struct { Widget.need_render(); } - fn get_case_data(self: *Self) *CaseData { - if (self.case_data) |*cd| return cd; - self.case_data = CaseData.init(self.allocator) catch @panic("CaseData.init"); - return &self.case_data.?; - } - fn buf_for_update(self: *Self) !*const Buffer { if (!self.pause_undo) { self.cursels_saved.clearAndFree(); @@ -4966,7 +4956,7 @@ pub const Editor = struct { var sfa = std.heap.stackFallback(4096, self.allocator); const cut_text = copy_selection(root, sel.*, sfa.get(), self.metrics) catch return error.Stop; defer allocator.free(cut_text); - const ucased = self.get_case_data().toUpperStr(allocator, cut_text) catch return error.Stop; + const ucased = Buffer.unicode.get_case_data().toUpperStr(allocator, cut_text) catch return error.Stop; defer allocator.free(ucased); root = try self.delete_selection(root, cursel, allocator); root = self.insert(root, cursel, ucased, allocator) catch return error.Stop; @@ -4994,7 +4984,7 @@ pub const Editor = struct { var sfa = std.heap.stackFallback(4096, self.allocator); const cut_text = copy_selection(root, sel.*, sfa.get(), self.metrics) catch return error.Stop; defer allocator.free(cut_text); - const ucased = self.get_case_data().toLowerStr(allocator, cut_text) catch return error.Stop; + const ucased = Buffer.unicode.get_case_data().toLowerStr(allocator, cut_text) catch return error.Stop; defer allocator.free(ucased); root = try self.delete_selection(root, cursel, allocator); root = self.insert(root, cursel, ucased, allocator) catch return error.Stop; @@ -5025,9 +5015,9 @@ pub const Editor = struct { self_: *Self, result: *std.ArrayList(u8), - const Error = @typeInfo(@typeInfo(@TypeOf(CaseData.toUpperStr)).Fn.return_type.?).ErrorUnion.error_set; + const Error = @typeInfo(@typeInfo(@TypeOf(Buffer.unicode.CaseData.toUpperStr)).Fn.return_type.?).ErrorUnion.error_set; pub fn write(writer: *@This(), bytes: []const u8) Error!void { - const cd = writer.self_.get_case_data(); + const cd = Buffer.unicode.get_case_data(); const flipped = if (cd.isLowerStr(bytes)) try cd.toUpperStr(writer.self_.allocator, bytes) else From fb5cd46d0b1fd277d6de3ded0a9d1d99bd73d643 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Wed, 12 Feb 2025 18:17:43 +0100 Subject: [PATCH 2/2] fix: check target missing color module --- build.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/build.zig b/build.zig index 99e798e..b135612 100644 --- a/build.zig +++ b/build.zig @@ -552,6 +552,7 @@ pub fn build_exe( check_exe.root_module.addImport("renderer", renderer_mod); check_exe.root_module.addImport("input", input_mod); check_exe.root_module.addImport("syntax", syntax_mod); + check_exe.root_module.addImport("color", color_mod); check_exe.root_module.addImport("version_info", b.createModule(.{ .root_source_file = version_info_file })); check_step.dependOn(&check_exe.step);