[Libguestfs] [PATCH v3 10/22] mllib: Convert Common_utils.parse_size and parse_resize to use PCRE.

Richard W.M. Jones rjones at redhat.com
Fri Sep 22 07:36:11 UTC 2017


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
 
+(* 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
+
 (* 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
-
-    if matches const_re then (
-      size_scaled (float_of_string (sub 1)) (sub 2)
-    )
-    else
-      error "%s: cannot parse size field" field
+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 = \
-- 
2.13.2




More information about the Libguestfs mailing list