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 31 #include "wtf/MathExtras.h" 32 #include "wtf/WTFExport.h" 33 #include "wtf/dtoa.h" 34 35 namespace WTF { 36 37 enum RoundingSignificantFiguresType { RoundingSignificantFigures }; 38 enum RoundingDecimalPlacesType { RoundingDecimalPlaces }; 39 40 class WTF_EXPORT DecimalNumber { 41 public: 42 DecimalNumber(double d) 43 { 44 ASSERT(std::isfinite(d)); 45 dtoa(m_significand, d, m_sign, m_exponent, m_precision); 46 47 ASSERT(m_precision); 48 // Zero should always have exponent 0. 49 ASSERT(m_significand[0] != '0' || !m_exponent); 50 // No values other than zero should have a leading zero. 51 ASSERT(m_significand[0] != '0' || m_precision == 1); 52 // No values other than zero should have trailing zeros. 53 ASSERT(m_significand[0] == '0' || m_significand[m_precision - 1] != '0'); 54 } 55 56 DecimalNumber(double d, RoundingSignificantFiguresType, unsigned significantFigures) 57 { 58 ASSERT(std::isfinite(d)); 59 dtoaRoundSF(m_significand, d, significantFigures, m_sign, m_exponent, m_precision); 60 61 ASSERT_WITH_SECURITY_IMPLICATION(significantFigures && significantFigures <= sizeof(DtoaBuffer)); 62 while (m_precision < significantFigures) 63 m_significand[m_precision++] = '0'; 64 65 ASSERT(m_precision); 66 // Zero should always have exponent 0. 67 ASSERT(m_significand[0] != '0' || !m_exponent); 68 } 69 70 DecimalNumber(double d, RoundingDecimalPlacesType, unsigned decimalPlaces) 71 { 72 ASSERT(std::isfinite(d)); 73 dtoaRoundDP(m_significand, d, decimalPlaces, m_sign, m_exponent, m_precision); 74 75 unsigned significantFigures = 1 + m_exponent + decimalPlaces; 76 ASSERT_WITH_SECURITY_IMPLICATION(significantFigures && significantFigures <= sizeof(DtoaBuffer)); 77 while (m_precision < significantFigures) 78 m_significand[m_precision++] = '0'; 79 80 ASSERT(m_precision); 81 // Zero should always have exponent 0. 82 ASSERT(m_significand[0] != '0' || !m_exponent); 83 } 84 85 unsigned bufferLengthForStringDecimal() const; 86 unsigned bufferLengthForStringExponential() const; 87 88 unsigned toStringDecimal(LChar* buffer, unsigned bufferLength) const; 89 unsigned toStringExponential(LChar* buffer, unsigned bufferLength) const; 90 91 bool sign() const { return m_sign; } 92 int exponent() const { return m_exponent; } 93 const char* significand() const { return m_significand; } // significand contains precision characters, is not null-terminated. 94 unsigned precision() const { return m_precision; } 95 96 private: 97 bool m_sign; 98 int m_exponent; 99 DtoaBuffer m_significand; 100 unsigned m_precision; 101 }; 102 103 } // namespace WTF 104 105 using WTF::DecimalNumber; 106 using WTF::RoundingSignificantFigures; 107 using WTF::RoundingDecimalPlaces; 108 109 #endif // DecimalNumber_h 110