Handle the case where the to-be-inserted string is a substring of the
authorMorten Welinder <terra@gnome.org>
Wed, 5 Nov 2003 16:24:44 +0000 (16:24 +0000)
committerMorten Welinder <mortenw@src.gnome.org>
Wed, 5 Nov 2003 16:24:44 +0000 (16:24 +0000)
2003-11-05  Morten Welinder  <terra@gnome.org>

* glib/gstring.c (g_string_insert_len): Handle the case where the
to-be-inserted string is a substring of the target string.
(g_string_assign): Handle "s = s;".
(#114260, self.)

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
glib/gstring.c
tests/string-test.c

index 3d5b55cdb33697254fb799c0d01ac81ab8b81db2..d229e38bca22ce9fa9aa73bf0acc8d0ec3da0fab 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2003-11-05  Morten Welinder  <terra@gnome.org>
+
+       * glib/gstring.c (g_string_insert_len): Handle the case where the
+       to-be-inserted string is a substring of the target string.
+       (g_string_assign): Handle "s = s;".
+       (#114260, self.)
+
 Sun Nov  2 01:47:31 2003  Matthias Clasen  <maclas@gmx.de>
 
        Fix 64bit printing for MSVC builds (#119292, Hans Breuer):
index 3d5b55cdb33697254fb799c0d01ac81ab8b81db2..d229e38bca22ce9fa9aa73bf0acc8d0ec3da0fab 100644 (file)
@@ -1,3 +1,10 @@
+2003-11-05  Morten Welinder  <terra@gnome.org>
+
+       * glib/gstring.c (g_string_insert_len): Handle the case where the
+       to-be-inserted string is a substring of the target string.
+       (g_string_assign): Handle "s = s;".
+       (#114260, self.)
+
 Sun Nov  2 01:47:31 2003  Matthias Clasen  <maclas@gmx.de>
 
        Fix 64bit printing for MSVC builds (#119292, Hans Breuer):
index 3d5b55cdb33697254fb799c0d01ac81ab8b81db2..d229e38bca22ce9fa9aa73bf0acc8d0ec3da0fab 100644 (file)
@@ -1,3 +1,10 @@
+2003-11-05  Morten Welinder  <terra@gnome.org>
+
+       * glib/gstring.c (g_string_insert_len): Handle the case where the
+       to-be-inserted string is a substring of the target string.
+       (g_string_assign): Handle "s = s;".
+       (#114260, self.)
+
 Sun Nov  2 01:47:31 2003  Matthias Clasen  <maclas@gmx.de>
 
        Fix 64bit printing for MSVC builds (#119292, Hans Breuer):
index 3d5b55cdb33697254fb799c0d01ac81ab8b81db2..d229e38bca22ce9fa9aa73bf0acc8d0ec3da0fab 100644 (file)
@@ -1,3 +1,10 @@
+2003-11-05  Morten Welinder  <terra@gnome.org>
+
+       * glib/gstring.c (g_string_insert_len): Handle the case where the
+       to-be-inserted string is a substring of the target string.
+       (g_string_assign): Handle "s = s;".
+       (#114260, self.)
+
 Sun Nov  2 01:47:31 2003  Matthias Clasen  <maclas@gmx.de>
 
        Fix 64bit printing for MSVC builds (#119292, Hans Breuer):
index 3d5b55cdb33697254fb799c0d01ac81ab8b81db2..d229e38bca22ce9fa9aa73bf0acc8d0ec3da0fab 100644 (file)
@@ -1,3 +1,10 @@
+2003-11-05  Morten Welinder  <terra@gnome.org>
+
+       * glib/gstring.c (g_string_insert_len): Handle the case where the
+       to-be-inserted string is a substring of the target string.
+       (g_string_assign): Handle "s = s;".
+       (#114260, self.)
+
 Sun Nov  2 01:47:31 2003  Matthias Clasen  <maclas@gmx.de>
 
        Fix 64bit printing for MSVC builds (#119292, Hans Breuer):
index 3d5b55cdb33697254fb799c0d01ac81ab8b81db2..d229e38bca22ce9fa9aa73bf0acc8d0ec3da0fab 100644 (file)
@@ -1,3 +1,10 @@
+2003-11-05  Morten Welinder  <terra@gnome.org>
+
+       * glib/gstring.c (g_string_insert_len): Handle the case where the
+       to-be-inserted string is a substring of the target string.
+       (g_string_assign): Handle "s = s;".
+       (#114260, self.)
+
 Sun Nov  2 01:47:31 2003  Matthias Clasen  <maclas@gmx.de>
 
        Fix 64bit printing for MSVC builds (#119292, Hans Breuer):
index 24d8b8592d4e698fed12980c226e441125577dc7..4f212a6dec7f35b75048765354a84ecd4c3de789 100644 (file)
@@ -373,9 +373,15 @@ g_string_assign (GString     *string,
 {
   g_return_val_if_fail (string != NULL, NULL);
   g_return_val_if_fail (rval != NULL, string);
-  
-  g_string_truncate (string, 0);
-  g_string_append (string, rval);
+
+  /* Make sure assigning to itself doesn't corrupt the string.  */
+  if (string->str != rval)
+    {
+      /* Assigning from substring should be ok since g_string_truncate
+        does not realloc.  */
+      g_string_truncate (string, 0);
+      g_string_append (string, rval);
+    }
 
   return string;
 }
@@ -436,17 +442,50 @@ g_string_insert_len (GString     *string,
     pos = string->len;
   else
     g_return_val_if_fail (pos <= string->len, string);
-  
-  g_string_maybe_expand (string, len);
 
-  /* If we aren't appending at the end, move a hunk
-   * of the old string to the end, opening up space
-   */
-  if (pos < string->len)
-    g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
-  
-  /* insert the new string */
-  g_memmove (string->str + pos, val, len);
+  /* Check whether val represents a substring of string.  This test
+     probably violates chapter and verse of the C standards, since
+     ">=" and "<=" are only valid when val really is a substring.
+     In practice, it will work on modern archs.  */
+  if (val >= string->str && val <= string->str + string->len)
+    {
+      gsize offset = val - string->str;
+      gsize precount = 0;
+
+      g_string_maybe_expand (string, len);
+      val = string->str + offset;
+      /* At this point, val is valid again.  */
+
+      /* Open up space where we are going to insert.  */
+      if (pos < string->len)
+       g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
+
+      /* Move the source part before the gap, if any.  */
+      if (offset < pos)
+       {
+         precount = MIN (len, pos - offset);
+         memcpy (string->str + pos, val, precount);
+       }
+
+      /* Move the source part after the gap, if any.  */
+      if (len > precount)
+       memcpy (string->str + pos + precount,
+               val + /* Already moved: */ precount + /* Space opened up: */ len,
+               len - precount);
+    }
+  else
+    {
+      g_string_maybe_expand (string, len);
+
+      /* If we aren't appending at the end, move a hunk
+       * of the old string to the end, opening up space
+       */
+      if (pos < string->len)
+       g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
+
+      /* insert the new string */
+      memcpy (string->str + pos, val, len);
+    }
 
   string->len += len;
 
index b328e9cc81b5ebc056ff59b605790d283c6988b9..d129b53f6f217684e1a5f1f33dce4aa7720d25a0 100644 (file)
@@ -89,7 +89,7 @@ main (int   argc,
   g_string_chunk_free (string_chunk);
 
   string1 = g_string_new ("hi pete!");
-  string2 = g_string_new ("");
+  string2 = g_string_new (NULL);
 
   g_assert (string1 != NULL);
   g_assert (string2 != NULL);
@@ -182,6 +182,33 @@ main (int   argc,
   g_assert (strcmp (string1->str, "firstlast") == 0);
   g_string_free (string1, TRUE);
 
+  /* insert_len with string overlap */
+  string1 = g_string_new ("textbeforetextafter");
+  g_string_insert_len (string1, 10, string1->str + 8, 5);
+  g_assert (strcmp (string1->str, "textbeforeretextextafter") == 0);
+  g_string_free (string1, TRUE);
+
+  string1 = g_string_new ("boring text");
+  g_string_insert_len (string1, 7, string1->str + 2, 4);
+  g_assert (strcmp (string1->str, "boring ringtext") == 0);
+  g_string_free (string1, TRUE);
+
+  string1 = g_string_new ("boring text");
+  g_string_insert_len (string1, 6, string1->str + 7, 4);
+  g_assert (strcmp (string1->str, "boringtext text") == 0);
+  g_string_free (string1, TRUE);
+
+  /* assign_len with string overlap */
+  string1 = g_string_new ("textbeforetextafter");
+  g_string_assign (string1, string1->str + 10);
+  g_assert (strcmp (string1->str, "textafter") == 0);
+  g_string_free (string1, TRUE);
+
+  string1 = g_string_new ("boring text");
+  g_string_assign (string1, string1->str);
+  g_assert (strcmp (string1->str, "boring text") == 0);
+  g_string_free (string1, TRUE);
+
   /* g_string_equal */
   string1 = g_string_new ("test");
   string2 = g_string_new ("te");