Merge "Better solution for Docomo 1339 bug." into tizen_2.1
[framework/web/webkit-efl.git] / Source / WTF / wtf / DecimalNumber.cpp
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