reflect renaming of g_string_sprintfa to g_string_printfa
[platform/upstream/glib.git] / 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 typedef struct _GRealStringChunk GRealStringChunk;
46 typedef struct _GRealString      GRealString;
47
48 struct _GRealStringChunk
49 {
50   GHashTable *const_table;
51   GSList     *storage_list;
52   gint        storage_next;
53   gint        this_size;
54   gint        default_size;
55 };
56
57 struct _GRealString
58 {
59   gchar *str;
60   gint   len;
61   gint   alloc;
62 };
63
64 G_LOCK_DEFINE_STATIC (string_mem_chunk);
65 static GMemChunk *string_mem_chunk = NULL;
66
67 /* Hash Functions.
68  */
69
70 gboolean
71 g_str_equal (gconstpointer v1,
72              gconstpointer v2)
73 {
74   const gchar *string1 = v1;
75   const gchar *string2 = v2;
76   
77   return strcmp (string1, string2) == 0;
78 }
79
80 /* 31 bit hash function */
81 guint
82 g_str_hash (gconstpointer key)
83 {
84   const char *p = key;
85   guint h = *p;
86
87   if (h)
88     for (p += 1; *p != '\0'; p++)
89       h = (h << 5) - h + *p;
90
91   return h;
92 }
93
94
95 /* String Chunks.
96  */
97
98 GStringChunk*
99 g_string_chunk_new (gint default_size)
100 {
101   GRealStringChunk *new_chunk = g_new (GRealStringChunk, 1);
102   gint size = 1;
103
104   while (size < default_size)
105     size <<= 1;
106
107   new_chunk->const_table       = NULL;
108   new_chunk->storage_list      = NULL;
109   new_chunk->storage_next      = size;
110   new_chunk->default_size      = size;
111   new_chunk->this_size         = size;
112
113   return (GStringChunk*) new_chunk;
114 }
115
116 void
117 g_string_chunk_free (GStringChunk *fchunk)
118 {
119   GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
120   GSList *tmp_list;
121
122   g_return_if_fail (chunk != NULL);
123
124   if (chunk->storage_list)
125     {
126       for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
127         g_free (tmp_list->data);
128
129       g_slist_free (chunk->storage_list);
130     }
131
132   if (chunk->const_table)
133     g_hash_table_destroy (chunk->const_table);
134
135   g_free (chunk);
136 }
137
138 gchar*
139 g_string_chunk_insert (GStringChunk *fchunk,
140                        const gchar  *string)
141 {
142   GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
143   gint len = strlen (string);
144   char* pos;
145
146   g_return_val_if_fail (chunk != NULL, NULL);
147
148   if ((chunk->storage_next + len + 1) > chunk->this_size)
149     {
150       gint new_size = chunk->default_size;
151
152       while (new_size < len+1)
153         new_size <<= 1;
154
155       chunk->storage_list = g_slist_prepend (chunk->storage_list,
156                                              g_new (char, new_size));
157
158       chunk->this_size = new_size;
159       chunk->storage_next = 0;
160     }
161
162   pos = ((char *) chunk->storage_list->data) + chunk->storage_next;
163
164   strcpy (pos, string);
165
166   chunk->storage_next += len + 1;
167
168   return pos;
169 }
170
171 gchar*
172 g_string_chunk_insert_const (GStringChunk *fchunk,
173                              const gchar  *string)
174 {
175   GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
176   char* lookup;
177
178   g_return_val_if_fail (chunk != NULL, NULL);
179
180   if (!chunk->const_table)
181     chunk->const_table = g_hash_table_new (g_str_hash, g_str_equal);
182
183   lookup = (char*) g_hash_table_lookup (chunk->const_table, (gchar *)string);
184
185   if (!lookup)
186     {
187       lookup = g_string_chunk_insert (fchunk, string);
188       g_hash_table_insert (chunk->const_table, lookup, lookup);
189     }
190
191   return lookup;
192 }
193
194 /* Strings.
195  */
196 static inline gint
197 nearest_power (gint num)
198 {
199   gint n = 1;
200
201   while (n < num)
202     n <<= 1;
203
204   return n;
205 }
206
207 static void
208 g_string_maybe_expand (GRealString* string, gint len)
209 {
210   if (string->len + len >= string->alloc)
211     {
212       string->alloc = nearest_power (string->len + len + 1);
213       string->str = g_realloc (string->str, string->alloc);
214     }
215 }
216
217 GString*
218 g_string_sized_new (guint dfl_size)
219 {
220   GRealString *string;
221
222   G_LOCK (string_mem_chunk);
223   if (!string_mem_chunk)
224     string_mem_chunk = g_mem_chunk_new ("string mem chunk",
225                                         sizeof (GRealString),
226                                         1024, G_ALLOC_AND_FREE);
227
228   string = g_chunk_new (GRealString, string_mem_chunk);
229   G_UNLOCK (string_mem_chunk);
230
231   string->alloc = 0;
232   string->len   = 0;
233   string->str   = NULL;
234
235   g_string_maybe_expand (string, MAX (dfl_size, 2));
236   string->str[0] = 0;
237
238   return (GString*) string;
239 }
240
241 GString*
242 g_string_new (const gchar *init)
243 {
244   GString *string;
245
246   string = g_string_sized_new (init ? strlen (init) + 2 : 2);
247
248   if (init)
249     g_string_append (string, init);
250
251   return string;
252 }
253
254 GString*
255 g_string_new_len (const gchar *init,
256                   gint         len)
257 {
258   GString *string;
259
260   if (len < 0)
261     return g_string_new (init);
262   else
263     {
264       string = g_string_sized_new (len);
265       
266       if (init)
267         g_string_append_len (string, init, len);
268       
269       return string;
270     }
271 }
272
273 gchar*
274 g_string_free (GString *string,
275                gboolean free_segment)
276 {
277   gchar *segment;
278
279   g_return_val_if_fail (string != NULL, NULL);
280
281   if (free_segment)
282     {
283       g_free (string->str);
284       segment = NULL;
285     }
286   else
287     segment = string->str;
288
289   G_LOCK (string_mem_chunk);
290   g_mem_chunk_free (string_mem_chunk, string);
291   G_UNLOCK (string_mem_chunk);
292
293   return segment;
294 }
295
296 gboolean
297 g_string_equal (const GString *v,
298                 const GString *v2)
299 {
300   gchar *p, *q;
301   GRealString *string1 = (GRealString *) v;
302   GRealString *string2 = (GRealString *) v2;
303   gint i = string1->len;
304
305   if (i != string2->len)
306     return FALSE;
307
308   p = string1->str;
309   q = string2->str;
310   while (i)
311     {
312       if (*p != *q)
313         return FALSE;
314       p++;
315       q++;
316       i--;
317     }
318   return TRUE;
319 }
320
321 /* 31 bit hash function */
322 guint
323 g_string_hash (const GString *str)
324 {
325   const gchar *p = str->str;
326   gint n = str->len;
327   guint h = 0;
328
329   while (n--)
330     {
331       h = (h << 5) - h + *p;
332       p++;
333     }
334
335   return h;
336 }
337
338 GString*
339 g_string_assign (GString     *string,
340                  const gchar *rval)
341 {
342   g_return_val_if_fail (string != NULL, NULL);
343   g_return_val_if_fail (rval != NULL, string);
344   
345   g_string_truncate (string, 0);
346   g_string_append (string, rval);
347
348   return string;
349 }
350
351 GString*
352 g_string_truncate (GString *fstring,
353                    guint    len)
354 {
355   GRealString *string = (GRealString *) fstring;
356
357   g_return_val_if_fail (string != NULL, NULL);
358
359   string->len = MIN (len, string->len);
360
361   string->str[string->len] = 0;
362
363   return fstring;
364 }
365
366 GString*
367 g_string_insert_len (GString     *fstring,
368                      gint         pos,
369                      const gchar *val,
370                      gint         len)
371 {
372   GRealString *string = (GRealString *) fstring;
373
374   g_return_val_if_fail (string != NULL, NULL);
375   g_return_val_if_fail (val != NULL, fstring);
376   g_return_val_if_fail (pos <= string->len, fstring);
377
378   if (len < 0)
379     len = strlen (val);
380
381   if (pos < 0)
382     pos = string->len;
383   
384   g_string_maybe_expand (string, len);
385
386   /* If we aren't appending at the end, move a hunk
387    * of the old string to the end, opening up space
388    */
389   if (pos < string->len)
390     g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
391   
392   /* insert the new string */
393   g_memmove (string->str + pos, val, len);
394
395   string->len += len;
396
397   string->str[string->len] = 0;
398
399   return fstring;
400 }
401
402 GString*
403 g_string_append (GString     *fstring,
404                  const gchar *val)
405 {  
406   g_return_val_if_fail (fstring != NULL, NULL);
407   g_return_val_if_fail (val != NULL, fstring);
408
409   return g_string_insert_len (fstring, -1, val, -1);
410 }
411
412 GString*
413 g_string_append_len (GString     *string,
414                      const gchar *val,
415                      gint         len)
416 {
417   g_return_val_if_fail (string != NULL, NULL);
418   g_return_val_if_fail (val != NULL, string);
419
420   return g_string_insert_len (string, -1, val, len);
421 }
422
423 GString*
424 g_string_append_c (GString *fstring,
425                    gchar    c)
426 {
427   g_return_val_if_fail (fstring != NULL, NULL);
428
429   return g_string_insert_c (fstring, -1, c);
430 }
431
432 GString*
433 g_string_prepend (GString     *fstring,
434                   const gchar *val)
435 {
436   g_return_val_if_fail (fstring != NULL, NULL);
437   g_return_val_if_fail (val != NULL, fstring);
438   
439   return g_string_insert_len (fstring, 0, val, -1);
440 }
441
442 GString*
443 g_string_prepend_len (GString     *string,
444                       const gchar *val,
445                       gint         len)
446 {
447   g_return_val_if_fail (string != NULL, NULL);
448   g_return_val_if_fail (val != NULL, string);
449
450   return g_string_insert_len (string, 0, val, len);
451 }
452
453 GString*
454 g_string_prepend_c (GString *fstring,
455                     gchar    c)
456 {  
457   g_return_val_if_fail (fstring != NULL, NULL);
458   
459   return g_string_insert_c (fstring, 0, c);
460 }
461
462 GString*
463 g_string_insert (GString     *fstring,
464                  gint         pos,
465                  const gchar *val)
466 {
467   g_return_val_if_fail (fstring != NULL, NULL);
468   g_return_val_if_fail (val != NULL, fstring);
469   g_return_val_if_fail (pos <= fstring->len, fstring);
470   
471   return g_string_insert_len (fstring, pos, val, -1);
472 }
473
474 GString*
475 g_string_insert_c (GString *fstring,
476                    gint     pos,
477                    gchar    c)
478 {
479   GRealString *string = (GRealString *) fstring;
480
481   g_return_val_if_fail (string != NULL, NULL);
482   g_return_val_if_fail (pos <= string->len, fstring);
483
484   g_string_maybe_expand (string, 1);
485
486   if (pos < 0)
487     pos = string->len;
488   
489   /* If not just an append, move the old stuff */
490   if (pos < string->len)
491     g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
492
493   string->str[pos] = c;
494
495   string->len += 1;
496
497   string->str[string->len] = 0;
498
499   return fstring;
500 }
501
502 GString*
503 g_string_erase (GString *fstring,
504                 gint     pos,
505                 gint     len)
506 {
507   GRealString *string = (GRealString*)fstring;
508
509   g_return_val_if_fail (string != NULL, NULL);
510   g_return_val_if_fail (len >= 0, fstring);
511   g_return_val_if_fail (pos >= 0, fstring);
512   g_return_val_if_fail (pos <= string->len, fstring);
513   g_return_val_if_fail (pos + len <= string->len, fstring);
514
515   if (pos + len < string->len)
516     g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
517
518   string->len -= len;
519   
520   string->str[string->len] = 0;
521
522   return fstring;
523 }
524
525 GString*
526 g_string_down (GString *fstring)
527 {
528   GRealString *string = (GRealString *) fstring;
529   guchar *s;
530   gint n = string->len;
531
532   g_return_val_if_fail (string != NULL, NULL);
533
534   s = (guchar *) string->str;
535
536   while (n)
537     {
538       *s = tolower (*s);
539       s++;
540       n--;
541     }
542
543   return fstring;
544 }
545
546 GString*
547 g_string_up (GString *fstring)
548 {
549   GRealString *string = (GRealString *) fstring;
550   guchar *s;
551   gint n = string->len;
552
553   g_return_val_if_fail (string != NULL, NULL);
554
555   s = (guchar *) string->str;
556
557   while (n)
558     {
559       *s = toupper (*s);
560       s++;
561       n--;
562     }
563
564   return fstring;
565 }
566
567 static void
568 g_string_printfa_internal (GString     *string,
569                            const gchar *fmt,
570                            va_list      args)
571 {
572   gchar *buffer;
573
574   buffer = g_strdup_vprintf (fmt, args);
575   g_string_append (string, buffer);
576   g_free (buffer);
577 }
578
579 void
580 g_string_printf (GString *string,
581                  const gchar *fmt,
582                  ...)
583 {
584   va_list args;
585
586   g_string_truncate (string, 0);
587
588   va_start (args, fmt);
589   g_string_printfa_internal (string, fmt, args);
590   va_end (args);
591 }
592
593 void
594 g_string_printfa (GString *string,
595                   const gchar *fmt,
596                   ...)
597 {
598   va_list args;
599
600   va_start (args, fmt);
601   g_string_printfa_internal (string, fmt, args);
602   va_end (args);
603 }