fix comment. (g_ascii_strtoull): new function, acting like strtoull(3) in

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().
This commit is contained in:
Tim Janik 2002-10-12 19:37:48 +00:00 committed by Tim Janik
parent 6b8ab1206e
commit f650a78e8b
11 changed files with 280 additions and 34 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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,6 +1193,9 @@ g_scanner_get_token_i (GScanner *scanner,
scanner->config->int_2_float)
{
*token_p = G_TOKEN_FLOAT;
if (scanner->config->store_int64)
value_p->v_float = value_p->v_int64;
else
value_p->v_float = value_p->v_int;
}
@ -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;
if (token == G_TOKEN_FLOAT)
value.v_float = g_strtod (gstring->str, &endptr);
else
{
guint64 ui64 = 0;
switch (token)
{
case G_TOKEN_BINARY:
value.v_binary = strtol (gstring->str, &endptr, 2);
ui64 = g_ascii_strtoull (gstring->str, &endptr, 2);
break;
case G_TOKEN_OCTAL:
value.v_octal = strtol (gstring->str, &endptr, 8);
ui64 = g_ascii_strtoull (gstring->str, &endptr, 8);
break;
case G_TOKEN_INT:
value.v_int = strtol (gstring->str, &endptr, 10);
ui64 = g_ascii_strtoull (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:
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)
{

View 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;
};

View 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)

View 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 */