Test for sched_yield as the native yield function first. Corrected typo
[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 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 (2);
247
248   if (init)
249     g_string_append (string, init);
250
251   return string;
252 }
253
254 void
255 g_string_free (GString *string,
256                gboolean free_segment)
257 {
258   g_return_if_fail (string != NULL);
259
260   if (free_segment)
261     g_free (string->str);
262
263   G_LOCK (string_mem_chunk);
264   g_mem_chunk_free (string_mem_chunk, string);
265   G_UNLOCK (string_mem_chunk);
266 }
267
268 GString*
269 g_string_assign (GString     *string,
270                  const gchar *rval)
271 {
272   g_return_val_if_fail (string != NULL, NULL);
273   g_return_val_if_fail (rval != NULL, string);
274   
275   g_string_truncate (string, 0);
276   g_string_append (string, rval);
277
278   return string;
279 }
280
281 GString*
282 g_string_truncate (GString *fstring,
283                    gint     len)
284 {
285   GRealString *string = (GRealString *) fstring;
286
287   g_return_val_if_fail (string != NULL, NULL);
288
289   string->len = MIN (len, string->len);
290
291   string->str[string->len] = 0;
292
293   return fstring;
294 }
295
296 GString*
297 g_string_insert_len (GString     *fstring,
298                      gint         pos,
299                      const gchar *val,
300                      gint         len)
301 {
302   GRealString *string = (GRealString *) fstring;
303
304   g_return_val_if_fail (string != NULL, NULL);
305   g_return_val_if_fail (val != NULL, fstring);
306   g_return_val_if_fail (pos <= string->len, fstring);
307
308   if (len < 0)
309     len = strlen (val);
310
311   if (pos < 0)
312     pos = string->len;
313   
314   g_string_maybe_expand (string, len);
315
316   /* If we aren't appending at the end, move a hunk
317    * of the old string to the end, opening up space
318    */
319   if (pos < string->len)
320     g_memmove (string->str + pos + len, string->str + pos, string->len - pos);
321   
322   /* insert the new string */
323   strncpy (string->str + pos, val, len);
324
325   string->len += len;
326
327   string->str[string->len] = 0;
328
329   return fstring;
330 }
331
332 GString*
333 g_string_append (GString     *fstring,
334                  const gchar *val)
335 {  
336   g_return_val_if_fail (fstring != NULL, NULL);
337   g_return_val_if_fail (val != NULL, fstring);
338
339   return g_string_insert_len (fstring, -1, val, -1);
340 }
341
342 GString*
343 g_string_append_len (GString     *string,
344                      const gchar *val,
345                      gint         len)
346 {
347   g_return_val_if_fail (string != NULL, NULL);
348   g_return_val_if_fail (val != NULL, string);
349
350   return g_string_insert_len (string, -1, val, len);
351 }
352
353 GString*
354 g_string_append_c (GString *fstring,
355                    gchar    c)
356 {
357   g_return_val_if_fail (fstring != NULL, NULL);
358
359   return g_string_insert_c (fstring, -1, c);
360 }
361
362 GString*
363 g_string_prepend (GString     *fstring,
364                   const gchar *val)
365 {
366   g_return_val_if_fail (fstring != NULL, NULL);
367   g_return_val_if_fail (val != NULL, fstring);
368   
369   return g_string_insert_len (fstring, 0, val, -1);
370 }
371
372 GString*
373 g_string_prepend_len (GString     *string,
374                       const gchar *val,
375                       gint         len)
376 {
377   g_return_val_if_fail (string != NULL, NULL);
378   g_return_val_if_fail (val != NULL, string);
379
380   return g_string_insert_len (string, 0, val, len);
381 }
382
383 GString*
384 g_string_prepend_c (GString *fstring,
385                     gchar    c)
386 {  
387   g_return_val_if_fail (fstring != NULL, NULL);
388   
389   return g_string_insert_c (fstring, 0, c);
390 }
391
392 GString*
393 g_string_insert (GString     *fstring,
394                  gint         pos,
395                  const gchar *val)
396 {
397   g_return_val_if_fail (fstring != NULL, NULL);
398   g_return_val_if_fail (val != NULL, fstring);
399   g_return_val_if_fail (pos <= fstring->len, fstring);
400   
401   return g_string_insert_len (fstring, pos, val, -1);
402 }
403
404 GString*
405 g_string_insert_c (GString *fstring,
406                    gint     pos,
407                    gchar    c)
408 {
409   GRealString *string = (GRealString *) fstring;
410
411   g_return_val_if_fail (string != NULL, NULL);
412   g_return_val_if_fail (pos <= string->len, fstring);
413
414   g_string_maybe_expand (string, 1);
415
416   if (pos < 0)
417     pos = string->len;
418   
419   /* If not just an append, move the old stuff */
420   if (pos < string->len)
421     g_memmove (string->str + pos + 1, string->str + pos, string->len - pos);
422
423   string->str[pos] = c;
424
425   string->len += 1;
426
427   string->str[string->len] = 0;
428
429   return fstring;
430 }
431
432 GString*
433 g_string_erase (GString *fstring,
434                 gint     pos,
435                 gint     len)
436 {
437   GRealString *string = (GRealString*)fstring;
438
439   g_return_val_if_fail (string != NULL, NULL);
440   g_return_val_if_fail (len >= 0, fstring);
441   g_return_val_if_fail (pos >= 0, fstring);
442   g_return_val_if_fail (pos <= string->len, fstring);
443   g_return_val_if_fail (pos + len <= string->len, fstring);
444
445   if (pos + len < string->len)
446     g_memmove (string->str + pos, string->str + pos + len, string->len - (pos + len));
447
448   string->len -= len;
449   
450   string->str[string->len] = 0;
451
452   return fstring;
453 }
454
455 GString*
456 g_string_down (GString *fstring)
457 {
458   GRealString *string = (GRealString *) fstring;
459   guchar *s;
460
461   g_return_val_if_fail (string != NULL, NULL);
462
463   s = string->str;
464
465   while (*s)
466     {
467       *s = tolower (*s);
468       s++;
469     }
470
471   return fstring;
472 }
473
474 GString*
475 g_string_up (GString *fstring)
476 {
477   GRealString *string = (GRealString *) fstring;
478   guchar *s;
479
480   g_return_val_if_fail (string != NULL, NULL);
481
482   s = string->str;
483
484   while (*s)
485     {
486       *s = toupper (*s);
487       s++;
488     }
489
490   return fstring;
491 }
492
493 static void
494 g_string_sprintfa_int (GString     *string,
495                        const gchar *fmt,
496                        va_list      args)
497 {
498   gchar *buffer;
499
500   buffer = g_strdup_vprintf (fmt, args);
501   g_string_append (string, buffer);
502   g_free (buffer);
503 }
504
505 void
506 g_string_sprintf (GString *string,
507                   const gchar *fmt,
508                   ...)
509 {
510   va_list args;
511
512   g_string_truncate (string, 0);
513
514   va_start (args, fmt);
515   g_string_sprintfa_int (string, fmt, args);
516   va_end (args);
517 }
518
519 void
520 g_string_sprintfa (GString *string,
521                    const gchar *fmt,
522                    ...)
523 {
524   va_list args;
525
526   va_start (args, fmt);
527   g_string_sprintfa_int (string, fmt, args);
528   va_end (args);
529 }