source: trunk/src/xmlpatterns/data/qatomiccomparators.cpp@ 5

Last change on this file since 5 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 13.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qabstractduration_p.h"
43#include "qabstractdatetime_p.h"
44#include "qbase64binary_p.h"
45#include "qboolean_p.h"
46#include "qdynamiccontext_p.h"
47#include "qqnamevalue_p.h"
48
49#include "qatomiccomparators_p.h"
50
51QT_BEGIN_NAMESPACE
52
53using namespace QPatternist;
54
55/* -------------------------------------------------- */
56AtomicComparator::ComparisonResult
57StringComparator::compare(const Item &o1,
58 const AtomicComparator::Operator,
59 const Item &o2) const
60{
61 const int result = QString::compare(o1.stringValue(), o2.stringValue());
62
63 if(result > 0)
64 return GreaterThan;
65 else if(result < 0)
66 return LessThan;
67 else
68 {
69 Q_ASSERT(result == 0);
70 return Equal;
71 }
72}
73
74bool StringComparator::equals(const Item &o1,
75 const Item &o2) const
76{
77 return o1.stringValue() == o2.stringValue();
78}
79/* -------------------------------------------------- */
80
81/* -------------------------------------------------- */
82AtomicComparator::ComparisonResult
83CaseInsensitiveStringComparator::compare(const Item &o1,
84 const AtomicComparator::Operator,
85 const Item &o2) const
86{
87 const QString i1(o1.stringValue().toLower());
88 const QString i2(o2.stringValue().toLower());
89 const int result = QString::compare(i1, i2);
90
91 if(result > 0)
92 return GreaterThan;
93 else if(result < 0)
94 return LessThan;
95 else
96 {
97 Q_ASSERT(result == 0);
98 return Equal;
99 }
100}
101
102bool CaseInsensitiveStringComparator::equals(const Item &o1,
103 const Item &o2) const
104{
105 const QString s1(o1.stringValue());
106 const QString s2(o2.stringValue());
107
108 return s1.length() == s2.length() &&
109 s1.startsWith(s2, Qt::CaseInsensitive);
110}
111/* -------------------------------------------------- */
112
113/* -------------------------------------------------- */
114bool BinaryDataComparator::equals(const Item &o1,
115 const Item &o2) const
116{
117 return o1.as<Base64Binary>()->asByteArray() ==
118 o2.as<Base64Binary>()->asByteArray();
119}
120/* -------------------------------------------------- */
121
122/* -------------------------------------------------- */
123AtomicComparator::ComparisonResult
124BooleanComparator::compare(const Item &o1,
125 const AtomicComparator::Operator,
126 const Item &o2) const
127{
128 /* We know Boolean::evaluateEBV doesn't use the DynamicContext. */
129 const bool v1 = o1.as<AtomicValue>()->evaluateEBV(QExplicitlySharedDataPointer<DynamicContext>());
130 const bool v2 = o2.as<AtomicValue>()->evaluateEBV(QExplicitlySharedDataPointer<DynamicContext>());
131
132 if(v1 == v2)
133 return Equal;
134 else if(v1 == false)
135 {
136 Q_ASSERT(v2 == true);
137 return LessThan;
138 }
139 else
140 {
141 Q_ASSERT(v1 == true && v2 == false);
142 return GreaterThan;
143 }
144}
145
146bool BooleanComparator::equals(const Item &o1,
147 const Item &o2) const
148{
149 /* Boolean is an atomic class. */
150 return o1.as<AtomicValue>() == o2.as<AtomicValue>();
151}
152/* -------------------------------------------------- */
153
154/* -------------------------------------------------- */
155AtomicComparator::ComparisonResult
156AbstractFloatComparator::compare(const Item &o1,
157 const AtomicComparator::Operator op,
158 const Item &o2) const
159{
160 const xsDouble v1 = o1.as<Numeric>()->toDouble();
161 const xsDouble v2 = o2.as<Numeric>()->toDouble();
162
163 if(Double::isEqual(v1, v2))
164 return Equal;
165 else if(v1 < v2)
166 return LessThan;
167 else if(v1 > v2)
168 return GreaterThan;
169 else
170 {
171 /* We have NaN values. Make sure we don't return a result which would
172 * signify success for the operator in question. */
173 if((op & OperatorGreaterThan) == OperatorGreaterThan)
174 return LessThan;
175 else
176 {
177 Q_ASSERT((op & OperatorLessThan) == OperatorLessThan);
178 return GreaterThan;
179 }
180 }
181}
182
183bool AbstractFloatComparator::equals(const Item &o1,
184 const Item &o2) const
185{
186 return Double::isEqual(o1.as<Numeric>()->toDouble(), o2.as<Numeric>()->toDouble());
187}
188/* -------------------------------------------------- */
189
190/* -------------------------------------------------- */
191AtomicComparator::ComparisonResult
192DecimalComparator::compare(const Item &o1,
193 const AtomicComparator::Operator,
194 const Item &o2) const
195{
196 const xsDecimal v1 = o1.as<Numeric>()->toDecimal();
197 const xsDecimal v2 = o2.as<Numeric>()->toDecimal();
198
199 if(Double::isEqual(v1, v2))
200 return Equal;
201 else if(v1 < v2)
202 return LessThan;
203 else
204 return GreaterThan;
205}
206
207bool DecimalComparator::equals(const Item &o1,
208 const Item &o2) const
209{
210 return Double::isEqual(o1.as<Numeric>()->toDecimal(), o2.as<Numeric>()->toDecimal());
211}
212/* -------------------------------------------------- */
213
214/* -------------------------------------------------- */
215AtomicComparator::ComparisonResult
216IntegerComparator::compare(const Item &o1,
217 const AtomicComparator::Operator,
218 const Item &o2) const
219{
220 const Numeric *const num1 = o1.as<Numeric>();
221 const Numeric *const num2 = o1.as<Numeric>();
222
223 /**
224 * Consider:
225 * xs:unsignedLong("100") > xs:unsignedLong("18446744073709551615")
226 *
227 * If we perform math on the values as if they were xsInteger, the right
228 * operand overflows, wraps around, and the expression evaluates to false.
229 * Hence we have this code to deal with it.
230 *
231 * This is runtime code, it would have been better if we had separate
232 * AtomicComparator classes for signed and unsigned values, but the changes
233 * required to the lookup code are extensive.
234 */
235 if(num1->isSigned() || num2->isSigned())
236 {
237 const xsInteger v1 = o1.as<Numeric>()->toInteger();
238 const xsInteger v2 = o2.as<Numeric>()->toInteger();
239
240 if(v1 == v2)
241 return Equal;
242 else if(v1 < v2)
243 return LessThan;
244 else
245 return GreaterThan;
246 }
247 else
248 {
249 const qulonglong v1 = o1.as<Numeric>()->toUnsignedInteger();
250 const qulonglong v2 = o2.as<Numeric>()->toUnsignedInteger();
251
252 if(v1 == v2)
253 return Equal;
254 else if(v1 < v2)
255 return LessThan;
256 else
257 return GreaterThan;
258 }
259}
260
261bool IntegerComparator::equals(const Item &o1,
262 const Item &o2) const
263{
264 return o1.as<Numeric>()->toInteger() == o2.as<Numeric>()->toInteger();
265}
266
267/* -------------------------------------------------- */
268
269/* -------------------------------------------------- */
270bool QNameComparator::equals(const Item &o1,
271 const Item &o2) const
272{
273 return o1.as<QNameValue>()->m_qName ==
274 o2.as<QNameValue>()->m_qName;
275}
276/* -------------------------------------------------- */
277
278/* -------------------------------------------------- */
279bool AbstractDateTimeComparator::equals(const Item &o1,
280 const Item &o2) const
281{
282 const QDateTime dt1(o1.as<AbstractDateTime>()->toDateTime());
283 const QDateTime dt2(o2.as<AbstractDateTime>()->toDateTime());
284
285 /*
286 pDebug() << "COMPARING:"
287 << o1->as<AbstractDateTime>()->toDateTime().toString()
288 << o2->as<AbstractDateTime>()->toDateTime().toString();
289 pDebug() << "DATE ONLY:"
290 << o1->as<AbstractDateTime>()->toDateTime().isDateOnly()
291 << o2->as<AbstractDateTime>()->toDateTime().isDateOnly();
292 */
293 return dt1 == dt2 &&
294 dt1.timeSpec() == dt2.timeSpec();
295}
296
297AtomicComparator::ComparisonResult
298AbstractDateTimeComparator::compare(const Item &operand1,
299 const AtomicComparator::Operator,
300 const Item &operand2) const