ICU-10232 DigitList to use strtod_l instead of strtod with cached host decimal point on platforms supporting strtod_l. For other platforms, detect host decimal point instead of using cached host decimal point char.
X-SVN-Rev: 39124
This commit is contained in:
parent
d9babe5948
commit
f2d8d1be68
29
icu4c/source/configure
vendored
29
icu4c/source/configure
vendored
@ -657,6 +657,7 @@ U_HAVE_EXTRAS
|
||||
EXTRAS_TRUE
|
||||
U_HAVE_WCSCPY
|
||||
U_HAVE_WCHAR_H
|
||||
U_HAVE_STRTOD_L
|
||||
U_TIMEZONE
|
||||
U_HAVE_TIMEZONE
|
||||
U_TZNAME
|
||||
@ -753,6 +754,7 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@ -856,6 +858,7 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@ -1108,6 +1111,15 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@ -1245,7 +1257,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir
|
||||
libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@ -1398,6 +1410,7 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
@ -7051,6 +7064,20 @@ fi
|
||||
|
||||
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "strtod_l" "ac_cv_func_strtod_l"
|
||||
if test "x$ac_cv_func_strtod_l" = xyes; then :
|
||||
|
||||
fi
|
||||
|
||||
if test x$ac_cv_func_strtod_l = xyes
|
||||
then
|
||||
U_HAVE_STRTOD_L=1
|
||||
else
|
||||
CONFIG_CPPFLAGS="${CONFIG_CPPFLAGS} -DU_HAVE_STRTOD_L=0"
|
||||
U_HAVE_STRTOD_L=0
|
||||
fi
|
||||
|
||||
|
||||
# Checks for typedefs
|
||||
ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default"
|
||||
if test "x$ac_cv_type_int8_t" = xyes; then :
|
||||
|
@ -893,6 +893,16 @@ fi
|
||||
AC_SUBST(U_HAVE_TIMEZONE)
|
||||
AC_SUBST(U_TIMEZONE)
|
||||
|
||||
AC_CHECK_FUNC(strtod_l)
|
||||
if test x$ac_cv_func_strtod_l = xyes
|
||||
then
|
||||
U_HAVE_STRTOD_L=1
|
||||
else
|
||||
CONFIG_CPPFLAGS="${CONFIG_CPPFLAGS} -DU_HAVE_STRTOD_L=0"
|
||||
U_HAVE_STRTOD_L=0
|
||||
fi
|
||||
AC_SUBST(U_HAVE_STRTOD_L)
|
||||
|
||||
# Checks for typedefs
|
||||
AC_CHECK_TYPE(int8_t,signed char)
|
||||
AC_CHECK_TYPE(uint8_t,unsigned char)
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include "putilimp.h"
|
||||
#include "uassert.h"
|
||||
#include "digitinterval.h"
|
||||
#include "ucln_in.h"
|
||||
#include "umutex.h"
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
@ -397,27 +399,6 @@ DigitList::append(char digit)
|
||||
internalClear();
|
||||
}
|
||||
|
||||
char DigitList::getStrtodDecimalSeparator() {
|
||||
// TODO: maybe use andy's pthread once.
|
||||
static char gDecimal = 0;
|
||||
char result;
|
||||
{
|
||||
Mutex mutex;
|
||||
result = gDecimal;;
|
||||
if (result == 0) {
|
||||
// We need to know the decimal separator character that will be used with strtod().
|
||||
// Depends on the C runtime global locale.
|
||||
// Most commonly is '.'
|
||||
// TODO: caching could fail if the global locale is changed on the fly.
|
||||
char rep[MAX_DIGITS];
|
||||
sprintf(rep, "%+1.1f", 1.0);
|
||||
result = rep[2];
|
||||
gDecimal = result;;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
/**
|
||||
@ -430,24 +411,11 @@ char DigitList::getStrtodDecimalSeparator() {
|
||||
double
|
||||
DigitList::getDouble() const
|
||||
{
|
||||
static char gDecimal = 0;
|
||||
char decimalSeparator;
|
||||
{
|
||||
Mutex mutex;
|
||||
if (fHave == kDouble) {
|
||||
return fUnion.fDouble;
|
||||
}
|
||||
decimalSeparator = gDecimal;
|
||||
}
|
||||
|
||||
if (decimalSeparator == 0) {
|
||||
// We need to know the decimal separator character that will be used with strtod().
|
||||
// Depends on the C runtime global locale.
|
||||
// Most commonly is '.'
|
||||
// TODO: caching could fail if the global locale is changed on the fly.
|
||||
char rep[MAX_DIGITS];
|
||||
sprintf(rep, "%+1.1f", 1.0);
|
||||
decimalSeparator = rep[2];
|
||||
}
|
||||
|
||||
double tDouble = 0.0;
|
||||
@ -484,25 +452,77 @@ DigitList::getDouble() const
|
||||
uprv_decNumberToString(this->fDecNumber, s.getAlias());
|
||||
}
|
||||
U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18);
|
||||
|
||||
if (decimalSeparator != '.') {
|
||||
char *decimalPt = strchr(s.getAlias(), '.');
|
||||
if (decimalPt != NULL) {
|
||||
*decimalPt = decimalSeparator;
|
||||
}
|
||||
}
|
||||
|
||||
char *end = NULL;
|
||||
tDouble = uprv_strtod(s.getAlias(), &end);
|
||||
tDouble = decimalStrToDouble(s.getAlias(), &end);
|
||||
}
|
||||
{
|
||||
Mutex mutex;
|
||||
DigitList *nonConstThis = const_cast<DigitList *>(this);
|
||||
nonConstThis->internalSetDouble(tDouble);
|
||||
gDecimal = decimalSeparator;
|
||||
}
|
||||
return tDouble;
|
||||
}
|
||||
|
||||
#if !defined(U_HAVE_STRTOD_L)
|
||||
# if U_PLATFORM_IS_DARWIN_BASED || U_PLATFORM_IS_LINUX_BASED || U_PLATFORM == U_PF_BSD || U_PLATFORM_HAS_WIN32_API
|
||||
# define U_HAVE_STRTOD_L 1
|
||||
# else
|
||||
# define U_HAVE_STRTOD_L 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if U_HAVE_STRTOD_L && U_PLATFORM_HAS_WIN32_API
|
||||
#define locale_t _locale_t
|
||||
#define newlocale(cat, loc, base) _create_locale(cat, loc)
|
||||
#define freelocale _free_locale
|
||||
#define strtod_l _strtod_l
|
||||
#endif
|
||||
|
||||
#if U_HAVE_STRTOD_L
|
||||
static locale_t gCLocale = (locale_t)0;
|
||||
#endif
|
||||
static icu::UInitOnce gCLocaleInitOnce = U_INITONCE_INITIALIZER;
|
||||
|
||||
U_CDECL_BEGIN
|
||||
// Cleanup callback func
|
||||
static UBool U_CALLCONV digitList_cleanup(void)
|
||||
{
|
||||
#if U_HAVE_STRTOD_L
|
||||
if (gCLocale != (locale_t)0) {
|
||||
freelocale(gCLocale);
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
// C Locale initialization func
|
||||
static void U_CALLCONV initCLocale(void) {
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_DIGITLIST, digitList_cleanup);
|
||||
#if U_HAVE_STRTOD_L
|
||||
gCLocale = newlocale(LC_ALL, "C", (locale_t)0);
|
||||
#endif
|
||||
}
|
||||
U_CDECL_END
|
||||
|
||||
double
|
||||
DigitList::decimalStrToDouble(char *decstr, char **end) {
|
||||
umtx_initOnce(gCLocaleInitOnce, &initCLocale);
|
||||
#if U_HAVE_STRTOD_L
|
||||
return strtod_l(decstr, end, gCLocale);
|
||||
#else
|
||||
char *decimalPt = strchr(decstr, '.');
|
||||
if (decimalPt) {
|
||||
// We need to know the decimal separator character that will be used with strtod().
|
||||
// Depends on the C runtime global locale.
|
||||
// Most commonly is '.'
|
||||
char rep[MAX_DIGITS];
|
||||
sprintf(rep, "%+1.1f", 1.0);
|
||||
*decimalPt = rep[2];
|
||||
}
|
||||
return uprv_strtod(decstr, end);
|
||||
#endif
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
/**
|
||||
|
@ -495,7 +495,8 @@ private:
|
||||
static inline void * U_EXPORT2 operator new(size_t size) U_NO_THROW { return ::operator new(size); };
|
||||
static inline void U_EXPORT2 operator delete(void *ptr ) U_NO_THROW { ::operator delete(ptr); };
|
||||
#endif
|
||||
static char U_EXPORT2 getStrtodDecimalSeparator();
|
||||
|
||||
static double U_EXPORT2 decimalStrToDouble(char *decstr, char **end);
|
||||
|
||||
/**
|
||||
* Placement new for stack usage
|
||||
|
@ -42,6 +42,7 @@ typedef enum ECleanupI18NType {
|
||||
UCLN_I18N_TIMEZONENAMES,
|
||||
UCLN_I18N_ZONEMETA,
|
||||
UCLN_I18N_TIMEZONE,
|
||||
UCLN_I18N_DIGITLIST,
|
||||
UCLN_I18N_DECFMT,
|
||||
UCLN_I18N_NUMFMT,
|
||||
UCLN_I18N_ALLOWED_HOUR_FORMATS,
|
||||
|
@ -114,15 +114,8 @@ double VisibleDigits::computeAbsDoubleValue() const {
|
||||
char str[MAX_DBL_DIGITS+18];
|
||||
uprv_decNumberToString(numberPtr, str);
|
||||
U_ASSERT(uprv_strlen(str) < MAX_DBL_DIGITS+18);
|
||||
char decimalSeparator = DigitList::getStrtodDecimalSeparator();
|
||||
if (decimalSeparator != '.') {
|
||||
char *decimalPt = strchr(str, '.');
|
||||
if (decimalPt != NULL) {
|
||||
*decimalPt = decimalSeparator;
|
||||
}
|
||||
}
|
||||
char *unused = NULL;
|
||||
return uprv_strtod(str, &unused);
|
||||
return DigitList::decimalStrToDouble(str, &unused);
|
||||
}
|
||||
|
||||
void VisibleDigits::getFixedDecimal(
|
||||
|
@ -45,8 +45,6 @@
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)\x86\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
|
||||
<ExecutablePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(VCInstallDir)bin;$(WindowsSdkDir)bin\NETFX 4.0 Tools;$(WindowsSdkDir)bin;$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(FrameworkSDKDir)\bin;$(MSBuildToolsPath32);$(VSInstallDir);$(SystemRoot)\SysWow64;$(FxCopDir);..\..\..\..\bin;$(PATH);</ExecutablePath>
|
||||
<ExecutablePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(VCInstallDir)bin;$(WindowsSdkDir)bin\NETFX 4.0 Tools;$(WindowsSdkDir)bin;$(VSInstallDir)Common7\Tools\bin;$(VSInstallDir)Common7\tools;$(VSInstallDir)Common7\ide;$(ProgramFiles)\HTML Help Workshop;$(FrameworkSDKDir)\bin;$(MSBuildToolsPath32);$(VSInstallDir);$(SystemRoot)\SysWow64;$(FxCopDir);..\..\..\..\bin;$(PATH);</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
|
Loading…
Reference in New Issue
Block a user