From Edward M. Lee <tailbert@yahoo.com>:
[glib.git] / gstring.c
bloba720ac73d70debb216156822c41a3d6a58763d95
1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
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/.
27 /*
28 * MT safe
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
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"
45 typedef struct _GRealStringChunk GRealStringChunk;
46 typedef struct _GRealString GRealString;
48 struct _GRealStringChunk
50 GHashTable *const_table;
51 GSList *storage_list;
52 gint storage_next;
53 gint this_size;
54 gint default_size;
57 struct _GRealString
59 gchar *str;
60 gint len;
61 gint alloc;
64 G_LOCK_DEFINE_STATIC (string_mem_chunk);
65 static GMemChunk *string_mem_chunk = NULL;
67 /* Hash Functions.
70 gboolean
71 g_str_equal (gconstpointer v1,
72 gconstpointer v2)
74 const gchar *string1 = v1;
75 const gchar *string2 = v2;
77 return strcmp (string1, string2) == 0;
80 /* 31 bit hash function */
81 guint
82 g_str_hash (gconstpointer key)
84 const char *p = key;
85 guint h = *p;
87 if (h)
88 for (p += 1; *p != '\0'; p++)
89 h = (h << 5) - h + *p;
91 return h;
95 /* String Chunks.
98 GStringChunk*
99 g_string_chunk_new (gint default_size)
101 GRealStringChunk *new_chunk = g_new (GRealStringChunk, 1);
102 gint size = 1;
104 while (size < default_size)
105 size <<= 1;
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;
113 return (GStringChunk*) new_chunk;
116 void
117 g_string_chunk_free (GStringChunk *fchunk)
119 GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
120 GSList *tmp_list;
122 g_return_if_fail (chunk != NULL);
124 if (chunk->storage_list)
126 for (tmp_list = chunk->storage_list; tmp_list; tmp_list = tmp_list->next)
127 g_free (tmp_list->data);
129 g_slist_free (chunk->storage_list);
132 if (chunk->const_table)
133 g_hash_table_destroy (chunk->const_table);
135 g_free (chunk);
138 gchar*
139 g_string_chunk_insert (GStringChunk *fchunk,
140 const gchar *string)
142 GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
143 gint len = strlen (string);
144 char* pos;
146 g_return_val_if_fail (chunk != NULL, NULL);
148 if ((chunk->storage_next + len + 1) > chunk->this_size)
150 gint new_size = chunk->default_size;
152 while (new_size < len+1)
153 new_size <<= 1;
155 chunk->storage_list = g_slist_prepend (chunk->storage_list,
156 g_new (char, new_size));
158 chunk->this_size = new_size;
159 chunk->storage_next = 0;
162 pos = ((char *) chunk->storage_list->data) + chunk->storage_next;
164 strcpy (pos, string);
166 chunk->storage_next += len + 1;
168 return pos;
171 gchar*
172 g_string_chunk_insert_const (GStringChunk *fchunk,
173 const gchar *string)
175 GRealStringChunk *chunk = (GRealStringChunk*) fchunk;
176 char* lookup;
178 g_return_val_if_fail (chunk != NULL, NULL);
180 if (!chunk->const_table)
181 chunk->const_table = g_hash_table_new (g_str_hash, g_str_equal);
183 lookup = (char*) g_hash_table_lookup (chunk->const_table, (gchar *)string);
185 if (!lookup)
187 lookup = g_string_chunk_insert (fchunk, string);
188 g_hash_table_insert (chunk->const_table, lookup, lookup);
191 return lookup;
194 /* Strings.
196 static inline gint
197 nearest_power (gint num)
199 gint n = 1;
201 while (n < num)
202 n <<= 1;
204 return n;
207 static void
208 g_string_maybe_expand (GRealString* string, gint len)
210 if (string->len + len >= string->alloc)
212 string->alloc = nearest_power (string->len + len + 1);
213 string->str = g_realloc (string->str, string->alloc);
217 GString*
218 g_string_sized_new (guint dfl_size)
220 GRealString *string;
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);
228 string = g_chunk_new (GRealString, string_mem_chunk);
229 G_UNLOCK (string_mem_chunk);
231 string->alloc = 0;
232 string->len = 0;
233 string->str = NULL;
235 g_string_maybe_expand (string, MAX (dfl_size, 2));
236 string->str[0] = 0;
238 return (GString*) string;
241 GString*
242 g_string_new (const gchar *init)
244 GString *string;
246 string = g_string_sized_new (init ? strlen (init) + 2 : 2);
248 if (init)
249 g_string_append (string, init);
251 return string;
254 GString*
255 g_string_new_len (const gchar *init,
256 gint len)
258 GString *string;
260 if (len < 0)
261 return g_string_new (init);
262 else
264 string = g_string_sized_new (len);
266 if (init)
267 g_string_append_len (string, init, len);
269 return string;
273 gchar*
274 g_string_free (GString *string,
275 gboolean free_segment)
277 gchar *segment;
279 g_return_val_if_fail (string != NULL, NULL);
281 if (free_segment)
283 g_free (string->str);
284 segment = NULL;
286 else
287 segment = string->str;
289 G_LOCK (string_mem_chunk);
290 g_mem_chunk_free (string_mem_chunk, string);
291 G_UNLOCK (string_mem_chunk);
293 return segment;
296 gboolean
297 g_string_equal (const GString *v,
298 const GString *v2)
300 gchar *p, *q;
301 GRealString *string1 = (GRealString *) v;
302 GRealString *string2 = (GRealString *) v2;
303 gint i = string1->len;
305 if (i != string2->len)
306 return FALSE;
308 p = string1->str;
309 q = string2->str;
310 while (i)
312 if (*p != *q)
313 return FALSE;
314 p++;
315 q++;
316 i--;
318 return TRUE;
321 /* 31 bit hash function */
322 guint
323 g_string_hash (const GString *str)
325 const gchar *p = str->str;
326 gint n = str->len;
327 guint h = 0;
329 while (n--)
331 h = (h << 5) - h + *p;
332 p++;
335 return h;
338 GString*
339 g_string_assign (GString *string,
340 const gchar *rval)
342 g_return_val_if_fail (string != NULL, NULL);
343 g_return_val_if_fail (rval != NULL, string);
345 g_string_truncate (string, 0);
346 g_string_append (string, rval);
348 return string;
351 GString*
352 g_string_truncate (GString *fstring,
353 guint len)
355 GRealString *string = (GRealString *) fstring;
357 g_return_val_if_fail (string != NULL, NULL);
359 string->len = MIN (len, string->len);
361 string->str[string->len] = 0;
363 return fstring;
366 GString*
367 g_string_insert_len (GString *fstring,
368 gint pos,
369 const gchar *val,
370 gint len)
372 GRealString *string = (GRealString *) fstring;
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);
378 if (len < 0)
379 len = strlen (val);
381 if (pos < 0)
382 pos = string->len;
384 g_string_maybe_expand (string, len);
386 /* If we aren't appending at the end, move a hunk
387 * of the old string to the end, opening up space
389 if (pos < string->len)
390 g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
392 /* insert the new string */
393 g_memmove (string->str + pos, val, len);
395 string->len += len;
397 string->str[string->len] = 0;
399 return fstring;
402 GString*
403 g_string_append (GString *fstring,
404 const gchar *val)
406 g_return_val_if_fail (fstring != NULL, NULL);
407 g_return_val_if_fail (val != NULL, fstring);
409 return g_string_insert_len (fstring, -1, val, -1);
412 GString*
413 g_string_append_len (GString *string,
414 const gchar *val,
415 gint len)
417 g_return_val_if_fail (string != NULL, NULL);
418 g_return_val_if_fail (val != NULL, string);
420 return g_string_insert_len (string, -1, val, len);
423 GString*
424 g_string_append_c (GString *fstring,
425 gchar c)
427 g_return_val_if_fail (fstring != NULL, NULL);
429 return g_string_insert_c (fstring, -1, c);
432 GString*
433 g_string_prepend (GString *fstring,
434 const gchar *val)
436 g_return_val_if_fail (fstring != NULL, NULL);
437 g_return_val_if_fail (val != NULL, fstring);
439 return g_string_insert_len (fstring, 0, val, -1);
442 GString*
443 g_string_prepend_len (GString *string,
444 const gchar *val,
445 gint len)
447 g_return_val_if_fail (string != NULL, NULL);
448 g_return_val_if_fail (val != NULL, string);
450 return g_string_insert_len (string, 0, val, len);
453 GString*
454 g_string_prepend_c (GString *fstring,
455 gchar c)
457 g_return_val_if_fail (fstring != NULL, NULL);
459 return g_string_insert_c (fstring, 0, c);
462 GString*
463 g_string_insert (GString *fstring,
464 gint pos,
465 const gchar *val)
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);
471 return g_string_insert_len (fstring, pos, val, -1);
474 GString*
475 g_string_insert_c (GString *fstring,
476 gint pos,
477 gchar c)
479 GRealString *string = (GRealString *) fstring;
481 g_return_val_if_fail (string != NULL, NULL);
482 g_return_val_if_fail (pos <= string->len, fstring);
484 g_string_maybe_expand (string, 1);
486 if (pos < 0)
487 pos = string->len;
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);
493 string->str[pos] = c;
495 string->len += 1;
497 string->str[string->len] = 0;
499 return fstring;
502 GString*
503 g_string_erase (GString *fstring,
504 gint pos,
505 gint len)
507 GRealString *string = (GRealString*)fstring;
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);
515 if (pos + len < string->len)
516 g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
518 string->len -= len;
520 string->str[string->len] = 0;
522 return fstring;
525 GString*
526 g_string_down (GString *fstring)
528 GRealString *string = (GRealString *) fstring;
529 guchar *s;
530 gint n = string->len;
532 g_return_val_if_fail (string != NULL, NULL);
534 s = (guchar *) string->str;
536 while (n)
538 *s = tolower (*s);
539 s++;
540 n--;
543 return fstring;
546 GString*
547 g_string_up (GString *fstring)
549 GRealString *string = (GRealString *) fstring;
550 guchar *s;
551 gint n = string->len;
553 g_return_val_if_fail (string != NULL, NULL);
555 s = (guchar *) string->str;
557 while (n)
559 *s = toupper (*s);
560 s++;
561 n--;
564 return fstring;
567 static void
568 g_string_printfa_internal (GString *string,
569 const gchar *fmt,
570 va_list args)
572 gchar *buffer;
574 buffer = g_strdup_vprintf (fmt, args);
575 g_string_append (string, buffer);
576 g_free (buffer);
579 void
580 g_string_printf (GString *string,
581 const gchar *fmt,
582 ...)
584 va_list args;
586 g_string_truncate (string, 0);
588 va_start (args, fmt);
589 g_string_printfa_internal (string, fmt, args);
590 va_end (args);
593 void
594 g_string_printfa (GString *string,
595 const gchar *fmt,
596 ...)
598 va_list args;
600 va_start (args, fmt);
601 g_string_printfa_internal (string, fmt, args);
602 va_end (args);