2006-08-19 Aaron Bockover <abockover@novell.com>
[mono.git] / eglib / src / gstring.c
index ae0ff39abe2717309ab8b14d103e84f8f5bff16a..f5d899d2755e0258cee9957a7a5bdd37dac2b462 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Author:
  *   Miguel de Icaza (miguel@novell.com)
+ *   Aaron Bockover (abockover@novell.com)
  *
  * (C) 2006 Novell, Inc.
  *
 #include <stdio.h>
 #include <glib.h>
 
-GString *
-g_string_new (const gchar *init)
-{
-       GString *ret = g_new (GString, 1);
-       int len, alloc;
-
-       len = strlen (init);
-       if (len < 15)
-               alloc = 16;
-       else
-               alloc = len+1;
-       ret->str = g_malloc (alloc);
-       ret->len = len;
-       ret->allocated_len = alloc;
-       strcpy (ret->str, init);
-
-       return ret;
+#define GROW_IF_NECESSARY(s,l) { \
+       if(s->len + l >= s->allocated_len) { \
+               s->allocated_len = (s->allocated_len + l + 16) * 2; \
+               s->str = g_realloc(s->str, s->allocated_len); \
+       } \
 }
 
 GString *
@@ -53,16 +42,21 @@ g_string_new_len (const gchar *init, gssize len)
 {
        GString *ret = g_new (GString, 1);
 
-       ret->str = g_malloc (len+1);
-       ret->allocated_len = len + 1;
-       ret->len = len;
+       ret->len = len < 0 ? strlen(init) : len;
+       ret->allocated_len = MAX(ret->len + 1, 16);
+       ret->str = g_malloc(ret->allocated_len);
+       memcpy(ret->str, init, ret->len);
+       ret->str[ret->len] = 0;
 
-       memcpy (ret->str, init, len);
-       ret->str [len] = 0;
-       
        return ret;
 }
 
+GString *
+g_string_new (const gchar *init)
+{
+       return g_string_new_len(init, -1);
+}
+
 GString *
 g_string_sized_new (gsize default_size)
 {
@@ -79,106 +73,79 @@ g_string_sized_new (gsize default_size)
 gchar *
 g_string_free (GString *string, gboolean free_segment)
 {
-       char *data;
+       gchar *data;
+       
        g_return_val_if_fail (string != NULL, NULL);
 
        data = string->str;
-       if (free_segment)
-               g_free (data);
-       g_free (string);
-
-       if (free_segment)
-               return NULL;
-       else
-               return data;
+       g_free(string);
        
+       if(!free_segment) {
+               return data;
+       }
+
+       g_free(data);
+       return NULL;
 }
 
 GString *
-g_string_append (GString *string, const gchar *val)
+g_string_append_len (GString *string, const gchar *val, gssize len)
 {
-       int len, size;
-       char *new;
-       
-       g_return_val_if_fail (string != NULL, NULL);
-       g_return_val_if_fail (val != NULL, string);
-       
-       len = strlen (val);
-       if ((string->len + len) < string->allocated_len){
-               strcat (string->str, val);
-               string->len += len;
-               return string;
+       g_return_val_if_fail(string != NULL, NULL);
+       g_return_val_if_fail(val != NULL, string);
+
+       if(len < 0) {
+               len = strlen(val);
        }
-       size = (len + string->len + 16) * 2;
-       new = g_malloc (size);
-       memcpy (new, string->str, string->len);
-       memcpy (new + string->len, val, len);
-       g_free (string->str);
-       string->str = new;
-       string->allocated_len = size;
+
+       GROW_IF_NECESSARY(string, len);
+       memcpy(string->str + string->len, val, len);
        string->len += len;
-       new [string->len] = 0;
-       
+       string->str[string->len] = 0;
+
        return string;
 }
 
+GString *
+g_string_append (GString *string, const gchar *val)
+{
+       g_return_val_if_fail(string != NULL, NULL);
+       g_return_val_if_fail(val != NULL, string);
+
+       return g_string_append_len(string, val, -1);
+}
+
 GString *
 g_string_append_c (GString *string, gchar c)
 {
-       gsize size;
-       char *new;
-       
-       g_return_val_if_fail (string != NULL, NULL);
+       g_return_val_if_fail(string != NULL, NULL);
 
-       if (string->len + 1 < string->allocated_len){
-               string->str [string->len] = c;
-               string->str [string->len+1] = 0;
-               string->len++;
-               return string;
-       }
-       size = (string->allocated_len + 16) * 2;
-       new = g_malloc (size);
-       memcpy (new, string->str, string->len);
-       new [string->len] = c;
-       new [string->len+1] = 0;
+       GROW_IF_NECESSARY(string, 1);
        
-       g_free (string->str);
-       string->allocated_len = size;
+       string->str[string->len] = c;
+       string->str[string->len + 1] = 0;
        string->len++;
-       string->str = new;
 
        return string;
 }
 
 GString *
-g_string_append_len (GString *string, const gchar *val, gssize len)
+g_string_prepend (GString *string, const gchar *val)
 {
-       int size;
-       char *new;
+       gssize len;
        
-       g_return_val_if_fail (string != NULL, NULL);
+       g_return_val_if_fail (string != NULL, string);
        g_return_val_if_fail (val != NULL, string);
-       if (len < 0)
-               return g_string_append (string, val);
-       
-       if ((string->len + len) < string->allocated_len){
-               memcpy (string->str+string->len, val, len);
-               string->len += len;
-               return string;
-       }
-       size = (len + string->len + 16) * 2;
-       new = g_malloc (size);
-       memcpy (new, string->str, string->len);
-       memcpy (new + string->len, val, len);
-       g_free (string->str);
-       string->str = new;
-       string->allocated_len = size;
-       string->len += len;
-       new [string->len] = 0;
+
+       len = strlen (val);
        
+       GROW_IF_NECESSARY(string, len); 
+       memmove(string->str + len, string->str, string->len + 1);
+       memcpy(string->str, val, len);
+
        return string;
 }
-       
+
 void
 g_string_append_printf (GString *string, const gchar *format, ...)
 {
@@ -220,52 +187,12 @@ g_string_truncate (GString *string, gsize len)
        g_return_val_if_fail (string != NULL, string);
 
        /* Silent return */
-       if (len < 0)
-               return string;
-       
-       if (len >= string->len)
+       if (len < 0 || len >= string->len) {
                return string;
-       string->len = len;
-       string->str [len] = 0;
-       return string;
-}
-
-GString *
-g_string_prepend (GString *string, const gchar *val)
-{
-       int vallen;
-       g_return_val_if_fail (string != NULL, string);
-       g_return_val_if_fail (val != NULL, string);
-
-       vallen = strlen (val);
-       
-       if ((string->len + vallen + 1) < string->allocated_len){
-               memmove (string->str+vallen, string->str, string->len+1);
-               memcpy (string->str, val, vallen);
-       } else {
-               /*
-                * Add some extra space, so we do not reallocate too often
-                * maybe we should centralize this decision somewhere else. 
-                */
-               char *new;
-               int nl = MAX (string->len + vallen + 1, string->allocated_len);
-               nl = nl < 8192 ? (nl * 3) : nl + 1024;
-
-               new = malloc (nl);
-               /* Failure */
-               if (new == NULL) {
-                       g_error ("No more memory");
-                       return string;
-               }
-               strcpy (new, val);
-               /* To cope with embedded nulls */
-               memcpy (new + vallen, string->str, string->len);
-               string->len = string->len + vallen;
-               g_free (string->str);
-               string->str = new;
-               string->allocated_len = nl;
        }
        
+       string->len = len;
+       string->str[len] = 0;
        return string;
 }