From f650a78e8b5b3c9e72431829e2a71820480a80f0 Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Sat, 12 Oct 2002 19:37:48 +0000 Subject: [PATCH] fix comment. (g_ascii_strtoull): new function, acting like strtoull(3) in Sat Oct 12 21:30:41 2002 Tim Janik * 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 | 12 +++++ ChangeLog.pre-2-10 | 12 +++++ ChangeLog.pre-2-12 | 12 +++++ ChangeLog.pre-2-2 | 12 +++++ ChangeLog.pre-2-4 | 12 +++++ ChangeLog.pre-2-6 | 12 +++++ ChangeLog.pre-2-8 | 12 +++++ glib/gscanner.c | 74 ++++++++++++++------------ glib/gscanner.h | 2 + glib/gstrfuncs.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++- glib/gstrfuncs.h | 3 ++ 11 files changed, 280 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9161c67..9610996 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Sat Oct 12 21:30:41 2002 Tim Janik + + * 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 * glib/gtree.c (g_tree_search), glib/gspawn.c diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 9161c67..9610996 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,15 @@ +Sat Oct 12 21:30:41 2002 Tim Janik + + * 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 * glib/gtree.c (g_tree_search), glib/gspawn.c diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 9161c67..9610996 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,15 @@ +Sat Oct 12 21:30:41 2002 Tim Janik + + * 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 * glib/gtree.c (g_tree_search), glib/gspawn.c diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 9161c67..9610996 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,15 @@ +Sat Oct 12 21:30:41 2002 Tim Janik + + * 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 * glib/gtree.c (g_tree_search), glib/gspawn.c diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 9161c67..9610996 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,15 @@ +Sat Oct 12 21:30:41 2002 Tim Janik + + * 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 * glib/gtree.c (g_tree_search), glib/gspawn.c diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 9161c67..9610996 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,15 @@ +Sat Oct 12 21:30:41 2002 Tim Janik + + * 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 * glib/gtree.c (g_tree_search), glib/gspawn.c diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 9161c67..9610996 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,15 @@ +Sat Oct 12 21:30:41 2002 Tim Janik + + * 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 * glib/gtree.c (g_tree_search), glib/gspawn.c diff --git a/glib/gscanner.c b/glib/gscanner.c index e09e63e..8055abf 100644 --- a/glib/gscanner.c +++ b/glib/gscanner.c @@ -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) { diff --git a/glib/gscanner.h b/glib/gscanner.h index f6b471d..afed198 100644 --- a/glib/gscanner.h +++ b/glib/gscanner.h @@ -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; }; diff --git a/glib/gstrfuncs.c b/glib/gstrfuncs.c index 6b5bbb1..cdea7f8 100644 --- a/glib/gstrfuncs.c +++ b/glib/gstrfuncs.c @@ -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) diff --git a/glib/gstrfuncs.h b/glib/gstrfuncs.h index 40c249a..4b182c4 100644 --- a/glib/gstrfuncs.h +++ b/glib/gstrfuncs.h @@ -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 */ -- 2.7.4