From d6b95124a6a823cce9491d5218070336b08e71c2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Denis-Courmont?= Date: Wed, 8 Mar 2006 12:25:29 +0000 Subject: [PATCH] * i18n_strtod: locale-agnostic strtod() (accepts both comma and dot as decimal separator) * us_strtod, us_atof: same as i18n_* but only accept dot in any case (this will be useful when parsing stream output chain which uses comma to separate options) --- include/charset.h | 4 +++ src/misc/charset.c | 65 ++++++++++++++++++++++++++++++++++++++------ src/test/i18n_atof.c | 37 ++++++++++++++++++++++--- 3 files changed, 93 insertions(+), 13 deletions(-) diff --git a/include/charset.h b/include/charset.h index a7398598e9..7fd2cf2f46 100644 --- a/include/charset.h +++ b/include/charset.h @@ -49,7 +49,11 @@ VLC_EXPORT( char *, EnsureUTF8, ( char * ) ); VLC_EXPORT( char *, FromUTF32, ( const wchar_t * ) ); VLC_EXPORT( char *, __vlc_fix_readdir_charset, ( vlc_object_t *, const char * ) ); #define vlc_fix_readdir_charset(a,b) __vlc_fix_readdir_charset(VLC_OBJECT(a),b) + +extern double i18n_strtod( const char *, char ** ); extern double i18n_atof( const char * ); +extern double us_strtod( const char *, char ** ); +extern double us_atof( const char * ); # ifdef __cplusplus } diff --git a/src/misc/charset.c b/src/misc/charset.c index a575f72136..2a66d67326 100644 --- a/src/misc/charset.c +++ b/src/misc/charset.c @@ -380,25 +380,72 @@ char *__vlc_fix_readdir_charset( vlc_object_t *p_this, const char *psz_string ) * dot (which is the american default), and comma (which is used in France, * the country with the most VLC developers, among others). * - * i18n_atof() has the same prototype as ANSI C atof() but it accepts + * i18n_strtod() has the same prototype as ANSI C strtod() but it accepts * either decimal separator when deserializing the string to a float number, * independant of the local computer setting. */ -double i18n_atof( const char *str ) +double i18n_strtod( const char *str, char **end ) { - char *end; - double d = strtod( str, &end ); + char *end_buf, e; + double d; - if(( *end == ',' ) || ( *end == '.' )) + if( end == NULL ) + end = &end_buf; + d = strtod( str, end ); + + e = **end; + if(( e == ',' ) || ( e == '.' )) { - char *dup = strdup( str ); + char dup[strlen( str ) + 1]; + strcpy( dup, str ); if( dup == NULL ) return d; - dup[end - str] = ( *end == ',' ) ? '.' : ','; - d = strtod( dup, &end ); - free( dup ); + dup[*end - str] = ( e == ',' ) ? '.' : ','; + d = strtod( dup, end ); } return d; } + +/** + * i18n_atof() has the same prototype as ANSI C atof() but it accepts + * either decimal separator when deserializing the string to a float number, + * independant of the local computer setting. + */ +double i18n_atof( const char *str ) +{ + return i18n_strtod( str, NULL ); +} + + +/** + * us_strtod() has the same prototype as ANSI C strtod() but it expects + * a dot as decimal separator regardless of the system locale. + */ +double us_strtod( const char *str, char **end ) +{ + char dup[strlen( str ) + 1], *ptr; + double d; + strcpy( dup, str ); + + ptr = strchr( dup, ',' ); + if( ptr != NULL ) + *ptr = '\0'; + + d = strtod( dup, &ptr ); + if( end != NULL ) + *end = (char *)&str[ptr - dup]; + + return d; +} + +/** + * us_atof() has the same prototype as ANSI C atof() but it expects a dot + * as decimal separator, regardless of the system locale. + */ +double us_atof( const char *str ) +{ + return us_strtod( str, NULL ); +} + diff --git a/src/test/i18n_atof.c b/src/test/i18n_atof.c index 4ac8eeeeb1..b7307eeca5 100644 --- a/src/test/i18n_atof.c +++ b/src/test/i18n_atof.c @@ -27,15 +27,44 @@ int main (void) { + const char dot9[] = "999999.999999"; + const char comma9[] = "999999,999999"; + const char sharp9[] = "999999#999999"; + char *end; + assert (i18n_atof("0") == 0.); assert (i18n_atof("1") == 1.); assert (i18n_atof("1.") == 1.); assert (i18n_atof("1,") == 1.); assert (i18n_atof("1#") == 1.); - assert (i18n_atof("999999.999999") == 999999.999999); - assert (i18n_atof("999999,999999") == 999999.999999); - assert (i18n_atof("999999#999999") == 999999.); - + assert (i18n_atof(dot9) == 999999.999999); + assert (i18n_atof(comma9) == 999999.999999); + assert (i18n_atof(sharp9) == 999999.); assert (i18n_atof("invalid") == 0.); + + assert (us_atof("0") == 0.); + assert (us_atof("1") == 1.); + assert (us_atof("1.") == 1.); + assert (us_atof("1,") == 1.); + assert (us_atof("1#") == 1.); + assert (us_atof(dot9) == 999999.999999); + assert (us_atof(comma9) == 999999.); + assert (us_atof(sharp9) == 999999.); + assert (us_atof("invalid") == 0.); + + assert ((i18n_strtod(dot9, &end ) == 999999.999999) + && (*end == '\0')); + assert ((i18n_strtod(comma9, &end ) == 999999.999999) + && (*end == '\0')); + assert ((i18n_strtod(sharp9, &end ) == 999999.) + && (*end == '#')); + + assert ((us_strtod(dot9, &end ) == 999999.999999) + && (*end == '\0')); + assert ((us_strtod(comma9, &end ) == 999999.) + && (*end == ',')); + assert ((us_strtod(sharp9, &end ) == 999999.) + && (*end == '#')); + return 0; } -- 2.39.2