Skip to content
This repository has been archived by the owner on Nov 17, 2020. It is now read-only.

Commit

Permalink
g_ascii_strtoll
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Clasen committed May 16, 2006
1 parent 503db3a commit 49ab402
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 40 deletions.
15 changes: 15 additions & 0 deletions ChangeLog
@@ -1,3 +1,18 @@
2006-05-16 Matthias Clasen <mclasen@redhat.com>

* tests/Makefile.am:
* tests/strtoll-test.c: Add tests for g_ascii_strtoll()
and g_ascii_strtoull().

* glib/glib.symbols:
* glib/gstrfuncs.h:
* glib/gstrfuncs.c (g_ascii_strtoll): New function to
parse signed 64bit integers like strtoll does.

* glib/goption.c (parse_int64): Use g_ascii_strtoll(),
since strtoll() is C99 and not available on some
systems. (#341826, Kazuki Iwamoto)

2006-05-15 Matthias Clasen <mclasen@redhat.com>

* configure.in: Bump version
Expand Down
15 changes: 15 additions & 0 deletions ChangeLog.pre-2-12
@@ -1,3 +1,18 @@
2006-05-16 Matthias Clasen <mclasen@redhat.com>

* tests/Makefile.am:
* tests/strtoll-test.c: Add tests for g_ascii_strtoll()
and g_ascii_strtoull().

* glib/glib.symbols:
* glib/gstrfuncs.h:
* glib/gstrfuncs.c (g_ascii_strtoll): New function to
parse signed 64bit integers like strtoll does.

* glib/goption.c (parse_int64): Use g_ascii_strtoll(),
since strtoll() is C99 and not available on some
systems. (#341826, Kazuki Iwamoto)

2006-05-15 Matthias Clasen <mclasen@redhat.com>

* configure.in: Bump version
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/ChangeLog
@@ -1,3 +1,7 @@
2006-05-16 Matthias Clasen <mclasen@redhat.com>

* glib/glib-sections.txt: Add g_ascii_strtoll

2006-05-15 Matthias Clasen <mclasen@redhat.com>

* === Released 2.11.1 ===
Expand Down
1 change: 1 addition & 0 deletions docs/reference/glib/glib-sections.txt
Expand Up @@ -1119,6 +1119,7 @@ g_strncasecmp
g_strreverse

<SUBSECTION>
g_ascii_strtoll
g_ascii_strtoull
G_ASCII_DTOSTR_BUF_SIZE
g_ascii_strtod
Expand Down
1 change: 1 addition & 0 deletions glib/glib.symbols
Expand Up @@ -1012,6 +1012,7 @@ g_ascii_formatd
g_ascii_strdown G_GNUC_MALLOC
g_ascii_strtod
g_ascii_strtoull
g_ascii_strtoll
g_ascii_strup G_GNUC_MALLOC
g_ascii_tolower G_GNUC_CONST
g_ascii_toupper G_GNUC_CONST
Expand Down
146 changes: 106 additions & 40 deletions glib/gstrfuncs.c
Expand Up @@ -591,38 +591,11 @@ g_ascii_formatd (gchar *buffer,
return buffer;
}

/**
* g_ascii_strtoull:
* @nptr: the string to convert to a numeric value.
* @endptr: if non-%NULL, it returns the character after
* the last character used in the conversion.
* @base: to be used for the conversion, 2..36 or 0
*
* Converts a string to a #guint64 value.
* This function behaves like the standard strtoull() function
* does in the C locale. It does this without actually
* changing the current locale, since that would not be
* thread-safe.
*
* This function is typically used when reading configuration
* files or other non-user input that should be locale independent.
* To handle input from the user you should normally use the
* locale-sensitive system strtoull() function.
*
* If the correct value would cause overflow, %G_MAXUINT64
* is returned, and %ERANGE is stored in %errno. If the base is
* outside the valid range, zero is returned, and %EINVAL is stored
* in %errno. If the string conversion fails, zero is returned, and
* @endptr returns @nptr (if @endptr is non-%NULL).
*
* Return value: the #guint64 value or zero on error.
*
* Since: 2.2
**/
guint64
g_ascii_strtoull (const gchar *nptr,
gchar **endptr,
guint base)
static guint64
g_parse_long_long (const gchar *nptr,
gchar **endptr,
guint base,
gboolean *negative)
{
/* this code is based on on the strtol(3) code from GNU libc released under
* the GNU Lesser General Public License.
Expand All @@ -637,7 +610,7 @@ g_ascii_strtoull (const gchar *nptr,
#define ISALPHA(c) (ISUPPER (c) || ISLOWER (c))
#define TOUPPER(c) (ISLOWER (c) ? (c) - 'a' + 'A' : (c))
#define TOLOWER(c) (ISUPPER (c) ? (c) - 'A' + 'a' : (c))
gboolean negative, overflow;
gboolean overflow;
guint64 cutoff;
guint64 cutlim;
guint64 ui64;
Expand All @@ -657,14 +630,15 @@ g_ascii_strtoull (const gchar *nptr,
/* Skip white space. */
while (ISSPACE (*s))
++s;
if (!*s)

if (G_UNLIKELY (!*s))
goto noconv;

/* Check for a sign. */
negative = FALSE;
*negative = FALSE;
if (*s == '-')
{
negative = TRUE;
*negative = TRUE;
++s;
}
else if (*s == '+')
Expand Down Expand Up @@ -721,14 +695,13 @@ g_ascii_strtoull (const gchar *nptr,
if (endptr)
*endptr = (gchar*) s;

if (overflow)
if (G_UNLIKELY (overflow))
{
errno = ERANGE;
return G_MAXUINT64;
}

/* Return the result of the appropriate sign. */
return negative ? -ui64 : ui64;

return ui64;

noconv:
/* We must handle a special case here: the base is 0 or 16 and the
Expand All @@ -747,6 +720,99 @@ g_ascii_strtoull (const gchar *nptr,
return 0;
}

/**
* g_ascii_strtoull:
* @nptr: the string to convert to a numeric value.
* @endptr: if non-%NULL, it returns the character after
* the last character used in the conversion.
* @base: to be used for the conversion, 2..36 or 0
*
* Converts a string to a #guint64 value.
* This function behaves like the standard strtoull() function
* does in the C locale. It does this without actually
* changing the current locale, since that would not be
* thread-safe.
*
* This function is typically used when reading configuration
* files or other non-user input that should be locale independent.
* To handle input from the user you should normally use the
* locale-sensitive system strtoull() function.
*
* If the correct value would cause overflow, %G_MAXUINT64
* is returned, and %ERANGE is stored in %errno. If the base is
* outside the valid range, zero is returned, and %EINVAL is stored
* in %errno. If the string conversion fails, zero is returned, and
* @endptr returns @nptr (if @endptr is non-%NULL).
*
* Return value: the #guint64 value or zero on error.
*
* Since: 2.2
**/
guint64
g_ascii_strtoull (const gchar *nptr,
gchar **endptr,
guint base)
{
gboolean negative;
guint64 result;

result = g_parse_long_long (nptr, endptr, base, &negative);

/* Return the result of the appropriate sign. */
return negative ? -result : result;
}

/**
* g_ascii_strtoll:
* @nptr: the string to convert to a numeric value.
* @endptr: if non-%NULL, it returns the character after
* the last character used in the conversion.
* @base: to be used for the conversion, 2..36 or 0
*
* Converts a string to a #gint64 value.
* This function behaves like the standard strtoll() function
* does in the C locale. It does this without actually
* changing the current locale, since that would not be
* thread-safe.
*
* This function is typically used when reading configuration
* files or other non-user input that should be locale independent.
* To handle input from the user you should normally use the
* locale-sensitive system strtoll() function.
*
* If the correct value would cause overflow, %G_MAXINT64 or %G_MININT64
* is returned, and %ERANGE is stored in %errno. If the base is
* outside the valid range, zero is returned, and %EINVAL is stored
* in %errno. If the string conversion fails, zero is returned, and
* @endptr returns @nptr (if @endptr is non-%NULL).
*
* Return value: the #gint64 value or zero on error.
*
* Since: 2.12
**/
gint64
g_ascii_strtoll (const gchar *nptr,
gchar **endptr,
guint base)
{
gboolean negative;
guint64 result;

result = g_parse_long_long (nptr, endptr, base, &negative);

if (negative && result > (guint64) G_MININT64)
{
errno = ERANGE;
return G_MININT64;
}
else if (!negative && result > (guint64) G_MAXINT64)
{
errno = ERANGE;
return G_MAXINT64;
}
else
return (gint64) result;
}

G_CONST_RETURN gchar*
g_strerror (gint errnum)
Expand Down
3 changes: 3 additions & 0 deletions glib/gstrfuncs.h
Expand Up @@ -130,6 +130,9 @@ gdouble g_ascii_strtod (const gchar *nptr,
guint64 g_ascii_strtoull (const gchar *nptr,
gchar **endptr,
guint base);
gint64 g_ascii_strtoll (const gchar *nptr,
gchar **endptr,
guint base);
/* 29 bytes should enough for all possible values that
* g_ascii_dtostr can produce.
* Then add 10 for good measure */
Expand Down
2 changes: 2 additions & 0 deletions tests/Makefile.am
Expand Up @@ -100,6 +100,7 @@ test_programs = \
strfunc-test \
string-test \
strtod-test \
strtoll-test \
thread-test \
threadpool-test \
tree-test \
Expand Down Expand Up @@ -166,6 +167,7 @@ spawn_test_LDADD = $(progs_ldadd)
strfunc_test_LDADD = $(progs_ldadd)
string_test_LDADD = $(progs_ldadd)
strtod_test_LDADD = $(progs_ldadd) -lm
strtoll_test_LDADD = $(progs_ldadd) -lm
thread_test_LDADD = $(thread_ldadd)
threadpool_test_LDADD = $(thread_ldadd)
tree_test_LDADD = $(progs_ldadd)
Expand Down
67 changes: 67 additions & 0 deletions tests/strtoll-test.c
@@ -0,0 +1,67 @@
#undef G_DISABLE_ASSERT
#undef G_LOG_DOMAIN

#include <errno.h>
#include <string.h>
#include <glib.h>


static void
test_uint64 (const gchar *str,
const gchar *end,
gint base,
guint64 result,
gint error)
{
guint64 actual;
gchar *endptr = NULL;
gint err;

errno = 0;
actual = g_ascii_strtoull (str, &endptr, base);
err = errno;

g_assert (actual == result);
g_assert (strcmp (end, endptr) == 0);
g_assert (err == error);
}

static void
test_int64 (const gchar *str,
const gchar *end,
gint base,
gint64 result,
gint error)
{
gint64 actual;
gchar *endptr = NULL;
gint err;

errno = 0;
actual = g_ascii_strtoll (str, &endptr, base);
err = errno;

g_assert (actual == result);
g_assert (strcmp (end, endptr) == 0);
g_assert (err == error);
}

int
main (int argc, char *argv[])
{
test_uint64 ("0", "", 10, 0, 0);
test_uint64 ("+0", "", 10, 0, 0);
test_uint64 ("-0", "", 10, 0, 0);
test_uint64 ("18446744073709551615", "", 10, G_MAXUINT64, 0);
test_uint64 ("18446744073709551616", "", 10, G_MAXUINT64, ERANGE);
test_uint64 ("20xyz", "xyz", 10, 20, 0);
test_uint64 ("-1", "", 10, G_MAXUINT64, 0);

test_int64 ("0", "", 10, 0, 0);
test_int64 ("9223372036854775807", "", 10, G_MAXINT64, 0);
test_int64 ("9223372036854775808", "", 10, G_MAXINT64, ERANGE);
test_int64 ("-9223372036854775808", "", 10, G_MININT64, 0);
test_int64 ("-9223372036854775809", "", 10, G_MININT64, ERANGE);

return 0;
}

0 comments on commit 49ab402

Please sign in to comment.