1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
46 // This file is not part of the Qt API. It exists purely as an
47 // implementation detail. This header file may change from version to
48 // version without notice, or even be removed.
52 #ifndef Patternist_DerivedInteger_H
53 #define Patternist_DerivedInteger_H
55 #include <private/qbuiltintypes_p.h>
56 #include <private/qinteger_p.h>
57 #include <private/qpatternistlocale_p.h>
58 #include <private/qvalidationerror_p.h>
67 * @relates DerivedInteger
69 enum DerivedIntegerLimitsUsage
74 LimitBoth = LimitUpwards | LimitDownwards
79 IgnorableSignedValue = 0,
80 IgnorableUnsignedValue = 0
83 template<TypeOfDerivedInteger DerivedType> class DerivedInteger;
85 template<TypeOfDerivedInteger DerivedType> class DerivedIntegerDetails;
88 class DerivedIntegerDetails<TypeByte>
91 friend class DerivedInteger<TypeByte>;
92 typedef qint8 StorageType;
93 typedef xsInteger TemporaryStorageType;
94 static const StorageType maxInclusive = 127;
95 static const StorageType minInclusive = -128;
96 static const DerivedIntegerLimitsUsage limitsUsage = LimitBoth;
99 * Disable the default constructor.
101 DerivedIntegerDetails() {}
103 Q_DISABLE_COPY(DerivedIntegerDetails)
107 class DerivedIntegerDetails<TypeInt>
110 friend class DerivedInteger<TypeInt>;
111 typedef qint32 StorageType;
112 typedef xsInteger TemporaryStorageType;
113 static const StorageType maxInclusive = Q_INT64_C(2147483647);
114 static const StorageType minInclusive = Q_INT64_C(-2147483648);
115 static const DerivedIntegerLimitsUsage limitsUsage = LimitBoth;
118 * Disable the default constructor.
120 DerivedIntegerDetails() {}
122 Q_DISABLE_COPY(DerivedIntegerDetails)
126 class DerivedIntegerDetails<TypeLong>
129 friend class DerivedInteger<TypeLong>;
130 typedef qint64 StorageType;
131 typedef StorageType TemporaryStorageType;
132 static const StorageType maxInclusive = Q_INT64_C(9223372036854775807);
135 * This messy arithmetic expression ensures that we don't get a warning
136 * on neither GCC nor MSVC.
138 static const StorageType minInclusive = -(Q_INT64_C(9223372036854775807)) - 1;
140 static const DerivedIntegerLimitsUsage limitsUsage = LimitBoth;
143 * Disable the default constructor.
145 DerivedIntegerDetails() {}
147 Q_DISABLE_COPY(DerivedIntegerDetails)
151 class DerivedIntegerDetails<TypeNegativeInteger>
154 friend class DerivedInteger<TypeNegativeInteger>;
155 typedef xsInteger StorageType;
156 typedef StorageType TemporaryStorageType;
157 static const StorageType maxInclusive = -1;
158 static const StorageType minInclusive = IgnorableSignedValue;
159 static const DerivedIntegerLimitsUsage limitsUsage = LimitUpwards;
162 * Disable the default constructor.
164 DerivedIntegerDetails() {}
166 Q_DISABLE_COPY(DerivedIntegerDetails)
170 class DerivedIntegerDetails<TypeNonNegativeInteger>
173 friend class DerivedInteger<TypeNonNegativeInteger>;
174 typedef xsInteger StorageType;
175 typedef StorageType TemporaryStorageType;
176 static const StorageType maxInclusive = IgnorableSignedValue;
177 static const StorageType minInclusive = 0;
178 static const DerivedIntegerLimitsUsage limitsUsage = LimitDownwards;
181 * Disable the default constructor.
183 DerivedIntegerDetails() {}
185 Q_DISABLE_COPY(DerivedIntegerDetails)
189 class DerivedIntegerDetails<TypeNonPositiveInteger>
192 friend class DerivedInteger<TypeNonPositiveInteger>;
193 typedef xsInteger StorageType;
194 typedef StorageType TemporaryStorageType;
195 static const StorageType maxInclusive = 0;
196 static const StorageType minInclusive = IgnorableSignedValue;
197 static const DerivedIntegerLimitsUsage limitsUsage = LimitUpwards;
200 * Disable the default constructor.
202 DerivedIntegerDetails() {}
204 Q_DISABLE_COPY(DerivedIntegerDetails)
208 class DerivedIntegerDetails<TypePositiveInteger>
211 friend class DerivedInteger<TypePositiveInteger>;
212 typedef xsInteger StorageType;
213 typedef StorageType TemporaryStorageType;
214 static const StorageType maxInclusive = IgnorableSignedValue;
215 static const StorageType minInclusive = 1;
216 static const DerivedIntegerLimitsUsage limitsUsage = LimitDownwards;
219 * Disable the default constructor.
221 DerivedIntegerDetails() {}
223 Q_DISABLE_COPY(DerivedIntegerDetails)
227 class DerivedIntegerDetails<TypeShort>
230 friend class DerivedInteger<TypeShort>;
231 typedef qint16 StorageType;
232 typedef xsInteger TemporaryStorageType;
233 static const StorageType maxInclusive = 32767;
234 static const StorageType minInclusive = -32768;
235 static const DerivedIntegerLimitsUsage limitsUsage = LimitBoth;
238 * Disable the default constructor.
240 DerivedIntegerDetails() {}
242 Q_DISABLE_COPY(DerivedIntegerDetails)
246 class DerivedIntegerDetails<TypeUnsignedByte>
249 friend class DerivedInteger<TypeUnsignedByte>;
250 typedef quint8 StorageType;
251 typedef qint64 TemporaryStorageType;
252 static const StorageType maxInclusive = 255;
253 static const StorageType minInclusive = 0;
254 static const DerivedIntegerLimitsUsage limitsUsage = LimitBoth;
257 * Disable the default constructor.
259 DerivedIntegerDetails() {}
261 Q_DISABLE_COPY(DerivedIntegerDetails)
265 class DerivedIntegerDetails<TypeUnsignedInt>
268 friend class DerivedInteger<TypeUnsignedInt>;
269 typedef quint32 StorageType;
270 typedef qint64 TemporaryStorageType;
271 static const StorageType maxInclusive = Q_UINT64_C(4294967295);
272 static const StorageType minInclusive = 0;
273 static const DerivedIntegerLimitsUsage limitsUsage = LimitBoth;
276 * Disable the default constructor.
278 DerivedIntegerDetails() {}
280 Q_DISABLE_COPY(DerivedIntegerDetails)
284 class DerivedIntegerDetails<TypeUnsignedLong>
287 friend class DerivedInteger<TypeUnsignedLong>;
288 typedef quint64 StorageType;
289 typedef StorageType TemporaryStorageType;
290 static const StorageType maxInclusive = Q_UINT64_C(18446744073709551615);
291 static const StorageType minInclusive = 0;
292 static const DerivedIntegerLimitsUsage limitsUsage = LimitBoth;
295 * Disable the default constructor.
297 DerivedIntegerDetails() {}
299 Q_DISABLE_COPY(DerivedIntegerDetails)
303 class DerivedIntegerDetails<TypeUnsignedShort>
306 friend class DerivedInteger<TypeUnsignedShort>;
307 typedef quint16 StorageType;
308 typedef qint64 TemporaryStorageType;
309 static const StorageType maxInclusive = 65535;
310 static const StorageType minInclusive = 0;
311 static const DerivedIntegerLimitsUsage limitsUsage = LimitBoth;
314 * Disable the default constructor.
316 DerivedIntegerDetails() {}
318 Q_DISABLE_COPY(DerivedIntegerDetails)
322 * @short Represents instances of derived @c xs:integer types, such as @c
325 * @author Frans Englich <frans.englich@nokia.com>
326 * @ingroup Patternist_xdm
328 template<TypeOfDerivedInteger DerivedType>
329 class DerivedInteger : public Numeric
332 typedef typename DerivedIntegerDetails<DerivedType>::StorageType StorageType;
333 typedef typename DerivedIntegerDetails<DerivedType>::TemporaryStorageType TemporaryStorageType;
335 static const StorageType maxInclusive = DerivedIntegerDetails<DerivedType>::maxInclusive;
336 static const StorageType minInclusive = DerivedIntegerDetails<DerivedType>::minInclusive;
337 static const DerivedIntegerLimitsUsage limitsUsage = DerivedIntegerDetails<DerivedType>::limitsUsage;
339 const StorageType m_value;
341 inline DerivedInteger(const StorageType num) : m_value(num)
346 * By refactoring out the simple comparison below into a template
347 * function, we avoid the warning "warning: comparison of unsigned expression < 0 is always false" with gcc
348 * when the class is instantiated with TypeUnsignedLong. The warning is
349 * a false positive since we check wehther LimitUpwards is set before
352 * This template function exists for no other reason. */
353 template<typename A, typename B>
354 static bool lessThan(const A &a, const B &b)
360 * This function exists for the same reason that lessThan() do.
362 template<typename A, typename B>
363 static bool largerOrEqual(const A &a, const B &b)
365 return qint64(a) >= b;
370 static ItemType::Ptr itemType()
374 case TypeByte: return BuiltinTypes::xsByte;
375 case TypeInt: return BuiltinTypes::xsInt;
376 case TypeLong: return BuiltinTypes::xsLong;
377 case TypeNegativeInteger: return BuiltinTypes::xsNegativeInteger;
378 case TypeNonNegativeInteger: return BuiltinTypes::xsNonNegativeInteger;
379 case TypeNonPositiveInteger: return BuiltinTypes::xsNonPositiveInteger;
380 case TypePositiveInteger: return BuiltinTypes::xsPositiveInteger;
381 case TypeShort: return BuiltinTypes::xsShort;
382 case TypeUnsignedByte: return BuiltinTypes::xsUnsignedByte;
383 case TypeUnsignedInt: return BuiltinTypes::xsUnsignedInt;
384 case TypeUnsignedLong: return BuiltinTypes::xsUnsignedLong;
385 case TypeUnsignedShort: return BuiltinTypes::xsUnsignedShort;
389 return ItemType::Ptr();
392 static AtomicValue::Ptr fromValue(const NamePool::Ptr &np, const TemporaryStorageType num)
394 /* If we use minInclusive when calling lessThan(), we for some
395 * reason get a linker error with GCC. Using this temporary
396 * variable solves it. */
397 const StorageType minimum = minInclusive;
399 if((limitsUsage & LimitUpwards) &&
402 return ValidationError::createError(QtXmlPatterns::tr(
403 "Value %1 of type %2 exceeds maximum (%3).")
404 .arg(QPatternist::formatData(static_cast<xsInteger>(num)))
405 .arg(formatType(np, itemType()))
406 .arg(QPatternist::formatData(static_cast<xsInteger>(maxInclusive))));
408 else if((limitsUsage & LimitDownwards) &&
409 lessThan(num, minimum))
411 return ValidationError::createError(QtXmlPatterns::tr(
412 "Value %1 of type %2 is below minimum (%3).")
413 .arg(QPatternist::formatData(static_cast<xsInteger>(num)))
414 .arg(formatType(np, itemType()))
415 .arg(QPatternist::formatData(static_cast<xsInteger>(minInclusive))));
418 return AtomicValue::Ptr(new DerivedInteger(num));
421 static AtomicValue::Ptr fromValueUnchecked(const TemporaryStorageType num)
423 return AtomicValue::Ptr(new DerivedInteger(num));
427 * Constructs an instance from the lexical
428 * representation @p strNumeric.
430 static AtomicValue::Ptr fromLexical(const NamePool::Ptr &np, const QString &strNumeric)
432 bool conversionOk = false;
433 TemporaryStorageType num;
435 /* Depending on the type, we need to call different conversion
436 * functions on QString. */
439 case TypeUnsignedLong:
441 /* Qt decides to flag '-' as invalid, so remove it before. */
442 if(strNumeric.contains(QLatin1Char('-')))
444 num = QString(strNumeric).remove(QLatin1Char('-')).toULongLong(&conversionOk);
447 conversionOk = false;
450 num = strNumeric.toULongLong(&conversionOk);
456 num = strNumeric.toLongLong(&conversionOk);
462 return fromValue(np, num);
464 return ValidationError::createError();
467 inline StorageType storedValue() const
473 * Determines the Effective %Boolean Value of this number.
475 * @returns @c false if the number is 0, otherwise @c true.
477 bool evaluateEBV(const QExplicitlySharedDataPointer<DynamicContext> &) const
482 virtual QString stringValue() const
484 return QString::number(m_value);
487 virtual ItemType::Ptr type() const
492 virtual xsDouble toDouble() const
494 return static_cast<xsDouble>(m_value);
497 virtual xsInteger toInteger() const
502 virtual xsFloat toFloat() const
504 return static_cast<xsFloat>(m_value);
507 virtual xsDecimal toDecimal() const
509 return static_cast<xsDecimal>(m_value);
512 virtual Numeric::Ptr round() const
514 /* xs:integerS never have a mantissa. */
515 return Numeric::Ptr(static_cast<Numeric *>(const_cast<AtomicValue *>(Integer::fromValue(m_value).asAtomicValue())));
518 virtual Numeric::Ptr roundHalfToEven(const xsInteger) const
520 return Numeric::Ptr(static_cast<Numeric *>(const_cast<AtomicValue *>(Integer::fromValue(m_value).asAtomicValue())));
523 virtual Numeric::Ptr floor() const
525 return Numeric::Ptr(static_cast<Numeric *>(const_cast<AtomicValue *>(Integer::fromValue(m_value).asAtomicValue())));
528 virtual Numeric::Ptr ceiling() const
530 return Numeric::Ptr(static_cast<Numeric *>(const_cast<AtomicValue *>(Integer::fromValue(m_value).asAtomicValue())));
533 virtual Numeric::Ptr abs() const
535 /* We unconditionally create an Integer even if we're a positive
536 * value, because one part of this is the type change to
539 * We've manually inlined qAbs() and invoke xsInteger's
540 * constructor. The reason being that we other gets truncation down
541 * to StorageType. See for instance XQTS test case absint1args-1. */
542 return Numeric::Ptr(static_cast<Numeric *>(const_cast<AtomicValue *>(Integer::fromValue(largerOrEqual(m_value, 0) ? xsInteger(m_value) : -xsInteger(m_value)).asAtomicValue())));
546 * @returns always @c false, @c xs:DerivedInteger doesn't have
547 * not-a-number in its value space.
549 virtual bool isNaN() const
555 * @returns always @c false, @c xs:DerivedInteger doesn't have
556 * infinity in its value space.
558 virtual bool isInf() const
563 virtual Item toNegated() const
565 return Integer::fromValue(-xsInteger(m_value));
568 virtual bool isSigned() const
572 /* Fallthrough all these. */
576 case TypeNegativeInteger:
577 case TypeNonNegativeInteger:
578 case TypeNonPositiveInteger:
579 case TypePositiveInteger:
582 /* Fallthrough all these. */
583 case TypeUnsignedByte:
584 case TypeUnsignedInt:
585 case TypeUnsignedLong:
586 case TypeUnsignedShort:
592 virtual qulonglong toUnsignedInteger() const
596 /* Fallthrough all these. */
600 case TypeNegativeInteger:
601 case TypeNonNegativeInteger:
602 case TypeNonPositiveInteger:
603 case TypePositiveInteger:
605 Q_ASSERT_X(false, Q_FUNC_INFO,
606 "It makes no sense to call this function, see Numeric::toUnsignedInteger().");
607 /* Fallthrough all these. */
608 case TypeUnsignedByte:
609 case TypeUnsignedInt:
610 case TypeUnsignedLong:
611 case TypeUnsignedShort: