src/xmlpatterns/data/qdecimal.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <math.h>
       
    43 
       
    44 #include "qabstractfloat_p.h"
       
    45 #include "qatomictype_p.h"
       
    46 #include "qbuiltintypes_p.h"
       
    47 #include "qvalidationerror_p.h"
       
    48 
       
    49 #include "qdecimal_p.h"
       
    50 
       
    51 QT_BEGIN_NAMESPACE
       
    52 
       
    53 using namespace QPatternist;
       
    54 
       
    55 Decimal::Decimal(const xsDecimal num) : m_value(num)
       
    56 {
       
    57 }
       
    58 
       
    59 Decimal::Ptr Decimal::fromValue(const xsDecimal num)
       
    60 {
       
    61     return Decimal::Ptr(new Decimal(num));
       
    62 }
       
    63 
       
    64 AtomicValue::Ptr Decimal::fromLexical(const QString &strNumeric)
       
    65 {
       
    66     /* QString::toDouble() handles the whitespace facet. */
       
    67     const QString strNumericTrimmed(strNumeric.trimmed());
       
    68 
       
    69     /* Block these out, as QString::toDouble() supports them. */
       
    70     if(strNumericTrimmed.compare(QLatin1String("-INF"), Qt::CaseInsensitive) == 0
       
    71        || strNumericTrimmed.compare(QLatin1String("INF"), Qt::CaseInsensitive)  == 0
       
    72        || strNumericTrimmed.compare(QLatin1String("+INF"), Qt::CaseInsensitive)  == 0
       
    73        || strNumericTrimmed.compare(QLatin1String("nan"), Qt::CaseInsensitive)  == 0
       
    74        || strNumericTrimmed.contains(QLatin1Char('e'))
       
    75        || strNumericTrimmed.contains(QLatin1Char('E')))
       
    76     {
       
    77         return ValidationError::createError();
       
    78     }
       
    79 
       
    80     bool conversionOk = false;
       
    81     const xsDecimal num = strNumericTrimmed.toDouble(&conversionOk);
       
    82 
       
    83     if(conversionOk)
       
    84         return AtomicValue::Ptr(new Decimal(num));
       
    85     else
       
    86         return ValidationError::createError();
       
    87 }
       
    88 
       
    89 bool Decimal::evaluateEBV(const QExplicitlySharedDataPointer<DynamicContext> &) const
       
    90 {
       
    91     return !Double::isEqual(m_value, 0.0);
       
    92 }
       
    93 
       
    94 QString Decimal::stringValue() const
       
    95 {
       
    96     return toString(m_value);
       
    97 }
       
    98 
       
    99 QString Decimal::toString(const xsDecimal value)
       
   100 {
       
   101     /*
       
   102      * If SV is in the value space of xs:integer, that is, if there are no
       
   103      * significant digits after the decimal point, then the value is converted
       
   104      * from an xs:decimal to an xs:integer and the resulting xs:integer is
       
   105      * converted to an xs:string using the rule above.
       
   106      */
       
   107     if(Double::isEqual(::floor(value), value))
       
   108     {
       
   109         /* The static_cast is identical to Integer::toInteger(). */
       
   110         return QString::number(static_cast<xsInteger>(value));
       
   111     }
       
   112     else
       
   113     {
       
   114         int sign;
       
   115         int decimalPoint;
       
   116         char *result = 0;
       
   117         static_cast<void>(qdtoa(value, 0, 0, &decimalPoint, &sign, 0, &result));
       
   118         /* If the copy constructor is used instead of QString::operator=(),
       
   119          * it doesn't compile. I have no idea why. */
       
   120         const QString qret(QString::fromLatin1(result));
       
   121         delete result;
       
   122 
       
   123         QString valueAsString;
       
   124 
       
   125         if(sign)
       
   126             valueAsString += QLatin1Char('-');
       
   127 
       
   128         if(0 < decimalPoint)
       
   129         {
       
   130             valueAsString += qret.left(decimalPoint);
       
   131             valueAsString += QLatin1Char('.');
       
   132             if (qret.size() <= decimalPoint)
       
   133                 valueAsString += QLatin1Char('0');
       
   134             else
       
   135                 valueAsString += qret.mid(decimalPoint);
       
   136         }
       
   137         else
       
   138         {
       
   139             valueAsString += QLatin1Char('0');
       
   140             valueAsString += QLatin1Char('.');
       
   141 
       
   142             for(int d = decimalPoint; d < 0; d++)
       
   143                 valueAsString += QLatin1Char('0');
       
   144 
       
   145             valueAsString += qret;
       
   146         }
       
   147 
       
   148         return valueAsString;
       
   149     }
       
   150 }
       
   151 
       
   152 ItemType::Ptr Decimal::type() const
       
   153 {
       
   154     return BuiltinTypes::xsDecimal;
       
   155 }
       
   156 
       
   157 xsDouble Decimal::toDouble() const
       
   158 {
       
   159     return static_cast<xsDouble>(m_value);
       
   160 }
       
   161 
       
   162 xsInteger Decimal::toInteger() const
       
   163 {
       
   164     return static_cast<xsInteger>(m_value);
       
   165 }
       
   166 
       
   167 xsFloat Decimal::toFloat() const
       
   168 {
       
   169     return static_cast<xsFloat>(m_value);
       
   170 }
       
   171 
       
   172 xsDecimal Decimal::toDecimal() const
       
   173 {
       
   174     return m_value;
       
   175 }
       
   176 
       
   177 qulonglong Decimal::toUnsignedInteger() const
       
   178 {
       
   179     Q_ASSERT_X(false, Q_FUNC_INFO,
       
   180                "It makes no sense to call this function, see Numeric::toUnsignedInteger().");
       
   181     return 0;
       
   182 }
       
   183 
       
   184 Numeric::Ptr Decimal::round() const
       
   185 {
       
   186     return Numeric::Ptr(new Decimal(roundFloat(m_value)));
       
   187 }
       
   188 
       
   189 Numeric::Ptr Decimal::roundHalfToEven(const xsInteger /*scale*/) const
       
   190 {
       
   191     return Numeric::Ptr();
       
   192 }
       
   193 
       
   194 Numeric::Ptr Decimal::floor() const
       
   195 {
       
   196     return Numeric::Ptr(new Decimal(static_cast<xsDecimal>(::floor(m_value))));
       
   197 }
       
   198 
       
   199 Numeric::Ptr Decimal::ceiling() const
       
   200 {
       
   201     return Numeric::Ptr(new Decimal(static_cast<xsDecimal>(ceil(m_value))));
       
   202 }
       
   203 
       
   204 Numeric::Ptr Decimal::abs() const
       
   205 {
       
   206     return Numeric::Ptr(new Decimal(static_cast<xsDecimal>(fabs(m_value))));
       
   207 }
       
   208 
       
   209 bool Decimal::isNaN() const
       
   210 {
       
   211     return false;
       
   212 }
       
   213 
       
   214 bool Decimal::isInf() const
       
   215 {
       
   216     return false;
       
   217 }
       
   218 
       
   219 Item Decimal::toNegated() const
       
   220 {
       
   221     if(AbstractFloat<true>::isEqual(m_value, 0.0))
       
   222         return fromValue(0).data();
       
   223     else
       
   224         return fromValue(-m_value).data();
       
   225 }
       
   226 
       
   227 bool Decimal::isSigned() const
       
   228 {
       
   229     Q_ASSERT_X(false, Q_FUNC_INFO,
       
   230                "It makes no sense to call this function, see Numeric::isSigned().");
       
   231     return false;
       
   232 }
       
   233 
       
   234 QT_END_NAMESPACE