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