source: trunk/third/glib2/glib/gstrfuncs.c @ 18159

Revision 18159, 58.3 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18158, which included commits to RCS files with non-trunk default branches.
Line 
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 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.
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 * Lesser General Public License for more details.
13 *
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.
18 */
19
20/*
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/.
25 */
26
27/*
28 * MT safe
29 */
30
31#include "config.h"
32
33#define _GNU_SOURCE             /* For stpcpy */
34
35#include <stdarg.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <locale.h>
40#include <errno.h>
41#include <ctype.h>              /* For tolower() */
42#if !defined (HAVE_STRSIGNAL) || !defined(NO_SYS_SIGLIST_DECL)
43#include <signal.h>
44#endif
45
46#include "glib.h"
47#include "gprintfint.h"
48
49#ifdef G_OS_WIN32
50#include <windows.h>
51#endif
52
53/* do not include <unistd.h> in this place since it
54 * inteferes with g_strsignal() on some OSes
55 */
56
57static const guint16 ascii_table_data[256] = {
58  0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
59  0x004, 0x104, 0x104, 0x004, 0x104, 0x104, 0x004, 0x004,
60  0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
61  0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
62  0x140, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
63  0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
64  0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459,
65  0x459, 0x459, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
66  0x0d0, 0x653, 0x653, 0x653, 0x653, 0x653, 0x653, 0x253,
67  0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
68  0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
69  0x253, 0x253, 0x253, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
70  0x0d0, 0x473, 0x473, 0x473, 0x473, 0x473, 0x473, 0x073,
71  0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
72  0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
73  0x073, 0x073, 0x073, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x004
74  /* the upper 128 are all zeroes */
75};
76
77#if defined(G_PLATFORM_WIN32) && defined(__GNUC__)
78__declspec(dllexport)
79#endif
80const guint16 * const g_ascii_table = ascii_table_data;
81
82gchar*
83g_strdup (const gchar *str)
84{
85  gchar *new_str;
86
87  if (str)
88    {
89      new_str = g_new (char, strlen (str) + 1);
90      strcpy (new_str, str);
91    }
92  else
93    new_str = NULL;
94
95  return new_str;
96}
97
98gpointer
99g_memdup (gconstpointer mem,
100          guint         byte_size)
101{
102  gpointer new_mem;
103
104  if (mem)
105    {
106      new_mem = g_malloc (byte_size);
107      memcpy (new_mem, mem, byte_size);
108    }
109  else
110    new_mem = NULL;
111
112  return new_mem;
113}
114
115gchar*
116g_strndup (const gchar *str,
117           gsize        n)   
118{
119  gchar *new_str;
120
121  if (str)
122    {
123      new_str = g_new (gchar, n + 1);
124      strncpy (new_str, str, n);
125      new_str[n] = '\0';
126    }
127  else
128    new_str = NULL;
129
130  return new_str;
131}
132
133gchar*
134g_strnfill (gsize length,     
135            gchar fill_char)
136{
137  gchar *str;
138
139  str = g_new (gchar, length + 1);
140  memset (str, (guchar)fill_char, length);
141  str[length] = '\0';
142
143  return str;
144}
145
146/**
147 * g_stpcpy:
148 * @dest: destination buffer.
149 * @src: source string.
150 *
151 * Copies a nul-terminated string into the dest buffer, include the
152 * trailing nul, and return a pointer to the trailing nul byte.
153 * This is useful for concatenating multiple strings together
154 * without having to repeatedly scan for the end.
155 *
156 * Return value: a pointer to trailing nul byte.
157 **/
158gchar *
159g_stpcpy (gchar       *dest,
160          const gchar *src)
161{
162#ifdef HAVE_STPCPY
163  g_return_val_if_fail (dest != NULL, NULL);
164  g_return_val_if_fail (src != NULL, NULL);
165  return stpcpy (dest, src);
166#else
167  register gchar *d = dest;
168  register const gchar *s = src;
169
170  g_return_val_if_fail (dest != NULL, NULL);
171  g_return_val_if_fail (src != NULL, NULL);
172  do
173    *d++ = *s;
174  while (*s++ != '\0');
175
176  return d - 1;
177#endif
178}
179
180gchar*
181g_strdup_vprintf (const gchar *format,
182                  va_list      args1)
183{
184  gchar *buffer;
185#ifdef HAVE_VASPRINTF
186  if (_g_vasprintf (&buffer, format, args1) < 0)
187    buffer = NULL;
188  else if (!g_mem_is_system_malloc ())
189    {
190      gchar *buffer1 = g_strdup (buffer);
191      free (buffer);
192      buffer = buffer1;
193    }
194#else
195  va_list args2;
196
197  G_VA_COPY (args2, args1);
198
199  buffer = g_new (gchar, g_printf_string_upper_bound (format, args1));
200
201  _g_vsprintf (buffer, format, args2);
202  va_end (args2);
203#endif
204  return buffer;
205}
206
207gchar*
208g_strdup_printf (const gchar *format,
209                 ...)
210{
211  gchar *buffer;
212  va_list args;
213
214  va_start (args, format);
215  buffer = g_strdup_vprintf (format, args);
216  va_end (args);
217
218  return buffer;
219}
220
221gchar*
222g_strconcat (const gchar *string1, ...)
223{
224  gsize   l;     
225  va_list args;
226  gchar   *s;
227  gchar   *concat;
228  gchar   *ptr;
229
230  g_return_val_if_fail (string1 != NULL, NULL);
231
232  l = 1 + strlen (string1);
233  va_start (args, string1);
234  s = va_arg (args, gchar*);
235  while (s)
236    {
237      l += strlen (s);
238      s = va_arg (args, gchar*);
239    }
240  va_end (args);
241
242  concat = g_new (gchar, l);
243  ptr = concat;
244
245  ptr = g_stpcpy (ptr, string1);
246  va_start (args, string1);
247  s = va_arg (args, gchar*);
248  while (s)
249    {
250      ptr = g_stpcpy (ptr, s);
251      s = va_arg (args, gchar*);
252    }
253  va_end (args);
254
255  return concat;
256}
257
258/**
259 * g_strtod:
260 * @nptr:    the string to convert to a numeric value.
261 * @endptr:  if non-%NULL, it returns the character after
262 *           the last character used in the conversion.
263 *
264 * Converts a string to a #gdouble value.
265 * It calls the standard strtod() function to handle the conversion, but
266 * if the string is not completely converted it attempts the conversion
267 * again with g_ascii_strtod(), and returns the best match.
268 *
269 * This function should seldomly be used. The normal situation when reading
270 * numbers not for human consumption is to use g_ascii_strtod(). Only when
271 * you know that you must expect both locale formatted and C formatted numbers
272 * should you use this. Make sure that you don't pass strings such as comma
273 * separated lists of values, since the commas may be interpreted as a decimal
274 * point in some locales, causing unexpected results.
275 *
276 * Return value: the #gdouble value.
277 **/
278gdouble
279g_strtod (const gchar *nptr,
280          gchar      **endptr)
281{
282  gchar *fail_pos_1;
283  gchar *fail_pos_2;
284  gdouble val_1;
285  gdouble val_2 = 0;
286
287  g_return_val_if_fail (nptr != NULL, 0);
288
289  fail_pos_1 = NULL;
290  fail_pos_2 = NULL;
291
292  val_1 = strtod (nptr, &fail_pos_1);
293
294  if (fail_pos_1 && fail_pos_1[0] != 0)
295    val_2 = g_ascii_strtod (nptr, &fail_pos_2);
296
297  if (!fail_pos_1 || fail_pos_1[0] == 0 || fail_pos_1 >= fail_pos_2)
298    {
299      if (endptr)
300        *endptr = fail_pos_1;
301      return val_1;
302    }
303  else
304    {
305      if (endptr)
306        *endptr = fail_pos_2;
307      return val_2;
308    }
309}
310
311/**
312 * g_ascii_strtod:
313 * @nptr:    the string to convert to a numeric value.
314 * @endptr:  if non-%NULL, it returns the character after
315 *           the last character used in the conversion.
316 *
317 * Converts a string to a #gdouble value.
318 * This function behaves like the standard strtod() function
319 * does in the C locale. It does this without actually
320 * changing the current locale, since that would not be
321 * thread-safe.
322 *
323 * This function is typically used when reading configuration
324 * files or other non-user input that should be locale independent.
325 * To handle input from the user you should normally use the
326 * locale-sensitive system strtod() function.
327 *
328 * To convert from a string to #gdouble in a locale-insensitive
329 * way, use g_ascii_dtostr().
330 *
331 * If the correct value would cause overflow, plus or minus %HUGE_VAL
332 * is returned (according to the sign of the value), and %ERANGE is
333 * stored in %errno. If the correct value would cause underflow,
334 * zero is returned and %ERANGE is stored in %errno.
335 *
336 * This function resets %errno before calling strtod() so that
337 * you can reliably detect overflow and underflow.
338 *
339 * Return value: the #gdouble value.
340 **/
341gdouble
342g_ascii_strtod (const gchar *nptr,
343                gchar      **endptr)
344{
345  gchar *fail_pos;
346  gdouble val;
347  struct lconv *locale_data;
348  const char *decimal_point;
349  int decimal_point_len;
350  const char *p, *decimal_point_pos;
351  const char *end = NULL; /* Silence gcc */
352
353  g_return_val_if_fail (nptr != NULL, 0);
354
355  fail_pos = NULL;
356
357  locale_data = localeconv ();
358  decimal_point = locale_data->decimal_point;
359  decimal_point_len = strlen (decimal_point);
360
361  g_assert (decimal_point_len != 0);
362 
363  decimal_point_pos = NULL;
364  if (decimal_point[0] != '.' ||
365      decimal_point[1] != 0)
366    {
367      p = nptr;
368      /* Skip leading space */
369      while (g_ascii_isspace (*p))
370        p++;
371     
372      /* Skip leading optional sign */
373      if (*p == '+' || *p == '-')
374        p++;
375     
376      if (p[0] == '0' &&
377          (p[1] == 'x' || p[1] == 'X'))
378        {
379          p += 2;
380          /* HEX - find the (optional) decimal point */
381         
382          while (g_ascii_isxdigit (*p))
383            p++;
384         
385          if (*p == '.')
386            {
387              decimal_point_pos = p++;
388             
389              while (g_ascii_isxdigit (*p))
390                p++;
391             
392              if (*p == 'p' || *p == 'P')
393                p++;
394              if (*p == '+' || *p == '-')
395                p++;
396              while (g_ascii_isdigit (*p))
397                p++;
398              end = p;
399            }
400        }
401      else
402        {
403          while (g_ascii_isdigit (*p))
404            p++;
405         
406          if (*p == '.')
407            {
408              decimal_point_pos = p++;
409             
410              while (g_ascii_isdigit (*p))
411                p++;
412             
413              if (*p == 'e' || *p == 'E')
414                p++;
415              if (*p == '+' || *p == '-')
416                p++;
417              while (g_ascii_isdigit (*p))
418                p++;
419              end = p;
420            }
421        }
422      /* For the other cases, we need not convert the decimal point */
423    }
424
425  /* Set errno to zero, so that we can distinguish zero results
426     and underflows */
427  errno = 0;
428 
429  if (decimal_point_pos)
430    {
431      char *copy, *c;
432
433      /* We need to convert the '.' to the locale specific decimal point */
434      copy = g_malloc (end - nptr + 1 + decimal_point_len);
435     
436      c = copy;
437      memcpy (c, nptr, decimal_point_pos - nptr);
438      c += decimal_point_pos - nptr;
439      memcpy (c, decimal_point, decimal_point_len);
440      c += decimal_point_len;
441      memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
442      c += end - (decimal_point_pos + 1);
443      *c = 0;
444
445      val = strtod (copy, &fail_pos);
446
447      if (fail_pos)
448        {
449          if (fail_pos > decimal_point_pos)
450            fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
451          else
452            fail_pos = (char *)nptr + (fail_pos - copy);
453        }
454     
455      g_free (copy);
456         
457    }
458  else
459    val = strtod (nptr, &fail_pos);
460
461  if (endptr)
462    *endptr = fail_pos;
463 
464  return val;
465}
466
467
468/**
469 * g_ascii_dtostr:
470 * @buffer: A buffer to place the resulting string in
471 * @buf_len: The length of the buffer.
472 * @d: The #gdouble to convert
473 *
474 * Converts a #gdouble to a string, using the '.' as
475 * decimal point.
476 *
477 * This functions generates enough precision that converting
478 * the string back using g_strtod() gives the same machine-number
479 * (on machines with IEEE compatible 64bit doubles). It is
480 * guaranteed that the size of the resulting string will never
481 * be larger than @G_ASCII_DTOSTR_BUF_SIZE bytes.
482 *
483 * Return value: The pointer to the buffer with the converted string.
484 **/
485gchar *
486g_ascii_dtostr (gchar       *buffer,
487                gint         buf_len,
488                gdouble      d)
489{
490  return g_ascii_formatd (buffer, buf_len, "%.17g", d);
491}
492
493/**
494 * g_ascii_formatd:
495 * @buffer: A buffer to place the resulting string in
496 * @buf_len: The length of the buffer.
497 * @format: The printf-style format to use for the
498 *          code to use for converting.
499 * @d: The #gdouble to convert
500 *
501 * Converts a #gdouble to a string, using the '.' as
502 * decimal point. To format the number you pass in
503 * a printf-style formating string. Allowed conversion
504 * specifiers are 'e', 'E', 'f', 'F', 'g' and 'G'.
505 *
506 * If you just want to want to serialize the value into a
507 * string, use g_ascii_dtostr().
508 *
509 * Return value: The pointer to the buffer with the converted string.
510 **/
511gchar *
512g_ascii_formatd (gchar       *buffer,
513                 gint         buf_len,
514                 const gchar *format,
515                 gdouble      d)
516{
517  struct lconv *locale_data;
518  const char *decimal_point;
519  int decimal_point_len;
520  gchar *p;
521  int rest_len;
522  gchar format_char;
523
524  g_return_val_if_fail (buffer != NULL, NULL);
525  g_return_val_if_fail (format[0] == '%', NULL);
526  g_return_val_if_fail (strpbrk (format + 1, "'l%") == NULL, NULL);
527 
528  format_char = format[strlen (format) - 1];
529 
530  g_return_val_if_fail (format_char == 'e' || format_char == 'E' ||
531                        format_char == 'f' || format_char == 'F' ||
532                        format_char == 'g' || format_char == 'G',
533                        NULL);
534
535  if (format[0] != '%')
536    return NULL;
537
538  if (strpbrk (format + 1, "'l%"))
539    return NULL;
540
541  if (!(format_char == 'e' || format_char == 'E' ||
542        format_char == 'f' || format_char == 'F' ||
543        format_char == 'g' || format_char == 'G'))
544    return NULL;
545
546     
547  _g_snprintf (buffer, buf_len, format, d);
548
549  locale_data = localeconv ();
550  decimal_point = locale_data->decimal_point;
551  decimal_point_len = strlen (decimal_point);
552
553  g_assert (decimal_point_len != 0);
554
555  if (decimal_point[0] != '.' ||
556      decimal_point[1] != 0)
557    {
558      p = buffer;
559
560      if (*p == '+' || *p == '-')
561        p++;
562
563      while (isdigit ((guchar)*p))
564        p++;
565
566      if (strncmp (p, decimal_point, decimal_point_len) == 0)
567        {
568          *p = '.';
569          p++;
570          if (decimal_point_len > 1) {
571            rest_len = strlen (p + (decimal_point_len-1));
572            memmove (p, p + (decimal_point_len-1),
573                     rest_len);
574            p[rest_len] = 0;
575           
576          }
577        }
578    }
579 
580  return buffer;
581}
582
583/**
584 * g_ascii_strtoull:
585 * @nptr:    the string to convert to a numeric value.
586 * @endptr:  if non-%NULL, it returns the character after
587 *           the last character used in the conversion.
588 * @base:    to be used for the conversion, 2..36 or 0
589 *
590 * Converts a string to a #guint64 value.
591 * This function behaves like the standard strtoull() function
592 * does in the C locale. It does this without actually
593 * changing the current locale, since that would not be
594 * thread-safe.
595 *
596 * This function is typically used when reading configuration
597 * files or other non-user input that should be locale independent.
598 * To handle input from the user you should normally use the
599 * locale-sensitive system strtoull() function.
600 *
601 * If the correct value would cause overflow, %G_MAXUINT64
602 * is returned, and %ERANGE is stored in %errno.
603 *
604 * Return value: the #guint64 value.
605 *
606 * Since: 2.2
607 **/
608guint64
609g_ascii_strtoull (const gchar *nptr,
610                  gchar      **endptr,
611                  guint        base)
612{
613  /* this code is based on on the strtol(3) code from GNU libc released under
614   * the GNU Lesser General Public License.
615   *
616   * Copyright (C) 1991,92,94,95,96,97,98,99,2000,01,02
617   *        Free Software Foundation, Inc.
618   */
619#define ISSPACE(c)              ((c) == ' ' || (c) == '\f' || (c) == '\n' || \
620                                 (c) == '\r' || (c) == '\t' || (c) == '\v')
621#define ISUPPER(c)              ((c) >= 'A' && (c) <= 'Z')
622#define ISLOWER(c)              ((c) >= 'a' && (c) <= 'z')
623#define ISALPHA(c)              (ISUPPER (c) || ISLOWER (c))
624#define TOUPPER(c)              (ISLOWER (c) ? (c) - 'a' + 'A' : (c))
625#define TOLOWER(c)              (ISUPPER (c) ? (c) - 'A' + 'a' : (c))
626  gboolean negative, overflow;
627  guint64 cutoff;
628  guint64 cutlim;
629  guint64 ui64;
630  const gchar *s, *save;
631  guchar c;
632 
633  g_return_val_if_fail (nptr != NULL, 0);
634 
635  if (base == 1 || base > 36)
636    {
637      errno = EINVAL;
638      return 0;
639    }
640 
641  save = s = nptr;
642 
643  /* Skip white space.  */
644  while (ISSPACE (*s))
645    ++s;
646  if (!*s)
647    goto noconv;
648 
649  /* Check for a sign.  */
650  negative = FALSE;
651  if (*s == '-')
652    {
653      negative = TRUE;
654      ++s;
655    }
656  else if (*s == '+')
657    ++s;
658 
659  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
660  if (*s == '0')
661    {
662      if ((base == 0 || base == 16) && TOUPPER (s[1]) == 'X')
663        {
664          s += 2;
665          base = 16;
666        }
667      else if (base == 0)
668        base = 8;
669    }
670  else if (base == 0)
671    base = 10;
672 
673  /* Save the pointer so we can check later if anything happened.  */
674  save = s;
675  cutoff = G_MAXUINT64 / base;
676  cutlim = G_MAXUINT64 % base;
677 
678  overflow = FALSE;
679  ui64 = 0;
680  c = *s;
681  for (; c; c = *++s)
682    {
683      if (c >= '0' && c <= '9')
684        c -= '0';
685      else if (ISALPHA (c))
686        c = TOUPPER (c) - 'A' + 10;
687      else
688        break;
689      if (c >= base)
690        break;
691      /* Check for overflow.  */
692      if (ui64 > cutoff || (ui64 == cutoff && c > cutlim))
693        overflow = TRUE;
694      else
695        {
696          ui64 *= base;
697          ui64 += c;
698        }
699    }
700 
701  /* Check if anything actually happened.  */
702  if (s == save)
703    goto noconv;
704 
705  /* Store in ENDPTR the address of one character
706     past the last character we converted.  */
707  if (endptr)
708    *endptr = (gchar*) s;
709 
710  if (overflow)
711    {
712      errno = ERANGE;
713      return G_MAXUINT64;
714    }
715 
716  /* Return the result of the appropriate sign.  */
717  return negative ? -ui64 : ui64;
718 
719 noconv:
720  /* We must handle a special case here: the base is 0 or 16 and the
721     first two characters are '0' and 'x', but the rest are no
722     hexadecimal digits.  This is no error case.  We return 0 and
723     ENDPTR points to the `x`.  */
724  if (endptr)
725    {
726      if (save - nptr >= 2 && TOUPPER (save[-1]) == 'X'
727          && save[-2] == '0')
728        *endptr = (gchar*) &save[-1];
729      else
730        /*  There was no number to convert.  */
731        *endptr = (gchar*) nptr;
732    }
733  return 0;
734}
735
736
737G_CONST_RETURN gchar*
738g_strerror (gint errnum)
739{
740  static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
741  char *msg;
742
743#ifdef HAVE_STRERROR
744  const char *msg_locale;
745
746  msg_locale = strerror (errnum);
747  if (g_get_charset (NULL))
748    return msg_locale;
749  else
750    {
751      gchar *msg_utf8 = g_locale_to_utf8 (msg_locale, -1, NULL, NULL, NULL);
752      if (msg_utf8)
753        {
754          /* Stick in the quark table so that we can return a static result
755           */
756          GQuark msg_quark = g_quark_from_string (msg_utf8);
757          g_free (msg_utf8);
758         
759          return g_quark_to_string (msg_quark);
760        }
761    }
762#elif NO_SYS_ERRLIST
763  switch (errnum)
764    {
765#ifdef E2BIG
766    case E2BIG: return "argument list too long";
767#endif
768#ifdef EACCES
769    case EACCES: return "permission denied";
770#endif
771#ifdef EADDRINUSE
772    case EADDRINUSE: return "address already in use";
773#endif
774#ifdef EADDRNOTAVAIL
775    case EADDRNOTAVAIL: return "can't assign requested address";
776#endif
777#ifdef EADV
778    case EADV: return "advertise error";
779#endif
780#ifdef EAFNOSUPPORT
781    case EAFNOSUPPORT: return "address family not supported by protocol family";
782#endif
783#ifdef EAGAIN
784    case EAGAIN: return "try again";
785#endif
786#ifdef EALIGN
787    case EALIGN: return "EALIGN";
788#endif
789#ifdef EALREADY
790    case EALREADY: return "operation already in progress";
791#endif
792#ifdef EBADE
793    case EBADE: return "bad exchange descriptor";
794#endif
795#ifdef EBADF
796    case EBADF: return "bad file number";
797#endif
798#ifdef EBADFD
799    case EBADFD: return "file descriptor in bad state";
800#endif
801#ifdef EBADMSG
802    case EBADMSG: return "not a data message";
803#endif
804#ifdef EBADR
805    case EBADR: return "bad request descriptor";
806#endif
807#ifdef EBADRPC
808    case EBADRPC: return "RPC structure is bad";
809#endif
810#ifdef EBADRQC
811    case EBADRQC: return "bad request code";
812#endif
813#ifdef EBADSLT
814    case EBADSLT: return "invalid slot";
815#endif
816#ifdef EBFONT
817    case EBFONT: return "bad font file format";
818#endif
819#ifdef EBUSY
820    case EBUSY: return "mount device busy";
821#endif
822#ifdef ECHILD
823    case ECHILD: return "no children";
824#endif
825#ifdef ECHRNG
826    case ECHRNG: return "channel number out of range";
827#endif
828#ifdef ECOMM
829    case ECOMM: return "communication error on send";
830#endif
831#ifdef ECONNABORTED
832    case ECONNABORTED: return "software caused connection abort";
833#endif
834#ifdef ECONNREFUSED
835    case ECONNREFUSED: return "connection refused";
836#endif
837#ifdef ECONNRESET
838    case ECONNRESET: return "connection reset by peer";
839#endif
840#if defined(EDEADLK) && (!defined(EWOULDBLOCK) || (EDEADLK != EWOULDBLOCK))
841    case EDEADLK: return "resource deadlock avoided";
842#endif
843#ifdef EDEADLOCK
844    case EDEADLOCK: return "resource deadlock avoided";
845#endif
846#ifdef EDESTADDRREQ
847    case EDESTADDRREQ: return "destination address required";
848#endif
849#ifdef EDIRTY
850    case EDIRTY: return "mounting a dirty fs w/o force";
851#endif
852#ifdef EDOM
853    case EDOM: return "math argument out of range";
854#endif
855#ifdef EDOTDOT
856    case EDOTDOT: return "cross mount point";
857#endif
858#ifdef EDQUOT
859    case EDQUOT: return "disk quota exceeded";
860#endif
861#ifdef EDUPPKG
862    case EDUPPKG: return "duplicate package name";
863#endif
864#ifdef EEXIST
865    case EEXIST: return "file already exists";
866#endif
867#ifdef EFAULT
868    case EFAULT: return "bad address in system call argument";
869#endif
870#ifdef EFBIG
871    case EFBIG: return "file too large";
872#endif
873#ifdef EHOSTDOWN
874    case EHOSTDOWN: return "host is down";
875#endif
876#ifdef EHOSTUNREACH
877    case EHOSTUNREACH: return "host is unreachable";
878#endif
879#ifdef EIDRM
880    case EIDRM: return "identifier removed";
881#endif
882#ifdef EINIT
883    case EINIT: return "initialization error";
884#endif
885#ifdef EINPROGRESS
886    case EINPROGRESS: return "operation now in progress";
887#endif
888#ifdef EINTR
889    case EINTR: return "interrupted system call";
890#endif
891#ifdef EINVAL
892    case EINVAL: return "invalid argument";
893#endif
894#ifdef EIO
895    case EIO: return "I/O error";
896#endif
897#ifdef EISCONN
898    case EISCONN: return "socket is already connected";
899#endif
900#ifdef EISDIR
901    case EISDIR: return "is a directory";
902#endif
903#ifdef EISNAME
904    case EISNAM: return "is a name file";
905#endif
906#ifdef ELBIN
907    case ELBIN: return "ELBIN";
908#endif
909#ifdef EL2HLT
910    case EL2HLT: return "level 2 halted";
911#endif
912#ifdef EL2NSYNC
913    case EL2NSYNC: return "level 2 not synchronized";
914#endif
915#ifdef EL3HLT
916    case EL3HLT: return "level 3 halted";
917#endif
918#ifdef EL3RST
919    case EL3RST: return "level 3 reset";
920#endif
921#ifdef ELIBACC
922    case ELIBACC: return "can not access a needed shared library";
923#endif
924#ifdef ELIBBAD
925    case ELIBBAD: return "accessing a corrupted shared library";
926#endif
927#ifdef ELIBEXEC
928    case ELIBEXEC: return "can not exec a shared library directly";
929#endif
930#ifdef ELIBMAX
931    case ELIBMAX: return "attempting to link in more shared libraries than system limit";
932#endif
933#ifdef ELIBSCN
934    case ELIBSCN: return ".lib section in a.out corrupted";
935#endif
936#ifdef ELNRNG
937    case ELNRNG: return "link number out of range";
938#endif
939#ifdef ELOOP
940    case ELOOP: return "too many levels of symbolic links";
941#endif
942#ifdef EMFILE
943    case EMFILE: return "too many open files";
944#endif
945#ifdef EMLINK
946    case EMLINK: return "too many links";
947#endif
948#ifdef EMSGSIZE
949    case EMSGSIZE: return "message too long";
950#endif
951#ifdef EMULTIHOP
952    case EMULTIHOP: return "multihop attempted";
953#endif
954#ifdef ENAMETOOLONG
955    case ENAMETOOLONG: return "file name too long";
956#endif
957#ifdef ENAVAIL
958    case ENAVAIL: return "not available";
959#endif
960#ifdef ENET
961    case ENET: return "ENET";
962#endif
963#ifdef ENETDOWN
964    case ENETDOWN: return "network is down";
965#endif
966#ifdef ENETRESET
967    case ENETRESET: return "network dropped connection on reset";
968#endif
969#ifdef ENETUNREACH
970    case ENETUNREACH: return "network is unreachable";
971#endif
972#ifdef ENFILE
973    case ENFILE: return "file table overflow";
974#endif
975#ifdef ENOANO
976    case ENOANO: return "anode table overflow";
977#endif
978#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
979    case ENOBUFS: return "no buffer space available";
980#endif
981#ifdef ENOCSI
982    case ENOCSI: return "no CSI structure available";
983#endif
984#ifdef ENODATA
985    case ENODATA: return "no data available";
986#endif
987#ifdef ENODEV
988    case ENODEV: return "no such device";
989#endif
990#ifdef ENOENT
991    case ENOENT: return "no such file or directory";
992#endif
993#ifdef ENOEXEC
994    case ENOEXEC: return "exec format error";
995#endif
996#ifdef ENOLCK
997    case ENOLCK: return "no locks available";
998#endif
999#ifdef ENOLINK
1000    case ENOLINK: return "link has be severed";
1001#endif
1002#ifdef ENOMEM
1003    case ENOMEM: return "not enough memory";
1004#endif
1005#ifdef ENOMSG
1006    case ENOMSG: return "no message of desired type";
1007#endif
1008#ifdef ENONET
1009    case ENONET: return "machine is not on the network";
1010#endif
1011#ifdef ENOPKG
1012    case ENOPKG: return "package not installed";
1013#endif
1014#ifdef ENOPROTOOPT
1015    case ENOPROTOOPT: return "bad proocol option";
1016#endif
1017#ifdef ENOSPC
1018    case ENOSPC: return "no space left on device";
1019#endif
1020#ifdef ENOSR
1021    case ENOSR: return "out of stream resources";
1022#endif
1023#ifdef ENOSTR
1024    case ENOSTR: return "not a stream device";
1025#endif
1026#ifdef ENOSYM
1027    case ENOSYM: return "unresolved symbol name";
1028#endif
1029#ifdef ENOSYS
1030    case ENOSYS: return "function not implemented";
1031#endif
1032#ifdef ENOTBLK
1033    case ENOTBLK: return "block device required";
1034#endif
1035#ifdef ENOTCONN
1036    case ENOTCONN: return "socket is not connected";
1037#endif
1038#ifdef ENOTDIR
1039    case ENOTDIR: return "not a directory";
1040#endif
1041#ifdef ENOTEMPTY
1042    case ENOTEMPTY: return "directory not empty";
1043#endif
1044#ifdef ENOTNAM
1045    case ENOTNAM: return "not a name file";
1046#endif
1047#ifdef ENOTSOCK
1048    case ENOTSOCK: return "socket operation on non-socket";
1049#endif
1050#ifdef ENOTTY
1051    case ENOTTY: return "inappropriate device for ioctl";
1052#endif
1053#ifdef ENOTUNIQ
1054    case ENOTUNIQ: return "name not unique on network";
1055#endif
1056#ifdef ENXIO
1057    case ENXIO: return "no such device or address";
1058#endif
1059#ifdef EOPNOTSUPP
1060    case EOPNOTSUPP: return "operation not supported on socket";
1061#endif
1062#ifdef EPERM
1063    case EPERM: return "not owner";
1064#endif
1065#ifdef EPFNOSUPPORT
1066    case EPFNOSUPPORT: return "protocol family not supported";
1067#endif
1068#ifdef EPIPE
1069    case EPIPE: return "broken pipe";
1070#endif
1071#ifdef EPROCLIM
1072    case EPROCLIM: return "too many processes";
1073#endif
1074#ifdef EPROCUNAVAIL
1075    case EPROCUNAVAIL: return "bad procedure for program";
1076#endif
1077#ifdef EPROGMISMATCH
1078    case EPROGMISMATCH: return "program version wrong";
1079#endif
1080#ifdef EPROGUNAVAIL
1081    case EPROGUNAVAIL: return "RPC program not available";
1082#endif
1083#ifdef EPROTO
1084    case EPROTO: return "protocol error";
1085#endif
1086#ifdef EPROTONOSUPPORT
1087    case EPROTONOSUPPORT: return "protocol not suppored";
1088#endif
1089#ifdef EPROTOTYPE
1090    case EPROTOTYPE: return "protocol wrong type for socket";
1091#endif
1092#ifdef ERANGE
1093    case ERANGE: return "math result unrepresentable";
1094#endif
1095#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
1096    case EREFUSED: return "EREFUSED";
1097#endif
1098#ifdef EREMCHG
1099    case EREMCHG: return "remote address changed";
1100#endif
1101#ifdef EREMDEV
1102    case EREMDEV: return "remote device";
1103#endif
1104#ifdef EREMOTE
1105    case EREMOTE: return "pathname hit remote file system";
1106#endif
1107#ifdef EREMOTEIO
1108    case EREMOTEIO: return "remote i/o error";
1109#endif
1110#ifdef EREMOTERELEASE
1111    case EREMOTERELEASE: return "EREMOTERELEASE";
1112#endif
1113#ifdef EROFS
1114    case EROFS: return "read-only file system";
1115#endif
1116#ifdef ERPCMISMATCH
1117    case ERPCMISMATCH: return "RPC version is wrong";
1118#endif
1119#ifdef ERREMOTE
1120    case ERREMOTE: return "object is remote";
1121#endif
1122#ifdef ESHUTDOWN
1123    case ESHUTDOWN: return "can't send afer socket shutdown";
1124#endif
1125#ifdef ESOCKTNOSUPPORT
1126    case ESOCKTNOSUPPORT: return "socket type not supported";
1127#endif
1128#ifdef ESPIPE
1129    case ESPIPE: return "invalid seek";
1130#endif
1131#ifdef ESRCH
1132    case ESRCH: return "no such process";
1133#endif
1134#ifdef ESRMNT
1135    case ESRMNT: return "srmount error";
1136#endif
1137#ifdef ESTALE
1138    case ESTALE: return "stale remote file handle";
1139#endif
1140#ifdef ESUCCESS
1141    case ESUCCESS: return "Error 0";
1142#endif
1143#ifdef ETIME
1144    case ETIME: return "timer expired";
1145#endif
1146#ifdef ETIMEDOUT
1147    case ETIMEDOUT: return "connection timed out";
1148#endif
1149#ifdef ETOOMANYREFS
1150    case ETOOMANYREFS: return "too many references: can't splice";
1151#endif
1152#ifdef ETXTBSY
1153    case ETXTBSY: return "text file or pseudo-device busy";
1154#endif
1155#ifdef EUCLEAN
1156    case EUCLEAN: return "structure needs cleaning";
1157#endif
1158#ifdef EUNATCH
1159    case EUNATCH: return "protocol driver not attached";
1160#endif
1161#ifdef EUSERS
1162    case EUSERS: return "too many users";
1163#endif
1164#ifdef EVERSION
1165    case EVERSION: return "version mismatch";
1166#endif
1167#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
1168    case EWOULDBLOCK: return "operation would block";
1169#endif
1170#ifdef EXDEV
1171    case EXDEV: return "cross-domain link";
1172#endif
1173#ifdef EXFULL
1174    case EXFULL: return "message tables full";
1175#endif
1176    }
1177#else /* NO_SYS_ERRLIST */
1178  extern int sys_nerr;
1179  extern char *sys_errlist[];
1180
1181  if ((errnum > 0) && (errnum <= sys_nerr))
1182    return sys_errlist [errnum];
1183#endif /* NO_SYS_ERRLIST */
1184
1185  msg = g_static_private_get (&msg_private);
1186  if (!msg)
1187    {
1188      msg = g_new (gchar, 64);
1189      g_static_private_set (&msg_private, msg, g_free);
1190    }
1191
1192  _g_sprintf (msg, "unknown error (%d)", errnum);
1193
1194  return msg;
1195}
1196
1197G_CONST_RETURN gchar*
1198g_strsignal (gint signum)
1199{
1200  static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
1201  char *msg;
1202
1203#ifdef HAVE_STRSIGNAL
1204  const char *msg_locale;
1205 
1206#if defined(G_OS_BEOS) || defined(G_WITH_CYGWIN)
1207extern const char *strsignal(int);
1208#else
1209  /* this is declared differently (const) in string.h on BeOS */
1210  extern char *strsignal (int sig);
1211#endif /* !G_OS_BEOS && !G_WITH_CYGWIN */
1212  msg_locale = strsignal (signum);
1213  if (g_get_charset (NULL))
1214    return msg_locale;
1215  else
1216    {
1217      gchar *msg_utf8 = g_locale_to_utf8 (msg_locale, -1, NULL, NULL, NULL);
1218      if (msg_utf8)
1219        {
1220          /* Stick in the quark table so that we can return a static result
1221           */
1222          GQuark msg_quark = g_quark_from_string (msg_utf8);
1223          g_free (msg_utf8);
1224         
1225          return g_quark_to_string (msg_quark);
1226        }
1227    }
1228#elif NO_SYS_SIGLIST
1229  switch (signum)
1230    {
1231#ifdef SIGHUP
1232    case SIGHUP: return "Hangup";
1233#endif
1234#ifdef SIGINT
1235    case SIGINT: return "Interrupt";
1236#endif
1237#ifdef SIGQUIT
1238    case SIGQUIT: return "Quit";
1239#endif
1240#ifdef SIGILL
1241    case SIGILL: return "Illegal instruction";
1242#endif
1243#ifdef SIGTRAP
1244    case SIGTRAP: return "Trace/breakpoint trap";
1245#endif
1246#ifdef SIGABRT
1247    case SIGABRT: return "IOT trap/Abort";
1248#endif
1249#ifdef SIGBUS
1250    case SIGBUS: return "Bus error";
1251#endif
1252#ifdef SIGFPE
1253    case SIGFPE: return "Floating point exception";
1254#endif
1255#ifdef SIGKILL
1256    case SIGKILL: return "Killed";
1257#endif
1258#ifdef SIGUSR1
1259    case SIGUSR1: return "User defined signal 1";
1260#endif
1261#ifdef SIGSEGV
1262    case SIGSEGV: return "Segmentation fault";
1263#endif
1264#ifdef SIGUSR2
1265    case SIGUSR2: return "User defined signal 2";
1266#endif
1267#ifdef SIGPIPE
1268    case SIGPIPE: return "Broken pipe";
1269#endif
1270#ifdef SIGALRM
1271    case SIGALRM: return "Alarm clock";
1272#endif
1273#ifdef SIGTERM
1274    case SIGTERM: return "Terminated";
1275#endif
1276#ifdef SIGSTKFLT
1277    case SIGSTKFLT: return "Stack fault";
1278#endif
1279#ifdef SIGCHLD
1280    case SIGCHLD: return "Child exited";
1281#endif
1282#ifdef SIGCONT
1283    case SIGCONT: return "Continued";
1284#endif
1285#ifdef SIGSTOP
1286    case SIGSTOP: return "Stopped (signal)";
1287#endif
1288#ifdef SIGTSTP
1289    case SIGTSTP: return "Stopped";
1290#endif
1291#ifdef SIGTTIN
1292    case SIGTTIN: return "Stopped (tty input)";
1293#endif
1294#ifdef SIGTTOU
1295    case SIGTTOU: return "Stopped (tty output)";
1296#endif
1297#ifdef SIGURG
1298    case SIGURG: return "Urgent condition";
1299#endif
1300#ifdef SIGXCPU
1301    case SIGXCPU: return "CPU time limit exceeded";
1302#endif
1303#ifdef SIGXFSZ
1304    case SIGXFSZ: return "File size limit exceeded";
1305#endif
1306#ifdef SIGVTALRM
1307    case SIGVTALRM: return "Virtual time alarm";
1308#endif
1309#ifdef SIGPROF
1310    case SIGPROF: return "Profile signal";
1311#endif
1312#ifdef SIGWINCH
1313    case SIGWINCH: return "Window size changed";
1314#endif
1315#ifdef SIGIO
1316    case SIGIO: return "Possible I/O";
1317#endif
1318#ifdef SIGPWR
1319    case SIGPWR: return "Power failure";
1320#endif
1321#ifdef SIGUNUSED
1322    case SIGUNUSED: return "Unused signal";
1323#endif
1324    }
1325#else /* NO_SYS_SIGLIST */
1326
1327#ifdef NO_SYS_SIGLIST_DECL
1328  extern char *sys_siglist[];   /*(see Tue Jan 19 00:44:24 1999 in changelog)*/
1329#endif
1330
1331  return (char*) /* this function should return const --josh */ sys_siglist [signum];
1332#endif /* NO_SYS_SIGLIST */
1333
1334  msg = g_static_private_get (&msg_private);
1335  if (!msg)
1336    {
1337      msg = g_new (gchar, 64);
1338      g_static_private_set (&msg_private, msg, g_free);
1339    }
1340
1341  _g_sprintf (msg, "unknown signal (%d)", signum);
1342 
1343  return msg;
1344}
1345
1346/* Functions g_strlcpy and g_strlcat were originally developed by
1347 * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
1348 * See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3
1349 * for more information.
1350 */
1351
1352#ifdef HAVE_STRLCPY
1353/* Use the native ones, if available; they might be implemented in assembly */
1354gsize
1355g_strlcpy (gchar       *dest,
1356           const gchar *src,
1357           gsize        dest_size)
1358{
1359  g_return_val_if_fail (dest != NULL, 0);
1360  g_return_val_if_fail (src  != NULL, 0);
1361 
1362  return strlcpy (dest, src, dest_size);
1363}
1364
1365gsize
1366g_strlcat (gchar       *dest,
1367           const gchar *src,
1368           gsize        dest_size)
1369{
1370  g_return_val_if_fail (dest != NULL, 0);
1371  g_return_val_if_fail (src  != NULL, 0);
1372 
1373  return strlcat (dest, src, dest_size);
1374}
1375
1376#else /* ! HAVE_STRLCPY */
1377/* g_strlcpy
1378 *
1379 * Copy string src to buffer dest (of buffer size dest_size).  At most
1380 * dest_size-1 characters will be copied.  Always NUL terminates
1381 * (unless dest_size == 0).  This function does NOT allocate memory.
1382 * Unlike strncpy, this function doesn't pad dest (so it's often faster).
1383 * Returns size of attempted result, strlen(src),
1384 * so if retval >= dest_size, truncation occurred.
1385 */
1386gsize
1387g_strlcpy (gchar       *dest,
1388           const gchar *src,
1389           gsize        dest_size)
1390{
1391  register gchar *d = dest;
1392  register const gchar *s = src;
1393  register gsize n = dest_size;
1394 
1395  g_return_val_if_fail (dest != NULL, 0);
1396  g_return_val_if_fail (src  != NULL, 0);
1397 
1398  /* Copy as many bytes as will fit */
1399  if (n != 0 && --n != 0)
1400    do
1401      {
1402        register gchar c = *s++;
1403       
1404        *d++ = c;
1405        if (c == 0)
1406          break;
1407      }
1408    while (--n != 0);
1409 
1410  /* If not enough room in dest, add NUL and traverse rest of src */
1411  if (n == 0)
1412    {
1413      if (dest_size != 0)
1414        *d = 0;
1415      while (*s++)
1416        ;
1417    }
1418 
1419  return s - src - 1;  /* count does not include NUL */
1420}
1421
1422/* g_strlcat
1423 *
1424 * Appends string src to buffer dest (of buffer size dest_size).
1425 * At most dest_size-1 characters will be copied.
1426 * Unlike strncat, dest_size is the full size of dest, not the space left over.
1427 * This function does NOT allocate memory.
1428 * This always NUL terminates (unless siz == 0 or there were no NUL characters
1429 * in the dest_size characters of dest to start with).
1430 * Returns size of attempted result, which is
1431 * MIN (dest_size, strlen (original dest)) + strlen (src),
1432 * so if retval >= dest_size, truncation occurred.
1433 */
1434gsize
1435g_strlcat (gchar       *dest,
1436           const gchar *src,
1437           gsize        dest_size)
1438{
1439  register gchar *d = dest;
1440  register const gchar *s = src;
1441  register gsize bytes_left = dest_size;
1442  gsize dlength;  /* Logically, MIN (strlen (d), dest_size) */
1443 
1444  g_return_val_if_fail (dest != NULL, 0);
1445  g_return_val_if_fail (src  != NULL, 0);
1446 
1447  /* Find the end of dst and adjust bytes left but don't go past end */
1448  while (*d != 0 && bytes_left-- != 0)
1449    d++;
1450  dlength = d - dest;
1451  bytes_left = dest_size - dlength;
1452 
1453  if (bytes_left == 0)
1454    return dlength + strlen (s);
1455 
1456  while (*s != 0)
1457    {
1458      if (bytes_left != 1)
1459        {
1460          *d++ = *s;
1461          bytes_left--;
1462        }
1463      s++;
1464    }
1465  *d = 0;
1466 
1467  return dlength + (s - src);  /* count does not include NUL */
1468}
1469#endif /* ! HAVE_STRLCPY */
1470
1471/**
1472 * g_ascii_strdown:
1473 * @str: a string.
1474 * @len: length of @str in bytes, or -1 if @str is nul-terminated.
1475 *
1476 * Converts all upper case ASCII letters to lower case ASCII letters.
1477 *
1478 * Return value: a newly-allocated string, with all the upper case
1479 *               characters in @str converted to lower case, with
1480 *               semantics that exactly match g_ascii_tolower(). (Note
1481 *               that this is unlike the old g_strdown(), which modified
1482 *               the string in place.)
1483 **/
1484gchar*
1485g_ascii_strdown (const gchar *str,
1486                 gssize       len)
1487{
1488  gchar *result, *s;
1489 
1490  g_return_val_if_fail (str != NULL, NULL);
1491
1492  if (len < 0)
1493    len = strlen (str);
1494
1495  result = g_strndup (str, len);
1496  for (s = result; *s; s++)
1497    *s = g_ascii_tolower (*s);
1498 
1499  return result;
1500}
1501
1502/**
1503 * g_ascii_strup:
1504 * @str: a string.
1505 * @len: length of @str in bytes, or -1 if @str is nul-terminated.
1506 *
1507 * Converts all lower case ASCII letters to upper case ASCII letters.
1508 *
1509 * Return value: a newly allocated string, with all the lower case
1510 *               characters in @str converted to upper case, with
1511 *               semantics that exactly match g_ascii_toupper(). (Note
1512 *               that this is unlike the old g_strup(), which modified
1513 *               the string in place.)
1514 **/
1515gchar*
1516g_ascii_strup (const gchar *str,
1517               gssize       len)
1518{
1519  gchar *result, *s;
1520
1521  g_return_val_if_fail (str != NULL, NULL);
1522
1523  if (len < 0)
1524    len = strlen (str);
1525
1526  result = g_strndup (str, len);
1527  for (s = result; *s; s++)
1528    *s = g_ascii_toupper (*s);
1529
1530  return result;
1531}
1532
1533/**
1534 * g_strdown:
1535 * @string: the string to convert.
1536 *
1537 * Converts a string to lower case. 
1538 *
1539 * Return value: the string
1540 *
1541 * Deprecated: This function is totally broken for the reasons discussed in
1542 * the g_strncasecmp() docs - use g_ascii_strdown() or g_utf8_strdown()
1543 * instead.
1544 **/
1545gchar*
1546g_strdown (gchar *string)
1547{
1548  register guchar *s;
1549 
1550  g_return_val_if_fail (string != NULL, NULL);
1551 
1552  s = (guchar *) string;
1553 
1554  while (*s)
1555    {
1556      if (isupper (*s))
1557        *s = tolower (*s);
1558      s++;
1559    }
1560 
1561  return (gchar *) string;
1562}
1563
1564/**
1565 * g_strup:
1566 * @string: the string to convert.
1567 *
1568 * Converts a string to upper case.
1569 *
1570 * Return value: the string
1571 *
1572 * Deprecated: This function is totally broken for the reasons discussed in
1573 * the g_strncasecmp() docs - use g_ascii_strup() or g_utf8_strup() instead.
1574 **/
1575gchar*
1576g_strup (gchar *string)
1577{
1578  register guchar *s;
1579
1580  g_return_val_if_fail (string != NULL, NULL);
1581
1582  s = (guchar *) string;
1583
1584  while (*s)
1585    {
1586      if (islower (*s))
1587        *s = toupper (*s);
1588      s++;
1589    }
1590
1591  return (gchar *) string;
1592}
1593
1594gchar*
1595g_strreverse (gchar *string)
1596{
1597  g_return_val_if_fail (string != NULL, NULL);
1598
1599  if (*string)
1600    {
1601      register gchar *h, *t;
1602
1603      h = string;
1604      t = string + strlen (string) - 1;
1605
1606      while (h < t)
1607        {
1608          register gchar c;
1609
1610          c = *h;
1611          *h = *t;
1612          h++;
1613          *t = c;
1614          t--;
1615        }
1616    }
1617
1618  return string;
1619}
1620
1621/**
1622 * g_ascii_tolower:
1623 * @c: any character.
1624 *
1625 * Convert a character to ASCII lower case.
1626 *
1627 * Unlike the standard C library tolower() function, this only
1628 * recognizes standard ASCII letters and ignores the locale, returning
1629 * all non-ASCII characters unchanged, even if they are lower case
1630 * letters in a particular character set. Also unlike the standard
1631 * library function, this takes and returns a char, not an int, so
1632 * don't call it on %EOF but no need to worry about casting to #guchar
1633 * before passing a possibly non-ASCII character in.
1634 *
1635 * Return value: the result of converting @c to lower case.
1636 *               If @c is not an ASCII upper case letter,
1637 *               @c is returned unchanged.
1638 **/
1639gchar
1640g_ascii_tolower (gchar c)
1641{
1642  return g_ascii_isupper (c) ? c - 'A' + 'a' : c;
1643}
1644
1645/**
1646 * g_ascii_toupper:
1647 * @c: any character.
1648 *
1649 * Convert a character to ASCII upper case.
1650 *
1651 * Unlike the standard C library toupper() function, this only
1652 * recognizes standard ASCII letters and ignores the locale, returning
1653 * all non-ASCII characters unchanged, even if they are upper case
1654 * letters in a particular character set. Also unlike the standard
1655 * library function, this takes and returns a char, not an int, so
1656 * don't call it on %EOF but no need to worry about casting to #guchar
1657 * before passing a possibly non-ASCII character in.
1658 *
1659 * Return value: the result of converting @c to upper case.
1660 *               If @c is not an ASCII lower case letter,
1661 *               @c is returned unchanged.
1662 **/
1663gchar
1664g_ascii_toupper (gchar c)
1665{
1666  return g_ascii_islower (c) ? c - 'a' + 'A' : c;
1667}
1668
1669/**
1670 * g_ascii_digit_value:
1671 * @c: an ASCII character.
1672 *
1673 * Determines the numeric value of a character as a decimal
1674 * digit. Differs from g_unichar_digit_value() because it takes
1675 * a char, so there's no worry about sign extension if characters
1676 * are signed.
1677 *
1678 * Return value: If @c is a decimal digit (according to
1679 * g_ascii_isdigit()), its numeric value. Otherwise, -1.
1680 **/
1681int
1682g_ascii_digit_value (gchar c)
1683{
1684  if (g_ascii_isdigit (c))
1685    return c - '0';
1686  return -1;
1687}
1688
1689/**
1690 * g_ascii_xdigit_value:
1691 * @c: an ASCII character.
1692 *
1693 * Determines the numeric value of a character as a hexidecimal
1694 * digit. Differs from g_unichar_xdigit_value() because it takes
1695 * a char, so there's no worry about sign extension if characters
1696 * are signed.
1697 *
1698 * Return value: If @c is a hex digit (according to
1699 * g_ascii_isxdigit()), its numeric value. Otherwise, -1.
1700 **/
1701int
1702g_ascii_xdigit_value (gchar c)
1703{
1704  if (c >= 'A' && c <= 'F')
1705    return c - 'A' + 10;
1706  if (c >= 'a' && c <= 'f')
1707    return c - 'a' + 10;
1708  return g_ascii_digit_value (c);
1709}
1710
1711/**
1712 * g_ascii_strcasecmp:
1713 * @s1: string to compare with @s2.
1714 * @s2: string to compare with @s1.
1715 *
1716 * Compare two strings, ignoring the case of ASCII characters.
1717 *
1718 * Unlike the BSD strcasecmp() function, this only recognizes standard
1719 * ASCII letters and ignores the locale, treating all non-ASCII
1720 * characters as if they are not letters.
1721 *
1722 * Return value: an integer less than, equal to, or greater than
1723 *               zero if @s1 is found, respectively, to be less than,
1724 *               to match, or to be greater than @s2.
1725 **/
1726gint
1727g_ascii_strcasecmp (const gchar *s1,
1728                    const gchar *s2)
1729{
1730  gint c1, c2;
1731
1732  g_return_val_if_fail (s1 != NULL, 0);
1733  g_return_val_if_fail (s2 != NULL, 0);
1734
1735  while (*s1 && *s2)
1736    {
1737      c1 = (gint)(guchar) g_ascii_tolower (*s1);
1738      c2 = (gint)(guchar) g_ascii_tolower (*s2);
1739      if (c1 != c2)
1740        return (c1 - c2);
1741      s1++; s2++;
1742    }
1743
1744  return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
1745}
1746
1747/**
1748 * g_ascii_strncasecmp:
1749 * @s1: string to compare with @s2.
1750 * @s2: string to compare with @s1.
1751 * @n:  number of characters to compare.
1752 *
1753 * Compare @s1 and @s2, ignoring the case of ASCII characters and any
1754 * characters after the first @n in each string.
1755 *
1756 * Unlike the BSD strcasecmp() function, this only recognizes standard
1757 * ASCII letters and ignores the locale, treating all non-ASCII
1758 * characters as if they are not letters.
1759 *
1760 * Return value: an integer less than, equal to, or greater than zero
1761 *               if the first @n bytes of @s1 is found, respectively,
1762 *               to be less than, to match, or to be greater than the
1763 *               first @n bytes of @s2.
1764 **/
1765gint
1766g_ascii_strncasecmp (const gchar *s1,
1767                     const gchar *s2,
1768                     gsize n)
1769{
1770  gint c1, c2;
1771
1772  g_return_val_if_fail (s1 != NULL, 0);
1773  g_return_val_if_fail (s2 != NULL, 0);
1774
1775  while (n && *s1 && *s2)
1776    {
1777      n -= 1;
1778      c1 = (gint)(guchar) g_ascii_tolower (*s1);
1779      c2 = (gint)(guchar) g_ascii_tolower (*s2);
1780      if (c1 != c2)
1781        return (c1 - c2);
1782      s1++; s2++;
1783    }
1784
1785  if (n)
1786    return (((gint) (guchar) *s1) - ((gint) (guchar) *s2));
1787  else
1788    return 0;
1789}
1790
1791/**
1792 * g_strcasecmp:
1793 * @s1: a string.
1794 * @s2: a string to compare with @s1.
1795 *
1796 * A case-insensitive string comparison, corresponding to the standard
1797 * strcasecmp() function on platforms which support it.
1798 *
1799 * Return value: 0 if the strings match, a negative value if @s1 &lt; @s2,
1800 *   or a positive value if @s1 &gt; @s2.
1801 *
1802 * Deprecated: See g_strncasecmp() for a discussion of why this function is
1803 *   deprecated and how to replace it.
1804 **/
1805gint
1806g_strcasecmp (const gchar *s1,
1807              const gchar *s2)
1808{
1809#ifdef HAVE_STRCASECMP
1810  g_return_val_if_fail (s1 != NULL, 0);
1811  g_return_val_if_fail (s2 != NULL, 0);
1812
1813  return strcasecmp (s1, s2);
1814#else
1815  gint c1, c2;
1816
1817  g_return_val_if_fail (s1 != NULL, 0);
1818  g_return_val_if_fail (s2 != NULL, 0);
1819
1820  while (*s1 && *s2)
1821    {
1822      /* According to A. Cox, some platforms have islower's that
1823       * don't work right on non-uppercase
1824       */
1825      c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1;
1826      c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2;
1827      if (c1 != c2)
1828        return (c1 - c2);
1829      s1++; s2++;
1830    }
1831
1832  return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
1833#endif
1834}
1835
1836/**
1837 * g_strncasecmp:
1838 * @s1: a string.
1839 * @s2: a string to compare with @s1.
1840 * @n: the maximum number of characters to compare.
1841 *
1842 * A case-insensitive string comparison, corresponding to the standard
1843 * strncasecmp() function on platforms which support it.
1844 * It is similar to g_strcasecmp() except it only compares the first @n
1845 * characters of the strings.
1846 *
1847 * Return value: 0 if the strings match, a negative value if @s1 &lt; @s2,
1848 *   or a positive value if @s1 &gt; @s2.
1849 *
1850 * Deprecated: The problem with g_strncasecmp() is that it does the
1851 * comparison by calling toupper()/tolower(). These functions are
1852 * locale-specific and operate on single bytes. However, it is impossible
1853 * to handle things correctly from an I18N standpoint by operating on
1854 * bytes, since characters may be multibyte. Thus g_strncasecmp() is
1855 * broken if your string is guaranteed to be ASCII, since it's
1856 * locale-sensitive, and it's broken if your string is localized, since
1857 * it doesn't work on many encodings at all, including UTF-8, EUC-JP,
1858 * etc.
1859 *
1860 * There are therefore two replacement functions: g_ascii_strncasecmp(),
1861 * which only works on ASCII and is not locale-sensitive, and
1862 * g_utf8_casefold(), which is good for case-insensitive sorting of UTF-8.
1863 **/
1864gint
1865g_strncasecmp (const gchar *s1,
1866               const gchar *s2,
1867               gsize n)     
1868{
1869#ifdef HAVE_STRNCASECMP
1870  return strncasecmp (s1, s2, n);
1871#else
1872  gint c1, c2;
1873
1874  g_return_val_if_fail (s1 != NULL, 0);
1875  g_return_val_if_fail (s2 != NULL, 0);
1876
1877  while (n && *s1 && *s2)
1878    {
1879      n -= 1;
1880      /* According to A. Cox, some platforms have islower's that
1881       * don't work right on non-uppercase
1882       */
1883      c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1;
1884      c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2;
1885      if (c1 != c2)
1886        return (c1 - c2);
1887      s1++; s2++;
1888    }
1889
1890  if (n)
1891    return (((gint) (guchar) *s1) - ((gint) (guchar) *s2));
1892  else
1893    return 0;
1894#endif
1895}
1896
1897gchar*
1898g_strdelimit (gchar       *string,
1899              const gchar *delimiters,
1900              gchar        new_delim)
1901{
1902  register gchar *c;
1903
1904  g_return_val_if_fail (string != NULL, NULL);
1905
1906  if (!delimiters)
1907    delimiters = G_STR_DELIMITERS;
1908
1909  for (c = string; *c; c++)
1910    {
1911      if (strchr (delimiters, *c))
1912        *c = new_delim;
1913    }
1914
1915  return string;
1916}
1917
1918gchar*
1919g_strcanon (gchar       *string,
1920            const gchar *valid_chars,
1921            gchar        substitutor)
1922{
1923  register gchar *c;
1924
1925  g_return_val_if_fail (string != NULL, NULL);
1926  g_return_val_if_fail (valid_chars != NULL, NULL);
1927
1928  for (c = string; *c; c++)
1929    {
1930      if (!strchr (valid_chars, *c))
1931        *c = substitutor;
1932    }
1933
1934  return string;
1935}
1936
1937gchar*
1938g_strcompress (const gchar *source)
1939{
1940  const gchar *p = source, *octal;
1941  gchar *dest = g_malloc (strlen (source) + 1);
1942  gchar *q = dest;
1943 
1944  while (*p)
1945    {
1946      if (*p == '\\')
1947        {
1948          p++;
1949          switch (*p)
1950            {
1951            case '0':  case '1':  case '2':  case '3':  case '4':
1952            case '5':  case '6':  case '7':
1953              *q = 0;
1954              octal = p;
1955              while ((p < octal + 3) && (*p >= '0') && (*p <= '7'))
1956                {
1957                  *q = (*q * 8) + (*p - '0');
1958                  p++;
1959                }
1960              q++;
1961              p--;
1962              break;
1963            case 'b':
1964              *q++ = '\b';
1965              break;
1966            case 'f':
1967              *q++ = '\f';
1968              break;
1969            case 'n':
1970              *q++ = '\n';
1971              break;
1972            case 'r':
1973              *q++ = '\r';
1974              break;
1975            case 't':
1976              *q++ = '\t';
1977              break;
1978            default:            /* Also handles \" and \\ */
1979              *q++ = *p;
1980              break;
1981            }
1982        }
1983      else
1984        *q++ = *p;
1985      p++;
1986    }
1987  *q = 0;
1988 
1989  return dest;
1990}
1991
1992gchar *
1993g_strescape (const gchar *source,
1994             const gchar *exceptions)
1995{
1996  const guchar *p;
1997  gchar *dest;
1998  gchar *q;
1999  guchar excmap[256];
2000 
2001  g_return_val_if_fail (source != NULL, NULL);
2002
2003  p = (guchar *) source;
2004  /* Each source byte needs maximally four destination chars (\777) */
2005  q = dest = g_malloc (strlen (source) * 4 + 1);
2006
2007  memset (excmap, 0, 256);
2008  if (exceptions)
2009    {
2010      guchar *e = (guchar *) exceptions;
2011
2012      while (*e)
2013        {
2014          excmap[*e] = 1;
2015          e++;
2016        }
2017    }
2018
2019  while (*p)
2020    {
2021      if (excmap[*p])
2022        *q++ = *p;
2023      else
2024        {
2025          switch (*p)
2026            {
2027            case '\b':
2028              *q++ = '\\';
2029              *q++ = 'b';
2030              break;
2031            case '\f':
2032              *q++ = '\\';
2033              *q++ = 'f';
2034              break;
2035            case '\n':
2036              *q++ = '\\';
2037              *q++ = 'n';
2038              break;
2039            case '\r':
2040              *q++ = '\\';
2041              *q++ = 'r';
2042              break;
2043            case '\t':
2044              *q++ = '\\';
2045              *q++ = 't';
2046              break;
2047            case '\\':
2048              *q++ = '\\';
2049              *q++ = '\\';
2050              break;
2051            case '"':
2052              *q++ = '\\';
2053              *q++ = '"';
2054              break;
2055            default:
2056              if ((*p < ' ') || (*p >= 0177))
2057                {
2058                  *q++ = '\\';
2059                  *q++ = '0' + (((*p) >> 6) & 07);
2060                  *q++ = '0' + (((*p) >> 3) & 07);
2061                  *q++ = '0' + ((*p) & 07);
2062                }
2063              else
2064                *q++ = *p;
2065              break;
2066            }
2067        }
2068      p++;
2069    }
2070  *q = 0;
2071  return dest;
2072}
2073
2074gchar*
2075g_strchug (gchar *string)
2076{
2077  guchar *start;
2078
2079  g_return_val_if_fail (string != NULL, NULL);
2080
2081  for (start = (guchar*) string; *start && g_ascii_isspace (*start); start++)
2082    ;
2083
2084  g_memmove (string, start, strlen ((gchar *) start) + 1);
2085
2086  return string;
2087}
2088
2089gchar*
2090g_strchomp (gchar *string)
2091{
2092  gsize len;
2093
2094  g_return_val_if_fail (string != NULL, NULL);
2095
2096  len = strlen (string);
2097  while (len--)
2098    {
2099      if (g_ascii_isspace ((guchar) string[len]))
2100        string[len] = '\0';
2101      else
2102        break;
2103    }
2104
2105  return string;
2106}
2107
2108/**
2109 * g_strsplit:
2110 * @string: a string to split.
2111 * @delimiter: a string which specifies the places at which to split the string.
2112 *     The delimiter is not included in any of the resulting strings, unless
2113 *     @max_tokens is reached.
2114 * @max_tokens: the maximum number of pieces to split @string into. If this is
2115 *              less than 1, the string is split completely.
2116 *
2117 * Splits a string into a maximum of @max_tokens pieces, using the given
2118 * @delimiter. If @max_tokens is reached, the remainder of @string is appended
2119 * to the last token.
2120 *
2121 * As a special case, the result of splitting the empty string "" is an empty
2122 * vector, not a vector containing a single string. The reason for this
2123 * special case is that being able to represent a empty vector is typically
2124 * more useful than consistent handling of empty elements. If you do need
2125 * to represent empty elements, you'll need to check for the empty string
2126 * before calling g_strsplit().
2127 *
2128 * Return value: a newly-allocated %NULL-terminated array of strings. Use
2129 *    g_strfreev() to free it.
2130 **/
2131gchar**
2132g_strsplit (const gchar *string,
2133            const gchar *delimiter,
2134            gint         max_tokens)
2135{
2136  GSList *string_list = NULL, *slist;
2137  gchar **str_array, *s;
2138  guint n = 0;
2139  const gchar *remainder;
2140
2141  g_return_val_if_fail (string != NULL, NULL);
2142  g_return_val_if_fail (delimiter != NULL, NULL);
2143  g_return_val_if_fail (delimiter[0] != '\0', NULL);
2144
2145  if (max_tokens < 1)
2146    max_tokens = G_MAXINT;
2147
2148  remainder = string;
2149  s = strstr (remainder, delimiter);
2150  if (s)
2151    {
2152      gsize delimiter_len = strlen (delimiter);   
2153
2154      while (--max_tokens && s)
2155        {
2156          gsize len;     
2157          gchar *new_string;
2158
2159          len = s - remainder;
2160          new_string = g_new (gchar, len + 1);
2161          strncpy (new_string, remainder, len);
2162          new_string[len] = 0;
2163          string_list = g_slist_prepend (string_list, new_string);
2164          n++;
2165          remainder = s + delimiter_len;
2166          s = strstr (remainder, delimiter);
2167        }
2168    }
2169  if (*string)
2170    {
2171      n++;
2172      string_list = g_slist_prepend (string_list, g_strdup (remainder));
2173    }
2174
2175  str_array = g_new (gchar*, n + 1);
2176
2177  str_array[n--] = NULL;
2178  for (slist = string_list; slist; slist = slist->next)
2179    str_array[n--] = slist->data;
2180
2181  g_slist_free (string_list);
2182
2183  return str_array;
2184}
2185
2186void
2187g_strfreev (gchar **str_array)
2188{
2189  if (str_array)
2190    {
2191      int i;
2192
2193      for(i = 0; str_array[i] != NULL; i++)
2194        g_free(str_array[i]);
2195
2196      g_free (str_array);
2197    }
2198}
2199
2200/**
2201 * g_strdupv:
2202 * @str_array: %NULL-terminated array of strings.
2203 *
2204 * Copies %NULL-terminated array of strings. The copy is a deep copy;
2205 * the new array should be freed by first freeing each string, then
2206 * the array itself. g_strfreev() does this for you. If called
2207 * on a %NULL value, g_strdupv() simply returns %NULL.
2208 *
2209 * Return value: a new %NULL-terminated array of strings.
2210 **/
2211gchar**
2212g_strdupv (gchar **str_array)
2213{
2214  if (str_array)
2215    {
2216      gint i;
2217      gchar **retval;
2218
2219      i = 0;
2220      while (str_array[i])
2221        ++i;
2222         
2223      retval = g_new (gchar*, i + 1);
2224
2225      i = 0;
2226      while (str_array[i])
2227        {
2228          retval[i] = g_strdup (str_array[i]);
2229          ++i;
2230        }
2231      retval[i] = NULL;
2232
2233      return retval;
2234    }
2235  else
2236    return NULL;
2237}
2238
2239gchar*
2240g_strjoinv (const gchar  *separator,
2241            gchar       **str_array)
2242{
2243  gchar *string;
2244  gchar *ptr;
2245
2246  g_return_val_if_fail (str_array != NULL, NULL);
2247
2248  if (separator == NULL)
2249    separator = "";
2250
2251  if (*str_array)
2252    {
2253      gint i;
2254      gsize len;
2255      gsize separator_len;     
2256
2257      separator_len = strlen (separator);
2258      /* First part, getting length */
2259      len = 1 + strlen (str_array[0]);
2260      for (i = 1; str_array[i] != NULL; i++)
2261        len += strlen (str_array[i]);
2262      len += separator_len * (i - 1);
2263
2264      /* Second part, building string */
2265      string = g_new (gchar, len);
2266      ptr = g_stpcpy (string, *str_array);
2267      for (i = 1; str_array[i] != NULL; i++)
2268        {
2269          ptr = g_stpcpy (ptr, separator);
2270          ptr = g_stpcpy (ptr, str_array[i]);
2271        }
2272      }
2273  else
2274    string = g_strdup ("");
2275
2276  return string;
2277}
2278
2279gchar*
2280g_strjoin (const gchar  *separator,
2281           ...)
2282{
2283  gchar *string, *s;
2284  va_list args;
2285  gsize len;               
2286  gsize separator_len;     
2287  gchar *ptr;
2288
2289  if (separator == NULL)
2290    separator = "";
2291
2292  separator_len = strlen (separator);
2293
2294  va_start (args, separator);
2295
2296  s = va_arg (args, gchar*);
2297
2298  if (s)
2299    {
2300      /* First part, getting length */
2301      len = 1 + strlen (s);
2302
2303      s = va_arg (args, gchar*);
2304      while (s)
2305        {
2306          len += separator_len + strlen (s);
2307          s = va_arg (args, gchar*);
2308        }
2309      va_end (args);
2310
2311      /* Second part, building string */
2312      string = g_new (gchar, len);
2313
2314      va_start (args, separator);
2315
2316      s = va_arg (args, gchar*);
2317      ptr = g_stpcpy (string, s);
2318
2319      s = va_arg (args, gchar*);
2320      while (s)
2321        {
2322          ptr = g_stpcpy (ptr, separator);
2323          ptr = g_stpcpy (ptr, s);
2324          s = va_arg (args, gchar*);
2325        }
2326    }
2327  else
2328    string = g_strdup ("");
2329
2330  va_end (args);
2331
2332  return string;
2333}
2334
2335
2336/**
2337 * g_strstr_len:
2338 * @haystack: a string.
2339 * @haystack_len: the maximum length of @haystack.
2340 * @needle: the string to search for.
2341 *
2342 * Searches the string @haystack for the first occurrence
2343 * of the string @needle, limiting the length of the search
2344 * to @haystack_len.
2345 *
2346 * Return value: a pointer to the found occurrence, or
2347 *    %NULL if not found.
2348 **/
2349gchar *
2350g_strstr_len (const gchar *haystack,
2351              gssize       haystack_len,
2352              const gchar *needle)
2353{
2354  g_return_val_if_fail (haystack != NULL, NULL);
2355  g_return_val_if_fail (needle != NULL, NULL);
2356 
2357  if (haystack_len < 0)
2358    return strstr (haystack, needle);
2359  else
2360    {
2361      const gchar *p = haystack;
2362      gsize needle_len = strlen (needle);
2363      const gchar *end;
2364      gsize i;
2365
2366      if (needle_len == 0)
2367        return (gchar *)haystack;
2368
2369      if (haystack_len < needle_len)
2370        return NULL;
2371     
2372      end = haystack + haystack_len - needle_len;
2373     
2374      while (*p && p <= end)
2375        {
2376          for (i = 0; i < needle_len; i++)
2377            if (p[i] != needle[i])
2378              goto next;
2379         
2380          return (gchar *)p;
2381         
2382        next:
2383          p++;
2384        }
2385     
2386      return NULL;
2387    }
2388}
2389
2390/**
2391 * g_strrstr:
2392 * @haystack: a nul-terminated string.
2393 * @needle: the nul-terminated string to search for.
2394 *
2395 * Searches the string @haystack for the last occurrence
2396 * of the string @needle.
2397 *
2398 * Return value: a pointer to the found occurrence, or
2399 *    %NULL if not found.
2400 **/
2401gchar *
2402g_strrstr (const gchar *haystack,
2403           const gchar *needle)
2404{
2405  gsize i;
2406  gsize needle_len;
2407  gsize haystack_len;
2408  const gchar *p;
2409     
2410  g_return_val_if_fail (haystack != NULL, NULL);
2411  g_return_val_if_fail (needle != NULL, NULL);
2412
2413  needle_len = strlen (needle);
2414  haystack_len = strlen (haystack);
2415
2416  if (needle_len == 0)
2417    return (gchar *)haystack;
2418
2419  if (haystack_len < needle_len)
2420    return NULL;
2421 
2422  p = haystack + haystack_len - needle_len;
2423
2424  while (p >= haystack)
2425    {
2426      for (i = 0; i < needle_len; i++)
2427        if (p[i] != needle[i])
2428          goto next;
2429     
2430      return (gchar *)p;
2431     
2432    next:
2433      p--;
2434    }
2435 
2436  return NULL;
2437}
2438
2439/**
2440 * g_strrstr_len:
2441 * @haystack: a nul-terminated string.
2442 * @haystack_len: the maximum length of @haystack.
2443 * @needle: the nul-terminated string to search for.
2444 *
2445 * Searches the string @haystack for the last occurrence
2446 * of the string @needle, limiting the length of the search
2447 * to @haystack_len.
2448 *
2449 * Return value: a pointer to the found occurrence, or
2450 *    %NULL if not found.
2451 **/
2452gchar *
2453g_strrstr_len (const gchar *haystack,
2454               gssize        haystack_len,
2455               const gchar *needle)
2456{
2457  g_return_val_if_fail (haystack != NULL, NULL);
2458  g_return_val_if_fail (needle != NULL, NULL);
2459 
2460  if (haystack_len < 0)
2461    return g_strrstr (haystack, needle);
2462  else
2463    {
2464      gsize needle_len = strlen (needle);
2465      const gchar *haystack_max = haystack + haystack_len;
2466      const gchar *p = haystack;
2467      gsize i;
2468
2469      while (p < haystack_max && *p)
2470        p++;
2471
2472      if (p < haystack + needle_len)
2473        return NULL;
2474       
2475      p -= needle_len;
2476
2477      while (p >= haystack)
2478        {
2479          for (i = 0; i < needle_len; i++)
2480            if (p[i] != needle[i])
2481              goto next;
2482         
2483          return (gchar *)p;
2484         
2485        next:
2486          p--;
2487        }
2488
2489      return NULL;
2490    }
2491}
2492
2493
2494/**
2495 * g_str_has_suffix:
2496 * @str: a nul-terminated string.
2497 * @suffix: the nul-terminated suffix to look for.
2498 *
2499 * Looks whether the string @str ends with @suffix.
2500 *
2501 * Return value: %TRUE if @str end with @suffix, %FALSE otherwise.
2502 *
2503 * Since: 2.2
2504 **/
2505gboolean
2506g_str_has_suffix (const gchar  *str,
2507                  const gchar  *suffix)
2508{
2509  int str_len;
2510  int suffix_len;
2511 
2512  g_return_val_if_fail (str != NULL, FALSE);
2513  g_return_val_if_fail (suffix != NULL, FALSE);
2514
2515  str_len = strlen (str);
2516  suffix_len = strlen (suffix);
2517
2518  if (str_len < suffix_len)
2519    return FALSE;
2520
2521  return strcmp (str + str_len - suffix_len, suffix) == 0;
2522}
2523
2524/**
2525 * g_str_has_prefix:
2526 * @str: a nul-terminated string.
2527 * @prefix: the nul-terminated prefix to look for.
2528 *
2529 * Looks whether the string @str begins with @prefix.
2530 *
2531 * Return value: %TRUE if @str begins with @prefix, %FALSE otherwise.
2532 *
2533 * Since: 2.2
2534 **/
2535gboolean
2536g_str_has_prefix (const gchar  *str,
2537                  const gchar  *prefix)
2538{
2539  int str_len;
2540  int prefix_len;
2541 
2542  g_return_val_if_fail (str != NULL, FALSE);
2543  g_return_val_if_fail (prefix != NULL, FALSE);
2544
2545  str_len = strlen (str);
2546  prefix_len = strlen (prefix);
2547
2548  if (str_len < prefix_len)
2549    return FALSE;
2550 
2551  return strncmp (str, prefix, prefix_len) == 0;
2552}
2553
Note: See TracBrowser for help on using the repository browser.