11const std = @import ("std" );
22const CsvLine = @import ("FieldReader/CsvLine.zig" );
3+ const ExitCode = @import ("exitCode.zig" ).ExitCode ;
4+ const mvzr = @import ("mvzr" );
35
46pub const OutputFormat = enum {
57 csv ,
@@ -23,7 +25,8 @@ const Selection = union(enum) {
2325const OptionError = error {
2426 NoSuchField ,
2527 NoHeader ,
26- MoreThanOneEqualInFilter ,
28+ NoEqualOrTildeInFilter ,
29+ RegexCompileError ,
2730};
2831
2932pub const Options = struct {
@@ -202,14 +205,21 @@ pub const Options = struct {
202205 }
203206};
204207
208+ const FilterType = enum { equal , regex };
209+ const FilterValue = struct {
210+ value : []const u8 ,
211+ type : FilterType ,
212+ regex : ? mvzr.Regex ,
213+ };
214+
205215pub const Filter = struct {
206216 selectionList : SelectionList ,
207- values : std .array_list .Managed ([] const u8 ),
217+ values : std .array_list .Managed (FilterValue ),
208218
209219 pub fn init (allocator : std.mem.Allocator ) ! Filter {
210220 return .{
211221 .selectionList = try SelectionList .init (allocator ),
212- .values = std .array_list .Managed ([] const u8 ).init (allocator ),
222+ .values = std .array_list .Managed (FilterValue ).init (allocator ),
213223 };
214224 }
215225
@@ -219,18 +229,31 @@ pub const Filter = struct {
219229 }
220230
221231 pub fn append (self : * Filter , filter : []const u8 ) ! void {
222- var it = std .mem .splitScalar (u8 , filter , '=' );
223- if (it .next ()) | field | {
224- try self .selectionList .append (field );
225- }
226- if (it .next ()) | value | {
227- try self .values .append (value );
232+ var eqlPos : usize = 0 ;
233+ var filterType : FilterType = undefined ;
234+
235+ if (std .mem .indexOfScalar (u8 , filter , '=' )) | pos | {
236+ eqlPos = pos ;
237+ filterType = .equal ;
238+ } else if (std .mem .indexOfScalar (u8 , filter , '~' )) | pos | {
239+ eqlPos = pos ;
240+ filterType = .regex ;
228241 } else {
229- try self . values . append ( "" ) ;
242+ return OptionError . NoEqualOrTildeInFilter ;
230243 }
231- if (it .next ()) | _ | {
232- return OptionError .MoreThanOneEqualInFilter ;
244+
245+ const field = filter [0.. eqlPos ];
246+ try self .selectionList .append (field );
247+
248+ const value = filter [eqlPos + 1 .. ];
249+ var regex : ? mvzr.Regex = null ;
250+ if (filterType == .regex ) {
251+ regex = mvzr .compile (value );
252+ if (regex == null ) {
253+ ExitCode .regexCompileError .printErrorAndExit (.{ value , field });
254+ }
233255 }
256+ try self .values .append (.{ .value = value , .type = filterType , .regex = regex });
234257 }
235258
236259 pub fn calculateIndices (self : * Filter , header : ? [][]const u8 ) ! void {
@@ -239,8 +262,14 @@ pub const Filter = struct {
239262
240263 pub fn matches (self : * const Filter , fields : [][]const u8 ) bool {
241264 for (self .selectionList .indices .? , 0.. ) | fieldIndex , i | {
242- if (! std .mem .eql (u8 , fields [fieldIndex ], self .values .items [i ])) {
243- return false ;
265+ const value = self .values .items [i ];
266+ switch (value .type ) {
267+ .equal = > if (! std .mem .eql (u8 , fields [fieldIndex ], value .value )) {
268+ return false ;
269+ },
270+ .regex = > if (! value .regex .? .isMatch (fields [fieldIndex ])) {
271+ return false ;
272+ },
244273 }
245274 }
246275 return true ;
@@ -304,9 +333,9 @@ const SelectionList = struct {
304333 return minusPos ;
305334 }
306335
307- fn addRange (list : * std .array_list .Managed (Selection ), field : []const u8 , miusPos : usize ) ! void {
308- if (toNumber (field [0.. miusPos ])) | from | {
309- if (toNumber (field [miusPos + 1 .. ])) | to | {
336+ fn addRange (list : * std .array_list .Managed (Selection ), field : []const u8 , minusPos : usize ) ! void {
337+ if (toNumber (field [0.. minusPos ])) | from | {
338+ if (toNumber (field [minusPos + 1 .. ])) | to | {
310339 for (from .. to + 1 ) | index | {
311340 try list .append (.{ .index = index - 1 });
312341 }
0 commit comments