Qt 4.8
qatomicmathematicians.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include <math.h>
43 
44 #include <qnumeric.h>
45 
46 #include "qabstractdatetime_p.h"
47 #include "qabstractduration_p.h"
48 #include "qabstractfloat_p.h"
49 #include "qdaytimeduration_p.h"
50 #include "qdecimal_p.h"
51 #include "qinteger_p.h"
52 #include "qpatternistlocale_p.h"
53 
55 
57 
58 using namespace QPatternist;
59 
60 /* The translation strings is place here once, in order to reduce work for translators,
61  * and provide consistency. */
62 
63 static inline QString idivZeroInvalid()
64 {
65  return QtXmlPatterns::tr("Integer division (%1) by zero (%2) is undefined.")
66  .arg(formatKeyword("idiv"))
67  .arg(formatData("0"));
68 }
69 
70 static inline QString divZeroInvalid()
71 {
72  return QtXmlPatterns::tr("Division (%1) by zero (%2) is undefined.")
73  .arg(formatKeyword("div"))
74  .arg(formatData("0"));
75 }
76 
77 static inline QString modZeroInvalid()
78 {
79  return QtXmlPatterns::tr("Modulus division (%1) by zero (%2) is undefined.")
80  .arg(formatKeyword("mod"))
81  .arg(formatData("0"));
82 }
83 
85  const Operator op,
86  const Item &o2,
88 {
89  switch(op)
90  {
91  case Div:
92  {
93  if(o2.as<Numeric>()->toInteger() == 0)
94  {
95  context->error(divZeroInvalid(), ReportContext::FOAR0001, this);
96  return Item(); /* Silences source code analyzer warning. */
97  }
98  else
99  return toItem(Decimal::fromValue(o1.as<Numeric>()->toDecimal() / o2.as<Numeric>()->toDecimal()));
100  }
101  case IDiv:
102  {
103  if(o2.as<Numeric>()->toInteger() == 0)
104  {
105  context->error(idivZeroInvalid(), ReportContext::FOAR0001, this);
106  return Item(); /* Silences source code analyzer warning. */
107  }
108  else
109  return Integer::fromValue(static_cast<xsInteger>(o1.as<Numeric>()->toDecimal() /
110  o2.as<Numeric>()->toDecimal()));
111  }
112  case Substract:
113  return toItem(Decimal::fromValue(o1.as<Numeric>()->toDecimal() - o2.as<Numeric>()->toDecimal()));
114  case Mod:
115  {
116  if(o2.as<Numeric>()->toInteger() == 0)
117  {
118  context->error(modZeroInvalid(), ReportContext::FOAR0001, this);
119  return Item(); /* Silences source code analyzer warning. */
120  }
121  else
122  return toItem(Decimal::fromValue(::fmod(o1.as<Numeric>()->toDecimal(), o2.as<Numeric>()->toDecimal())));
123  }
124  case Multiply:
125  return toItem(Decimal::fromValue(o1.as<Numeric>()->toDecimal() * o2.as<Numeric>()->toDecimal()));
126  case Add:
127  return toItem(Decimal::fromValue(o1.as<Numeric>()->toDecimal() + o2.as<Numeric>()->toDecimal()));
128  }
129 
130  Q_ASSERT(false);
131  return Item(); /* GCC unbarfer. */
132 }
133 
135  const Operator op,
136  const Item &o2,
138 {
139  switch(op)
140  {
141  case Div:
142  if(o2.as<Numeric>()->toInteger() == 0)
143  {
144  context->error(divZeroInvalid(), ReportContext::FOAR0001, this);
145  return Item(); /* Silences source code analyzer warning. */
146  }
147  else /* C++ automatically performs truncation of long integer(xsInteger). */
148  return toItem(Decimal::fromValue(o1.as<Numeric>()->toDecimal() / o2.as<Numeric>()->toDecimal()));
149  case IDiv:
150  {
151  if(o2.as<Numeric>()->toInteger() == 0)
152  {
153  context->error(idivZeroInvalid(), ReportContext::FOAR0001, this);
154  return Item(); /* Silences source code analyzer warning. */
155  }
156  else /* C++ automatically performs truncation of long integer(xsInteger). */
157  return Integer::fromValue(o1.as<Numeric>()->toInteger() / o2.as<Numeric>()->toInteger());
158  }
159  case Substract:
160  return Integer::fromValue(o1.as<Numeric>()->toInteger() - o2.as<Numeric>()->toInteger());
161  case Mod:
162  {
163  const xsInteger divisor = o2.as<Numeric>()->toInteger();
164 
165  if(divisor == 0)
166  {
167  context->error(modZeroInvalid(), ReportContext::FOAR0001, this);
168  return Item(); /* Silences source code analyzer warning. */
169  }
170  else
171  return Integer::fromValue(o1.as<Numeric>()->toInteger() % divisor);
172  }
173  case Multiply:
174  return Integer::fromValue(o1.as<Numeric>()->toInteger() * o2.as<Numeric>()->toInteger());
175  case Add:
176  return Integer::fromValue(o1.as<Numeric>()->toInteger() + o2.as<Numeric>()->toInteger());
177  }
178 
179  Q_ASSERT(false);
180  return Item(); /* GCC unbarfer. */
181 }
182 
184  const Operator op,
185  const Item &o2,
187 {
188  Q_ASSERT(op == Div || op == Multiply);
189 
190  const AbstractDuration::Ptr duration(o1.as<AbstractDuration>());
191  const xsDouble dbl = o2.as<Numeric>()->toDouble();
192 
193  switch(op)
194  {
195  case Div:
196  {
197  if(qIsInf(dbl))
198  return duration->fromValue(0);
199  else if(qIsNaN(dbl))
200  {
201  context->error(QtXmlPatterns::tr(
202  "Dividing a value of type %1 by %2 (not-a-number) "
203  "is not allowed.")
204  .arg(formatType(context->namePool(),
205  duration->type()))
206  .arg(formatData("NaN")),
208  this);
209  return Item();
210  }
211  else if(Double::isEqual(dbl, 0))
212  {
213  context->error(QtXmlPatterns::tr(
214  "Dividing a value of type %1 by %2 or %3 (plus or "
215  "minus zero) is not allowed.")
216  .arg(formatType(context->namePool(),
217  duration->type()))
218  .arg(formatData("-0"))
219  .arg(formatData("0")),
221  this);
222  return Item();
223  }
224 
225  return duration->fromValue(static_cast<AbstractDuration::Value>(duration->value() / dbl));
226  }
227  case Multiply:
228  {
229  if(Double::isEqual(dbl, 0))
230  return duration->fromValue(0);
231  else if(qIsNaN(dbl))
232  {
233  context->error(QtXmlPatterns::tr(
234  "Dividing a value of type %1 by %2 (not-a-number) "
235  "is not allowed.")
236  .arg(formatType(context->namePool(),
237  duration->type()))
238  .arg(formatData("NaN")),
240  this);
241  return Item();
242  }
243  else if(qIsInf(dbl))
244  {
245  context->error(QtXmlPatterns::tr(
246  "Multiplication of a value of type %1 by %2 or %3 "
247  "(plus or minus infinity) is not allowed.")
248  .arg(formatType(context->namePool(),
249  duration->type()))
250  .arg(formatData("-INF"))
251  .arg(formatData("INF")),
253  this);
254  return Item();
255  }
256 
257  return duration->fromValue(static_cast<AbstractDuration::Value>(duration->value() * dbl));
258  }
259  default:
260  {
261  Q_ASSERT(false);
262  return Item(); /* Silence warning. */
263  }
264  }
265 }
266 
268  const Operator op,
269  const Item &o2,
271 {
272  const AbstractDuration::Ptr duration(o1.as<AbstractDuration>());
273  const AbstractDuration::Value op2 = o2.as<AbstractDuration>()->value();
274 
275  switch(op)
276  {
277  case Div:
278  return toItem(Decimal::fromValue(static_cast<xsDecimal>(duration->value()) / op2));
279  case Substract:
280  return duration->fromValue(duration->value() - op2);
281  case Add:
282  return duration->fromValue(duration->value() + op2);
283  default:
284  {
285  Q_ASSERT(false);
286  return Item(); /* Silence warning. */
287  }
288  }
289 }
290 
292 OperandSwitcherMathematician(const AtomicMathematician::Ptr &mathematician) : m_mather(mathematician)
293 {
294  Q_ASSERT(mathematician);
295 }
296 
298  const Operator op,
299  const Item &o2,
301 {
302  return m_mather->calculate(o2, op, o1, context);
303 }
304 
305 
307  const Operator op,
308  const Item &o2,
310 {
311  Q_ASSERT(op == Substract || op == Add);
312 
313  const AbstractDateTime::Ptr adt(o1.as<AbstractDateTime>());
314  const AbstractDuration::Ptr dur(o2.as<AbstractDuration>());
315  QDateTime dt(adt->toDateTime());
316  //pDebug() << "DateTimeDurationMathematician::calculate():" << dt.toString();
317  //dt.setDateOnly(false);
318  const qint8 sign = (op == Add ? 1 : -1) * (dur->isPositive() ? 1 : -1);
319 
320  // TODO milli seconds
321  dt = dt.addSecs(sign * (dur->seconds() + dur->minutes() * 60 + dur->hours() * 60 * 60));
322  dt = dt.addDays(sign * dur->days());
323  dt = dt.addMonths(sign * dur->months());
324  dt = dt.addYears(sign * dur->years());
325 
326  QString msg;
327 
328  if(AbstractDateTime::isRangeValid(dt.date(), msg))
329  return adt->fromValue(dt);
330  else
331  {
332  context->error(msg, ReportContext::FODT0001,
333  this);
334  return Item();
335  }
336 }
337 
339  const Operator op,
340  const Item &o2,
342 {
343  Q_ASSERT(op == Substract || op == Add);
344  QDateTime dt1(o1.as<AbstractDateTime>()->toDateTime());
345  QDateTime dt2(o2.as<AbstractDateTime>()->toDateTime());
346 
347  const int diff = op == Add ? dt1.secsTo(dt2) : dt2.secsTo(dt1);
348 
349  return toItem(DayTimeDuration::fromSeconds(diff));
350 }
351 
virtual NamePool::Ptr namePool() const =0
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
Base class for classes implementing durations.
Base class for classes implementing values related to time, date or both.
QString formatKeyword(const QString &keyword)
virtual xsFloat toDecimal() const =0
qint64 xsInteger
QString formatType(const NamePool::Ptr &np, const T &type)
Formats ItemType and SequenceType.
Item toItem(const QExplicitlySharedDataPointer< T > atomicValue)
Definition: qitem_p.h:431
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static Item fromValue(const xsInteger num)
Definition: qinteger.cpp:52
static int sign(int x)
static DayTimeDuration::Ptr fromSeconds(const SecondCountProperty secs, const MSecondProperty msecs=0)
signed char qint8
Definition: qglobal.h:933
static QString idivZeroInvalid()
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void error(const QString &message, const ReportContext::ErrorCode errorCode, const QSourceLocation &sourceLocation)
virtual Item calculate(const Item &o1, const Operator op, const Item &o2, const QExplicitlySharedDataPointer< DynamicContext > &context) const
The namespace for the internal API of QtXmlPatterns.
virtual Item calculate(const Item &o1, const Operator op, const Item &o2, const QExplicitlySharedDataPointer< DynamicContext > &context) const
static Bigint * diff(Bigint *a, Bigint *b)
static QString modZeroInvalid()
const QDateTime & toDateTime() const
virtual Item calculate(const Item &o1, const Operator op, const Item &o2, const QExplicitlySharedDataPointer< DynamicContext > &context) const
static Decimal::Ptr fromValue(const xsDecimal num)
Definition: qdecimal.cpp:59
static QString formatData(const QString &data)
virtual Item calculate(const Item &o1, const Operator op, const Item &o2, const QExplicitlySharedDataPointer< DynamicContext > &context) const
Contains classes performing arithemetic operations between atomic values, such as subtracting two dat...
Q_CORE_EXPORT bool qIsNaN(double d)
Returns true if the double {d} is not a number (NaN).
Definition: qnumeric.cpp:55
virtual Item calculate(const Item &o1, const Operator op, const Item &o2, const QExplicitlySharedDataPointer< DynamicContext > &context) const
virtual Item calculate(const Item &o1, const Operator op, const Item &o2, const QExplicitlySharedDataPointer< DynamicContext > &context) const
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
OperandSwitcherMathematician(const AtomicMathematician::Ptr &mathematician)
qint64 Value
The amount in milli seconds.
Contains functions used for formatting arguments, such as keywords and paths, in translated strings...
The QDateTime class provides date and time functions.
Definition: qdatetime.h:216
Represents an item in the XPath 2.0 Data Model.
Definition: qitem_p.h:182
static bool isEqual(const xsDouble a, const xsDouble b)
Base class for all numeric values.
static bool isRangeValid(const QDate &date, QString &message)
virtual xsInteger toInteger() const =0
static QString divZeroInvalid()
virtual Item calculate(const Item &o1, const Operator op, const Item &o2, const QExplicitlySharedDataPointer< DynamicContext > &context) const
static qreal toDouble(const QChar *&str)
TCastTarget * as() const
Definition: qitem_p.h:278
virtual Item calculate(const Item &operand1, const Operator op, const Item &operand2, const QExplicitlySharedDataPointer< DynamicContext > &context) const =0
Q_CORE_EXPORT bool qIsInf(double d)
Returns true if the double {d} is equivalent to infinity.
Definition: qnumeric.cpp:50