glib/libglib/src/gstring.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* GLIB - Library of useful routines for C programming
       
     2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
       
     3  * Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
       
     4  *
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Lesser General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Lesser General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Lesser General Public
       
    16  * License along with this library; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 /*
       
    22  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
       
    23  * file for a list of people on the GLib Team.  See the ChangeLog
       
    24  * files for a list of changes.  These files are distributed with
       
    25  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
       
    26  */
       
    27 
       
    28 /* 
       
    29  * MT safe
       
    30  */
       
    31 
       
    32 #include "config.h"
       
    33 
       
    34 #ifdef HAVE_UNISTD_H
       
    35 #include <unistd.h>
       
    36 #endif
       
    37 #include <stdarg.h>
       
    38 #include <stdlib.h>
       
    39 #include <stdio.h>
       
    40 #include <string.h>
       
    41 #include <ctype.h>
       
    42 
       
    43 #include "glib.h"
       
    44 #include "gprintf.h"
       
    45 
       
    46 #include "galias.h"
       
    47 
       
    48 struct _GStringChunk
       
    49 {
       
    50   GHashTable *const_table;
       
    51   GSList     *storage_list;
       
    52   gsize       storage_next;    
       
    53   gsize       this_size;       
       
    54   gsize       default_size;    
       
    55 };
       
    56 
       
    57 /* Hash Functions.
       
    58  */
       
    59 
       
    60 /**
       
    61  * g_str_equal:
       
    62  * @v1: a key. 
       
    63  * @v2: a key to compare with @v1.
       
    64  * 
       
    65  * Compares two strings and returns %TRUE if they are equal.
       
    66  * It can be passed to g_hash_table_new() as the @key_equal_func
       
    67  * parameter, when using strings as keys in a #GHashTable.
       
    68  *
       
    69  * Returns: %TRUE if the two keys match.
       
    70  */
       
    71 EXPORT_C gboolean
       
    72 g_str_equal (gconstpointer v1,
       
    73 	     gconstpointer v2)
       
    74 {
       
    75   const gchar *string1 = v1;
       
    76   const gchar *string2 = v2;
       
    77   
       
    78   return strcmp (string1, string2) == 0;
       
    79 }
       
    80 
       
    81 /**
       
    82  * g_str_hash:
       
    83  * @v: a string key.
       
    84  *
       
    85  * Converts a string to a hash value.
       
    86  * It can be passed to g_hash_table_new() as the @hash_func parameter, 
       
    87  * when using strings as keys in a #GHashTable.
       
    88  *
       
    89  * Returns: a hash value corresponding to the key.
       
    90  */
       
    91 EXPORT_C guint
       
    92 g_str_hash (gconstpointer v)
       
    93 {
       
    94   /* 31 bit hash function */
       
    95   const signed char *p = v;
       
    96   guint32 h = *p;
       
    97 
       
    98   if (h)
       
    99     for (p += 1; *p != '\0'; p++)
       
   100       h = (h << 5) - h + *p;
       
   101 
       
   102   return h;
       
   103 }
       
   104 
       
   105 #define MY_MAXSIZE ((gsize)-1)
       
   106 
       
   107 static inline gsize
       
   108 nearest_power (gsize base, gsize num)    
       
   109 {
       
   110   if (num > MY_MAXSIZE / 2)
       
   111     {
       
   112       return MY_MAXSIZE;
       
   113     }
       
   114   else
       
   115     {
       
   116       gsize n = base;
       
   117 
       
   118       while (n < num)
       
   119 	n <<= 1;
       
   120       
       
   121       return n;
       
   122     }
       
   123 }
       
   124 
       
   125 /* String Chunks.
       
   126  */
       
   127 
       
   128 EXPORT_C GStringChunk*
       
   129 g_string_chunk_new (gsize default_size)    
       
   130 {
       
   131   GStringChunk *new_chunk = g_new (GStringChunk, 1);
       
   132   gsize size = 1;
       
   133   size = nearest_power (1, default_size);
       
   134 
       
   135   new_chunk->const_table       = NULL;
       
   136   new_chunk->storage_list      = NULL;
       
   137   new_chunk->storage_next      = size;
       
   138   new_chunk->default_size      = size;
       
   139   new_chunk->this_size         = size;
       
   140 
       
   141   return new_chunk;
       
   142 }
       
   143 
       
   144 EXPORT_C void
       
   145 g_string_chunk_free (GStringChunk *chunk)
       
   146 {
       
   147   GSList *tmp_list;
       
   148 
       
   149   g_return_if_fail (chunk != NULL);
       
   150 
       
   151   if (chunk->storage_list)
       
   152     {
       
   153       for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
       
   154 	g_free (tmp_list->data);
       
   155 
       
   156       g_slist_free (chunk->storage_list);
       
   157     }
       
   158 
       
   159   if (chunk->const_table)
       
   160     g_hash_table_destroy (chunk->const_table);
       
   161 
       
   162   g_free (chunk);
       
   163 }
       
   164 
       
   165 EXPORT_C gchar*
       
   166 g_string_chunk_insert (GStringChunk *chunk,
       
   167 		       const gchar  *string)
       
   168 {
       
   169   g_return_val_if_fail (chunk != NULL, NULL);
       
   170 
       
   171   return g_string_chunk_insert_len (chunk, string, -1);
       
   172 }
       
   173 
       
   174 EXPORT_C gchar*
       
   175 g_string_chunk_insert_const (GStringChunk *chunk,
       
   176 			     const gchar  *string)
       
   177 {
       
   178   char* lookup;
       
   179 
       
   180   g_return_val_if_fail (chunk != NULL, NULL);
       
   181 
       
   182   if (!chunk->const_table)
       
   183     chunk->const_table = g_hash_table_new (g_str_hash, g_str_equal);
       
   184 
       
   185   lookup = (char*) g_hash_table_lookup (chunk->const_table, (gchar *)string);
       
   186 
       
   187   if (!lookup)
       
   188     {
       
   189       lookup = g_string_chunk_insert (chunk, string);
       
   190       g_hash_table_insert (chunk->const_table, lookup, lookup);
       
   191     }
       
   192 
       
   193   return lookup;
       
   194 }
       
   195 
       
   196 /**
       
   197  * g_string_chunk_insert_len:
       
   198  * @chunk: a #GStringChunk
       
   199  * @string: bytes to insert
       
   200  * @len: number of bytes of @string to insert, or -1 to insert a 
       
   201  *     nul-terminated string. 
       
   202  * 
       
   203  * Adds a copy of the first @len bytes of @string to the #GStringChunk. The
       
   204  * copy is nul-terminated.
       
   205  * 
       
   206  * The characters in the string can be changed, if necessary, though you
       
   207  * should not change anything after the end of the string.
       
   208  * 
       
   209  * Return value: a pointer to the copy of @string within the #GStringChunk
       
   210  * 
       
   211  * Since: 2.4
       
   212  **/
       
   213 EXPORT_C gchar*
       
   214 g_string_chunk_insert_len (GStringChunk *chunk,
       
   215 			   const gchar  *string, 
       
   216 			   gssize        len)
       
   217 {
       
   218   gssize size;
       
   219   gchar* pos;
       
   220   g_return_val_if_fail (chunk != NULL, NULL);
       
   221 
       
   222   if (len < 0)
       
   223     size = strlen (string);
       
   224   else
       
   225     size = len;
       
   226   
       
   227   if ((chunk->storage_next + size + 1) > chunk->this_size)
       
   228     {
       
   229       gsize new_size = nearest_power (chunk->default_size, size + 1);
       
   230       chunk->storage_list = g_slist_prepend (chunk->storage_list,
       
   231 					     g_new (gchar, new_size));
       
   232       chunk->this_size = new_size;
       
   233       chunk->storage_next = 0;
       
   234     }
       
   235 
       
   236   pos = ((gchar *) chunk->storage_list->data) + chunk->storage_next;
       
   237 
       
   238   *(pos + size) = '\0';
       
   239 
       
   240   strncpy (pos, string, size);
       
   241   if (len > 0)
       
   242     size = strlen (pos);
       
   243 
       
   244   chunk->storage_next += size + 1;
       
   245 
       
   246   return pos;
       
   247 }
       
   248 
       
   249 /* Strings.
       
   250  */
       
   251 static void
       
   252 g_string_maybe_expand (GString* string,
       
   253 		       gsize    len) 
       
   254 {
       
   255   if (string->len + len >= string->allocated_len)
       
   256     {
       
   257       string->allocated_len = nearest_power (1, string->len + len + 1); 
       
   258       string->str = g_realloc (string->str, string->allocated_len);
       
   259     }
       
   260 }
       
   261 
       
   262 EXPORT_C GString*
       
   263 g_string_sized_new (gsize dfl_size)    
       
   264 {
       
   265   GString *string = g_slice_new (GString);
       
   266   
       
   267   string->allocated_len = 0;
       
   268   string->len   = 0;
       
   269   string->str   = NULL;
       
   270 
       
   271   g_string_maybe_expand (string, MAX (dfl_size, 2));
       
   272   string->str[0] = 0;
       
   273 
       
   274   return string;
       
   275 }
       
   276 
       
   277 EXPORT_C GString*
       
   278 g_string_new (const gchar *init)
       
   279 {
       
   280   GString *string;
       
   281 
       
   282   if (init == NULL || *init == '\0')
       
   283     string = g_string_sized_new (2);
       
   284   else 
       
   285     {
       
   286       gint len;
       
   287 
       
   288       len = strlen (init);
       
   289       string = g_string_sized_new (len + 2);
       
   290 
       
   291       g_string_append_len (string, init, len);
       
   292     }
       
   293 
       
   294   return string;
       
   295 }
       
   296 
       
   297 EXPORT_C GString*
       
   298 g_string_new_len (const gchar *init,
       
   299                   gssize       len)    
       
   300 {
       
   301   GString *string;
       
   302 
       
   303   if (len < 0)
       
   304     return g_string_new (init);
       
   305   else
       
   306     {
       
   307       string = g_string_sized_new (len);
       
   308       
       
   309       if (init)
       
   310         g_string_append_len (string, init, len);
       
   311       
       
   312       return string;
       
   313     }
       
   314 }
       
   315 
       
   316 EXPORT_C gchar*
       
   317 g_string_free (GString *string,
       
   318 	       gboolean free_segment)
       
   319 {
       
   320   gchar *segment;
       
   321 
       
   322   g_return_val_if_fail (string != NULL, NULL);
       
   323 
       
   324   if (free_segment)
       
   325     {
       
   326       g_free (string->str);
       
   327       segment = NULL;
       
   328     }
       
   329   else
       
   330     segment = string->str;
       
   331 
       
   332   g_slice_free (GString, string);
       
   333 
       
   334   return segment;
       
   335 }
       
   336 
       
   337 EXPORT_C gboolean
       
   338 g_string_equal (const GString *v,
       
   339                 const GString *v2)
       
   340 {
       
   341   gchar *p, *q;
       
   342   GString *string1 = (GString *) v;
       
   343   GString *string2 = (GString *) v2;
       
   344   gsize i = string1->len;    
       
   345 
       
   346   if (i != string2->len)
       
   347     return FALSE;
       
   348 
       
   349   p = string1->str;
       
   350   q = string2->str;
       
   351   while (i)
       
   352     {
       
   353       if (*p != *q)
       
   354 	return FALSE;
       
   355       p++;
       
   356       q++;
       
   357       i--;
       
   358     }
       
   359   return TRUE;
       
   360 }
       
   361 
       
   362 /* 31 bit hash function */
       
   363 EXPORT_C guint
       
   364 g_string_hash (const GString *str)
       
   365 {
       
   366   const gchar *p = str->str;
       
   367   gsize n = str->len;    
       
   368   guint h = 0;
       
   369 
       
   370   while (n--)
       
   371     {
       
   372       h = (h << 5) - h + *p;
       
   373       p++;
       
   374     }
       
   375 
       
   376   return h;
       
   377 }
       
   378 
       
   379 EXPORT_C GString*
       
   380 g_string_assign (GString     *string,
       
   381 		 const gchar *rval)
       
   382 {
       
   383   g_return_val_if_fail (string != NULL, NULL);
       
   384   g_return_val_if_fail (rval != NULL, string);
       
   385 
       
   386   /* Make sure assigning to itself doesn't corrupt the string.  */
       
   387   if (string->str != rval)
       
   388     {
       
   389       /* Assigning from substring should be ok since g_string_truncate
       
   390 	 does not realloc.  */
       
   391       g_string_truncate (string, 0);
       
   392       g_string_append (string, rval);
       
   393     }
       
   394 
       
   395   return string;
       
   396 }
       
   397 
       
   398 EXPORT_C GString*
       
   399 g_string_truncate (GString *string,
       
   400 		   gsize    len)    
       
   401 {
       
   402   g_return_val_if_fail (string != NULL, NULL);
       
   403 
       
   404   string->len = MIN (len, string->len);
       
   405   string->str[string->len] = 0;
       
   406 
       
   407   return string;
       
   408 }
       
   409 
       
   410 /**
       
   411  * g_string_set_size:
       
   412  * @string: a #GString
       
   413  * @len: the new length
       
   414  * 
       
   415  * Sets the length of a #GString. If the length is less than
       
   416  * the current length, the string will be truncated. If the
       
   417  * length is greater than the current length, the contents
       
   418  * of the newly added area are undefined. (However, as
       
   419  * always, string->str[string->len] will be a nul byte.) 
       
   420  * 
       
   421  * Return value: @string
       
   422  **/
       
   423 EXPORT_C GString*
       
   424 g_string_set_size (GString *string,
       
   425 		   gsize    len)    
       
   426 {
       
   427   g_return_val_if_fail (string != NULL, NULL);
       
   428 
       
   429   if (len >= string->allocated_len)
       
   430     g_string_maybe_expand (string, len - string->len);
       
   431   
       
   432   string->len = len;
       
   433   string->str[len] = 0;
       
   434 
       
   435   return string;
       
   436 }
       
   437 
       
   438 EXPORT_C GString*
       
   439 g_string_insert_len (GString     *string,
       
   440 		     gssize       pos,    
       
   441 		     const gchar *val,
       
   442 		     gssize       len)    
       
   443 {
       
   444   g_return_val_if_fail (string != NULL, NULL);
       
   445   g_return_val_if_fail (val != NULL, string);
       
   446 
       
   447   if (len < 0)
       
   448     len = strlen (val);
       
   449 
       
   450   if (pos < 0)
       
   451     pos = string->len;
       
   452   else
       
   453     g_return_val_if_fail (pos <= string->len, string);
       
   454 
       
   455   /* Check whether val represents a substring of string.  This test
       
   456      probably violates chapter and verse of the C standards, since
       
   457      ">=" and "<=" are only valid when val really is a substring.
       
   458      In practice, it will work on modern archs.  */
       
   459   if (val >= string->str && val <= string->str + string->len)
       
   460     {
       
   461       gsize offset = val - string->str;
       
   462       gsize precount = 0;
       
   463 
       
   464       g_string_maybe_expand (string, len);
       
   465       val = string->str + offset;
       
   466       /* At this point, val is valid again.  */
       
   467 
       
   468       /* Open up space where we are going to insert.  */
       
   469       if (pos < string->len)
       
   470 	g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
       
   471 
       
   472       /* Move the source part before the gap, if any.  */
       
   473       if (offset < pos)
       
   474 	{
       
   475 	  precount = MIN (len, pos - offset);
       
   476 	  memcpy (string->str + pos, val, precount);
       
   477 	}
       
   478 
       
   479       /* Move the source part after the gap, if any.  */
       
   480       if (len > precount)
       
   481 	memcpy (string->str + pos + precount,
       
   482 		val + /* Already moved: */ precount + /* Space opened up: */ len,
       
   483 		len - precount);
       
   484     }
       
   485   else
       
   486     {
       
   487       g_string_maybe_expand (string, len);
       
   488 
       
   489       /* If we aren't appending at the end, move a hunk
       
   490        * of the old string to the end, opening up space
       
   491        */
       
   492       if (pos < string->len)
       
   493 	g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
       
   494 
       
   495       /* insert the new string */
       
   496       if (len == 1)
       
   497         string->str[pos] = *val;
       
   498       else
       
   499         memcpy (string->str + pos, val, len);
       
   500     }
       
   501 
       
   502   string->len += len;
       
   503 
       
   504   string->str[string->len] = 0;
       
   505 
       
   506   return string;
       
   507 }
       
   508 
       
   509 EXPORT_C GString*
       
   510 g_string_append (GString     *string,
       
   511 		 const gchar *val)
       
   512 {  
       
   513   g_return_val_if_fail (string != NULL, NULL);
       
   514   g_return_val_if_fail (val != NULL, string);
       
   515 
       
   516   return g_string_insert_len (string, -1, val, -1);
       
   517 }
       
   518 
       
   519 EXPORT_C GString*
       
   520 g_string_append_len (GString	 *string,
       
   521                      const gchar *val,
       
   522                      gssize       len)    
       
   523 {
       
   524   g_return_val_if_fail (string != NULL, NULL);
       
   525   g_return_val_if_fail (val != NULL, string);
       
   526 
       
   527   return g_string_insert_len (string, -1, val, len);
       
   528 }
       
   529 
       
   530 #undef g_string_append_c
       
   531 EXPORT_C GString*
       
   532 g_string_append_c (GString *string,
       
   533 		   gchar    c)
       
   534 {
       
   535   g_return_val_if_fail (string != NULL, NULL);
       
   536 
       
   537   return g_string_insert_c (string, -1, c);
       
   538 }
       
   539 
       
   540 /**
       
   541  * g_string_append_unichar:
       
   542  * @string: a #GString
       
   543  * @wc: a Unicode character
       
   544  * 
       
   545  * Converts a Unicode character into UTF-8, and appends it
       
   546  * to the string.
       
   547  * 
       
   548  * Return value: @string
       
   549  **/
       
   550 EXPORT_C GString*
       
   551 g_string_append_unichar (GString  *string,
       
   552 			 gunichar  wc)
       
   553 {  
       
   554   g_return_val_if_fail (string != NULL, NULL);
       
   555   
       
   556   return g_string_insert_unichar (string, -1, wc);
       
   557 }
       
   558 
       
   559 EXPORT_C GString*
       
   560 g_string_prepend (GString     *string,
       
   561 		  const gchar *val)
       
   562 {
       
   563   g_return_val_if_fail (string != NULL, NULL);
       
   564   g_return_val_if_fail (val != NULL, string);
       
   565   
       
   566   return g_string_insert_len (string, 0, val, -1);
       
   567 }
       
   568 
       
   569 EXPORT_C GString*
       
   570 g_string_prepend_len (GString	  *string,
       
   571                       const gchar *val,
       
   572                       gssize       len)    
       
   573 {
       
   574   g_return_val_if_fail (string != NULL, NULL);
       
   575   g_return_val_if_fail (val != NULL, string);
       
   576 
       
   577   return g_string_insert_len (string, 0, val, len);
       
   578 }
       
   579 
       
   580 EXPORT_C GString*
       
   581 g_string_prepend_c (GString *string,
       
   582 		    gchar    c)
       
   583 {  
       
   584   g_return_val_if_fail (string != NULL, NULL);
       
   585   
       
   586   return g_string_insert_c (string, 0, c);
       
   587 }
       
   588 
       
   589 /**
       
   590  * g_string_prepend_unichar:
       
   591  * @string: a #GString.
       
   592  * @wc: a Unicode character.
       
   593  * 
       
   594  * Converts a Unicode character into UTF-8, and prepends it
       
   595  * to the string.
       
   596  * 
       
   597  * Return value: @string.
       
   598  **/
       
   599 EXPORT_C GString*
       
   600 g_string_prepend_unichar (GString  *string,
       
   601 			  gunichar  wc)
       
   602 {  
       
   603   g_return_val_if_fail (string != NULL, NULL);
       
   604   
       
   605   return g_string_insert_unichar (string, 0, wc);
       
   606 }
       
   607 
       
   608 EXPORT_C GString*
       
   609 g_string_insert (GString     *string,
       
   610 		 gssize       pos,    
       
   611 		 const gchar *val)
       
   612 {
       
   613   g_return_val_if_fail (string != NULL, NULL);
       
   614   g_return_val_if_fail (val != NULL, string);
       
   615   if (pos >= 0)
       
   616     g_return_val_if_fail (pos <= string->len, string);
       
   617   
       
   618   return g_string_insert_len (string, pos, val, -1);
       
   619 }
       
   620 
       
   621 EXPORT_C GString*
       
   622 g_string_insert_c (GString *string,
       
   623 		   gssize   pos,    
       
   624 		   gchar    c)
       
   625 {
       
   626   g_return_val_if_fail (string != NULL, NULL);
       
   627 
       
   628   g_string_maybe_expand (string, 1);
       
   629 
       
   630   if (pos < 0)
       
   631     pos = string->len;
       
   632   else
       
   633     g_return_val_if_fail (pos <= string->len, string);
       
   634   
       
   635   /* If not just an append, move the old stuff */
       
   636   if (pos < string->len)
       
   637     g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
       
   638 
       
   639   string->str[pos] = c;
       
   640 
       
   641   string->len += 1;
       
   642 
       
   643   string->str[string->len] = 0;
       
   644 
       
   645   return string;
       
   646 }
       
   647 
       
   648 /**
       
   649  * g_string_insert_unichar:
       
   650  * @string: a #GString
       
   651  * @pos: the position at which to insert character, or -1 to
       
   652  *       append at the end of the string.
       
   653  * @wc: a Unicode character
       
   654  * 
       
   655  * Converts a Unicode character into UTF-8, and insert it
       
   656  * into the string at the given position.
       
   657  * 
       
   658  * Return value: @string
       
   659  **/
       
   660 EXPORT_C GString*
       
   661 g_string_insert_unichar (GString *string,
       
   662 			 gssize   pos,    
       
   663 			 gunichar wc)
       
   664 {
       
   665   gint charlen, first, i;
       
   666   gchar *dest;
       
   667 
       
   668   g_return_val_if_fail (string != NULL, NULL);
       
   669 
       
   670   /* Code copied from g_unichar_to_utf() */
       
   671   if (wc < 0x80)
       
   672     {
       
   673       first = 0;
       
   674       charlen = 1;
       
   675     }
       
   676   else if (wc < 0x800)
       
   677     {
       
   678       first = 0xc0;
       
   679       charlen = 2;
       
   680     }
       
   681   else if (wc < 0x10000)
       
   682     {
       
   683       first = 0xe0;
       
   684       charlen = 3;
       
   685     }
       
   686    else if (wc < 0x200000)
       
   687     {
       
   688       first = 0xf0;
       
   689       charlen = 4;
       
   690     }
       
   691   else if (wc < 0x4000000)
       
   692     {
       
   693       first = 0xf8;
       
   694       charlen = 5;
       
   695     }
       
   696   else
       
   697     {
       
   698       first = 0xfc;
       
   699       charlen = 6;
       
   700     }
       
   701   /* End of copied code */
       
   702 
       
   703   g_string_maybe_expand (string, charlen);
       
   704 
       
   705   if (pos < 0)
       
   706     pos = string->len;
       
   707   else
       
   708     g_return_val_if_fail (pos <= string->len, string);
       
   709 
       
   710   /* If not just an append, move the old stuff */
       
   711   if (pos < string->len)
       
   712     g_memmove (string->str + pos + charlen, string->str + pos, string->len - pos);
       
   713 
       
   714   dest = string->str + pos;
       
   715   /* Code copied from g_unichar_to_utf() */
       
   716   for (i = charlen - 1; i > 0; --i)
       
   717     {
       
   718       dest[i] = (wc & 0x3f) | 0x80;
       
   719       wc >>= 6;
       
   720     }
       
   721   dest[0] = wc | first;
       
   722   /* End of copied code */
       
   723   
       
   724   string->len += charlen;
       
   725 
       
   726   string->str[string->len] = 0;
       
   727 
       
   728   return string;
       
   729 }
       
   730 
       
   731 EXPORT_C GString*
       
   732 g_string_erase (GString *string,
       
   733 		gssize   pos,
       
   734 		gssize   len)
       
   735 {
       
   736   g_return_val_if_fail (string != NULL, NULL);
       
   737   g_return_val_if_fail (pos >= 0, string);
       
   738   g_return_val_if_fail (pos <= string->len, string);
       
   739 
       
   740   if (len < 0)
       
   741     len = string->len - pos;
       
   742   else
       
   743     {
       
   744       g_return_val_if_fail (pos + len <= string->len, string);
       
   745 
       
   746       if (pos + len < string->len)
       
   747 	g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
       
   748     }
       
   749 
       
   750   string->len -= len;
       
   751   
       
   752   string->str[string->len] = 0;
       
   753 
       
   754   return string;
       
   755 }
       
   756 
       
   757 /**
       
   758  * g_string_ascii_down:
       
   759  * @string: a GString
       
   760  * 
       
   761  * Converts all upper case ASCII letters to lower case ASCII letters.
       
   762  * 
       
   763  * Return value: passed-in @string pointer, with all the upper case
       
   764  *               characters converted to lower case in place, with
       
   765  *               semantics that exactly match g_ascii_tolower.
       
   766  **/
       
   767 EXPORT_C GString*
       
   768 g_string_ascii_down (GString *string)
       
   769 {
       
   770   gchar *s;
       
   771   gint n;
       
   772 
       
   773   g_return_val_if_fail (string != NULL, NULL);
       
   774 
       
   775   n = string->len;
       
   776   s = string->str;
       
   777 
       
   778   while (n)
       
   779     {
       
   780       *s = g_ascii_tolower (*s);
       
   781       s++;
       
   782       n--;
       
   783     }
       
   784 
       
   785   return string;
       
   786 }
       
   787 
       
   788 /**
       
   789  * g_string_ascii_up:
       
   790  * @string: a GString
       
   791  * 
       
   792  * Converts all lower case ASCII letters to upper case ASCII letters.
       
   793  * 
       
   794  * Return value: passed-in @string pointer, with all the lower case
       
   795  *               characters converted to upper case in place, with
       
   796  *               semantics that exactly match g_ascii_toupper.
       
   797  **/
       
   798 EXPORT_C GString*
       
   799 g_string_ascii_up (GString *string)
       
   800 {
       
   801   gchar *s;
       
   802   gint n;
       
   803 
       
   804   g_return_val_if_fail (string != NULL, NULL);
       
   805 
       
   806   n = string->len;
       
   807   s = string->str;
       
   808 
       
   809   while (n)
       
   810     {
       
   811       *s = g_ascii_toupper (*s);
       
   812       s++;
       
   813       n--;
       
   814     }
       
   815 
       
   816   return string;
       
   817 }
       
   818 
       
   819 /**
       
   820  * g_string_down:
       
   821  * @string: a #GString
       
   822  *  
       
   823  * Converts a #GString to lowercase.
       
   824  *
       
   825  * Returns: the #GString.
       
   826  *
       
   827  * Deprecated:2.2: This function uses the locale-specific tolower() function, 
       
   828  * which is almost never the right thing. Use g_string_ascii_down() or 
       
   829  * g_utf8_strdown() instead.
       
   830  */
       
   831 EXPORT_C GString*
       
   832 g_string_down (GString *string)
       
   833 {
       
   834   guchar *s;
       
   835   glong n;
       
   836 
       
   837   g_return_val_if_fail (string != NULL, NULL);
       
   838 
       
   839   n = string->len;    
       
   840   s = (guchar *) string->str;
       
   841 
       
   842   while (n)
       
   843     {
       
   844       if (isupper (*s))
       
   845 	*s = tolower (*s);
       
   846       s++;
       
   847       n--;
       
   848     }
       
   849 
       
   850   return string;
       
   851 }
       
   852 
       
   853 /**
       
   854  * g_string_up:
       
   855  * @string: a #GString 
       
   856  * 
       
   857  * Converts a #GString to uppercase.
       
   858  * 
       
   859  * Return value: the #GString
       
   860  *
       
   861  * Deprecated:2.2: This function uses the locale-specific toupper() function, 
       
   862  * which is almost never the right thing. Use g_string_ascii_up() or 
       
   863  * g_utf8_strup() instead.
       
   864  **/
       
   865 EXPORT_C GString*
       
   866 g_string_up (GString *string)
       
   867 {
       
   868   guchar *s;
       
   869   glong n;
       
   870 
       
   871   g_return_val_if_fail (string != NULL, NULL);
       
   872 
       
   873   n = string->len;
       
   874   s = (guchar *) string->str;
       
   875 
       
   876   while (n)
       
   877     {
       
   878       if (islower (*s))
       
   879 	*s = toupper (*s);
       
   880       s++;
       
   881       n--;
       
   882     }
       
   883 
       
   884   return string;
       
   885 }
       
   886 
       
   887 static void
       
   888 g_string_append_printf_internal (GString     *string,
       
   889 				 const gchar *fmt,
       
   890 				 va_list      args)
       
   891 {
       
   892   gchar *buffer;
       
   893   gint length;
       
   894   
       
   895   length = g_vasprintf (&buffer, fmt, args);
       
   896   g_string_append_len (string, buffer, length);
       
   897   g_free (buffer);
       
   898 }
       
   899 
       
   900 EXPORT_C void
       
   901 g_string_printf (GString *string,
       
   902 		 const gchar *fmt,
       
   903 		 ...)
       
   904 {
       
   905   va_list args;
       
   906 
       
   907   g_string_truncate (string, 0);
       
   908 
       
   909   va_start (args, fmt);
       
   910   g_string_append_printf_internal (string, fmt, args);
       
   911   va_end (args);
       
   912 }
       
   913 
       
   914 EXPORT_C void
       
   915 g_string_append_printf (GString *string,
       
   916 			const gchar *fmt,
       
   917 			...)
       
   918 {
       
   919   va_list args;
       
   920 
       
   921   va_start (args, fmt);
       
   922   g_string_append_printf_internal (string, fmt, args);
       
   923   va_end (args);
       
   924 }
       
   925 
       
   926 #define __G_STRING_C__
       
   927 #include "galiasdef.c"