Blame glib/gstrfuncs.c

Packit ae235b
/* GLIB - Library of useful routines for C programming
Packit ae235b
 * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
Packit ae235b
 *
Packit ae235b
 * This library is free software; you can redistribute it and/or
Packit ae235b
 * modify it under the terms of the GNU Lesser General Public
Packit ae235b
 * License as published by the Free Software Foundation; either
Packit ae235b
 * version 2.1 of the License, or (at your option) any later version.
Packit ae235b
 *
Packit ae235b
 * This library is distributed in the hope that it will be useful,
Packit ae235b
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit ae235b
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit ae235b
 * Lesser General Public License for more details.
Packit ae235b
 *
Packit ae235b
 * You should have received a copy of the GNU Lesser General Public
Packit ae235b
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
Packit ae235b
 */
Packit ae235b
Packit ae235b
/*
Packit ae235b
 * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
Packit ae235b
 * file for a list of people on the GLib Team.  See the ChangeLog
Packit ae235b
 * files for a list of changes.  These files are distributed with
Packit ae235b
 * GLib at ftp://ftp.gtk.org/pub/gtk/.
Packit ae235b
 */
Packit ae235b
Packit ae235b
/*
Packit ae235b
 * MT safe
Packit ae235b
 */
Packit ae235b
Packit ae235b
#include "config.h"
Packit ae235b
Packit ae235b
#include <stdarg.h>
Packit ae235b
#include <stdio.h>
Packit ae235b
#include <stdlib.h>
Packit ae235b
#include <locale.h>
Packit ae235b
#include <string.h>
Packit ae235b
#include <locale.h>
Packit ae235b
#include <errno.h>
Packit ae235b
#include <ctype.h>              /* For tolower() */
Packit ae235b
Packit ae235b
#ifdef HAVE_XLOCALE_H
Packit ae235b
/* Needed on BSD/OS X for e.g. strtod_l */
Packit ae235b
#include <xlocale.h>
Packit ae235b
#endif
Packit ae235b
Packit ae235b
#ifdef G_OS_WIN32
Packit ae235b
#include <windows.h>
Packit ae235b
#endif
Packit ae235b
Packit ae235b
/* do not include <unistd.h> here, it may interfere with g_strsignal() */
Packit ae235b
Packit ae235b
#include "gstrfuncs.h"
Packit ae235b
Packit ae235b
#include "gprintf.h"
Packit ae235b
#include "gprintfint.h"
Packit ae235b
#include "glibintl.h"
Packit ae235b
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * SECTION:string_utils
Packit ae235b
 * @title: String Utility Functions
Packit ae235b
 * @short_description: various string-related functions
Packit ae235b
 *
Packit ae235b
 * This section describes a number of utility functions for creating,
Packit ae235b
 * duplicating, and manipulating strings.
Packit ae235b
 *
Packit ae235b
 * Note that the functions g_printf(), g_fprintf(), g_sprintf(),
Packit ae235b
 * g_vprintf(), g_vfprintf(), g_vsprintf() and g_vasprintf()
Packit ae235b
 * are declared in the header `gprintf.h` which is not included in `glib.h`
Packit ae235b
 * (otherwise using `glib.h` would drag in `stdio.h`), so you'll have to
Packit ae235b
 * explicitly include `<glib/gprintf.h>` in order to use the GLib
Packit ae235b
 * printf() functions.
Packit ae235b
 *
Packit ae235b
 * ## String precision pitfalls # {#string-precision}
Packit ae235b
 *
Packit ae235b
 * While you may use the printf() functions to format UTF-8 strings,
Packit ae235b
 * notice that the precision of a \%Ns parameter is interpreted
Packit ae235b
 * as the number of bytes, not characters to print. On top of that,
Packit ae235b
 * the GNU libc implementation of the printf() functions has the
Packit ae235b
 * "feature" that it checks that the string given for the \%Ns
Packit ae235b
 * parameter consists of a whole number of characters in the current
Packit ae235b
 * encoding. So, unless you are sure you are always going to be in an
Packit ae235b
 * UTF-8 locale or your know your text is restricted to ASCII, avoid
Packit ae235b
 * using \%Ns. If your intention is to format strings for a
Packit ae235b
 * certain number of columns, then \%Ns is not a correct solution
Packit ae235b
 * anyway, since it fails to take wide characters (see g_unichar_iswide())
Packit ae235b
 * into account.
Packit ae235b
 *
Packit ae235b
 * Note also that there are various printf() parameters which are platform
Packit ae235b
 * dependent. GLib provides platform independent macros for these parameters
Packit ae235b
 * which should be used instead. A common example is %G_GUINT64_FORMAT, which
Packit ae235b
 * should be used instead of `%llu` or similar parameters for formatting
Packit ae235b
 * 64-bit integers. These macros are all named `G_*_FORMAT`; see
Packit ae235b
 * [Basic Types][glib-Basic-Types].
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_isalnum:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Determines whether a character is alphanumeric.
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library isalnum() function, this only
Packit ae235b
 * recognizes standard ASCII letters and ignores the locale,
Packit ae235b
 * returning %FALSE for all non-ASCII characters. Also, unlike
Packit ae235b
 * the standard library function, this takes a char, not an int,
Packit ae235b
 * so don't call it on %EOF, but no need to cast to #guchar before
Packit ae235b
 * passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @c is an ASCII alphanumeric character
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_isalpha:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Determines whether a character is alphabetic (i.e. a letter).
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library isalpha() function, this only
Packit ae235b
 * recognizes standard ASCII letters and ignores the locale,
Packit ae235b
 * returning %FALSE for all non-ASCII characters. Also, unlike
Packit ae235b
 * the standard library function, this takes a char, not an int,
Packit ae235b
 * so don't call it on %EOF, but no need to cast to #guchar before
Packit ae235b
 * passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @c is an ASCII alphabetic character
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_iscntrl:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Determines whether a character is a control character.
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library iscntrl() function, this only
Packit ae235b
 * recognizes standard ASCII control characters and ignores the
Packit ae235b
 * locale, returning %FALSE for all non-ASCII characters. Also,
Packit ae235b
 * unlike the standard library function, this takes a char, not
Packit ae235b
 * an int, so don't call it on %EOF, but no need to cast to #guchar
Packit ae235b
 * before passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @c is an ASCII control character.
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_isdigit:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Determines whether a character is digit (0-9).
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library isdigit() function, this takes
Packit ae235b
 * a char, not an int, so don't call it  on %EOF, but no need to
Packit ae235b
 * cast to #guchar before passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @c is an ASCII digit.
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_isgraph:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Determines whether a character is a printing character and not a space.
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library isgraph() function, this only
Packit ae235b
 * recognizes standard ASCII characters and ignores the locale,
Packit ae235b
 * returning %FALSE for all non-ASCII characters. Also, unlike
Packit ae235b
 * the standard library function, this takes a char, not an int,
Packit ae235b
 * so don't call it on %EOF, but no need to cast to #guchar before
Packit ae235b
 * passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @c is an ASCII printing character other than space.
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_islower:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Determines whether a character is an ASCII lower case letter.
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library islower() function, this only
Packit ae235b
 * recognizes standard ASCII letters and ignores the locale,
Packit ae235b
 * returning %FALSE for all non-ASCII characters. Also, unlike
Packit ae235b
 * the standard library function, this takes a char, not an int,
Packit ae235b
 * so don't call it on %EOF, but no need to worry about casting
Packit ae235b
 * to #guchar before passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @c is an ASCII lower case letter
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_isprint:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Determines whether a character is a printing character.
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library isprint() function, this only
Packit ae235b
 * recognizes standard ASCII characters and ignores the locale,
Packit ae235b
 * returning %FALSE for all non-ASCII characters. Also, unlike
Packit ae235b
 * the standard library function, this takes a char, not an int,
Packit ae235b
 * so don't call it on %EOF, but no need to cast to #guchar before
Packit ae235b
 * passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @c is an ASCII printing character.
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_ispunct:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Determines whether a character is a punctuation character.
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library ispunct() function, this only
Packit ae235b
 * recognizes standard ASCII letters and ignores the locale,
Packit ae235b
 * returning %FALSE for all non-ASCII characters. Also, unlike
Packit ae235b
 * the standard library function, this takes a char, not an int,
Packit ae235b
 * so don't call it on %EOF, but no need to cast to #guchar before
Packit ae235b
 * passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @c is an ASCII punctuation character.
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_isspace:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Determines whether a character is a white-space character.
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library isspace() function, this only
Packit ae235b
 * recognizes standard ASCII white-space and ignores the locale,
Packit ae235b
 * returning %FALSE for all non-ASCII characters. Also, unlike
Packit ae235b
 * the standard library function, this takes a char, not an int,
Packit ae235b
 * so don't call it on %EOF, but no need to cast to #guchar before
Packit ae235b
 * passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @c is an ASCII white-space character
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_isupper:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Determines whether a character is an ASCII upper case letter.
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library isupper() function, this only
Packit ae235b
 * recognizes standard ASCII letters and ignores the locale,
Packit ae235b
 * returning %FALSE for all non-ASCII characters. Also, unlike
Packit ae235b
 * the standard library function, this takes a char, not an int,
Packit ae235b
 * so don't call it on %EOF, but no need to worry about casting
Packit ae235b
 * to #guchar before passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @c is an ASCII upper case letter
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_isxdigit:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Determines whether a character is a hexadecimal-digit character.
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library isxdigit() function, this takes
Packit ae235b
 * a char, not an int, so don't call it on %EOF, but no need to
Packit ae235b
 * cast to #guchar before passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @c is an ASCII hexadecimal-digit character.
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * G_ASCII_DTOSTR_BUF_SIZE:
Packit ae235b
 *
Packit ae235b
 * A good size for a buffer to be passed into g_ascii_dtostr().
Packit ae235b
 * It is guaranteed to be enough for all output of that function
Packit ae235b
 * on systems with 64bit IEEE-compatible doubles.
Packit ae235b
 *
Packit ae235b
 * The typical usage would be something like:
Packit ae235b
 * |[ 
Packit ae235b
 *   char buf[G_ASCII_DTOSTR_BUF_SIZE];
Packit ae235b
 *
Packit ae235b
 *   fprintf (out, "value=%s\n", g_ascii_dtostr (buf, sizeof (buf), value));
Packit ae235b
 * ]|
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strstrip:
Packit ae235b
 * @string: a string to remove the leading and trailing whitespace from
Packit ae235b
 *
Packit ae235b
 * Removes leading and trailing whitespace from a string.
Packit ae235b
 * See g_strchomp() and g_strchug().
Packit ae235b
 *
Packit ae235b
 * Returns: @string
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * G_STR_DELIMITERS:
Packit ae235b
 *
Packit ae235b
 * The standard delimiters, used in g_strdelimit().
Packit ae235b
 */
Packit ae235b
Packit ae235b
static const guint16 ascii_table_data[256] = {
Packit ae235b
  0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
Packit ae235b
  0x004, 0x104, 0x104, 0x004, 0x104, 0x104, 0x004, 0x004,
Packit ae235b
  0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
Packit ae235b
  0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
Packit ae235b
  0x140, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
Packit ae235b
  0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
Packit ae235b
  0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459, 0x459,
Packit ae235b
  0x459, 0x459, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
Packit ae235b
  0x0d0, 0x653, 0x653, 0x653, 0x653, 0x653, 0x653, 0x253,
Packit ae235b
  0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
Packit ae235b
  0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253, 0x253,
Packit ae235b
  0x253, 0x253, 0x253, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x0d0,
Packit ae235b
  0x0d0, 0x473, 0x473, 0x473, 0x473, 0x473, 0x473, 0x073,
Packit ae235b
  0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
Packit ae235b
  0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073, 0x073,
Packit ae235b
  0x073, 0x073, 0x073, 0x0d0, 0x0d0, 0x0d0, 0x0d0, 0x004
Packit ae235b
  /* the upper 128 are all zeroes */
Packit ae235b
};
Packit ae235b
Packit ae235b
const guint16 * const g_ascii_table = ascii_table_data;
Packit ae235b
Packit ae235b
#if defined (HAVE_NEWLOCALE) && \
Packit ae235b
    defined (HAVE_USELOCALE) && \
Packit ae235b
    defined (HAVE_STRTOD_L) && \
Packit ae235b
    defined (HAVE_STRTOULL_L) && \
Packit ae235b
    defined (HAVE_STRTOLL_L)
Packit ae235b
#define USE_XLOCALE 1
Packit ae235b
#endif
Packit ae235b
Packit ae235b
#ifdef USE_XLOCALE
Packit ae235b
static locale_t
Packit ae235b
get_C_locale (void)
Packit ae235b
{
Packit ae235b
  static gsize initialized = FALSE;
Packit ae235b
  static locale_t C_locale = NULL;
Packit ae235b
Packit ae235b
  if (g_once_init_enter (&initialized))
Packit ae235b
    {
Packit ae235b
      C_locale = newlocale (LC_ALL_MASK, "C", NULL);
Packit ae235b
      g_once_init_leave (&initialized, TRUE);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return C_locale;
Packit ae235b
}
Packit ae235b
#endif
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strdup:
Packit ae235b
 * @str: (nullable): the string to duplicate
Packit ae235b
 *
Packit ae235b
 * Duplicates a string. If @str is %NULL it returns %NULL.
Packit ae235b
 * The returned string should be freed with g_free()
Packit ae235b
 * when no longer needed.
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated copy of @str
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_strdup (const gchar *str)
Packit ae235b
{
Packit ae235b
  gchar *new_str;
Packit ae235b
  gsize length;
Packit ae235b
Packit ae235b
  if (str)
Packit ae235b
    {
Packit ae235b
      length = strlen (str) + 1;
Packit ae235b
      new_str = g_new (char, length);
Packit ae235b
      memcpy (new_str, str, length);
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    new_str = NULL;
Packit ae235b
Packit ae235b
  return new_str;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_memdup:
Packit ae235b
 * @mem: the memory to copy.
Packit ae235b
 * @byte_size: the number of bytes to copy.
Packit ae235b
 *
Packit ae235b
 * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it
Packit ae235b
 * from @mem. If @mem is %NULL it returns %NULL.
Packit ae235b
 *
Packit ae235b
 * Returns: a pointer to the newly-allocated copy of the memory, or %NULL if @mem
Packit ae235b
 *  is %NULL.
Packit ae235b
 */
Packit ae235b
gpointer
Packit ae235b
g_memdup (gconstpointer mem,
Packit ae235b
          guint         byte_size)
Packit ae235b
{
Packit ae235b
  gpointer new_mem;
Packit ae235b
Packit ae235b
  if (mem && byte_size != 0)
Packit ae235b
    {
Packit ae235b
      new_mem = g_malloc (byte_size);
Packit ae235b
      memcpy (new_mem, mem, byte_size);
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    new_mem = NULL;
Packit ae235b
Packit ae235b
  return new_mem;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strndup:
Packit ae235b
 * @str: the string to duplicate
Packit ae235b
 * @n: the maximum number of bytes to copy from @str
Packit ae235b
 *
Packit ae235b
 * Duplicates the first @n bytes of a string, returning a newly-allocated
Packit ae235b
 * buffer @n + 1 bytes long which will always be nul-terminated. If @str
Packit ae235b
 * is less than @n bytes long the buffer is padded with nuls. If @str is
Packit ae235b
 * %NULL it returns %NULL. The returned value should be freed when no longer
Packit ae235b
 * needed.
Packit ae235b
 *
Packit ae235b
 * To copy a number of characters from a UTF-8 encoded string,
Packit ae235b
 * use g_utf8_strncpy() instead.
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated buffer containing the first @n bytes
Packit ae235b
 *     of @str, nul-terminated
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_strndup (const gchar *str,
Packit ae235b
           gsize        n)
Packit ae235b
{
Packit ae235b
  gchar *new_str;
Packit ae235b
Packit ae235b
  if (str)
Packit ae235b
    {
Packit ae235b
      new_str = g_new (gchar, n + 1);
Packit ae235b
      strncpy (new_str, str, n);
Packit ae235b
      new_str[n] = '\0';
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    new_str = NULL;
Packit ae235b
Packit ae235b
  return new_str;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strnfill:
Packit ae235b
 * @length: the length of the new string
Packit ae235b
 * @fill_char: the byte to fill the string with
Packit ae235b
 *
Packit ae235b
 * Creates a new string @length bytes long filled with @fill_char.
Packit ae235b
 * The returned string should be freed when no longer needed.
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated string filled the @fill_char
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_strnfill (gsize length,
Packit ae235b
            gchar fill_char)
Packit ae235b
{
Packit ae235b
  gchar *str;
Packit ae235b
Packit ae235b
  str = g_new (gchar, length + 1);
Packit ae235b
  memset (str, (guchar)fill_char, length);
Packit ae235b
  str[length] = '\0';
Packit ae235b
Packit ae235b
  return str;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_stpcpy:
Packit ae235b
 * @dest: destination buffer.
Packit ae235b
 * @src: source string.
Packit ae235b
 *
Packit ae235b
 * Copies a nul-terminated string into the dest buffer, include the
Packit ae235b
 * trailing nul, and return a pointer to the trailing nul byte.
Packit ae235b
 * This is useful for concatenating multiple strings together
Packit ae235b
 * without having to repeatedly scan for the end.
Packit ae235b
 *
Packit ae235b
 * Returns: a pointer to trailing nul byte.
Packit ae235b
 **/
Packit ae235b
gchar *
Packit ae235b
g_stpcpy (gchar       *dest,
Packit ae235b
          const gchar *src)
Packit ae235b
{
Packit ae235b
#ifdef HAVE_STPCPY
Packit ae235b
  g_return_val_if_fail (dest != NULL, NULL);
Packit ae235b
  g_return_val_if_fail (src != NULL, NULL);
Packit ae235b
  return stpcpy (dest, src);
Packit ae235b
#else
Packit ae235b
  gchar *d = dest;
Packit ae235b
  const gchar *s = src;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (dest != NULL, NULL);
Packit ae235b
  g_return_val_if_fail (src != NULL, NULL);
Packit ae235b
  do
Packit ae235b
    *d++ = *s;
Packit ae235b
  while (*s++ != '\0');
Packit ae235b
Packit ae235b
  return d - 1;
Packit ae235b
#endif
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strdup_vprintf:
Packit ae235b
 * @format: a standard printf() format string, but notice
Packit ae235b
 *     [string precision pitfalls][string-precision]
Packit ae235b
 * @args: the list of parameters to insert into the format string
Packit ae235b
 *
Packit ae235b
 * Similar to the standard C vsprintf() function but safer, since it
Packit ae235b
 * calculates the maximum space required and allocates memory to hold
Packit ae235b
 * the result. The returned string should be freed with g_free() when
Packit ae235b
 * no longer needed.
Packit ae235b
 *
Packit ae235b
 * See also g_vasprintf(), which offers the same functionality, but
Packit ae235b
 * additionally returns the length of the allocated string.
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated string holding the result
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_strdup_vprintf (const gchar *format,
Packit ae235b
                  va_list      args)
Packit ae235b
{
Packit ae235b
  gchar *string = NULL;
Packit ae235b
Packit ae235b
  g_vasprintf (&string, format, args);
Packit ae235b
Packit ae235b
  return string;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strdup_printf:
Packit ae235b
 * @format: a standard printf() format string, but notice
Packit ae235b
 *     [string precision pitfalls][string-precision]
Packit ae235b
 * @...: the parameters to insert into the format string
Packit ae235b
 *
Packit ae235b
 * Similar to the standard C sprintf() function but safer, since it
Packit ae235b
 * calculates the maximum space required and allocates memory to hold
Packit ae235b
 * the result. The returned string should be freed with g_free() when no
Packit ae235b
 * longer needed.
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated string holding the result
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_strdup_printf (const gchar *format,
Packit ae235b
                 ...)
Packit ae235b
{
Packit ae235b
  gchar *buffer;
Packit ae235b
  va_list args;
Packit ae235b
Packit ae235b
  va_start (args, format);
Packit ae235b
  buffer = g_strdup_vprintf (format, args);
Packit ae235b
  va_end (args);
Packit ae235b
Packit ae235b
  return buffer;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strconcat:
Packit ae235b
 * @string1: the first string to add, which must not be %NULL
Packit ae235b
 * @...: a %NULL-terminated list of strings to append to the string
Packit ae235b
 *
Packit ae235b
 * Concatenates all of the given strings into one long string. The
Packit ae235b
 * returned string should be freed with g_free() when no longer needed.
Packit ae235b
 *
Packit ae235b
 * The variable argument list must end with %NULL. If you forget the %NULL,
Packit ae235b
 * g_strconcat() will start appending random memory junk to your string.
Packit ae235b
 *
Packit ae235b
 * Note that this function is usually not the right function to use to
Packit ae235b
 * assemble a translated message from pieces, since proper translation
Packit ae235b
 * often requires the pieces to be reordered.
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated string containing all the string arguments
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_strconcat (const gchar *string1, ...)
Packit ae235b
{
Packit ae235b
  gsize   l;
Packit ae235b
  va_list args;
Packit ae235b
  gchar   *s;
Packit ae235b
  gchar   *concat;
Packit ae235b
  gchar   *ptr;
Packit ae235b
Packit ae235b
  if (!string1)
Packit ae235b
    return NULL;
Packit ae235b
Packit ae235b
  l = 1 + strlen (string1);
Packit ae235b
  va_start (args, string1);
Packit ae235b
  s = va_arg (args, gchar*);
Packit ae235b
  while (s)
Packit ae235b
    {
Packit ae235b
      l += strlen (s);
Packit ae235b
      s = va_arg (args, gchar*);
Packit ae235b
    }
Packit ae235b
  va_end (args);
Packit ae235b
Packit ae235b
  concat = g_new (gchar, l);
Packit ae235b
  ptr = concat;
Packit ae235b
Packit ae235b
  ptr = g_stpcpy (ptr, string1);
Packit ae235b
  va_start (args, string1);
Packit ae235b
  s = va_arg (args, gchar*);
Packit ae235b
  while (s)
Packit ae235b
    {
Packit ae235b
      ptr = g_stpcpy (ptr, s);
Packit ae235b
      s = va_arg (args, gchar*);
Packit ae235b
    }
Packit ae235b
  va_end (args);
Packit ae235b
Packit ae235b
  return concat;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strtod:
Packit ae235b
 * @nptr:    the string to convert to a numeric value.
Packit ae235b
 * @endptr:  (out) (transfer none) (optional): if non-%NULL, it returns the
Packit ae235b
 *           character after the last character used in the conversion.
Packit ae235b
 *
Packit ae235b
 * Converts a string to a #gdouble value.
Packit ae235b
 * It calls the standard strtod() function to handle the conversion, but
Packit ae235b
 * if the string is not completely converted it attempts the conversion
Packit ae235b
 * again with g_ascii_strtod(), and returns the best match.
Packit ae235b
 *
Packit ae235b
 * This function should seldom be used. The normal situation when reading
Packit ae235b
 * numbers not for human consumption is to use g_ascii_strtod(). Only when
Packit ae235b
 * you know that you must expect both locale formatted and C formatted numbers
Packit ae235b
 * should you use this. Make sure that you don't pass strings such as comma
Packit ae235b
 * separated lists of values, since the commas may be interpreted as a decimal
Packit ae235b
 * point in some locales, causing unexpected results.
Packit ae235b
 *
Packit ae235b
 * Returns: the #gdouble value.
Packit ae235b
 **/
Packit ae235b
gdouble
Packit ae235b
g_strtod (const gchar *nptr,
Packit ae235b
          gchar      **endptr)
Packit ae235b
{
Packit ae235b
  gchar *fail_pos_1;
Packit ae235b
  gchar *fail_pos_2;
Packit ae235b
  gdouble val_1;
Packit ae235b
  gdouble val_2 = 0;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (nptr != NULL, 0);
Packit ae235b
Packit ae235b
  fail_pos_1 = NULL;
Packit ae235b
  fail_pos_2 = NULL;
Packit ae235b
Packit ae235b
  val_1 = strtod (nptr, &fail_pos_1);
Packit ae235b
Packit ae235b
  if (fail_pos_1 && fail_pos_1[0] != 0)
Packit ae235b
    val_2 = g_ascii_strtod (nptr, &fail_pos_2);
Packit ae235b
Packit ae235b
  if (!fail_pos_1 || fail_pos_1[0] == 0 || fail_pos_1 >= fail_pos_2)
Packit ae235b
    {
Packit ae235b
      if (endptr)
Packit ae235b
        *endptr = fail_pos_1;
Packit ae235b
      return val_1;
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      if (endptr)
Packit ae235b
        *endptr = fail_pos_2;
Packit ae235b
      return val_2;
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_strtod:
Packit ae235b
 * @nptr:    the string to convert to a numeric value.
Packit ae235b
 * @endptr:  (out) (transfer none) (optional): if non-%NULL, it returns the
Packit ae235b
 *           character after the last character used in the conversion.
Packit ae235b
 *
Packit ae235b
 * Converts a string to a #gdouble value.
Packit ae235b
 *
Packit ae235b
 * This function behaves like the standard strtod() function
Packit ae235b
 * does in the C locale. It does this without actually changing
Packit ae235b
 * the current locale, since that would not be thread-safe.
Packit ae235b
 * A limitation of the implementation is that this function
Packit ae235b
 * will still accept localized versions of infinities and NANs.
Packit ae235b
 *
Packit ae235b
 * This function is typically used when reading configuration
Packit ae235b
 * files or other non-user input that should be locale independent.
Packit ae235b
 * To handle input from the user you should normally use the
Packit ae235b
 * locale-sensitive system strtod() function.
Packit ae235b
 *
Packit ae235b
 * To convert from a #gdouble to a string in a locale-insensitive
Packit ae235b
 * way, use g_ascii_dtostr().
Packit ae235b
 *
Packit ae235b
 * If the correct value would cause overflow, plus or minus %HUGE_VAL
Packit ae235b
 * is returned (according to the sign of the value), and %ERANGE is
Packit ae235b
 * stored in %errno. If the correct value would cause underflow,
Packit ae235b
 * zero is returned and %ERANGE is stored in %errno.
Packit ae235b
 *
Packit ae235b
 * This function resets %errno before calling strtod() so that
Packit ae235b
 * you can reliably detect overflow and underflow.
Packit ae235b
 *
Packit ae235b
 * Returns: the #gdouble value.
Packit ae235b
 */
Packit ae235b
gdouble
Packit ae235b
g_ascii_strtod (const gchar *nptr,
Packit ae235b
                gchar      **endptr)
Packit ae235b
{
Packit ae235b
#ifdef USE_XLOCALE
Packit ae235b
Packit ae235b
  g_return_val_if_fail (nptr != NULL, 0);
Packit ae235b
Packit ae235b
  errno = 0;
Packit ae235b
Packit ae235b
  return strtod_l (nptr, endptr, get_C_locale ());
Packit ae235b
Packit ae235b
#else
Packit ae235b
Packit ae235b
  gchar *fail_pos;
Packit ae235b
  gdouble val;
Packit ae235b
#ifndef __BIONIC__
Packit ae235b
  struct lconv *locale_data;
Packit ae235b
#endif
Packit ae235b
  const char *decimal_point;
Packit ae235b
  gsize decimal_point_len;
Packit ae235b
  const char *p, *decimal_point_pos;
Packit ae235b
  const char *end = NULL; /* Silence gcc */
Packit ae235b
  int strtod_errno;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (nptr != NULL, 0);
Packit ae235b
Packit ae235b
  fail_pos = NULL;
Packit ae235b
Packit ae235b
#ifndef __BIONIC__
Packit ae235b
  locale_data = localeconv ();
Packit ae235b
  decimal_point = locale_data->decimal_point;
Packit ae235b
  decimal_point_len = strlen (decimal_point);
Packit ae235b
#else
Packit ae235b
  decimal_point = ".";
Packit ae235b
  decimal_point_len = 1;
Packit ae235b
#endif
Packit ae235b
Packit ae235b
  g_assert (decimal_point_len != 0);
Packit ae235b
Packit ae235b
  decimal_point_pos = NULL;
Packit ae235b
  end = NULL;
Packit ae235b
Packit ae235b
  if (decimal_point[0] != '.' ||
Packit ae235b
      decimal_point[1] != 0)
Packit ae235b
    {
Packit ae235b
      p = nptr;
Packit ae235b
      /* Skip leading space */
Packit ae235b
      while (g_ascii_isspace (*p))
Packit ae235b
        p++;
Packit ae235b
Packit ae235b
      /* Skip leading optional sign */
Packit ae235b
      if (*p == '+' || *p == '-')
Packit ae235b
        p++;
Packit ae235b
Packit ae235b
      if (p[0] == '0' &&
Packit ae235b
          (p[1] == 'x' || p[1] == 'X'))
Packit ae235b
        {
Packit ae235b
          p += 2;
Packit ae235b
          /* HEX - find the (optional) decimal point */
Packit ae235b
Packit ae235b
          while (g_ascii_isxdigit (*p))
Packit ae235b
            p++;
Packit ae235b
Packit ae235b
          if (*p == '.')
Packit ae235b
            decimal_point_pos = p++;
Packit ae235b
Packit ae235b
          while (g_ascii_isxdigit (*p))
Packit ae235b
            p++;
Packit ae235b
Packit ae235b
          if (*p == 'p' || *p == 'P')
Packit ae235b
            p++;
Packit ae235b
          if (*p == '+' || *p == '-')
Packit ae235b
            p++;
Packit ae235b
          while (g_ascii_isdigit (*p))
Packit ae235b
            p++;
Packit ae235b
Packit ae235b
          end = p;
Packit ae235b
        }
Packit ae235b
      else if (g_ascii_isdigit (*p) || *p == '.')
Packit ae235b
        {
Packit ae235b
          while (g_ascii_isdigit (*p))
Packit ae235b
            p++;
Packit ae235b
Packit ae235b
          if (*p == '.')
Packit ae235b
            decimal_point_pos = p++;
Packit ae235b
Packit ae235b
          while (g_ascii_isdigit (*p))
Packit ae235b
            p++;
Packit ae235b
Packit ae235b
          if (*p == 'e' || *p == 'E')
Packit ae235b
            p++;
Packit ae235b
          if (*p == '+' || *p == '-')
Packit ae235b
            p++;
Packit ae235b
          while (g_ascii_isdigit (*p))
Packit ae235b
            p++;
Packit ae235b
Packit ae235b
          end = p;
Packit ae235b
        }
Packit ae235b
      /* For the other cases, we need not convert the decimal point */
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (decimal_point_pos)
Packit ae235b
    {
Packit ae235b
      char *copy, *c;
Packit ae235b
Packit ae235b
      /* We need to convert the '.' to the locale specific decimal point */
Packit ae235b
      copy = g_malloc (end - nptr + 1 + decimal_point_len);
Packit ae235b
Packit ae235b
      c = copy;
Packit ae235b
      memcpy (c, nptr, decimal_point_pos - nptr);
Packit ae235b
      c += decimal_point_pos - nptr;
Packit ae235b
      memcpy (c, decimal_point, decimal_point_len);
Packit ae235b
      c += decimal_point_len;
Packit ae235b
      memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
Packit ae235b
      c += end - (decimal_point_pos + 1);
Packit ae235b
      *c = 0;
Packit ae235b
Packit ae235b
      errno = 0;
Packit ae235b
      val = strtod (copy, &fail_pos);
Packit ae235b
      strtod_errno = errno;
Packit ae235b
Packit ae235b
      if (fail_pos)
Packit ae235b
        {
Packit ae235b
          if (fail_pos - copy > decimal_point_pos - nptr)
Packit ae235b
            fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
Packit ae235b
          else
Packit ae235b
            fail_pos = (char *)nptr + (fail_pos - copy);
Packit ae235b
        }
Packit ae235b
Packit ae235b
      g_free (copy);
Packit ae235b
Packit ae235b
    }
Packit ae235b
  else if (end)
Packit ae235b
    {
Packit ae235b
      char *copy;
Packit ae235b
Packit ae235b
      copy = g_malloc (end - (char *)nptr + 1);
Packit ae235b
      memcpy (copy, nptr, end - nptr);
Packit ae235b
      *(copy + (end - (char *)nptr)) = 0;
Packit ae235b
Packit ae235b
      errno = 0;
Packit ae235b
      val = strtod (copy, &fail_pos);
Packit ae235b
      strtod_errno = errno;
Packit ae235b
Packit ae235b
      if (fail_pos)
Packit ae235b
        {
Packit ae235b
          fail_pos = (char *)nptr + (fail_pos - copy);
Packit ae235b
        }
Packit ae235b
Packit ae235b
      g_free (copy);
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      errno = 0;
Packit ae235b
      val = strtod (nptr, &fail_pos);
Packit ae235b
      strtod_errno = errno;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (endptr)
Packit ae235b
    *endptr = fail_pos;
Packit ae235b
Packit ae235b
  errno = strtod_errno;
Packit ae235b
Packit ae235b
  return val;
Packit ae235b
#endif
Packit ae235b
}
Packit ae235b
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_dtostr:
Packit ae235b
 * @buffer: A buffer to place the resulting string in
Packit ae235b
 * @buf_len: The length of the buffer.
Packit ae235b
 * @d: The #gdouble to convert
Packit ae235b
 *
Packit ae235b
 * Converts a #gdouble to a string, using the '.' as
Packit ae235b
 * decimal point.
Packit ae235b
 *
Packit ae235b
 * This function generates enough precision that converting
Packit ae235b
 * the string back using g_ascii_strtod() gives the same machine-number
Packit ae235b
 * (on machines with IEEE compatible 64bit doubles). It is
Packit ae235b
 * guaranteed that the size of the resulting string will never
Packit ae235b
 * be larger than @G_ASCII_DTOSTR_BUF_SIZE bytes, including the terminating
Packit ae235b
 * nul character, which is always added.
Packit ae235b
 *
Packit ae235b
 * Returns: The pointer to the buffer with the converted string.
Packit ae235b
 **/
Packit ae235b
gchar *
Packit ae235b
g_ascii_dtostr (gchar       *buffer,
Packit ae235b
                gint         buf_len,
Packit ae235b
                gdouble      d)
Packit ae235b
{
Packit ae235b
  return g_ascii_formatd (buffer, buf_len, "%.17g", d);
Packit ae235b
}
Packit ae235b
Packit ae235b
#pragma GCC diagnostic push
Packit ae235b
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_formatd:
Packit ae235b
 * @buffer: A buffer to place the resulting string in
Packit ae235b
 * @buf_len: The length of the buffer.
Packit ae235b
 * @format: The printf()-style format to use for the
Packit ae235b
 *          code to use for converting.
Packit ae235b
 * @d: The #gdouble to convert
Packit ae235b
 *
Packit ae235b
 * Converts a #gdouble to a string, using the '.' as
Packit ae235b
 * decimal point. To format the number you pass in
Packit ae235b
 * a printf()-style format string. Allowed conversion
Packit ae235b
 * specifiers are 'e', 'E', 'f', 'F', 'g' and 'G'.
Packit ae235b
 *
Packit ae235b
 * The returned buffer is guaranteed to be nul-terminated.
Packit ae235b
 *
Packit ae235b
 * If you just want to want to serialize the value into a
Packit ae235b
 * string, use g_ascii_dtostr().
Packit ae235b
 *
Packit ae235b
 * Returns: The pointer to the buffer with the converted string.
Packit ae235b
 */
Packit ae235b
gchar *
Packit ae235b
g_ascii_formatd (gchar       *buffer,
Packit ae235b
                 gint         buf_len,
Packit ae235b
                 const gchar *format,
Packit ae235b
                 gdouble      d)
Packit ae235b
{
Packit ae235b
#ifdef USE_XLOCALE
Packit ae235b
  locale_t old_locale;
Packit ae235b
Packit ae235b
  old_locale = uselocale (get_C_locale ());
Packit ae235b
   _g_snprintf (buffer, buf_len, format, d);
Packit ae235b
  uselocale (old_locale);
Packit ae235b
Packit ae235b
  return buffer;
Packit ae235b
#else
Packit ae235b
#ifndef __BIONIC__
Packit ae235b
  struct lconv *locale_data;
Packit ae235b
#endif
Packit ae235b
  const char *decimal_point;
Packit ae235b
  gsize decimal_point_len;
Packit ae235b
  gchar *p;
Packit ae235b
  int rest_len;
Packit ae235b
  gchar format_char;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (buffer != NULL, NULL);
Packit ae235b
  g_return_val_if_fail (format[0] == '%', NULL);
Packit ae235b
  g_return_val_if_fail (strpbrk (format + 1, "'l%") == NULL, NULL);
Packit ae235b
Packit ae235b
  format_char = format[strlen (format) - 1];
Packit ae235b
Packit ae235b
  g_return_val_if_fail (format_char == 'e' || format_char == 'E' ||
Packit ae235b
                        format_char == 'f' || format_char == 'F' ||
Packit ae235b
                        format_char == 'g' || format_char == 'G',
Packit ae235b
                        NULL);
Packit ae235b
Packit ae235b
  if (format[0] != '%')
Packit ae235b
    return NULL;
Packit ae235b
Packit ae235b
  if (strpbrk (format + 1, "'l%"))
Packit ae235b
    return NULL;
Packit ae235b
Packit ae235b
  if (!(format_char == 'e' || format_char == 'E' ||
Packit ae235b
        format_char == 'f' || format_char == 'F' ||
Packit ae235b
        format_char == 'g' || format_char == 'G'))
Packit ae235b
    return NULL;
Packit ae235b
Packit ae235b
  _g_snprintf (buffer, buf_len, format, d);
Packit ae235b
Packit ae235b
#ifndef __BIONIC__
Packit ae235b
  locale_data = localeconv ();
Packit ae235b
  decimal_point = locale_data->decimal_point;
Packit ae235b
  decimal_point_len = strlen (decimal_point);
Packit ae235b
#else
Packit ae235b
  decimal_point = ".";
Packit ae235b
  decimal_point_len = 1;
Packit ae235b
#endif
Packit ae235b
Packit ae235b
  g_assert (decimal_point_len != 0);
Packit ae235b
Packit ae235b
  if (decimal_point[0] != '.' ||
Packit ae235b
      decimal_point[1] != 0)
Packit ae235b
    {
Packit ae235b
      p = buffer;
Packit ae235b
Packit ae235b
      while (g_ascii_isspace (*p))
Packit ae235b
        p++;
Packit ae235b
Packit ae235b
      if (*p == '+' || *p == '-')
Packit ae235b
        p++;
Packit ae235b
Packit ae235b
      while (isdigit ((guchar)*p))
Packit ae235b
        p++;
Packit ae235b
Packit ae235b
      if (strncmp (p, decimal_point, decimal_point_len) == 0)
Packit ae235b
        {
Packit ae235b
          *p = '.';
Packit ae235b
          p++;
Packit ae235b
          if (decimal_point_len > 1)
Packit ae235b
            {
Packit ae235b
              rest_len = strlen (p + (decimal_point_len - 1));
Packit ae235b
              memmove (p, p + (decimal_point_len - 1), rest_len);
Packit ae235b
              p[rest_len] = 0;
Packit ae235b
            }
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return buffer;
Packit ae235b
#endif
Packit ae235b
}
Packit ae235b
#pragma GCC diagnostic pop
Packit ae235b
Packit ae235b
#define ISSPACE(c)              ((c) == ' ' || (c) == '\f' || (c) == '\n' || \
Packit ae235b
                                 (c) == '\r' || (c) == '\t' || (c) == '\v')
Packit ae235b
#define ISUPPER(c)              ((c) >= 'A' && (c) <= 'Z')
Packit ae235b
#define ISLOWER(c)              ((c) >= 'a' && (c) <= 'z')
Packit ae235b
#define ISALPHA(c)              (ISUPPER (c) || ISLOWER (c))
Packit ae235b
#define TOUPPER(c)              (ISLOWER (c) ? (c) - 'a' + 'A' : (c))
Packit ae235b
#define TOLOWER(c)              (ISUPPER (c) ? (c) - 'A' + 'a' : (c))
Packit ae235b
Packit ae235b
#ifndef USE_XLOCALE
Packit ae235b
Packit ae235b
static guint64
Packit ae235b
g_parse_long_long (const gchar  *nptr,
Packit ae235b
                   const gchar **endptr,
Packit ae235b
                   guint         base,
Packit ae235b
                   gboolean     *negative)
Packit ae235b
{
Packit ae235b
  /* this code is based on on the strtol(3) code from GNU libc released under
Packit ae235b
   * the GNU Lesser General Public License.
Packit ae235b
   *
Packit ae235b
   * Copyright (C) 1991,92,94,95,96,97,98,99,2000,01,02
Packit ae235b
   *        Free Software Foundation, Inc.
Packit ae235b
   */
Packit ae235b
  gboolean overflow;
Packit ae235b
  guint64 cutoff;
Packit ae235b
  guint64 cutlim;
Packit ae235b
  guint64 ui64;
Packit ae235b
  const gchar *s, *save;
Packit ae235b
  guchar c;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (nptr != NULL, 0);
Packit ae235b
Packit ae235b
  *negative = FALSE;
Packit ae235b
  if (base == 1 || base > 36)
Packit ae235b
    {
Packit ae235b
      errno = EINVAL;
Packit ae235b
      if (endptr)
Packit ae235b
        *endptr = nptr;
Packit ae235b
      return 0;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  save = s = nptr;
Packit ae235b
Packit ae235b
  /* Skip white space.  */
Packit ae235b
  while (ISSPACE (*s))
Packit ae235b
    ++s;
Packit ae235b
Packit ae235b
  if (G_UNLIKELY (!*s))
Packit ae235b
    goto noconv;
Packit ae235b
Packit ae235b
  /* Check for a sign.  */
Packit ae235b
  if (*s == '-')
Packit ae235b
    {
Packit ae235b
      *negative = TRUE;
Packit ae235b
      ++s;
Packit ae235b
    }
Packit ae235b
  else if (*s == '+')
Packit ae235b
    ++s;
Packit ae235b
Packit ae235b
  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
Packit ae235b
  if (*s == '0')
Packit ae235b
    {
Packit ae235b
      if ((base == 0 || base == 16) && TOUPPER (s[1]) == 'X')
Packit ae235b
        {
Packit ae235b
          s += 2;
Packit ae235b
          base = 16;
Packit ae235b
        }
Packit ae235b
      else if (base == 0)
Packit ae235b
        base = 8;
Packit ae235b
    }
Packit ae235b
  else if (base == 0)
Packit ae235b
    base = 10;
Packit ae235b
Packit ae235b
  /* Save the pointer so we can check later if anything happened.  */
Packit ae235b
  save = s;
Packit ae235b
  cutoff = G_MAXUINT64 / base;
Packit ae235b
  cutlim = G_MAXUINT64 % base;
Packit ae235b
Packit ae235b
  overflow = FALSE;
Packit ae235b
  ui64 = 0;
Packit ae235b
  c = *s;
Packit ae235b
  for (; c; c = *++s)
Packit ae235b
    {
Packit ae235b
      if (c >= '0' && c <= '9')
Packit ae235b
        c -= '0';
Packit ae235b
      else if (ISALPHA (c))
Packit ae235b
        c = TOUPPER (c) - 'A' + 10;
Packit ae235b
      else
Packit ae235b
        break;
Packit ae235b
      if (c >= base)
Packit ae235b
        break;
Packit ae235b
      /* Check for overflow.  */
Packit ae235b
      if (ui64 > cutoff || (ui64 == cutoff && c > cutlim))
Packit ae235b
        overflow = TRUE;
Packit ae235b
      else
Packit ae235b
        {
Packit ae235b
          ui64 *= base;
Packit ae235b
          ui64 += c;
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
Packit ae235b
  /* Check if anything actually happened.  */
Packit ae235b
  if (s == save)
Packit ae235b
    goto noconv;
Packit ae235b
Packit ae235b
  /* Store in ENDPTR the address of one character
Packit ae235b
     past the last character we converted.  */
Packit ae235b
  if (endptr)
Packit ae235b
    *endptr = s;
Packit ae235b
Packit ae235b
  if (G_UNLIKELY (overflow))
Packit ae235b
    {
Packit ae235b
      errno = ERANGE;
Packit ae235b
      return G_MAXUINT64;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return ui64;
Packit ae235b
Packit ae235b
 noconv:
Packit ae235b
  /* We must handle a special case here: the base is 0 or 16 and the
Packit ae235b
     first two characters are '0' and 'x', but the rest are no
Packit ae235b
     hexadecimal digits.  This is no error case.  We return 0 and
Packit ae235b
     ENDPTR points to the `x`.  */
Packit ae235b
  if (endptr)
Packit ae235b
    {
Packit ae235b
      if (save - nptr >= 2 && TOUPPER (save[-1]) == 'X'
Packit ae235b
          && save[-2] == '0')
Packit ae235b
        *endptr = &save[-1];
Packit ae235b
      else
Packit ae235b
        /*  There was no number to convert.  */
Packit ae235b
        *endptr = nptr;
Packit ae235b
    }
Packit ae235b
  return 0;
Packit ae235b
}
Packit ae235b
#endif /* !USE_XLOCALE */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_strtoull:
Packit ae235b
 * @nptr:    the string to convert to a numeric value.
Packit ae235b
 * @endptr:  (out) (transfer none) (optional): if non-%NULL, it returns the
Packit ae235b
 *           character after the last character used in the conversion.
Packit ae235b
 * @base:    to be used for the conversion, 2..36 or 0
Packit ae235b
 *
Packit ae235b
 * Converts a string to a #guint64 value.
Packit ae235b
 * This function behaves like the standard strtoull() function
Packit ae235b
 * does in the C locale. It does this without actually
Packit ae235b
 * changing the current locale, since that would not be
Packit ae235b
 * thread-safe.
Packit ae235b
 *
Packit ae235b
 * This function is typically used when reading configuration
Packit ae235b
 * files or other non-user input that should be locale independent.
Packit ae235b
 * To handle input from the user you should normally use the
Packit ae235b
 * locale-sensitive system strtoull() function.
Packit ae235b
 *
Packit ae235b
 * If the correct value would cause overflow, %G_MAXUINT64
Packit ae235b
 * is returned, and `ERANGE` is stored in `errno`.
Packit ae235b
 * If the base is outside the valid range, zero is returned, and
Packit ae235b
 * `EINVAL` is stored in `errno`.
Packit ae235b
 * If the string conversion fails, zero is returned, and @endptr returns
Packit ae235b
 * @nptr (if @endptr is non-%NULL).
Packit ae235b
 *
Packit ae235b
 * Returns: the #guint64 value or zero on error.
Packit ae235b
 *
Packit ae235b
 * Since: 2.2
Packit ae235b
 */
Packit ae235b
guint64
Packit ae235b
g_ascii_strtoull (const gchar *nptr,
Packit ae235b
                  gchar      **endptr,
Packit ae235b
                  guint        base)
Packit ae235b
{
Packit ae235b
#ifdef USE_XLOCALE
Packit ae235b
  return strtoull_l (nptr, endptr, base, get_C_locale ());
Packit ae235b
#else
Packit ae235b
  gboolean negative;
Packit ae235b
  guint64 result;
Packit ae235b
Packit ae235b
  result = g_parse_long_long (nptr, (const gchar **) endptr, base, &negative);
Packit ae235b
Packit ae235b
  /* Return the result of the appropriate sign.  */
Packit ae235b
  return negative ? -result : result;
Packit ae235b
#endif
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_strtoll:
Packit ae235b
 * @nptr:    the string to convert to a numeric value.
Packit ae235b
 * @endptr:  (out) (transfer none) (optional): if non-%NULL, it returns the
Packit ae235b
 *           character after the last character used in the conversion.
Packit ae235b
 * @base:    to be used for the conversion, 2..36 or 0
Packit ae235b
 *
Packit ae235b
 * Converts a string to a #gint64 value.
Packit ae235b
 * This function behaves like the standard strtoll() function
Packit ae235b
 * does in the C locale. It does this without actually
Packit ae235b
 * changing the current locale, since that would not be
Packit ae235b
 * thread-safe.
Packit ae235b
 *
Packit ae235b
 * This function is typically used when reading configuration
Packit ae235b
 * files or other non-user input that should be locale independent.
Packit ae235b
 * To handle input from the user you should normally use the
Packit ae235b
 * locale-sensitive system strtoll() function.
Packit ae235b
 *
Packit ae235b
 * If the correct value would cause overflow, %G_MAXINT64 or %G_MININT64
Packit ae235b
 * is returned, and `ERANGE` is stored in `errno`.
Packit ae235b
 * If the base is outside the valid range, zero is returned, and
Packit ae235b
 * `EINVAL` is stored in `errno`. If the
Packit ae235b
 * string conversion fails, zero is returned, and @endptr returns @nptr
Packit ae235b
 * (if @endptr is non-%NULL).
Packit ae235b
 *
Packit ae235b
 * Returns: the #gint64 value or zero on error.
Packit ae235b
 *
Packit ae235b
 * Since: 2.12
Packit ae235b
 */
Packit ae235b
gint64
Packit ae235b
g_ascii_strtoll (const gchar *nptr,
Packit ae235b
                 gchar      **endptr,
Packit ae235b
                 guint        base)
Packit ae235b
{
Packit ae235b
#ifdef USE_XLOCALE
Packit ae235b
  return strtoll_l (nptr, endptr, base, get_C_locale ());
Packit ae235b
#else
Packit ae235b
  gboolean negative;
Packit ae235b
  guint64 result;
Packit ae235b
Packit ae235b
  result = g_parse_long_long (nptr, (const gchar **) endptr, base, &negative);
Packit ae235b
Packit ae235b
  if (negative && result > (guint64) G_MININT64)
Packit ae235b
    {
Packit ae235b
      errno = ERANGE;
Packit ae235b
      return G_MININT64;
Packit ae235b
    }
Packit ae235b
  else if (!negative && result > (guint64) G_MAXINT64)
Packit ae235b
    {
Packit ae235b
      errno = ERANGE;
Packit ae235b
      return G_MAXINT64;
Packit ae235b
    }
Packit ae235b
  else if (negative)
Packit ae235b
    return - (gint64) result;
Packit ae235b
  else
Packit ae235b
    return (gint64) result;
Packit ae235b
#endif
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strerror:
Packit ae235b
 * @errnum: the system error number. See the standard C %errno
Packit ae235b
 *     documentation
Packit ae235b
 *
Packit ae235b
 * Returns a string corresponding to the given error code, e.g. "no
Packit ae235b
 * such process". Unlike strerror(), this always returns a string in
Packit ae235b
 * UTF-8 encoding, and the pointer is guaranteed to remain valid for
Packit ae235b
 * the lifetime of the process.
Packit ae235b
 *
Packit ae235b
 * Note that the string may be translated according to the current locale.
Packit ae235b
 *
Packit ae235b
 * The value of %errno will not be changed by this function. However, it may
Packit ae235b
 * be changed by intermediate function calls, so you should save its value
Packit ae235b
 * as soon as the call returns:
Packit ae235b
 * |[
Packit ae235b
 *   int saved_errno;
Packit ae235b
 *
Packit ae235b
 *   ret = read (blah);
Packit ae235b
 *   saved_errno = errno;
Packit ae235b
 *
Packit ae235b
 *   g_strerror (saved_errno);
Packit ae235b
 * ]|
Packit ae235b
 *
Packit ae235b
 * Returns: a UTF-8 string describing the error code. If the error code
Packit ae235b
 *     is unknown, it returns a string like "unknown error ()".
Packit ae235b
 */
Packit ae235b
const gchar *
Packit ae235b
g_strerror (gint errnum)
Packit ae235b
{
Packit ae235b
  static GHashTable *errors;
Packit ae235b
  G_LOCK_DEFINE_STATIC (errors);
Packit ae235b
  const gchar *msg;
Packit ae235b
  gint saved_errno = errno;
Packit ae235b
Packit ae235b
  G_LOCK (errors);
Packit ae235b
  if (errors)
Packit ae235b
    msg = g_hash_table_lookup (errors, GINT_TO_POINTER (errnum));
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      errors = g_hash_table_new (NULL, NULL);
Packit ae235b
      msg = NULL;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (!msg)
Packit ae235b
    {
Packit ae235b
      gchar buf[1024];
Packit ae235b
      GError *error = NULL;
Packit ae235b
Packit ae235b
#if defined(G_OS_WIN32)
Packit ae235b
      strerror_s (buf, sizeof (buf), errnum);
Packit ae235b
      msg = buf;
Packit ae235b
#elif defined(HAVE_STRERROR_R)
Packit ae235b
      /* Match the condition in strerror_r(3) for glibc */
Packit ae235b
#  if defined(STRERROR_R_CHAR_P)
Packit ae235b
      msg = strerror_r (errnum, buf, sizeof (buf));
Packit ae235b
#  else
Packit ae235b
      (void) strerror_r (errnum, buf, sizeof (buf));
Packit ae235b
      msg = buf;
Packit ae235b
#  endif /* HAVE_STRERROR_R */
Packit ae235b
#else
Packit ae235b
      g_strlcpy (buf, strerror (errnum), sizeof (buf));
Packit ae235b
      msg = buf;
Packit ae235b
#endif
Packit ae235b
      if (!g_get_charset (NULL))
Packit ae235b
        {
Packit ae235b
          msg = g_locale_to_utf8 (msg, -1, NULL, NULL, &error);
Packit ae235b
          if (error)
Packit ae235b
            g_print ("%s\n", error->message);
Packit ae235b
        }
Packit ae235b
      else if (msg == (const gchar *)buf)
Packit ae235b
        msg = g_strdup (buf);
Packit ae235b
Packit ae235b
      g_hash_table_insert (errors, GINT_TO_POINTER (errnum), (char *) msg);
Packit ae235b
    }
Packit ae235b
  G_UNLOCK (errors);
Packit ae235b
Packit ae235b
  errno = saved_errno;
Packit ae235b
  return msg;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strsignal:
Packit ae235b
 * @signum: the signal number. See the `signal` documentation
Packit ae235b
 *
Packit ae235b
 * Returns a string describing the given signal, e.g. "Segmentation fault".
Packit ae235b
 * You should use this function in preference to strsignal(), because it
Packit ae235b
 * returns a string in UTF-8 encoding, and since not all platforms support
Packit ae235b
 * the strsignal() function.
Packit ae235b
 *
Packit ae235b
 * Returns: a UTF-8 string describing the signal. If the signal is unknown,
Packit ae235b
 *     it returns "unknown signal (<signum>)".
Packit ae235b
 */
Packit ae235b
const gchar *
Packit ae235b
g_strsignal (gint signum)
Packit ae235b
{
Packit ae235b
  gchar *msg;
Packit ae235b
  gchar *tofree;
Packit ae235b
  const gchar *ret;
Packit ae235b
Packit ae235b
  msg = tofree = NULL;
Packit ae235b
Packit ae235b
#ifdef HAVE_STRSIGNAL
Packit ae235b
  msg = strsignal (signum);
Packit ae235b
  if (!g_get_charset (NULL))
Packit ae235b
    msg = tofree = g_locale_to_utf8 (msg, -1, NULL, NULL, NULL);
Packit ae235b
#endif
Packit ae235b
Packit ae235b
  if (!msg)
Packit ae235b
    msg = tofree = g_strdup_printf ("unknown signal (%d)", signum);
Packit ae235b
  ret = g_intern_string (msg);
Packit ae235b
  g_free (tofree);
Packit ae235b
Packit ae235b
  return ret;
Packit ae235b
}
Packit ae235b
Packit ae235b
/* Functions g_strlcpy and g_strlcat were originally developed by
Packit ae235b
 * Todd C. Miller <Todd.Miller@courtesan.com> to simplify writing secure code.
Packit ae235b
 * See http://www.openbsd.org/cgi-bin/man.cgi?query=strlcpy 
Packit ae235b
 * for more information.
Packit ae235b
 */
Packit ae235b
Packit ae235b
#ifdef HAVE_STRLCPY
Packit ae235b
/* Use the native ones, if available; they might be implemented in assembly */
Packit ae235b
gsize
Packit ae235b
g_strlcpy (gchar       *dest,
Packit ae235b
           const gchar *src,
Packit ae235b
           gsize        dest_size)
Packit ae235b
{
Packit ae235b
  g_return_val_if_fail (dest != NULL, 0);
Packit ae235b
  g_return_val_if_fail (src  != NULL, 0);
Packit ae235b
Packit ae235b
  return strlcpy (dest, src, dest_size);
Packit ae235b
}
Packit ae235b
Packit ae235b
gsize
Packit ae235b
g_strlcat (gchar       *dest,
Packit ae235b
           const gchar *src,
Packit ae235b
           gsize        dest_size)
Packit ae235b
{
Packit ae235b
  g_return_val_if_fail (dest != NULL, 0);
Packit ae235b
  g_return_val_if_fail (src  != NULL, 0);
Packit ae235b
Packit ae235b
  return strlcat (dest, src, dest_size);
Packit ae235b
}
Packit ae235b
Packit ae235b
#else /* ! HAVE_STRLCPY */
Packit ae235b
/**
Packit ae235b
 * g_strlcpy:
Packit ae235b
 * @dest: destination buffer
Packit ae235b
 * @src: source buffer
Packit ae235b
 * @dest_size: length of @dest in bytes
Packit ae235b
 *
Packit ae235b
 * Portability wrapper that calls strlcpy() on systems which have it,
Packit ae235b
 * and emulates strlcpy() otherwise. Copies @src to @dest; @dest is
Packit ae235b
 * guaranteed to be nul-terminated; @src must be nul-terminated;
Packit ae235b
 * @dest_size is the buffer size, not the number of bytes to copy.
Packit ae235b
 *
Packit ae235b
 * At most @dest_size - 1 characters will be copied. Always nul-terminates
Packit ae235b
 * (unless @dest_size is 0). This function does not allocate memory. Unlike
Packit ae235b
 * strncpy(), this function doesn't pad @dest (so it's often faster). It
Packit ae235b
 * returns the size of the attempted result, strlen (src), so if
Packit ae235b
 * @retval >= @dest_size, truncation occurred.
Packit ae235b
 *
Packit ae235b
 * Caveat: strlcpy() is supposedly more secure than strcpy() or strncpy(),
Packit ae235b
 * but if you really want to avoid screwups, g_strdup() is an even better
Packit ae235b
 * idea.
Packit ae235b
 *
Packit ae235b
 * Returns: length of @src
Packit ae235b
 */
Packit ae235b
gsize
Packit ae235b
g_strlcpy (gchar       *dest,
Packit ae235b
           const gchar *src,
Packit ae235b
           gsize        dest_size)
Packit ae235b
{
Packit ae235b
  gchar *d = dest;
Packit ae235b
  const gchar *s = src;
Packit ae235b
  gsize n = dest_size;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (dest != NULL, 0);
Packit ae235b
  g_return_val_if_fail (src  != NULL, 0);
Packit ae235b
Packit ae235b
  /* Copy as many bytes as will fit */
Packit ae235b
  if (n != 0 && --n != 0)
Packit ae235b
    do
Packit ae235b
      {
Packit ae235b
        gchar c = *s++;
Packit ae235b
Packit ae235b
        *d++ = c;
Packit ae235b
        if (c == 0)
Packit ae235b
          break;
Packit ae235b
      }
Packit ae235b
    while (--n != 0);
Packit ae235b
Packit ae235b
  /* If not enough room in dest, add NUL and traverse rest of src */
Packit ae235b
  if (n == 0)
Packit ae235b
    {
Packit ae235b
      if (dest_size != 0)
Packit ae235b
        *d = 0;
Packit ae235b
      while (*s++)
Packit ae235b
        ;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return s - src - 1;  /* count does not include NUL */
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strlcat:
Packit ae235b
 * @dest: destination buffer, already containing one nul-terminated string
Packit ae235b
 * @src: source buffer
Packit ae235b
 * @dest_size: length of @dest buffer in bytes (not length of existing string
Packit ae235b
 *     inside @dest)
Packit ae235b
 *
Packit ae235b
 * Portability wrapper that calls strlcat() on systems which have it,
Packit ae235b
 * and emulates it otherwise. Appends nul-terminated @src string to @dest,
Packit ae235b
 * guaranteeing nul-termination for @dest. The total size of @dest won't
Packit ae235b
 * exceed @dest_size.
Packit ae235b
 *
Packit ae235b
 * At most @dest_size - 1 characters will be copied. Unlike strncat(),
Packit ae235b
 * @dest_size is the full size of dest, not the space left over. This
Packit ae235b
 * function does not allocate memory. It always nul-terminates (unless
Packit ae235b
 * @dest_size == 0 or there were no nul characters in the @dest_size
Packit ae235b
 * characters of dest to start with).
Packit ae235b
 *
Packit ae235b
 * Caveat: this is supposedly a more secure alternative to strcat() or
Packit ae235b
 * strncat(), but for real security g_strconcat() is harder to mess up.
Packit ae235b
 *
Packit ae235b
 * Returns: size of attempted result, which is MIN (dest_size, strlen
Packit ae235b
 *     (original dest)) + strlen (src), so if retval >= dest_size,
Packit ae235b
 *     truncation occurred.
Packit ae235b
 */
Packit ae235b
gsize
Packit ae235b
g_strlcat (gchar       *dest,
Packit ae235b
           const gchar *src,
Packit ae235b
           gsize        dest_size)
Packit ae235b
{
Packit ae235b
  gchar *d = dest;
Packit ae235b
  const gchar *s = src;
Packit ae235b
  gsize bytes_left = dest_size;
Packit ae235b
  gsize dlength;  /* Logically, MIN (strlen (d), dest_size) */
Packit ae235b
Packit ae235b
  g_return_val_if_fail (dest != NULL, 0);
Packit ae235b
  g_return_val_if_fail (src  != NULL, 0);
Packit ae235b
Packit ae235b
  /* Find the end of dst and adjust bytes left but don't go past end */
Packit ae235b
  while (*d != 0 && bytes_left-- != 0)
Packit ae235b
    d++;
Packit ae235b
  dlength = d - dest;
Packit ae235b
  bytes_left = dest_size - dlength;
Packit ae235b
Packit ae235b
  if (bytes_left == 0)
Packit ae235b
    return dlength + strlen (s);
Packit ae235b
Packit ae235b
  while (*s != 0)
Packit ae235b
    {
Packit ae235b
      if (bytes_left != 1)
Packit ae235b
        {
Packit ae235b
          *d++ = *s;
Packit ae235b
          bytes_left--;
Packit ae235b
        }
Packit ae235b
      s++;
Packit ae235b
    }
Packit ae235b
  *d = 0;
Packit ae235b
Packit ae235b
  return dlength + (s - src);  /* count does not include NUL */
Packit ae235b
}
Packit ae235b
#endif /* ! HAVE_STRLCPY */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_strdown:
Packit ae235b
 * @str: a string
Packit ae235b
 * @len: length of @str in bytes, or -1 if @str is nul-terminated
Packit ae235b
 *
Packit ae235b
 * Converts all upper case ASCII letters to lower case ASCII letters.
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated string, with all the upper case
Packit ae235b
 *     characters in @str converted to lower case, with semantics that
Packit ae235b
 *     exactly match g_ascii_tolower(). (Note that this is unlike the
Packit ae235b
 *     old g_strdown(), which modified the string in place.)
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_ascii_strdown (const gchar *str,
Packit ae235b
                 gssize       len)
Packit ae235b
{
Packit ae235b
  gchar *result, *s;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (str != NULL, NULL);
Packit ae235b
Packit ae235b
  if (len < 0)
Packit ae235b
    len = (gssize) strlen (str);
Packit ae235b
Packit ae235b
  result = g_strndup (str, (gsize) len);
Packit ae235b
  for (s = result; *s; s++)
Packit ae235b
    *s = g_ascii_tolower (*s);
Packit ae235b
Packit ae235b
  return result;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_strup:
Packit ae235b
 * @str: a string
Packit ae235b
 * @len: length of @str in bytes, or -1 if @str is nul-terminated
Packit ae235b
 *
Packit ae235b
 * Converts all lower case ASCII letters to upper case ASCII letters.
Packit ae235b
 *
Packit ae235b
 * Returns: a newly allocated string, with all the lower case
Packit ae235b
 *     characters in @str converted to upper case, with semantics that
Packit ae235b
 *     exactly match g_ascii_toupper(). (Note that this is unlike the
Packit ae235b
 *     old g_strup(), which modified the string in place.)
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_ascii_strup (const gchar *str,
Packit ae235b
               gssize       len)
Packit ae235b
{
Packit ae235b
  gchar *result, *s;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (str != NULL, NULL);
Packit ae235b
Packit ae235b
  if (len < 0)
Packit ae235b
    len = (gssize) strlen (str);
Packit ae235b
Packit ae235b
  result = g_strndup (str, (gsize) len);
Packit ae235b
  for (s = result; *s; s++)
Packit ae235b
    *s = g_ascii_toupper (*s);
Packit ae235b
Packit ae235b
  return result;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_str_is_ascii:
Packit ae235b
 * @str: a string
Packit ae235b
 *
Packit ae235b
 * Determines if a string is pure ASCII. A string is pure ASCII if it
Packit ae235b
 * contains no bytes with the high bit set.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @str is ASCII
Packit ae235b
 *
Packit ae235b
 * Since: 2.40
Packit ae235b
 */
Packit ae235b
gboolean
Packit ae235b
g_str_is_ascii (const gchar *str)
Packit ae235b
{
Packit ae235b
  gint i;
Packit ae235b
Packit ae235b
  for (i = 0; str[i]; i++)
Packit ae235b
    if (str[i] & 0x80)
Packit ae235b
      return FALSE;
Packit ae235b
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strdown:
Packit ae235b
 * @string: the string to convert.
Packit ae235b
 *
Packit ae235b
 * Converts a string to lower case.
Packit ae235b
 *
Packit ae235b
 * Returns: the string
Packit ae235b
 *
Packit ae235b
 * Deprecated:2.2: This function is totally broken for the reasons discussed
Packit ae235b
 * in the g_strncasecmp() docs - use g_ascii_strdown() or g_utf8_strdown()
Packit ae235b
 * instead.
Packit ae235b
 **/
Packit ae235b
gchar*
Packit ae235b
g_strdown (gchar *string)
Packit ae235b
{
Packit ae235b
  guchar *s;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (string != NULL, NULL);
Packit ae235b
Packit ae235b
  s = (guchar *) string;
Packit ae235b
Packit ae235b
  while (*s)
Packit ae235b
    {
Packit ae235b
      if (isupper (*s))
Packit ae235b
        *s = tolower (*s);
Packit ae235b
      s++;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return (gchar *) string;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strup:
Packit ae235b
 * @string: the string to convert
Packit ae235b
 *
Packit ae235b
 * Converts a string to upper case.
Packit ae235b
 *
Packit ae235b
 * Returns: the string
Packit ae235b
 *
Packit ae235b
 * Deprecated:2.2: This function is totally broken for the reasons
Packit ae235b
 *     discussed in the g_strncasecmp() docs - use g_ascii_strup()
Packit ae235b
 *     or g_utf8_strup() instead.
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_strup (gchar *string)
Packit ae235b
{
Packit ae235b
  guchar *s;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (string != NULL, NULL);
Packit ae235b
Packit ae235b
  s = (guchar *) string;
Packit ae235b
Packit ae235b
  while (*s)
Packit ae235b
    {
Packit ae235b
      if (islower (*s))
Packit ae235b
        *s = toupper (*s);
Packit ae235b
      s++;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return (gchar *) string;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strreverse:
Packit ae235b
 * @string: the string to reverse
Packit ae235b
 *
Packit ae235b
 * Reverses all of the bytes in a string. For example,
Packit ae235b
 * `g_strreverse ("abcdef")` will result in "fedcba".
Packit ae235b
 *
Packit ae235b
 * Note that g_strreverse() doesn't work on UTF-8 strings
Packit ae235b
 * containing multibyte characters. For that purpose, use
Packit ae235b
 * g_utf8_strreverse().
Packit ae235b
 *
Packit ae235b
 * Returns: the same pointer passed in as @string
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_strreverse (gchar *string)
Packit ae235b
{
Packit ae235b
  g_return_val_if_fail (string != NULL, NULL);
Packit ae235b
Packit ae235b
  if (*string)
Packit ae235b
    {
Packit ae235b
      gchar *h, *t;
Packit ae235b
Packit ae235b
      h = string;
Packit ae235b
      t = string + strlen (string) - 1;
Packit ae235b
Packit ae235b
      while (h < t)
Packit ae235b
        {
Packit ae235b
          gchar c;
Packit ae235b
Packit ae235b
          c = *h;
Packit ae235b
          *h = *t;
Packit ae235b
          h++;
Packit ae235b
          *t = c;
Packit ae235b
          t--;
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return string;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_tolower:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Convert a character to ASCII lower case.
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library tolower() function, this only
Packit ae235b
 * recognizes standard ASCII letters and ignores the locale, returning
Packit ae235b
 * all non-ASCII characters unchanged, even if they are lower case
Packit ae235b
 * letters in a particular character set. Also unlike the standard
Packit ae235b
 * library function, this takes and returns a char, not an int, so
Packit ae235b
 * don't call it on %EOF but no need to worry about casting to #guchar
Packit ae235b
 * before passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: the result of converting @c to lower case. If @c is
Packit ae235b
 *     not an ASCII upper case letter, @c is returned unchanged.
Packit ae235b
 */
Packit ae235b
gchar
Packit ae235b
g_ascii_tolower (gchar c)
Packit ae235b
{
Packit ae235b
  return g_ascii_isupper (c) ? c - 'A' + 'a' : c;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_toupper:
Packit ae235b
 * @c: any character
Packit ae235b
 *
Packit ae235b
 * Convert a character to ASCII upper case.
Packit ae235b
 *
Packit ae235b
 * Unlike the standard C library toupper() function, this only
Packit ae235b
 * recognizes standard ASCII letters and ignores the locale, returning
Packit ae235b
 * all non-ASCII characters unchanged, even if they are upper case
Packit ae235b
 * letters in a particular character set. Also unlike the standard
Packit ae235b
 * library function, this takes and returns a char, not an int, so
Packit ae235b
 * don't call it on %EOF but no need to worry about casting to #guchar
Packit ae235b
 * before passing a possibly non-ASCII character in.
Packit ae235b
 *
Packit ae235b
 * Returns: the result of converting @c to upper case. If @c is not
Packit ae235b
 *    an ASCII lower case letter, @c is returned unchanged.
Packit ae235b
 */
Packit ae235b
gchar
Packit ae235b
g_ascii_toupper (gchar c)
Packit ae235b
{
Packit ae235b
  return g_ascii_islower (c) ? c - 'a' + 'A' : c;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_digit_value:
Packit ae235b
 * @c: an ASCII character
Packit ae235b
 *
Packit ae235b
 * Determines the numeric value of a character as a decimal digit.
Packit ae235b
 * Differs from g_unichar_digit_value() because it takes a char, so
Packit ae235b
 * there's no worry about sign extension if characters are signed.
Packit ae235b
 *
Packit ae235b
 * Returns: If @c is a decimal digit (according to g_ascii_isdigit()),
Packit ae235b
 *    its numeric value. Otherwise, -1.
Packit ae235b
 */
Packit ae235b
int
Packit ae235b
g_ascii_digit_value (gchar c)
Packit ae235b
{
Packit ae235b
  if (g_ascii_isdigit (c))
Packit ae235b
    return c - '0';
Packit ae235b
  return -1;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_xdigit_value:
Packit ae235b
 * @c: an ASCII character.
Packit ae235b
 *
Packit ae235b
 * Determines the numeric value of a character as a hexidecimal
Packit ae235b
 * digit. Differs from g_unichar_xdigit_value() because it takes
Packit ae235b
 * a char, so there's no worry about sign extension if characters
Packit ae235b
 * are signed.
Packit ae235b
 *
Packit ae235b
 * Returns: If @c is a hex digit (according to g_ascii_isxdigit()),
Packit ae235b
 *     its numeric value. Otherwise, -1.
Packit ae235b
 */
Packit ae235b
int
Packit ae235b
g_ascii_xdigit_value (gchar c)
Packit ae235b
{
Packit ae235b
  if (c >= 'A' && c <= 'F')
Packit ae235b
    return c - 'A' + 10;
Packit ae235b
  if (c >= 'a' && c <= 'f')
Packit ae235b
    return c - 'a' + 10;
Packit ae235b
  return g_ascii_digit_value (c);
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_strcasecmp:
Packit ae235b
 * @s1: string to compare with @s2
Packit ae235b
 * @s2: string to compare with @s1
Packit ae235b
 *
Packit ae235b
 * Compare two strings, ignoring the case of ASCII characters.
Packit ae235b
 *
Packit ae235b
 * Unlike the BSD strcasecmp() function, this only recognizes standard
Packit ae235b
 * ASCII letters and ignores the locale, treating all non-ASCII
Packit ae235b
 * bytes as if they are not letters.
Packit ae235b
 *
Packit ae235b
 * This function should be used only on strings that are known to be
Packit ae235b
 * in encodings where the bytes corresponding to ASCII letters always
Packit ae235b
 * represent themselves. This includes UTF-8 and the ISO-8859-*
Packit ae235b
 * charsets, but not for instance double-byte encodings like the
Packit ae235b
 * Windows Codepage 932, where the trailing bytes of double-byte
Packit ae235b
 * characters include all ASCII letters. If you compare two CP932
Packit ae235b
 * strings using this function, you will get false matches.
Packit ae235b
 *
Packit ae235b
 * Both @s1 and @s2 must be non-%NULL.
Packit ae235b
 *
Packit ae235b
 * Returns: 0 if the strings match, a negative value if @s1 < @s2,
Packit ae235b
 *     or a positive value if @s1 > @s2.
Packit ae235b
 */
Packit ae235b
gint
Packit ae235b
g_ascii_strcasecmp (const gchar *s1,
Packit ae235b
                    const gchar *s2)
Packit ae235b
{
Packit ae235b
  gint c1, c2;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (s1 != NULL, 0);
Packit ae235b
  g_return_val_if_fail (s2 != NULL, 0);
Packit ae235b
Packit ae235b
  while (*s1 && *s2)
Packit ae235b
    {
Packit ae235b
      c1 = (gint)(guchar) TOLOWER (*s1);
Packit ae235b
      c2 = (gint)(guchar) TOLOWER (*s2);
Packit ae235b
      if (c1 != c2)
Packit ae235b
        return (c1 - c2);
Packit ae235b
      s1++; s2++;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_strncasecmp:
Packit ae235b
 * @s1: string to compare with @s2
Packit ae235b
 * @s2: string to compare with @s1
Packit ae235b
 * @n: number of characters to compare
Packit ae235b
 *
Packit ae235b
 * Compare @s1 and @s2, ignoring the case of ASCII characters and any
Packit ae235b
 * characters after the first @n in each string.
Packit ae235b
 *
Packit ae235b
 * Unlike the BSD strcasecmp() function, this only recognizes standard
Packit ae235b
 * ASCII letters and ignores the locale, treating all non-ASCII
Packit ae235b
 * characters as if they are not letters.
Packit ae235b
 *
Packit ae235b
 * The same warning as in g_ascii_strcasecmp() applies: Use this
Packit ae235b
 * function only on strings known to be in encodings where bytes
Packit ae235b
 * corresponding to ASCII letters always represent themselves.
Packit ae235b
 *
Packit ae235b
 * Returns: 0 if the strings match, a negative value if @s1 < @s2,
Packit ae235b
 *     or a positive value if @s1 > @s2.
Packit ae235b
 */
Packit ae235b
gint
Packit ae235b
g_ascii_strncasecmp (const gchar *s1,
Packit ae235b
                     const gchar *s2,
Packit ae235b
                     gsize        n)
Packit ae235b
{
Packit ae235b
  gint c1, c2;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (s1 != NULL, 0);
Packit ae235b
  g_return_val_if_fail (s2 != NULL, 0);
Packit ae235b
Packit ae235b
  while (n && *s1 && *s2)
Packit ae235b
    {
Packit ae235b
      n -= 1;
Packit ae235b
      c1 = (gint)(guchar) TOLOWER (*s1);
Packit ae235b
      c2 = (gint)(guchar) TOLOWER (*s2);
Packit ae235b
      if (c1 != c2)
Packit ae235b
        return (c1 - c2);
Packit ae235b
      s1++; s2++;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (n)
Packit ae235b
    return (((gint) (guchar) *s1) - ((gint) (guchar) *s2));
Packit ae235b
  else
Packit ae235b
    return 0;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strcasecmp:
Packit ae235b
 * @s1: a string
Packit ae235b
 * @s2: a string to compare with @s1
Packit ae235b
 *
Packit ae235b
 * A case-insensitive string comparison, corresponding to the standard
Packit ae235b
 * strcasecmp() function on platforms which support it.
Packit ae235b
 *
Packit ae235b
 * Returns: 0 if the strings match, a negative value if @s1 < @s2,
Packit ae235b
 *     or a positive value if @s1 > @s2.
Packit ae235b
 *
Packit ae235b
 * Deprecated:2.2: See g_strncasecmp() for a discussion of why this
Packit ae235b
 *     function is deprecated and how to replace it.
Packit ae235b
 */
Packit ae235b
gint
Packit ae235b
g_strcasecmp (const gchar *s1,
Packit ae235b
              const gchar *s2)
Packit ae235b
{
Packit ae235b
#ifdef HAVE_STRCASECMP
Packit ae235b
  g_return_val_if_fail (s1 != NULL, 0);
Packit ae235b
  g_return_val_if_fail (s2 != NULL, 0);
Packit ae235b
Packit ae235b
  return strcasecmp (s1, s2);
Packit ae235b
#else
Packit ae235b
  gint c1, c2;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (s1 != NULL, 0);
Packit ae235b
  g_return_val_if_fail (s2 != NULL, 0);
Packit ae235b
Packit ae235b
  while (*s1 && *s2)
Packit ae235b
    {
Packit ae235b
      /* According to A. Cox, some platforms have islower's that
Packit ae235b
       * don't work right on non-uppercase
Packit ae235b
       */
Packit ae235b
      c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1;
Packit ae235b
      c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2;
Packit ae235b
      if (c1 != c2)
Packit ae235b
        return (c1 - c2);
Packit ae235b
      s1++; s2++;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return (((gint)(guchar) *s1) - ((gint)(guchar) *s2));
Packit ae235b
#endif
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strncasecmp:
Packit ae235b
 * @s1: a string
Packit ae235b
 * @s2: a string to compare with @s1
Packit ae235b
 * @n: the maximum number of characters to compare
Packit ae235b
 *
Packit ae235b
 * A case-insensitive string comparison, corresponding to the standard
Packit ae235b
 * strncasecmp() function on platforms which support it. It is similar
Packit ae235b
 * to g_strcasecmp() except it only compares the first @n characters of
Packit ae235b
 * the strings.
Packit ae235b
 *
Packit ae235b
 * Returns: 0 if the strings match, a negative value if @s1 < @s2,
Packit ae235b
 *     or a positive value if @s1 > @s2.
Packit ae235b
 *
Packit ae235b
 * Deprecated:2.2: The problem with g_strncasecmp() is that it does
Packit ae235b
 *     the comparison by calling toupper()/tolower(). These functions
Packit ae235b
 *     are locale-specific and operate on single bytes. However, it is
Packit ae235b
 *     impossible to handle things correctly from an internationalization
Packit ae235b
 *     standpoint by operating on bytes, since characters may be multibyte.
Packit ae235b
 *     Thus g_strncasecmp() is broken if your string is guaranteed to be
Packit ae235b
 *     ASCII, since it is locale-sensitive, and it's broken if your string
Packit ae235b
 *     is localized, since it doesn't work on many encodings at all,
Packit ae235b
 *     including UTF-8, EUC-JP, etc.
Packit ae235b
 *
Packit ae235b
 *     There are therefore two replacement techniques: g_ascii_strncasecmp(),
Packit ae235b
 *     which only works on ASCII and is not locale-sensitive, and
Packit ae235b
 *     g_utf8_casefold() followed by strcmp() on the resulting strings,
Packit ae235b
 *     which is good for case-insensitive sorting of UTF-8.
Packit ae235b
 */
Packit ae235b
gint
Packit ae235b
g_strncasecmp (const gchar *s1,
Packit ae235b
               const gchar *s2,
Packit ae235b
               guint n)
Packit ae235b
{
Packit ae235b
#ifdef HAVE_STRNCASECMP
Packit ae235b
  return strncasecmp (s1, s2, n);
Packit ae235b
#else
Packit ae235b
  gint c1, c2;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (s1 != NULL, 0);
Packit ae235b
  g_return_val_if_fail (s2 != NULL, 0);
Packit ae235b
Packit ae235b
  while (n && *s1 && *s2)
Packit ae235b
    {
Packit ae235b
      n -= 1;
Packit ae235b
      /* According to A. Cox, some platforms have islower's that
Packit ae235b
       * don't work right on non-uppercase
Packit ae235b
       */
Packit ae235b
      c1 = isupper ((guchar)*s1) ? tolower ((guchar)*s1) : *s1;
Packit ae235b
      c2 = isupper ((guchar)*s2) ? tolower ((guchar)*s2) : *s2;
Packit ae235b
      if (c1 != c2)
Packit ae235b
        return (c1 - c2);
Packit ae235b
      s1++; s2++;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (n)
Packit ae235b
    return (((gint) (guchar) *s1) - ((gint) (guchar) *s2));
Packit ae235b
  else
Packit ae235b
    return 0;
Packit ae235b
#endif
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strdelimit:
Packit ae235b
 * @string: the string to convert
Packit ae235b
 * @delimiters: (nullable): a string containing the current delimiters,
Packit ae235b
 *     or %NULL to use the standard delimiters defined in #G_STR_DELIMITERS
Packit ae235b
 * @new_delimiter: the new delimiter character
Packit ae235b
 *
Packit ae235b
 * Converts any delimiter characters in @string to @new_delimiter.
Packit ae235b
 * Any characters in @string which are found in @delimiters are
Packit ae235b
 * changed to the @new_delimiter character. Modifies @string in place,
Packit ae235b
 * and returns @string itself, not a copy. The return value is to
Packit ae235b
 * allow nesting such as
Packit ae235b
 * |[ 
Packit ae235b
 *   g_ascii_strup (g_strdelimit (str, "abc", '?'))
Packit ae235b
 * ]|
Packit ae235b
 *
Packit ae235b
 * Returns: @string
Packit ae235b
 */
Packit ae235b
gchar *
Packit ae235b
g_strdelimit (gchar       *string,
Packit ae235b
              const gchar *delimiters,
Packit ae235b
              gchar        new_delim)
Packit ae235b
{
Packit ae235b
  gchar *c;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (string != NULL, NULL);
Packit ae235b
Packit ae235b
  if (!delimiters)
Packit ae235b
    delimiters = G_STR_DELIMITERS;
Packit ae235b
Packit ae235b
  for (c = string; *c; c++)
Packit ae235b
    {
Packit ae235b
      if (strchr (delimiters, *c))
Packit ae235b
        *c = new_delim;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return string;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strcanon:
Packit ae235b
 * @string: a nul-terminated array of bytes
Packit ae235b
 * @valid_chars: bytes permitted in @string
Packit ae235b
 * @substitutor: replacement character for disallowed bytes
Packit ae235b
 *
Packit ae235b
 * For each character in @string, if the character is not in @valid_chars,
Packit ae235b
 * replaces the character with @substitutor. Modifies @string in place,
Packit ae235b
 * and return @string itself, not a copy. The return value is to allow
Packit ae235b
 * nesting such as
Packit ae235b
 * |[ 
Packit ae235b
 *   g_ascii_strup (g_strcanon (str, "abc", '?'))
Packit ae235b
 * ]|
Packit ae235b
 *
Packit ae235b
 * Returns: @string
Packit ae235b
 */
Packit ae235b
gchar *
Packit ae235b
g_strcanon (gchar       *string,
Packit ae235b
            const gchar *valid_chars,
Packit ae235b
            gchar        substitutor)
Packit ae235b
{
Packit ae235b
  gchar *c;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (string != NULL, NULL);
Packit ae235b
  g_return_val_if_fail (valid_chars != NULL, NULL);
Packit ae235b
Packit ae235b
  for (c = string; *c; c++)
Packit ae235b
    {
Packit ae235b
      if (!strchr (valid_chars, *c))
Packit ae235b
        *c = substitutor;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return string;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strcompress:
Packit ae235b
 * @source: a string to compress
Packit ae235b
 *
Packit ae235b
 * Replaces all escaped characters with their one byte equivalent.
Packit ae235b
 *
Packit ae235b
 * This function does the reverse conversion of g_strescape().
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated copy of @source with all escaped
Packit ae235b
 *     character compressed
Packit ae235b
 */
Packit ae235b
gchar *
Packit ae235b
g_strcompress (const gchar *source)
Packit ae235b
{
Packit ae235b
  const gchar *p = source, *octal;
Packit ae235b
  gchar *dest;
Packit ae235b
  gchar *q;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (source != NULL, NULL);
Packit ae235b
Packit ae235b
  dest = g_malloc (strlen (source) + 1);
Packit ae235b
  q = dest;
Packit ae235b
Packit ae235b
  while (*p)
Packit ae235b
    {
Packit ae235b
      if (*p == '\\')
Packit ae235b
        {
Packit ae235b
          p++;
Packit ae235b
          switch (*p)
Packit ae235b
            {
Packit ae235b
            case '\0':
Packit ae235b
              g_warning ("g_strcompress: trailing \\");
Packit ae235b
              goto out;
Packit ae235b
            case '0':  case '1':  case '2':  case '3':  case '4':
Packit ae235b
            case '5':  case '6':  case '7':
Packit ae235b
              *q = 0;
Packit ae235b
              octal = p;
Packit ae235b
              while ((p < octal + 3) && (*p >= '0') && (*p <= '7'))
Packit ae235b
                {
Packit ae235b
                  *q = (*q * 8) + (*p - '0');
Packit ae235b
                  p++;
Packit ae235b
                }
Packit ae235b
              q++;
Packit ae235b
              p--;
Packit ae235b
              break;
Packit ae235b
            case 'b':
Packit ae235b
              *q++ = '\b';
Packit ae235b
              break;
Packit ae235b
            case 'f':
Packit ae235b
              *q++ = '\f';
Packit ae235b
              break;
Packit ae235b
            case 'n':
Packit ae235b
              *q++ = '\n';
Packit ae235b
              break;
Packit ae235b
            case 'r':
Packit ae235b
              *q++ = '\r';
Packit ae235b
              break;
Packit ae235b
            case 't':
Packit ae235b
              *q++ = '\t';
Packit ae235b
              break;
Packit ae235b
            case 'v':
Packit ae235b
              *q++ = '\v';
Packit ae235b
              break;
Packit ae235b
            default:            /* Also handles \" and \\ */
Packit ae235b
              *q++ = *p;
Packit ae235b
              break;
Packit ae235b
            }
Packit ae235b
        }
Packit ae235b
      else
Packit ae235b
        *q++ = *p;
Packit ae235b
      p++;
Packit ae235b
    }
Packit ae235b
out:
Packit ae235b
  *q = 0;
Packit ae235b
Packit ae235b
  return dest;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strescape:
Packit ae235b
 * @source: a string to escape
Packit ae235b
 * @exceptions: (nullable): a string of characters not to escape in @source
Packit ae235b
 *
Packit ae235b
 * Escapes the special characters '\b', '\f', '\n', '\r', '\t', '\v', '\'
Packit ae235b
 * and '"' in the string @source by inserting a '\' before
Packit ae235b
 * them. Additionally all characters in the range 0x01-0x1F (everything
Packit ae235b
 * below SPACE) and in the range 0x7F-0xFF (all non-ASCII chars) are
Packit ae235b
 * replaced with a '\' followed by their octal representation.
Packit ae235b
 * Characters supplied in @exceptions are not escaped.
Packit ae235b
 *
Packit ae235b
 * g_strcompress() does the reverse conversion.
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated copy of @source with certain
Packit ae235b
 *     characters escaped. See above.
Packit ae235b
 */
Packit ae235b
gchar *
Packit ae235b
g_strescape (const gchar *source,
Packit ae235b
             const gchar *exceptions)
Packit ae235b
{
Packit ae235b
  const guchar *p;
Packit ae235b
  gchar *dest;
Packit ae235b
  gchar *q;
Packit ae235b
  guchar excmap[256];
Packit ae235b
Packit ae235b
  g_return_val_if_fail (source != NULL, NULL);
Packit ae235b
Packit ae235b
  p = (guchar *) source;
Packit ae235b
  /* Each source byte needs maximally four destination chars (\777) */
Packit ae235b
  q = dest = g_malloc (strlen (source) * 4 + 1);
Packit ae235b
Packit ae235b
  memset (excmap, 0, 256);
Packit ae235b
  if (exceptions)
Packit ae235b
    {
Packit ae235b
      guchar *e = (guchar *) exceptions;
Packit ae235b
Packit ae235b
      while (*e)
Packit ae235b
        {
Packit ae235b
          excmap[*e] = 1;
Packit ae235b
          e++;
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
Packit ae235b
  while (*p)
Packit ae235b
    {
Packit ae235b
      if (excmap[*p])
Packit ae235b
        *q++ = *p;
Packit ae235b
      else
Packit ae235b
        {
Packit ae235b
          switch (*p)
Packit ae235b
            {
Packit ae235b
            case '\b':
Packit ae235b
              *q++ = '\\';
Packit ae235b
              *q++ = 'b';
Packit ae235b
              break;
Packit ae235b
            case '\f':
Packit ae235b
              *q++ = '\\';
Packit ae235b
              *q++ = 'f';
Packit ae235b
              break;
Packit ae235b
            case '\n':
Packit ae235b
              *q++ = '\\';
Packit ae235b
              *q++ = 'n';
Packit ae235b
              break;
Packit ae235b
            case '\r':
Packit ae235b
              *q++ = '\\';
Packit ae235b
              *q++ = 'r';
Packit ae235b
              break;
Packit ae235b
            case '\t':
Packit ae235b
              *q++ = '\\';
Packit ae235b
              *q++ = 't';
Packit ae235b
              break;
Packit ae235b
            case '\v':
Packit ae235b
              *q++ = '\\';
Packit ae235b
              *q++ = 'v';
Packit ae235b
              break;
Packit ae235b
            case '\\':
Packit ae235b
              *q++ = '\\';
Packit ae235b
              *q++ = '\\';
Packit ae235b
              break;
Packit ae235b
            case '"':
Packit ae235b
              *q++ = '\\';
Packit ae235b
              *q++ = '"';
Packit ae235b
              break;
Packit ae235b
            default:
Packit ae235b
              if ((*p < ' ') || (*p >= 0177))
Packit ae235b
                {
Packit ae235b
                  *q++ = '\\';
Packit ae235b
                  *q++ = '0' + (((*p) >> 6) & 07);
Packit ae235b
                  *q++ = '0' + (((*p) >> 3) & 07);
Packit ae235b
                  *q++ = '0' + ((*p) & 07);
Packit ae235b
                }
Packit ae235b
              else
Packit ae235b
                *q++ = *p;
Packit ae235b
              break;
Packit ae235b
            }
Packit ae235b
        }
Packit ae235b
      p++;
Packit ae235b
    }
Packit ae235b
  *q = 0;
Packit ae235b
  return dest;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strchug:
Packit ae235b
 * @string: a string to remove the leading whitespace from
Packit ae235b
 *
Packit ae235b
 * Removes leading whitespace from a string, by moving the rest
Packit ae235b
 * of the characters forward.
Packit ae235b
 *
Packit ae235b
 * This function doesn't allocate or reallocate any memory;
Packit ae235b
 * it modifies @string in place. Therefore, it cannot be used on
Packit ae235b
 * statically allocated strings.
Packit ae235b
 *
Packit ae235b
 * The pointer to @string is returned to allow the nesting of functions.
Packit ae235b
 *
Packit ae235b
 * Also see g_strchomp() and g_strstrip().
Packit ae235b
 *
Packit ae235b
 * Returns: @string
Packit ae235b
 */
Packit ae235b
gchar *
Packit ae235b
g_strchug (gchar *string)
Packit ae235b
{
Packit ae235b
  guchar *start;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (string != NULL, NULL);
Packit ae235b
Packit ae235b
  for (start = (guchar*) string; *start && g_ascii_isspace (*start); start++)
Packit ae235b
    ;
Packit ae235b
Packit ae235b
  memmove (string, start, strlen ((gchar *) start) + 1);
Packit ae235b
Packit ae235b
  return string;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strchomp:
Packit ae235b
 * @string: a string to remove the trailing whitespace from
Packit ae235b
 *
Packit ae235b
 * Removes trailing whitespace from a string.
Packit ae235b
 *
Packit ae235b
 * This function doesn't allocate or reallocate any memory;
Packit ae235b
 * it modifies @string in place. Therefore, it cannot be used
Packit ae235b
 * on statically allocated strings.
Packit ae235b
 *
Packit ae235b
 * The pointer to @string is returned to allow the nesting of functions.
Packit ae235b
 *
Packit ae235b
 * Also see g_strchug() and g_strstrip().
Packit ae235b
 *
Packit ae235b
 * Returns: @string
Packit ae235b
 */
Packit ae235b
gchar *
Packit ae235b
g_strchomp (gchar *string)
Packit ae235b
{
Packit ae235b
  gsize len;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (string != NULL, NULL);
Packit ae235b
Packit ae235b
  len = strlen (string);
Packit ae235b
  while (len--)
Packit ae235b
    {
Packit ae235b
      if (g_ascii_isspace ((guchar) string[len]))
Packit ae235b
        string[len] = '\0';
Packit ae235b
      else
Packit ae235b
        break;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return string;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strsplit:
Packit ae235b
 * @string: a string to split
Packit ae235b
 * @delimiter: a string which specifies the places at which to split
Packit ae235b
 *     the string. The delimiter is not included in any of the resulting
Packit ae235b
 *     strings, unless @max_tokens is reached.
Packit ae235b
 * @max_tokens: the maximum number of pieces to split @string into.
Packit ae235b
 *     If this is less than 1, the string is split completely.
Packit ae235b
 *
Packit ae235b
 * Splits a string into a maximum of @max_tokens pieces, using the given
Packit ae235b
 * @delimiter. If @max_tokens is reached, the remainder of @string is
Packit ae235b
 * appended to the last token.
Packit ae235b
 *
Packit ae235b
 * As an example, the result of g_strsplit (":a:bc::d:", ":", -1) is a
Packit ae235b
 * %NULL-terminated vector containing the six strings "", "a", "bc", "", "d"
Packit ae235b
 * and "".
Packit ae235b
 *
Packit ae235b
 * As a special case, the result of splitting the empty string "" is an empty
Packit ae235b
 * vector, not a vector containing a single string. The reason for this
Packit ae235b
 * special case is that being able to represent a empty vector is typically
Packit ae235b
 * more useful than consistent handling of empty elements. If you do need
Packit ae235b
 * to represent empty elements, you'll need to check for the empty string
Packit ae235b
 * before calling g_strsplit().
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated %NULL-terminated array of strings. Use
Packit ae235b
 *    g_strfreev() to free it.
Packit ae235b
 */
Packit ae235b
gchar**
Packit ae235b
g_strsplit (const gchar *string,
Packit ae235b
            const gchar *delimiter,
Packit ae235b
            gint         max_tokens)
Packit ae235b
{
Packit ae235b
  GSList *string_list = NULL, *slist;
Packit ae235b
  gchar **str_array, *s;
Packit ae235b
  guint n = 0;
Packit ae235b
  const gchar *remainder;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (string != NULL, NULL);
Packit ae235b
  g_return_val_if_fail (delimiter != NULL, NULL);
Packit ae235b
  g_return_val_if_fail (delimiter[0] != '\0', NULL);
Packit ae235b
Packit ae235b
  if (max_tokens < 1)
Packit ae235b
    max_tokens = G_MAXINT;
Packit ae235b
Packit ae235b
  remainder = string;
Packit ae235b
  s = strstr (remainder, delimiter);
Packit ae235b
  if (s)
Packit ae235b
    {
Packit ae235b
      gsize delimiter_len = strlen (delimiter);
Packit ae235b
Packit ae235b
      while (--max_tokens && s)
Packit ae235b
        {
Packit ae235b
          gsize len;
Packit ae235b
Packit ae235b
          len = s - remainder;
Packit ae235b
          string_list = g_slist_prepend (string_list,
Packit ae235b
                                         g_strndup (remainder, len));
Packit ae235b
          n++;
Packit ae235b
          remainder = s + delimiter_len;
Packit ae235b
          s = strstr (remainder, delimiter);
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
  if (*string)
Packit ae235b
    {
Packit ae235b
      n++;
Packit ae235b
      string_list = g_slist_prepend (string_list, g_strdup (remainder));
Packit ae235b
    }
Packit ae235b
Packit ae235b
  str_array = g_new (gchar*, n + 1);
Packit ae235b
Packit ae235b
  str_array[n--] = NULL;
Packit ae235b
  for (slist = string_list; slist; slist = slist->next)
Packit ae235b
    str_array[n--] = slist->data;
Packit ae235b
Packit ae235b
  g_slist_free (string_list);
Packit ae235b
Packit ae235b
  return str_array;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strsplit_set:
Packit ae235b
 * @string: The string to be tokenized
Packit ae235b
 * @delimiters: A nul-terminated string containing bytes that are used
Packit ae235b
 *     to split the string.
Packit ae235b
 * @max_tokens: The maximum number of tokens to split @string into.
Packit ae235b
 *     If this is less than 1, the string is split completely
Packit ae235b
 *
Packit ae235b
 * Splits @string into a number of tokens not containing any of the characters
Packit ae235b
 * in @delimiter. A token is the (possibly empty) longest string that does not
Packit ae235b
 * contain any of the characters in @delimiters. If @max_tokens is reached, the
Packit ae235b
 * remainder is appended to the last token.
Packit ae235b
 *
Packit ae235b
 * For example the result of g_strsplit_set ("abc:def/ghi", ":/", -1) is a
Packit ae235b
 * %NULL-terminated vector containing the three strings "abc", "def",
Packit ae235b
 * and "ghi".
Packit ae235b
 *
Packit ae235b
 * The result of g_strsplit_set (":def/ghi:", ":/", -1) is a %NULL-terminated
Packit ae235b
 * vector containing the four strings "", "def", "ghi", and "".
Packit ae235b
 *
Packit ae235b
 * As a special case, the result of splitting the empty string "" is an empty
Packit ae235b
 * vector, not a vector containing a single string. The reason for this
Packit ae235b
 * special case is that being able to represent a empty vector is typically
Packit ae235b
 * more useful than consistent handling of empty elements. If you do need
Packit ae235b
 * to represent empty elements, you'll need to check for the empty string
Packit ae235b
 * before calling g_strsplit_set().
Packit ae235b
 *
Packit ae235b
 * Note that this function works on bytes not characters, so it can't be used
Packit ae235b
 * to delimit UTF-8 strings for anything but ASCII characters.
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated %NULL-terminated array of strings. Use
Packit ae235b
 *    g_strfreev() to free it.
Packit ae235b
 *
Packit ae235b
 * Since: 2.4
Packit ae235b
 **/
Packit ae235b
gchar **
Packit ae235b
g_strsplit_set (const gchar *string,
Packit ae235b
                const gchar *delimiters,
Packit ae235b
                gint         max_tokens)
Packit ae235b
{
Packit ae235b
  gboolean delim_table[256];
Packit ae235b
  GSList *tokens, *list;
Packit ae235b
  gint n_tokens;
Packit ae235b
  const gchar *s;
Packit ae235b
  const gchar *current;
Packit ae235b
  gchar *token;
Packit ae235b
  gchar **result;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (string != NULL, NULL);
Packit ae235b
  g_return_val_if_fail (delimiters != NULL, NULL);
Packit ae235b
Packit ae235b
  if (max_tokens < 1)
Packit ae235b
    max_tokens = G_MAXINT;
Packit ae235b
Packit ae235b
  if (*string == '\0')
Packit ae235b
    {
Packit ae235b
      result = g_new (char *, 1);
Packit ae235b
      result[0] = NULL;
Packit ae235b
      return result;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  memset (delim_table, FALSE, sizeof (delim_table));
Packit ae235b
  for (s = delimiters; *s != '\0'; ++s)
Packit ae235b
    delim_table[*(guchar *)s] = TRUE;
Packit ae235b
Packit ae235b
  tokens = NULL;
Packit ae235b
  n_tokens = 0;
Packit ae235b
Packit ae235b
  s = current = string;
Packit ae235b
  while (*s != '\0')
Packit ae235b
    {
Packit ae235b
      if (delim_table[*(guchar *)s] && n_tokens + 1 < max_tokens)
Packit ae235b
        {
Packit ae235b
          token = g_strndup (current, s - current);
Packit ae235b
          tokens = g_slist_prepend (tokens, token);
Packit ae235b
          ++n_tokens;
Packit ae235b
Packit ae235b
          current = s + 1;
Packit ae235b
        }
Packit ae235b
Packit ae235b
      ++s;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  token = g_strndup (current, s - current);
Packit ae235b
  tokens = g_slist_prepend (tokens, token);
Packit ae235b
  ++n_tokens;
Packit ae235b
Packit ae235b
  result = g_new (gchar *, n_tokens + 1);
Packit ae235b
Packit ae235b
  result[n_tokens] = NULL;
Packit ae235b
  for (list = tokens; list != NULL; list = list->next)
Packit ae235b
    result[--n_tokens] = list->data;
Packit ae235b
Packit ae235b
  g_slist_free (tokens);
Packit ae235b
Packit ae235b
  return result;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * GStrv:
Packit ae235b
 *
Packit ae235b
 * A typedef alias for gchar**. This is mostly useful when used together with
Packit ae235b
 * g_auto().
Packit ae235b
 */
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strfreev:
Packit ae235b
 * @str_array: (nullable): a %NULL-terminated array of strings to free
Packit ae235b
 *
Packit ae235b
 * Frees a %NULL-terminated array of strings, as well as each
Packit ae235b
 * string it contains.
Packit ae235b
 *
Packit ae235b
 * If @str_array is %NULL, this function simply returns.
Packit ae235b
 */
Packit ae235b
void
Packit ae235b
g_strfreev (gchar **str_array)
Packit ae235b
{
Packit ae235b
  if (str_array)
Packit ae235b
    {
Packit ae235b
      int i;
Packit ae235b
Packit ae235b
      for (i = 0; str_array[i] != NULL; i++)
Packit ae235b
        g_free (str_array[i]);
Packit ae235b
Packit ae235b
      g_free (str_array);
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strdupv:
Packit ae235b
 * @str_array: (nullable): a %NULL-terminated array of strings
Packit ae235b
 *
Packit ae235b
 * Copies %NULL-terminated array of strings. The copy is a deep copy;
Packit ae235b
 * the new array should be freed by first freeing each string, then
Packit ae235b
 * the array itself. g_strfreev() does this for you. If called
Packit ae235b
 * on a %NULL value, g_strdupv() simply returns %NULL.
Packit ae235b
 *
Packit ae235b
 * Returns: (nullable): a new %NULL-terminated array of strings.
Packit ae235b
 */
Packit ae235b
gchar**
Packit ae235b
g_strdupv (gchar **str_array)
Packit ae235b
{
Packit ae235b
  if (str_array)
Packit ae235b
    {
Packit ae235b
      gint i;
Packit ae235b
      gchar **retval;
Packit ae235b
Packit ae235b
      i = 0;
Packit ae235b
      while (str_array[i])
Packit ae235b
        ++i;
Packit ae235b
Packit ae235b
      retval = g_new (gchar*, i + 1);
Packit ae235b
Packit ae235b
      i = 0;
Packit ae235b
      while (str_array[i])
Packit ae235b
        {
Packit ae235b
          retval[i] = g_strdup (str_array[i]);
Packit ae235b
          ++i;
Packit ae235b
        }
Packit ae235b
      retval[i] = NULL;
Packit ae235b
Packit ae235b
      return retval;
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    return NULL;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strjoinv:
Packit ae235b
 * @separator: (nullable): a string to insert between each of the
Packit ae235b
 *     strings, or %NULL
Packit ae235b
 * @str_array: a %NULL-terminated array of strings to join
Packit ae235b
 *
Packit ae235b
 * Joins a number of strings together to form one long string, with the
Packit ae235b
 * optional @separator inserted between each of them. The returned string
Packit ae235b
 * should be freed with g_free().
Packit ae235b
 *
Packit ae235b
 * If @str_array has no items, the return value will be an
Packit ae235b
 * empty string. If @str_array contains a single item, @separator will not
Packit ae235b
 * appear in the resulting string.
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated string containing all of the strings joined
Packit ae235b
 *     together, with @separator between them
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_strjoinv (const gchar  *separator,
Packit ae235b
            gchar       **str_array)
Packit ae235b
{
Packit ae235b
  gchar *string;
Packit ae235b
  gchar *ptr;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (str_array != NULL, NULL);
Packit ae235b
Packit ae235b
  if (separator == NULL)
Packit ae235b
    separator = "";
Packit ae235b
Packit ae235b
  if (*str_array)
Packit ae235b
    {
Packit ae235b
      gint i;
Packit ae235b
      gsize len;
Packit ae235b
      gsize separator_len;
Packit ae235b
Packit ae235b
      separator_len = strlen (separator);
Packit ae235b
      /* First part, getting length */
Packit ae235b
      len = 1 + strlen (str_array[0]);
Packit ae235b
      for (i = 1; str_array[i] != NULL; i++)
Packit ae235b
        len += strlen (str_array[i]);
Packit ae235b
      len += separator_len * (i - 1);
Packit ae235b
Packit ae235b
      /* Second part, building string */
Packit ae235b
      string = g_new (gchar, len);
Packit ae235b
      ptr = g_stpcpy (string, *str_array);
Packit ae235b
      for (i = 1; str_array[i] != NULL; i++)
Packit ae235b
        {
Packit ae235b
          ptr = g_stpcpy (ptr, separator);
Packit ae235b
          ptr = g_stpcpy (ptr, str_array[i]);
Packit ae235b
        }
Packit ae235b
      }
Packit ae235b
  else
Packit ae235b
    string = g_strdup ("");
Packit ae235b
Packit ae235b
  return string;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strjoin:
Packit ae235b
 * @separator: (nullable): a string to insert between each of the
Packit ae235b
 *     strings, or %NULL
Packit ae235b
 * @...: a %NULL-terminated list of strings to join
Packit ae235b
 *
Packit ae235b
 * Joins a number of strings together to form one long string, with the
Packit ae235b
 * optional @separator inserted between each of them. The returned string
Packit ae235b
 * should be freed with g_free().
Packit ae235b
 *
Packit ae235b
 * Returns: a newly-allocated string containing all of the strings joined
Packit ae235b
 *     together, with @separator between them
Packit ae235b
 */
Packit ae235b
gchar*
Packit ae235b
g_strjoin (const gchar *separator,
Packit ae235b
           ...)
Packit ae235b
{
Packit ae235b
  gchar *string, *s;
Packit ae235b
  va_list args;
Packit ae235b
  gsize len;
Packit ae235b
  gsize separator_len;
Packit ae235b
  gchar *ptr;
Packit ae235b
Packit ae235b
  if (separator == NULL)
Packit ae235b
    separator = "";
Packit ae235b
Packit ae235b
  separator_len = strlen (separator);
Packit ae235b
Packit ae235b
  va_start (args, separator);
Packit ae235b
Packit ae235b
  s = va_arg (args, gchar*);
Packit ae235b
Packit ae235b
  if (s)
Packit ae235b
    {
Packit ae235b
      /* First part, getting length */
Packit ae235b
      len = 1 + strlen (s);
Packit ae235b
Packit ae235b
      s = va_arg (args, gchar*);
Packit ae235b
      while (s)
Packit ae235b
        {
Packit ae235b
          len += separator_len + strlen (s);
Packit ae235b
          s = va_arg (args, gchar*);
Packit ae235b
        }
Packit ae235b
      va_end (args);
Packit ae235b
Packit ae235b
      /* Second part, building string */
Packit ae235b
      string = g_new (gchar, len);
Packit ae235b
Packit ae235b
      va_start (args, separator);
Packit ae235b
Packit ae235b
      s = va_arg (args, gchar*);
Packit ae235b
      ptr = g_stpcpy (string, s);
Packit ae235b
Packit ae235b
      s = va_arg (args, gchar*);
Packit ae235b
      while (s)
Packit ae235b
        {
Packit ae235b
          ptr = g_stpcpy (ptr, separator);
Packit ae235b
          ptr = g_stpcpy (ptr, s);
Packit ae235b
          s = va_arg (args, gchar*);
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
  else
Packit ae235b
    string = g_strdup ("");
Packit ae235b
Packit ae235b
  va_end (args);
Packit ae235b
Packit ae235b
  return string;
Packit ae235b
}
Packit ae235b
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strstr_len:
Packit ae235b
 * @haystack: a string
Packit ae235b
 * @haystack_len: the maximum length of @haystack. Note that -1 is
Packit ae235b
 *     a valid length, if @haystack is nul-terminated, meaning it will
Packit ae235b
 *     search through the whole string.
Packit ae235b
 * @needle: the string to search for
Packit ae235b
 *
Packit ae235b
 * Searches the string @haystack for the first occurrence
Packit ae235b
 * of the string @needle, limiting the length of the search
Packit ae235b
 * to @haystack_len.
Packit ae235b
 *
Packit ae235b
 * Returns: a pointer to the found occurrence, or
Packit ae235b
 *    %NULL if not found.
Packit ae235b
 */
Packit ae235b
gchar *
Packit ae235b
g_strstr_len (const gchar *haystack,
Packit ae235b
              gssize       haystack_len,
Packit ae235b
              const gchar *needle)
Packit ae235b
{
Packit ae235b
  g_return_val_if_fail (haystack != NULL, NULL);
Packit ae235b
  g_return_val_if_fail (needle != NULL, NULL);
Packit ae235b
Packit ae235b
  if (haystack_len < 0)
Packit ae235b
    return strstr (haystack, needle);
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      const gchar *p = haystack;
Packit ae235b
      gsize needle_len = strlen (needle);
Packit ae235b
      const gchar *end;
Packit ae235b
      gsize i;
Packit ae235b
Packit ae235b
      if (needle_len == 0)
Packit ae235b
        return (gchar *)haystack;
Packit ae235b
Packit ae235b
      if (haystack_len < needle_len)
Packit ae235b
        return NULL;
Packit ae235b
Packit ae235b
      end = haystack + haystack_len - needle_len;
Packit ae235b
Packit ae235b
      while (p <= end && *p)
Packit ae235b
        {
Packit ae235b
          for (i = 0; i < needle_len; i++)
Packit ae235b
            if (p[i] != needle[i])
Packit ae235b
              goto next;
Packit ae235b
Packit ae235b
          return (gchar *)p;
Packit ae235b
Packit ae235b
        next:
Packit ae235b
          p++;
Packit ae235b
        }
Packit ae235b
Packit ae235b
      return NULL;
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strrstr:
Packit ae235b
 * @haystack: a nul-terminated string
Packit ae235b
 * @needle: the nul-terminated string to search for
Packit ae235b
 *
Packit ae235b
 * Searches the string @haystack for the last occurrence
Packit ae235b
 * of the string @needle.
Packit ae235b
 *
Packit ae235b
 * Returns: a pointer to the found occurrence, or
Packit ae235b
 *    %NULL if not found.
Packit ae235b
 */
Packit ae235b
gchar *
Packit ae235b
g_strrstr (const gchar *haystack,
Packit ae235b
           const gchar *needle)
Packit ae235b
{
Packit ae235b
  gsize i;
Packit ae235b
  gsize needle_len;
Packit ae235b
  gsize haystack_len;
Packit ae235b
  const gchar *p;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (haystack != NULL, NULL);
Packit ae235b
  g_return_val_if_fail (needle != NULL, NULL);
Packit ae235b
Packit ae235b
  needle_len = strlen (needle);
Packit ae235b
  haystack_len = strlen (haystack);
Packit ae235b
Packit ae235b
  if (needle_len == 0)
Packit ae235b
    return (gchar *)haystack;
Packit ae235b
Packit ae235b
  if (haystack_len < needle_len)
Packit ae235b
    return NULL;
Packit ae235b
Packit ae235b
  p = haystack + haystack_len - needle_len;
Packit ae235b
Packit ae235b
  while (p >= haystack)
Packit ae235b
    {
Packit ae235b
      for (i = 0; i < needle_len; i++)
Packit ae235b
        if (p[i] != needle[i])
Packit ae235b
          goto next;
Packit ae235b
Packit ae235b
      return (gchar *)p;
Packit ae235b
Packit ae235b
    next:
Packit ae235b
      p--;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return NULL;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strrstr_len:
Packit ae235b
 * @haystack: a nul-terminated string
Packit ae235b
 * @haystack_len: the maximum length of @haystack
Packit ae235b
 * @needle: the nul-terminated string to search for
Packit ae235b
 *
Packit ae235b
 * Searches the string @haystack for the last occurrence
Packit ae235b
 * of the string @needle, limiting the length of the search
Packit ae235b
 * to @haystack_len.
Packit ae235b
 *
Packit ae235b
 * Returns: a pointer to the found occurrence, or
Packit ae235b
 *    %NULL if not found.
Packit ae235b
 */
Packit ae235b
gchar *
Packit ae235b
g_strrstr_len (const gchar *haystack,
Packit ae235b
               gssize        haystack_len,
Packit ae235b
               const gchar *needle)
Packit ae235b
{
Packit ae235b
  g_return_val_if_fail (haystack != NULL, NULL);
Packit ae235b
  g_return_val_if_fail (needle != NULL, NULL);
Packit ae235b
Packit ae235b
  if (haystack_len < 0)
Packit ae235b
    return g_strrstr (haystack, needle);
Packit ae235b
  else
Packit ae235b
    {
Packit ae235b
      gsize needle_len = strlen (needle);
Packit ae235b
      const gchar *haystack_max = haystack + haystack_len;
Packit ae235b
      const gchar *p = haystack;
Packit ae235b
      gsize i;
Packit ae235b
Packit ae235b
      while (p < haystack_max && *p)
Packit ae235b
        p++;
Packit ae235b
Packit ae235b
      if (p < haystack + needle_len)
Packit ae235b
        return NULL;
Packit ae235b
Packit ae235b
      p -= needle_len;
Packit ae235b
Packit ae235b
      while (p >= haystack)
Packit ae235b
        {
Packit ae235b
          for (i = 0; i < needle_len; i++)
Packit ae235b
            if (p[i] != needle[i])
Packit ae235b
              goto next;
Packit ae235b
Packit ae235b
          return (gchar *)p;
Packit ae235b
Packit ae235b
        next:
Packit ae235b
          p--;
Packit ae235b
        }
Packit ae235b
Packit ae235b
      return NULL;
Packit ae235b
    }
Packit ae235b
}
Packit ae235b
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_str_has_suffix:
Packit ae235b
 * @str: a nul-terminated string
Packit ae235b
 * @suffix: the nul-terminated suffix to look for
Packit ae235b
 *
Packit ae235b
 * Looks whether the string @str ends with @suffix.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @str end with @suffix, %FALSE otherwise.
Packit ae235b
 *
Packit ae235b
 * Since: 2.2
Packit ae235b
 */
Packit ae235b
gboolean
Packit ae235b
g_str_has_suffix (const gchar *str,
Packit ae235b
                  const gchar *suffix)
Packit ae235b
{
Packit ae235b
  gsize str_len;
Packit ae235b
  gsize suffix_len;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (str != NULL, FALSE);
Packit ae235b
  g_return_val_if_fail (suffix != NULL, FALSE);
Packit ae235b
Packit ae235b
  str_len = strlen (str);
Packit ae235b
  suffix_len = strlen (suffix);
Packit ae235b
Packit ae235b
  if (str_len < suffix_len)
Packit ae235b
    return FALSE;
Packit ae235b
Packit ae235b
  return strcmp (str + str_len - suffix_len, suffix) == 0;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_str_has_prefix:
Packit ae235b
 * @str: a nul-terminated string
Packit ae235b
 * @prefix: the nul-terminated prefix to look for
Packit ae235b
 *
Packit ae235b
 * Looks whether the string @str begins with @prefix.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @str begins with @prefix, %FALSE otherwise.
Packit ae235b
 *
Packit ae235b
 * Since: 2.2
Packit ae235b
 */
Packit ae235b
gboolean
Packit ae235b
g_str_has_prefix (const gchar *str,
Packit ae235b
                  const gchar *prefix)
Packit ae235b
{
Packit ae235b
  g_return_val_if_fail (str != NULL, FALSE);
Packit ae235b
  g_return_val_if_fail (prefix != NULL, FALSE);
Packit ae235b
Packit ae235b
  return strncmp (str, prefix, strlen (prefix)) == 0;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strv_length:
Packit ae235b
 * @str_array: a %NULL-terminated array of strings
Packit ae235b
 *
Packit ae235b
 * Returns the length of the given %NULL-terminated
Packit ae235b
 * string array @str_array.
Packit ae235b
 *
Packit ae235b
 * Returns: length of @str_array.
Packit ae235b
 *
Packit ae235b
 * Since: 2.6
Packit ae235b
 */
Packit ae235b
guint
Packit ae235b
g_strv_length (gchar **str_array)
Packit ae235b
{
Packit ae235b
  guint i = 0;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (str_array != NULL, 0);
Packit ae235b
Packit ae235b
  while (str_array[i])
Packit ae235b
    ++i;
Packit ae235b
Packit ae235b
  return i;
Packit ae235b
}
Packit ae235b
Packit ae235b
static void
Packit ae235b
index_add_folded (GPtrArray   *array,
Packit ae235b
                  const gchar *start,
Packit ae235b
                  const gchar *end)
Packit ae235b
{
Packit ae235b
  gchar *normal;
Packit ae235b
Packit ae235b
  normal = g_utf8_normalize (start, end - start, G_NORMALIZE_ALL_COMPOSE);
Packit ae235b
Packit ae235b
  /* TODO: Invent time machine.  Converse with Mustafa Ataturk... */
Packit ae235b
  if (strstr (normal, "ı") || strstr (normal, "İ"))
Packit ae235b
    {
Packit ae235b
      gchar *s = normal;
Packit ae235b
      GString *tmp;
Packit ae235b
Packit ae235b
      tmp = g_string_new (NULL);
Packit ae235b
Packit ae235b
      while (*s)
Packit ae235b
        {
Packit ae235b
          gchar *i, *I, *e;
Packit ae235b
Packit ae235b
          i = strstr (s, "ı");
Packit ae235b
          I = strstr (s, "İ");
Packit ae235b
Packit ae235b
          if (!i && !I)
Packit ae235b
            break;
Packit ae235b
          else if (i && !I)
Packit ae235b
            e = i;
Packit ae235b
          else if (I && !i)
Packit ae235b
            e = I;
Packit ae235b
          else if (i < I)
Packit ae235b
            e = i;
Packit ae235b
          else
Packit ae235b
            e = I;
Packit ae235b
Packit ae235b
          g_string_append_len (tmp, s, e - s);
Packit ae235b
          g_string_append_c (tmp, 'i');
Packit ae235b
          s = g_utf8_next_char (e);
Packit ae235b
        }
Packit ae235b
Packit ae235b
      g_string_append (tmp, s);
Packit ae235b
      g_free (normal);
Packit ae235b
      normal = g_string_free (tmp, FALSE);
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_ptr_array_add (array, g_utf8_casefold (normal, -1));
Packit ae235b
  g_free (normal);
Packit ae235b
}
Packit ae235b
Packit ae235b
static gchar **
Packit ae235b
split_words (const gchar *value)
Packit ae235b
{
Packit ae235b
  const gchar *start = NULL;
Packit ae235b
  GPtrArray *result;
Packit ae235b
  const gchar *s;
Packit ae235b
Packit ae235b
  result = g_ptr_array_new ();
Packit ae235b
Packit ae235b
  for (s = value; *s; s = g_utf8_next_char (s))
Packit ae235b
    {
Packit ae235b
      gunichar c = g_utf8_get_char (s);
Packit ae235b
Packit ae235b
      if (start == NULL)
Packit ae235b
        {
Packit ae235b
          if (g_unichar_isalnum (c) || g_unichar_ismark (c))
Packit ae235b
            start = s;
Packit ae235b
        }
Packit ae235b
      else
Packit ae235b
        {
Packit ae235b
          if (!g_unichar_isalnum (c) && !g_unichar_ismark (c))
Packit ae235b
            {
Packit ae235b
              index_add_folded (result, start, s);
Packit ae235b
              start = NULL;
Packit ae235b
            }
Packit ae235b
        }
Packit ae235b
    }
Packit ae235b
Packit ae235b
  if (start)
Packit ae235b
    index_add_folded (result, start, s);
Packit ae235b
Packit ae235b
  g_ptr_array_add (result, NULL);
Packit ae235b
Packit ae235b
  return (gchar **) g_ptr_array_free (result, FALSE);
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_str_tokenize_and_fold:
Packit ae235b
 * @string: a string
Packit ae235b
 * @translit_locale: (nullable): the language code (like 'de' or
Packit ae235b
 *   'en_GB') from which @string originates
Packit ae235b
 * @ascii_alternates: (out) (transfer full) (array zero-terminated=1): a
Packit ae235b
 *   return location for ASCII alternates
Packit ae235b
 *
Packit ae235b
 * Tokenises @string and performs folding on each token.
Packit ae235b
 *
Packit ae235b
 * A token is a non-empty sequence of alphanumeric characters in the
Packit ae235b
 * source string, separated by non-alphanumeric characters.  An
Packit ae235b
 * "alphanumeric" character for this purpose is one that matches
Packit ae235b
 * g_unichar_isalnum() or g_unichar_ismark().
Packit ae235b
 *
Packit ae235b
 * Each token is then (Unicode) normalised and case-folded.  If
Packit ae235b
 * @ascii_alternates is non-%NULL and some of the returned tokens
Packit ae235b
 * contain non-ASCII characters, ASCII alternatives will be generated.
Packit ae235b
 *
Packit ae235b
 * The number of ASCII alternatives that are generated and the method
Packit ae235b
 * for doing so is unspecified, but @translit_locale (if specified) may
Packit ae235b
 * improve the transliteration if the language of the source string is
Packit ae235b
 * known.
Packit ae235b
 *
Packit ae235b
 * Returns: (transfer full) (array zero-terminated=1): the folded tokens
Packit ae235b
 *
Packit ae235b
 * Since: 2.40
Packit ae235b
 **/
Packit ae235b
gchar **
Packit ae235b
g_str_tokenize_and_fold (const gchar   *string,
Packit ae235b
                         const gchar   *translit_locale,
Packit ae235b
                         gchar       ***ascii_alternates)
Packit ae235b
{
Packit ae235b
  gchar **result;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (string != NULL, NULL);
Packit ae235b
Packit ae235b
  if (ascii_alternates && g_str_is_ascii (string))
Packit ae235b
    {
Packit ae235b
      *ascii_alternates = g_new0 (gchar *, 0 + 1);
Packit ae235b
      ascii_alternates = NULL;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  result = split_words (string);
Packit ae235b
Packit ae235b
  if (ascii_alternates)
Packit ae235b
    {
Packit ae235b
      gint i, j, n;
Packit ae235b
Packit ae235b
      n = g_strv_length (result);
Packit ae235b
      *ascii_alternates = g_new (gchar *, n + 1);
Packit ae235b
      j = 0;
Packit ae235b
Packit ae235b
      for (i = 0; i < n; i++)
Packit ae235b
        {
Packit ae235b
          if (!g_str_is_ascii (result[i]))
Packit ae235b
            {
Packit ae235b
              gchar *composed;
Packit ae235b
              gchar *ascii;
Packit ae235b
              gint k;
Packit ae235b
Packit ae235b
              composed = g_utf8_normalize (result[i], -1, G_NORMALIZE_ALL_COMPOSE);
Packit ae235b
Packit ae235b
              ascii = g_str_to_ascii (composed, translit_locale);
Packit ae235b
Packit ae235b
              /* Only accept strings that are now entirely alnums */
Packit ae235b
              for (k = 0; ascii[k]; k++)
Packit ae235b
                if (!g_ascii_isalnum (ascii[k]))
Packit ae235b
                  break;
Packit ae235b
Packit ae235b
              if (ascii[k] == '\0')
Packit ae235b
                /* Made it to the end... */
Packit ae235b
                (*ascii_alternates)[j++] = ascii;
Packit ae235b
              else
Packit ae235b
                g_free (ascii);
Packit ae235b
Packit ae235b
              g_free (composed);
Packit ae235b
            }
Packit ae235b
        }
Packit ae235b
Packit ae235b
      (*ascii_alternates)[j] = NULL;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return result;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_str_match_string:
Packit ae235b
 * @search_term: the search term from the user
Packit ae235b
 * @potential_hit: the text that may be a hit
Packit ae235b
 * @accept_alternates: %TRUE to accept ASCII alternates
Packit ae235b
 *
Packit ae235b
 * Checks if a search conducted for @search_term should match
Packit ae235b
 * @potential_hit.
Packit ae235b
 *
Packit ae235b
 * This function calls g_str_tokenize_and_fold() on both
Packit ae235b
 * @search_term and @potential_hit.  ASCII alternates are never taken
Packit ae235b
 * for @search_term but will be taken for @potential_hit according to
Packit ae235b
 * the value of @accept_alternates.
Packit ae235b
 *
Packit ae235b
 * A hit occurs when each folded token in @search_term is a prefix of a
Packit ae235b
 * folded token from @potential_hit.
Packit ae235b
 *
Packit ae235b
 * Depending on how you're performing the search, it will typically be
Packit ae235b
 * faster to call g_str_tokenize_and_fold() on each string in
Packit ae235b
 * your corpus and build an index on the returned folded tokens, then
Packit ae235b
 * call g_str_tokenize_and_fold() on the search term and
Packit ae235b
 * perform lookups into that index.
Packit ae235b
 *
Packit ae235b
 * As some examples, searching for ‘fred’ would match the potential hit
Packit ae235b
 * ‘Smith, Fred’ and also ‘Frédéric’.  Searching for ‘Fréd’ would match
Packit ae235b
 * ‘Frédéric’ but not ‘Frederic’ (due to the one-directional nature of
Packit ae235b
 * accent matching).  Searching ‘fo’ would match ‘Foo’ and ‘Bar Foo
Packit ae235b
 * Baz’, but not ‘SFO’ (because no word has ‘fo’ as a prefix).
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @potential_hit is a hit
Packit ae235b
 *
Packit ae235b
 * Since: 2.40
Packit ae235b
 **/
Packit ae235b
gboolean
Packit ae235b
g_str_match_string (const gchar *search_term,
Packit ae235b
                    const gchar *potential_hit,
Packit ae235b
                    gboolean     accept_alternates)
Packit ae235b
{
Packit ae235b
  gchar **alternates = NULL;
Packit ae235b
  gchar **term_tokens;
Packit ae235b
  gchar **hit_tokens;
Packit ae235b
  gboolean matched;
Packit ae235b
  gint i, j;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (search_term != NULL, FALSE);
Packit ae235b
  g_return_val_if_fail (potential_hit != NULL, FALSE);
Packit ae235b
Packit ae235b
  term_tokens = g_str_tokenize_and_fold (search_term, NULL, NULL);
Packit ae235b
  hit_tokens = g_str_tokenize_and_fold (potential_hit, NULL, accept_alternates ? &alternates : NULL);
Packit ae235b
Packit ae235b
  matched = TRUE;
Packit ae235b
Packit ae235b
  for (i = 0; term_tokens[i]; i++)
Packit ae235b
    {
Packit ae235b
      for (j = 0; hit_tokens[j]; j++)
Packit ae235b
        if (g_str_has_prefix (hit_tokens[j], term_tokens[i]))
Packit ae235b
          goto one_matched;
Packit ae235b
Packit ae235b
      if (accept_alternates)
Packit ae235b
        for (j = 0; alternates[j]; j++)
Packit ae235b
          if (g_str_has_prefix (alternates[j], term_tokens[i]))
Packit ae235b
            goto one_matched;
Packit ae235b
Packit ae235b
      matched = FALSE;
Packit ae235b
      break;
Packit ae235b
Packit ae235b
one_matched:
Packit ae235b
      continue;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  g_strfreev (term_tokens);
Packit ae235b
  g_strfreev (hit_tokens);
Packit ae235b
  g_strfreev (alternates);
Packit ae235b
Packit ae235b
  return matched;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_strv_contains:
Packit ae235b
 * @strv: a %NULL-terminated array of strings
Packit ae235b
 * @str: a string
Packit ae235b
 *
Packit ae235b
 * Checks if @strv contains @str. @strv must not be %NULL.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @str is an element of @strv, according to g_str_equal().
Packit ae235b
 *
Packit ae235b
 * Since: 2.44
Packit ae235b
 */
Packit ae235b
gboolean
Packit ae235b
g_strv_contains (const gchar * const *strv,
Packit ae235b
                 const gchar         *str)
Packit ae235b
{
Packit ae235b
  g_return_val_if_fail (strv != NULL, FALSE);
Packit ae235b
  g_return_val_if_fail (str != NULL, FALSE);
Packit ae235b
Packit ae235b
  for (; *strv != NULL; strv++)
Packit ae235b
    {
Packit ae235b
      if (g_str_equal (str, *strv))
Packit ae235b
        return TRUE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  return FALSE;
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
str_has_sign (const gchar *str)
Packit ae235b
{
Packit ae235b
  return str[0] == '-' || str[0] == '+';
Packit ae235b
}
Packit ae235b
Packit ae235b
static gboolean
Packit ae235b
str_has_hex_prefix (const gchar *str)
Packit ae235b
{
Packit ae235b
  return str[0] == '0' && g_ascii_tolower (str[1]) == 'x';
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_string_to_signed:
Packit ae235b
 * @str: a string
Packit ae235b
 * @base: base of a parsed number
Packit ae235b
 * @min: a lower bound (inclusive)
Packit ae235b
 * @max: an upper bound (inclusive)
Packit ae235b
 * @out_num: (out) (optional): a return location for a number
Packit ae235b
 * @error: a return location for #GError
Packit ae235b
 *
Packit ae235b
 * A convenience function for converting a string to a signed number.
Packit ae235b
 *
Packit ae235b
 * This function assumes that @str contains only a number of the given
Packit ae235b
 * @base that is within inclusive bounds limited by @min and @max. If
Packit ae235b
 * this is true, then the converted number is stored in @out_num. An
Packit ae235b
 * empty string is not a valid input. A string with leading or
Packit ae235b
 * trailing whitespace is also an invalid input.
Packit ae235b
 *
Packit ae235b
 * @base can be between 2 and 36 inclusive. Hexadecimal numbers must
Packit ae235b
 * not be prefixed with "0x" or "0X". Such a problem does not exist
Packit ae235b
 * for octal numbers, since they were usually prefixed with a zero
Packit ae235b
 * which does not change the value of the parsed number.
Packit ae235b
 *
Packit ae235b
 * Parsing failures result in an error with the %G_NUMBER_PARSER_ERROR
Packit ae235b
 * domain. If the input is invalid, the error code will be
Packit ae235b
 * %G_NUMBER_PARSER_ERROR_INVALID. If the parsed number is out of
Packit ae235b
 * bounds - %G_NUMBER_PARSER_ERROR_OUT_OF_BOUNDS.
Packit ae235b
 *
Packit ae235b
 * See g_ascii_strtoll() if you have more complex needs such as
Packit ae235b
 * parsing a string which starts with a number, but then has other
Packit ae235b
 * characters.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @str was a number, otherwise %FALSE.
Packit ae235b
 *
Packit ae235b
 * Since: 2.54
Packit ae235b
 */
Packit ae235b
gboolean
Packit ae235b
g_ascii_string_to_signed (const gchar  *str,
Packit ae235b
                          guint         base,
Packit ae235b
                          gint64        min,
Packit ae235b
                          gint64        max,
Packit ae235b
                          gint64       *out_num,
Packit ae235b
                          GError      **error)
Packit ae235b
{
Packit ae235b
  gint64 number;
Packit ae235b
  const gchar *end_ptr = NULL;
Packit ae235b
  gint saved_errno = 0;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (str != NULL, FALSE);
Packit ae235b
  g_return_val_if_fail (base >= 2 && base <= 36, FALSE);
Packit ae235b
  g_return_val_if_fail (min <= max, FALSE);
Packit ae235b
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
Packit ae235b
Packit ae235b
  if (str[0] == '\0')
Packit ae235b
    {
Packit ae235b
      g_set_error_literal (error,
Packit ae235b
                           G_NUMBER_PARSER_ERROR, G_NUMBER_PARSER_ERROR_INVALID,
Packit ae235b
                           _("Empty string is not a number"));
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  errno = 0;
Packit ae235b
  number = g_ascii_strtoll (str, (gchar **)&end_ptr, base);
Packit ae235b
  saved_errno = errno;
Packit ae235b
Packit ae235b
  if (/* We do not allow leading whitespace, but g_ascii_strtoll
Packit ae235b
       * accepts it and just skips it, so we need to check for it
Packit ae235b
       * ourselves.
Packit ae235b
       */
Packit ae235b
      g_ascii_isspace (str[0]) ||
Packit ae235b
      /* We don't support hexadecimal numbers prefixed with 0x or
Packit ae235b
       * 0X.
Packit ae235b
       */
Packit ae235b
      (base == 16 &&
Packit ae235b
       (str_has_sign (str) ? str_has_hex_prefix (str + 1) : str_has_hex_prefix (str))) ||
Packit ae235b
      (saved_errno != 0 && saved_errno != ERANGE) ||
Packit ae235b
      end_ptr == NULL ||
Packit ae235b
      *end_ptr != '\0')
Packit ae235b
    {
Packit ae235b
      g_set_error (error,
Packit ae235b
                   G_NUMBER_PARSER_ERROR, G_NUMBER_PARSER_ERROR_INVALID,
Packit ae235b
                   _("“%s” is not a signed number"), str);
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
  if (saved_errno == ERANGE || number < min || number > max)
Packit ae235b
    {
Packit ae235b
      gchar *min_str = g_strdup_printf ("%" G_GINT64_FORMAT, min);
Packit ae235b
      gchar *max_str = g_strdup_printf ("%" G_GINT64_FORMAT, max);
Packit ae235b
Packit ae235b
      g_set_error (error,
Packit ae235b
                   G_NUMBER_PARSER_ERROR, G_NUMBER_PARSER_ERROR_OUT_OF_BOUNDS,
Packit ae235b
                   _("Number “%s” is out of bounds [%s, %s]"),
Packit ae235b
                   str, min_str, max_str);
Packit ae235b
      g_free (min_str);
Packit ae235b
      g_free (max_str);
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
  if (out_num != NULL)
Packit ae235b
    *out_num = number;
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
/**
Packit ae235b
 * g_ascii_string_to_unsigned:
Packit ae235b
 * @str: a string
Packit ae235b
 * @base: base of a parsed number
Packit ae235b
 * @min: a lower bound (inclusive)
Packit ae235b
 * @max: an upper bound (inclusive)
Packit ae235b
 * @out_num: (out) (optional): a return location for a number
Packit ae235b
 * @error: a return location for #GError
Packit ae235b
 *
Packit ae235b
 * A convenience function for converting a string to an unsigned number.
Packit ae235b
 *
Packit ae235b
 * This function assumes that @str contains only a number of the given
Packit ae235b
 * @base that is within inclusive bounds limited by @min and @max. If
Packit ae235b
 * this is true, then the converted number is stored in @out_num. An
Packit ae235b
 * empty string is not a valid input. A string with leading or
Packit ae235b
 * trailing whitespace is also an invalid input.
Packit ae235b
 *
Packit ae235b
 * @base can be between 2 and 36 inclusive. Hexadecimal numbers must
Packit ae235b
 * not be prefixed with "0x" or "0X". Such a problem does not exist
Packit ae235b
 * for octal numbers, since they were usually prefixed with a zero
Packit ae235b
 * which does not change the value of the parsed number.
Packit ae235b
 *
Packit ae235b
 * Parsing failures result in an error with the %G_NUMBER_PARSER_ERROR
Packit ae235b
 * domain. If the input is invalid, the error code will be
Packit ae235b
 * %G_NUMBER_PARSER_ERROR_INVALID. If the parsed number is out of
Packit ae235b
 * bounds - %G_NUMBER_PARSER_ERROR_OUT_OF_BOUNDS.
Packit ae235b
 *
Packit ae235b
 * See g_ascii_strtoull() if you have more complex needs such as
Packit ae235b
 * parsing a string which starts with a number, but then has other
Packit ae235b
 * characters.
Packit ae235b
 *
Packit ae235b
 * Returns: %TRUE if @str was a number, otherwise %FALSE.
Packit ae235b
 *
Packit ae235b
 * Since: 2.54
Packit ae235b
 */
Packit ae235b
gboolean
Packit ae235b
g_ascii_string_to_unsigned (const gchar  *str,
Packit ae235b
                            guint         base,
Packit ae235b
                            guint64       min,
Packit ae235b
                            guint64       max,
Packit ae235b
                            guint64      *out_num,
Packit ae235b
                            GError      **error)
Packit ae235b
{
Packit ae235b
  guint64 number;
Packit ae235b
  const gchar *end_ptr = NULL;
Packit ae235b
  gint saved_errno = 0;
Packit ae235b
Packit ae235b
  g_return_val_if_fail (str != NULL, FALSE);
Packit ae235b
  g_return_val_if_fail (base >= 2 && base <= 36, FALSE);
Packit ae235b
  g_return_val_if_fail (min <= max, FALSE);
Packit ae235b
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
Packit ae235b
Packit ae235b
  if (str[0] == '\0')
Packit ae235b
    {
Packit ae235b
      g_set_error_literal (error,
Packit ae235b
                           G_NUMBER_PARSER_ERROR, G_NUMBER_PARSER_ERROR_INVALID,
Packit ae235b
                           _("Empty string is not a number"));
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
Packit ae235b
  errno = 0;
Packit ae235b
  number = g_ascii_strtoull (str, (gchar **)&end_ptr, base);
Packit ae235b
  saved_errno = errno;
Packit ae235b
Packit ae235b
  if (/* We do not allow leading whitespace, but g_ascii_strtoull
Packit ae235b
       * accepts it and just skips it, so we need to check for it
Packit ae235b
       * ourselves.
Packit ae235b
       */
Packit ae235b
      g_ascii_isspace (str[0]) ||
Packit ae235b
      /* Unsigned number should have no sign.
Packit ae235b
       */
Packit ae235b
      str_has_sign (str) ||
Packit ae235b
      /* We don't support hexadecimal numbers prefixed with 0x or
Packit ae235b
       * 0X.
Packit ae235b
       */
Packit ae235b
      (base == 16 && str_has_hex_prefix (str)) ||
Packit ae235b
      (saved_errno != 0 && saved_errno != ERANGE) ||
Packit ae235b
      end_ptr == NULL ||
Packit ae235b
      *end_ptr != '\0')
Packit ae235b
    {
Packit ae235b
      g_set_error (error,
Packit ae235b
                   G_NUMBER_PARSER_ERROR, G_NUMBER_PARSER_ERROR_INVALID,
Packit ae235b
                   _("“%s” is not an unsigned number"), str);
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
  if (saved_errno == ERANGE || number < min || number > max)
Packit ae235b
    {
Packit ae235b
      gchar *min_str = g_strdup_printf ("%" G_GUINT64_FORMAT, min);
Packit ae235b
      gchar *max_str = g_strdup_printf ("%" G_GUINT64_FORMAT, max);
Packit ae235b
Packit ae235b
      g_set_error (error,
Packit ae235b
                   G_NUMBER_PARSER_ERROR, G_NUMBER_PARSER_ERROR_OUT_OF_BOUNDS,
Packit ae235b
                   _("Number “%s” is out of bounds [%s, %s]"),
Packit ae235b
                   str, min_str, max_str);
Packit ae235b
      g_free (min_str);
Packit ae235b
      g_free (max_str);
Packit ae235b
      return FALSE;
Packit ae235b
    }
Packit ae235b
  if (out_num != NULL)
Packit ae235b
    *out_num = number;
Packit ae235b
  return TRUE;
Packit ae235b
}
Packit ae235b
Packit ae235b
G_DEFINE_QUARK (g-number-parser-error-quark, g_number_parser_error)