1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
/****************************************************************
*
* The author of this software is David M. Gay.
*
* Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
* Copyright (C) 2002, 2005, 2006, 2007, 2008, 2010, 2012 Apple Inc.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose without fee is hereby granted, provided that this entire notice
* is included in all copies of any software which is or includes a copy
* or modification of this software and in all copies of the supporting
* documentation for such software.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
*
***************************************************************/
/* Please send bug reports to David M. Gay (dmg at acm dot org,
* with " at " changed at "@" and " dot " changed to "."). */
/* On a machine with IEEE extended-precision registers, it is
* necessary to specify double-precision (53-bit) rounding precision
* before invoking strtod or dtoa. If the machine uses (the equivalent
* of) Intel 80x87 arithmetic, the call
* _control87(PC_53, MCW_PC);
* does this with many compilers. Whether this or another call is
* appropriate depends on the compiler; for this to work, it may be
* necessary to #include "float.h" or another system-dependent header
* file.
*/
#include "wtf/dtoa.h"
#include "wtf/Vector.h"
#include <string.h>
namespace WTF {
const char* numberToString(double d, NumberToStringBuffer buffer) {
double_conversion::StringBuilder builder(buffer, NumberToStringBufferLength);
const double_conversion::DoubleToStringConverter& converter =
double_conversion::DoubleToStringConverter::EcmaScriptConverter();
converter.ToShortest(d, &builder);
return builder.Finalize();
}
static inline const char* formatStringTruncatingTrailingZerosIfNeeded(
NumberToStringBuffer buffer,
double_conversion::StringBuilder& builder) {
size_t length = builder.position();
// If there is an exponent, stripping trailing zeros would be incorrect.
// FIXME: Zeros should be stripped before the 'e'.
if (memchr(buffer, 'e', length))
return builder.Finalize();
size_t decimalPointPosition = 0;
for (; decimalPointPosition < length; ++decimalPointPosition) {
if (buffer[decimalPointPosition] == '.')
break;
}
// No decimal seperator found, early exit.
if (decimalPointPosition == length)
return builder.Finalize();
size_t truncatedLength = length - 1;
for (; truncatedLength > decimalPointPosition; --truncatedLength) {
if (buffer[truncatedLength] != '0')
break;
}
// No trailing zeros found to strip.
if (truncatedLength == length - 1)
return builder.Finalize();
// If we removed all trailing zeros, remove the decimal point as well.
if (truncatedLength == decimalPointPosition) {
DCHECK_GT(truncatedLength, 0u);
--truncatedLength;
}
// Truncate the StringBuilder, and return the final result.
builder.SetPosition(truncatedLength + 1);
return builder.Finalize();
}
const char* numberToFixedPrecisionString(double d,
unsigned significantFigures,
NumberToStringBuffer buffer) {
// Mimic String::format("%.[precision]g", ...), but use dtoas rounding
// facilities.
// "g": Signed value printed in f or e format, whichever is more compact for
// the given value and precision.
// The e format is used only when the exponent of the value is less than -4 or
// greater than or equal to the precision argument. Trailing zeros are
// truncated, and the decimal point appears only if one or more digits follow
// it.
// "precision": The precision specifies the maximum number of significant
// digits printed.
double_conversion::StringBuilder builder(buffer, NumberToStringBufferLength);
const double_conversion::DoubleToStringConverter& converter =
double_conversion::DoubleToStringConverter::EcmaScriptConverter();
converter.ToPrecision(d, significantFigures, &builder);
// FIXME: Trailing zeros should never be added in the first place. The
// current implementation does not strip when there is an exponent, eg.
// 1.50000e+10.
return formatStringTruncatingTrailingZerosIfNeeded(buffer, builder);
}
const char* numberToFixedWidthString(double d,
unsigned decimalPlaces,
NumberToStringBuffer buffer) {
// Mimic String::format("%.[precision]f", ...), but use dtoas rounding
// facilities.
// "f": Signed value having the form [ - ]dddd.dddd, where dddd is one or more
// decimal digits. The number of digits before the decimal point depends on
// the magnitude of the number, and the number of digits after the decimal
// point depends on the requested precision.
// "precision": The precision value specifies the number of digits after the
// decimal point. If a decimal point appears, at least one digit appears
// before it. The value is rounded to the appropriate number of digits.
double_conversion::StringBuilder builder(buffer, NumberToStringBufferLength);
const double_conversion::DoubleToStringConverter& converter =
double_conversion::DoubleToStringConverter::EcmaScriptConverter();
converter.ToFixed(d, decimalPlaces, &builder);
return builder.Finalize();
}
namespace Internal {
double parseDoubleFromLongString(const UChar* string,
size_t length,
size_t& parsedLength) {
Vector<LChar> conversionBuffer(length);
for (size_t i = 0; i < length; ++i)
conversionBuffer[i] = isASCII(string[i]) ? string[i] : 0;
return parseDouble(conversionBuffer.data(), length, parsedLength);
}
} // namespace Internal
} // namespace WTF
|