Commit d6b95124 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

* 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)
parent 88fcc88c
...@@ -49,7 +49,11 @@ VLC_EXPORT( char *, EnsureUTF8, ( char * ) ); ...@@ -49,7 +49,11 @@ VLC_EXPORT( char *, EnsureUTF8, ( char * ) );
VLC_EXPORT( char *, FromUTF32, ( const wchar_t * ) ); VLC_EXPORT( char *, FromUTF32, ( const wchar_t * ) );
VLC_EXPORT( char *, __vlc_fix_readdir_charset, ( vlc_object_t *, const char * ) ); 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) #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 i18n_atof( const char * );
extern double us_strtod( const char *, char ** );
extern double us_atof( const char * );
# ifdef __cplusplus # ifdef __cplusplus
} }
......
...@@ -380,25 +380,72 @@ char *__vlc_fix_readdir_charset( vlc_object_t *p_this, const char *psz_string ) ...@@ -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, * dot (which is the american default), and comma (which is used in France,
* the country with the most VLC developers, among others). * 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, * either decimal separator when deserializing the string to a float number,
* independant of the local computer setting. * independant of the local computer setting.
*/ */
double i18n_atof( const char *str ) double i18n_strtod( const char *str, char **end )
{ {
char *end; char *end_buf, e;
double d = strtod( str, &end ); 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 ) if( dup == NULL )
return d; return d;
dup[end - str] = ( *end == ',' ) ? '.' : ','; dup[*end - str] = ( e == ',' ) ? '.' : ',';
d = strtod( dup, &end ); d = strtod( dup, end );
free( dup );
} }
return d; 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 );
}
...@@ -27,15 +27,44 @@ ...@@ -27,15 +27,44 @@
int main (void) 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("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("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(dot9) == 999999.999999);
assert (i18n_atof("999999,999999") == 999999.999999); assert (i18n_atof(comma9) == 999999.999999);
assert (i18n_atof("999999#999999") == 999999.); assert (i18n_atof(sharp9) == 999999.);
assert (i18n_atof("invalid") == 0.); 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; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment