summaryrefslogtreecommitdiff
path: root/src/DisplayWidth.zig
diff options
context:
space:
mode:
authorGravatar Sam Atman2025-04-30 20:30:39 -0400
committerGravatar Sam Atman2025-04-30 20:30:39 -0400
commit10048b0d31d0db923ae39c6bbd67139ed6252f6f (patch)
tree65df1666aacd102f59b4ac0844ccc7f7ddda91db /src/DisplayWidth.zig
parentSetup variants for all allocating modules (diff)
downloadzg-10048b0d31d0db923ae39c6bbd67139ed6252f6f.tar.gz
zg-10048b0d31d0db923ae39c6bbd67139ed6252f6f.tar.xz
zg-10048b0d31d0db923ae39c6bbd67139ed6252f6f.zip
Allocation Failure Tests
These turned up an excessive amount of allocations in CanonData and CompatData, which have been reduced to two through the somewhat squirrely use of 'magic numbers'. There are now allocation tests for every allocated structure in the library, and they run to completion in a reasonable amount of time. So, that's nice.
Diffstat (limited to 'src/DisplayWidth.zig')
-rw-r--r--src/DisplayWidth.zig72
1 files changed, 46 insertions, 26 deletions
diff --git a/src/DisplayWidth.zig b/src/DisplayWidth.zig
index c0d6d96..4c63be4 100644
--- a/src/DisplayWidth.zig
+++ b/src/DisplayWidth.zig
@@ -1,27 +1,18 @@
1const std = @import("std"); 1//! Display Width module
2const builtin = @import("builtin"); 2//!
3const options = @import("options"); 3//! Answers questions about the printable width in monospaced fonts of the
4const ArrayList = std.ArrayList; 4//! string of interest.
5const compress = std.compress;
6const mem = std.mem;
7const simd = std.simd;
8const testing = std.testing;
9
10const ascii = @import("ascii");
11const CodePointIterator = @import("code_point").Iterator;
12pub const DisplayWidthData = @import("DisplayWidthData");
13 5
14const Graphemes = @import("Graphemes"); 6graphemes: Graphemes = undefined,
15
16graphemes: Graphemes,
17s1: []u16 = undefined, 7s1: []u16 = undefined,
18s2: []i4 = undefined, 8s2: []i4 = undefined,
19owns_graphemes: bool, 9owns_graphemes: bool = true,
20 10
21const DisplayWidth = @This(); 11const DisplayWidth = @This();
22 12
23pub fn init(allocator: mem.Allocator) mem.Allocator.Error!DisplayWidth { 13pub fn init(allocator: Allocator) Allocator.Error!DisplayWidth {
24 var dw: DisplayWidth = try DisplayWidth.setup(allocator); 14 var dw = DisplayWidth{};
15 try dw.setup(allocator);
25 errdefer { 16 errdefer {
26 allocator.free(dw.s1); 17 allocator.free(dw.s1);
27 allocator.free(dw.s2); 18 allocator.free(dw.s2);
@@ -32,15 +23,16 @@ pub fn init(allocator: mem.Allocator) mem.Allocator.Error!DisplayWidth {
32 return dw; 23 return dw;
33} 24}
34 25
35pub fn initWithGraphemes(allocator: mem.Allocator, graphemes: Graphemes) mem.Allocator.Error!DisplayWidth { 26pub fn initWithGraphemes(allocator: Allocator, graphemes: Graphemes) Allocator.Error!DisplayWidth {
36 var dw = try DisplayWidth.setup(allocator); 27 var dw = DisplayWidth{};
28 try dw.setup(allocator);
37 dw.graphemes = graphemes; 29 dw.graphemes = graphemes;
38 dw.owns_graphemes = false; 30 dw.owns_graphemes = false;
39 return dw; 31 return dw;
40} 32}
41 33
42// Sets up the DisplayWidthData, leaving the GraphemeData undefined. 34// Sets up the DisplayWidthData, leaving the GraphemeData undefined.
43fn setup(allocator: mem.Allocator) mem.Allocator.Error!DisplayWidth { 35fn setup(dw: *DisplayWidth, allocator: Allocator) Allocator.Error!void {
44 const decompressor = compress.flate.inflate.decompressor; 36 const decompressor = compress.flate.inflate.decompressor;
45 const in_bytes = @embedFile("dwp"); 37 const in_bytes = @embedFile("dwp");
46 var in_fbs = std.io.fixedBufferStream(in_bytes); 38 var in_fbs = std.io.fixedBufferStream(in_bytes);
@@ -49,8 +41,6 @@ fn setup(allocator: mem.Allocator) mem.Allocator.Error!DisplayWidth {
49 41
50 const endian = builtin.cpu.arch.endian(); 42 const endian = builtin.cpu.arch.endian();
51 43
52 var dw: DisplayWidth = undefined;
53
54 const stage_1_len: u16 = reader.readInt(u16, endian) catch unreachable; 44 const stage_1_len: u16 = reader.readInt(u16, endian) catch unreachable;
55 dw.s1 = try allocator.alloc(u16, stage_1_len); 45 dw.s1 = try allocator.alloc(u16, stage_1_len);
56 errdefer allocator.free(dw.s1); 46 errdefer allocator.free(dw.s1);
@@ -60,11 +50,9 @@ fn setup(allocator: mem.Allocator) mem.Allocator.Error!DisplayWidth {
60 dw.s2 = try allocator.alloc(i4, stage_2_len); 50 dw.s2 = try allocator.alloc(i4, stage_2_len);
61 errdefer allocator.free(dw.s2); 51 errdefer allocator.free(dw.s2);
62 for (0..stage_2_len) |i| dw.s2[i] = @intCast(reader.readInt(i8, endian) catch unreachable); 52 for (0..stage_2_len) |i| dw.s2[i] = @intCast(reader.readInt(i8, endian) catch unreachable);
63
64 return dw;
65} 53}
66 54
67pub fn deinit(dw: *const DisplayWidth, allocator: mem.Allocator) void { 55pub fn deinit(dw: *const DisplayWidth, allocator: Allocator) void {
68 allocator.free(dw.s1); 56 allocator.free(dw.s1);
69 allocator.free(dw.s2); 57 allocator.free(dw.s2);
70 if (dw.owns_graphemes) dw.graphemes.deinit(allocator); 58 if (dw.owns_graphemes) dw.graphemes.deinit(allocator);
@@ -445,3 +433,35 @@ test "wrap" {
445 const want = "The quick \nbrown fox \njumped \nover the \nlazy dog!"; 433 const want = "The quick \nbrown fox \njumped \nover the \nlazy dog!";
446 try testing.expectEqualStrings(want, got); 434 try testing.expectEqualStrings(want, got);
447} 435}
436
437fn testAllocation(allocator: Allocator) !void {
438 {
439 var dw = try DisplayWidth.init(allocator);
440 dw.deinit(allocator);
441 }
442 {
443 var graph = try Graphemes.init(allocator);
444 defer graph.deinit(allocator);
445 var dw = try DisplayWidth.initWithGraphemes(allocator, graph);
446 dw.deinit(allocator);
447 }
448}
449
450test "allocation test" {
451 try testing.checkAllAllocationFailures(testing.allocator, testAllocation, .{});
452}
453
454const std = @import("std");
455const builtin = @import("builtin");
456const options = @import("options");
457const ArrayList = std.ArrayList;
458const compress = std.compress;
459const mem = std.mem;
460const Allocator = mem.Allocator;
461const simd = std.simd;
462const testing = std.testing;
463
464const ascii = @import("ascii");
465const CodePointIterator = @import("code_point").Iterator;
466
467const Graphemes = @import("Graphemes");