g_ascii_strtoll
authorMatthias Clasen <matthiasc@src.gnome.org>
Tue, 16 May 2006 05:49:46 +0000 (05:49 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Tue, 16 May 2006 05:49:46 +0000 (05:49 +0000)
ChangeLog
ChangeLog.pre-2-12
docs/reference/ChangeLog
docs/reference/glib/glib-sections.txt
glib/glib.symbols
glib/gstrfuncs.c
glib/gstrfuncs.h
tests/Makefile.am
tests/strtoll-test.c [new file with mode: 0644]

index ef00354..d8652f5 100644 (file)
--- a/ChangeLog
+++ b/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
index ef00354..d8652f5 100644 (file)
@@ -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
index 11e766f..b8b1f6f 100644 (file)
@@ -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 ===
index 687847b..aa64591 100644 (file)
@@ -1119,6 +1119,7 @@ g_strncasecmp
 g_strreverse
 
 <SUBSECTION>
+g_ascii_strtoll
 g_ascii_strtoull
 G_ASCII_DTOSTR_BUF_SIZE
 g_ascii_strtod
index 61f33e4..62e2a10 100644 (file)
@@ -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
index d7db600..260853a 100644 (file)
@@ -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.
@@ -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;
@@ -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 == '+')
@@ -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
@@ -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)
index 9c41dca..15803be 100644 (file)
@@ -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 */
index a4d5e74..b731aff 100644 (file)
@@ -100,6 +100,7 @@ test_programs =                                     \
        strfunc-test                            \
        string-test                             \
        strtod-test                             \
+       strtoll-test                            \
        thread-test                             \
        threadpool-test                         \
        tree-test                               \
@@ -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)
diff --git a/tests/strtoll-test.c b/tests/strtoll-test.c
new file mode 100644 (file)
index 0000000..6c1de3f
--- /dev/null
@@ -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;
+}