diff --git a/scripts/UnicodeData.zig b/scripts/UnicodeData.zig index 9830aebe63856b67ffc85193dd616dfb92376939..cf61c5bb640cffc7b9c4dca0e96fd8aa7f984d80 100644 --- a/scripts/UnicodeData.zig +++ b/scripts/UnicodeData.zig @@ -8,6 +8,7 @@ pub usingnamespace common.Main(struct { pub const dest_header = \\const ucd = @import("./lib.zig"); + \\const std = @import("std"); \\ \\pub const Codepoint = struct { \\ u21, // U+ code @@ -47,6 +48,31 @@ pub usingnamespace common.Main(struct { \\ narrow, \\}; \\ + \\pub fn find(cp: u21) Codepoint { + \\ return data[binarySearchClosest(Codepoint, &data, cp, compare)]; + \\} + \\ + \\fn binarySearchClosest(comptime T: type, items: []const T, context: anytype, comptime compareFn: fn (@TypeOf(context), T) std.math.Order) usize { + \\ var low: usize = 0; + \\ var high: usize = items.len; + \\ while (low < high) { + \\ const mid = low + (high - low) / 2; + \\ switch (compareFn(context, items[mid])) { + \\ .eq => return mid, + \\ .gt => low = mid + 1, + \\ .lt => high = mid, + \\ } + \\ } + \\ std.debug.assert(low == high); + \\ return high; + \\} + \\ + \\pub fn compare(needle: u21, row: Codepoint) std.math.Order { + \\ if (needle < row[0]) return .lt; + \\ if (needle > row[0]) return .gt; + \\ return .eq; + \\} + \\ \\pub const data = [_]Codepoint{ \\ ; diff --git a/src/unicode_data.zig b/src/unicode_data.zig index 54e8baf7363a4d735732f6e46a894ecd07f9ecde..a36fa34a59fc3a45ab18a47cfa77d4f72680c4a0 100644 --- a/src/unicode_data.zig +++ b/src/unicode_data.zig @@ -6,6 +6,7 @@ // zig fmt: off const ucd = @import("./lib.zig"); +const std = @import("std"); pub const Codepoint = struct { u21, // U+ code @@ -45,6 +46,31 @@ pub const Decomposition = enum { narrow, }; +pub fn find(cp: u21) Codepoint { + return data[binarySearchClosest(Codepoint, &data, cp, compare)]; +} + +fn binarySearchClosest(comptime T: type, items: []const T, context: anytype, comptime compareFn: fn (@TypeOf(context), T) std.math.Order) usize { + var low: usize = 0; + var high: usize = items.len; + while (low < high) { + const mid = low + (high - low) / 2; + switch (compareFn(context, items[mid])) { + .eq => return mid, + .gt => low = mid + 1, + .lt => high = mid, + } + } + std.debug.assert(low == high); + return high; +} + +pub fn compare(needle: u21, row: Codepoint) std.math.Order { + if (needle < row[0]) return .lt; + if (needle > row[0]) return .gt; + return .eq; +} + pub const data = [_]Codepoint{ .{ 0x0000, "", .Cc, 0, .BN, .__none, &.{}, "", "", "", false, null, null, null, }, .{ 0x0001, "", .Cc, 0, .BN, .__none, &.{}, "", "", "", false, null, null, null, },