[glib] add g_regex_escape_nul



commit 5eee90fbbc76ee129d7f846633a667889149ab03
Author: Paolo Bonzini <pbonzini redhat com>
Date:   Thu Apr 15 08:23:00 2010 +0200

    add g_regex_escape_nul
    
    The function can be used to let regex compile non-NUL-terminated
    strings without redesigning the way the pattern is stored in GRegex
    objects and retrieved with g_regex_get_pattern.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=615895

 docs/reference/glib/glib-sections.txt |    1 +
 glib/glib.symbols                     |    1 +
 glib/gregex.c                         |   68 +++++++++++++++++++++++++++++++++
 glib/gregex.h                         |    2 +
 glib/tests/regex.c                    |   42 ++++++++++++++++++++
 5 files changed, 114 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 0f750c6..0a129ad 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -981,6 +981,7 @@ g_regex_get_string_number
 g_regex_get_compile_flags
 g_regex_get_match_flags
 g_regex_escape_string
+g_regex_escape_nul
 g_regex_match_simple
 g_regex_match
 g_regex_match_full
diff --git a/glib/glib.symbols b/glib/glib.symbols
index abe216a..a0c902f 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -1352,6 +1352,7 @@ g_regex_get_string_number
 g_regex_get_compile_flags
 g_regex_get_match_flags
 g_regex_escape_string
+g_regex_escape_nul
 g_regex_match_simple
 g_regex_match
 g_regex_match_full
diff --git a/glib/gregex.c b/glib/gregex.c
index 7603b5f..0e8a429 100644
--- a/glib/gregex.c
+++ b/glib/gregex.c
@@ -2833,6 +2833,74 @@ g_regex_check_replacement (const gchar  *replacement,
 }
 
 /**
+ * g_regex_escape_nul:
+ * @string: the string to escape
+ * @length: the length of @string
+ *
+ * Escapes the nul characters in @string to "\x00".  It can be used
+ * to compile a regex with embedded nul characters.
+ *
+ * For completeness, @length can be -1 for a nul-terminated string.
+ * In this case the output string will be of course equal to @string.
+ *
+ * Returns: a newly-allocated escaped string
+ *
+ * Since: 2.30
+ */
+gchar *
+g_regex_escape_nul (const gchar *string,
+                    gint         length)
+{
+  GString *escaped;
+  const gchar *p, *piece_start, *end;
+  gint backslashes;
+
+  g_return_val_if_fail (string != NULL, NULL);
+
+  if (length < 0)
+    return g_strdup (string);
+
+  end = string + length;
+  p = piece_start = string;
+  escaped = g_string_sized_new (length + 1);
+
+  backslashes = 0;
+  while (p < end)
+    {
+      switch (*p)
+        {
+        case '\0':
+          if (p != piece_start)
+            {
+              /* copy the previous piece. */
+              g_string_append_len (escaped, piece_start, p - piece_start);
+            }
+          if ((backslashes & 1) == 0)
+            g_string_append_c (escaped, '\\');
+          g_string_append_c (escaped, 'x');
+          g_string_append_c (escaped, '0');
+          g_string_append_c (escaped, '0');
+          piece_start = ++p;
+          backslashes = 0;
+          break;
+        case '\\':
+          backslashes++;
+          ++p;
+          break;
+        default:
+          backslashes = 0;
+          p = g_utf8_next_char (p);
+          break;
+        }
+    }
+
+  if (piece_start < end)
+    g_string_append_len (escaped, piece_start, end - piece_start);
+
+  return g_string_free (escaped, FALSE);
+}
+
+/**
  * g_regex_escape_string:
  * @string: (array length=length): the string to escape
  * @length: the length of @string, or -1 if @string is nul-terminated
diff --git a/glib/gregex.h b/glib/gregex.h
index c3fb753..666b487 100644
--- a/glib/gregex.h
+++ b/glib/gregex.h
@@ -364,6 +364,8 @@ gint		  g_regex_get_string_number	(const GRegex        *regex,
 						 const gchar         *name);
 gchar		 *g_regex_escape_string		(const gchar         *string,
 						 gint                 length);
+gchar		 *g_regex_escape_nul		(const gchar         *string,
+						 gint                 length);
 
 GRegexCompileFlags g_regex_get_compile_flags    (const GRegex        *regex);
 GRegexMatchFlags   g_regex_get_match_flags      (const GRegex        *regex);
diff --git a/glib/tests/regex.c b/glib/tests/regex.c
index 9a8dbc2..7f7cc65 100644
--- a/glib/tests/regex.c
+++ b/glib/tests/regex.c
@@ -1129,6 +1129,31 @@ test_escape (gconstpointer d)
   g_free (path);                                        \
 }
 
+static void
+test_escape_nul (gconstpointer d)
+{
+  const TestEscapeData *data = d;
+  gchar *escaped;
+
+  escaped = g_regex_escape_nul (data->string, data->length);
+
+  g_assert_cmpstr (escaped, ==, data->expected);
+
+  g_free (escaped);
+}
+
+#define TEST_ESCAPE_NUL(_string, _length, _expected) {  \
+  TestEscapeData *data;                                 \
+  gchar *path;                                          \
+  data = g_new0 (TestEscapeData, 1);                    \
+  data->string = _string;                               \
+  data->length = _length;                               \
+  data->expected = _expected;                           \
+  path = g_strdup_printf ("/regex/escape_nul/%d", ++total);  \
+  g_test_add_data_func (path, data, test_escape_nul);   \
+  g_free (path);                                        \
+}
+
 typedef struct {
   const gchar *pattern;
   const gchar *string;
@@ -2574,6 +2599,23 @@ main (int argc, char *argv[])
   TEST_GET_STRING_NUMBER("(?:a)(?P<A>.)", "A", 1);
   TEST_GET_STRING_NUMBER("(?:a)(?P<A>.)", "B", -1);
 
+  /* TEST_ESCAPE_NUL(string, length, expected) */
+  TEST_ESCAPE_NUL("hello world", -1, "hello world");
+  TEST_ESCAPE_NUL("hello\0world", -1, "hello");
+  TEST_ESCAPE_NUL("\0world", -1, "");
+  TEST_ESCAPE_NUL("hello world", 5, "hello");
+  TEST_ESCAPE_NUL("hello.world", 11, "hello.world");
+  TEST_ESCAPE_NUL("a(b\\b.$", 7, "a(b\\b.$");
+  TEST_ESCAPE_NUL("hello\0", 6, "hello\\x00");
+  TEST_ESCAPE_NUL("\0world", 6, "\\x00world");
+  TEST_ESCAPE_NUL("\0\0", 2, "\\x00\\x00");
+  TEST_ESCAPE_NUL("hello\0world", 11, "hello\\x00world");
+  TEST_ESCAPE_NUL("hello\0world\0", 12, "hello\\x00world\\x00");
+  TEST_ESCAPE_NUL("hello\\\0world", 12, "hello\\x00world");
+  TEST_ESCAPE_NUL("hello\\\\\0world", 13, "hello\\\\\\x00world");
+  TEST_ESCAPE_NUL("|()[]{}^$*+?.", 13, "|()[]{}^$*+?.");
+  TEST_ESCAPE_NUL("|()[]{}^$*+?.\\\\", 15, "|()[]{}^$*+?.\\\\");
+
   /* TEST_ESCAPE(string, length, expected) */
   TEST_ESCAPE("hello world", -1, "hello world");
   TEST_ESCAPE("hello world", 5, "hello");



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]