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