diff options
| author | 2025-04-30 20:30:39 -0400 | |
|---|---|---|
| committer | 2025-04-30 20:30:39 -0400 | |
| commit | 10048b0d31d0db923ae39c6bbd67139ed6252f6f (patch) | |
| tree | 65df1666aacd102f59b4ac0844ccc7f7ddda91db /src/DisplayWidth.zig | |
| parent | Setup variants for all allocating modules (diff) | |
| download | zg-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.zig | 72 |
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 @@ | |||
| 1 | const std = @import("std"); | 1 | //! Display Width module |
| 2 | const builtin = @import("builtin"); | 2 | //! |
| 3 | const options = @import("options"); | 3 | //! Answers questions about the printable width in monospaced fonts of the |
| 4 | const ArrayList = std.ArrayList; | 4 | //! string of interest. |
| 5 | const compress = std.compress; | ||
| 6 | const mem = std.mem; | ||
| 7 | const simd = std.simd; | ||
| 8 | const testing = std.testing; | ||
| 9 | |||
| 10 | const ascii = @import("ascii"); | ||
| 11 | const CodePointIterator = @import("code_point").Iterator; | ||
| 12 | pub const DisplayWidthData = @import("DisplayWidthData"); | ||
| 13 | 5 | ||
| 14 | const Graphemes = @import("Graphemes"); | 6 | graphemes: Graphemes = undefined, |
| 15 | |||
| 16 | graphemes: Graphemes, | ||
| 17 | s1: []u16 = undefined, | 7 | s1: []u16 = undefined, |
| 18 | s2: []i4 = undefined, | 8 | s2: []i4 = undefined, |
| 19 | owns_graphemes: bool, | 9 | owns_graphemes: bool = true, |
| 20 | 10 | ||
| 21 | const DisplayWidth = @This(); | 11 | const DisplayWidth = @This(); |
| 22 | 12 | ||
| 23 | pub fn init(allocator: mem.Allocator) mem.Allocator.Error!DisplayWidth { | 13 | pub 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 | ||
| 35 | pub fn initWithGraphemes(allocator: mem.Allocator, graphemes: Graphemes) mem.Allocator.Error!DisplayWidth { | 26 | pub 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. |
| 43 | fn setup(allocator: mem.Allocator) mem.Allocator.Error!DisplayWidth { | 35 | fn 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 | ||
| 67 | pub fn deinit(dw: *const DisplayWidth, allocator: mem.Allocator) void { | 55 | pub 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 | |||
| 437 | fn 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 | |||
| 450 | test "allocation test" { | ||
| 451 | try testing.checkAllAllocationFailures(testing.allocator, testAllocation, .{}); | ||
| 452 | } | ||
| 453 | |||
| 454 | const std = @import("std"); | ||
| 455 | const builtin = @import("builtin"); | ||
| 456 | const options = @import("options"); | ||
| 457 | const ArrayList = std.ArrayList; | ||
| 458 | const compress = std.compress; | ||
| 459 | const mem = std.mem; | ||
| 460 | const Allocator = mem.Allocator; | ||
| 461 | const simd = std.simd; | ||
| 462 | const testing = std.testing; | ||
| 463 | |||
| 464 | const ascii = @import("ascii"); | ||
| 465 | const CodePointIterator = @import("code_point").Iterator; | ||
| 466 | |||
| 467 | const Graphemes = @import("Graphemes"); | ||