Optimise single-character insertions
authorRoss Burton <rburton@src.gnome.org>
Thu, 18 Aug 2005 09:30:24 +0000 (09:30 +0000)
committerRoss Burton <rburton@src.gnome.org>
Thu, 18 Aug 2005 09:30:24 +0000 (09:30 +0000)
ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-8
glib/gstring.c
glib/gutf8.c
tests/string-test.c

index 2b065ae..41c53b7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2005-08-18  Ross Burton  <ross@burtonini.com>
+
+       * glib/gstring.c:
+       Optimise single-character insertions.
+       
+       * glib/gutf8.c:
+       Note copied code.
+       
+       * tests/string-test.c:
+       Add tests for new optimisation, and fix a leak.
+
 2005-08-17  Matthias Clasen  <mclasen@redhat.com>
 
        * configure.in: Check for crt_externs.h and _NSGetEnviron.
index 2b065ae..41c53b7 100644 (file)
@@ -1,3 +1,14 @@
+2005-08-18  Ross Burton  <ross@burtonini.com>
+
+       * glib/gstring.c:
+       Optimise single-character insertions.
+       
+       * glib/gutf8.c:
+       Note copied code.
+       
+       * tests/string-test.c:
+       Add tests for new optimisation, and fix a leak.
+
 2005-08-17  Matthias Clasen  <mclasen@redhat.com>
 
        * configure.in: Check for crt_externs.h and _NSGetEnviron.
index 2b065ae..41c53b7 100644 (file)
@@ -1,3 +1,14 @@
+2005-08-18  Ross Burton  <ross@burtonini.com>
+
+       * glib/gstring.c:
+       Optimise single-character insertions.
+       
+       * glib/gutf8.c:
+       Note copied code.
+       
+       * tests/string-test.c:
+       Add tests for new optimisation, and fix a leak.
+
 2005-08-17  Matthias Clasen  <mclasen@redhat.com>
 
        * configure.in: Check for crt_externs.h and _NSGetEnviron.
index 2b065ae..41c53b7 100644 (file)
@@ -1,3 +1,14 @@
+2005-08-18  Ross Burton  <ross@burtonini.com>
+
+       * glib/gstring.c:
+       Optimise single-character insertions.
+       
+       * glib/gutf8.c:
+       Note copied code.
+       
+       * tests/string-test.c:
+       Add tests for new optimisation, and fix a leak.
+
 2005-08-17  Matthias Clasen  <mclasen@redhat.com>
 
        * configure.in: Check for crt_externs.h and _NSGetEnviron.
index 43125eb..c0c0b6f 100644 (file)
@@ -510,7 +510,10 @@ g_string_insert_len (GString     *string,
        g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
 
       /* insert the new string */
-      memcpy (string->str + pos, val, len);
+      if (len == 1)
+        string->str[pos] = *val;
+      else
+        memcpy (string->str + pos, val, len);
     }
 
   string->len += len;
@@ -675,18 +678,71 @@ GString*
 g_string_insert_unichar (GString *string,
                         gssize   pos,    
                         gunichar wc)
-{  
-  gchar buf[6];
-  gint charlen;
+{
+  gint charlen, first, i;
+  gchar *dest;
 
-  /* We could be somewhat more efficient here by computing
-   * the length, adding the space, then converting into that
-   * space, by cut-and-pasting the internals of g_unichar_to_utf8.
-   */
   g_return_val_if_fail (string != NULL, NULL);
 
-  charlen = g_unichar_to_utf8 (wc, buf);
-  return g_string_insert_len (string, pos, buf, charlen);
+  /* Code copied from g_unichar_to_utf() */
+  if (wc < 0x80)
+    {
+      first = 0;
+      charlen = 1;
+    }
+  else if (wc < 0x800)
+    {
+      first = 0xc0;
+      charlen = 2;
+    }
+  else if (wc < 0x10000)
+    {
+      first = 0xe0;
+      charlen = 3;
+    }
+   else if (wc < 0x200000)
+    {
+      first = 0xf0;
+      charlen = 4;
+    }
+  else if (wc < 0x4000000)
+    {
+      first = 0xf8;
+      charlen = 5;
+    }
+  else
+    {
+      first = 0xfc;
+      charlen = 6;
+    }
+  /* End of copied code */
+
+  g_string_maybe_expand (string, charlen);
+
+  if (pos < 0)
+    pos = string->len;
+  else
+    g_return_val_if_fail (pos <= string->len, string);
+
+  /* If not just an append, move the old stuff */
+  if (pos < string->len)
+    g_memmove (string->str + pos + charlen, string->str + pos, string->len - pos);
+
+  dest = string->str + pos;
+  /* Code copied from g_unichar_to_utf() */
+  for (i = charlen - 1; i > 0; --i)
+    {
+      dest[i] = (wc & 0x3f) | 0x80;
+      wc >>= 6;
+    }
+  dest[0] = wc | first;
+  /* End of copied code */
+  
+  string->len += charlen;
+
+  string->str[string->len] = 0;
+
+  return string;
 }
 
 GString*
index d3aa85d..dc87523 100644 (file)
@@ -536,6 +536,7 @@ int
 g_unichar_to_utf8 (gunichar c,
                   gchar   *outbuf)
 {
+  /* If this gets modified, also update the copy in g_string_insert_unichar() */
   guint len = 0;    
   int first;
   int i;
index d129b53..4ba7fc2 100644 (file)
@@ -133,7 +133,6 @@ main (int   argc,
   g_string_free (string1, TRUE);
 
   /* append_len */
-
   string1 = g_string_new ("firsthalf");
   g_string_append_len (string1, "lasthalfjunkjunk", strlen ("lasthalf"));
   g_assert (strcmp (string1->str, "firsthalflasthalf") == 0);
@@ -164,7 +163,6 @@ main (int   argc,
   g_string_free (string1, TRUE);
   
   /* insert_len */
-
   string1 = g_string_new ("firstlast");
   g_string_insert_len (string1, 5, "middlejunkjunk", strlen ("middle"));
   g_assert (strcmp (string1->str, "firstmiddlelast") == 0);
@@ -209,6 +207,48 @@ main (int   argc,
   g_assert (strcmp (string1->str, "boring text") == 0);
   g_string_free (string1, TRUE);
 
+  /* insert_unichar with insertion in middle */
+  string1 = g_string_new ("firsthalf");
+  g_string_insert_unichar (string1, 5, 0x0041);
+  g_assert (strcmp (string1->str, "first\x41half") == 0);
+  g_string_free (string1, TRUE);
+
+  string1 = g_string_new ("firsthalf");
+  g_string_insert_unichar (string1, 5, 0x0298);
+  g_assert (strcmp (string1->str, "first\xCA\x98half") == 0);
+  g_string_free (string1, TRUE);
+
+  string1 = g_string_new ("firsthalf");
+  g_string_insert_unichar (string1, 5, 0xFFFD);
+  g_assert (strcmp (string1->str, "first\xEF\xBF\xBDhalf") == 0);
+  g_string_free (string1, TRUE);
+
+  string1 = g_string_new ("firsthalf");
+  g_string_insert_unichar (string1, 5, 0x1D100);
+  g_assert (strcmp (string1->str, "first\xF0\x9D\x84\x80half") == 0);
+  g_string_free (string1, TRUE);
+
+  /* insert_unichar with insertion at end */
+  string1 = g_string_new ("start");
+  g_string_insert_unichar (string1, -1, 0x0041);
+  g_assert (strcmp (string1->str, "start\x41") == 0);
+  g_string_free (string1, TRUE);
+
+  string1 = g_string_new ("start");
+  g_string_insert_unichar (string1, -1, 0x0298);
+  g_assert (strcmp (string1->str, "start\xCA\x98") == 0);
+  g_string_free (string1, TRUE);
+
+  string1 = g_string_new ("start");
+  g_string_insert_unichar (string1, -1, 0xFFFD);
+  g_assert (strcmp (string1->str, "start\xEF\xBF\xBD") == 0);
+  g_string_free (string1, TRUE);
+
+  string1 = g_string_new ("start");
+  g_string_insert_unichar (string1, -1, 0x1D100);
+  g_assert (strcmp (string1->str, "start\xF0\x9D\x84\x80") == 0);
+  g_string_free (string1, TRUE);
+
   /* g_string_equal */
   string1 = g_string_new ("test");
   string2 = g_string_new ("te");
@@ -261,6 +301,8 @@ main (int   argc,
   tmp_string = (gchar *) g_malloc (10);
   g_snprintf (tmp_string, 10, "%2$s %1$s", "a", "b");
   g_assert (strcmp (tmp_string, "b a") == 0);
+  g_free (tmp_string);
+
   return 0;
 }