From 843ea53af09d0e2d74e7bd2820fc6c2af8fc2d2b Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 21 Sep 2017 10:57:56 +0100 Subject: [PATCH] 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. --- dib/Makefile.am | 3 + get-kernel/Makefile.am | 3 + mllib/Makefile.am | 6 ++ mllib/common_utils.ml | 107 +++++++++++++++--------------------- mllib/common_utils_tests.ml | 10 +++- resize/Makefile.am | 3 + sparsify/Makefile.am | 3 + 7 files changed, 72 insertions(+), 63 deletions(-) diff --git a/dib/Makefile.am b/dib/Makefile.am index d5fc4e48d..fda074b45 100644 --- a/dib/Makefile.am +++ b/dib/Makefile.am @@ -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 = \ diff --git a/get-kernel/Makefile.am b/get-kernel/Makefile.am index 8c194df36..f833f35f4 100644 --- a/get-kernel/Makefile.am +++ b/get-kernel/Makefile.am @@ -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 = \ diff --git a/mllib/Makefile.am b/mllib/Makefile.am index 2f6d2043a..3f2af3c61 100644 --- a/mllib/Makefile.am +++ b/mllib/Makefile.am @@ -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 = \ diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml index 597128967..3355365c6 100644 --- a/mllib/common_utils.ml +++ b/mllib/common_utils.ml @@ -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 diff --git a/mllib/common_utils_tests.ml b/mllib/common_utils_tests.ml index ee8a60463..f7a4eafd1 100644 --- a/mllib/common_utils_tests.ml +++ b/mllib/common_utils_tests.ml @@ -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"); diff --git a/resize/Makefile.am b/resize/Makefile.am index df73af4a4..035bfb9fe 100644 --- a/resize/Makefile.am +++ b/resize/Makefile.am @@ -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 = \ diff --git a/sparsify/Makefile.am b/sparsify/Makefile.am index 3b4ea3420..427d35670 100644 --- a/sparsify/Makefile.am +++ b/sparsify/Makefile.am @@ -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 = \