mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 608915 - part 2 - use MFBT's double-conversion code in nsString::AppendFloat; r=bz,gps
This commit is contained in:
parent
a3fdb565b6
commit
0cdfeef8f7
@ -445,12 +445,8 @@ class nsTSubstring_CharT
|
||||
/**
|
||||
* Append the given float to this string
|
||||
*/
|
||||
void AppendFloat( float aFloat )
|
||||
{ DoAppendFloat(aFloat, 6); }
|
||||
void AppendFloat( double aFloat )
|
||||
{ DoAppendFloat(aFloat, 15); }
|
||||
private:
|
||||
void NS_FASTCALL DoAppendFloat( double aFloat, int digits );
|
||||
void NS_FASTCALL AppendFloat( float aFloat );
|
||||
void NS_FASTCALL AppendFloat( double aFloat );
|
||||
public:
|
||||
|
||||
// AppendLiteral must ONLY be applied to an actual literal string.
|
||||
|
@ -25,6 +25,10 @@ if CONFIG['INTEL_ARCHITECTURE']:
|
||||
'nsUTF8UtilsSSE2.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/mfbt/double-conversion',
|
||||
]
|
||||
|
||||
LIBRARY_NAME = 'string_s'
|
||||
|
||||
MSVC_ENABLE_PGO = True
|
||||
|
@ -4,7 +4,9 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "prdtoa.h"
|
||||
#include "double-conversion.h"
|
||||
|
||||
using double_conversion::DoubleToStringConverter;
|
||||
|
||||
#ifdef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
|
||||
nsTSubstring_CharT::nsTSubstring_CharT( char_type *data, size_type length,
|
||||
@ -790,103 +792,94 @@ void nsTSubstring_CharT::AppendPrintf( const char* format, va_list ap )
|
||||
NS_RUNTIMEABORT("Allocation or other failure in PR_vsxprintf");
|
||||
}
|
||||
|
||||
/* hack to make sure we define Modified_cnvtf only once */
|
||||
/* hack to make sure we define FormatWithoutTrailingZeros only once */
|
||||
#ifdef CharT_is_PRUnichar
|
||||
/**
|
||||
* This is a copy of |PR_cnvtf| with a bug fixed. (The second argument
|
||||
* of PR_dtoa is 2 rather than 1.)
|
||||
*
|
||||
* XXX(darin): if this is the right thing, then why wasn't it fixed in NSPR?!?
|
||||
*/
|
||||
static void
|
||||
Modified_cnvtf(char (& buf)[40], int prcsn, double fval)
|
||||
// Returns the length of the formatted aDouble in buf.
|
||||
static int
|
||||
FormatWithoutTrailingZeros(char (& buf)[40], double aDouble,
|
||||
int precision)
|
||||
{
|
||||
int decpt, sign, numdigits;
|
||||
char num[40];
|
||||
char *nump;
|
||||
char *bufp = buf;
|
||||
char *endnum;
|
||||
static const DoubleToStringConverter converter(DoubleToStringConverter::UNIQUE_ZERO |
|
||||
DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN,
|
||||
"Infinity",
|
||||
"NaN",
|
||||
'e',
|
||||
-6, 21,
|
||||
6, 1);
|
||||
double_conversion::StringBuilder builder(buf, sizeof(buf));
|
||||
bool exponential_notation = false;
|
||||
converter.ToPrecision(aDouble, precision, &exponential_notation, &builder);
|
||||
int length = builder.position();
|
||||
char* formattedDouble = builder.Finalize();
|
||||
|
||||
if (PR_dtoa(fval, 2, prcsn, &decpt, &sign, &endnum, num, sizeof(num))
|
||||
== PR_FAILURE) {
|
||||
buf[0] = '\0';
|
||||
return;
|
||||
// If we have a shorter string than precision, it means we have a special
|
||||
// value (NaN or Infinity). All other numbers will be formatted with at
|
||||
// least precision digits.
|
||||
if (length <= precision) {
|
||||
return length;
|
||||
}
|
||||
numdigits = endnum - num;
|
||||
nump = num;
|
||||
|
||||
/*
|
||||
* The NSPR code had a fancy way of checking that we weren't dealing
|
||||
* with -0.0 or -NaN, but I'll just use < instead.
|
||||
* XXX Should we check !isnan(fval) as well? Is it portable? We
|
||||
* probably don't need to bother since NAN isn't portable.
|
||||
*/
|
||||
if (sign && fval < 0.0f) {
|
||||
*bufp++ = '-';
|
||||
|
||||
char* end = formattedDouble + length;
|
||||
char* decimalPoint = strchr(buf, '.');
|
||||
// No trailing zeros to remove.
|
||||
if (decimalPoint == nullptr) {
|
||||
return length;
|
||||
}
|
||||
|
||||
if (decpt == 9999) {
|
||||
while ((*bufp++ = *nump++) != 0) {} /* nothing to execute */
|
||||
return;
|
||||
}
|
||||
|
||||
if (decpt > (prcsn+1) || decpt < -(prcsn-1) || decpt < -5) {
|
||||
*bufp++ = *nump++;
|
||||
if (numdigits != 1) {
|
||||
*bufp++ = '.';
|
||||
}
|
||||
|
||||
while (*nump != '\0') {
|
||||
*bufp++ = *nump++;
|
||||
}
|
||||
*bufp++ = 'e';
|
||||
PR_snprintf(bufp, sizeof(num) - (bufp - buf), "%+d", decpt-1);
|
||||
}
|
||||
else if (decpt >= 0) {
|
||||
if (decpt == 0) {
|
||||
*bufp++ = '0';
|
||||
}
|
||||
else {
|
||||
while (decpt--) {
|
||||
if (*nump != '\0') {
|
||||
*bufp++ = *nump++;
|
||||
}
|
||||
else {
|
||||
*bufp++ = '0';
|
||||
}
|
||||
if (MOZ_UNLIKELY(exponential_notation)) {
|
||||
// We need to check for cases like 1.00000e-10 (yes, this is
|
||||
// disgusting).
|
||||
char* exponent = end - 1;
|
||||
for ( ; ; --exponent) {
|
||||
if (*exponent == 'e') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*nump != '\0') {
|
||||
*bufp++ = '.';
|
||||
while (*nump != '\0') {
|
||||
*bufp++ = *nump++;
|
||||
char* zerosBeforeExponent = exponent - 1;
|
||||
for ( ; zerosBeforeExponent != decimalPoint; --zerosBeforeExponent) {
|
||||
if (*zerosBeforeExponent != '0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*bufp++ = '\0';
|
||||
}
|
||||
else if (decpt < 0) {
|
||||
*bufp++ = '0';
|
||||
*bufp++ = '.';
|
||||
while (decpt++) {
|
||||
*bufp++ = '0';
|
||||
if (zerosBeforeExponent == decimalPoint) {
|
||||
--zerosBeforeExponent;
|
||||
}
|
||||
// Slide the exponent to the left over the trailing zeros. Don't
|
||||
// worry about copying the trailing NUL character.
|
||||
size_t exponentSize = end - exponent;
|
||||
memmove(zerosBeforeExponent + 1, exponent, exponentSize);
|
||||
length -= exponent - (zerosBeforeExponent + 1);
|
||||
} else {
|
||||
char* trailingZeros = end - 1;
|
||||
for ( ; trailingZeros != decimalPoint; --trailingZeros) {
|
||||
if (*trailingZeros != '0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (trailingZeros == decimalPoint) {
|
||||
--trailingZeros;
|
||||
}
|
||||
length -= end - (trailingZeros + 1);
|
||||
}
|
||||
|
||||
while (*nump != '\0') {
|
||||
*bufp++ = *nump++;
|
||||
}
|
||||
*bufp++ = '\0';
|
||||
}
|
||||
return length;
|
||||
}
|
||||
#endif /* CharT_is_PRUnichar */
|
||||
|
||||
void
|
||||
nsTSubstring_CharT::DoAppendFloat( double aFloat, int digits )
|
||||
nsTSubstring_CharT::AppendFloat( float aFloat )
|
||||
{
|
||||
char buf[40];
|
||||
// Use Modified_cnvtf, which is locale-insensitive, instead of the
|
||||
// locale-sensitive PR_snprintf or sprintf(3)
|
||||
Modified_cnvtf(buf, digits, aFloat);
|
||||
AppendASCII(buf);
|
||||
int length = FormatWithoutTrailingZeros(buf, aFloat, 6);
|
||||
AppendASCII(buf, length);
|
||||
}
|
||||
|
||||
void
|
||||
nsTSubstring_CharT::AppendFloat( double aFloat )
|
||||
{
|
||||
char buf[40];
|
||||
int length = FormatWithoutTrailingZeros(buf, aFloat, 15);
|
||||
AppendASCII(buf, length);
|
||||
}
|
||||
|
||||
size_t
|
||||
|
Loading…
Reference in New Issue
Block a user