Fixes for #58195, based on some ideas from Hidetosh Tajima.
[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 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 #include <stdarg.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include "glib.h"
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   string = g_string_sized_new (init ? strlen (init) + 2 : 2);
239
240   if (init)
241     g_string_append (string, init);
242
243   return string;
244 }
245
246 GString*
247 g_string_new_len (const gchar *init,
248                   gssize       len)    
249 {
250   GString *string;
251
252   if (len < 0)
253     return g_string_new (init);
254   else
255     {
256       string = g_string_sized_new (len);
257       
258       if (init)
259         g_string_append_len (string, init, len);
260       
261       return string;
262     }
263 }
264
265 gchar*
266 g_string_free (GString *string,
267                gboolean free_segment)
268 {
269   gchar *segment;
270
271   g_return_val_if_fail (string != NULL, NULL);
272
273   if (free_segment)
274     {
275       g_free (string->str);
276       segment = NULL;
277     }
278   else
279     segment = string->str;
280
281   G_LOCK (string_mem_chunk);
282   g_mem_chunk_free (string_mem_chunk, string);
283   G_UNLOCK (string_mem_chunk);
284
285   return segment;
286 }
287
288 gboolean
289 g_string_equal (const GString *v,
290                 const GString *v2)
291 {
292   gchar *p, *q;
293   GString *string1 = (GString *) v;
294   GString *string2 = (GString *) v2;
295   gsize i = string1->len;    
296
297   if (i != string2->len)
298     return FALSE;
299
300   p = string1->str;
301   q = string2->str;
302   while (i)
303     {
304       if (*p != *q)
305         return FALSE;
306       p++;
307       q++;
308       i--;
309     }
310   return TRUE;
311 }
312
313 /* 31 bit hash function */
314 guint
315 g_string_hash (const GString *str)
316 {
317   const gchar *p = str->str;
318   gsize n = str->len;    
319   guint h = 0;
320
321   while (n--)
322     {
323       h = (h << 5) - h + *p;
324       p++;
325     }
326
327   return h;
328 }
329
330 GString*
331 g_string_assign (GString     *string,
332                  const gchar *rval)
333 {
334   g_return_val_if_fail (string != NULL, NULL);
335   g_return_val_if_fail (rval != NULL, string);
336   
337   g_string_truncate (string, 0);
338   g_string_append (string, rval);
339
340   return string;
341 }
342
343 GString*
344 g_string_truncate (GString *string,
345                    gsize    len)    
346 {
347   g_return_val_if_fail (string != NULL, NULL);
348
349   string->len = MIN (len, string->len);
350   string->str[string->len] = 0;
351
352   return string;
353 }
354
355 /**
356  * g_string_set_size:
357  * @string: a #GString
358  * @len: the new length
359  * 
360  * Sets the length of a #GString. If the length is less than
361  * the current length, the string will be truncated. If the
362  * length is greater than the current length, the contents
363  * of the newly added area are undefined. (However, as
364  * always, string->str[string->len] will be a nul byte.) 
365  * 
366  * Return value: @string
367  **/
368 GString*
369 g_string_set_size (GString *string,
370                    gsize    len)    
371 {
372   g_return_val_if_fail (string != NULL, NULL);
373
374   if (len >= string->allocated_len)
375     g_string_maybe_expand (string, len - string->len);
376   
377   string->len = len;
378   string->str[len] = 0;
379
380   return string;
381 }
382
383 GString*
384 g_string_insert_len (GString     *string,
385                      gssize       pos,    
386                      const gchar *val,
387                      gssize       len)    
388 {
389   g_return_val_if_fail (string != NULL, NULL);
390   g_return_val_if_fail (val != NULL, string);
391
392   if (len < 0)
393     len = strlen (val);
394
395   if (pos < 0)
396     pos = string->len;
397   else
398     g_return_val_if_fail (pos <= string->len, string);
399   
400   g_string_maybe_expand (string, len);
401
402   /* If we aren't appending at the end, move a hunk
403    * of the old string to the end, opening up space
404    */
405   if (pos < string->len)
406     g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
407   
408   /* insert the new string */
409   g_memmove (string->str + pos, val, len);
410
411   string->len += len;
412
413   string->str[string->len] = 0;
414
415   return string;
416 }
417
418 GString*
419 g_string_append (GString     *string,
420                  const gchar *val)
421 {  
422   g_return_val_if_fail (string != NULL, NULL);
423   g_return_val_if_fail (val != NULL, string);
424
425   return g_string_insert_len (string, -1, val, -1);
426 }
427
428 GString*
429 g_string_append_len (GString     *string,
430                      const gchar *val,
431                      gssize       len)    
432 {
433   g_return_val_if_fail (string != NULL, NULL);
434   g_return_val_if_fail (val != NULL, string);
435
436   return g_string_insert_len (string, -1, val, len);
437 }
438
439 GString*
440 g_string_append_c (GString *string,
441                    gchar    c)
442 {
443   g_return_val_if_fail (string != NULL, NULL);
444
445   return g_string_insert_c (string, -1, c);
446 }
447
448 /**
449  * g_string_append_unichar:
450  * @string: a #GString
451  * @wc: a Unicode character
452  * 
453  * Converts a Unicode character into UTF-8, and appends it
454  * to the string.
455  * 
456  * Return value: @string
457  **/
458 GString*
459 g_string_append_unichar (GString  *string,
460                          gunichar  wc)
461 {  
462   g_return_val_if_fail (string != NULL, NULL);
463   
464   return g_string_insert_unichar (string, -1, wc);
465 }
466
467 GString*
468 g_string_prepend (GString     *string,
469                   const gchar *val)
470 {
471   g_return_val_if_fail (string != NULL, NULL);
472   g_return_val_if_fail (val != NULL, string);
473   
474   return g_string_insert_len (string, 0, val, -1);
475 }
476
477 GString*
478 g_string_prepend_len (GString     *string,
479                       const gchar *val,
480                       gssize       len)    
481 {
482   g_return_val_if_fail (string != NULL, NULL);
483   g_return_val_if_fail (val != NULL, string);
484
485   return g_string_insert_len (string, 0, val, len);
486 }
487
488 GString*
489 g_string_prepend_c (GString *string,
490                     gchar    c)
491 {  
492   g_return_val_if_fail (string != NULL, NULL);
493   
494   return g_string_insert_c (string, 0, c);
495 }
496
497 /**
498  * g_string_append_unichar:
499  * @string: a #GString
500  * @wc: a Unicode character
501  * 
502  * Converts a Unicode character into UTF-8, and prepends it
503  * to the string.
504  * 
505  * Return value: @string
506  **/
507 GString*
508 g_string_prepend_unichar (GString  *string,
509                           gunichar  wc)
510 {  
511   g_return_val_if_fail (string != NULL, NULL);
512   
513   return g_string_insert_unichar (string, 0, wc);
514 }
515
516 GString*
517 g_string_insert (GString     *string,
518                  gssize       pos,    
519                  const gchar *val)
520 {
521   g_return_val_if_fail (string != NULL, NULL);
522   g_return_val_if_fail (val != NULL, string);
523   if (pos >= 0)
524     g_return_val_if_fail (pos <= string->len, string);
525   
526   return g_string_insert_len (string, pos, val, -1);
527 }
528
529 GString*
530 g_string_insert_c (GString *string,
531                    gssize   pos,    
532                    gchar    c)
533 {
534   g_return_val_if_fail (string != NULL, NULL);
535
536   g_string_maybe_expand (string, 1);
537
538   if (pos < 0)
539     pos = string->len;
540   else
541     g_return_val_if_fail (pos <= string->len, string);
542   
543   /* If not just an append, move the old stuff */
544   if (pos < string->len)
545     g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
546
547   string->str[pos] = c;
548
549   string->len += 1;
550
551   string->str[string->len] = 0;
552
553   return string;
554 }
555
556 /**
557  * g_string_insert_unichar:
558  * @string: a #Gstring
559  * @pos: the position at which to insert character, or -1 to
560  *       append at the end of the string.
561  * @wc: a Unicode character
562  * 
563  * Converts a Unicode character into UTF-8, and insert it
564  * into the string at the given position.
565  * 
566  * Return value: @string
567  **/
568 GString*
569 g_string_insert_unichar (GString *string,
570                          gssize   pos,    
571                          gunichar wc)
572 {  
573   gchar buf[6];
574   gint charlen;
575
576   /* We could be somewhat more efficient here by computing
577    * the length, adding the space, then converting into that
578    * space, by cut-and-pasting the internals of g_unichar_to_utf8.
579    */
580   g_return_val_if_fail (string != NULL, NULL);
581
582   charlen = g_unichar_to_utf8 (wc, buf);
583   return g_string_insert_len (string, pos, buf, charlen);
584 }
585
586 GString*
587 g_string_erase (GString *string,
588                 gsize    pos,    
589                 gsize    len)    
590 {
591   g_return_val_if_fail (string != NULL, NULL);
592   g_return_val_if_fail (pos >= 0, string);
593   g_return_val_if_fail (pos <= string->len, string);
594
595   if (len < 0)
596     len = string->len - pos;
597   else
598     {
599       g_return_val_if_fail (pos + len <= string->len, string);
600
601       if (pos + len < string->len)
602         g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
603     }
604
605   string->len -= len;
606   
607   string->str[string->len] = 0;
608
609   return string;
610 }
611
612 /**
613  * g_string_ascii_down:
614  * @string: a GString
615  * 
616  * Converts all upper case ASCII letters to lower case ASCII letters.
617  * 
618  * Return value: passed-in @string pointer, with all the upper case
619  *               characters converted to lower case in place, with
620  *               semantics that exactly match g_ascii_tolower.
621  **/
622 GString*
623 g_string_ascii_down (GString *string)
624 {
625   gchar *s;
626   gint n = string->len;
627
628   g_return_val_if_fail (string != NULL, NULL);
629
630   s = string->str;
631
632   while (n)
633     {
634       *s = g_ascii_tolower (*s);
635       s++;
636       n--;
637     }
638
639   return string;
640 }
641
642 /**
643  * g_string_ascii_up:
644  * @string: a GString
645  * 
646  * Converts all lower case ASCII letters to upper case ASCII letters.
647  * 
648  * Return value: passed-in @string pointer, with all the lower case
649  *               characters converted to upper case in place, with
650  *               semantics that exactly match g_ascii_toupper.
651  **/
652 GString*
653 g_string_ascii_up (GString *string)
654 {
655   gchar *s;
656   gint n = string->len;
657
658   g_return_val_if_fail (string != NULL, NULL);
659
660   s = string->str;
661
662   while (n)
663     {
664       *s = g_ascii_toupper (*s);
665       s++;
666       n--;
667     }
668
669   return string;
670 }
671
672 GString*
673 g_string_down (GString *string)
674 {
675   guchar *s;
676   glong n = string->len;    
677
678   g_return_val_if_fail (string != NULL, NULL);
679
680   s = (guchar *) string->str;
681
682   while (n)
683     {
684       if (isupper (*s))
685         *s = tolower (*s);
686       s++;
687       n--;
688     }
689
690   return string;
691 }
692
693 GString*
694 g_string_up (GString *string)
695 {
696   guchar *s;
697   glong n = string->len;
698
699   g_return_val_if_fail (string != NULL, NULL);
700
701   s = (guchar *) string->str;
702
703   while (n)
704     {
705       if (islower (*s))
706         *s = toupper (*s);
707       s++;
708       n--;
709     }
710
711   return string;
712 }
713
714 static void
715 g_string_printfa_internal (GString     *string,
716                            const gchar *fmt,
717                            va_list      args)
718 {
719   gchar *buffer;
720
721   buffer = g_strdup_vprintf (fmt, args);
722   g_string_append (string, buffer);
723   g_free (buffer);
724 }
725
726 void
727 g_string_printf (GString *string,
728                  const gchar *fmt,
729                  ...)
730 {
731   va_list args;
732
733   g_string_truncate (string, 0);
734
735   va_start (args, fmt);
736   g_string_printfa_internal (string, fmt, args);
737   va_end (args);
738 }
739
740 void
741 g_string_printfa (GString *string,
742                   const gchar *fmt,
743                   ...)
744 {
745   va_list args;
746
747   va_start (args, fmt);
748   g_string_printfa_internal (string, fmt, args);
749   va_end (args);
750 }