applied patch from Andreas Persenius <ndap@swipnet.se> that updates the
[platform/upstream/glib.git] / glib / gstring.c
index fd8e512..4f2ce7d 100644 (file)
@@ -2,23 +2,23 @@
  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
+ * Lesser General Public License for more details.
  *
- * You should have received a copy of the GNU Library General Public
+ * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
 
 /*
- * Modified by the GLib Team and others 1997-1999.  See the AUTHORS
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GLib Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
  * MT safe
  */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #include <stdarg.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -35,7 +42,6 @@
 #include <ctype.h>
 #include "glib.h"
 
-
 typedef struct _GRealStringChunk GRealStringChunk;
 typedef struct _GRealString      GRealString;
 
@@ -61,29 +67,28 @@ static GMemChunk *string_mem_chunk = NULL;
 /* Hash Functions.
  */
 
-gint
-g_str_equal (gconstpointer v, gconstpointer v2)
+gboolean
+g_str_equal (gconstpointer v1,
+            gconstpointer v2)
 {
-  return strcmp ((const gchar*) v, (const gchar*)v2) == 0;
+  const gchar *string1 = v1;
+  const gchar *string2 = v2;
+  
+  return strcmp (string1, string2) == 0;
 }
 
-/* a char* hash function from ASU */
+/* 31 bit hash function */
 guint
-g_str_hash (gconstpointer v)
+g_str_hash (gconstpointer key)
 {
-  const char *s = (char*)v;
-  const char *p;
-  guint h=0, g;
-
-  for(p = s; *p != '\0'; p += 1) {
-    h = ( h << 4 ) + *p;
-    if ( ( g = h & 0xf0000000 ) ) {
-      h = h ^ (g >> 24);
-      h = h ^ g;
-    }
-  }
+  const char *p = key;
+  guint h = *p;
 
-  return h /* % M */;
+  if (h)
+    for (p += 1; *p != '\0'; p++)
+      h = (h << 5) - h + *p;
+
+  return h;
 }
 
 
@@ -154,7 +159,7 @@ g_string_chunk_insert (GStringChunk *fchunk,
       chunk->storage_next = 0;
     }
 
-  pos = ((char*)chunk->storage_list->data) + chunk->storage_next;
+  pos = ((char *) chunk->storage_list->data) + chunk->storage_next;
 
   strcpy (pos, string);
 
@@ -188,8 +193,8 @@ g_string_chunk_insert_const (GStringChunk *fchunk,
 
 /* Strings.
  */
-static gint
-nearest_pow (gint num)
+static inline gint
+nearest_power (gint num)
 {
   gint n = 1;
 
@@ -204,7 +209,7 @@ g_string_maybe_expand (GRealString* string, gint len)
 {
   if (string->len + len >= string->alloc)
     {
-      string->alloc = nearest_pow (string->len + len + 1);
+      string->alloc = nearest_power (string->len + len + 1);
       string->str = g_realloc (string->str, string->alloc);
     }
 }
@@ -248,7 +253,7 @@ g_string_new (const gchar *init)
 
 void
 g_string_free (GString *string,
-              gint free_segment)
+              gboolean free_segment)
 {
   g_return_if_fail (string != NULL);
 
@@ -260,82 +265,104 @@ g_string_free (GString *string,
   G_UNLOCK (string_mem_chunk);
 }
 
-GString*
-g_string_assign (GString *lval,
-                const gchar *rval)
+gboolean
+g_string_equal (const GString *v,
+                const GString *v2)
 {
-  g_string_truncate (lval, 0);
-  g_string_append (lval, rval);
+  gchar *p, *q;
+  GRealString *string1 = (GRealString *) v;
+  GRealString *string2 = (GRealString *) v2;
+  gint i = string1->len;
 
-  return lval;
+  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_truncate (GString* fstring,
-                  gint len)
+/* 31 bit hash function */
+guint
+g_string_hash (const GString *str)
 {
-  GRealString *string = (GRealString*)fstring;
+  const gchar *p = str->str;
+  gint n = str->len;
+  guint h = 0;
 
-  g_return_val_if_fail (string != NULL, NULL);
-
-  string->len = len;
-
-  string->str[len] = 0;
+  while (n--)
+    {
+      h = (h << 5) - h + *p;
+      p++;
+    }
 
-  return fstring;
+  return h;
 }
 
 GString*
-g_string_append (GString *fstring,
-                const gchar *val)
+g_string_assign (GString     *string,
+                const gchar *rval)
 {
-  GRealString *string = (GRealString*)fstring;
-  int len;
-
   g_return_val_if_fail (string != NULL, NULL);
-  g_return_val_if_fail (val != NULL, fstring);
+  g_return_val_if_fail (rval != NULL, string);
   
-  len = strlen (val);
-  g_string_maybe_expand (string, len);
-
-  strcpy (string->str + string->len, val);
-
-  string->len += len;
+  g_string_truncate (string, 0);
+  g_string_append (string, rval);
 
-  return fstring;
+  return string;
 }
 
 GString*
-g_string_append_c (GString *fstring,
-                  gchar c)
+g_string_truncate (GString *fstring,
+                  guint    len)
 {
-  GRealString *string = (GRealString*)fstring;
+  GRealString *string = (GRealString *) fstring;
 
   g_return_val_if_fail (string != NULL, NULL);
-  g_string_maybe_expand (string, 1);
 
-  string->str[string->len++] = c;
+  string->len = MIN (len, string->len);
+
   string->str[string->len] = 0;
 
   return fstring;
 }
 
 GString*
-g_string_prepend (GString *fstring,
-                 const gchar *val)
+g_string_insert_len (GString     *fstring,
+                    gint         pos,
+                    const gchar *val,
+                    gint         len)
 {
-  GRealString *string = (GRealString*)fstring;
-  gint len;
+  GRealString *string = (GRealString *) fstring;
 
   g_return_val_if_fail (string != NULL, NULL);
   g_return_val_if_fail (val != NULL, fstring);
+  g_return_val_if_fail (pos <= string->len, fstring);
 
-  len = strlen (val);
-  g_string_maybe_expand (string, len);
+  if (len < 0)
+    len = strlen (val);
 
-  g_memmove (string->str + len, string->str, string->len);
+  if (pos < 0)
+    pos = string->len;
+  
+  g_string_maybe_expand (string, len);
 
-  strncpy (string->str, val, 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);
 
   string->len += len;
 
@@ -345,23 +372,63 @@ g_string_prepend (GString *fstring,
 }
 
 GString*
-g_string_prepend_c (GString *fstring,
-                   gchar    c)
-{
-  GRealString *string = (GRealString*)fstring;
+g_string_append (GString     *fstring,
+                const gchar *val)
+{  
+  g_return_val_if_fail (fstring != NULL, NULL);
+  g_return_val_if_fail (val != NULL, fstring);
+
+  return g_string_insert_len (fstring, -1, val, -1);
+}
 
+GString*
+g_string_append_len (GString    *string,
+                     const gchar *val,
+                     gint         len)
+{
   g_return_val_if_fail (string != NULL, NULL);
-  g_string_maybe_expand (string, 1);
+  g_return_val_if_fail (val != NULL, string);
 
-  g_memmove (string->str + 1, string->str, string->len);
+  return g_string_insert_len (string, -1, val, len);
+}
 
-  string->str[0] = c;
+GString*
+g_string_append_c (GString *fstring,
+                  gchar    c)
+{
+  g_return_val_if_fail (fstring != NULL, NULL);
 
-  string->len += 1;
+  return g_string_insert_c (fstring, -1, c);
+}
 
-  string->str[string->len] = 0;
+GString*
+g_string_prepend (GString     *fstring,
+                 const gchar *val)
+{
+  g_return_val_if_fail (fstring != NULL, NULL);
+  g_return_val_if_fail (val != NULL, fstring);
+  
+  return g_string_insert_len (fstring, 0, val, -1);
+}
 
-  return fstring;
+GString*
+g_string_prepend_len (GString    *string,
+                      const gchar *val,
+                      gint         len)
+{
+  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (val != NULL, string);
+
+  return g_string_insert_len (string, 0, val, len);
+}
+
+GString*
+g_string_prepend_c (GString *fstring,
+                   gchar    c)
+{  
+  g_return_val_if_fail (fstring != NULL, NULL);
+  
+  return g_string_insert_c (fstring, 0, c);
 }
 
 GString*
@@ -369,41 +436,31 @@ g_string_insert (GString     *fstring,
                 gint         pos,
                 const gchar *val)
 {
-  GRealString *string = (GRealString*)fstring;
-  gint len;
-
-  g_return_val_if_fail (string != NULL, NULL);
+  g_return_val_if_fail (fstring != NULL, NULL);
   g_return_val_if_fail (val != NULL, fstring);
-  g_return_val_if_fail (pos >= 0, fstring);
-  g_return_val_if_fail (pos <= string->len, fstring);
-
-  len = strlen (val);
-  g_string_maybe_expand (string, len);
-
-  g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
-
-  strncpy (string->str + pos, val, len);
-
-  string->len += len;
-
-  string->str[string->len] = 0;
-
-  return fstring;
+  g_return_val_if_fail (pos <= fstring->len, fstring);
+  
+  return g_string_insert_len (fstring, pos, val, -1);
 }
 
-GString *
+GString*
 g_string_insert_c (GString *fstring,
                   gint     pos,
                   gchar    c)
 {
-  GRealString *string = (GRealString*)fstring;
+  GRealString *string = (GRealString *) fstring;
 
   g_return_val_if_fail (string != NULL, NULL);
   g_return_val_if_fail (pos <= string->len, fstring);
 
   g_string_maybe_expand (string, 1);
 
-  g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
+  if (pos < 0)
+    pos = string->len;
+  
+  /* If not just an append, move the old stuff */
+  if (pos < string->len)
+    g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
 
   string->str[pos] = c;
 
@@ -416,8 +473,8 @@ g_string_insert_c (GString *fstring,
 
 GString*
 g_string_erase (GString *fstring,
-               gint pos,
-               gint len)
+               gint     pos,
+               gint     len)
 {
   GRealString *string = (GRealString*)fstring;
 
@@ -440,17 +497,19 @@ g_string_erase (GString *fstring,
 GString*
 g_string_down (GString *fstring)
 {
-  GRealString *string = (GRealString*)fstring;
-  gchar *s;
+  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;
@@ -459,17 +518,19 @@ g_string_down (GString *fstring)
 GString*
 g_string_up (GString *fstring)
 {
-  GRealString *string = (GRealString*)fstring;
-  gchar *s;
+  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;