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