Use g_vasprintf() and g_string_append_len(), thus enabling embedded nuls
[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   g_string_truncate (string, 0);
378   g_string_append (string, rval);
379
380   return string;
381 }
382
383 GString*
384 g_string_truncate (GString *string,
385                    gsize    len)    
386 {
387   g_return_val_if_fail (string != NULL, NULL);
388
389   string->len = MIN (len, string->len);
390   string->str[string->len] = 0;
391
392   return string;
393 }
394
395 /**
396  * g_string_set_size:
397  * @string: a #GString
398  * @len: the new length
399  * 
400  * Sets the length of a #GString. If the length is less than
401  * the current length, the string will be truncated. If the
402  * length is greater than the current length, the contents
403  * of the newly added area are undefined. (However, as
404  * always, string->str[string->len] will be a nul byte.) 
405  * 
406  * Return value: @string
407  **/
408 GString*
409 g_string_set_size (GString *string,
410                    gsize    len)    
411 {
412   g_return_val_if_fail (string != NULL, NULL);
413
414   if (len >= string->allocated_len)
415     g_string_maybe_expand (string, len - string->len);
416   
417   string->len = len;
418   string->str[len] = 0;
419
420   return string;
421 }
422
423 GString*
424 g_string_insert_len (GString     *string,
425                      gssize       pos,    
426                      const gchar *val,
427                      gssize       len)    
428 {
429   g_return_val_if_fail (string != NULL, NULL);
430   g_return_val_if_fail (val != NULL, string);
431
432   if (len < 0)
433     len = strlen (val);
434
435   if (pos < 0)
436     pos = string->len;
437   else
438     g_return_val_if_fail (pos <= string->len, string);
439   
440   g_string_maybe_expand (string, len);
441
442   /* If we aren't appending at the end, move a hunk
443    * of the old string to the end, opening up space
444    */
445   if (pos < string->len)
446     g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
447   
448   /* insert the new string */
449   g_memmove (string->str + pos, val, len);
450
451   string->len += len;
452
453   string->str[string->len] = 0;
454
455   return string;
456 }
457
458 GString*
459 g_string_append (GString     *string,
460                  const gchar *val)
461 {  
462   g_return_val_if_fail (string != NULL, NULL);
463   g_return_val_if_fail (val != NULL, string);
464
465   return g_string_insert_len (string, -1, val, -1);
466 }
467
468 GString*
469 g_string_append_len (GString     *string,
470                      const gchar *val,
471                      gssize       len)    
472 {
473   g_return_val_if_fail (string != NULL, NULL);
474   g_return_val_if_fail (val != NULL, string);
475
476   return g_string_insert_len (string, -1, val, len);
477 }
478
479 GString*
480 g_string_append_c (GString *string,
481                    gchar    c)
482 {
483   g_return_val_if_fail (string != NULL, NULL);
484
485   return g_string_insert_c (string, -1, c);
486 }
487
488 /**
489  * g_string_append_unichar:
490  * @string: a #GString
491  * @wc: a Unicode character
492  * 
493  * Converts a Unicode character into UTF-8, and appends it
494  * to the string.
495  * 
496  * Return value: @string
497  **/
498 GString*
499 g_string_append_unichar (GString  *string,
500                          gunichar  wc)
501 {  
502   g_return_val_if_fail (string != NULL, NULL);
503   
504   return g_string_insert_unichar (string, -1, wc);
505 }
506
507 GString*
508 g_string_prepend (GString     *string,
509                   const gchar *val)
510 {
511   g_return_val_if_fail (string != NULL, NULL);
512   g_return_val_if_fail (val != NULL, string);
513   
514   return g_string_insert_len (string, 0, val, -1);
515 }
516
517 GString*
518 g_string_prepend_len (GString     *string,
519                       const gchar *val,
520                       gssize       len)    
521 {
522   g_return_val_if_fail (string != NULL, NULL);
523   g_return_val_if_fail (val != NULL, string);
524
525   return g_string_insert_len (string, 0, val, len);
526 }
527
528 GString*
529 g_string_prepend_c (GString *string,
530                     gchar    c)
531 {  
532   g_return_val_if_fail (string != NULL, NULL);
533   
534   return g_string_insert_c (string, 0, c);
535 }
536
537 /**
538  * g_string_prepend_unichar:
539  * @string: a #GString.
540  * @wc: a Unicode character.
541  * 
542  * Converts a Unicode character into UTF-8, and prepends it
543  * to the string.
544  * 
545  * Return value: @string.
546  **/
547 GString*
548 g_string_prepend_unichar (GString  *string,
549                           gunichar  wc)
550 {  
551   g_return_val_if_fail (string != NULL, NULL);
552   
553   return g_string_insert_unichar (string, 0, wc);
554 }
555
556 GString*
557 g_string_insert (GString     *string,
558                  gssize       pos,    
559                  const gchar *val)
560 {
561   g_return_val_if_fail (string != NULL, NULL);
562   g_return_val_if_fail (val != NULL, string);
563   if (pos >= 0)
564     g_return_val_if_fail (pos <= string->len, string);
565   
566   return g_string_insert_len (string, pos, val, -1);
567 }
568
569 GString*
570 g_string_insert_c (GString *string,
571                    gssize   pos,    
572                    gchar    c)
573 {
574   g_return_val_if_fail (string != NULL, NULL);
575
576   g_string_maybe_expand (string, 1);
577
578   if (pos < 0)
579     pos = string->len;
580   else
581     g_return_val_if_fail (pos <= string->len, string);
582   
583   /* If not just an append, move the old stuff */
584   if (pos < string->len)
585     g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
586
587   string->str[pos] = c;
588
589   string->len += 1;
590
591   string->str[string->len] = 0;
592
593   return string;
594 }
595
596 /**
597  * g_string_insert_unichar:
598  * @string: a #GString
599  * @pos: the position at which to insert character, or -1 to
600  *       append at the end of the string.
601  * @wc: a Unicode character
602  * 
603  * Converts a Unicode character into UTF-8, and insert it
604  * into the string at the given position.
605  * 
606  * Return value: @string
607  **/
608 GString*
609 g_string_insert_unichar (GString *string,
610                          gssize   pos,    
611                          gunichar wc)
612 {  
613   gchar buf[6];
614   gint charlen;
615
616   /* We could be somewhat more efficient here by computing
617    * the length, adding the space, then converting into that
618    * space, by cut-and-pasting the internals of g_unichar_to_utf8.
619    */
620   g_return_val_if_fail (string != NULL, NULL);
621
622   charlen = g_unichar_to_utf8 (wc, buf);
623   return g_string_insert_len (string, pos, buf, charlen);
624 }
625
626 GString*
627 g_string_erase (GString *string,
628                 gssize   pos,
629                 gssize   len)
630 {
631   g_return_val_if_fail (string != NULL, NULL);
632   g_return_val_if_fail (pos >= 0, string);
633   g_return_val_if_fail (pos <= string->len, string);
634
635   if (len < 0)
636     len = string->len - pos;
637   else
638     {
639       g_return_val_if_fail (pos + len <= string->len, string);
640
641       if (pos + len < string->len)
642         g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
643     }
644
645   string->len -= len;
646   
647   string->str[string->len] = 0;
648
649   return string;
650 }
651
652 /**
653  * g_string_ascii_down:
654  * @string: a GString
655  * 
656  * Converts all upper case ASCII letters to lower case ASCII letters.
657  * 
658  * Return value: passed-in @string pointer, with all the upper case
659  *               characters converted to lower case in place, with
660  *               semantics that exactly match g_ascii_tolower.
661  **/
662 GString*
663 g_string_ascii_down (GString *string)
664 {
665   gchar *s;
666   gint n = string->len;
667
668   g_return_val_if_fail (string != NULL, NULL);
669
670   s = string->str;
671
672   while (n)
673     {
674       *s = g_ascii_tolower (*s);
675       s++;
676       n--;
677     }
678
679   return string;
680 }
681
682 /**
683  * g_string_ascii_up:
684  * @string: a GString
685  * 
686  * Converts all lower case ASCII letters to upper case ASCII letters.
687  * 
688  * Return value: passed-in @string pointer, with all the lower case
689  *               characters converted to upper case in place, with
690  *               semantics that exactly match g_ascii_toupper.
691  **/
692 GString*
693 g_string_ascii_up (GString *string)
694 {
695   gchar *s;
696   gint n = string->len;
697
698   g_return_val_if_fail (string != NULL, NULL);
699
700   s = string->str;
701
702   while (n)
703     {
704       *s = g_ascii_toupper (*s);
705       s++;
706       n--;
707     }
708
709   return string;
710 }
711
712 /**
713  * g_string_down:
714  * @string: a #GString
715  *  
716  * Converts a #GString to lowercase.
717  *
718  * Returns: the #GString.
719  *
720  * Deprecated: This function uses the locale-specific tolower() function, 
721  * which is almost never the right thing. Use g_string_ascii_down() or 
722  * g_utf8_strdown() instead.
723  */
724 GString*
725 g_string_down (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 (isupper (*s))
737         *s = tolower (*s);
738       s++;
739       n--;
740     }
741
742   return string;
743 }
744
745 /**
746  * g_string_up:
747  * @string: a #GString 
748  * 
749  * Converts a #GString to uppercase.
750  * 
751  * Return value: the #GString
752  *
753  * Deprecated: This function uses the locale-specific toupper() function, 
754  * which is almost never the right thing. Use g_string_ascii_up() or 
755  * g_utf8_strup() instead.
756  **/
757 GString*
758 g_string_up (GString *string)
759 {
760   guchar *s;
761   glong n = string->len;
762
763   g_return_val_if_fail (string != NULL, NULL);
764
765   s = (guchar *) string->str;
766
767   while (n)
768     {
769       if (islower (*s))
770         *s = toupper (*s);
771       s++;
772       n--;
773     }
774
775   return string;
776 }
777
778 static void
779 g_string_append_printf_internal (GString     *string,
780                                  const gchar *fmt,
781                                  va_list      args)
782 {
783   gchar *buffer;
784   gint length;
785   
786   length = g_vasprintf (&buffer, fmt, args);
787   g_string_append_len (string, buffer, length);
788   g_free (buffer);
789 }
790
791 void
792 g_string_printf (GString *string,
793                  const gchar *fmt,
794                  ...)
795 {
796   va_list args;
797
798   g_string_truncate (string, 0);
799
800   va_start (args, fmt);
801   g_string_append_printf_internal (string, fmt, args);
802   va_end (args);
803 }
804
805 void
806 g_string_append_printf (GString *string,
807                         const gchar *fmt,
808                         ...)
809 {
810   va_list args;
811
812   va_start (args, fmt);
813   g_string_append_printf_internal (string, fmt, args);
814   va_end (args);
815 }