fix comment. (g_ascii_strtoull): new function, acting like strtoull(3) in
authorTim Janik <timj@gtk.org>
Sat, 12 Oct 2002 19:37:48 +0000 (19:37 +0000)
committerTim Janik <timj@src.gnome.org>
Sat, 12 Oct 2002 19:37:48 +0000 (19:37 +0000)
Sat Oct 12 21:30:41 2002  Tim Janik  <timj@gtk.org>

        * merged up from glib-2-0:

        * glib/gstrfuncs.c (g_ascii_strtod): fix comment.
        (g_ascii_strtoull): new function, acting like strtoull(3) in the C
        locale.

        * glib/gscanner.[hc]: fix 32bit issues with integer parsing and
        support storing 64bit values in GTokenValue by
        using g_ascii_strtoull().

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
glib/gscanner.c
glib/gscanner.h
glib/gstrfuncs.c
glib/gstrfuncs.h

index 9161c67..9610996 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+Sat Oct 12 21:30:41 2002  Tim Janik  <timj@gtk.org>
+
+       * merged up from glib-2-0:
+
+        * glib/gstrfuncs.c (g_ascii_strtod): fix comment.
+        (g_ascii_strtoull): new function, acting like strtoull(3) in the C
+        locale.
+
+        * glib/gscanner.[hc]: fix 32bit issues with integer parsing and
+        support storing 64bit values in GTokenValue by
+        using g_ascii_strtoull().
+
 Sat Oct 12 12:34:22 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * glib/gtree.c (g_tree_search), glib/gspawn.c
index 9161c67..9610996 100644 (file)
@@ -1,3 +1,15 @@
+Sat Oct 12 21:30:41 2002  Tim Janik  <timj@gtk.org>
+
+       * merged up from glib-2-0:
+
+        * glib/gstrfuncs.c (g_ascii_strtod): fix comment.
+        (g_ascii_strtoull): new function, acting like strtoull(3) in the C
+        locale.
+
+        * glib/gscanner.[hc]: fix 32bit issues with integer parsing and
+        support storing 64bit values in GTokenValue by
+        using g_ascii_strtoull().
+
 Sat Oct 12 12:34:22 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * glib/gtree.c (g_tree_search), glib/gspawn.c
index 9161c67..9610996 100644 (file)
@@ -1,3 +1,15 @@
+Sat Oct 12 21:30:41 2002  Tim Janik  <timj@gtk.org>
+
+       * merged up from glib-2-0:
+
+        * glib/gstrfuncs.c (g_ascii_strtod): fix comment.
+        (g_ascii_strtoull): new function, acting like strtoull(3) in the C
+        locale.
+
+        * glib/gscanner.[hc]: fix 32bit issues with integer parsing and
+        support storing 64bit values in GTokenValue by
+        using g_ascii_strtoull().
+
 Sat Oct 12 12:34:22 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * glib/gtree.c (g_tree_search), glib/gspawn.c
index 9161c67..9610996 100644 (file)
@@ -1,3 +1,15 @@
+Sat Oct 12 21:30:41 2002  Tim Janik  <timj@gtk.org>
+
+       * merged up from glib-2-0:
+
+        * glib/gstrfuncs.c (g_ascii_strtod): fix comment.
+        (g_ascii_strtoull): new function, acting like strtoull(3) in the C
+        locale.
+
+        * glib/gscanner.[hc]: fix 32bit issues with integer parsing and
+        support storing 64bit values in GTokenValue by
+        using g_ascii_strtoull().
+
 Sat Oct 12 12:34:22 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * glib/gtree.c (g_tree_search), glib/gspawn.c
index 9161c67..9610996 100644 (file)
@@ -1,3 +1,15 @@
+Sat Oct 12 21:30:41 2002  Tim Janik  <timj@gtk.org>
+
+       * merged up from glib-2-0:
+
+        * glib/gstrfuncs.c (g_ascii_strtod): fix comment.
+        (g_ascii_strtoull): new function, acting like strtoull(3) in the C
+        locale.
+
+        * glib/gscanner.[hc]: fix 32bit issues with integer parsing and
+        support storing 64bit values in GTokenValue by
+        using g_ascii_strtoull().
+
 Sat Oct 12 12:34:22 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * glib/gtree.c (g_tree_search), glib/gspawn.c
index 9161c67..9610996 100644 (file)
@@ -1,3 +1,15 @@
+Sat Oct 12 21:30:41 2002  Tim Janik  <timj@gtk.org>
+
+       * merged up from glib-2-0:
+
+        * glib/gstrfuncs.c (g_ascii_strtod): fix comment.
+        (g_ascii_strtoull): new function, acting like strtoull(3) in the C
+        locale.
+
+        * glib/gscanner.[hc]: fix 32bit issues with integer parsing and
+        support storing 64bit values in GTokenValue by
+        using g_ascii_strtoull().
+
 Sat Oct 12 12:34:22 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * glib/gtree.c (g_tree_search), glib/gspawn.c
index 9161c67..9610996 100644 (file)
@@ -1,3 +1,15 @@
+Sat Oct 12 21:30:41 2002  Tim Janik  <timj@gtk.org>
+
+       * merged up from glib-2-0:
+
+        * glib/gstrfuncs.c (g_ascii_strtod): fix comment.
+        (g_ascii_strtoull): new function, acting like strtoull(3) in the C
+        locale.
+
+        * glib/gscanner.[hc]: fix 32bit issues with integer parsing and
+        support storing 64bit values in GTokenValue by
+        using g_ascii_strtoull().
+
 Sat Oct 12 12:34:22 2002  Soeren Sandmann  <sandmann@daimi.au.dk>
 
        * glib/gtree.c (g_tree_search), glib/gspawn.c
index e09e63e..8055abf 100644 (file)
@@ -71,7 +71,6 @@ struct        _GScannerKey
 };
 
 
-
 /* --- variables --- */
 static GScannerConfig g_scanner_config_template =
 {
@@ -115,6 +114,7 @@ static GScannerConfig g_scanner_config_template =
   TRUE                 /* char_2_token */,
   FALSE                        /* symbol_2_token */,
   FALSE                        /* scope_0_fallback */,
+  FALSE                        /* store_int64 */,
 };
 
 
@@ -211,14 +211,15 @@ g_scanner_new (const GScannerConfig *config_templ)
   scanner->config->char_2_token                 = config_templ->char_2_token;
   scanner->config->symbol_2_token       = config_templ->symbol_2_token;
   scanner->config->scope_0_fallback     = config_templ->scope_0_fallback;
+  scanner->config->store_int64          = config_templ->store_int64;
   
   scanner->token = G_TOKEN_NONE;
-  scanner->value.v_int = 0;
+  scanner->value.v_int64 = 0;
   scanner->line = 1;
   scanner->position = 0;
   
   scanner->next_token = G_TOKEN_NONE;
-  scanner->next_value.v_int = 0;
+  scanner->next_value.v_int64 = 0;
   scanner->next_line = 1;
   scanner->next_position = 0;
   
@@ -608,7 +609,7 @@ g_scanner_cur_value (GScanner *scanner)
 {
   GTokenValue v;
   
-  v.v_int = 0;
+  v.v_int64 = 0;
   
   g_return_val_if_fail (scanner != NULL, v);
 
@@ -654,7 +655,7 @@ g_scanner_input_file (GScanner *scanner,
     g_scanner_sync_file_offset (scanner);
 
   scanner->token = G_TOKEN_NONE;
-  scanner->value.v_int = 0;
+  scanner->value.v_int64 = 0;
   scanner->line = 1;
   scanner->position = 0;
   scanner->next_token = G_TOKEN_NONE;
@@ -682,7 +683,7 @@ g_scanner_input_text (GScanner        *scanner,
     g_scanner_sync_file_offset (scanner);
 
   scanner->token = G_TOKEN_NONE;
-  scanner->value.v_int = 0;
+  scanner->value.v_int64 = 0;
   scanner->line = 1;
   scanner->position = 0;
   scanner->next_token = G_TOKEN_NONE;
@@ -956,7 +957,10 @@ g_scanner_unexp_token (GScanner            *scanner,
     case G_TOKEN_OCTAL:
     case G_TOKEN_INT:
     case G_TOKEN_HEX:
-      g_snprintf (token_string, token_string_len, "number `%ld'", scanner->value.v_int);
+      if (scanner->config->store_int64)
+       g_snprintf (token_string, token_string_len, "number `%llu'", scanner->value.v_int64);
+      else
+       g_snprintf (token_string, token_string_len, "number `%lu'", scanner->value.v_int);
       break;
       
     case G_TOKEN_FLOAT:
@@ -1189,7 +1193,10 @@ g_scanner_get_token_i (GScanner  *scanner,
       scanner->config->int_2_float)
     {
       *token_p = G_TOKEN_FLOAT;
-      value_p->v_float = value_p->v_int;
+      if (scanner->config->store_int64)
+       value_p->v_float = value_p->v_int64;
+      else
+       value_p->v_float = value_p->v_int;
     }
   
   errno = 0;
@@ -1213,7 +1220,7 @@ g_scanner_get_token_ll    (GScanner       *scanner,
   guchar          ch;
   
   config = scanner->config;
-  (*value_p).v_int = 0;
+  (*value_p).v_int64 = 0;
   
   if ((scanner->text >= scanner->text_end && scanner->input_fd < 0) ||
       scanner->token == G_TOKEN_EOF)
@@ -1234,7 +1241,7 @@ g_scanner_get_token_ll    (GScanner       *scanner,
       
       ch = g_scanner_get_char (scanner, line_p, position_p);
       
-      value.v_int = 0;
+      value.v_int64 = 0;
       token = G_TOKEN_NONE;
       
       /* this is *evil*, but needed ;(
@@ -1557,30 +1564,31 @@ g_scanner_get_token_ll  (GScanner       *scanner,
          while (in_number);
          
          endptr = NULL;
-         switch (token)
+         if (token == G_TOKEN_FLOAT)
+           value.v_float = g_strtod (gstring->str, &endptr);
+         else
            {
-           case G_TOKEN_BINARY:
-             value.v_binary = strtol (gstring->str, &endptr, 2);
-             break;
-             
-           case G_TOKEN_OCTAL:
-             value.v_octal = strtol (gstring->str, &endptr, 8);
-             break;
-             
-           case G_TOKEN_INT:
-             value.v_int = strtol (gstring->str, &endptr, 10);
-             break;
-             
-           case G_TOKEN_FLOAT:
-             value.v_float = g_strtod (gstring->str, &endptr);
-             break;
-             
-           case G_TOKEN_HEX:
-             value.v_hex = strtol (gstring->str, &endptr, 16);
-             break;
-             
-           default:
-             break;
+             guint64 ui64 = 0;
+             switch (token)
+               {
+               case G_TOKEN_BINARY:
+                 ui64 = g_ascii_strtoull (gstring->str, &endptr, 2);
+                 break;
+               case G_TOKEN_OCTAL:
+                 ui64 = g_ascii_strtoull (gstring->str, &endptr, 8);
+                 break;
+               case G_TOKEN_INT:
+                 ui64 = g_ascii_strtoull (gstring->str, &endptr, 10);
+                 break;
+               case G_TOKEN_HEX:
+                 ui64 = g_ascii_strtoull (gstring->str, &endptr, 16);
+                 break;
+               default: ;
+               }
+             if (scanner->config->store_int64)
+               value.v_int64 = ui64;
+             else
+               value.v_int = ui64;
            }
          if (endptr && *endptr)
            {
index f6b471d..afed198 100644 (file)
@@ -110,6 +110,7 @@ union       _GTokenValue
   gulong       v_binary;
   gulong       v_octal;
   gulong       v_int;
+  guint64       v_int64;
   gdouble      v_float;
   gulong       v_hex;
   gchar                *v_string;
@@ -154,6 +155,7 @@ struct      _GScannerConfig
   guint                char_2_token : 1;               /* return G_TOKEN_CHAR? */
   guint                symbol_2_token : 1;
   guint                scope_0_fallback : 1;           /* try scope 0 on lookups? */
+  guint                store_int64 : 1;                /* use value.v_int64 rather than v_int */
   guint                padding_dummy;
 };
 
index 6b5bbb1..cdea7f8 100644 (file)
@@ -321,7 +321,7 @@ g_strtod (const gchar *nptr,
  * thread-safe.
  *
  * This function is typically used when reading configuration
- * files or other non-user input that should be locale dependent.
+ * 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 strtod() function.
  *
@@ -464,6 +464,7 @@ g_ascii_strtod (const gchar *nptr,
   return val;
 }
 
+
 /**
  * g_ascii_dtostr:
  * @buffer: A buffer to place the resulting string in
@@ -579,6 +580,154 @@ 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 strtull() 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.
+ *
+ * Return value: the #guint64 value.
+ **/
+guint64
+g_ascii_strtoull (const gchar *nptr,
+                 gchar      **endptr,
+                 guint        base)
+{
+  /* this code is based on on the strtol(3) code from GLibC released under
+   * the GNU Lesser General Public License.
+   */
+#define ISSPACE(c)             ((c) == ' ' || (c) == '\f' || (c) == '\n' || \
+                                (c) == '\r' || (c) == '\t' || (c) == '\v')
+#define ISUPPER(c)             ((c) >= 'A' && (c) <= 'Z')
+#define ISLOWER(c)             ((c) >= 'a' && (c) <= 'z')
+#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;
+  guint64 cutoff;
+  guint64 cutlim;
+  guint64 ui64;
+  const gchar *s, *save;
+  guchar c;
+  
+  g_return_val_if_fail (nptr != NULL, 0);
+  
+  if (base == 1 || base > 36)
+    {
+      errno = EINVAL;
+      return 0;
+    }
+  
+  save = s = nptr;
+  
+  /* Skip white space.  */
+  while (ISSPACE (*s))
+    ++s;
+  if (!*s)
+    goto noconv;
+  
+  /* Check for a sign.  */
+  negative = FALSE;
+  if (*s == '-')
+    {
+      negative = TRUE;
+      ++s;
+    }
+  else if (*s == '+')
+    ++s;
+  
+  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
+  if (*s == '0')
+    {
+      if ((base == 0 || base == 16) && TOUPPER (s[1]) == 'X')
+       {
+         s += 2;
+         base = 16;
+       }
+      else if (base == 0)
+       base = 8;
+    }
+  else if (base == 0)
+    base = 10;
+  
+  /* Save the pointer so we can check later if anything happened.  */
+  save = s;
+  cutoff = G_MAXUINT64 / base;
+  cutlim = G_MAXUINT64 % base;
+  
+  overflow = FALSE;
+  ui64 = 0;
+  c = *s;
+  for (; c; c = *++s)
+    {
+      if (c >= '0' && c <= '9')
+       c -= '0';
+      else if (ISALPHA (c))
+       c = TOUPPER (c) - 'A' + 10;
+      else
+       break;
+      if (c >= base)
+       break;
+      /* Check for overflow.  */
+      if (ui64 > cutoff || (ui64 == cutoff && c > cutlim))
+       overflow = TRUE;
+      else
+       {
+         ui64 *= base;
+         ui64 += c;
+       }
+    }
+  
+  /* Check if anything actually happened.  */
+  if (s == save)
+    goto noconv;
+  
+  /* Store in ENDPTR the address of one character
+     past the last character we converted.  */
+  if (endptr)
+    *endptr = (gchar*) s;
+  
+  if (overflow)
+    {
+      errno = ERANGE;
+      return G_MAXUINT64;
+    }
+  
+  /* Return the result of the appropriate sign.  */
+  return negative ? -ui64 : ui64;
+  
+ noconv:
+  /* We must handle a special case here: the base is 0 or 16 and the
+     first two characters are '0' and 'x', but the rest are no
+     hexadecimal digits.  This is no error case.  We return 0 and
+     ENDPTR points to the `x`.  */
+  if (endptr)
+    {
+      if (save - nptr >= 2 && TOUPPER (save[-1]) == 'X'
+         && save[-2] == '0')
+       *endptr = (gchar*) &save[-1];
+      else
+       /*  There was no number to convert.  */
+       *endptr = (gchar*) nptr;
+    }
+  return 0;
+}
+
 
 G_CONST_RETURN gchar*
 g_strerror (gint errnum)
index 40c249a..4b182c4 100644 (file)
@@ -127,6 +127,9 @@ gdouble                   g_strtod         (const gchar  *nptr,
                                        gchar       **endptr);
 gdouble                      g_ascii_strtod   (const gchar  *nptr,
                                        gchar       **endptr);
+guint64                      g_ascii_strtoull (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 */