inserted additional note to look for ChangeLog and AUTHORS file for a log
[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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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-1999.  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 <stdarg.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "glib.h"
37
38
39 typedef struct _GRealStringChunk GRealStringChunk;
40 typedef struct _GRealString      GRealString;
41
42 struct _GRealStringChunk
43 {
44   GHashTable *const_table;
45   GSList     *storage_list;
46   gint        storage_next;
47   gint        this_size;
48   gint        default_size;
49 };
50
51 struct _GRealString
52 {
53   gchar *str;
54   gint   len;
55   gint   alloc;
56 };
57
58 G_LOCK_DEFINE_STATIC (string_mem_chunk);
59 static GMemChunk *string_mem_chunk = NULL;
60
61 /* Hash Functions.
62  */
63
64 gint
65 g_str_equal (gconstpointer v, gconstpointer v2)
66 {
67   return strcmp ((const gchar*) v, (const gchar*)v2) == 0;
68 }
69
70 /* a char* hash function from ASU */
71 guint
72 g_str_hash (gconstpointer v)
73 {
74   const char *s = (char*)v;
75   const char *p;
76   guint h=0, g;
77
78   for(p = s; *p != '\0'; p += 1) {
79     h = ( h << 4 ) + *p;
80     if ( ( g = h & 0xf0000000 ) ) {
81       h = h ^ (g >> 24);
82       h = h ^ g;
83     }
84   }
85
86   return h /* % M */;
87 }
88
89
90 /* String Chunks.
91  */
92
93 GStringChunk*
94 g_string_chunk_new (gint default_size)
95 {
96   GRealStringChunk *new_chunk = g_new (GRealStringChunk, 1);
97   gint size = 1;
98
99   while (size < default_size)
100     size <<= 1;
101
102   new_chunk->const_table       = NULL;
103   new_chunk->storage_list      = NULL;
104   new_chunk->storage_next      = size;
105   new_chunk->default_size      = size;
106   new_chunk->this_size         = size;
107
108   return (GStringChunk*) new_chunk;
109 }
110
111 void
112 g_string_chunk_free (GStringChunk *fchunk)
113 {
114   GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
115   GSList *tmp_list;
116
117   g_return_if_fail (chunk != NULL);
118
119   if (chunk->storage_list)
120     {
121       for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
122         g_free (tmp_list->data);
123
124       g_slist_free (chunk->storage_list);
125     }
126
127   if (chunk->const_table)
128     g_hash_table_destroy (chunk->const_table);
129
130   g_free (chunk);
131 }
132
133 gchar*
134 g_string_chunk_insert (GStringChunk *fchunk,
135                        const gchar  *string)
136 {
137   GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
138   gint len = strlen (string);
139   char* pos;
140
141   g_return_val_if_fail (chunk != NULL, NULL);
142
143   if ((chunk->storage_next + len + 1) > chunk->this_size)
144     {
145       gint new_size = chunk->default_size;
146
147       while (new_size < len+1)
148         new_size <<= 1;
149
150       chunk->storage_list = g_slist_prepend (chunk->storage_list,
151                                              g_new (char, new_size));
152
153       chunk->this_size = new_size;
154       chunk->storage_next = 0;
155     }
156
157   pos = ((char*)chunk->storage_list->data) + chunk->storage_next;
158
159   strcpy (pos, string);
160
161   chunk->storage_next += len + 1;
162
163   return pos;
164 }
165
166 gchar*
167 g_string_chunk_insert_const (GStringChunk *fchunk,
168                              const gchar  *string)
169 {
170   GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
171   char* lookup;
172
173   g_return_val_if_fail (chunk != NULL, NULL);
174
175   if (!chunk->const_table)
176     chunk->const_table = g_hash_table_new (g_str_hash, g_str_equal);
177
178   lookup = (char*) g_hash_table_lookup (chunk->const_table, (gchar *)string);
179
180   if (!lookup)
181     {
182       lookup = g_string_chunk_insert (fchunk, string);
183       g_hash_table_insert (chunk->const_table, lookup, lookup);
184     }
185
186   return lookup;
187 }
188
189 /* Strings.
190  */
191 static gint
192 nearest_pow (gint num)
193 {
194   gint n = 1;
195
196   while (n < num)
197     n <<= 1;
198
199   return n;
200 }
201
202 static void
203 g_string_maybe_expand (GRealString* string, gint len)
204 {
205   if (string->len + len >= string->alloc)
206     {
207       string->alloc = nearest_pow (string->len + len + 1);
208       string->str = g_realloc (string->str, string->alloc);
209     }
210 }
211
212 GString*
213 g_string_sized_new (guint dfl_size)
214 {
215   GRealString *string;
216
217   G_LOCK (string_mem_chunk);
218   if (!string_mem_chunk)
219     string_mem_chunk = g_mem_chunk_new ("string mem chunk",
220                                         sizeof (GRealString),
221                                         1024, G_ALLOC_AND_FREE);
222
223   string = g_chunk_new (GRealString, string_mem_chunk);
224   G_UNLOCK (string_mem_chunk);
225
226   string->alloc = 0;
227   string->len   = 0;
228   string->str   = NULL;
229
230   g_string_maybe_expand (string, MAX (dfl_size, 2));
231   string->str[0] = 0;
232
233   return (GString*) string;
234 }
235
236 GString*
237 g_string_new (const gchar *init)
238 {
239   GString *string;
240
241   string = g_string_sized_new (2);
242
243   if (init)
244     g_string_append (string, init);
245
246   return string;
247 }
248
249 void
250 g_string_free (GString *string,
251                gint free_segment)
252 {
253   g_return_if_fail (string != NULL);
254
255   if (free_segment)
256     g_free (string->str);
257
258   G_LOCK (string_mem_chunk);
259   g_mem_chunk_free (string_mem_chunk, string);
260   G_UNLOCK (string_mem_chunk);
261 }
262
263 GString*
264 g_string_assign (GString *lval,
265                  const gchar *rval)
266 {
267   g_string_truncate (lval, 0);
268   g_string_append (lval, rval);
269
270   return lval;
271 }
272
273 GString*
274 g_string_truncate (GString* fstring,
275                    gint len)
276 {
277   GRealString *string = (GRealString*)fstring;
278
279   g_return_val_if_fail (string != NULL, NULL);
280
281   string->len = len;
282
283   string->str[len] = 0;
284
285   return fstring;
286 }
287
288 GString*
289 g_string_append (GString *fstring,
290                  const gchar *val)
291 {
292   GRealString *string = (GRealString*)fstring;
293   int len;
294
295   g_return_val_if_fail (string != NULL, NULL);
296   g_return_val_if_fail (val != NULL, fstring);
297   
298   len = strlen (val);
299   g_string_maybe_expand (string, len);
300
301   strcpy (string->str + string->len, val);
302
303   string->len += len;
304
305   return fstring;
306 }
307
308 GString*
309 g_string_append_c (GString *fstring,
310                    gchar c)
311 {
312   GRealString *string = (GRealString*)fstring;
313
314   g_return_val_if_fail (string != NULL, NULL);
315   g_string_maybe_expand (string, 1);
316
317   string->str[string->len++] = c;
318   string->str[string->len] = 0;
319
320   return fstring;
321 }
322
323 GString*
324 g_string_prepend (GString *fstring,
325                   const gchar *val)
326 {
327   GRealString *string = (GRealString*)fstring;
328   gint len;
329
330   g_return_val_if_fail (string != NULL, NULL);
331   g_return_val_if_fail (val != NULL, fstring);
332
333   len = strlen (val);
334   g_string_maybe_expand (string, len);
335
336   g_memmove (string->str + len, string->str, string->len);
337
338   strncpy (string->str, val, len);
339
340   string->len += len;
341
342   string->str[string->len] = 0;
343
344   return fstring;
345 }
346
347 GString*
348 g_string_prepend_c (GString *fstring,
349                     gchar    c)
350 {
351   GRealString *string = (GRealString*)fstring;
352
353   g_return_val_if_fail (string != NULL, NULL);
354   g_string_maybe_expand (string, 1);
355
356   g_memmove (string->str + 1, string->str, string->len);
357
358   string->str[0] = c;
359
360   string->len += 1;
361
362   string->str[string->len] = 0;
363
364   return fstring;
365 }
366
367 GString*
368 g_string_insert (GString     *fstring,
369                  gint         pos,
370                  const gchar *val)
371 {
372   GRealString *string = (GRealString*)fstring;
373   gint len;
374
375   g_return_val_if_fail (string != NULL, NULL);
376   g_return_val_if_fail (val != NULL, fstring);
377   g_return_val_if_fail (pos >= 0, fstring);
378   g_return_val_if_fail (pos <= string->len, fstring);
379
380   len = strlen (val);
381   g_string_maybe_expand (string, len);
382
383   g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
384
385   strncpy (string->str + pos, val, len);
386
387   string->len += len;
388
389   string->str[string->len] = 0;
390
391   return fstring;
392 }
393
394 GString *
395 g_string_insert_c (GString *fstring,
396                    gint     pos,
397                    gchar    c)
398 {
399   GRealString *string = (GRealString*)fstring;
400
401   g_return_val_if_fail (string != NULL, NULL);
402   g_return_val_if_fail (pos <= string->len, fstring);
403
404   g_string_maybe_expand (string, 1);
405
406   g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
407
408   string->str[pos] = c;
409
410   string->len += 1;
411
412   string->str[string->len] = 0;
413
414   return fstring;
415 }
416
417 GString*
418 g_string_erase (GString *fstring,
419                 gint pos,
420                 gint len)
421 {
422   GRealString *string = (GRealString*)fstring;
423
424   g_return_val_if_fail (string != NULL, NULL);
425   g_return_val_if_fail (len >= 0, fstring);
426   g_return_val_if_fail (pos >= 0, fstring);
427   g_return_val_if_fail (pos <= string->len, fstring);
428   g_return_val_if_fail (pos + len <= string->len, fstring);
429
430   if (pos + len < string->len)
431     g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
432
433   string->len -= len;
434   
435   string->str[string->len] = 0;
436
437   return fstring;
438 }
439
440 GString*
441 g_string_down (GString *fstring)
442 {
443   GRealString *string = (GRealString*)fstring;
444   gchar *s;
445
446   g_return_val_if_fail (string != NULL, NULL);
447
448   s = string->str;
449
450   while (*s)
451     {
452       *s = tolower (*s);
453       s++;
454     }
455
456   return fstring;
457 }
458
459 GString*
460 g_string_up (GString *fstring)
461 {
462   GRealString *string = (GRealString*)fstring;
463   gchar *s;
464
465   g_return_val_if_fail (string != NULL, NULL);
466
467   s = string->str;
468
469   while (*s)
470     {
471       *s = toupper (*s);
472       s++;
473     }
474
475   return fstring;
476 }
477
478 static void
479 g_string_sprintfa_int (GString     *string,
480                        const gchar *fmt,
481                        va_list      args)
482 {
483   gchar *buffer;
484
485   buffer = g_strdup_vprintf (fmt, args);
486   g_string_append (string, buffer);
487   g_free (buffer);
488 }
489
490 void
491 g_string_sprintf (GString *string,
492                   const gchar *fmt,
493                   ...)
494 {
495   va_list args;
496
497   g_string_truncate (string, 0);
498
499   va_start (args, fmt);
500   g_string_sprintfa_int (string, fmt, args);
501   va_end (args);
502 }
503
504 void
505 g_string_sprintfa (GString *string,
506                    const gchar *fmt,
507                    ...)
508 {
509   va_list args;
510
511   va_start (args, fmt);
512   g_string_sprintfa_int (string, fmt, args);
513   va_end (args);
514 }