summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@baturin.org>2022-05-10 14:21:48 +0300
committerDaniil Baturin <daniil@baturin.org>2022-05-19 16:19:27 +0300
commitf0d5e978fa8de3f4c0a01989def0f83892104d00 (patch)
treeabeed62f737b817b28ae599a4118646c03f866a1
parentf19a5e813d7a311601dbbc3014522d606d1bba39 (diff)
downloadvyos-utils-f0d5e978fa8de3f4c0a01989def0f83892104d00.tar.gz
vyos-utils-f0d5e978fa8de3f4c0a01989def0f83892104d00.zip
T4421: add support for floating point number in the numeric validator
-rwxr-xr-xdebian/rules2
-rw-r--r--src/numeric.ml49
2 files changed, 30 insertions, 21 deletions
diff --git a/debian/rules b/debian/rules
index e3462af..4d3db35 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 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..ab59d6c 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,39 @@ 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 number_of_string opts s =
+ 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 +70,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;