+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
+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
+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
+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
+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
+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
+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
};
-
/* --- variables --- */
static GScannerConfig g_scanner_config_template =
{
TRUE /* char_2_token */,
FALSE /* symbol_2_token */,
FALSE /* scope_0_fallback */,
+ FALSE /* store_int64 */,
};
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;
{
GTokenValue v;
- v.v_int = 0;
+ v.v_int64 = 0;
g_return_val_if_fail (scanner != NULL, v);
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;
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;
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:
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;
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)
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 ;(
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)
{
gulong v_binary;
gulong v_octal;
gulong v_int;
+ guint64 v_int64;
gdouble v_float;
gulong v_hex;
gchar *v_string;
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;
};
* 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.
*
return val;
}
+
/**
* g_ascii_dtostr:
* @buffer: A buffer to place the resulting string in
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)
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 */