1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef DecimalNumber_h
27#define DecimalNumber_h
28
29#include <math.h>
30#include <wtf/dtoa.h>
31#include <wtf/MathExtras.h>
32#include <wtf/text/WTFString.h>
33
34namespace WTF {
35
36enum RoundingSignificantFiguresType { RoundingSignificantFigures };
37enum RoundingDecimalPlacesType { RoundingDecimalPlaces };
38
39class DecimalNumber {
40public:
41    DecimalNumber(double d)
42    {
43        ASSERT(std::isfinite(d));
44        dtoa(m_significand, d, m_sign, m_exponent, m_precision);
45
46        ASSERT(m_precision);
47        // Zero should always have exponent 0.
48        ASSERT(m_significand[0] != '0' || !m_exponent);
49        // No values other than zero should have a leading zero.
50        ASSERT(m_significand[0] != '0' || m_precision == 1);
51        // No values other than zero should have trailing zeros.
52        ASSERT(m_significand[0] == '0' || m_significand[m_precision - 1] != '0');
53    }
54
55    DecimalNumber(double d, RoundingSignificantFiguresType, unsigned significantFigures)
56    {
57        ASSERT(std::isfinite(d));
58        dtoaRoundSF(m_significand, d, significantFigures, m_sign, m_exponent, m_precision);
59
60        ASSERT_WITH_SECURITY_IMPLICATION(significantFigures && significantFigures <= sizeof(DtoaBuffer));
61        while (m_precision < significantFigures)
62            m_significand[m_precision++] = '0';
63
64        ASSERT(m_precision);
65        // Zero should always have exponent 0.
66        ASSERT(m_significand[0] != '0' || !m_exponent);
67    }
68
69    DecimalNumber(double d, RoundingDecimalPlacesType, unsigned decimalPlaces)
70    {
71        ASSERT(std::isfinite(d));
72        dtoaRoundDP(m_significand, d, decimalPlaces, m_sign, m_exponent, m_precision);
73
74        unsigned significantFigures = 1 + m_exponent + decimalPlaces;
75        ASSERT_WITH_SECURITY_IMPLICATION(significantFigures && significantFigures <= sizeof(DtoaBuffer));
76        while (m_precision < significantFigures)
77            m_significand[m_precision++] = '0';
78
79        ASSERT(m_precision);
80        // Zero should always have exponent 0.
81        ASSERT(m_significand[0] != '0' || !m_exponent);
82    }
83
84    WTF_EXPORT_PRIVATE unsigned bufferLengthForStringDecimal() const;
85    WTF_EXPORT_PRIVATE unsigned bufferLengthForStringExponential() const;
86
87    WTF_EXPORT_PRIVATE unsigned toStringDecimal(LChar* buffer, unsigned bufferLength) const;
88    WTF_EXPORT_PRIVATE unsigned toStringExponential(LChar* buffer, unsigned bufferLength) const;
89
90    bool sign() const { return m_sign; }
91    int exponent() const { return m_exponent; }
92    const char* significand() const { return m_significand; } // significand contains precision characters, is not null-terminated.
93    unsigned precision() const { return m_precision; }
94
95private:
96    bool m_sign;
97    int m_exponent;
98    DtoaBuffer m_significand;
99    unsigned m_precision;
100};
101
102} // namespace WTF
103
104using WTF::DecimalNumber;
105using WTF::RoundingSignificantFigures;
106using WTF::RoundingDecimalPlaces;
107
108#endif // DecimalNumber_h
109