052a47a6b6415e4d3d9236f3fecfd160f8ee6806
[profile/ivi/qtxmlpatterns.git] / src / xmlpatterns / expr / qcomparisonplatform_tpl_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 /**
43  * @file
44  * @short This file is included by qcomparisonplatform_p.h.
45  * If you need includes in this file, put them in qcomparisonplatform_p.h, outside of the namespace.
46  */
47
48 template <typename TSubClass, bool issueError,
49           AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode>
50 bool ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>::
51 flexibleCompare(const Item &it1,
52                 const Item &it2,
53                 const DynamicContext::Ptr &context) const
54 {
55     if(m_comparator)
56         /* The comparator was located at compile time. */
57         return compare(it1, it2, m_comparator, operatorID());
58     else
59     {
60         const AtomicComparator::Ptr cp(fetchComparator(it1.type(),
61                                                        it2.type(),
62                                                        context));
63
64         return cp ? compare(it1, it2, cp, operatorID()) : false;
65     }
66 }
67
68 template <typename TSubClass, bool issueError,
69           AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode>
70 AtomicComparator::ComparisonResult
71 ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>::
72 detailedFlexibleCompare(const Item &it1,
73                         const Item &it2,
74                         const DynamicContext::Ptr &context) const
75 {
76     AtomicComparator::Ptr comp;
77
78     if(m_comparator)
79         comp = m_comparator;
80     else
81     {
82         comp = fetchComparator(it1.type(),
83                                it2.type(),
84                                context);
85     }
86
87     Q_ASSERT_X(operatorID() == AtomicComparator::OperatorLessThanNaNLeast || operatorID() == AtomicComparator::OperatorLessThanNaNGreatest,
88                Q_FUNC_INFO, "Only OperatorLessThan is currently supported for this function.");
89     return comp->compare(it1, operatorID(), it2);
90 }
91
92 template <typename TSubClass, bool issueError,
93           AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode>
94 bool ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>::
95 compare(const Item &oand1,
96         const Item &oand2,
97         const AtomicComparator::Ptr &comp,
98         const AtomicComparator::Operator op) const
99 {
100     Q_ASSERT(oand1);
101     Q_ASSERT(oand2);
102     Q_ASSERT(comp);
103
104     switch(op)
105     {
106         case AtomicComparator::OperatorEqual:
107             return comp->equals(oand1, oand2);
108         case AtomicComparator::OperatorNotEqual:
109             return !comp->equals(oand1, oand2);
110         case AtomicComparator::OperatorLessThanNaNLeast:
111         case AtomicComparator::OperatorLessThanNaNGreatest:
112         /* Fallthrough. */
113         case AtomicComparator::OperatorLessThan:
114             return comp->compare(oand1, op, oand2) == AtomicComparator::LessThan;
115         case AtomicComparator::OperatorGreaterThan:
116             return comp->compare(oand1, op, oand2) == AtomicComparator::GreaterThan;
117         case AtomicComparator::OperatorLessOrEqual:
118         {
119             const AtomicComparator::ComparisonResult ret = comp->compare(oand1, op, oand2);
120             return ret == AtomicComparator::LessThan || ret == AtomicComparator::Equal;
121         }
122         case(AtomicComparator::OperatorGreaterOrEqual):
123         {
124             const AtomicComparator::ComparisonResult ret = comp->compare(oand1, op, oand2);
125             return ret == AtomicComparator::GreaterThan || ret == AtomicComparator::Equal;
126         }
127     }
128
129     /* GCC unbarfer, this line should never be reached. */
130     Q_ASSERT(false);
131     return false;
132 }
133
134 template <typename TSubClass, bool issueError,
135           AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode>
136 AtomicComparator::Ptr ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>::
137 fetchComparator(const ItemType::Ptr &t1,
138                 const ItemType::Ptr &t2,
139                 const ReportContext::Ptr &context) const
140 {
141     Q_ASSERT(t1);
142     Q_ASSERT(t2);
143
144     if(*BuiltinTypes::xsAnyAtomicType == *t1    ||
145        *BuiltinTypes::xsAnyAtomicType == *t2    ||
146        *BuiltinTypes::item == *t1               ||
147        *BuiltinTypes::item == *t2               ||
148        *BuiltinTypes::numeric == *t1            ||
149        *BuiltinTypes::numeric == *t2            ||
150        *CommonSequenceTypes::Empty == *t1       ||
151        *CommonSequenceTypes::Empty == *t2)
152     {
153         /* The static type of(at least) one of the operands could not
154          * be narrowed further, so we do the operator
155          * lookup at runtime.
156          */
157         return AtomicComparator::Ptr();
158     }
159
160     const AtomicComparatorLocator::Ptr locator
161         (static_cast<const AtomicType *>(t1.data())->comparatorLocator());
162
163     if(!locator)
164     {
165         if(issueError)
166         {
167             context->error(QtXmlPatterns::tr("No comparisons can be done involving the type %1.")
168                                             .arg(formatType(context->namePool(), t1)),
169                                        errorCode, static_cast<const TSubClass *>(this)->actualReflection());
170         }
171         return AtomicComparator::Ptr();
172     }
173
174     const AtomicComparator::Ptr comp(static_cast<const AtomicType *>(t2.data())->accept(locator, operatorID(),
175                                                                                        static_cast<const TSubClass *>(this)->actualReflection()));
176
177     if(comp)
178         return comp;
179     else if(issueError)
180     {
181         context->error(QtXmlPatterns::tr("Operator %1 is not available between atomic values of type %2 and %3.")
182                                         .arg(formatKeyword(AtomicComparator::displayName(operatorID(),
183                                                                                          comparisonType)),
184                                              formatType(context->namePool(), t1),
185                                              formatType(context->namePool(), t2)),
186                                    errorCode, static_cast<const TSubClass *>(this)->actualReflection());
187     }
188
189     return AtomicComparator::Ptr();
190 }
191
192 template <typename TSubClass, bool issueError,
193           AtomicComparator::ComparisonType comparisonType, ReportContext::ErrorCode errorCode>
194 void ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>::
195 prepareComparison(const AtomicComparator::Ptr &c)
196 {
197     m_comparator = c;
198 }
199