Handle the case where the to-be-inserted string is a substring of the
[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 GString*
519 g_string_append_c (GString *string,
520                    gchar    c)
521 {
522   g_return_val_if_fail (string != NULL, NULL);
523
524   return g_string_insert_c (string, -1, c);
525 }
526
527 /**
528  * g_string_append_unichar:
529  * @string: a #GString
530  * @wc: a Unicode character
531  * 
532  * Converts a Unicode character into UTF-8, and appends it
533  * to the string.
534  * 
535  * Return value: @string
536  **/
537 GString*
538 g_string_append_unichar (GString  *string,
539                          gunichar  wc)
540 {  
541   g_return_val_if_fail (string != NULL, NULL);
542   
543   return g_string_insert_unichar (string, -1, wc);
544 }
545
546 GString*
547 g_string_prepend (GString     *string,
548                   const gchar *val)
549 {
550   g_return_val_if_fail (string != NULL, NULL);
551   g_return_val_if_fail (val != NULL, string);
552   
553   return g_string_insert_len (string, 0, val, -1);
554 }
555
556 GString*
557 g_string_prepend_len (GString     *string,
558                       const gchar *val,
559                       gssize       len)    
560 {
561   g_return_val_if_fail (string != NULL, NULL);
562   g_return_val_if_fail (val != NULL, string);
563
564   return g_string_insert_len (string, 0, val, len);
565 }
566
567 GString*
568 g_string_prepend_c (GString *string,
569                     gchar    c)
570 {  
571   g_return_val_if_fail (string != NULL, NULL);
572   
573   return g_string_insert_c (string, 0, c);
574 }
575
576 /**
577  * g_string_prepend_unichar:
578  * @string: a #GString.
579  * @wc: a Unicode character.
580  * 
581  * Converts a Unicode character into UTF-8, and prepends it
582  * to the string.
583  * 
584  * Return value: @string.
585  **/
586 GString*
587 g_string_prepend_unichar (GString  *string,
588                           gunichar  wc)
589 {  
590   g_return_val_if_fail (string != NULL, NULL);
591   
592   return g_string_insert_unichar (string, 0, wc);
593 }
594
595 GString*
596 g_string_insert (GString     *string,
597                  gssize       pos,    
598                  const gchar *val)
599 {
600   g_return_val_if_fail (string != NULL, NULL);
601   g_return_val_if_fail (val != NULL, string);
602   if (pos >= 0)
603     g_return_val_if_fail (pos <= string->len, string);
604   
605   return g_string_insert_len (string, pos, val, -1);
606 }
607
608 GString*
609 g_string_insert_c (GString *string,
610                    gssize   pos,    
611                    gchar    c)
612 {
613   g_return_val_if_fail (string != NULL, NULL);
614
615   g_string_maybe_expand (string, 1);
616
617   if (pos < 0)
618     pos = string->len;
619   else
620     g_return_val_if_fail (pos <= string->len, string);
621   
622   /* If not just an append, move the old stuff */
623   if (pos < string->len)
624     g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
625
626   string->str[pos] = c;
627
628   string->len += 1;
629
630   string->str[string->len] = 0;
631
632   return string;
633 }
634
635 /**
636  * g_string_insert_unichar:
637  * @string: a #GString
638  * @pos: the position at which to insert character, or -1 to
639  *       append at the end of the string.
640  * @wc: a Unicode character
641  * 
642  * Converts a Unicode character into UTF-8, and insert it
643  * into the string at the given position.
644  * 
645  * Return value: @string
646  **/
647 GString*
648 g_string_insert_unichar (GString *string,
649                          gssize   pos,    
650                          gunichar wc)
651 {  
652   gchar buf[6];
653   gint charlen;
654
655   /* We could be somewhat more efficient here by computing
656    * the length, adding the space, then converting into that
657    * space, by cut-and-pasting the internals of g_unichar_to_utf8.
658    */
659   g_return_val_if_fail (string != NULL, NULL);
660
661   charlen = g_unichar_to_utf8 (wc, buf);
662   return g_string_insert_len (string, pos, buf, charlen);
663 }
664
665 GString*
666 g_string_erase (GString *string,
667                 gssize   pos,
668                 gssize   len)
669 {
670   g_return_val_if_fail (string != NULL, NULL);
671   g_return_val_if_fail (pos >= 0, string);
672   g_return_val_if_fail (pos <= string->len, string);
673
674   if (len < 0)
675     len = string->len - pos;
676   else
677     {
678       g_return_val_if_fail (pos + len <= string->len, string);
679
680       if (pos + len < string->len)
681         g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
682     }
683
684   string->len -= len;
685   
686   string->str[string->len] = 0;
687
688   return string;
689 }
690
691 /**
692  * g_string_ascii_down:
693  * @string: a GString
694  * 
695  * Converts all upper case ASCII letters to lower case ASCII letters.
696  * 
697  * Return value: passed-in @string pointer, with all the upper case
698  *               characters converted to lower case in place, with
699  *               semantics that exactly match g_ascii_tolower.
700  **/
701 GString*
702 g_string_ascii_down (GString *string)
703 {
704   gchar *s;
705   gint n = string->len;
706
707   g_return_val_if_fail (string != NULL, NULL);
708
709   s = string->str;
710
711   while (n)
712     {
713       *s = g_ascii_tolower (*s);
714       s++;
715       n--;
716     }
717
718   return string;
719 }
720
721 /**
722  * g_string_ascii_up:
723  * @string: a GString
724  * 
725  * Converts all lower case ASCII letters to upper case ASCII letters.
726  * 
727  * Return value: passed-in @string pointer, with all the lower case
728  *               characters converted to upper case in place, with
729  *               semantics that exactly match g_ascii_toupper.
730  **/
731 GString*
732 g_string_ascii_up (GString *string)
733 {
734   gchar *s;
735   gint n = string->len;
736
737   g_return_val_if_fail (string != NULL, NULL);
738
739   s = string->str;
740
741   while (n)
742     {
743       *s = g_ascii_toupper (*s);
744       s++;
745       n--;
746     }
747
748   return string;
749 }
750
751 /**
752  * g_string_down:
753  * @string: a #GString
754  *  
755  * Converts a #GString to lowercase.
756  *
757  * Returns: the #GString.
758  *
759  * Deprecated: This function uses the locale-specific tolower() function, 
760  * which is almost never the right thing. Use g_string_ascii_down() or 
761  * g_utf8_strdown() instead.
762  */
763 GString*
764 g_string_down (GString *string)
765 {
766   guchar *s;
767   glong n = string->len;    
768
769   g_return_val_if_fail (string != NULL, NULL);
770
771   s = (guchar *) string->str;
772
773   while (n)
774     {
775       if (isupper (*s))
776         *s = tolower (*s);
777       s++;
778       n--;
779     }
780
781   return string;
782 }
783
784 /**
785  * g_string_up:
786  * @string: a #GString 
787  * 
788  * Converts a #GString to uppercase.
789  * 
790  * Return value: the #GString
791  *
792  * Deprecated: This function uses the locale-specific toupper() function, 
793  * which is almost never the right thing. Use g_string_ascii_up() or 
794  * g_utf8_strup() instead.
795  **/
796 GString*
797 g_string_up (GString *string)
798 {
799   guchar *s;
800   glong n = string->len;
801
802   g_return_val_if_fail (string != NULL, NULL);
803
804   s = (guchar *) string->str;
805
806   while (n)
807     {
808       if (islower (*s))
809         *s = toupper (*s);
810       s++;
811       n--;
812     }
813
814   return string;
815 }
816
817 static void
818 g_string_append_printf_internal (GString     *string,
819                                  const gchar *fmt,
820                                  va_list      args)
821 {
822   gchar *buffer;
823   gint length;
824   
825   length = g_vasprintf (&buffer, fmt, args);
826   g_string_append_len (string, buffer, length);
827   g_free (buffer);
828 }
829
830 void
831 g_string_printf (GString *string,
832                  const gchar *fmt,
833                  ...)
834 {
835   va_list args;
836
837   g_string_truncate (string, 0);
838
839   va_start (args, fmt);
840   g_string_append_printf_internal (string, fmt, args);
841   va_end (args);
842 }
843
844 void
845 g_string_append_printf (GString *string,
846                         const gchar *fmt,
847                         ...)
848 {
849   va_list args;
850
851   va_start (args, fmt);
852   g_string_append_printf_internal (string, fmt, args);
853   va_end (args);
854 }