Optimize the common cases (init == NULL or init == "") a bit. replace uses
[platform/upstream/glib.git] / glib / gstring.c
1 /* GLIB - Library of useful routines for C programming
2  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GLib Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GLib at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 /* 
28  * MT safe
29  */
30
31 #include "config.h"
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #include <stdarg.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <ctype.h>
41
42 #include "glib.h"
43
44
45 struct _GStringChunk
46 {
47   GHashTable *const_table;
48   GSList     *storage_list;
49   gsize       storage_next;    
50   gsize       this_size;       
51   gsize       default_size;    
52 };
53
54 G_LOCK_DEFINE_STATIC (string_mem_chunk);
55 static GMemChunk *string_mem_chunk = NULL;
56
57 /* Hash Functions.
58  */
59
60 gboolean
61 g_str_equal (gconstpointer v1,
62              gconstpointer v2)
63 {
64   const gchar *string1 = v1;
65   const gchar *string2 = v2;
66   
67   return strcmp (string1, string2) == 0;
68 }
69
70 /* 31 bit hash function */
71 guint
72 g_str_hash (gconstpointer key)
73 {
74   const char *p = key;
75   guint h = *p;
76
77   if (h)
78     for (p += 1; *p != '\0'; p++)
79       h = (h << 5) - h + *p;
80
81   return h;
82 }
83
84 #define MY_MAXSIZE ((gsize)-1)
85
86 static inline gsize
87 nearest_power (gsize base, gsize num)    
88 {
89   if (num > MY_MAXSIZE / 2)
90     {
91       return MY_MAXSIZE;
92     }
93   else
94     {
95       gsize n = base;
96
97       while (n < num)
98         n <<= 1;
99       
100       return n;
101     }
102 }
103
104 /* String Chunks.
105  */
106
107 GStringChunk*
108 g_string_chunk_new (gsize default_size)    
109 {
110   GStringChunk *new_chunk = g_new (GStringChunk, 1);
111   gsize size = 1;    
112
113   size = nearest_power (1, default_size);
114
115   new_chunk->const_table       = NULL;
116   new_chunk->storage_list      = NULL;
117   new_chunk->storage_next      = size;
118   new_chunk->default_size      = size;
119   new_chunk->this_size         = size;
120
121   return new_chunk;
122 }
123
124 void
125 g_string_chunk_free (GStringChunk *chunk)
126 {
127   GSList *tmp_list;
128
129   g_return_if_fail (chunk != NULL);
130
131   if (chunk->storage_list)
132     {
133       for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
134         g_free (tmp_list->data);
135
136       g_slist_free (chunk->storage_list);
137     }
138
139   if (chunk->const_table)
140     g_hash_table_destroy (chunk->const_table);
141
142   g_free (chunk);
143 }
144
145 gchar*
146 g_string_chunk_insert (GStringChunk *chunk,
147                        const gchar  *string)
148 {
149   gsize len = strlen (string);
150   char* pos;
151
152   g_return_val_if_fail (chunk != NULL, NULL);
153
154   if ((chunk->storage_next + len + 1) > chunk->this_size)
155     {
156       gsize new_size = nearest_power (chunk->default_size, len + 1);
157
158       chunk->storage_list = g_slist_prepend (chunk->storage_list,
159                                              g_new (char, new_size));
160
161       chunk->this_size = new_size;
162       chunk->storage_next = 0;
163     }
164
165   pos = ((char *) chunk->storage_list->data) + chunk->storage_next;
166
167   strcpy (pos, string);
168
169   chunk->storage_next += len + 1;
170
171   return pos;
172 }
173
174 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 /* Strings.
197  */
198 static void
199 g_string_maybe_expand (GString* string,
200                        gsize    len) 
201 {
202   if (string->len + len >= string->allocated_len)
203     {
204       string->allocated_len = nearest_power (1, string->len + len + 1);
205       string->str = g_realloc (string->str, string->allocated_len);
206     }
207 }
208
209 GString*
210 g_string_sized_new (gsize dfl_size)    
211 {
212   GString *string;
213
214   G_LOCK (string_mem_chunk);
215   if (!string_mem_chunk)
216     string_mem_chunk = g_mem_chunk_new ("string mem chunk",
217                                         sizeof (GString),
218                                         1024, G_ALLOC_AND_FREE);
219
220   string = g_chunk_new (GString, string_mem_chunk);
221   G_UNLOCK (string_mem_chunk);
222
223   string->allocated_len = 0;
224   string->len   = 0;
225   string->str   = NULL;
226
227   g_string_maybe_expand (string, MAX (dfl_size, 2));
228   string->str[0] = 0;
229
230   return string;
231 }
232
233 GString*
234 g_string_new (const gchar *init)
235 {
236   GString *string;
237
238   if (init == NULL || *init == '\0')
239     string = g_string_sized_new (2);
240   else 
241     {
242       gint len;
243
244       len = strlen (init);
245       string = g_string_sized_new (len + 2);
246
247       g_string_append_len (string, init, len);
248     }
249
250   return string;
251 }
252
253 GString*
254 g_string_new_len (const gchar *init,
255                   gssize       len)    
256 {
257   GString *string;
258
259   if (len < 0)
260     return g_string_new (init);
261   else
262     {
263       string = g_string_sized_new (len);
264       
265       if (init)
266         g_string_append_len (string, init, len);
267       
268       return string;
269     }
270 }
271
272 gchar*
273 g_string_free (GString *string,
274                gboolean free_segment)
275 {
276   gchar *segment;
277
278   g_return_val_if_fail (string != NULL, NULL);
279
280   if (free_segment)
281     {
282       g_free (string->str);
283       segment = NULL;
284     }
285   else
286     segment = string->str;
287
288   G_LOCK (string_mem_chunk);
289   g_mem_chunk_free (string_mem_chunk, string);
290   G_UNLOCK (string_mem_chunk);
291
292   return segment;
293 }
294
295 gboolean
296 g_string_equal (const GString *v,
297                 const GString *v2)
298 {
299   gchar *p, *q;
300   GString *string1 = (GString *) v;
301   GString *string2 = (GString *) v2;
302   gsize i = string1->len;    
303
304   if (i != string2->len)
305     return FALSE;
306
307   p = string1->str;
308   q = string2->str;
309   while (i)
310     {
311       if (*p != *q)
312         return FALSE;
313       p++;
314       q++;
315       i--;
316     }
317   return TRUE;
318 }
319
320 /* 31 bit hash function */
321 guint
322 g_string_hash (const GString *str)
323 {
324   const gchar *p = str->str;
325   gsize n = str->len;    
326   guint h = 0;
327
328   while (n--)
329     {
330       h = (h << 5) - h + *p;
331       p++;
332     }
333
334   return h;
335 }
336
337 GString*
338 g_string_assign (GString     *string,
339                  const gchar *rval)
340 {
341   g_return_val_if_fail (string != NULL, NULL);
342   g_return_val_if_fail (rval != NULL, string);
343   
344   g_string_truncate (string, 0);
345   g_string_append (string, rval);
346
347   return string;
348 }
349
350 GString*
351 g_string_truncate (GString *string,
352                    gsize    len)    
353 {
354   g_return_val_if_fail (string != NULL, NULL);
355
356   string->len = MIN (len, string->len);
357   string->str[string->len] = 0;
358
359   return string;
360 }
361
362 /**
363  * g_string_set_size:
364  * @string: a #GString
365  * @len: the new length
366  * 
367  * Sets the length of a #GString. If the length is less than
368  * the current length, the string will be truncated. If the
369  * length is greater than the current length, the contents
370  * of the newly added area are undefined. (However, as
371  * always, string->str[string->len] will be a nul byte.) 
372  * 
373  * Return value: @string
374  **/
375 GString*
376 g_string_set_size (GString *string,
377                    gsize    len)    
378 {
379   g_return_val_if_fail (string != NULL, NULL);
380
381   if (len >= string->allocated_len)
382     g_string_maybe_expand (string, len - string->len);
383   
384   string->len = len;
385   string->str[len] = 0;
386
387   return string;
388 }
389
390 GString*
391 g_string_insert_len (GString     *string,
392                      gssize       pos,    
393                      const gchar *val,
394                      gssize       len)    
395 {
396   g_return_val_if_fail (string != NULL, NULL);
397   g_return_val_if_fail (val != NULL, string);
398
399   if (len < 0)
400     len = strlen (val);
401
402   if (pos < 0)
403     pos = string->len;
404   else
405     g_return_val_if_fail (pos <= string->len, string);
406   
407   g_string_maybe_expand (string, len);
408
409   /* If we aren't appending at the end, move a hunk
410    * of the old string to the end, opening up space
411    */
412   if (pos < string->len)
413     g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
414   
415   /* insert the new string */
416   g_memmove (string->str + pos, val, len);
417
418   string->len += len;
419
420   string->str[string->len] = 0;
421
422   return string;
423 }
424
425 GString*
426 g_string_append (GString     *string,
427                  const gchar *val)
428 {  
429   g_return_val_if_fail (string != NULL, NULL);
430   g_return_val_if_fail (val != NULL, string);
431
432   return g_string_insert_len (string, -1, val, -1);
433 }
434
435 GString*
436 g_string_append_len (GString     *string,
437                      const gchar *val,
438                      gssize       len)    
439 {
440   g_return_val_if_fail (string != NULL, NULL);
441   g_return_val_if_fail (val != NULL, string);
442
443   return g_string_insert_len (string, -1, val, len);
444 }
445
446 GString*
447 g_string_append_c (GString *string,
448                    gchar    c)
449 {
450   g_return_val_if_fail (string != NULL, NULL);
451
452   return g_string_insert_c (string, -1, c);
453 }
454
455 /**
456  * g_string_append_unichar:
457  * @string: a #GString
458  * @wc: a Unicode character
459  * 
460  * Converts a Unicode character into UTF-8, and appends it
461  * to the string.
462  * 
463  * Return value: @string
464  **/
465 GString*
466 g_string_append_unichar (GString  *string,
467                          gunichar  wc)
468 {  
469   g_return_val_if_fail (string != NULL, NULL);
470   
471   return g_string_insert_unichar (string, -1, wc);
472 }
473
474 GString*
475 g_string_prepend (GString     *string,
476                   const gchar *val)
477 {
478   g_return_val_if_fail (string != NULL, NULL);
479   g_return_val_if_fail (val != NULL, string);
480   
481   return g_string_insert_len (string, 0, val, -1);
482 }
483
484 GString*
485 g_string_prepend_len (GString     *string,
486                       const gchar *val,
487                       gssize       len)    
488 {
489   g_return_val_if_fail (string != NULL, NULL);
490   g_return_val_if_fail (val != NULL, string);
491
492   return g_string_insert_len (string, 0, val, len);
493 }
494
495 GString*
496 g_string_prepend_c (GString *string,
497                     gchar    c)
498 {  
499   g_return_val_if_fail (string != NULL, NULL);
500   
501   return g_string_insert_c (string, 0, c);
502 }
503
504 /**
505  * g_string_prepend_unichar:
506  * @string: a #GString.
507  * @wc: a Unicode character.
508  * 
509  * Converts a Unicode character into UTF-8, and prepends it
510  * to the string.
511  * 
512  * Return value: @string.
513  **/
514 GString*
515 g_string_prepend_unichar (GString  *string,
516                           gunichar  wc)
517 {  
518   g_return_val_if_fail (string != NULL, NULL);
519   
520   return g_string_insert_unichar (string, 0, wc);
521 }
522
523 GString*
524 g_string_insert (GString     *string,
525                  gssize       pos,    
526                  const gchar *val)
527 {
528   g_return_val_if_fail (string != NULL, NULL);
529   g_return_val_if_fail (val != NULL, string);
530   if (pos >= 0)
531     g_return_val_if_fail (pos <= string->len, string);
532   
533   return g_string_insert_len (string, pos, val, -1);
534 }
535
536 GString*
537 g_string_insert_c (GString *string,
538                    gssize   pos,    
539                    gchar    c)
540 {
541   g_return_val_if_fail (string != NULL, NULL);
542
543   g_string_maybe_expand (string, 1);
544
545   if (pos < 0)
546     pos = string->len;
547   else
548     g_return_val_if_fail (pos <= string->len, string);
549   
550   /* If not just an append, move the old stuff */
551   if (pos < string->len)
552     g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
553
554   string->str[pos] = c;
555
556   string->len += 1;
557
558   string->str[string->len] = 0;
559
560   return string;
561 }
562
563 /**
564  * g_string_insert_unichar:
565  * @string: a #GString
566  * @pos: the position at which to insert character, or -1 to
567  *       append at the end of the string.
568  * @wc: a Unicode character
569  * 
570  * Converts a Unicode character into UTF-8, and insert it
571  * into the string at the given position.
572  * 
573  * Return value: @string
574  **/
575 GString*
576 g_string_insert_unichar (GString *string,
577                          gssize   pos,    
578                          gunichar wc)
579 {  
580   gchar buf[6];
581   gint charlen;
582
583   /* We could be somewhat more efficient here by computing
584    * the length, adding the space, then converting into that
585    * space, by cut-and-pasting the internals of g_unichar_to_utf8.
586    */
587   g_return_val_if_fail (string != NULL, NULL);
588
589   charlen = g_unichar_to_utf8 (wc, buf);
590   return g_string_insert_len (string, pos, buf, charlen);
591 }
592
593 GString*
594 g_string_erase (GString *string,
595                 gssize   pos,
596                 gssize   len)
597 {
598   g_return_val_if_fail (string != NULL, NULL);
599   g_return_val_if_fail (pos >= 0, string);
600   g_return_val_if_fail (pos <= string->len, string);
601
602   if (len < 0)
603     len = string->len - pos;
604   else
605     {
606       g_return_val_if_fail (pos + len <= string->len, string);
607
608       if (pos + len < string->len)
609         g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
610     }
611
612   string->len -= len;
613   
614   string->str[string->len] = 0;
615
616   return string;
617 }
618
619 /**
620  * g_string_ascii_down:
621  * @string: a GString
622  * 
623  * Converts all upper case ASCII letters to lower case ASCII letters.
624  * 
625  * Return value: passed-in @string pointer, with all the upper case
626  *               characters converted to lower case in place, with
627  *               semantics that exactly match g_ascii_tolower.
628  **/
629 GString*
630 g_string_ascii_down (GString *string)
631 {
632   gchar *s;
633   gint n = string->len;
634
635   g_return_val_if_fail (string != NULL, NULL);
636
637   s = string->str;
638
639   while (n)
640     {
641       *s = g_ascii_tolower (*s);
642       s++;
643       n--;
644     }
645
646   return string;
647 }
648
649 /**
650  * g_string_ascii_up:
651  * @string: a GString
652  * 
653  * Converts all lower case ASCII letters to upper case ASCII letters.
654  * 
655  * Return value: passed-in @string pointer, with all the lower case
656  *               characters converted to upper case in place, with
657  *               semantics that exactly match g_ascii_toupper.
658  **/
659 GString*
660 g_string_ascii_up (GString *string)
661 {
662   gchar *s;
663   gint n = string->len;
664
665   g_return_val_if_fail (string != NULL, NULL);
666
667   s = string->str;
668
669   while (n)
670     {
671       *s = g_ascii_toupper (*s);
672       s++;
673       n--;
674     }
675
676   return string;
677 }
678
679 /**
680  * g_string_down:
681  * @string: a #GString
682  *  
683  * Converts a #GString to lowercase.
684  *
685  * Returns: the #GString.
686  *
687  * Deprecated: This function uses the locale-specific tolower() function, 
688  * which is almost never the right thing. Use g_string_ascii_down() or 
689  * g_utf8_strdown() instead.
690  */
691 GString*
692 g_string_down (GString *string)
693 {
694   guchar *s;
695   glong n = string->len;    
696
697   g_return_val_if_fail (string != NULL, NULL);
698
699   s = (guchar *) string->str;
700
701   while (n)
702     {
703       if (isupper (*s))
704         *s = tolower (*s);
705       s++;
706       n--;
707     }
708
709   return string;
710 }
711
712 /**
713  * g_string_up:
714  * @string: a #GString 
715  * 
716  * Converts a #GString to uppercase.
717  * 
718  * Return value: the #GString
719  *
720  * Deprecated: This function uses the locale-specific toupper() function, 
721  * which is almost never the right thing. Use g_string_ascii_up() or 
722  * g_utf8_strup() instead.
723  **/
724 GString*
725 g_string_up (GString *string)
726 {
727   guchar *s;
728   glong n = string->len;
729
730   g_return_val_if_fail (string != NULL, NULL);
731
732   s = (guchar *) string->str;
733
734   while (n)
735     {
736       if (islower (*s))
737         *s = toupper (*s);
738       s++;
739       n--;
740     }
741
742   return string;
743 }
744
745 static void
746 g_string_append_printf_internal (GString     *string,
747                                  const gchar *fmt,
748                                  va_list      args)
749 {
750   gchar *buffer;
751
752   buffer = g_strdup_vprintf (fmt, args);
753   g_string_append (string, buffer);
754   g_free (buffer);
755 }
756
757 void
758 g_string_printf (GString *string,
759                  const gchar *fmt,
760                  ...)
761 {
762   va_list args;
763
764   g_string_truncate (string, 0);
765
766   va_start (args, fmt);
767   g_string_append_printf_internal (string, fmt, args);
768   va_end (args);
769 }
770
771 void
772 g_string_append_printf (GString *string,
773                         const gchar *fmt,
774                         ...)
775 {
776   va_list args;
777
778   va_start (args, fmt);
779   g_string_append_printf_internal (string, fmt, args);
780   va_end (args);
781 }