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