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
51/**
52 * @file
53 * @short This file is included by qcomparisonplatform_p.h.
54 * If you need includes in this file, put them in qcomparisonplatform_p.h, outside of the namespace.
55 */
56
57template <typename TSubClass, bool issueError,
58 AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode>
59bool ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>::
60flexibleCompare(const Item &it1,
61 const Item &it2,
62 const DynamicContext::Ptr &context) const
63{
64 if(m_comparator)
65 /* The comparator was located at compile time. */
66 return compare(i1: it1, i2: it2, comp: m_comparator, op: operatorID());
67 else
68 {
69 const AtomicComparator::Ptr cp(fetchComparator(type1: it1.type(),
70 type2: it2.type(),
71 context));
72
73 return cp ? compare(i1: it1, i2: it2, comp: cp, op: operatorID()) : false;
74 }
75}
76
77template <typename TSubClass, bool issueError,
78 AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode>
79AtomicComparator::ComparisonResult
80ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>::
81detailedFlexibleCompare(const Item &it1,
82 const Item &it2,
83 const DynamicContext::Ptr &context) const
84{
85 AtomicComparator::Ptr comp;
86
87 if(m_comparator)
88 comp = m_comparator;
89 else
90 {
91 comp = fetchComparator(type1: it1.type(),
92 type2: it2.type(),
93 context);
94 }
95
96 Q_ASSERT_X(operatorID() == AtomicComparator::OperatorLessThanNaNLeast || operatorID() == AtomicComparator::OperatorLessThanNaNGreatest,
97 Q_FUNC_INFO, "Only OperatorLessThan is currently supported for this function.");
98 return comp->compare(op1: it1, op: operatorID(), op2: it2);
99}
100
101template <typename TSubClass, bool issueError,
102 AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode>
103bool ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>::
104compare(const Item &oand1,
105 const Item &oand2,
106 const AtomicComparator::Ptr &comp,
107 const AtomicComparator::Operator op) const
108{
109 Q_ASSERT(oand1);
110 Q_ASSERT(oand2);
111 Q_ASSERT(comp);
112
113 switch(op)
114 {
115 case AtomicComparator::OperatorEqual:
116 return comp->equals(op1: oand1, op2: oand2);
117 case AtomicComparator::OperatorNotEqual:
118 return !comp->equals(op1: oand1, op2: oand2);
119 case AtomicComparator::OperatorLessThanNaNLeast:
120 case AtomicComparator::OperatorLessThanNaNGreatest:
121 case AtomicComparator::OperatorLessThan:
122 return comp->compare(op1: oand1, op, op2: oand2) == AtomicComparator::LessThan;
123 case AtomicComparator::OperatorGreaterThan:
124 return comp->compare(op1: oand1, op, op2: oand2) == AtomicComparator::GreaterThan;
125 case AtomicComparator::OperatorLessOrEqual:
126 {
127 const AtomicComparator::ComparisonResult ret = comp->compare(op1: oand1, op, op2: oand2);
128 return ret == AtomicComparator::LessThan || ret == AtomicComparator::Equal;
129 }
130 case(AtomicComparator::OperatorGreaterOrEqual):
131 {
132 const AtomicComparator::ComparisonResult ret = comp->compare(op1: oand1, op, op2: oand2);
133 return ret == AtomicComparator::GreaterThan || ret == AtomicComparator::Equal;
134 }
135 }
136
137 /* GCC unbarfer, this line should never be reached. */
138 Q_ASSERT(false);
139 return false;
140}
141
142template <typename TSubClass, bool issueError,
143 AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode>
144AtomicComparator::Ptr ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>::
145fetchComparator(const ItemType::Ptr &t1,
146 const ItemType::Ptr &t2,
147 const ReportContext::Ptr &context) const
148{
149 Q_ASSERT(t1);
150 Q_ASSERT(t2);
151
152 if(*BuiltinTypes::xsAnyAtomicType == *t1 ||
153 *BuiltinTypes::xsAnyAtomicType == *t2 ||
154 *BuiltinTypes::item == *t1 ||
155 *BuiltinTypes::item == *t2 ||
156 *BuiltinTypes::numeric == *t1 ||
157 *BuiltinTypes::numeric == *t2 ||
158 *CommonSequenceTypes::Empty == *t1 ||
159 *CommonSequenceTypes::Empty == *t2)
160 {
161 /* The static type of(at least) one of the operands could not
162 * be narrowed further, so we do the operator
163 * lookup at runtime.
164 */
165 return AtomicComparator::Ptr();
166 }
167
168 const AtomicComparatorLocator::Ptr locator
169 (static_cast<const AtomicType *>(t1.data())->comparatorLocator());
170
171 if(!locator)
172 {
173 if(issueError)
174 {
175 context->error(QtXmlPatterns::tr(sourceText: "No comparisons can be done involving the type %1.")
176 .arg(a: formatType(np: context->namePool(), type: t1)),
177 errorCode, static_cast<const TSubClass *>(this)->actualReflection());
178 }
179 return AtomicComparator::Ptr();
180 }
181
182 const AtomicComparator::Ptr comp(static_cast<const AtomicType *>(t2.data())->accept(locator, operatorID(),
183 static_cast<const TSubClass *>(this)->actualReflection()));
184
185 if(comp)
186 return comp;
187 else if(issueError)
188 {
189 context->error(QtXmlPatterns::tr(sourceText: "Operator %1 is not available between atomic values of type %2 and %3.")
190 .arg(formatKeyword(AtomicComparator::displayName(op: operatorID(),
191 type: comparisonType)),
192 formatType(np: context->namePool(), type: t1),
193 formatType(np: context->namePool(), type: t2)),
194 errorCode, static_cast<const TSubClass *>(this)->actualReflection());
195 }
196
197 return AtomicComparator::Ptr();
198}
199
200template <typename TSubClass, bool issueError,
201 AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode>
202void ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>::
203prepareComparison(const AtomicComparator::Ptr &c)
204{
205 m_comparator = c;
206}
207
208

source code of qtxmlpatterns/src/xmlpatterns/expr/qcomparisonplatform_tpl_p.h