| /* |
| * Copyright (C) 2003-2019 Apple Inc. All rights reserved. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| * |
| */ |
| |
| #include "config.h" |
| #include <wtf/dtoa.h> |
| |
| namespace WTF { |
| |
| const char* numberToString(float number, NumberToStringBuffer& buffer) |
| { |
| double_conversion::StringBuilder builder(&buffer[0], sizeof(buffer)); |
| double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToShortestSingle(number, &builder); |
| return builder.Finalize(); |
| } |
| |
| const char* numberToString(double d, NumberToStringBuffer& buffer) |
| { |
| double_conversion::StringBuilder builder(&buffer[0], sizeof(buffer)); |
| auto& converter = double_conversion::DoubleToStringConverter::EcmaScriptConverter(); |
| converter.ToShortest(d, &builder); |
| return builder.Finalize(); |
| } |
| |
| static inline void truncateTrailingZeros(char* buffer, double_conversion::StringBuilder& builder) |
| { |
| size_t length = builder.position(); |
| size_t decimalPointPosition = 0; |
| for (; decimalPointPosition < length; ++decimalPointPosition) { |
| if (buffer[decimalPointPosition] == '.') |
| break; |
| } |
| |
| // No decimal separator found, early exit. |
| if (decimalPointPosition == length) |
| return; |
| |
| size_t pastMantissa = decimalPointPosition + 1; |
| for (; pastMantissa < length; ++pastMantissa) { |
| if (buffer[pastMantissa] == 'e') |
| break; |
| } |
| |
| size_t truncatedLength = pastMantissa; |
| for (; truncatedLength > decimalPointPosition + 1; --truncatedLength) { |
| if (buffer[truncatedLength - 1] != '0') |
| break; |
| } |
| |
| // No trailing zeros found to strip. |
| if (truncatedLength == pastMantissa) |
| return; |
| |
| // If we removed all trailing zeros, remove the decimal point as well. |
| if (truncatedLength == decimalPointPosition + 1) |
| truncatedLength = decimalPointPosition; |
| |
| // Truncate the mantissa, and return the final result. |
| builder.RemoveCharacters(truncatedLength, pastMantissa); |
| } |
| |
| const char* numberToFixedPrecisionString(float number, unsigned significantFigures, NumberToStringBuffer& buffer, bool shouldTruncateTrailingZeros) |
| { |
| // For now, just call the double precision version. |
| // Do that here instead of at callers to pave the way to add a more efficient code path later. |
| return numberToFixedPrecisionString(static_cast<double>(number), significantFigures, buffer, shouldTruncateTrailingZeros); |
| } |
| |
| const char* numberToFixedPrecisionString(double d, unsigned significantFigures, NumberToStringBuffer& buffer, bool shouldTruncateTrailingZeros) |
| { |
| // Mimic sprintf("%.[precision]g", ...). |
| // "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[0], sizeof(buffer)); |
| auto& converter = double_conversion::DoubleToStringConverter::EcmaScriptConverter(); |
| converter.ToPrecision(d, significantFigures, &builder); |
| if (shouldTruncateTrailingZeros) |
| truncateTrailingZeros(buffer.data(), builder); |
| return builder.Finalize(); |
| } |
| |
| const char* numberToFixedWidthString(float number, unsigned decimalPlaces, NumberToStringBuffer& buffer) |
| { |
| // For now, just call the double precision version. |
| // Do that here instead of at callers to pave the way to add a more efficient code path later. |
| return numberToFixedWidthString(static_cast<double>(number), decimalPlaces, buffer); |
| } |
| |
| const char* numberToFixedWidthString(double d, unsigned decimalPlaces, NumberToStringBuffer& buffer) |
| { |
| // Mimic sprintf("%.[precision]f", ...). |
| // "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[0], sizeof(buffer)); |
| auto& converter = double_conversion::DoubleToStringConverter::EcmaScriptConverter(); |
| converter.ToFixed(d, decimalPlaces, &builder); |
| return builder.Finalize(); |
| } |
| |
| const char* numberToCSSString(double d, NumberToCSSStringBuffer& buffer) |
| { |
| // Mimic sprintf("%.[precision]f", ...). |
| // "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[0], sizeof(buffer)); |
| auto& converter = double_conversion::DoubleToStringConverter::CSSConverter(); |
| converter.ToFixedUncapped(d, 6, &builder); |
| truncateTrailingZeros(buffer.data(), builder); |
| // If we've truncated the trailing zeros and a trailing decimal, we may have a -0. Remove the negative sign in this case. |
| if (builder.position() == 2 && buffer[0] == '-' && buffer[1] == '0') |
| builder.RemoveCharacters(0, 1); |
| 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 |