pkg/oniguruma: search

This commit is contained in:
Mitchell Hashimoto
2023-11-25 09:20:06 -08:00
parent 4d3c7212d8
commit 364020973c
6 changed files with 62 additions and 5 deletions

View File

@ -24,7 +24,7 @@ pub fn build(b: *std.Build) !void {
test_step.dependOn(&tests_run.step);
// Uncomment this if we're debugging tests
// b.installArtifact(test_exe);
b.installArtifact(test_exe);
}
}

View File

@ -5,9 +5,9 @@ const Encoding = @import("types.zig").Encoding;
pub const MAX_ERROR_LEN = c.ONIG_MAX_ERROR_MESSAGE_LEN;
/// Convert an Oniguruma error to an error.
pub fn convertError(code: c_int) !void {
pub fn convertError(code: c_int) !c_int {
if (code >= 0) return code;
switch (code) {
c.ONIG_NORMAL => {},
else => return error.OnigurumaError,
}
}

View File

@ -5,7 +5,7 @@ const errors = @import("errors.zig");
/// Call once per process to initialize Oniguruma. This should be given
/// the encodings that the program will use.
pub fn init(encs: []const *Encoding) !void {
try errors.convertError(c.onig_initialize(
_ = try errors.convertError(c.onig_initialize(
@constCast(@ptrCast(@alignCast(encs.ptr))),
@intCast(encs.len),
));

View File

@ -1,6 +1,7 @@
pub usingnamespace @import("init.zig");
pub usingnamespace @import("errors.zig");
pub usingnamespace @import("regex.zig");
pub usingnamespace @import("region.zig");
pub usingnamespace @import("types.zig");
pub const c = @import("c.zig");

View File

@ -3,6 +3,7 @@ const c = @import("c.zig");
const types = @import("types.zig");
const errors = @import("errors.zig");
const testEnsureInit = @import("testing.zig").ensureInit;
const Region = @import("region.zig").Region;
const ErrorInfo = errors.ErrorInfo;
const Encoding = types.Encoding;
const Option = types.Option;
@ -19,7 +20,7 @@ pub const Regex = struct {
err: ?*ErrorInfo,
) !Regex {
var self: Regex = undefined;
try errors.convertError(c.onig_new(
_ = try errors.convertError(c.onig_new(
&self.value,
pattern.ptr,
pattern.ptr + pattern.len,
@ -34,10 +35,49 @@ pub const Regex = struct {
pub fn deinit(self: *Regex) void {
c.onig_free(self.value);
}
/// onig_search shorthand to search an entire string.
pub fn search(
self: *Regex,
str: []const u8,
region: *Region,
options: Option,
) !usize {
return try self.searchAdvanced(str, 0, str.len, region, options);
}
/// onig_search
pub fn searchAdvanced(
self: *Regex,
str: []const u8,
start: usize,
end: usize,
region: *Region,
options: Option,
) !usize {
const pos = try errors.convertError(c.onig_search(
self.value,
str.ptr,
str.ptr + str.len,
str.ptr + start,
str.ptr + end,
@ptrCast(region),
options.int(),
));
return @intCast(pos);
}
};
test {
const testing = std.testing;
try testEnsureInit();
var re = try Regex.init("foo", .{}, Encoding.utf8, Syntax.default, null);
defer re.deinit();
var region: Region = .{};
defer region.deinit();
const pos = try re.search("hello foo bar", &region, .{});
try testing.expectEqual(@as(usize, 6), pos);
}

16
pkg/oniguruma/region.zig Normal file
View File

@ -0,0 +1,16 @@
const std = @import("std");
const c = @import("c.zig");
pub const Region = extern struct {
allocated: c_int = 0,
num_regs: c_int = 0,
beg: ?[*]c_int = null,
end: ?[*]c_int = null,
history_root: ?*c.OnigCaptureTreeNode = null, // TODO: convert to Zig
pub fn deinit(self: *Region) void {
// We never free ourself because allocation of Region in the Zig
// bindings is handled by the Zig program.
c.onig_region_free(@ptrCast(self), 0);
}
};