summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Estabrook <jestabro@vyos.io>2022-06-17 20:30:52 -0500
committerJohn Estabrook <jestabro@vyos.io>2022-06-17 20:30:52 -0500
commitdbf73551a7f770f763d6286f5080c37cdb15f20c (patch)
tree485894fce8336d0468486d611fde6e80ebe6cada
parent43e9a47879749d2035c39a08ec422aceac49842e (diff)
downloadvyos-utils-dbf73551a7f770f763d6286f5080c37cdb15f20c.tar.gz
vyos-utils-dbf73551a7f770f763d6286f5080c37cdb15f20c.zip
numeric: T4467: add support for relative values: +/-N
Add option '--relative' to check that value is of the form '+/-N' for some numeric N (e.g. +10' or '-30'), interpreted as a relative increment or decrement, rather than a signed integer/float. This may be combined with any other option, which will be applied to the value stripped of the leading modifier. Testing this extension revealed that negative values are being interpreted as options, whether quoted or not; to address that, an Arg.Rest keyword '--' is introduced, which will need to be passed along with the option in interface definitions using the above. For example: <validator name="numeric" argument="--relative --"/>
-rw-r--r--src/numeric.ml23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/numeric.ml b/src/numeric.ml
index b296cec..ad3a066 100644
--- a/src/numeric.ml
+++ b/src/numeric.ml
@@ -3,13 +3,15 @@ type options = {
nonnegative: bool;
allow_float: bool;
ranges: string list;
+ relative: bool;
}
let default_opts = {
positive = false;
nonnegative = false;
allow_float = false;
- ranges = []
+ ranges = [];
+ relative = false
}
let opts = ref default_opts
@@ -21,6 +23,8 @@ let args = [
("--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");
+ ("--relative", Arg.Unit (fun () -> opts := {!opts with relative=true}), "Allow relative increment/decrement (+/-N)");
+ ("--", Arg.Rest (fun s -> number_arg := s), "Interpret next item as an argument");
]
let usage = Printf.sprintf "Usage: %s [OPTIONS] <number>" Sys.argv.(0)
@@ -39,6 +43,20 @@ let looks_like_number value =
try let _ = Pcre.exec ~pat:"^(\\-?)[0-9]+(\\.[0-9]+)?$" value in true
with Not_found -> false
+let is_relative value =
+ try let _ = Pcre.exec ~pat:"^[+-][0-9]+$" value in true
+ with Not_found -> false
+
+let number_string_from_relative value =
+ String.sub value 1 (String.length value - 1)
+
+let get_relative opts s =
+ if opts.relative then
+ if not (is_relative s) then
+ failwith "Value is not a relative increment/decrement"
+ else number_string_from_relative s
+ else s
+
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
@@ -75,7 +93,8 @@ let check_ranges ranges n =
let () = try
let opts = !opts in
- let n = number_of_string opts !number_arg in
+ let s = get_relative opts !number_arg in
+ let n = number_of_string opts s in
check_nonnegative opts n;
check_positive opts n;
if opts.ranges <> [] then