New function, to insert possible non-nul-terminated byte sequences into a
[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   g_return_val_if_fail (chunk != NULL, NULL);
150
151   return g_string_chunk_insert_len (chunk, string, -1);
152 }
153
154 gchar*
155 g_string_chunk_insert_const (GStringChunk *chunk,
156                              const gchar  *string)
157 {
158   char* lookup;
159
160   g_return_val_if_fail (chunk != NULL, NULL);
161
162   if (!chunk->const_table)
163     chunk->const_table = g_hash_table_new (g_str_hash, g_str_equal);
164
165   lookup = (char*) g_hash_table_lookup (chunk->const_table, (gchar *)string);
166
167   if (!lookup)
168     {
169       lookup = g_string_chunk_insert (chunk, string);
170       g_hash_table_insert (chunk->const_table, lookup, lookup);
171     }
172
173   return lookup;
174 }
175
176 /**
177  * g_string_chunk_insert_len:
178  * @chunk: a #GStringChunk
179  * @string: bytes to insert
180  * @len: number of bytes of @string to insert, or -1 to insert a 
181  *     nul-terminated string. 
182  * 
183  * Adds a copy of the first @len bytes of @string to the #GStringChunk. The
184  * copy is nul-terminated.
185  * 
186  * The characters in the string can be changed, if necessary, though you
187  * should not change anything after the end of the string.
188  * 
189  * Return value: a pointer to the copy of @string within the #GStringChunk
190  * 
191  * Since: 2.4
192  **/
193 gchar*
194 g_string_chunk_insert_len (GStringChunk *chunk,
195                            const gchar  *string, 
196                            gssize        len)
197 {
198   gchar* pos;
199
200   g_return_val_if_fail (chunk != NULL, NULL);
201
202   if (len < 0)
203     len = strlen (string);
204   
205   if ((chunk->storage_next + len + 1) > chunk->this_size)
206     {
207       gsize new_size = nearest_power (chunk->default_size, len + 1);
208
209       chunk->storage_list = g_slist_prepend (chunk->storage_list,
210                                              g_new (gchar, new_size));
211
212       chunk->this_size = new_size;
213       chunk->storage_next = 0;
214     }
215
216   pos = ((gchar *) chunk->storage_list->data) + chunk->storage_next;
217
218   *(pos + len) = '\0';
219
220   strncpy (pos, string, len);
221   len = strlen (pos);
222
223   chunk->storage_next += len + 1;
224
225   return pos;
226 }
227
228 /* Strings.
229  */
230 static void
231 g_string_maybe_expand (GString* string,
232                        gsize    len) 
233 {
234   if (string->len + len >= string->allocated_len)
235     {
236       string->allocated_len = nearest_power (1, string->len + len + 1);
237       string->str = g_realloc (string->str, string->allocated_len);
238     }
239 }
240
241 GString*
242 g_string_sized_new (gsize dfl_size)    
243 {
244   GString *string;
245
246   G_LOCK (string_mem_chunk);
247   if (!string_mem_chunk)
248     string_mem_chunk = g_mem_chunk_new ("string mem chunk",
249                                         sizeof (GString),
250                                         1024, G_ALLOC_AND_FREE);
251
252   string = g_chunk_new (GString, string_mem_chunk);
253   G_UNLOCK (string_mem_chunk);
254
255   string->allocated_len = 0;
256   string->len   = 0;
257   string->str   = NULL;
258
259   g_string_maybe_expand (string, MAX (dfl_size, 2));
260   string->str[0] = 0;
261
262   return string;
263 }
264
265 GString*
266 g_string_new (const gchar *init)
267 {
268   GString *string;
269
270   if (init == NULL || *init == '\0')
271     string = g_string_sized_new (2);
272   else 
273     {
274       gint len;
275
276       len = strlen (init);
277       string = g_string_sized_new (len + 2);
278
279       g_string_append_len (string, init, len);
280     }
281
282   return string;
283 }
284
285 GString*
286 g_string_new_len (const gchar *init,
287                   gssize       len)    
288 {
289   GString *string;
290
291   if (len < 0)
292     return g_string_new (init);
293   else
294     {
295       string = g_string_sized_new (len);
296       
297       if (init)
298         g_string_append_len (string, init, len);
299       
300       return string;
301     }
302 }
303
304 gchar*
305 g_string_free (GString *string,
306                gboolean free_segment)
307 {
308   gchar *segment;
309
310   g_return_val_if_fail (string != NULL, NULL);
311
312   if (free_segment)
313     {
314       g_free (string->str);
315       segment = NULL;
316     }
317   else
318     segment = string->str;
319
320   G_LOCK (string_mem_chunk);
321   g_mem_chunk_free (string_mem_chunk, string);
322   G_UNLOCK (string_mem_chunk);
323
324   return segment;
325 }
326
327 gboolean
328 g_string_equal (const GString *v,
329                 const GString *v2)
330 {
331   gchar *p, *q;
332   GString *string1 = (GString *) v;
333   GString *string2 = (GString *) v2;
334   gsize i = string1->len;    
335
336   if (i != string2->len)
337     return FALSE;
338
339   p = string1->str;
340   q = string2->str;
341   while (i)
342     {
343       if (*p != *q)
344         return FALSE;
345       p++;
346       q++;
347       i--;
348     }
349   return TRUE;
350 }
351
352 /* 31 bit hash function */
353 guint
354 g_string_hash (const GString *str)
355 {
356   const gchar *p = str->str;
357   gsize n = str->len;    
358   guint h = 0;
359
360   while (n--)
361     {
362       h = (h << 5) - h + *p;
363       p++;
364     }
365
366   return h;
367 }
368
369 GString*
370 g_string_assign (GString     *string,
371                  const gchar *rval)
372 {
373   g_return_val_if_fail (string != NULL, NULL);
374   g_return_val_if_fail (rval != NULL, string);
375   
376   g_string_truncate (string, 0);
377   g_string_append (string, rval);
378
379   return string;
380 }
381
382 GString*
383 g_string_truncate (GString *string,
384                    gsize    len)    
385 {
386   g_return_val_if_fail (string != NULL, NULL);
387
388   string->len = MIN (len, string->len);
389   string->str[string->len] = 0;
390
391   return string;
392 }
393
394 /**
395  * g_string_set_size:
396  * @string: a #GString
397  * @len: the new length
398  * 
399  * Sets the length of a #GString. If the length is less than
400  * the current length, the string will be truncated. If the
401  * length is greater than the current length, the contents
402  * of the newly added area are undefined. (However, as
403  * always, string->str[string->len] will be a nul byte.) 
404  * 
405  * Return value: @string
406  **/
407 GString*
408 g_string_set_size (GString *string,
409                    gsize    len)    
410 {
411   g_return_val_if_fail (string != NULL, NULL);
412
413   if (len >= string->allocated_len)
414     g_string_maybe_expand (string, len - string->len);
415   
416   string->len = len;
417   string->str[len] = 0;
418
419   return string;
420 }
421
422 GString*
423 g_string_insert_len (GString     *string,
424                      gssize       pos,    
425                      const gchar *val,
426                      gssize       len)    
427 {
428   g_return_val_if_fail (string != NULL, NULL);
429   g_return_val_if_fail (val != NULL, string);
430
431   if (len < 0)
432     len = strlen (val);
433
434   if (pos < 0)
435     pos = string->len;
436   else
437     g_return_val_if_fail (pos <= string->len, string);
438   
439   g_string_maybe_expand (string, len);
440
441   /* If we aren't appending at the end, move a hunk
442    * of the old string to the end, opening up space
443    */
444   if (pos < string->len)
445     g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
446   
447   /* insert the new string */
448   g_memmove (string->str + pos, val, len);
449
450   string->len += len;
451
452   string->str[string->len] = 0;
453
454   return string;
455 }
456
457 GString*
458 g_string_append (GString     *string,
459                  const gchar *val)
460 {  
461   g_return_val_if_fail (string != NULL, NULL);
462   g_return_val_if_fail (val != NULL, string);
463
464   return g_string_insert_len (string, -1, val, -1);
465 }
466
467 GString*
468 g_string_append_len (GString     *string,
469                      const gchar *val,
470                      gssize       len)    
471 {
472   g_return_val_if_fail (string != NULL, NULL);
473   g_return_val_if_fail (val != NULL, string);
474
475   return g_string_insert_len (string, -1, val, len);
476 }
477
478 GString*
479 g_string_append_c (GString *string,
480                    gchar    c)
481 {
482   g_return_val_if_fail (string != NULL, NULL);
483
484   return g_string_insert_c (string, -1, c);
485 }
486
487 /**
488  * g_string_append_unichar:
489  * @string: a #GString
490  * @wc: a Unicode character
491  * 
492  * Converts a Unicode character into UTF-8, and appends it
493  * to the string.
494  * 
495  * Return value: @string
496  **/
497 GString*
498 g_string_append_unichar (GString  *string,
499                          gunichar  wc)
500 {  
501   g_return_val_if_fail (string != NULL, NULL);
502   
503   return g_string_insert_unichar (string, -1, wc);
504 }
505
506 GString*
507 g_string_prepend (GString     *string,
508                   const gchar *val)
509 {
510   g_return_val_if_fail (string != NULL, NULL);
511   g_return_val_if_fail (val != NULL, string);
512   
513   return g_string_insert_len (string, 0, val, -1);
514 }
515
516 GString*
517 g_string_prepend_len (GString     *string,
518                       const gchar *val,
519                       gssize       len)    
520 {
521   g_return_val_if_fail (string != NULL, NULL);
522   g_return_val_if_fail (val != NULL, string);
523
524   return g_string_insert_len (string, 0, val, len);
525 }
526
527 GString*
528 g_string_prepend_c (GString *string,
529                     gchar    c)
530 {  
531   g_return_val_if_fail (string != NULL, NULL);
532   
533   return g_string_insert_c (string, 0, c);
534 }
535
536 /**
537  * g_string_prepend_unichar:
538  * @string: a #GString.
539  * @wc: a Unicode character.
540  * 
541  * Converts a Unicode character into UTF-8, and prepends it
542  * to the string.
543  * 
544  * Return value: @string.
545  **/
546 GString*
547 g_string_prepend_unichar (GString  *string,
548                           gunichar  wc)
549 {  
550   g_return_val_if_fail (string != NULL, NULL);
551   
552   return g_string_insert_unichar (string, 0, wc);
553 }
554
555 GString*
556 g_string_insert (GString     *string,
557                  gssize       pos,    
558                  const gchar *val)
559 {
560   g_return_val_if_fail (string != NULL, NULL);
561   g_return_val_if_fail (val != NULL, string);
562   if (pos >= 0)
563     g_return_val_if_fail (pos <= string->len, string);
564   
565   return g_string_insert_len (string, pos, val, -1);
566 }
567
568 GString*
569 g_string_insert_c (GString *string,
570                    gssize   pos,    
571                    gchar    c)
572 {
573   g_return_val_if_fail (string != NULL, NULL);
574
575   g_string_maybe_expand (string, 1);
576
577   if (pos < 0)
578     pos = string->len;
579   else
580     g_return_val_if_fail (pos <= string->len, string);
581   
582   /* If not just an append, move the old stuff */
583   if (pos < string->len)
584     g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
585
586   string->str[pos] = c;
587
588   string->len += 1;
589
590   string->str[string->len] = 0;
591
592   return string;
593 }
594
595 /**
596  * g_string_insert_unichar:
597  * @string: a #GString
598  * @pos: the position at which to insert character, or -1 to
599  *       append at the end of the string.
600  * @wc: a Unicode character
601  * 
602  * Converts a Unicode character into UTF-8, and insert it
603  * into the string at the given position.
604  * 
605  * Return value: @string
606  **/
607 GString*
608 g_string_insert_unichar (GString *string,
609                          gssize   pos,    
610                          gunichar wc)
611 {  
612   gchar buf[6];
613   gint charlen;
614
615   /* We could be somewhat more efficient here by computing
616    * the length, adding the space, then converting into that
617    * space, by cut-and-pasting the internals of g_unichar_to_utf8.
618    */
619   g_return_val_if_fail (string != NULL, NULL);
620
621   charlen = g_unichar_to_utf8 (wc, buf);
622   return g_string_insert_len (string, pos, buf, charlen);
623 }
624
625 GString*
626 g_string_erase (GString *string,
627                 gssize   pos,
628                 gssize   len)
629 {
630   g_return_val_if_fail (string != NULL, NULL);
631   g_return_val_if_fail (pos >= 0, string);
632   g_return_val_if_fail (pos <= string->len, string);
633
634   if (len < 0)
635     len = string->len - pos;
636   else
637     {
638       g_return_val_if_fail (pos + len <= string->len, string);
639
640       if (pos + len < string->len)
641         g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
642     }
643
644   string->len -= len;
645   
646   string->str[string->len] = 0;
647
648   return string;
649 }
650
651 /**
652  * g_string_ascii_down:
653  * @string: a GString
654  * 
655  * Converts all upper case ASCII letters to lower case ASCII letters.
656  * 
657  * Return value: passed-in @string pointer, with all the upper case
658  *               characters converted to lower case in place, with
659  *               semantics that exactly match g_ascii_tolower.
660  **/
661 GString*
662 g_string_ascii_down (GString *string)
663 {
664   gchar *s;
665   gint n = string->len;
666
667   g_return_val_if_fail (string != NULL, NULL);
668
669   s = string->str;
670
671   while (n)
672     {
673       *s = g_ascii_tolower (*s);
674       s++;
675       n--;
676     }
677
678   return string;
679 }
680
681 /**
682  * g_string_ascii_up:
683  * @string: a GString
684  * 
685  * Converts all lower case ASCII letters to upper case ASCII letters.
686  * 
687  * Return value: passed-in @string pointer, with all the lower case
688  *               characters converted to upper case in place, with
689  *               semantics that exactly match g_ascii_toupper.
690  **/
691 GString*
692 g_string_ascii_up (GString *string)
693 {
694   gchar *s;
695   gint n = string->len;
696
697   g_return_val_if_fail (string != NULL, NULL);
698
699   s = string->str;
700
701   while (n)
702     {
703       *s = g_ascii_toupper (*s);
704       s++;
705       n--;
706     }
707
708   return string;
709 }
710
711 /**
712  * g_string_down:
713  * @string: a #GString
714  *  
715  * Converts a #GString to lowercase.
716  *
717  * Returns: the #GString.
718  *
719  * Deprecated: This function uses the locale-specific tolower() function, 
720  * which is almost never the right thing. Use g_string_ascii_down() or 
721  * g_utf8_strdown() instead.
722  */
723 GString*
724 g_string_down (GString *string)
725 {
726   guchar *s;
727   glong n = string->len;    
728
729   g_return_val_if_fail (string != NULL, NULL);
730
731   s = (guchar *) string->str;
732
733   while (n)
734     {
735       if (isupper (*s))
736         *s = tolower (*s);
737       s++;
738       n--;
739     }
740
741   return string;
742 }
743
744 /**
745  * g_string_up:
746  * @string: a #GString 
747  * 
748  * Converts a #GString to uppercase.
749  * 
750  * Return value: the #GString
751  *
752  * Deprecated: This function uses the locale-specific toupper() function, 
753  * which is almost never the right thing. Use g_string_ascii_up() or 
754  * g_utf8_strup() instead.
755  **/
756 GString*
757 g_string_up (GString *string)
758 {
759   guchar *s;
760   glong n = string->len;
761
762   g_return_val_if_fail (string != NULL, NULL);
763
764   s = (guchar *) string->str;
765
766   while (n)
767     {
768       if (islower (*s))
769         *s = toupper (*s);
770       s++;
771       n--;
772     }
773
774   return string;
775 }
776
777 static void
778 g_string_append_printf_internal (GString     *string,
779                                  const gchar *fmt,
780                                  va_list      args)
781 {
782   gchar *buffer;
783
784   buffer = g_strdup_vprintf (fmt, args);
785   g_string_append (string, buffer);
786   g_free (buffer);
787 }
788
789 void
790 g_string_printf (GString *string,
791                  const gchar *fmt,
792                  ...)
793 {
794   va_list args;
795
796   g_string_truncate (string, 0);
797
798   va_start (args, fmt);
799   g_string_append_printf_internal (string, fmt, args);
800   va_end (args);
801 }
802
803 void
804 g_string_append_printf (GString *string,
805                         const gchar *fmt,
806                         ...)
807 {
808   va_list args;
809
810   va_start (args, fmt);
811   g_string_append_printf_internal (string, fmt, args);
812   va_end (args);
813 }