[Libguestfs] [PATCH v3 02/22] common/mlpcre: Add PCRE.subi to return indexes instead of the substring.

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


---
 common/mlpcre/PCRE.ml       |  3 +--
 common/mlpcre/PCRE.mli      | 14 ++++++++++++++
 common/mlpcre/pcre-c.c      | 27 +++++++++++++++++++++++++++
 common/mlpcre/pcre_tests.ml | 19 ++++++++++++++++---
 4 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/common/mlpcre/PCRE.ml b/common/mlpcre/PCRE.ml
index 94eea4b34..5269d41f8 100644
--- a/common/mlpcre/PCRE.ml
+++ b/common/mlpcre/PCRE.ml
@@ -23,10 +23,9 @@ exception Error of string * int
 type regexp
 
 external compile : string -> regexp = "guestfs_int_pcre_compile"
-
 external matches : regexp -> string -> bool = "guestfs_int_pcre_matches"
-
 external sub : int -> string = "guestfs_int_pcre_sub"
+external subi : int -> int * int = "guestfs_int_pcre_subi"
 
 let () =
   Callback.register_exception "PCRE.Error" (Error ("", 0))
diff --git a/common/mlpcre/PCRE.mli b/common/mlpcre/PCRE.mli
index 331a50a9a..02f16d19d 100644
--- a/common/mlpcre/PCRE.mli
+++ b/common/mlpcre/PCRE.mli
@@ -77,3 +77,17 @@ val sub : int -> string
 
     If there was no nth substring then this raises [Not_found].
     This can also raise {!Error} for other PCRE-related errors. *)
+
+val subi : int -> int * int
+(** Return the nth substring (capture) matched by the previous call
+    to {!matches} in the current thread.
+
+    This is the same as {!sub} but instead of copying the
+    substring out, it returns the indexes into the original string
+    of the first character of the substring and the first
+    character after the substring.
+
+    (See pcreapi(3) section "How pcre_exec() returns captured substrings"
+    for exact details).
+
+    If there was no nth substring then this raises [Not_found]. *)
diff --git a/common/mlpcre/pcre-c.c b/common/mlpcre/pcre-c.c
index da9b50d34..15775dad0 100644
--- a/common/mlpcre/pcre-c.c
+++ b/common/mlpcre/pcre-c.c
@@ -225,3 +225,30 @@ guestfs_int_pcre_sub (value nv)
   memcpy (String_val (strv), str, len);
   CAMLreturn (strv);
 }
+
+value
+guestfs_int_pcre_subi (value nv)
+{
+  CAMLparam1 (nv);
+  int n = Int_val (nv);
+  CAMLlocal1 (rv);
+  struct last_match *m = gl_tls_get (last_match);
+
+  if (m == NULL)
+    raise_pcre_error ("PCRE.subi called without calling PCRE.matches", 0);
+
+  if (n < 0)
+    caml_invalid_argument ("PCRE.subi: n must be >= 0");
+
+  /* eg if there are 2 captures, m->r == 3, and valid values of n are
+   * 0, 1 or 2.
+   */
+  if (n >= m->r)
+    caml_raise_not_found ();
+
+  rv = caml_alloc (2, 0);
+  Store_field (rv, 0, Val_int (m->vec[n*2]));
+  Store_field (rv, 1, Val_int (m->vec[n*2+1]));
+
+  CAMLreturn (rv);
+}
diff --git a/common/mlpcre/pcre_tests.ml b/common/mlpcre/pcre_tests.ml
index 2b18f462f..316a4348e 100644
--- a/common/mlpcre/pcre_tests.ml
+++ b/common/mlpcre/pcre_tests.ml
@@ -34,6 +34,12 @@ let sub i =
   eprintf " %s\n%!" r;
   r
 
+let subi i =
+  eprintf "PCRE.subi %d ->%!" i;
+  let i1, i2 = PCRE.subi i in
+  eprintf " (%d, %d)\n%!" i1 i2;
+  (i1, i2)
+
 let () =
   try
     let re0 = compile "a+b" in
@@ -62,19 +68,26 @@ let () =
     assert (matches re2 "ccac" = true);
     assert (sub 1 = "a");
     assert (sub 2 = "");
-    assert (sub 0 = "a")
+    assert (sub 0 = "a");
+    assert (subi 0 = (2, 3));
+    assert (subi 1 = (2, 3));
+    assert (subi 2 = (3, 3))
   with
   | Not_found ->
      failwith "one of the PCRE.sub functions unexpectedly raised Not_found"
   | PCRE.Error (msg, code) ->
      failwith (sprintf "PCRE error: %s (PCRE error code %d)" msg code)
 
-(* Run some out of range [sub] calls to ensure an exception is thrown. *)
+(* Run some out of range [sub] and [subi] calls to ensure an exception
+ * is thrown.
+ *)
 let () =
   let re2 = compile "(a+)(b*)" in
   ignore (matches re2 "ccac");
   (try ignore (sub 3) with Not_found -> ());
-  (try ignore (sub (-1)) with Invalid_argument _ -> ())
+  (try ignore (sub (-1)) with Invalid_argument _ -> ());
+  (try ignore (subi 3) with Not_found -> ());
+  (try ignore (subi (-1)) with Invalid_argument _ -> ())
 
 (* Compile some bad regexps and check that an exception is thrown.
  * It would be nice to check the error message is right but
-- 
2.13.2




More information about the Libguestfs mailing list