From cf462028d5921efd53996cee0c340e8d7f402784 Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Fri, 21 May 2021 15:22:46 -0500 Subject: T3574: add support for --grp argument Add support for --grp argument, which joins the arguments following (up until the next --grp) with logical and; arguments preceding a group, and other groups following, are joined by logical or. --- src/validate_value.ml | 55 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/validate_value.ml b/src/validate_value.ml index 0b4148f..6d52618 100644 --- a/src/validate_value.ml +++ b/src/validate_value.ml @@ -1,7 +1,30 @@ -type check = Regex of string | Exec of string +type check = Regex of string | Exec of string | Grp | Faux -let validate_value buf value_constraint value = +let checks = ref [] + +let find_next_grp n l = + let rec aux i = function + | [] -> List.length l + | h::t -> + if i > n && h = Grp then i + else aux (i+1) t + in aux 0 l + +let get_next_range = + let n = ref (-1) in + let f () = + let i = !n and j = (n := find_next_grp !n !checks; !n) in + (i, j) in + f + +let rec validate_value buf value_constraint value = match value_constraint with + | Faux -> false + | Grp -> + let (k, j) = get_next_range () in + let in_grp i = if i > k && i < j then true else false in + let conj_checks = List.filteri (fun i _ -> in_grp i) !checks in + List.fold_left (&&) true (List.map (fun e -> validate_value buf e value) conj_checks) | Regex s -> (try let _ = Pcre.exec ~pat:s value in true with Not_found -> false) @@ -24,25 +47,37 @@ let validate_value buf value_constraint value = let value = ref "" -let checks = ref [] - let args = [ ("--regex", Arg.String (fun s -> checks := (Regex s) :: !checks), "Check the value against a regex"); ("--exec", Arg.String (fun s -> checks := (Exec s) :: !checks), "Check the value against an external command"); + ("--grp", Arg.Unit (fun () -> checks := (Grp) :: !checks), "Group following arguments, joining results with logical and"); ("--value", Arg.String (fun s -> value := s), "Value to check"); ] let usage = Printf.sprintf "Usage: %s [OPTIONS] " Sys.argv.(0) let () = Arg.parse args (fun _ -> ()) usage -let _ = - let buf = Buffer.create 4096 in +let buf = Buffer.create 4096 + +let mask l = + let (k, j) = get_next_range () in + let imask i e = + match e with + | Grp -> Grp + | _ -> if i >= k && i <= j then e else Faux in + List.mapi (fun i e -> imask i e) l + +let validate = + checks := List.rev(!checks); let value = !value in - let checks = !checks in - match checks with - | [] -> exit 0 + let disj_checks = mask !checks in + match disj_checks with + | [] -> false | _ -> - List.iter (fun c -> if (validate_value buf c value) then exit 0 else ()) checks; + List.fold_left (||) false (List.map (fun c -> validate_value buf c value) disj_checks) + +let _ = + if validate then exit 0 else (* If we got this far, value validation failed. Show the user output from the validators. *) -- cgit v1.2.3 From 9b593c24700a3e0e0b37fa3cf4161f305a9c7ccb Mon Sep 17 00:00:00 2001 From: John Estabrook Date: Sun, 13 Jun 2021 11:52:35 -0500 Subject: T3574: refactor for clarity --- src/validate_value.ml | 99 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/validate_value.ml b/src/validate_value.ml index 6d52618..32d34de 100644 --- a/src/validate_value.ml +++ b/src/validate_value.ml @@ -1,30 +1,16 @@ -type check = Regex of string | Exec of string | Grp | Faux +type argopt = RegexOpt of string | ExecOpt of string | GroupSeparator +type check = Regex of string | Exec of string | Group of check list +let options = ref [] let checks = ref [] +let value = ref "" -let find_next_grp n l = - let rec aux i = function - | [] -> List.length l - | h::t -> - if i > n && h = Grp then i - else aux (i+1) t - in aux 0 l - -let get_next_range = - let n = ref (-1) in - let f () = - let i = !n and j = (n := find_next_grp !n !checks; !n) in - (i, j) in - f +let buf = Buffer.create 4096 let rec validate_value buf value_constraint value = match value_constraint with - | Faux -> false - | Grp -> - let (k, j) = get_next_range () in - let in_grp i = if i > k && i < j then true else false in - let conj_checks = List.filteri (fun i _ -> in_grp i) !checks in - List.fold_left (&&) true (List.map (fun e -> validate_value buf e value) conj_checks) + | Group l -> + List.for_all (fun c -> validate_value buf c value) l | Regex s -> (try let _ = Pcre.exec ~pat:s value in true with Not_found -> false) @@ -45,36 +31,73 @@ let rec validate_value buf value_constraint value = let () = Buffer.add_string buf out; Buffer.add_string buf "\n" in false -let value = ref "" - let args = [ - ("--regex", Arg.String (fun s -> checks := (Regex s) :: !checks), "Check the value against a regex"); - ("--exec", Arg.String (fun s -> checks := (Exec s) :: !checks), "Check the value against an external command"); - ("--grp", Arg.Unit (fun () -> checks := (Grp) :: !checks), "Group following arguments, joining results with logical and"); + ("--regex", Arg.String (fun s -> options := (RegexOpt s) :: !options), "Check the value against a regex"); + ("--exec", Arg.String (fun s -> options := (ExecOpt s) :: !options), "Check the value against an external command"); + ("--grp", Arg.Unit (fun () -> options := (GroupSeparator) :: !options), "Group following arguments, combining results with logical and"); ("--value", Arg.String (fun s -> value := s), "Value to check"); ] let usage = Printf.sprintf "Usage: %s [OPTIONS] " Sys.argv.(0) let () = Arg.parse args (fun _ -> ()) usage -let buf = Buffer.create 4096 +let find_next_group n l = + let rec aux i = function + | [] -> List.length l + | h::t -> + if i > n && h = GroupSeparator then i + else aux (i+1) t + in aux 0 l + +let get_next_range = + let n = ref (-1) in + let f () = + let i = !n and j = (n := find_next_group !n !options; !n) in + (i, j) in + f + +let option_to_check opt = + match opt with + | RegexOpt s -> Regex s + | ExecOpt s -> Exec s + | GroupSeparator -> raise (Invalid_argument "GroupSeparator in isolation has no corresponding check") + +let read_initial_options j = + if j > 0 then + let initial_options = List.filteri (fun i _ -> i < j) !options in + ignore (List.map (fun c -> checks := (option_to_check c) :: !checks) initial_options); () + else () + +let read_group_options i j = + if i < j then + let group_options = List.filteri (fun k _ -> i < k && k < j) !options in + let l = List.map (fun c -> option_to_check c) group_options in + checks := (Group l) :: !checks; () + else () + +let read_options () = + options := List.rev(!options); + + let (_, j) = get_next_range () in + read_initial_options j; -let mask l = - let (k, j) = get_next_range () in - let imask i e = - match e with - | Grp -> Grp - | _ -> if i >= k && i <= j then e else Faux in - List.mapi (fun i e -> imask i e) l + let quit_loop = ref false in + while not !quit_loop do + let i, j = get_next_range () in + if i < j then + read_group_options i j + else + quit_loop := true + done let validate = - checks := List.rev(!checks); + read_options (); let value = !value in - let disj_checks = mask !checks in - match disj_checks with + let checks = !checks in + match checks with | [] -> false | _ -> - List.fold_left (||) false (List.map (fun c -> validate_value buf c value) disj_checks) + List.exists (fun c -> validate_value buf c value) checks let _ = if validate then exit 0 else -- cgit v1.2.3