mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-08 03:45:49 +01:00
Add g_strtod & co.
2001-10-24 Alex Larsson <alexl@redhat.com> * docs/reference/glib/glib-sections.txt: Add g_strtod & co. * docs/reference/glib/tmpl/string_utils.sgml: Add docs for G_ASCII_DTOSTR_BUF_SIZE. * glib/gstrfuncs.[ch]: Added g_ascii_strtod, g_ascii_dtostr and g_ascii_formatd. * tests/Makefile.am: * tests/strtod-test.c: Add tests for g_ascii_strtod & co.
This commit is contained in:
parent
b0facb3863
commit
3c39c8fcd0
15
ChangeLog
15
ChangeLog
@ -1,3 +1,18 @@
|
||||
2001-10-24 Alex Larsson <alexl@redhat.com>
|
||||
|
||||
* docs/reference/glib/glib-sections.txt:
|
||||
Add g_strtod & co.
|
||||
|
||||
* docs/reference/glib/tmpl/string_utils.sgml:
|
||||
Add docs for G_ASCII_DTOSTR_BUF_SIZE.
|
||||
|
||||
* glib/gstrfuncs.[ch]:
|
||||
Added g_ascii_strtod, g_ascii_dtostr and g_ascii_formatd.
|
||||
|
||||
* tests/Makefile.am:
|
||||
* tests/strtod-test.c:
|
||||
Add tests for g_ascii_strtod & co.
|
||||
|
||||
2001-10-23 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32.in: Typo: GLIB_MICRO_VERSION and
|
||||
|
@ -1,3 +1,18 @@
|
||||
2001-10-24 Alex Larsson <alexl@redhat.com>
|
||||
|
||||
* docs/reference/glib/glib-sections.txt:
|
||||
Add g_strtod & co.
|
||||
|
||||
* docs/reference/glib/tmpl/string_utils.sgml:
|
||||
Add docs for G_ASCII_DTOSTR_BUF_SIZE.
|
||||
|
||||
* glib/gstrfuncs.[ch]:
|
||||
Added g_ascii_strtod, g_ascii_dtostr and g_ascii_formatd.
|
||||
|
||||
* tests/Makefile.am:
|
||||
* tests/strtod-test.c:
|
||||
Add tests for g_ascii_strtod & co.
|
||||
|
||||
2001-10-23 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32.in: Typo: GLIB_MICRO_VERSION and
|
||||
|
@ -1,3 +1,18 @@
|
||||
2001-10-24 Alex Larsson <alexl@redhat.com>
|
||||
|
||||
* docs/reference/glib/glib-sections.txt:
|
||||
Add g_strtod & co.
|
||||
|
||||
* docs/reference/glib/tmpl/string_utils.sgml:
|
||||
Add docs for G_ASCII_DTOSTR_BUF_SIZE.
|
||||
|
||||
* glib/gstrfuncs.[ch]:
|
||||
Added g_ascii_strtod, g_ascii_dtostr and g_ascii_formatd.
|
||||
|
||||
* tests/Makefile.am:
|
||||
* tests/strtod-test.c:
|
||||
Add tests for g_ascii_strtod & co.
|
||||
|
||||
2001-10-23 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32.in: Typo: GLIB_MICRO_VERSION and
|
||||
|
@ -1,3 +1,18 @@
|
||||
2001-10-24 Alex Larsson <alexl@redhat.com>
|
||||
|
||||
* docs/reference/glib/glib-sections.txt:
|
||||
Add g_strtod & co.
|
||||
|
||||
* docs/reference/glib/tmpl/string_utils.sgml:
|
||||
Add docs for G_ASCII_DTOSTR_BUF_SIZE.
|
||||
|
||||
* glib/gstrfuncs.[ch]:
|
||||
Added g_ascii_strtod, g_ascii_dtostr and g_ascii_formatd.
|
||||
|
||||
* tests/Makefile.am:
|
||||
* tests/strtod-test.c:
|
||||
Add tests for g_ascii_strtod & co.
|
||||
|
||||
2001-10-23 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32.in: Typo: GLIB_MICRO_VERSION and
|
||||
|
@ -1,3 +1,18 @@
|
||||
2001-10-24 Alex Larsson <alexl@redhat.com>
|
||||
|
||||
* docs/reference/glib/glib-sections.txt:
|
||||
Add g_strtod & co.
|
||||
|
||||
* docs/reference/glib/tmpl/string_utils.sgml:
|
||||
Add docs for G_ASCII_DTOSTR_BUF_SIZE.
|
||||
|
||||
* glib/gstrfuncs.[ch]:
|
||||
Added g_ascii_strtod, g_ascii_dtostr and g_ascii_formatd.
|
||||
|
||||
* tests/Makefile.am:
|
||||
* tests/strtod-test.c:
|
||||
Add tests for g_ascii_strtod & co.
|
||||
|
||||
2001-10-23 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32.in: Typo: GLIB_MICRO_VERSION and
|
||||
|
@ -1,3 +1,18 @@
|
||||
2001-10-24 Alex Larsson <alexl@redhat.com>
|
||||
|
||||
* docs/reference/glib/glib-sections.txt:
|
||||
Add g_strtod & co.
|
||||
|
||||
* docs/reference/glib/tmpl/string_utils.sgml:
|
||||
Add docs for G_ASCII_DTOSTR_BUF_SIZE.
|
||||
|
||||
* glib/gstrfuncs.[ch]:
|
||||
Added g_ascii_strtod, g_ascii_dtostr and g_ascii_formatd.
|
||||
|
||||
* tests/Makefile.am:
|
||||
* tests/strtod-test.c:
|
||||
Add tests for g_ascii_strtod & co.
|
||||
|
||||
2001-10-23 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32.in: Typo: GLIB_MICRO_VERSION and
|
||||
|
@ -1,3 +1,18 @@
|
||||
2001-10-24 Alex Larsson <alexl@redhat.com>
|
||||
|
||||
* docs/reference/glib/glib-sections.txt:
|
||||
Add g_strtod & co.
|
||||
|
||||
* docs/reference/glib/tmpl/string_utils.sgml:
|
||||
Add docs for G_ASCII_DTOSTR_BUF_SIZE.
|
||||
|
||||
* glib/gstrfuncs.[ch]:
|
||||
Added g_ascii_strtod, g_ascii_dtostr and g_ascii_formatd.
|
||||
|
||||
* tests/Makefile.am:
|
||||
* tests/strtod-test.c:
|
||||
Add tests for g_ascii_strtod & co.
|
||||
|
||||
2001-10-23 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32.in: Typo: GLIB_MICRO_VERSION and
|
||||
|
@ -1,3 +1,18 @@
|
||||
2001-10-24 Alex Larsson <alexl@redhat.com>
|
||||
|
||||
* docs/reference/glib/glib-sections.txt:
|
||||
Add g_strtod & co.
|
||||
|
||||
* docs/reference/glib/tmpl/string_utils.sgml:
|
||||
Add docs for G_ASCII_DTOSTR_BUF_SIZE.
|
||||
|
||||
* glib/gstrfuncs.[ch]:
|
||||
Added g_ascii_strtod, g_ascii_dtostr and g_ascii_formatd.
|
||||
|
||||
* tests/Makefile.am:
|
||||
* tests/strtod-test.c:
|
||||
Add tests for g_ascii_strtod & co.
|
||||
|
||||
2001-10-23 Tor Lillqvist <tml@iki.fi>
|
||||
|
||||
* config.h.win32.in: Typo: GLIB_MICRO_VERSION and
|
||||
|
@ -922,6 +922,12 @@ g_strncasecmp
|
||||
|
||||
<SUBSECTION>
|
||||
g_strreverse
|
||||
|
||||
<SUBSECTION>
|
||||
G_ASCII_DTOSTR_BUF_SIZE
|
||||
g_ascii_strtod
|
||||
g_ascii_dtostr
|
||||
g_ascii_formatd
|
||||
g_strtod
|
||||
|
||||
<SUBSECTION>
|
||||
|
@ -562,19 +562,68 @@ For example, g_strreverse ("abcdef") will result in "fedcba".
|
||||
@Returns: the same pointer passed in as @string.
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_strtod ##### -->
|
||||
<!-- ##### MACRO G_ASCII_DTOSTR_BUF_SIZE ##### -->
|
||||
<para>
|
||||
Converts a string to a gdouble value.
|
||||
It calls the standard <function>strtod()</function> function
|
||||
to handle the conversion, but if the string is not completely converted
|
||||
it attempts the conversion again in the "C" locale, and returns the best
|
||||
match.
|
||||
A good size for a buffer to be passed into <function>g_ascii_dtostr</function>.
|
||||
It is guaranteed to be enough for all output of that function on systems with
|
||||
64bit IEEE compatible doubles.
|
||||
</para>
|
||||
<para>
|
||||
The typical usage would be something like:
|
||||
</para>
|
||||
<para>
|
||||
<literal>
|
||||
char buf[G_ASCII_DTOSTR_BUF_SIZE];
|
||||
|
||||
fprintf (out, "value=%s\n", g_ascii_dtostr (buf, sizeof (buf), value));
|
||||
</literal>
|
||||
</para>
|
||||
|
||||
@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.
|
||||
@Returns: the gdouble value.
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_ascii_strtod ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@nptr:
|
||||
@endptr:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_ascii_dtostr ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@buffer:
|
||||
@buf_len:
|
||||
@d:
|
||||
@Returns:
|
||||
<!-- # Unused Parameters # -->
|
||||
@format:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_ascii_formatd ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@buffer:
|
||||
@buf_len:
|
||||
@format:
|
||||
@d:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_strtod ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@nptr:
|
||||
@endptr:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION g_strchug ##### -->
|
||||
|
303
glib/gstrfuncs.c
303
glib/gstrfuncs.c
@ -39,6 +39,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h> /* For tolower() */
|
||||
#if !defined (HAVE_STRSIGNAL) || !defined(NO_SYS_SIGLIST_DECL)
|
||||
#include <signal.h>
|
||||
@ -253,6 +254,26 @@ g_strconcat (const gchar *string1, ...)
|
||||
return concat;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_strtod:
|
||||
* @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.
|
||||
*
|
||||
* Converts a string to a gdouble value.
|
||||
* It calls the standard strtod() function to handle the conversion, but
|
||||
* if the string is not completely converted it attempts the conversion
|
||||
* again with @g_ascii_strtod, and returns the best match.
|
||||
*
|
||||
* This function should seldom be used. The normal situation when reading
|
||||
* numbers not for human consumption is to use @g_ascii_strtod(). Only when
|
||||
* you know that you must expect both locale formated and C formated numbers
|
||||
* should you use this. Make sure that you don't pass strings such as comma
|
||||
* separated lists of values, since the commas may be interpreted as a decimal
|
||||
* point in some locales, causing unexpected results.
|
||||
*
|
||||
* Return value: the gdouble value.
|
||||
**/
|
||||
gdouble
|
||||
g_strtod (const gchar *nptr,
|
||||
gchar **endptr)
|
||||
@ -270,15 +291,7 @@ g_strtod (const gchar *nptr,
|
||||
val_1 = strtod (nptr, &fail_pos_1);
|
||||
|
||||
if (fail_pos_1 && fail_pos_1[0] != 0)
|
||||
{
|
||||
gchar *old_locale;
|
||||
|
||||
old_locale = g_strdup (setlocale (LC_NUMERIC, NULL));
|
||||
setlocale (LC_NUMERIC, "C");
|
||||
val_2 = strtod (nptr, &fail_pos_2);
|
||||
setlocale (LC_NUMERIC, old_locale);
|
||||
g_free (old_locale);
|
||||
}
|
||||
val_2 = g_ascii_strtod (nptr, &fail_pos_2);
|
||||
|
||||
if (!fail_pos_1 || fail_pos_1[0] == 0 || fail_pos_1 >= fail_pos_2)
|
||||
{
|
||||
@ -294,6 +307,278 @@ g_strtod (const gchar *nptr,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ascii_strtod:
|
||||
* @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.
|
||||
*
|
||||
* Converts a string to a gdouble value.
|
||||
* This function behaves like the standard strtod() 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 dependent.
|
||||
* To handle input from the user you should normally use the
|
||||
* locale-sensitive system strtod function.
|
||||
*
|
||||
* To convert from a string to double in a locale-insensitive
|
||||
* way, use @g_ascii_dtostr.
|
||||
*
|
||||
* If the correct value would cause overflow, plus or minus HUGE_VAL
|
||||
* is returned (according to the sign of the value), and ERANGE is
|
||||
* stored in errno. If the correct value would cause underflow,
|
||||
* zero is returned and ERANGE is stored in errno.
|
||||
*
|
||||
* This function resets errno before calling strtod() so that
|
||||
* you can reliably detect overflow and underflow.
|
||||
*
|
||||
* Return value: the gdouble value.
|
||||
**/
|
||||
gdouble
|
||||
g_ascii_strtod (const gchar *nptr,
|
||||
gchar **endptr)
|
||||
{
|
||||
gchar *fail_pos;
|
||||
gdouble val;
|
||||
struct lconv *locale_data;
|
||||
const char *decimal_point;
|
||||
int decimal_point_len;
|
||||
const char *p, *decimal_point_pos;
|
||||
const char *end = NULL; /* Silence gcc */
|
||||
|
||||
g_return_val_if_fail (nptr != NULL, 0);
|
||||
|
||||
fail_pos = NULL;
|
||||
|
||||
locale_data = localeconv ();
|
||||
decimal_point = locale_data->decimal_point;
|
||||
decimal_point_len = strlen (decimal_point);
|
||||
|
||||
g_assert (decimal_point_len != 0);
|
||||
|
||||
decimal_point_pos = NULL;
|
||||
if (decimal_point[0] != '.' ||
|
||||
decimal_point[1] != 0)
|
||||
{
|
||||
p = nptr;
|
||||
/* Skip leading space */
|
||||
while (isspace ((guchar)*p))
|
||||
p++;
|
||||
|
||||
/* Skip leading optional sign */
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
|
||||
if (p[0] == '0' &&
|
||||
(p[1] == 'x' || p[1] == 'X'))
|
||||
{
|
||||
p += 2;
|
||||
/* HEX - find the (optional) decimal point */
|
||||
|
||||
while (isxdigit ((guchar)*p))
|
||||
p++;
|
||||
|
||||
if (*p == '.')
|
||||
{
|
||||
decimal_point_pos = p++;
|
||||
|
||||
while (isxdigit ((guchar)*p))
|
||||
p++;
|
||||
|
||||
if (*p == 'p' || *p == 'P')
|
||||
p++;
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
while (isdigit ((guchar)*p))
|
||||
p++;
|
||||
end = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (isdigit ((guchar)*p))
|
||||
p++;
|
||||
|
||||
if (*p == '.')
|
||||
{
|
||||
decimal_point_pos = p++;
|
||||
|
||||
while (isdigit ((guchar)*p))
|
||||
p++;
|
||||
|
||||
if (*p == 'e' || *p == 'E')
|
||||
p++;
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
while (isdigit ((guchar)*p))
|
||||
p++;
|
||||
end = p;
|
||||
}
|
||||
}
|
||||
/* For the other cases, we need not convert the decimal point */
|
||||
}
|
||||
|
||||
/* Set errno to zero, so that we can distinguish zero results
|
||||
and underflows */
|
||||
errno = 0;
|
||||
|
||||
if (decimal_point_pos)
|
||||
{
|
||||
char *copy, *c;
|
||||
|
||||
/* We need to convert the '.' to the locale specific decimal point */
|
||||
copy = g_malloc (end - nptr + 1 + decimal_point_len);
|
||||
|
||||
c = copy;
|
||||
memcpy (c, nptr, decimal_point_pos - nptr);
|
||||
c += decimal_point_pos - nptr;
|
||||
memcpy (c, decimal_point, decimal_point_len);
|
||||
c += decimal_point_len;
|
||||
memcpy (c, decimal_point_pos + 1, end - (decimal_point_pos + 1));
|
||||
c += end - (decimal_point_pos + 1);
|
||||
*c = 0;
|
||||
|
||||
val = strtod (copy, &fail_pos);
|
||||
|
||||
if (fail_pos)
|
||||
{
|
||||
if (fail_pos > decimal_point_pos)
|
||||
fail_pos = (char *)nptr + (fail_pos - copy) - (decimal_point_len - 1);
|
||||
else
|
||||
fail_pos = (char *)nptr + (fail_pos - copy);
|
||||
}
|
||||
|
||||
g_free (copy);
|
||||
|
||||
}
|
||||
else
|
||||
val = strtod (nptr, &fail_pos);
|
||||
|
||||
if (endptr)
|
||||
*endptr = fail_pos;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ascii_dtostr:
|
||||
* @buffer: A buffer to place the resulting string in
|
||||
* @buf_len: The length of the buffer.
|
||||
* @d: The double to convert
|
||||
*
|
||||
* Converts a double to a string, using the '.' as
|
||||
* decimal_point.
|
||||
*
|
||||
* This functions generates enough precision that converting
|
||||
* the string back using @g_strtod gives the same machine-number
|
||||
* (on machines with IEEE compatible 64bit doubles). It is
|
||||
* guaranteed that the size of the resulting string will never
|
||||
* be larger than @G_ASCII_DTOSTR_BUF_SIZE bytes.
|
||||
*
|
||||
* Return value: The pointer to the buffer with the converted string.
|
||||
**/
|
||||
gchar *
|
||||
g_ascii_dtostr (gchar *buffer,
|
||||
gint buf_len,
|
||||
gdouble d)
|
||||
{
|
||||
return g_ascii_formatd (buffer, buf_len, "%.17g", d);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ascii_formatd:
|
||||
* @buffer: A buffer to place the resulting string in
|
||||
* @buf_len: The length of the buffer.
|
||||
* @format: The printf-style format to use for the
|
||||
* code to use for converting.
|
||||
* @d: The double to convert
|
||||
*
|
||||
* Converts a double to a string, using the '.' as
|
||||
* decimal_point. To format the number you pass in
|
||||
* a printf-style formating string. Allowed conversion
|
||||
* specifiers are eEfFgG.
|
||||
*
|
||||
* If you just want to want to serialize the value into a
|
||||
* string, use @g_ascii_dtostr.
|
||||
*
|
||||
* Return value: The pointer to the buffer with the converted string.
|
||||
**/
|
||||
gchar *
|
||||
g_ascii_formatd (gchar *buffer,
|
||||
gint buf_len,
|
||||
const gchar *format,
|
||||
gdouble d)
|
||||
{
|
||||
struct lconv *locale_data;
|
||||
const char *decimal_point;
|
||||
int decimal_point_len;
|
||||
gchar *p;
|
||||
int rest_len;
|
||||
gchar format_char;
|
||||
|
||||
g_return_val_if_fail (buffer != NULL, NULL);
|
||||
g_return_val_if_fail (format[0] == '%', NULL);
|
||||
g_return_val_if_fail (strpbrk (format + 1, "'l%") == NULL, NULL);
|
||||
|
||||
format_char = format[strlen (format) - 1];
|
||||
|
||||
g_return_val_if_fail (format_char == 'e' || format_char == 'E' ||
|
||||
format_char == 'f' || format_char == 'F' ||
|
||||
format_char == 'g' || format_char == 'G',
|
||||
NULL);
|
||||
|
||||
if (format[0] != '%')
|
||||
return NULL;
|
||||
|
||||
if (strpbrk (format + 1, "'l%"))
|
||||
return NULL;
|
||||
|
||||
if (!(format_char == 'e' || format_char == 'E' ||
|
||||
format_char == 'f' || format_char == 'F' ||
|
||||
format_char == 'g' || format_char == 'G'))
|
||||
return NULL;
|
||||
|
||||
|
||||
g_snprintf (buffer, buf_len, format, d);
|
||||
|
||||
locale_data = localeconv ();
|
||||
decimal_point = locale_data->decimal_point;
|
||||
decimal_point_len = strlen (decimal_point);
|
||||
|
||||
g_assert (decimal_point_len != 0);
|
||||
|
||||
if (decimal_point[0] != '.' ||
|
||||
decimal_point[1] != 0)
|
||||
{
|
||||
p = buffer;
|
||||
|
||||
if (*p == '+' || *p == '-')
|
||||
p++;
|
||||
|
||||
while (isdigit ((guchar)*p))
|
||||
p++;
|
||||
|
||||
if (strncmp (p, decimal_point, decimal_point_len) == 0)
|
||||
{
|
||||
*p = '.';
|
||||
p++;
|
||||
if (decimal_point_len > 1) {
|
||||
rest_len = strlen (p + (decimal_point_len-1));
|
||||
memmove (p, p + (decimal_point_len-1),
|
||||
rest_len);
|
||||
p[rest_len] = 0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
G_CONST_RETURN gchar*
|
||||
g_strerror (gint errnum)
|
||||
{
|
||||
|
@ -98,8 +98,6 @@ gchar* g_strdelimit (gchar *string,
|
||||
gchar* g_strcanon (gchar *string,
|
||||
const gchar *valid_chars,
|
||||
gchar substitutor);
|
||||
gdouble g_strtod (const gchar *nptr,
|
||||
gchar **endptr);
|
||||
G_CONST_RETURN gchar* g_strerror (gint errnum) G_GNUC_CONST;
|
||||
G_CONST_RETURN gchar* g_strsignal (gint signum) G_GNUC_CONST;
|
||||
gchar* g_strreverse (gchar *string);
|
||||
@ -118,6 +116,24 @@ gchar * g_strrstr_len (const gchar *haystack,
|
||||
gssize haystack_len,
|
||||
const gchar *needle);
|
||||
|
||||
/* String to/from double conversion functions */
|
||||
|
||||
gdouble g_strtod (const gchar *nptr,
|
||||
gchar **endptr);
|
||||
gdouble g_ascii_strtod (const gchar *nptr,
|
||||
gchar **endptr);
|
||||
/* 29 bytes should enough for all possible values that
|
||||
* g_ascii_dtostr can produce.
|
||||
* Then add 10 for good measure */
|
||||
#define G_ASCII_DTOSTR_BUF_SIZE (29 + 10)
|
||||
gchar * g_ascii_dtostr (gchar *buffer,
|
||||
gint buf_len,
|
||||
gdouble d);
|
||||
gchar * g_ascii_formatd (gchar *buffer,
|
||||
gint buf_len,
|
||||
const gchar *format,
|
||||
gdouble d);
|
||||
|
||||
/* removes leading spaces */
|
||||
gchar* g_strchug (gchar *string);
|
||||
/* removes trailing spaces */
|
||||
|
@ -72,6 +72,7 @@ test_programs = \
|
||||
spawn-test \
|
||||
strfunc-test \
|
||||
string-test \
|
||||
strtod-test \
|
||||
thread-test \
|
||||
threadpool-test \
|
||||
tree-test \
|
||||
@ -114,6 +115,7 @@ slist_test_LDADD = $(progs_LDADD)
|
||||
spawn_test_LDADD = $(progs_LDADD)
|
||||
strfunc_test_LDADD = $(progs_LDADD)
|
||||
string_test_LDADD = $(progs_LDADD)
|
||||
strtod_test_LDADD = $(progs_LDADD) -lm
|
||||
thread_test_LDADD = $(thread_LDADD)
|
||||
threadpool_test_LDADD = $(thread_LDADD)
|
||||
tree_test_LDADD = $(progs_LDADD)
|
||||
|
53
tests/strtod-test.c
Normal file
53
tests/strtod-test.c
Normal file
@ -0,0 +1,53 @@
|
||||
#include <glib.h>
|
||||
#include <locale.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
void
|
||||
test_string (char *number, double res)
|
||||
{
|
||||
gdouble d;
|
||||
char *locales[] = {"sv_SE", "en_US", "fa_IR", "C"};
|
||||
int l;
|
||||
char *end;
|
||||
|
||||
for (l = 0; l < G_N_ELEMENTS (locales); l++)
|
||||
{
|
||||
setlocale (LC_NUMERIC, locales[l]);
|
||||
d = g_ascii_strtod (number, &end);
|
||||
if (d != res)
|
||||
g_print ("g_ascii_strtod for locale %s failed\n", locales[l]);
|
||||
if (*end != 0)
|
||||
g_print ("g_ascii_strtod for locale %s endptr was wrong\n", locales[l]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
gdouble d;
|
||||
char buffer[G_ASCII_DTOSTR_BUF_SIZE];
|
||||
|
||||
test_string ("123.123", 123.123);
|
||||
test_string ("123.123e2", 123.123e2);
|
||||
test_string ("123.123e-2", 123.123e-2);
|
||||
test_string ("-123.123", -123.123);
|
||||
test_string ("-123.123e2", -123.123e2);
|
||||
test_string ("-123.123e-2", -123.123e-2);
|
||||
|
||||
d = 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0;
|
||||
g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
|
||||
|
||||
d = -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0;
|
||||
g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
|
||||
|
||||
d = pow (2.0, -1024.1);
|
||||
g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
|
||||
|
||||
d = -pow (2.0, -1024.1);
|
||||
g_assert (d == g_ascii_strtod (g_ascii_dtostr (buffer, sizeof (buffer), d), NULL));
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user