diff options
author | John Estabrook <jestabro@vyos.io> | 2022-05-13 15:27:03 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-13 15:27:03 -0500 |
commit | 43e9a47879749d2035c39a08ec422aceac49842e (patch) | |
tree | b73f26786d52f25aee8e2334f45a3538bd8337c3 | |
parent | 964ced5a0ffe146115194dc50bf755a241fa40a1 (diff) | |
parent | 4aa302a05fad95f3d13eb2ff20bbfee88c32e7ff (diff) | |
download | vyos-utils-43e9a47879749d2035c39a08ec422aceac49842e.tar.gz vyos-utils-43e9a47879749d2035c39a08ec422aceac49842e.zip |
Merge pull request #2 from dmbaturin/T4421
T4421: add support for floating point number in the numeric validator
-rwxr-xr-x | debian/rules | 2 | ||||
-rw-r--r-- | src/numeric.ml | 54 |
2 files changed, 35 insertions, 21 deletions
diff --git a/debian/rules b/debian/rules index e3462af..c6e8920 100755 --- a/debian/rules +++ b/debian/rules @@ -8,7 +8,7 @@ DIR := debian/tmp override_dh_auto_build: eval `opam env` mkdir -p _build - ocamlfind ocamlopt -o _build/numeric -package num -linkpkg src/numeric.ml + ocamlfind ocamlopt -o _build/numeric -package pcre -linkpkg src/numeric.ml ocamlfind ocamlopt -o _build/validate-value -package pcre,unix,containers -linkpkg src/validate_value.ml override_dh_auto_install: diff --git a/src/numeric.ml b/src/numeric.ml index 17fcac6..b296cec 100644 --- a/src/numeric.ml +++ b/src/numeric.ml @@ -1,23 +1,17 @@ type options = { positive: bool; nonnegative: bool; + allow_float: bool; ranges: string list; } let default_opts = { positive = false; nonnegative = false; + allow_float = false; ranges = [] } -let int_of_string = Big_int.big_int_of_string -let int_of_string_opt = Big_int.big_int_of_string_opt -let big = Big_int.big_int_of_int -let (>=) = Big_int.ge_big_int -let (<=) = Big_int.le_big_int -let (<) = Big_int.lt_big_int -let (>) = Big_int.gt_big_int - let opts = ref default_opts let number_arg = ref "" @@ -26,6 +20,7 @@ let args = [ ("--non-negative", Arg.Unit (fun () -> opts := {!opts with nonnegative=true}), "Check if the number is non-negative (>= 0)"); ("--positive", Arg.Unit (fun () -> opts := {!opts with positive=true}), "Check if the number is positive (> 0)"); ("--range", Arg.String (fun s -> let optsv = !opts in opts := {optsv with ranges=(s :: optsv.ranges)}), "Check if the number is within a range (inclusive)"); + ("--float", Arg.Unit (fun () -> opts := {!opts with allow_float=true}), "Allow floating-point numbers"); ] let usage = Printf.sprintf "Usage: %s [OPTIONS] <number>" Sys.argv.(0) @@ -33,25 +28,44 @@ let () = if Array.length Sys.argv = 1 then (Arg.usage args usage; exit 1) let () = Arg.parse args (fun s -> number_arg := s) usage let check_nonnegative opts n = - if opts.nonnegative && (n < (big 0)) then + if opts.nonnegative && (n < 0.0) then failwith "Number should be non-negative." let check_positive opts n = - if opts.positive && (n <= (big 0)) then + if opts.positive && (n <= 0.0) then failwith "Number should be positive" -let number_of_string s = - let n = int_of_string_opt s in +let looks_like_number value = + try let _ = Pcre.exec ~pat:"^(\\-?)[0-9]+(\\.[0-9]+)?$" value in true + with Not_found -> false + +let number_of_string opts s = + if not (looks_like_number s) then Printf.ksprintf failwith "'%s' is not a valid number" s else + let n = float_of_string_opt s in match n with - | Some n -> n + | Some n -> + (* If floats are explicitly allowed, just return the number. *) + if opts.allow_float then n + (* If floats are not explicitly allowed, check if the argument has a decimal separator in it. + If the argument string contains a dot but float_of_string didn't dislike it, + it's a valid number but not an integer. + *) + else if not (String.contains s '.') then n + (* If float_of_string returned None, the argument string is just garbage rather than a number. *) + else Printf.ksprintf failwith "'%s' is not a valid integer number" s | None -> - Printf.ksprintf failwith "'%s' is not a valid integer number" s + Printf.ksprintf failwith "'%s' is not a valid number" s -let range_of_string s = - let rs = String.split_on_char '-' s |> List.map String.trim |> List.map int_of_string_opt in +let range_of_string opts s = + let rs = String.split_on_char '-' s |> List.map String.trim |> List.map (number_of_string opts) in match rs with - | [Some l; Some r] -> (l, r) - | _ -> Printf.ksprintf failwith "'%s' is not a valid number range" s + | [l; r] -> (l, r) + | exception (Failure msg) -> + (* Some of the numbers in the range are bad. *) + Printf.ksprintf failwith "'%s' is not a valid number range: %s" s msg + | _ -> + (* The range itself if malformed, like 1-10-20. *) + Printf.ksprintf failwith "'%s' is not a valid number range" s let check_ranges ranges n = let in_range (l, r) n = (n >= l) && (n <= r) in @@ -61,11 +75,11 @@ let check_ranges ranges n = let () = try let opts = !opts in - let n = number_of_string !number_arg in + let n = number_of_string opts !number_arg in check_nonnegative opts n; check_positive opts n; if opts.ranges <> [] then - let ranges = List.map range_of_string opts.ranges in + let ranges = List.map (range_of_string opts) opts.ranges in check_ranges ranges n with (Failure err) -> print_endline err; |