1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
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 The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40//
41// W A R N I N G
42// -------------
43//
44// This file is not part of the Qt API. It exists purely as an
45// implementation detail. This header file may change from version to
46// version without notice, or even be removed.
47//
48// We mean it.
49
50#ifndef Patternist_AtomicCasters_H
51#define Patternist_AtomicCasters_H
52
53#include <private/qatomiccaster_p.h>
54#include <private/qdecimal_p.h>
55#include <private/qderivedinteger_p.h>
56#include <private/qderivedstring_p.h>
57#include <private/qinteger_p.h>
58#include <private/qvalidationerror_p.h>
59
60/**
61 * @file
62 * @short Contains classes sub-classing AtomicCaster and which
63 * are responsible of casting an atomic value to another type.
64 */
65
66QT_BEGIN_NAMESPACE
67
68namespace QPatternist
69{
70
71 /**
72 * @short Casts any atomic value to @c xs:string.
73 *
74 * This class uses Item::stringValue() for retrieving a string
75 * representation, and thus supports casting from atomic values
76 * of any type.
77 *
78 * @ingroup Patternist_xdm
79 * @author Frans Englich <frans.englich@nokia.com>
80 */
81 template<TypeOfDerivedString DerivedType>
82 class ToStringCaster : public AtomicCaster
83 {
84 public:
85 virtual Item castFrom(const Item &from,
86 const QExplicitlySharedDataPointer<DynamicContext> &context) const
87 {
88 Q_ASSERT(from);
89 return DerivedString<DerivedType>::fromLexical(context->namePool(), from.stringValue());
90 }
91 };
92
93 /**
94 * @short Casts any atomic value to @c xs:untypedAtomic.
95 *
96 * This class uses Item::stringValue() for retrieving a string
97 * representation, and thus supports casting from atomic values
98 * of any type. The implementation is similar to ToStringCaster.
99 *
100 * @ingroup Patternist_xdm
101 * @author Frans Englich <frans.englich@nokia.com>
102 */
103 class ToUntypedAtomicCaster : public AtomicCaster
104 {
105 public:
106 virtual Item castFrom(const Item &from,
107 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
108 };
109
110 /**
111 * @short Casts a string value to @c xs:anyURI.
112 *
113 * @ingroup Patternist_xdm
114 * @author Frans Englich <frans.englich@nokia.com>
115 */
116 class ToAnyURICaster : public AtomicCaster
117 {
118 public:
119 virtual Item castFrom(const Item &from,
120 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
121 };
122
123 /**
124 * @short Casts a @c xs:hexBinary atomic value to @c xs:base64Binary.
125 *
126 * @ingroup Patternist_xdm
127 * @author Frans Englich <frans.englich@nokia.com>
128 */
129 class HexBinaryToBase64BinaryCaster : public AtomicCaster
130 {
131 public:
132 virtual Item castFrom(const Item &from,
133 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
134 };
135
136 /**
137 * @short Casts a @c xs:base64Binary atomic value to @c xs:hexBinary.
138 *
139 * @ingroup Patternist_xdm
140 * @author Frans Englich <frans.englich@nokia.com>
141 */
142 class Base64BinaryToHexBinaryCaster : public AtomicCaster
143 {
144 public:
145 virtual Item castFrom(const Item &from,
146 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
147 };
148
149 /**
150 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:base64Binary.
151 *
152 * @ingroup Patternist_xdm
153 * @author Frans Englich <frans.englich@nokia.com>
154 */
155 class StringToBase64BinaryCaster : public AtomicCaster
156 {
157 public:
158 virtual Item castFrom(const Item &from,
159 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
160 };
161
162 /**
163 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:hexBinary.
164 *
165 * @ingroup Patternist_xdm
166 * @author Frans Englich <frans.englich@nokia.com>
167 */
168 class StringToHexBinaryCaster : public AtomicCaster
169 {
170 public:
171 virtual Item castFrom(const Item &from,
172 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
173 };
174
175 /**
176 * @short Casts any @c numeric value to @c xs:boolean.
177 *
178 * @ingroup Patternist_xdm
179 * @author Frans Englich <frans.englich@nokia.com>
180 */
181 class NumericToBooleanCaster : public AtomicCaster
182 {
183 public:
184 virtual Item castFrom(const Item &from,
185 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
186 };
187
188 /**
189 * @short Casts any string value, @c xs:string or @c xs:untypedAtomic, to @c xs:boolean.
190 *
191 * @ingroup Patternist_xdm
192 * @author Frans Englich <frans.englich@nokia.com>
193 */
194 class StringToBooleanCaster : public AtomicCaster
195 {
196 public:
197 virtual Item castFrom(const Item &from,
198 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
199 };
200
201 /**
202 * @short Casts a @c numeric value, such as @c xs:double or @c xs:decimal, to @c xs:integer or
203 * @c xs:decimal, depending on IsInteger.
204 *
205 * castFrom() uses Numeric::toInteger() for doing the actual casting.
206 *
207 * @ingroup Patternist_xdm
208 * @author Frans Englich <frans.englich@nokia.com>
209 */
210 template <const bool IsInteger>
211 class NumericToDecimalCaster : public AtomicCaster
212 {
213 public:
214 /**
215 * Used by NumericToDerivedIntegerCaster in addition to this class.
216 */
217 static inline QString errorMessage()
218 {
219 return QtXmlPatterns::tr(sourceText: "When casting to %1 from %2, the source value cannot be %3.");
220 }
221
222 virtual Item castFrom(const Item &from,
223 const QExplicitlySharedDataPointer<DynamicContext> &context) const
224 {
225 const ItemType::Ptr t(from.type());
226 const Numeric *const num = from.template as<Numeric>();
227
228 if(BuiltinTypes::xsDouble->xdtTypeMatches(other: t) || BuiltinTypes::xsFloat->xdtTypeMatches(other: t))
229 {
230 if(num->isInf() || num->isNaN())
231 {
232 return ValidationError::createError(description: errorMessage()
233 .arg(a: formatType(np: context->namePool(), type: IsInteger ? BuiltinTypes::xsInteger : BuiltinTypes::xsDecimal))
234 .arg(a: formatType(np: context->namePool(), type: t))
235 .arg(a: formatData(data: num->stringValue())),
236 ReportContext::FOCA0002);
237 }
238 }
239
240 if(IsInteger)
241 return Integer::fromValue(num: num->toInteger());
242 else
243 return toItem(atomicValue: Decimal::fromValue(num: num->toDecimal()));
244 }
245 };
246
247 /**
248 * @short Casts a string value, @c xs:string or @c xs:untypedAtomic, to @c xs:decimal.
249 *
250 * @ingroup Patternist_xdm
251 * @author Frans Englich <frans.englich@nokia.com>
252 */
253 class StringToDecimalCaster : public AtomicCaster
254 {
255 public:
256 virtual Item castFrom(const Item &from,
257 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
258 };
259
260 /**
261 * @short Casts a string value, @c xs:string or @c xs:untypedAtomic, to @c xs:integer.
262 *
263 * @ingroup Patternist_xdm
264 * @author Frans Englich <frans.englich@nokia.com>
265 */
266 class StringToIntegerCaster : public AtomicCaster
267 {
268 public:
269 virtual Item castFrom(const Item &from,
270 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
271 };
272
273 /**
274 * @short Casts a value of type @c xs:boolean to @c xs:decimal.
275 *
276 * @ingroup Patternist_xdm
277 * @author Frans Englich <frans.englich@nokia.com>
278 */
279 class BooleanToDecimalCaster : public AtomicCaster
280 {
281 public:
282 virtual Item castFrom(const Item &from,
283 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
284 };
285
286 /**
287 * @short Casts a value of type @c xs:boolean to @c xs:integer.
288 *
289 * @ingroup Patternist_xdm
290 * @author Frans Englich <frans.englich@nokia.com>
291 */
292 class BooleanToIntegerCaster : public AtomicCaster
293 {
294 public:
295 virtual Item castFrom(const Item &from,
296 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
297 };
298
299 /**
300 * @short Casts a value to itself. Essentially, this AtomicCaster does nothing.
301 *
302 * Casting a value to the type of itself is defined to be a noop,
303 * no operation. When it can be statically detected that will be done,
304 * CastAs rewrites itself appropriately during compilation, but
305 * in some cases insufficent data is available at compile time and then
306 * is this class need on a case-per-case base at evaluation time.
307 *
308 * @ingroup Patternist_xdm
309 * @author Frans Englich <frans.englich@nokia.com>
310 */
311 class SelfToSelfCaster : public AtomicCaster
312 {
313 public:
314
315 /**
316 * This function simply returns @p from.
317 */
318 virtual Item castFrom(const Item &from,
319 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
320 };
321
322 /**
323 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:gYear.
324 *
325 * @ingroup Patternist_xdm
326 * @author Frans Englich <frans.englich@nokia.com>
327 */
328 class StringToGYearCaster : public AtomicCaster
329 {
330 public:
331 virtual Item castFrom(const Item &from,
332 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
333 };
334
335 /**
336 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:gDay.
337 *
338 * @ingroup Patternist_xdm
339 * @author Frans Englich <frans.englich@nokia.com>
340 */
341 class StringToGDayCaster : public AtomicCaster
342 {
343 public:
344 virtual Item castFrom(const Item &from,
345 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
346 };
347
348 /**
349 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:gMonth.
350 *
351 * @ingroup Patternist_xdm
352 * @author Frans Englich <frans.englich@nokia.com>
353 */
354 class StringToGMonthCaster : public AtomicCaster
355 {
356 public:
357 virtual Item castFrom(const Item &from,
358 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
359 };
360
361 /**
362 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:gYearMonth.
363 *
364 * @ingroup Patternist_xdm
365 * @author Frans Englich <frans.englich@nokia.com>
366 */
367 class StringToGYearMonthCaster : public AtomicCaster
368 {
369 public:
370 virtual Item castFrom(const Item &from,
371 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
372 };
373
374 /**
375 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:gYearMonth.
376 *
377 * @ingroup Patternist_xdm
378 * @author Frans Englich <frans.englich@nokia.com>
379 */
380 class StringToGMonthDayCaster : public AtomicCaster
381 {
382 public:
383 virtual Item castFrom(const Item &from,
384 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
385 };
386
387 /**
388 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:dateTime.
389 *
390 * @ingroup Patternist_xdm
391 * @author Frans Englich <frans.englich@nokia.com>
392 */
393 class StringToDateTimeCaster : public AtomicCaster
394 {
395 public:
396 virtual Item castFrom(const Item &from,
397 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
398 };
399
400 /**
401 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:time.
402 *
403 * @ingroup Patternist_xdm
404 * @author Frans Englich <frans.englich@nokia.com>
405 */
406 class StringToTimeCaster : public AtomicCaster
407 {
408 public:
409 virtual Item castFrom(const Item &from,
410 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
411 };
412
413 /**
414 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:date.
415 *
416 * @ingroup Patternist_xdm
417 * @author Frans Englich <frans.englich@nokia.com>
418 */
419 class StringToDateCaster : public AtomicCaster
420 {
421 public:
422 virtual Item castFrom(const Item &from,
423 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
424 };
425
426 /**
427 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:duration.
428 *
429 * @ingroup Patternist_xdm
430 * @author Frans Englich <frans.englich@nokia.com>
431 */
432 class StringToDurationCaster : public AtomicCaster
433 {
434 public:
435 virtual Item castFrom(const Item &from,
436 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
437 };
438
439 /**
440 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:dayTimeDuration.
441 *
442 * @ingroup Patternist_xdm
443 * @author Frans Englich <frans.englich@nokia.com>
444 */
445 class StringToDayTimeDurationCaster : public AtomicCaster
446 {
447 public:
448 virtual Item castFrom(const Item &from,
449 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
450 };
451
452 /**
453 * @short Casts a @c xs:string or @c xs:untypedAtomic atomic value to @c xs:yearMonthDuration.
454 *
455 * @ingroup Patternist_xdm
456 * @author Frans Englich <frans.englich@nokia.com>
457 */
458 class StringToYearMonthDurationCaster : public AtomicCaster
459 {
460 public:
461 virtual Item castFrom(const Item &from,
462 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
463 };
464
465
466 /**
467 * @short Casts a @c xs:date or @c xs:dateTime atomic value to @c xs:gYear.
468 *
469 * @ingroup Patternist_xdm
470 * @author Frans Englich <frans.englich@nokia.com>
471 */
472 class AbstractDateTimeToGYearCaster : public AtomicCaster
473 {
474 public:
475 virtual Item castFrom(const Item &from,
476 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
477 };
478
479 /**
480 * @short Casts a @c xs:date or @c xs:dateTime atomic value to @c xs:gYearMonth.
481 *
482 * @ingroup Patternist_xdm
483 * @author Frans Englich <frans.englich@nokia.com>
484 */
485 class AbstractDateTimeToGYearMonthCaster : public AtomicCaster
486 {
487 public:
488 virtual Item castFrom(const Item &from,
489 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
490 };
491
492 /**
493 * @short Casts a @c xs:date or @c xs:dateTime atomic value to @c xs:gMonth.
494 *
495 * @ingroup Patternist_xdm
496 * @author Frans Englich <frans.englich@nokia.com>
497 */
498 class AbstractDateTimeToGMonthCaster : public AtomicCaster
499 {
500 public:
501 virtual Item castFrom(const Item &from,
502 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
503 };
504
505 /**
506 * @short Casts a @c xs:date or @c xs:dateTime atomic value to @c xs:gMonthDay.
507 *
508 * @ingroup Patternist_xdm
509 * @author Frans Englich <frans.englich@nokia.com>
510 */
511 class AbstractDateTimeToGMonthDayCaster : public AtomicCaster
512 {
513 public:
514 virtual Item castFrom(const Item &from,
515 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
516 };
517
518 /**
519 * @short Casts a @c xs:date or @c xs:dateTime atomic value to @c xs:gDay.
520 *
521 * @ingroup Patternist_xdm
522 * @author Frans Englich <frans.englich@nokia.com>
523 */
524 class AbstractDateTimeToGDayCaster : public AtomicCaster
525 {
526 public:
527 virtual Item castFrom(const Item &from,
528 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
529 };
530
531 /**
532 * @short Casts an AbstractDateTime instance to DateTime.
533 *
534 * @ingroup Patternist_xdm
535 * @author Frans Englich <frans.englich@nokia.com>
536 */
537 class AbstractDateTimeToDateTimeCaster : public AtomicCaster
538 {
539 public:
540 virtual Item castFrom(const Item &from,
541 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
542 };
543
544 /**
545 * @short Casts an AbstractDateTime instance to SchemaTime.
546 *
547 * @ingroup Patternist_xdm
548 * @author Frans Englich <frans.englich@nokia.com>
549 */
550 class AbstractDateTimeToDateCaster : public AtomicCaster
551 {
552 public:
553 virtual Item castFrom(const Item &from,
554 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
555 };
556
557 /**
558 * @short Casts an AbstractDateTime instance to SchemaTime.
559 *
560 * @ingroup Patternist_xdm
561 * @author Frans Englich <frans.englich@nokia.com>
562 */
563 class AbstractDateTimeToTimeCaster : public AtomicCaster
564 {
565 public:
566 virtual Item castFrom(const Item &from,
567 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
568 };
569
570 /**
571 * @short Casts an AbstractDuration instance to Duration.
572 *
573 * @ingroup Patternist_xdm
574 * @author Frans Englich <frans.englich@nokia.com>
575 */
576 class AbstractDurationToDurationCaster : public AtomicCaster
577 {
578 public:
579 virtual Item castFrom(const Item &from,
580 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
581 };
582
583 /**
584 * @short Casts an AbstractDuration instance to DayTimeDuration.
585 *
586 * @ingroup Patternist_xdm
587 * @author Frans Englich <frans.englich@nokia.com>
588 */
589 class AbstractDurationToDayTimeDurationCaster : public AtomicCaster
590 {
591 public:
592 virtual Item castFrom(const Item &from,
593 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
594 };
595
596 /**
597 * @short Casts an AbstractDuration instance to YearMonthDuration.
598 *
599 * @ingroup Patternist_xdm
600 * @author Frans Englich <frans.englich@nokia.com>
601 */
602 class AbstractDurationToYearMonthDurationCaster : public AtomicCaster
603 {
604 public:
605 virtual Item castFrom(const Item &from,
606 const QExplicitlySharedDataPointer<DynamicContext> &context) const;
607 };
608
609 /**
610 * @short Casts an @c xs:string instance to a derived type of @c xs:integer.
611 *
612 * @ingroup Patternist_xdm
613 * @author Frans Englich <frans.englich@nokia.com>
614 */
615 template<TypeOfDerivedInteger type>
616 class StringToDerivedIntegerCaster : public AtomicCaster
617 {
618 public:
619 virtual Item
620 castFrom(const Item &from,
621 const QExplicitlySharedDataPointer<DynamicContext> &context) const
622 {
623 return DerivedInteger<type>::fromLexical(context->namePool(), from.stringValue());
624 }
625 };
626
627 /**
628 * @short Casts an @c xs:boolean instance to a derived type of @c xs:integer.
629 *
630 * @ingroup Patternist_xdm
631 * @author Frans Englich <frans.englich@nokia.com>
632 */
633 template<TypeOfDerivedInteger type>
634 class BooleanToDerivedIntegerCaster : public AtomicCaster
635 {
636 public:
637 virtual Item
638 castFrom(const Item &from,
639 const QExplicitlySharedDataPointer<DynamicContext> &context) const
640 {
641 return DerivedInteger<type>::fromValue(context->namePool(), from.template as<AtomicValue>()->evaluateEBV(context) ? 1 : 0);
642 }
643 };
644
645 /**
646 * @short Casts an @c xs:boolean instance to a derived type of @c xs:integer.
647 *
648 * @ingroup Patternist_xdm
649 * @author Frans Englich <frans.englich@nokia.com>
650 */
651 template<TypeOfDerivedString type>
652 class AnyToDerivedStringCaster : public AtomicCaster
653 {
654 public:
655 virtual Item
656 castFrom(const Item &from,
657 const QExplicitlySharedDataPointer<DynamicContext> &context) const
658 {
659 return DerivedString<type>::fromLexical(context->namePool(), from.stringValue());
660 }
661 };
662
663 /**
664 * @short Casts any @c numeric instance to a derived type of @c xs:integer.
665 *
666 * @ingroup Patternist_xdm
667 * @author Frans Englich <frans.englich@nokia.com>
668 */
669 template<TypeOfDerivedInteger type>
670 class NumericToDerivedIntegerCaster : public AtomicCaster
671 {
672 public:
673 virtual Item
674 castFrom(const Item &from,
675 const QExplicitlySharedDataPointer<DynamicContext> &context) const
676 {
677 const ItemType::Ptr t(from.type());
678 const Numeric *const num = from.template as<Numeric>();
679
680 if(BuiltinTypes::xsDouble->xdtTypeMatches(other: t) || BuiltinTypes::xsFloat->xdtTypeMatches(other: t))
681 {
682 if(num->isInf() || num->isNaN())
683 {
684 return ValidationError::createError(description: NumericToDecimalCaster<false>::errorMessage()
685 .arg(formatType(context->namePool(), DerivedInteger<type>::itemType()))
686 .arg(formatType(np: context->namePool(), type: t))
687 .arg(formatData(data: num->stringValue())),
688 ReportContext::FOCA0002);
689 }
690 }
691
692 return toItem(DerivedInteger<type>::fromValue(context->namePool(), from.template as<Numeric>()->toInteger()));
693 }
694 };
695}
696
697QT_END_NAMESPACE
698
699#endif
700

source code of qtxmlpatterns/src/xmlpatterns/data/qatomiccasters_p.h