Proposed patch: Modify glib to permit embedded NULs in GString.



Here's a proposed glib patch & ChangeLog entry. It does 3 things:

* It modifies glib so GString can support embedded ASCII NULs (\0).
  Many other languages' string type can do this (Perl, Python, Ada, etc.).
  It's often convenient to be able to handle NULs in strings, and there's
  no reason that GString shouldn't be able to do this too.

* It adds a "gboolean g_string_equal()".  This is primarily because,
  if there are embedded NULs, the strcmp() functions no longer do the trick.
  Besides, any string data type should have an equality test available.

* Finally, it changes the return type of g_str_equal from "gint" to "gboolean".
  Somehow this was missed in the big move to gboolean, and it makes
  no sense for this function to be "different" than the rest.
  This caused several lines in glib.h to change due to reformatting.

Seem okay?



Tue Jun 27 12:40:23 EDT 2000  David A. Wheeler <dwheeler@dwheeler.com>

	* glib.h: Added g_string_equal for comparing GStrings;
	changed g_str_equal so it returns gboolean (instead of gint).

	* gstring.c: Modified GString implementation to support embedded
	ASCII NUL ('\0') characters, and implemented g_string_equal.

	* testglib.c: Added tests for g_string_equal and tests for
	proper handling of embedded ASCII NUL characters.




--- glib.orig/glib.h	Sat Jun 24 18:30:10 2000
+++ glib/glib.h	Tue Jun 27 12:20:35 2000
@@ -1865,6 +1865,8 @@
 GString*     g_string_sized_new         (guint		  dfl_size);
 void	     g_string_free	        (GString	 *string,
 					 gboolean	  free_segment);
+gboolean     g_string_equal             (const GString	 *v,
+					 const GString 	 *v2);
 GString*     g_string_assign            (GString	 *string,
 					 const gchar	 *rval);
 GString*     g_string_truncate          (GString	 *string,
@@ -1989,13 +1991,13 @@

 /* Hash Functions
  */
-gint  g_str_equal (gconstpointer   v,
-		   gconstpointer   v2);
-guint g_str_hash  (gconstpointer   v);
-
-gint  g_int_equal (gconstpointer   v,
-		   gconstpointer   v2);
-guint g_int_hash  (gconstpointer   v);
+gboolean g_str_equal (gconstpointer   v,
+		      gconstpointer   v2);
+guint	 g_str_hash  (gconstpointer   v);
+
+gint	 g_int_equal (gconstpointer   v,
+		      gconstpointer   v2);
+guint	 g_int_hash  (gconstpointer   v);

 /* This "hash" function will just return the key's adress as an
  * unsigned integer. Useful for hashing on plain adresses or

--- glib.orig/gstring.c	Fri May 19 06:01:08 2000
+++ glib/gstring.c	Tue Jun 27 12:22:06 2000
@@ -67,7 +67,7 @@
 /* Hash Functions.
  */

-gint
+gboolean
 g_str_equal (gconstpointer v1,
 	     gconstpointer v2)
 {
@@ -265,6 +265,30 @@
   G_UNLOCK (string_mem_chunk);
 }

+gboolean
+g_string_equal (const GString *v,
+                const GString *v2)
+{
+  gchar *p, *q;
+  GRealString *string1 = (GRealString *) v;
+  GRealString *string2 = (GRealString *) v2;
+  gint i = string1->len;
+
+  if (i != string2->len)
+    return FALSE;
+
+  p = string1->str;
+  q = string2->str;
+  while (i) {
+    if (*p != *q)
+      return FALSE;
+    p++;
+    q++;
+    i--;
+  }
+  return TRUE;
+}
+
 GString*
 g_string_assign (GString     *string,
 		 const gchar *rval)
@@ -320,7 +344,7 @@
     g_memmove (string->str + pos + len, string->str + pos, string->len - pos);

   /* insert the new string */
-  strncpy (string->str + pos, val, len);
+  g_memmove (string->str + pos, val, len);

   string->len += len;

@@ -457,15 +481,17 @@
 {
   GRealString *string = (GRealString *) fstring;
   guchar *s;
+  gint n = string->len;

   g_return_val_if_fail (string != NULL, NULL);

   s = string->str;

-  while (*s)
+  while (n)
     {
       *s = tolower (*s);
       s++;
+      n--;
     }

   return fstring;
@@ -476,15 +502,17 @@
 {
   GRealString *string = (GRealString *) fstring;
   guchar *s;
+  gint n = string->len;

   g_return_val_if_fail (string != NULL, NULL);

   s = string->str;

-  while (*s)
+  while (n)
     {
       *s = toupper (*s);
       s++;
+      n--;
     }

   return fstring;

--- glib.orig/testglib.c	Wed Mar  1 04:44:09 2000
+++ glib/testglib.c	Tue Jun 27 12:30:31 2000
@@ -795,7 +795,37 @@
   g_string_insert_len (string1, 5, "last", -1);
   g_assert (strcmp (string1->str, "firstlast") == 0);
   g_string_free (string1, TRUE);
+
+  /* g_string_equal */
+  string1 = g_string_new ("test");
+  string2 = g_string_new ("te");
+  g_assert (! g_string_equal(string1, string2));
+  g_string_append (string2, "st");
+  g_assert (g_string_equal(string1, string2));
+  g_string_free (string1, TRUE);
+  g_string_free (string2, TRUE);

+  /* Special case test: Handle embedded ASCII 0 (NUL) characters. */
+  string1 = g_string_new ("fiddle");
+  string2 = g_string_new ("fiddle");
+  g_assert (g_string_equal(string1, string2));
+  g_string_append_c(string1, '\0');
+  g_assert (! g_string_equal(string1, string2));
+  g_string_append_c(string2, '\0');
+  g_assert (g_string_equal(string1, string2));
+  g_string_append_c(string1, 'x');
+  g_string_append_c(string2, 'y');
+  g_assert (! g_string_equal(string1, string2));
+  g_assert (string1->len == 8);
+  g_string_append(string1, "yzzy");
+  g_assert (string1->len == 12);
+  g_assert ( memcmp(string1->str, "fiddle\0xyzzy", 13) == 0);
+  g_string_insert(string1, 1, "QED");
+  g_assert ( memcmp(string1->str, "fQEDiddle\0xyzzy", 16) == 0);
+  g_string_free (string1, TRUE);
+  g_string_free (string2, TRUE);
+
+
   g_print ("ok\n");

   g_print ("checking timers...\n");




-- 

--- David A. Wheeler
    dwheeler@ida.org





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