source: trunk/src/xmlpatterns/data/qderivedinteger_p.h@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 21.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtXmlPatterns module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42//
43// W A R N I N G
44// -------------
45//
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.
49//
50// We mean it.
51
52#ifndef Patternist_DerivedInteger_H
53#define Patternist_DerivedInteger_H
54
55#include "qbuiltintypes_p.h"
56#include "qinteger_p.h"
57#include "qpatternistlocale_p.h"
58#include "qvalidationerror_p.h"
59
60QT_BEGIN_HEADER
61
62QT_BEGIN_NAMESPACE
63
64namespace QPatternist
65{
66 /**
67 * @relates DerivedInteger
68 */
69 enum DerivedIntegerLimitsUsage
70 {
71 None = 1,
72 LimitUpwards = 2,
73 LimitDownwards = 4,
74 LimitBoth = LimitUpwards | LimitDownwards
75 };
76
77 enum
78 {
79 IgnorableSignedValue = 0,
80 IgnorableUnsignedValue = 0
81 };
82
83 template<TypeOfDerivedInteger DerivedType> class DerivedInteger;
84
85 template<TypeOfDerivedInteger DerivedType> class DerivedIntegerDetails;
86
87 template<>
88 class DerivedIntegerDetails<TypeByte>
89 {
90 private:
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;
97
98 /**
99 * Disable the default constructor.
100 */
101 DerivedIntegerDetails() {}
102
103 Q_DISABLE_COPY(DerivedIntegerDetails)
104 };
105
106 template<>
107 class DerivedIntegerDetails<TypeInt>
108 {
109 private:
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;
116
117 /**
118 * Disable the default constructor.
119 */
120 DerivedIntegerDetails() {}
121
122 Q_DISABLE_COPY(DerivedIntegerDetails)
123 };
124
125 template<>
126 class DerivedIntegerDetails<TypeLong>
127 {
128 private:
129 friend class DerivedInteger<TypeLong>;
130 typedef qint64 StorageType;
131 typedef StorageType TemporaryStorageType;
132 static const StorageType maxInclusive = Q_INT64_C(9223372036854775807);
133
134 /**
135 * This messy arithmetic expression ensures that we don't get a warning
136 * on neither GCC nor MSVC.
137 */
138 static const StorageType minInclusive = -(Q_INT64_C(9223372036854775807)) - 1;
139
140 static const DerivedIntegerLimitsUsage limitsUsage = LimitBoth;
141
142 /**
143 * Disable the default constructor.
144 */
145 DerivedIntegerDetails() {}
146
147 Q_DISABLE_COPY(DerivedIntegerDetails)
148 };
149
150 template<>
151 class DerivedIntegerDetails<TypeNegativeInteger>
152 {
153 private:
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;
160
161 /**
162 * Disable the default constructor.
163 */
164 DerivedIntegerDetails() {}
165
166 Q_DISABLE_COPY(DerivedIntegerDetails)
167 };
168
169 template<>
170 class DerivedIntegerDetails<TypeNonNegativeInteger>
171 {
172 private:
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;
179
180 /**
181 * Disable the default constructor.
182 */
183 DerivedIntegerDetails() {}
184
185 Q_DISABLE_COPY(DerivedIntegerDetails)
186 };
187
188 template<>
189 class DerivedIntegerDetails<TypeNonPositiveInteger>
190 {
191 private:
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;
198
199 /**
200 * Disable the default constructor.
201 */
202 DerivedIntegerDetails() {}
203
204 Q_DISABLE_COPY(DerivedIntegerDetails)
205 };
206
207 template<>
208 class DerivedIntegerDetails<TypePositiveInteger>
209 {
210 private:
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;
217
218 /**
219 * Disable the default constructor.
220 */
221 DerivedIntegerDetails() {}
222
223 Q_DISABLE_COPY(DerivedIntegerDetails)
224 };
225
226 template<>
227 class DerivedIntegerDetails<TypeShort>
228 {
229 private:
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;
236
237 /**
238 * Disable the default constructor.
239 */
240 DerivedIntegerDetails() {}
241
242 Q_DISABLE_COPY(DerivedIntegerDetails)
243 };
244
245 template<>
246 class DerivedIntegerDetails<TypeUnsignedByte>
247 {
248 private:
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;
255
256 /**
257 * Disable the default constructor.
258 */
259 DerivedIntegerDetails() {}
260
261 Q_DISABLE_COPY(DerivedIntegerDetails)
262 };
263
264 template<>
265 class DerivedIntegerDetails<TypeUnsignedInt>
266 {
267 private:
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;
274
275 /**
276 * Disable the default constructor.
277 */
278 DerivedIntegerDetails() {}
279
280 Q_DISABLE_COPY(DerivedIntegerDetails)
281 };
282
283 template<>
284 class DerivedIntegerDetails<TypeUnsignedLong>
285 {
286 private:
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;
293
294 /**
295 * Disable the default constructor.
296 */
297 DerivedIntegerDetails() {}
298
299 Q_DISABLE_COPY(DerivedIntegerDetails)
300 };
301
302 template<>
303 class DerivedIntegerDetails<TypeUnsignedShort>
304 {
305 private:
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;
312
313 /**
314 * Disable the default constructor.
315 */
316 DerivedIntegerDetails() {}
317
318 Q_DISABLE_COPY(DerivedIntegerDetails)
319 };
320
321 /**
322 * @short Represents instances of derived @c xs:integer types, such as @c
323 * xs:byte.
324 *
325 * @author Frans Englich <[email protected]>
326 * @ingroup Patternist_xdm
327 */
328 template<TypeOfDerivedInteger DerivedType>
329 class DerivedInteger : public Numeric
330 {
331 private:
332 typedef typename DerivedIntegerDetails<DerivedType>::StorageType StorageType;
333 typedef typename DerivedIntegerDetails<DerivedType>::TemporaryStorageType TemporaryStorageType;
334
335 static const StorageType maxInclusive = DerivedIntegerDetails<DerivedType>::maxInclusive;
336 static const StorageType minInclusive = DerivedIntegerDetails<DerivedType>::minInclusive;
337 static const DerivedIntegerLimitsUsage limitsUsage = DerivedIntegerDetails<DerivedType>::limitsUsage;
338
339 const StorageType m_value;
340
341 inline DerivedInteger(const StorageType num) : m_value(num)
342 {
343 }
344
345 /**
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
350 * instantiating.
351 *
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)
355 {
356 return a < b;
357 }
358
359 /**
360 * This function exists for the same reason that lessThan() do.
361 */
362 template<typename A, typename B>
363 static bool largerOrEqual(const A &a, const B &b)
364 {
365 return qint64(a) >= b;
366 }
367
368 public:
369
370 static ItemType::Ptr itemType()
371 {
372 switch(DerivedType)
373 {
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;
386 }
387
388 Q_ASSERT(false);
389 return ItemType::Ptr();
390 }
391
392 static AtomicValue::Ptr fromValue(const NamePool::Ptr &np, const TemporaryStorageType num)
393 {
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;
398
399 if((limitsUsage & LimitUpwards) &&
400 num > maxInclusive)
401 {
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))));
407 }
408 else if((limitsUsage & LimitDownwards) &&
409 lessThan(num, minimum))
410 {
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))));
416 }
417 else
418 return AtomicValue::Ptr(new DerivedInteger(num));
419 }
420
421 static AtomicValue::Ptr fromValueUnchecked(const TemporaryStorageType num)
422 {
423 return AtomicValue::Ptr(new DerivedInteger(num));
424 }
425
426 /**
427 * Constructs an instance from the lexical
428 * representation @p strNumeric.
429 */
430 static AtomicValue::Ptr fromLexical(const NamePool::Ptr &np, const QString &strNumeric)
431 {
432 bool conversionOk = false;
433 TemporaryStorageType num;
434
435 /* Depending on the type, we need to call different conversion
436 * functions on QString. */
437 switch(DerivedType)
438 {
439 case TypeUnsignedLong:
440 {
441 /* Qt decides to flag '-' as invalid, so remove it before. */
442 if(strNumeric.contains(QLatin1Char('-')))
443 {
444 num = QString(strNumeric).remove(QLatin1Char('-')).toULongLong(&conversionOk);
445
446 if(num != 0)
447 conversionOk = false;
448 }
449 else
450 num = strNumeric.toULongLong(&conversionOk);
451
452 break;
453 }
454 default:
455 {
456 num = strNumeric.toLongLong(&conversionOk);
457 break;
458 }
459 }
460
461 if(conversionOk)
462 return fromValue(np, num);
463 else
464 return ValidationError::createError();
465 }
466
467 inline StorageType storedValue() const
468 {
469 return m_value;
470 }
471
472 /**
473 * Determines the Effective %Boolean Value of this number.
474 *
475 * @returns @c false if the number is 0, otherwise @c true.
476 */
477 bool evaluateEBV(const QExplicitlySharedDataPointer<DynamicContext> &) const
478 {
479 return m_value != 0;
480 }
481
482 virtual QString stringValue() const
483 {
484 return QString::number(m_value);
485 }
486
487 virtual ItemType::Ptr type() const
488 {
489 return itemType();
490 }
491
492 virtual xsDouble toDouble() const
493 {
494 return static_cast<xsDouble>(m_value);
495 }
496
497 virtual xsInteger toInteger() const
498 {
499 return m_value;
500 }
501
502 virtual xsFloat toFloat() const
503 {
504 return static_cast<xsFloat>(m_value);
505 }
506
507 virtual xsDecimal toDecimal() const
508 {
509 return static_cast<xsDecimal>(m_value);
510 }
511
512 virtual Numeric::Ptr round() const
513 {
514 /* xs:integerS never have a mantissa. */
515 return Numeric::Ptr(static_cast<Numeric *>(const_cast<AtomicValue *>(Integer::fromValue(m_value).asAtomicValue())));
516 }
517
518 virtual Numeric::Ptr roundHalfToEven(const xsInteger) const
519 {
520 return Numeric::Ptr(static_cast<Numeric *>(const_cast<AtomicValue *>(Integer::fromValue(m_value).asAtomicValue())));
521 }
522
523 virtual Numeric::Ptr floor() const
524 {
525 return Numeric::Ptr(static_cast<Numeric *>(const_cast<AtomicValue *>(Integer::fromValue(m_value).asAtomicValue())));
526 }
527
528 virtual Numeric::Ptr ceiling() const
529 {
530 return Numeric::Ptr(static_cast<Numeric *>(const_cast<AtomicValue *>(Integer::fromValue(m_value).asAtomicValue())));
531 }
532
533 virtual Numeric::Ptr abs() const
534 {
535 /* We unconditionally create an Integer even if we're a positive
536 * value, because one part of this is the type change to
537 * xs:integer.
538 *
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())));
543 }
544
545 /**
546 * @returns always @c false, @c xs:DerivedInteger doesn't have
547 * not-a-number in its value space.
548 */
549 virtual bool isNaN() const
550 {
551 return false;
552 }
553
554 /**
555 * @returns always @c false, @c xs:DerivedInteger doesn't have
556 * infinity in its value space.
557 */
558 virtual bool isInf() const
559 {
560 return false;
561 }
562
563 virtual Item toNegated() const
564 {
565 return Integer::fromValue(-xsInteger(m_value));
566 }
567
568 virtual bool isSigned() const
569 {
570 switch(DerivedType)
571 {
572 /* Fallthrough all these. */
573 case TypeByte:
574 case TypeInt:
575 case TypeLong:
576 case TypeNegativeInteger:
577 case TypeNonNegativeInteger:
578 case TypeNonPositiveInteger:
579 case TypePositiveInteger:
580 case TypeShort:
581 return true;
582 /* Fallthrough all these. */
583 case TypeUnsignedByte:
584 case TypeUnsignedInt:
585 case TypeUnsignedLong:
586 case TypeUnsignedShort:
587 return false;
588 }
589 return false;
590 }
591
592 virtual qulonglong toUnsignedInteger() const
593 {
594 switch(DerivedType)
595 {
596 /* Fallthrough all these. */
597 case TypeByte:
598 case TypeInt:
599 case TypeLong:
600 case TypeNegativeInteger:
601 case TypeNonNegativeInteger:
602 case TypeNonPositiveInteger:
603 case TypePositiveInteger:
604 case TypeShort:
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:
612 return m_value;
613 }
614 return 0;
615 }
616
617 };
618}
619
620QT_END_NAMESPACE
621
622QT_END_HEADER
623
624#endif
Note: See TracBrowser for help on using the repository browser.