Home | History | Annotate | Download | only in wtf
      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