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 #include "config.h" 27 #include "DecimalNumber.h" 28 29 namespace WTF { 30 31 unsigned DecimalNumber::bufferLengthForStringDecimal() const 32 { 33 unsigned length = 0; 34 // if the exponent is negative the number decimal representation is of the form: 35 // [<sign>]0.[<zeros>]<significand> 36 if (m_exponent < 0) { 37 if (m_sign) 38 ++length; 39 length += 2; // for "0." 40 length += -m_exponent - 1; 41 length += m_precision; 42 return length; 43 } 44 45 unsigned digitsBeforeDecimalPoint = m_exponent + 1; 46 47 // If the precision is <= than the number of digits to get up to the decimal 48 // point, then there is no fractional part, number is of the form: 49 // [<sign>]<significand>[<zeros>] 50 if (m_precision <= digitsBeforeDecimalPoint) { 51 if (m_sign) 52 ++length; 53 length += m_precision; 54 length += digitsBeforeDecimalPoint - m_precision; 55 return length; 56 } 57 58 // If we get here, number starts before the decimal point, and ends after it, 59 // as such is of the form: 60 // [<sign>]<significand-begin>.<significand-end> 61 if (m_sign) 62 ++length; 63 length += digitsBeforeDecimalPoint; 64 ++length; // for decimal point 65 length += m_precision - digitsBeforeDecimalPoint; 66 67 return length; 68 } 69 70 unsigned DecimalNumber::bufferLengthForStringExponential() const 71 { 72 unsigned length = 0; 73 if (m_sign) 74 ++length; 75 76 // Add the significand 77 ++length; 78 79 if (m_precision > 1) { 80 ++length; // for decimal point 81 length += m_precision - 1; 82 } 83 84 // Add "e+" or "e-" 85 length += 2; 86 87 int exponent = (m_exponent >= 0) ? m_exponent : -m_exponent; 88 89 // Add the exponent 90 if (exponent >= 100) 91 ++length; 92 if (exponent >= 10) 93 ++length; 94 ++length; 95 96 return length; 97 } 98 99 unsigned DecimalNumber::toStringDecimal(LChar* buffer, unsigned bufferLength) const 100 { 101 ASSERT_UNUSED(bufferLength, bufferLength >= bufferLengthForStringDecimal()); 102 103 // Should always be at least one digit to add to the string! 104 ASSERT(m_precision); 105 LChar* next = buffer; 106 107 // if the exponent is negative the number decimal representation is of the form: 108 // [<sign>]0.[<zeros>]<significand> 109 if (m_exponent < 0) { 110 unsigned zeros = -m_exponent - 1; 111 112 if (m_sign) 113 *next++ = '-'; 114 *next++ = '0'; 115 *next++ = '.'; 116 for (unsigned i = 0; i < zeros; ++i) 117 *next++ = '0'; 118 for (unsigned i = 0; i < m_precision; ++i) 119 *next++ = m_significand[i]; 120 121 return next - buffer; 122 } 123 124 unsigned digitsBeforeDecimalPoint = m_exponent + 1; 125 126 // If the precision is <= than the number of digits to get up to the decimal 127 // point, then there is no fractional part, number is of the form: 128 // [<sign>]<significand>[<zeros>] 129 if (m_precision <= digitsBeforeDecimalPoint) { 130 if (m_sign) 131 *next++ = '-'; 132 for (unsigned i = 0; i < m_precision; ++i) 133 *next++ = m_significand[i]; 134 for (unsigned i = 0; i < (digitsBeforeDecimalPoint - m_precision); ++i) 135 *next++ = '0'; 136 137 return next - buffer; 138 } 139 140 // If we get here, number starts before the decimal point, and ends after it, 141 // as such is of the form: 142 // [<sign>]<significand-begin>.<significand-end> 143 144 if (m_sign) 145 *next++ = '-'; 146 for (unsigned i = 0; i < digitsBeforeDecimalPoint; ++i) 147 *next++ = m_significand[i]; 148 *next++ = '.'; 149 for (unsigned i = digitsBeforeDecimalPoint; i < m_precision; ++i) 150 *next++ = m_significand[i]; 151 152 return next - buffer; 153 } 154 155 unsigned DecimalNumber::toStringExponential(LChar* buffer, unsigned bufferLength) const 156 { 157 ASSERT_UNUSED(bufferLength, bufferLength >= bufferLengthForStringExponential()); 158 159 // Should always be at least one digit to add to the string! 160 ASSERT(m_precision); 161 LChar* next = buffer; 162 163 // Add the sign 164 if (m_sign) 165 *next++ = '-'; 166 167 // Add the significand 168 *next++ = m_significand[0]; 169 if (m_precision > 1) { 170 *next++ = '.'; 171 for (unsigned i = 1; i < m_precision; ++i) 172 *next++ = m_significand[i]; 173 } 174 175 // Add "e+" or "e-" 176 *next++ = 'e'; 177 int exponent; 178 if (m_exponent >= 0) { 179 *next++ = '+'; 180 exponent = m_exponent; 181 } else { 182 *next++ = '-'; 183 exponent = -m_exponent; 184 } 185 186 // Add the exponent 187 if (exponent >= 100) 188 *next++ = '0' + exponent / 100; 189 if (exponent >= 10) 190 *next++ = '0' + (exponent % 100) / 10; 191 *next++ = '0' + exponent % 10; 192 193 return next - buffer; 194 } 195 196 } // namespace WTF 197