authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-20 23:19:12 -08:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-01-20 23:19:12 -08:00
log338a9cb2ecb894ee599e422d454fad96e5cb8c96
tree2d8d06629f10bfa3273576f0c27fa92c202c5439
parent1a28511f024ee69b3b35f125a6d72ac6fa3cc7c8

add a helper find() method to UnicodeData


2 files changed, 52 insertions(+), 0 deletions(-)

scripts/UnicodeData.zig+26
...@@ -8,6 +8,7 @@ pub usingnamespace common.Main(struct {...@@ -8,6 +8,7 @@ pub usingnamespace common.Main(struct {
88
9 pub const dest_header =9 pub const dest_header =
10 \\const ucd = @import("./lib.zig");10 \\const ucd = @import("./lib.zig");
11 \\const std = @import("std");
11 \\12 \\
12 \\pub const Codepoint = struct {13 \\pub const Codepoint = struct {
13 \\ u21, // U+ code14 \\ u21, // U+ code
...@@ -47,6 +48,31 @@ pub usingnamespace common.Main(struct {...@@ -47,6 +48,31 @@ pub usingnamespace common.Main(struct {
47 \\ narrow,48 \\ narrow,
48 \\};49 \\};
49 \\50 \\
51 \\pub fn find(cp: u21) Codepoint {
52 \\ return data[binarySearchClosest(Codepoint, &data, cp, compare)];
53 \\}
54 \\
55 \\fn binarySearchClosest(comptime T: type, items: []const T, context: anytype, comptime compareFn: fn (@TypeOf(context), T) std.math.Order) usize {
56 \\ var low: usize = 0;
57 \\ var high: usize = items.len;
58 \\ while (low < high) {
59 \\ const mid = low + (high - low) / 2;
60 \\ switch (compareFn(context, items[mid])) {
61 \\ .eq => return mid,
62 \\ .gt => low = mid + 1,
63 \\ .lt => high = mid,
64 \\ }
65 \\ }
66 \\ std.debug.assert(low == high);
67 \\ return high;
68 \\}
69 \\
70 \\pub fn compare(needle: u21, row: Codepoint) std.math.Order {
71 \\ if (needle < row[0]) return .lt;
72 \\ if (needle > row[0]) return .gt;
73 \\ return .eq;
74 \\}
75 \\
50 \\pub const data = [_]Codepoint{76 \\pub const data = [_]Codepoint{
51 \\77 \\
52 ;78 ;
src/unicode_data.zig+26
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6// zig fmt: off6// zig fmt: off
77
8const ucd = @import("./lib.zig");8const ucd = @import("./lib.zig");
9const std = @import("std");
910
10pub const Codepoint = struct {11pub const Codepoint = struct {
11 u21, // U+ code12 u21, // U+ code
...@@ -45,6 +46,31 @@ pub const Decomposition = enum {...@@ -45,6 +46,31 @@ pub const Decomposition = enum {
45 narrow,46 narrow,
46};47};
4748
49pub fn find(cp: u21) Codepoint {
50 return data[binarySearchClosest(Codepoint, &data, cp, compare)];
51}
52
53fn binarySearchClosest(comptime T: type, items: []const T, context: anytype, comptime compareFn: fn (@TypeOf(context), T) std.math.Order) usize {
54 var low: usize = 0;
55 var high: usize = items.len;
56 while (low < high) {
57 const mid = low + (high - low) / 2;
58 switch (compareFn(context, items[mid])) {
59 .eq => return mid,
60 .gt => low = mid + 1,
61 .lt => high = mid,
62 }
63 }
64 std.debug.assert(low == high);
65 return high;
66}
67
68pub fn compare(needle: u21, row: Codepoint) std.math.Order {
69 if (needle < row[0]) return .lt;
70 if (needle > row[0]) return .gt;
71 return .eq;
72}
73
48pub const data = [_]Codepoint{74pub const data = [_]Codepoint{
49 .{ 0x0000, "<control>", .Cc, 0, .BN, .__none, &.{}, "", "", "", false, null, null, null, },75 .{ 0x0000, "<control>", .Cc, 0, .BN, .__none, &.{}, "", "", "", false, null, null, null, },
50 .{ 0x0001, "<control>", .Cc, 0, .BN, .__none, &.{}, "", "", "", false, null, null, null, },76 .{ 0x0001, "<control>", .Cc, 0, .BN, .__none, &.{}, "", "", "", false, null, null, null, },