[Changes from josh to sync with his glib stuff -Yosh]
[platform/upstream/glib.git] / gutils.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 <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <locale.h>
24 #include <ctype.h>              /* For tolower() */
25 #include "glib.h"
26
27 const guint glib_major_version = GLIB_MAJOR_VERSION;
28 const guint glib_minor_version = GLIB_MINOR_VERSION;
29 const guint glib_micro_version = GLIB_MICRO_VERSION;
30
31 extern char* g_vsprintf (const gchar *fmt, va_list *args, va_list *args2);
32
33 gchar*
34 g_strdup (const gchar *str)
35 {
36   gchar *new_str;
37   
38   new_str = NULL;
39   if (str)
40     {
41       new_str = g_new (char, strlen (str) + 1);
42       strcpy (new_str, str);
43     }
44   
45   return new_str;
46 }
47
48 gchar*
49 g_strconcat (const gchar *string1, ...)
50 {
51   guint   l;
52   va_list args;
53   gchar   *s;
54   gchar   *concat;
55   
56   g_return_val_if_fail (string1 != NULL, NULL);
57   
58   l = 1 + strlen (string1);
59   va_start (args, string1);
60   s = va_arg (args, gchar*);
61   while (s)
62     {
63       l += strlen (s);
64       s = va_arg (args, gchar*);
65     }
66   va_end (args);
67   
68   concat = g_new (gchar, l);
69   concat[0] = 0;
70   
71   strcat (concat, string1);
72   va_start (args, string1);
73   s = va_arg (args, gchar*);
74   while (s)
75     {
76       strcat (concat, s);
77       s = va_arg (args, gchar*);
78     }
79   va_end (args);
80   
81   return concat;
82 }
83
84 gdouble
85 g_strtod (const gchar *nptr,
86           gchar **endptr)
87 {
88   gchar *fail_pos_1;
89   gchar *fail_pos_2;
90   gdouble val_1;
91   gdouble val_2 = 0;
92
93   g_return_val_if_fail (nptr != NULL, 0);
94
95   fail_pos_1 = NULL;
96   fail_pos_2 = NULL;
97
98   val_1 = strtod (nptr, &fail_pos_1);
99
100   if (fail_pos_1 && fail_pos_1[0] != 0)
101     {
102       gchar *old_locale;
103
104       old_locale = setlocale (LC_NUMERIC, "C");
105       val_2 = strtod (nptr, &fail_pos_2);
106       setlocale (LC_NUMERIC, old_locale);
107     }
108
109   if (!fail_pos_1 || fail_pos_1[0] == 0 || fail_pos_1 >= fail_pos_2)
110     {
111       if (endptr)
112         *endptr = fail_pos_1;
113       return val_1;
114     }
115   else
116     {
117       if (endptr)
118         *endptr = fail_pos_2;
119       return val_2;
120     }
121 }
122
123 gchar*
124 g_strerror (gint errnum)
125 {
126   static char msg[64];
127   
128 #ifdef HAVE_STRERROR
129   return strerror (errnum);
130 #elif NO_SYS_ERRLIST
131   switch (errnum)
132     {
133 #ifdef E2BIG
134     case E2BIG: return "argument list too long";
135 #endif
136 #ifdef EACCES
137     case EACCES: return "permission denied";
138 #endif
139 #ifdef EADDRINUSE
140     case EADDRINUSE: return "address already in use";
141 #endif
142 #ifdef EADDRNOTAVAIL
143     case EADDRNOTAVAIL: return "can't assign requested address";
144 #endif
145 #ifdef EADV
146     case EADV: return "advertise error";
147 #endif
148 #ifdef EAFNOSUPPORT
149     case EAFNOSUPPORT: return "address family not supported by protocol family";
150 #endif
151 #ifdef EAGAIN
152     case EAGAIN: return "try again";
153 #endif
154 #ifdef EALIGN
155     case EALIGN: return "EALIGN";
156 #endif
157 #ifdef EALREADY
158     case EALREADY: return "operation already in progress";
159 #endif
160 #ifdef EBADE
161     case EBADE: return "bad exchange descriptor";
162 #endif
163 #ifdef EBADF
164     case EBADF: return "bad file number";
165 #endif
166 #ifdef EBADFD
167     case EBADFD: return "file descriptor in bad state";
168 #endif
169 #ifdef EBADMSG
170     case EBADMSG: return "not a data message";
171 #endif
172 #ifdef EBADR
173     case EBADR: return "bad request descriptor";
174 #endif
175 #ifdef EBADRPC
176     case EBADRPC: return "RPC structure is bad";
177 #endif
178 #ifdef EBADRQC
179     case EBADRQC: return "bad request code";
180 #endif
181 #ifdef EBADSLT
182     case EBADSLT: return "invalid slot";
183 #endif
184 #ifdef EBFONT
185     case EBFONT: return "bad font file format";
186 #endif
187 #ifdef EBUSY
188     case EBUSY: return "mount device busy";
189 #endif
190 #ifdef ECHILD
191     case ECHILD: return "no children";
192 #endif
193 #ifdef ECHRNG
194     case ECHRNG: return "channel number out of range";
195 #endif
196 #ifdef ECOMM
197     case ECOMM: return "communication error on send";
198 #endif
199 #ifdef ECONNABORTED
200     case ECONNABORTED: return "software caused connection abort";
201 #endif
202 #ifdef ECONNREFUSED
203     case ECONNREFUSED: return "connection refused";
204 #endif
205 #ifdef ECONNRESET
206     case ECONNRESET: return "connection reset by peer";
207 #endif
208 #if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
209     case EDEADLK: return "resource deadlock avoided";
210 #endif
211 #ifdef EDEADLOCK
212     case EDEADLOCK: return "resource deadlock avoided";
213 #endif
214 #ifdef EDESTADDRREQ
215     case EDESTADDRREQ: return "destination address required";
216 #endif
217 #ifdef EDIRTY
218     case EDIRTY: return "mounting a dirty fs w/o force";
219 #endif
220 #ifdef EDOM
221     case EDOM: return "math argument out of range";
222 #endif
223 #ifdef EDOTDOT
224     case EDOTDOT: return "cross mount point";
225 #endif
226 #ifdef EDQUOT
227     case EDQUOT: return "disk quota exceeded";
228 #endif
229 #ifdef EDUPPKG
230     case EDUPPKG: return "duplicate package name";
231 #endif
232 #ifdef EEXIST
233     case EEXIST: return "file already exists";
234 #endif
235 #ifdef EFAULT
236     case EFAULT: return "bad address in system call argument";
237 #endif
238 #ifdef EFBIG
239     case EFBIG: return "file too large";
240 #endif
241 #ifdef EHOSTDOWN
242     case EHOSTDOWN: return "host is down";
243 #endif
244 #ifdef EHOSTUNREACH
245     case EHOSTUNREACH: return "host is unreachable";
246 #endif
247 #ifdef EIDRM
248     case EIDRM: return "identifier removed";
249 #endif
250 #ifdef EINIT
251     case EINIT: return "initialization error";
252 #endif
253 #ifdef EINPROGRESS
254     case EINPROGRESS: return "operation now in progress";
255 #endif
256 #ifdef EINTR
257     case EINTR: return "interrupted system call";
258 #endif
259 #ifdef EINVAL
260     case EINVAL: return "invalid argument";
261 #endif
262 #ifdef EIO
263     case EIO: return "I/O error";
264 #endif
265 #ifdef EISCONN
266     case EISCONN: return "socket is already connected";
267 #endif
268 #ifdef EISDIR
269     case EISDIR: return "illegal operation on a directory";
270 #endif
271 #ifdef EISNAME
272     case EISNAM: return "is a name file";
273 #endif
274 #ifdef ELBIN
275     case ELBIN: return "ELBIN";
276 #endif
277 #ifdef EL2HLT
278     case EL2HLT: return "level 2 halted";
279 #endif
280 #ifdef EL2NSYNC
281     case EL2NSYNC: return "level 2 not synchronized";
282 #endif
283 #ifdef EL3HLT
284     case EL3HLT: return "level 3 halted";
285 #endif
286 #ifdef EL3RST
287     case EL3RST: return "level 3 reset";
288 #endif
289 #ifdef ELIBACC
290     case ELIBACC: return "can not access a needed shared library";
291 #endif
292 #ifdef ELIBBAD
293     case ELIBBAD: return "accessing a corrupted shared library";
294 #endif
295 #ifdef ELIBEXEC
296     case ELIBEXEC: return "can not exec a shared library directly";
297 #endif
298 #ifdef ELIBMAX
299     case ELIBMAX: return "attempting to link in more shared libraries than system limit";
300 #endif
301 #ifdef ELIBSCN
302     case ELIBSCN: return ".lib section in a.out corrupted";
303 #endif
304 #ifdef ELNRNG
305     case ELNRNG: return "link number out of range";
306 #endif
307 #ifdef ELOOP
308     case ELOOP: return "too many levels of symbolic links";
309 #endif
310 #ifdef EMFILE
311     case EMFILE: return "too many open files";
312 #endif
313 #ifdef EMLINK
314     case EMLINK: return "too many links";
315 #endif
316 #ifdef EMSGSIZE
317     case EMSGSIZE: return "message too long";
318 #endif
319 #ifdef EMULTIHOP
320     case EMULTIHOP: return "multihop attempted";
321 #endif
322 #ifdef ENAMETOOLONG
323     case ENAMETOOLONG: return "file name too long";
324 #endif
325 #ifdef ENAVAIL
326     case ENAVAIL: return "not available";
327 #endif
328 #ifdef ENET
329     case ENET: return "ENET";
330 #endif
331 #ifdef ENETDOWN
332     case ENETDOWN: return "network is down";
333 #endif
334 #ifdef ENETRESET
335     case ENETRESET: return "network dropped connection on reset";
336 #endif
337 #ifdef ENETUNREACH
338     case ENETUNREACH: return "network is unreachable";
339 #endif
340 #ifdef ENFILE
341     case ENFILE: return "file table overflow";
342 #endif
343 #ifdef ENOANO
344     case ENOANO: return "anode table overflow";
345 #endif
346 #if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
347     case ENOBUFS: return "no buffer space available";
348 #endif
349 #ifdef ENOCSI
350     case ENOCSI: return "no CSI structure available";
351 #endif
352 #ifdef ENODATA
353     case ENODATA: return "no data available";
354 #endif
355 #ifdef ENODEV
356     case ENODEV: return "no such device";
357 #endif
358 #ifdef ENOENT
359     case ENOENT: return "no such file or directory";
360 #endif
361 #ifdef ENOEXEC
362     case ENOEXEC: return "exec format error";
363 #endif
364 #ifdef ENOLCK
365     case ENOLCK: return "no locks available";
366 #endif
367 #ifdef ENOLINK
368     case ENOLINK: return "link has be severed";
369 #endif
370 #ifdef ENOMEM
371     case ENOMEM: return "not enough memory";
372 #endif
373 #ifdef ENOMSG
374     case ENOMSG: return "no message of desired type";
375 #endif
376 #ifdef ENONET
377     case ENONET: return "machine is not on the network";
378 #endif
379 #ifdef ENOPKG
380     case ENOPKG: return "package not installed";
381 #endif
382 #ifdef ENOPROTOOPT
383     case ENOPROTOOPT: return "bad proocol option";
384 #endif
385 #ifdef ENOSPC
386     case ENOSPC: return "no space left on device";
387 #endif
388 #ifdef ENOSR
389     case ENOSR: return "out of stream resources";
390 #endif
391 #ifdef ENOSTR
392     case ENOSTR: return "not a stream device";
393 #endif
394 #ifdef ENOSYM
395     case ENOSYM: return "unresolved symbol name";
396 #endif
397 #ifdef ENOSYS
398     case ENOSYS: return "function not implemented";
399 #endif
400 #ifdef ENOTBLK
401     case ENOTBLK: return "block device required";
402 #endif
403 #ifdef ENOTCONN
404     case ENOTCONN: return "socket is not connected";
405 #endif
406 #ifdef ENOTDIR
407     case ENOTDIR: return "not a directory";
408 #endif
409 #ifdef ENOTEMPTY
410     case ENOTEMPTY: return "directory not empty";
411 #endif
412 #ifdef ENOTNAM
413     case ENOTNAM: return "not a name file";
414 #endif
415 #ifdef ENOTSOCK
416     case ENOTSOCK: return "socket operation on non-socket";
417 #endif
418 #ifdef ENOTTY
419     case ENOTTY: return "inappropriate device for ioctl";
420 #endif
421 #ifdef ENOTUNIQ
422     case ENOTUNIQ: return "name not unique on network";
423 #endif
424 #ifdef ENXIO
425     case ENXIO: return "no such device or address";
426 #endif
427 #ifdef EOPNOTSUPP
428     case EOPNOTSUPP: return "operation not supported on socket";
429 #endif
430 #ifdef EPERM
431     case EPERM: return "not owner";
432 #endif
433 #ifdef EPFNOSUPPORT
434     case EPFNOSUPPORT: return "protocol family not supported";
435 #endif
436 #ifdef EPIPE
437     case EPIPE: return "broken pipe";
438 #endif
439 #ifdef EPROCLIM
440     case EPROCLIM: return "too many processes";
441 #endif
442 #ifdef EPROCUNAVAIL
443     case EPROCUNAVAIL: return "bad procedure for program";
444 #endif
445 #ifdef EPROGMISMATCH
446     case EPROGMISMATCH: return "program version wrong";
447 #endif
448 #ifdef EPROGUNAVAIL
449     case EPROGUNAVAIL: return "RPC program not available";
450 #endif
451 #ifdef EPROTO
452     case EPROTO: return "protocol error";
453 #endif
454 #ifdef EPROTONOSUPPORT
455     case EPROTONOSUPPORT: return "protocol not suppored";
456 #endif
457 #ifdef EPROTOTYPE
458     case EPROTOTYPE: return "protocol wrong type for socket";
459 #endif
460 #ifdef ERANGE
461     case ERANGE: return "math result unrepresentable";
462 #endif
463 #if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
464     case EREFUSED: return "EREFUSED";
465 #endif
466 #ifdef EREMCHG
467     case EREMCHG: return "remote address changed";
468 #endif
469 #ifdef EREMDEV
470     case EREMDEV: return "remote device";
471 #endif
472 #ifdef EREMOTE
473     case EREMOTE: return "pathname hit remote file system";
474 #endif
475 #ifdef EREMOTEIO
476     case EREMOTEIO: return "remote i/o error";
477 #endif
478 #ifdef EREMOTERELEASE
479     case EREMOTERELEASE: return "EREMOTERELEASE";
480 #endif
481 #ifdef EROFS
482     case EROFS: return "read-only file system";
483 #endif
484 #ifdef ERPCMISMATCH
485     case ERPCMISMATCH: return "RPC version is wrong";
486 #endif
487 #ifdef ERREMOTE
488     case ERREMOTE: return "object is remote";
489 #endif
490 #ifdef ESHUTDOWN
491     case ESHUTDOWN: return "can't send afer socket shutdown";
492 #endif
493 #ifdef ESOCKTNOSUPPORT
494     case ESOCKTNOSUPPORT: return "socket type not supported";
495 #endif
496 #ifdef ESPIPE
497     case ESPIPE: return "invalid seek";
498 #endif
499 #ifdef ESRCH
500     case ESRCH: return "no such process";
501 #endif
502 #ifdef ESRMNT
503     case ESRMNT: return "srmount error";
504 #endif
505 #ifdef ESTALE
506     case ESTALE: return "stale remote file handle";
507 #endif
508 #ifdef ESUCCESS
509     case ESUCCESS: return "Error 0";
510 #endif
511 #ifdef ETIME
512     case ETIME: return "timer expired";
513 #endif
514 #ifdef ETIMEDOUT
515     case ETIMEDOUT: return "connection timed out";
516 #endif
517 #ifdef ETOOMANYREFS
518     case ETOOMANYREFS: return "too many references: can't splice";
519 #endif
520 #ifdef ETXTBSY
521     case ETXTBSY: return "text file or pseudo-device busy";
522 #endif
523 #ifdef EUCLEAN
524     case EUCLEAN: return "structure needs cleaning";
525 #endif
526 #ifdef EUNATCH
527     case EUNATCH: return "protocol driver not attached";
528 #endif
529 #ifdef EUSERS
530     case EUSERS: return "too many users";
531 #endif
532 #ifdef EVERSION
533     case EVERSION: return "version mismatch";
534 #endif
535 #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
536     case EWOULDBLOCK: return "operation would block";
537 #endif
538 #ifdef EXDEV
539     case EXDEV: return "cross-domain link";
540 #endif
541 #ifdef EXFULL
542     case EXFULL: return "message tables full";
543 #endif
544     }
545 #else /* NO_SYS_ERRLIST */
546   extern int sys_nerr;
547   extern char *sys_errlist[];
548
549   if ((errnum > 0) && (errnum <= sys_nerr))
550     return sys_errlist [errnum];
551 #endif /* NO_SYS_ERRLIST */
552
553   sprintf (msg, "unknown error (%d)", errnum);
554   return msg;
555 }
556
557 gchar*
558 g_strsignal (gint signum)
559 {
560   static char msg[64];
561
562 #ifdef HAVE_STRSIGNAL
563   extern char *strsignal (int sig);
564   return strsignal (signum);
565 #elif NO_SYS_SIGLIST
566   switch (signum)
567     {
568 #ifdef SIGHUP
569     case SIGHUP: return "Hangup";
570 #endif
571 #ifdef SIGINT
572     case SIGINT: return "Interrupt";
573 #endif
574 #ifdef SIGQUIT
575     case SIGQUIT: return "Quit";
576 #endif
577 #ifdef SIGILL
578     case SIGILL: return "Illegal instruction";
579 #endif
580 #ifdef SIGTRAP
581     case SIGTRAP: return "Trace/breakpoint trap";
582 #endif
583 #ifdef SIGABRT
584     case SIGABRT: return "IOT trap/Abort";
585 #endif
586 #ifdef SIGBUS
587     case SIGBUS: return "Bus error";
588 #endif
589 #ifdef SIGFPE
590     case SIGFPE: return "Floating point exception";
591 #endif
592 #ifdef SIGKILL
593     case SIGKILL: return "Killed";
594 #endif
595 #ifdef SIGUSR1
596     case SIGUSR1: return "User defined signal 1";
597 #endif
598 #ifdef SIGSEGV
599     case SIGSEGV: return "Segmentation fault";
600 #endif
601 #ifdef SIGUSR2
602     case SIGUSR2: return "User defined signal 2";
603 #endif
604 #ifdef SIGPIPE
605     case SIGPIPE: return "Broken pipe";
606 #endif
607 #ifdef SIGALRM
608     case SIGALRM: return "Alarm clock";
609 #endif
610 #ifdef SIGTERM
611     case SIGTERM: return "Terminated";
612 #endif
613 #ifdef SIGSTKFLT
614     case SIGSTKFLT: return "Stack fault";
615 #endif
616 #ifdef SIGCHLD
617     case SIGCHLD: return "Child exited";
618 #endif
619 #ifdef SIGCONT
620     case SIGCONT: return "Continued";
621 #endif
622 #ifdef SIGSTOP
623     case SIGSTOP: return "Stopped (signal)";
624 #endif
625 #ifdef SIGTSTP
626     case SIGTSTP: return "Stopped";
627 #endif
628 #ifdef SIGTTIN
629     case SIGTTIN: return "Stopped (tty input)";
630 #endif
631 #ifdef SIGTTOU
632     case SIGTTOU: return "Stopped (tty output)";
633 #endif
634 #ifdef SIGURG
635     case SIGURG: return "Urgent condition";
636 #endif
637 #ifdef SIGXCPU
638     case SIGXCPU: return "CPU time limit exceeded";
639 #endif
640 #ifdef SIGXFSZ
641     case SIGXFSZ: return "File size limit exceeded";
642 #endif
643 #ifdef SIGVTALRM
644     case SIGVTALRM: return "Virtual time alarm";
645 #endif
646 #ifdef SIGPROF
647     case SIGPROF: return "Profile signal";
648 #endif
649 #ifdef SIGWINCH
650     case SIGWINCH: return "Window size changed";
651 #endif
652 #ifdef SIGIO
653     case SIGIO: return "Possible I/O";
654 #endif
655 #ifdef SIGPWR
656     case SIGPWR: return "Power failure";
657 #endif
658 #ifdef SIGUNUSED
659     case SIGUNUSED: return "Unused signal";
660 #endif
661     }
662 #else /* NO_SYS_SIGLIST */
663   extern char *sys_siglist[];
664   return sys_siglist [signum];
665 #endif /* NO_SYS_SIGLIST */
666
667   sprintf (msg, "unknown signal (%d)", signum);
668   return msg;
669 }
670
671 gint
672 g_snprintf (gchar       *str,
673             gulong       n,
674             gchar const *fmt,
675             ...)
676 {
677 #ifdef HAVE_VSNPRINTF
678   va_list args;
679   gint retval;
680   
681   va_start (args, fmt);
682   retval = vsnprintf (str, n, fmt, args);
683   va_end (args);
684
685   return retval;
686
687 #else
688   gchar *printed;
689   va_list args, args2;
690
691   va_start (args, fmt);
692   va_start (args2, fmt);
693   
694   printed = g_vsprintf (fmt, &args, &args2);
695   strncpy (str, printed, n);
696   str[n-1] = '\0';
697   
698   va_end (args2);
699   va_end (args);
700
701   return strlen (str);
702
703 #endif
704 }
705
706 void
707 g_strdown (gchar  *string)
708 {
709   register gchar *s;
710
711   g_return_if_fail (string != NULL);
712
713   s = string;
714
715   while (*s)
716     {
717       *s = tolower (*s);
718       s++;
719     }
720 }
721
722 void
723 g_strup (gchar  *string)
724 {
725   register gchar *s;
726
727   g_return_if_fail (string != NULL);
728
729   s = string;
730
731   while (*s)
732     {
733       *s = toupper (*s);
734       s++;
735     }
736 }
737
738 void
739 g_strreverse (gchar       *string)
740 {
741   g_return_if_fail (string != NULL);
742
743   if (*string)
744     {
745       register gchar *h, *t;
746
747       h = string;
748       t = string + strlen (string) - 1;
749       
750       while (h < t)
751         {
752           register gchar c;
753           
754           c = *h;
755           *h = *t;
756           h++;
757           *t = c;
758           t--;
759         }
760     }
761 }
762
763 gint
764 g_strcasecmp (const gchar *s1,
765               const gchar *s2)
766 {
767 #ifdef HAVE_STRCASECMP
768   return strcasecmp (s1, s2);
769 #else
770   gint c1, c2;
771
772   while (*s1 && *s2)
773     {
774       /* According to A. Cox, some platforms have islower's that
775        * don't work right on non-uppercase
776        */
777       c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1;
778       c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2;
779       if (c1 != c2)
780         return (c1 - c2);
781       s1++; s2++;
782     }
783
784   return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
785 #endif
786 }
787
788 void
789 g_strdelimit (gchar       *string,
790               const gchar *delimiters,
791               gchar        new_delim)
792 {
793   register gchar *c;
794
795   g_return_if_fail (string != NULL);
796
797   if (!delimiters)
798     delimiters = G_STR_DELIMITERS;
799
800   for (c = string; *c; c++)
801     {
802       if (strchr (delimiters, *c))
803         *c = new_delim;
804     }
805 }
806
807 guint        
808 g_parse_debug_string  (const gchar *string, 
809                        GDebugKey   *keys, 
810                        guint        nkeys)
811 {
812   guint i;
813   guint result = 0;
814
815   g_return_val_if_fail (string != NULL, 0);
816
817   if (!g_strcasecmp (string, "all"))
818     {
819       for (i=0; i<nkeys; i++)
820         result |= keys[i].value;
821     }
822   else
823     {
824       gchar *str = g_strdup (string);
825       gchar *p = str;
826       gchar *q;
827       gboolean done = FALSE;
828
829       while (*p && !done)
830         {
831           q = strchr (p, ':');
832           if (!q)
833             {
834               q = p + strlen(p);
835               done = TRUE;
836             }
837
838           *q = 0;
839
840           for (i=0; i<nkeys; i++)
841             if (!g_strcasecmp(keys[i].key, p))
842               result |= keys[i].value;
843
844           p = q+1;
845         }
846       
847       g_free (str);
848     }
849
850   return result;
851 }
852
853 guint
854 g_direct_hash(gconstpointer v)
855 {
856   return GPOINTER_TO_UINT (v);
857 }
858
859 gint
860 g_direct_equal(gconstpointer v, gconstpointer v2)
861 {
862   return GPOINTER_TO_UINT (v) == GPOINTER_TO_UINT (v2);
863 }
864
865 gint
866 g_int_equal (gconstpointer v, gconstpointer v2)
867 {
868   return *((const gint*) v) == *((const gint*) v2);
869 }
870
871 guint
872 g_int_hash (gconstpointer v)
873 {
874   return *(const gint*) v;
875 }