1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
const std = @import("std");
const c = @import("c.zig").c;
const types = @import("types.zig");
const errors = @import("errors.zig");
const testEnsureInit = @import("testing.zig").ensureInit;
const MatchParam = @import("match_param.zig").MatchParam;
const Region = @import("region.zig").Region;
const Error = errors.Error;
const ErrorInfo = errors.ErrorInfo;
const Encoding = types.Encoding;
const Option = types.Option;
const Syntax = types.Syntax;
pub const Regex = struct {
value: c.OnigRegex,
pub fn init(
pattern: []const u8,
options: Option,
enc: *Encoding,
syntax: *Syntax,
err: ?*ErrorInfo,
) !Regex {
var self: Regex = undefined;
_ = try errors.convertError(c.onig_new(
&self.value,
pattern.ptr,
pattern.ptr + pattern.len,
options.int(),
@ptrCast(@alignCast(enc)),
@ptrCast(@alignCast(syntax)),
@ptrCast(err),
));
return self;
}
pub fn deinit(self: *Regex) void {
c.onig_free(self.value);
}
/// Search an entire string for matches. This always returns a region
/// which may heap allocate (C allocator).
pub fn search(
self: *Regex,
str: []const u8,
options: Option,
) !Region {
return self.searchWithParam(str, options, null);
}
/// Search an entire string for matches. This always returns a region
/// which may heap allocate (C allocator).
pub fn searchWithParam(
self: *Regex,
str: []const u8,
options: Option,
match_param: ?*MatchParam,
) !Region {
var region: Region = .{};
// As part of the searchAdvanced API call below, onig may allocate
// memory even if we fail to match. We need to deinit if there are
// any errors to free that memory.
errdefer region.deinit();
_ = try self.searchAdvancedWithParam(
str,
0,
str.len,
®ion,
options,
match_param,
);
return region;
}
/// onig_search directly
pub fn searchAdvanced(
self: *Regex,
str: []const u8,
start: usize,
end: usize,
region: *Region,
options: Option,
) !usize {
return self.searchAdvancedWithParam(
str,
start,
end,
region,
options,
null,
);
}
/// onig_search_with_param directly
pub fn searchAdvancedWithParam(
self: *Regex,
str: []const u8,
start: usize,
end: usize,
region: *Region,
options: Option,
match_param: ?*MatchParam,
) !usize {
const pos = try errors.convertError(if (match_param) |param|
c.onig_search_with_param(
self.value,
str.ptr,
str.ptr + str.len,
str.ptr + start,
str.ptr + end,
@ptrCast(region),
options.int(),
param.value,
)
else
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 reg = try re.search("hello foo bar", .{});
defer reg.deinit();
try testing.expectEqual(@as(usize, 1), reg.count());
try testing.expectError(Error.Mismatch, re.search("hello", .{}));
var match_param = try MatchParam.init();
defer match_param.deinit();
try match_param.setRetryLimitInSearch(1000);
var reg_param = try re.searchWithParam("hello foo bar", .{}, &match_param);
defer reg_param.deinit();
try testing.expectEqual(@as(usize, 1), reg_param.count());
}
|