summaryrefslogtreecommitdiff
path: root/bench/src
diff options
context:
space:
mode:
authorGravatar Jose Colon Rodriguez2024-03-31 11:26:14 -0400
committerGravatar Jose Colon Rodriguez2024-03-31 11:26:14 -0400
commitf1cfab7059e922d45ebbe19c58acef8fa80dc85e (patch)
treef8067e499095514185eca7e04077a6d64a1bd01b /bench/src
parentAdded Ghostty ref in README (diff)
downloadzg-f1cfab7059e922d45ebbe19c58acef8fa80dc85e.tar.gz
zg-f1cfab7059e922d45ebbe19c58acef8fa80dc85e.tar.xz
zg-f1cfab7059e922d45ebbe19c58acef8fa80dc85e.zip
Added benchmarks; Unicode version; Removed Ziglyph dep
Diffstat (limited to 'bench/src')
-rw-r--r--bench/src/tests.zig229
-rw-r--r--bench/src/zg_case.zig43
-rw-r--r--bench/src/zg_caseless.zig60
-rw-r--r--bench/src/zg_codepoint.zig27
-rw-r--r--bench/src/zg_grapheme.zig29
-rw-r--r--bench/src/zg_normalize.zig76
-rw-r--r--bench/src/zg_width.zig33
-rw-r--r--bench/src/ziglyph_case.zig41
-rw-r--r--bench/src/ziglyph_caseless.zig35
-rw-r--r--bench/src/ziglyph_codepoint.zig27
-rw-r--r--bench/src/ziglyph_grapheme.zig27
-rw-r--r--bench/src/ziglyph_normalizer.zig75
-rw-r--r--bench/src/ziglyph_width.zig30
13 files changed, 732 insertions, 0 deletions
diff --git a/bench/src/tests.zig b/bench/src/tests.zig
new file mode 100644
index 0000000..a8a2a98
--- /dev/null
+++ b/bench/src/tests.zig
@@ -0,0 +1,229 @@
1const std = @import("std");
2const testing = std.testing;
3const expect = testing.expect;
4const expectEqual = testing.expectEqual;
5const expectEqualStrings = testing.expectEqualStrings;
6
7const allocator = testing.allocator;
8
9const GenCatData = @import("GenCatData");
10
11test "General Category" {
12 const gcd = try GenCatData.init(allocator);
13 defer gcd.deinit();
14
15 try expect(gcd.gc('A') == .Lu); // Lu: uppercase letter
16 try expect(gcd.gc('3') == .Nd); // Nd: Decimal number
17 try expect(gcd.isControl(0));
18 try expect(gcd.isLetter('z'));
19 try expect(gcd.isMark('\u{301}'));
20 try expect(gcd.isNumber('3'));
21 try expect(gcd.isPunctuation('['));
22 try expect(gcd.isSeparator(' '));
23 try expect(gcd.isSymbol('©'));
24}
25
26const PropsData = @import("PropsData");
27
28test "Properties" {
29 const pd = try PropsData.init(allocator);
30 defer pd.deinit();
31
32 try expect(pd.isMath('+'));
33 try expect(pd.isAlphabetic('Z'));
34 try expect(pd.isWhitespace(' '));
35 try expect(pd.isHexDigit('f'));
36 try expect(!pd.isHexDigit('z'));
37
38 try expect(pd.isDiacritic('\u{301}'));
39 try expect(pd.isIdStart('Z')); // Identifier start character
40 try expect(!pd.isIdStart('1'));
41 try expect(pd.isIdContinue('1'));
42 try expect(pd.isXidStart('\u{b33}')); // Extended identifier start character
43 try expect(pd.isXidContinue('\u{e33}'));
44 try expect(!pd.isXidStart('1'));
45
46 // Note surprising Unicode numeric types!
47 try expect(pd.isNumeric('\u{277f}'));
48 try expect(!pd.isNumeric('3'));
49 try expect(pd.isDigit('\u{2070}'));
50 try expect(!pd.isDigit('3'));
51 try expect(pd.isDecimal('3'));
52}
53
54const CaseData = @import("CaseData");
55
56test "Case" {
57 const cd = try CaseData.init(allocator);
58 defer cd.deinit();
59
60 try expect(cd.isUpper('A'));
61 try expect('A' == cd.toUpper('a'));
62 try expect(cd.isLower('a'));
63 try expect('a' == cd.toLower('A'));
64
65 try expect(cd.isCased('É'));
66 try expect(!cd.isCased('3'));
67
68 try expect(cd.isUpperStr("HELLO 123!"));
69 const ucased = try cd.toUpperStr(allocator, "hello 123");
70 defer allocator.free(ucased);
71 try expectEqualStrings("HELLO 123", ucased);
72
73 try expect(cd.isLowerStr("hello 123!"));
74 const lcased = try cd.toLowerStr(allocator, "HELLO 123");
75 defer allocator.free(lcased);
76 try expectEqualStrings("hello 123", lcased);
77}
78
79const Normalize = @import("Normalize");
80
81test "Normalization" {
82 var norm_data = try Normalize.NormData.init(allocator);
83 defer norm_data.deinit();
84 const n = Normalize{ .norm_data = &norm_data };
85
86 // NFD: Canonical decomposition
87 const nfd_result = try n.nfd(allocator, "Héllo World! \u{3d3}");
88 defer nfd_result.deinit();
89 try expectEqualStrings("He\u{301}llo World! \u{3d2}\u{301}", nfd_result.slice);
90
91 // NFKD: Compatibility decomposition
92 const nfkd_result = try n.nfkd(allocator, "Héllo World! \u{3d3}");
93 defer nfkd_result.deinit();
94 try expectEqualStrings("He\u{301}llo World! \u{3a5}\u{301}", nfkd_result.slice);
95
96 // NFC: Canonical composition
97 const nfc_result = try n.nfc(allocator, "Complex char: \u{3D2}\u{301}");
98 defer nfc_result.deinit();
99 try expectEqualStrings("Complex char: \u{3D3}", nfc_result.slice);
100
101 // NFKC: Compatibility composition
102 const nfkc_result = try n.nfkc(allocator, "Complex char: \u{03A5}\u{0301}");
103 defer nfkc_result.deinit();
104 try expectEqualStrings("Complex char: \u{038E}", nfkc_result.slice);
105
106 // Test for equality of two strings after normalizing to NFC.
107 try expect(try n.eql(allocator, "foé", "foe\u{0301}"));
108 try expect(try n.eql(allocator, "foϓ", "fo\u{03D2}\u{0301}"));
109}
110
111const CaseFold = @import("CaseFold");
112
113test "Caseless matching" {
114 var norm_data = try Normalize.NormData.init(allocator);
115 defer norm_data.deinit();
116 const n = Normalize{ .norm_data = &norm_data };
117
118 const cfd = try CaseFold.FoldData.init(allocator);
119 defer cfd.deinit();
120 const cf = CaseFold{ .fold_data = &cfd };
121
122 // compatCaselessMatch provides the deepest level of caseless
123 // matching because it decomposes and composes fully to NFKC.
124 const a = "Héllo World! \u{3d3}";
125 const b = "He\u{301}llo World! \u{3a5}\u{301}";
126 try expect(try cf.compatCaselessMatch(allocator, &n, a, b));
127
128 const c = "He\u{301}llo World! \u{3d2}\u{301}";
129 try expect(try cf.compatCaselessMatch(allocator, &n, a, c));
130
131 // canonCaselessMatch isn't as comprehensive as compatCaselessMatch
132 // because it only decomposes and composes to NFC. But it's faster.
133 try expect(!try cf.canonCaselessMatch(allocator, &n, a, b));
134 try expect(try cf.canonCaselessMatch(allocator, &n, a, c));
135}
136
137const DisplayWidth = @import("DisplayWidth");
138
139test "Display width" {
140 const dwd = try DisplayWidth.DisplayWidthData.init(allocator);
141 defer dwd.deinit();
142 const dw = DisplayWidth{ .data = &dwd };
143
144 // String display width
145 try expectEqual(@as(usize, 5), dw.strWidth("Hello\r\n"));
146 try expectEqual(@as(usize, 8), dw.strWidth("Hello 😊"));
147 try expectEqual(@as(usize, 8), dw.strWidth("Héllo 😊"));
148 try expectEqual(@as(usize, 9), dw.strWidth("Ẓ̌á̲l͔̝̞̄̑͌g̖̘̘̔̔͢͞͝o̪̔T̢̙̫̈̍͞e̬͈͕͌̏͑x̺̍ṭ̓̓ͅ"));
149 try expectEqual(@as(usize, 17), dw.strWidth("슬라바 우크라이나"));
150
151 // Centering text
152 const centered = try dw.center(allocator, "w😊w", 10, "-");
153 defer allocator.free(centered);
154 try expectEqualStrings("---w😊w---", centered);
155
156 // Pad left
157 const right_aligned = try dw.padLeft(allocator, "abc", 9, "*");
158 defer allocator.free(right_aligned);
159 try expectEqualStrings("******abc", right_aligned);
160
161 // Pad right
162 const left_aligned = try dw.padRight(allocator, "abc", 9, "*");
163 defer allocator.free(left_aligned);
164 try expectEqualStrings("abc******", left_aligned);
165
166 // Wrap text
167 const input = "The quick brown fox\r\njumped over the lazy dog!";
168 const wrapped = try dw.wrap(allocator, input, 10, 3);
169 defer allocator.free(wrapped);
170 const want =
171 \\The quick
172 \\brown fox
173 \\jumped
174 \\over the
175 \\lazy dog!
176 ;
177 try expectEqualStrings(want, wrapped);
178}
179
180const code_point = @import("code_point");
181
182test "Code point iterator" {
183 const str = "Hi 😊";
184 var iter = code_point.Iterator{ .bytes = str };
185 var i: usize = 0;
186
187 while (iter.next()) |cp| : (i += 1) {
188 if (i == 0) try expect(cp.code == 'H');
189 if (i == 1) try expect(cp.code == 'i');
190 if (i == 2) try expect(cp.code == ' ');
191
192 if (i == 3) {
193 try expect(cp.code == '😊');
194 try expect(cp.offset == 3);
195 try expect(cp.len == 4);
196 }
197 }
198}
199
200const grapheme = @import("grapheme");
201
202test "Grapheme cluster iterator" {
203 const gd = try grapheme.GraphemeData.init(allocator);
204 defer gd.deinit();
205 const str = "He\u{301}"; // Hé
206 var iter = grapheme.Iterator.init(str, &gd);
207 var i: usize = 0;
208
209 while (iter.next()) |gc| : (i += 1) {
210 if (i == 0) try expect(gc.len == 1);
211
212 if (i == 1) {
213 try expect(gc.len == 3);
214 try expect(gc.offset == 1);
215 try expectEqualStrings("e\u{301}", gc.bytes(str));
216 }
217 }
218}
219
220const ScriptsData = @import("ScriptsData");
221
222test "Scripts" {
223 const sd = try ScriptsData.init(allocator);
224 defer sd.deinit();
225
226 try expect(sd.script('A') == .Latin);
227 try expect(sd.script('Ω') == .Greek);
228 try expect(sd.script('צ') == .Hebrew);
229}
diff --git a/bench/src/zg_case.zig b/bench/src/zg_case.zig
new file mode 100644
index 0000000..e602c00
--- /dev/null
+++ b/bench/src/zg_case.zig
@@ -0,0 +1,43 @@
1const std = @import("std");
2
3const CaseData = @import("CaseData");
4
5pub fn main() !void {
6 var args_iter = std.process.args();
7 _ = args_iter.skip();
8 const in_path = args_iter.next() orelse return error.MissingArg;
9
10 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11 defer arena.deinit();
12 const allocator = arena.allocator();
13
14 const input = try std.fs.cwd().readFileAlloc(
15 allocator,
16 in_path,
17 std.math.maxInt(u32),
18 );
19 defer allocator.free(input);
20
21 const case_data = try CaseData.init(allocator);
22
23 var iter = std.mem.splitScalar(u8, input, '\n');
24 var result: usize = 0;
25 var timer = try std.time.Timer.start();
26
27 while (iter.next()) |line| {
28 const upper = try case_data.toUpperStr(allocator, line);
29 const lower = try case_data.toLowerStr(allocator, line);
30 result += upper.len + lower.len;
31 }
32 std.debug.print("zg toUpperStr/toLowerStr: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
33
34 result = 0;
35 iter.reset();
36 timer.reset();
37
38 while (iter.next()) |line| {
39 if (case_data.isUpperStr(line)) result += 1;
40 if (case_data.isLowerStr(line)) result += 2;
41 }
42 std.debug.print("zg isUpperStr/isLowerStr: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
43}
diff --git a/bench/src/zg_caseless.zig b/bench/src/zg_caseless.zig
new file mode 100644
index 0000000..410a62b
--- /dev/null
+++ b/bench/src/zg_caseless.zig
@@ -0,0 +1,60 @@
1const std = @import("std");
2
3const CaseFold = @import("CaseFold");
4const Normalize = @import("Normalize");
5
6pub fn main() !void {
7 var args_iter = std.process.args();
8 _ = args_iter.skip();
9 const in_path = args_iter.next() orelse return error.MissingArg;
10
11 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
12 defer arena.deinit();
13 const allocator = arena.allocator();
14
15 const input = try std.fs.cwd().readFileAlloc(
16 allocator,
17 in_path,
18 std.math.maxInt(u32),
19 );
20 defer allocator.free(input);
21
22 const fold_data = try CaseFold.FoldData.init(allocator);
23 var case_fold = CaseFold{ .fold_data = &fold_data };
24 const norm_data = try Normalize.NormData.init(allocator);
25 var normalize = Normalize{ .norm_data = &norm_data };
26
27 var iter = std.mem.splitScalar(u8, input, '\n');
28 var result: usize = 0;
29 var buf: [256]u8 = [_]u8{'z'} ** 256;
30 var prev_line: []const u8 = buf[0..1];
31 var timer = try std.time.Timer.start();
32
33 while (iter.next()) |line| {
34 if (try case_fold.compatCaselessMatch(
35 allocator,
36 &normalize,
37 prev_line,
38 line,
39 )) result += 1;
40 @memcpy(buf[0..line.len], line);
41 prev_line = buf[0..line.len];
42 }
43 std.debug.print("zg CaseFold.compatCaselessMatch: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
44
45 result = 0;
46 iter.reset();
47 timer.reset();
48
49 while (iter.next()) |line| {
50 if (try case_fold.canonCaselessMatch(
51 allocator,
52 &normalize,
53 prev_line,
54 line,
55 )) result += 1;
56 @memcpy(buf[0..line.len], line);
57 prev_line = buf[0..line.len];
58 }
59 std.debug.print("zg CaseFold.canonCaselessMatch: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
60}
diff --git a/bench/src/zg_codepoint.zig b/bench/src/zg_codepoint.zig
new file mode 100644
index 0000000..0564fa1
--- /dev/null
+++ b/bench/src/zg_codepoint.zig
@@ -0,0 +1,27 @@
1const std = @import("std");
2
3const CodePointIterator = @import("code_point").Iterator;
4
5pub fn main() !void {
6 var args_iter = std.process.args();
7 _ = args_iter.skip();
8 const in_path = args_iter.next() orelse return error.MissingArg;
9
10 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11 defer arena.deinit();
12 const allocator = arena.allocator();
13
14 const input = try std.fs.cwd().readFileAlloc(
15 allocator,
16 in_path,
17 std.math.maxInt(u32),
18 );
19 defer allocator.free(input);
20
21 var iter = CodePointIterator{ .bytes = input };
22 var result: usize = 0;
23 var timer = try std.time.Timer.start();
24
25 while (iter.next()) |_| result += 1;
26 std.debug.print("zg CodePointIterator: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
27}
diff --git a/bench/src/zg_grapheme.zig b/bench/src/zg_grapheme.zig
new file mode 100644
index 0000000..106b970
--- /dev/null
+++ b/bench/src/zg_grapheme.zig
@@ -0,0 +1,29 @@
1const std = @import("std");
2
3const GraphemeData = @import("grapheme").GraphemeData;
4const GraphemeIterator = @import("grapheme").Iterator;
5
6pub fn main() !void {
7 var args_iter = std.process.args();
8 _ = args_iter.skip();
9 const in_path = args_iter.next() orelse return error.MissingArg;
10
11 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
12 defer arena.deinit();
13 const allocator = arena.allocator();
14
15 const input = try std.fs.cwd().readFileAlloc(
16 allocator,
17 in_path,
18 std.math.maxInt(u32),
19 );
20 defer allocator.free(input);
21
22 const grapheme_data = try GraphemeData.init(allocator);
23 var iter = GraphemeIterator.init(input, &grapheme_data);
24 var result: usize = 0;
25 var timer = try std.time.Timer.start();
26
27 while (iter.next()) |_| result += 1;
28 std.debug.print("zg GraphemeIterator: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
29}
diff --git a/bench/src/zg_normalize.zig b/bench/src/zg_normalize.zig
new file mode 100644
index 0000000..956106f
--- /dev/null
+++ b/bench/src/zg_normalize.zig
@@ -0,0 +1,76 @@
1const std = @import("std");
2
3const Normalize = @import("Normalize");
4
5pub fn main() !void {
6 var args_iter = std.process.args();
7 _ = args_iter.skip();
8 const in_path = args_iter.next() orelse return error.MissingArg;
9
10 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11 defer arena.deinit();
12 const allocator = arena.allocator();
13
14 const input = try std.fs.cwd().readFileAlloc(
15 allocator,
16 in_path,
17 std.math.maxInt(u32),
18 );
19 defer allocator.free(input);
20
21 const norm_data = try Normalize.NormData.init(allocator);
22 const normalize = Normalize{ .norm_data = &norm_data };
23
24 var iter = std.mem.splitScalar(u8, input, '\n');
25 var result: usize = 0;
26 var timer = try std.time.Timer.start();
27
28 while (iter.next()) |line| {
29 const nfkc = try normalize.nfkc(allocator, line);
30 result += nfkc.slice.len;
31 }
32 std.debug.print("zg Normalize.nfkc: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
33
34 result = 0;
35 iter.reset();
36 timer.reset();
37
38 while (iter.next()) |line| {
39 const nfc = try normalize.nfc(allocator, line);
40 result += nfc.slice.len;
41 }
42 std.debug.print("zg Normalize.nfc: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
43
44 result = 0;
45 iter.reset();
46 timer.reset();
47
48 while (iter.next()) |line| {
49 const nfkd = try normalize.nfkd(allocator, line);
50 result += nfkd.slice.len;
51 }
52 std.debug.print("zg Normalize.nfkd: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
53
54 result = 0;
55 iter.reset();
56 timer.reset();
57
58 while (iter.next()) |line| {
59 const nfd = try normalize.nfd(allocator, line);
60 result += nfd.slice.len;
61 }
62 std.debug.print("zg Normalize.nfd: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
63
64 result = 0;
65 iter.reset();
66 var buf: [256]u8 = [_]u8{'z'} ** 256;
67 var prev_line: []const u8 = buf[0..1];
68 timer.reset();
69
70 while (iter.next()) |line| {
71 if (try normalize.eql(allocator, prev_line, line)) result += 1;
72 @memcpy(buf[0..line.len], line);
73 prev_line = buf[0..line.len];
74 }
75 std.debug.print("Zg Normalize.eql: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
76}
diff --git a/bench/src/zg_width.zig b/bench/src/zg_width.zig
new file mode 100644
index 0000000..c0ce57c
--- /dev/null
+++ b/bench/src/zg_width.zig
@@ -0,0 +1,33 @@
1const std = @import("std");
2
3const DisplayWidth = @import("DisplayWidth");
4
5pub fn main() !void {
6 var args_iter = std.process.args();
7 _ = args_iter.skip();
8 const in_path = args_iter.next() orelse return error.MissingArg;
9
10 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11 defer arena.deinit();
12 const allocator = arena.allocator();
13
14 const input = try std.fs.cwd().readFileAlloc(
15 allocator,
16 in_path,
17 std.math.maxInt(u32),
18 );
19 defer allocator.free(input);
20
21 const width_data = try DisplayWidth.DisplayWidthData.init(allocator);
22 const display_width = DisplayWidth{ .data = &width_data };
23
24 var iter = std.mem.splitScalar(u8, input, '\n');
25 var result: usize = 0;
26 var timer = try std.time.Timer.start();
27
28 while (iter.next()) |line| {
29 const width = display_width.strWidth(line);
30 result += width;
31 }
32 std.debug.print("zg DisplayWidth.strWidth: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
33}
diff --git a/bench/src/ziglyph_case.zig b/bench/src/ziglyph_case.zig
new file mode 100644
index 0000000..c6ef6ec
--- /dev/null
+++ b/bench/src/ziglyph_case.zig
@@ -0,0 +1,41 @@
1const std = @import("std");
2
3const ziglyph = @import("ziglyph");
4
5pub fn main() !void {
6 var args_iter = std.process.args();
7 _ = args_iter.skip();
8 const in_path = args_iter.next() orelse return error.MissingArg;
9
10 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11 defer arena.deinit();
12 const allocator = arena.allocator();
13
14 const input = try std.fs.cwd().readFileAlloc(
15 allocator,
16 in_path,
17 std.math.maxInt(u32),
18 );
19 defer allocator.free(input);
20
21 var iter = std.mem.splitScalar(u8, input, '\n');
22 var result: usize = 0;
23 var timer = try std.time.Timer.start();
24
25 while (iter.next()) |line| {
26 const upper = try ziglyph.toUpperStr(allocator, line);
27 const lower = try ziglyph.toLowerStr(allocator, line);
28 result += upper.len + lower.len;
29 }
30 std.debug.print("Ziglyph toUpperStr/toLowerStr: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
31
32 result = 0;
33 iter.reset();
34 timer.reset();
35
36 while (iter.next()) |line| {
37 if (ziglyph.isUpperStr(line)) result += 1;
38 if (ziglyph.isLowerStr(line)) result += 2;
39 }
40 std.debug.print("Ziglyph isUpperStr/isLowerStr: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
41}
diff --git a/bench/src/ziglyph_caseless.zig b/bench/src/ziglyph_caseless.zig
new file mode 100644
index 0000000..f80668e
--- /dev/null
+++ b/bench/src/ziglyph_caseless.zig
@@ -0,0 +1,35 @@
1const std = @import("std");
2
3const Normalizer = @import("ziglyph").Normalizer;
4
5pub fn main() !void {
6 var args_iter = std.process.args();
7 _ = args_iter.skip();
8 const in_path = args_iter.next() orelse return error.MissingArg;
9
10 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11 defer arena.deinit();
12 const allocator = arena.allocator();
13
14 const input = try std.fs.cwd().readFileAlloc(
15 allocator,
16 in_path,
17 std.math.maxInt(u32),
18 );
19 defer allocator.free(input);
20
21 var normalizer = try Normalizer.init(allocator);
22
23 var iter = std.mem.splitScalar(u8, input, '\n');
24 var result: usize = 0;
25 var buf: [256]u8 = [_]u8{'z'} ** 256;
26 var prev_line: []const u8 = buf[0..1];
27 var timer = try std.time.Timer.start();
28
29 while (iter.next()) |line| {
30 if (try normalizer.eqlCaseless(allocator, prev_line, line)) result += 1;
31 @memcpy(buf[0..line.len], line);
32 prev_line = buf[0..line.len];
33 }
34 std.debug.print("Ziglyph Normalizer.eqlCaseless: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
35}
diff --git a/bench/src/ziglyph_codepoint.zig b/bench/src/ziglyph_codepoint.zig
new file mode 100644
index 0000000..4c8fc18
--- /dev/null
+++ b/bench/src/ziglyph_codepoint.zig
@@ -0,0 +1,27 @@
1const std = @import("std");
2
3const CodePointIterator = @import("ziglyph").CodePointIterator;
4
5pub fn main() !void {
6 var args_iter = std.process.args();
7 _ = args_iter.skip();
8 const in_path = args_iter.next() orelse return error.MissingArg;
9
10 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11 defer arena.deinit();
12 const allocator = arena.allocator();
13
14 const input = try std.fs.cwd().readFileAlloc(
15 allocator,
16 in_path,
17 std.math.maxInt(u32),
18 );
19 defer allocator.free(input);
20
21 var iter = CodePointIterator{ .bytes = input };
22 var result: usize = 0;
23 var timer = try std.time.Timer.start();
24
25 while (iter.next()) |_| result += 1;
26 std.debug.print("Ziglyph CodePointIterator: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
27}
diff --git a/bench/src/ziglyph_grapheme.zig b/bench/src/ziglyph_grapheme.zig
new file mode 100644
index 0000000..b47eea3
--- /dev/null
+++ b/bench/src/ziglyph_grapheme.zig
@@ -0,0 +1,27 @@
1const std = @import("std");
2
3const GraphemeIterator = @import("ziglyph").GraphemeIterator;
4
5pub fn main() !void {
6 var args_iter = std.process.args();
7 _ = args_iter.skip();
8 const in_path = args_iter.next() orelse return error.MissingArg;
9
10 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11 defer arena.deinit();
12 const allocator = arena.allocator();
13
14 const input = try std.fs.cwd().readFileAlloc(
15 allocator,
16 in_path,
17 std.math.maxInt(u32),
18 );
19 defer allocator.free(input);
20
21 var iter = GraphemeIterator.init(input);
22 var result: usize = 0;
23 var timer = try std.time.Timer.start();
24
25 while (iter.next()) |_| result += 1;
26 std.debug.print("Ziglyph GraphemeIterator: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
27}
diff --git a/bench/src/ziglyph_normalizer.zig b/bench/src/ziglyph_normalizer.zig
new file mode 100644
index 0000000..fea162c
--- /dev/null
+++ b/bench/src/ziglyph_normalizer.zig
@@ -0,0 +1,75 @@
1const std = @import("std");
2
3const Normalizer = @import("ziglyph").Normalizer;
4
5pub fn main() !void {
6 var args_iter = std.process.args();
7 _ = args_iter.skip();
8 const in_path = args_iter.next() orelse return error.MissingArg;
9
10 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11 defer arena.deinit();
12 const allocator = arena.allocator();
13
14 const input = try std.fs.cwd().readFileAlloc(
15 allocator,
16 in_path,
17 std.math.maxInt(u32),
18 );
19 defer allocator.free(input);
20
21 var normalizer = try Normalizer.init(allocator);
22
23 var iter = std.mem.splitScalar(u8, input, '\n');
24 var result: usize = 0;
25 var timer = try std.time.Timer.start();
26
27 while (iter.next()) |line| {
28 const nfkc = try normalizer.nfkc(allocator, line);
29 result += nfkc.slice.len;
30 }
31 std.debug.print("Ziglyph Normalizer.nfkc: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
32
33 result = 0;
34 iter.reset();
35 timer.reset();
36
37 while (iter.next()) |line| {
38 const nfc = try normalizer.nfc(allocator, line);
39 result += nfc.slice.len;
40 }
41 std.debug.print("Ziglyph Normalizer.nfc: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
42
43 result = 0;
44 iter.reset();
45 timer.reset();
46
47 while (iter.next()) |line| {
48 const nfkd = try normalizer.nfkd(allocator, line);
49 result += nfkd.slice.len;
50 }
51 std.debug.print("Ziglyph Normalizer.nfkd: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
52
53 result = 0;
54 iter.reset();
55 timer.reset();
56
57 while (iter.next()) |line| {
58 const nfd = try normalizer.nfd(allocator, line);
59 result += nfd.slice.len;
60 }
61 std.debug.print("Ziglyph Normalizer.nfd: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
62
63 result = 0;
64 iter.reset();
65 var buf: [256]u8 = [_]u8{'z'} ** 256;
66 var prev_line: []const u8 = buf[0..1];
67 timer.reset();
68
69 while (iter.next()) |line| {
70 if (try normalizer.eql(allocator, prev_line, line)) result += 1;
71 @memcpy(buf[0..line.len], line);
72 prev_line = buf[0..line.len];
73 }
74 std.debug.print("Ziglyph Normalizer.eql: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
75}
diff --git a/bench/src/ziglyph_width.zig b/bench/src/ziglyph_width.zig
new file mode 100644
index 0000000..01dd9ee
--- /dev/null
+++ b/bench/src/ziglyph_width.zig
@@ -0,0 +1,30 @@
1const std = @import("std");
2
3const display_width = @import("ziglyph").display_width;
4
5pub fn main() !void {
6 var args_iter = std.process.args();
7 _ = args_iter.skip();
8 const in_path = args_iter.next() orelse return error.MissingArg;
9
10 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
11 defer arena.deinit();
12 const allocator = arena.allocator();
13
14 const input = try std.fs.cwd().readFileAlloc(
15 allocator,
16 in_path,
17 std.math.maxInt(u32),
18 );
19 defer allocator.free(input);
20
21 var iter = std.mem.splitScalar(u8, input, '\n');
22 var result: usize = 0;
23 var timer = try std.time.Timer.start();
24
25 while (iter.next()) |line| {
26 const width = try display_width.strWidth(line, .half);
27 result += width;
28 }
29 std.debug.print("Ziglyph display_width.strWidth: result: {}, took: {}\n", .{ result, timer.lap() / std.time.ns_per_ms });
30}