mllib: Convert Common_utils.parse_size and parse_resize to use PCRE.

This also involved enhancing/fixing the test so that parse_size has
test coverage.
This commit is contained in:
Richard W.M. Jones
2017-09-21 10:57:56 +01:00
parent 508f3b29b8
commit 843ea53af0
7 changed files with 72 additions and 63 deletions

View File

@@ -85,6 +85,7 @@ OCAMLPACKAGES = \
-I $(top_builddir)/ocaml \
-I $(top_builddir)/common/mlstdutils \
-I $(top_builddir)/common/mlutils \
-I $(top_builddir)/common/mlpcre \
-I $(top_builddir)/mllib
if HAVE_OCAML_PKG_GETTEXT
OCAMLPACKAGES += -package gettext-stub
@@ -109,6 +110,7 @@ OCAMLLINKFLAGS = \
mlstdutils.$(MLARCHIVE) \
mlguestfs.$(MLARCHIVE) \
mlcutils.$(MLARCHIVE) \
mlpcre.$(MLARCHIVE) \
mllib.$(MLARCHIVE) \
$(LINK_CUSTOM_OCAMLC_ONLY)
@@ -116,6 +118,7 @@ virt_dib_DEPENDENCIES = \
$(OBJECTS) \
../common/mlstdutils/mlstdutils.$(MLARCHIVE) \
../common/mlutils/mlcutils.$(MLARCHIVE) \
../common/mlpcre/mlpcre.$(MLARCHIVE) \
../mllib/mllib.$(MLARCHIVE) \
$(top_srcdir)/ocaml-link.sh
virt_dib_LINK = \

View File

@@ -68,6 +68,7 @@ OCAMLPACKAGES = \
-I $(top_builddir)/ocaml \
-I $(top_builddir)/common/mlstdutils \
-I $(top_builddir)/common/mlutils \
-I $(top_builddir)/common/mlpcre \
-I $(top_builddir)/mllib
if HAVE_OCAML_PKG_GETTEXT
OCAMLPACKAGES += -package gettext-stub
@@ -91,6 +92,7 @@ endif
OCAMLLINKFLAGS = \
mlstdutils.$(MLARCHIVE) \
mlguestfs.$(MLARCHIVE) \
mlpcre.$(MLARCHIVE) \
mlcutils.$(MLARCHIVE) \
mllib.$(MLARCHIVE) \
$(LINK_CUSTOM_OCAMLC_ONLY)
@@ -99,6 +101,7 @@ virt_get_kernel_DEPENDENCIES = \
$(OBJECTS) \
../common/mlstdutils/mlstdutils.$(MLARCHIVE) \
../common/mlutils/mlcutils.$(MLARCHIVE) \
../common/mlpcre/mlpcre.$(MLARCHIVE) \
../mllib/mllib.$(MLARCHIVE) \
$(top_srcdir)/ocaml-link.sh
virt_get_kernel_LINK = \

View File

@@ -86,6 +86,7 @@ libmllib_a_CPPFLAGS = \
-I$(top_srcdir)/common/utils \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/common/options \
-I$(top_srcdir)/common/mlpcre \
-I$(top_srcdir)/common/mlxml \
-I$(top_srcdir)/common/mlstdutils \
-I$(top_srcdir)/common/mlutils
@@ -106,6 +107,7 @@ OCAMLPACKAGES = \
-I $(top_builddir)/lib/.libs \
-I $(top_builddir)/gnulib/lib/.libs \
-I $(top_builddir)/ocaml \
-I $(top_builddir)/common/mlpcre \
-I $(top_builddir)/common/mlxml \
-I $(top_builddir)/common/mlstdutils \
-I $(top_builddir)/common/mlutils \
@@ -189,12 +191,14 @@ endif
OCAMLLINKFLAGS = \
mlstdutils.$(MLARCHIVE) \
mlcutils.$(MLARCHIVE) \
mlpcre.$(MLARCHIVE) \
mlguestfs.$(MLARCHIVE) \
$(LINK_CUSTOM_OCAMLC_ONLY)
common_utils_tests_DEPENDENCIES = \
$(common_utils_tests_THEOBJECTS) \
../common/mlstdutils/mlstdutils.$(MLARCHIVE) \
../common/mlpcre/mlpcre.$(MLARCHIVE) \
$(MLLIB_CMA) \
$(top_srcdir)/ocaml-link.sh
common_utils_tests_LINK = \
@@ -206,6 +210,7 @@ common_utils_tests_LINK = \
getopt_tests_DEPENDENCIES = \
$(getopt_tests_THEOBJECTS) \
../common/mlstdutils/mlstdutils.$(MLARCHIVE) \
../common/mlpcre/mlpcre.$(MLARCHIVE) \
$(MLLIB_CMA) \
$(top_srcdir)/ocaml-link.sh
getopt_tests_LINK = \
@@ -217,6 +222,7 @@ getopt_tests_LINK = \
JSON_tests_DEPENDENCIES = \
$(JSON_tests_THEOBJECTS) \
../common/mlstdutils/mlstdutils.$(MLARCHIVE) \
../common/mlpcre/mlpcre.$(MLARCHIVE) \
$(MLLIB_CMA) \
$(top_srcdir)/ocaml-link.sh
JSON_tests_LINK = \

View File

@@ -155,73 +155,56 @@ let virt_tools_data_dir =
) in
fun () -> Lazy.force dir
(* Parse a size field, eg. "10G". *)
let parse_size =
let const_re = Str.regexp "^\\([.0-9]+\\)\\([bKMG]\\)$" in
fun field ->
let matches rex = Str.string_match rex field 0 in
let sub i = Str.matched_group i field in
let size_scaled f = function
| "b" -> Int64.of_float f
| "K" -> Int64.of_float (f *. 1024.)
| "M" -> Int64.of_float (f *. 1024. *. 1024.)
| "G" -> Int64.of_float (f *. 1024. *. 1024. *. 1024.)
| _ -> assert false
in
(* Used by parse_size and parse_resize below. *)
let const_re = PCRE.compile "^([.0-9]+)([bKMG])$"
let plus_const_re = PCRE.compile "^\\+([.0-9]+)([bKMG])$"
let minus_const_re = PCRE.compile "^-([.0-9]+)([bKMG])$"
let percent_re = PCRE.compile "^([.0-9]+)%$"
let plus_percent_re = PCRE.compile "^\\+([.0-9]+)%$"
let minus_percent_re = PCRE.compile "^-([.0-9]+)%$"
let size_scaled f = function
| "b" -> Int64.of_float f
| "K" -> Int64.of_float (f *. 1024.)
| "M" -> Int64.of_float (f *. 1024. *. 1024.)
| "G" -> Int64.of_float (f *. 1024. *. 1024. *. 1024.)
| _ -> assert false
if matches const_re then (
size_scaled (float_of_string (sub 1)) (sub 2)
)
else
error "%s: cannot parse size field" field
(* Parse a size field, eg. "10G". *)
let parse_size field =
if PCRE.matches const_re field then
size_scaled (float_of_string (PCRE.sub 1)) (PCRE.sub 2)
else
error "%s: cannot parse size field" field
(* Parse a size field, eg. "10G", "+20%" etc. Used particularly by
* virt-resize --resize and --resize-force options.
*)
let parse_resize =
let const_re = Str.regexp "^\\([.0-9]+\\)\\([bKMG]\\)$"
and plus_const_re = Str.regexp "^\\+\\([.0-9]+\\)\\([bKMG]\\)$"
and minus_const_re = Str.regexp "^-\\([.0-9]+\\)\\([bKMG]\\)$"
and percent_re = Str.regexp "^\\([.0-9]+\\)%$"
and plus_percent_re = Str.regexp "^\\+\\([.0-9]+\\)%$"
and minus_percent_re = Str.regexp "^-\\([.0-9]+\\)%$"
in
fun oldsize field ->
let matches rex = Str.string_match rex field 0 in
let sub i = Str.matched_group i field in
let size_scaled f = function
| "b" -> Int64.of_float f
| "K" -> Int64.of_float (f *. 1024.)
| "M" -> Int64.of_float (f *. 1024. *. 1024.)
| "G" -> Int64.of_float (f *. 1024. *. 1024. *. 1024.)
| _ -> assert false
in
if matches const_re then (
size_scaled (float_of_string (sub 1)) (sub 2)
)
else if matches plus_const_re then (
let incr = size_scaled (float_of_string (sub 1)) (sub 2) in
oldsize +^ incr
)
else if matches minus_const_re then (
let incr = size_scaled (float_of_string (sub 1)) (sub 2) in
oldsize -^ incr
)
else if matches percent_re then (
let percent = Int64.of_float (10. *. float_of_string (sub 1)) in
oldsize *^ percent /^ 1000L
)
else if matches plus_percent_re then (
let percent = Int64.of_float (10. *. float_of_string (sub 1)) in
oldsize +^ oldsize *^ percent /^ 1000L
)
else if matches minus_percent_re then (
let percent = Int64.of_float (10. *. float_of_string (sub 1)) in
oldsize -^ oldsize *^ percent /^ 1000L
)
else
error "%s: cannot parse resize field" field
let parse_resize oldsize field =
if PCRE.matches const_re field then (
size_scaled (float_of_string (PCRE.sub 1)) (PCRE.sub 2)
)
else if PCRE.matches plus_const_re field then (
let incr = size_scaled (float_of_string (PCRE.sub 1)) (PCRE.sub 2) in
oldsize +^ incr
)
else if PCRE.matches minus_const_re field then (
let incr = size_scaled (float_of_string (PCRE.sub 1)) (PCRE.sub 2) in
oldsize -^ incr
)
else if PCRE.matches percent_re field then (
let percent = Int64.of_float (10. *. float_of_string (PCRE.sub 1)) in
oldsize *^ percent /^ 1000L
)
else if PCRE.matches plus_percent_re field then (
let percent = Int64.of_float (10. *. float_of_string (PCRE.sub 1)) in
oldsize +^ oldsize *^ percent /^ 1000L
)
else if PCRE.matches minus_percent_re field then (
let percent = Int64.of_float (10. *. float_of_string (PCRE.sub 1)) in
oldsize -^ oldsize *^ percent /^ 1000L
)
else
error "%s: cannot parse resize field" field
let human_size i =
let sign, i = if i < 0L then "-", Int64.neg i else "", i in

View File

@@ -29,8 +29,16 @@ let assert_equal_int = assert_equal ~printer:(fun x -> string_of_int x)
let assert_equal_int64 = assert_equal ~printer:(fun x -> Int64.to_string x)
let assert_equal_intlist = assert_equal ~printer:(fun x -> "(" ^ (String.concat ";" (List.map string_of_int x)) ^ ")")
(* Test Common_utils.parse_size. *)
(* Test Common_utils.parse_size and Common_utils.parse_resize. *)
let test_parse_resize ctx =
assert_equal_int64 1_L (parse_size "1b");
assert_equal_int64 10_L (parse_size "10b");
assert_equal_int64 1024_L (parse_size "1K");
assert_equal_int64 102400_L (parse_size "100K");
(* Fractions are always rounded down. *)
assert_equal_int64 1153433_L (parse_size "1.1M");
assert_equal_int64 1202590842_L (parse_size "1.12G");
(* For absolute sizes, oldsize is ignored. *)
assert_equal_int64 100_L (parse_resize 100_L "100b");
assert_equal_int64 100_L (parse_resize 1000_L "100b");

View File

@@ -65,6 +65,7 @@ OCAMLPACKAGES = \
-I $(top_builddir)/common/mlstdutils \
-I $(top_builddir)/common/mlprogress \
-I $(top_builddir)/common/mlutils \
-I $(top_builddir)/common/mlpcre \
-I $(top_builddir)/mllib
if HAVE_OCAML_PKG_GETTEXT
OCAMLPACKAGES += -package gettext-stub
@@ -90,6 +91,7 @@ OCAMLLINKFLAGS = \
mlstdutils.$(MLARCHIVE) \
mlguestfs.$(MLARCHIVE) \
mlprogress.$(MLARCHIVE) \
mlpcre.$(MLARCHIVE) \
mlcutils.$(MLARCHIVE) \
mllib.$(MLARCHIVE) \
$(LINK_CUSTOM_OCAMLC_ONLY)
@@ -98,6 +100,7 @@ virt_resize_DEPENDENCIES = \
$(OBJECTS) \
../common/mlstdutils/mlstdutils.$(MLARCHIVE) \
../common/mlutils/mlcutils.$(MLARCHIVE) \
../common/mlpcre/mlpcre.$(MLARCHIVE) \
../mllib/mllib.$(MLARCHIVE) \
$(top_srcdir)/ocaml-link.sh
virt_resize_LINK = \

View File

@@ -73,6 +73,7 @@ OCAMLPACKAGES = \
-I $(top_builddir)/common/mlstdutils \
-I $(top_builddir)/common/mlprogress \
-I $(top_builddir)/common/mlutils \
-I $(top_builddir)/common/mlpcre \
-I $(top_builddir)/mllib
if HAVE_OCAML_PKG_GETTEXT
OCAMLPACKAGES += -package gettext-stub
@@ -98,6 +99,7 @@ OCAMLLINKFLAGS = \
mlstdutils.$(MLARCHIVE) \
mlguestfs.$(MLARCHIVE) \
mlprogress.$(MLARCHIVE) \
mlpcre.$(MLARCHIVE) \
mlcutils.$(MLARCHIVE) \
mllib.$(MLARCHIVE) \
$(LINK_CUSTOM_OCAMLC_ONLY)
@@ -106,6 +108,7 @@ virt_sparsify_DEPENDENCIES = \
$(OBJECTS) \
../common/mlstdutils/mlstdutils.$(MLARCHIVE) \
../common/mlutils/mlcutils.$(MLARCHIVE) \
../common/mlpcre/mlpcre.$(MLARCHIVE) \
../mllib/mllib.$(MLARCHIVE) \
$(top_srcdir)/ocaml-link.sh
virt_sparsify_LINK = \