Qt 4.8
qgeneralcomparison.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qbuiltintypes_p.h"
43 #include "qcommonsequencetypes_p.h"
44 #include "qcommonvalues_p.h"
45 #include "qebvextractor_p.h"
46 #include "qitem_p.h"
47 #include "qliteral_p.h"
48 #include "qoptimizationpasses_p.h"
50 #include "qvaluecomparison_p.h"
51 
52 #include "qgeneralcomparison_p.h"
53 
55 
56 using namespace QPatternist;
57 
60  const Expression::Ptr &op2,
61  const bool isBackwardsCompat) : PairContainer(op1, op2)
62  , m_operator(op)
63  , m_isBackwardsCompat(isBackwardsCompat)
64 {
65 }
66 
68  const Item &op2,
69  const DynamicContext::Ptr &context) const
70 {
71  Q_ASSERT(op1);
72  Q_ASSERT(op2);
73 
74  if(comparator())
75  return compare(op1, op2, comparator(), m_operator);
76 
77  Expression::Ptr a1(new Literal(op1));
78  Expression::Ptr a2(new Literal(op2));
79 
80  const AtomicComparator::Ptr comp(fetchGeneralComparator(a1, a2, context));
81  /* The fetchGeneralComparator call may rewrite a1 and/or a2. */
82  Q_ASSERT(a1);
83  Q_ASSERT(a2);
84  Q_ASSERT(comp);
85 
86  return compare(a1->evaluateSingleton(context),
87  a2->evaluateSingleton(context),
88  comp,
89  m_operator);
90 }
91 
93 {
94  const Item::Iterator::Ptr it1(m_operand1->evaluateSequence(context));
95  Item item1(it1->next());
96 
97  if(!item1)
98  return false;
99 
100  const Item::Iterator::Ptr it2(m_operand2->evaluateSequence(context));
101  Item::List cache;
102  Item item2;
103 
104  while(true)
105  {
106  item2 = it2->next();
107  if(!item2)
108  break;
109 
110  if(generalCompare(item1, item2, context))
111  return true;
112 
113  cache.append(item2);
114  }
115 
116  while(true)
117  {
118  item1 = it1->next();
119 
120  if(!item1)
121  return false;
122 
123  const Item::List::const_iterator end(cache.constEnd());
125 
126  for(; it != end; ++it)
127  if(generalCompare(item1, *it, context))
128  return true;
129  }
130 
131  Q_ASSERT(false);
132  return false;
133 }
134 
136 {
137  const Expression::Ptr me(PairContainer::compress(context));
138 
139  if(me != this)
140  return me;
141 
144 
145  return me;
146 }
147 
149  const SequenceType::Ptr &reqType)
150 {
151 
152  const Expression::Ptr me(PairContainer::typeCheck(context, reqType));
153 
156 
157  if(*CommonSequenceTypes::Empty == *t1 ||
159  {
160  return wrapLiteral(CommonValues::BooleanFalse, context, this);
161  }
162 
163  if(*BuiltinTypes::xsAnyAtomicType == *t1 ||
165  return me;
166 
168 
171  {
172  /* Rewrite to a ValueComparison whose operands uses typing rules
173  * as for an general comparison(that's what's done above). */
175  m_operator,
176  m_operand2))->typeCheck(context, reqType),
177  context);
178  }
179  else
180  return me;
181 }
182 
184  const Expression::Ptr &source)
185 {
186  type = source->staticType()->itemType();
187 }
188 
190  Expression::Ptr &op2,
191  const ReportContext::Ptr &context) const
192 {
193  ItemType::Ptr t1(op1->staticType()->itemType());
194  ItemType::Ptr t2(op2->staticType()->itemType());
195 
196  /* a. "If one of the atomic values is an instance of xs:untypedAtomic and
197  * the other is an instance of a numeric type, then the xs:untypedAtomic
198  * value is cast to the type xs:double." */
199  if(BuiltinTypes::numeric->xdtTypeMatches(t1) &&
200  BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t2))
201  {
203 
204  /* The types might have changed, reload. */
205  updateType(t2, op2);
206  }
207  else if(BuiltinTypes::numeric->xdtTypeMatches(t2) &&
208  BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t1))
209  {
211 
212  /* The types might have changed, reload. */
213  updateType(t1, op1);
214  }
215  /* "If XPath 1.0 compatibility mode is true, a general comparison is
216  * evaluated by applying the following rules, in order:
217  * 1. If either operand is a single atomic value that is an instance of
218  * xs:boolean, then the other operand is converted to xs:boolean by taking
219  * its effective boolean value."
220  *
221  * Notably, it's not conversion to boolean, it is EBV extraction.
222  */
223  else if(m_isBackwardsCompat && BuiltinTypes::xsBoolean->xdtTypeMatches(t1))
224  {
225  op2 = Expression::Ptr(new EBVExtractor(op2));
226  updateType(t2, op2);
227  }
228  else if(m_isBackwardsCompat && BuiltinTypes::xsBoolean->xdtTypeMatches(t2))
229  {
230  op1 = Expression::Ptr(new EBVExtractor(op1));
231  updateType(t1, op1);
232  }
233  /* b. "If one of the atomic values is an instance of xs:untypedAtomic and
234  * the other is an instance of xs:untypedAtomic or xs:string, then the
235  * xs:untypedAtomic value (or values) is (are) cast to the type xs:string."
236  *
237  * c. "If one of the atomic values is an instance of xs:untypedAtomic and the
238  * other is not an instance of xs:string, xs:untypedAtomic, or any numeric
239  * type, then the xs:untypedAtomic value is cast to the dynamic type of the
240  * other value." */
241  else if(BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t1) &&
242  !BuiltinTypes::xsString->xdtTypeMatches(t2) &&
243  !BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t2) &&
244  !BuiltinTypes::xsAnyURI->xdtTypeMatches(t2))
245  {
246  op1 = Expression::Ptr(new UntypedAtomicConverter(op1, t2));
247  updateType(t1, op1);
248  }
249  else if(BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t2) &&
250  !BuiltinTypes::xsString->xdtTypeMatches(t1) &&
251  !BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t1) &&
252  !BuiltinTypes::xsAnyURI->xdtTypeMatches(t1))
253  {
254  op2 = Expression::Ptr(new UntypedAtomicConverter(op2, t1));
255  updateType(t2, op2);
256  }
257 
258  /* d. "After performing the conversions described above, the atomic
259  * values are compared using one of the value comparison operators
260  * eq, ne, lt, le, gt, or ge, depending on whether the general comparison
261  * operator was =, !=, <, <=, >, or >=. The values have the required
262  * magnitude relationship if and only if the result of this value comparison
263  * is true." */
264 
265  return fetchComparator(t1, t2, context);
266 }
267 
269 {
272 }
273 
275 {
276  SequenceType::List result;
279  return result;
280 }
281 
283 {
285 }
286 
288 {
289  return visitor->visit(this);
290 }
291 
293 {
294  return IDGeneralComparison;
295 }
296 
int type
Definition: qmetatype.cpp:239
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static void updateType(ItemType::Ptr &type, const Expression::Ptr &source)
#define it(className, varName)
bool generalCompare(const Item &op1, const Item &op2, const DynamicContext::Ptr &context) const
virtual SequenceType::List expectedOperandTypes() const
Due to strong interdependencies, this file contains the definitions for the classes Item...
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qlist.h:269
virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType)
Definition: qexpression.cpp:70
virtual QList< QExplicitlySharedDataPointer< OptimizationPass > > optimizationPasses() const
bool compare(const Item &i1, const Item &i2, const AtomicComparator::Ptr &comp, const AtomicComparator::Operator op) const
Compares i1 and i2 with operator op, using comparator comp. All input arguments must be valid...
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
virtual Expression::Ptr compress(const StaticContext::Ptr &context)
virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType)
AtomicComparator::Ptr fetchComparator(const ItemType::Ptr &type1, const ItemType::Ptr &type2, const ReportContext::Ptr &context) const
virtual Expression::Ptr compress(const StaticContext::Ptr &context)
static const AtomicType::Ptr xsString
friend class const_iterator
Definition: qlist.h:264
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
OptimizationPass::List comparisonPasses
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static bool isEmpty(const char *str)
static void rewrite(Expression::Ptr &old, const Expression::Ptr &New, const StaticContext::Ptr &context)
const AtomicComparator::Operator m_operator
The namespace for the internal API of QtXmlPatterns.
static const AtomicType::Ptr xsDouble
virtual Cardinality cardinality() const =0
virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const
GeneralComparison(const Expression::Ptr &op1, const AtomicComparator::Operator op, const Expression::Ptr &op2, const bool isBackwardsCompat=false)
static const AtomicType::Ptr xsUntypedAtomic
Houses an AtomicValue, making it available as an Expression.
Definition: qliteral_p.h:74
QExplicitlySharedDataPointer< Expression > Ptr
A smart pointer wrapping mutable Expression instances.
static const SequenceType::Ptr ExactlyOneBoolean
virtual SequenceType::Ptr staticType() const =0
static const EmptySequenceType::Ptr Empty
Represents an item in the XPath 2.0 Data Model.
Definition: qitem_p.h:182
AtomicComparator::Ptr fetchGeneralComparator(Expression::Ptr &op1, Expression::Ptr &op2, const ReportContext::Ptr &context) const
static const AtomicType::Ptr numeric
Calculates the Effective Boolean Value of its operand.
Casts every item in a sequence obtained from evaluating an Expression, to a requested atomic type...
virtual bool evaluateEBV(const DynamicContext::Ptr &) const
static const AtomicType::Ptr xsBoolean
static const AtomicType::Ptr xsAnyAtomicType
Implements XPath 2.0 value comparions, such as the eq operator.
virtual ItemType::Ptr itemType() const =0
static bool isCaseInsensitiveCompare(Expression::Ptr &op1, Expression::Ptr &op2)
static const SequenceType::Ptr ZeroOrMoreAtomicTypes
static const AtomicValue::Ptr BooleanFalse
static const KeyPair *const end
virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const
static const AtomicType::Ptr xsAnyURI
virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:272
virtual SequenceType::Ptr staticType() const
Base class for expressions that has exactly two operands.