Qt 4.8
qpath.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 "qgenericsequencetype_p.h"
45 #include "qnodesort_p.h"
46 #include "qpatternistlocale_p.h"
48 #include "qtypechecker_p.h"
49 
50 #include "qpath_p.h"
51 
53 
54 using namespace QPatternist;
55 
56 Path::Path(const Expression::Ptr &operand1,
57  const Expression::Ptr &operand2,
58  const Kind kind) : PairContainer(operand1, operand2)
59  , m_hasCreatedSorter(kind != RegularPath)
60  , m_isLast(false)
61  , m_checkXPTY0018(kind == RegularPath)
62  , m_kind(kind)
63 {
64 }
65 
67  const DynamicContext::Ptr &context) const
68 {
69  /* item is the focus here. That is in <e/>/1, item is <e/>. However,
70  * we don't use it, since the context item is accessed through
71  * DynamicContext::focusIterator() and friends. */
72  Q_ASSERT(item);
73  Q_UNUSED(item); /* Needed when compiling in release mode. */
74  return m_operand2->evaluateSequence(context);
75 }
76 
78 {
79  /* Note, we use the old context for m_operand1. */
80  const Item::Iterator::Ptr source(m_operand1->evaluateSequence(context));
81 
82  const DynamicContext::Ptr focus(context->createFocus());
83  focus->setFocusIterator(source);
84 
85  const Item::Iterator::Ptr result(makeSequenceMappingIterator<Item>(ConstPtr(this), source, focus));
86 
87  if(m_checkXPTY0018)
88  {
89  /* This is an expensive code path, but it should happen very rarely. */
90 
91  enum FoundItem
92  {
93  FoundNone,
94  FoundNode,
95  FoundAtomicValue
96  } hasFound = FoundNone;
97 
98  Item::List whenChecked;
99 
100  Item next(result->next());
101 
102  while(next)
103  {
104  const FoundItem found = next.isAtomicValue() ? FoundAtomicValue : FoundNode;
105 
106  if(hasFound != FoundNone && hasFound != found)
107  {
108  /* It's an atomic value and we've already found a node. Mixed content. */
109  context->error(QtXmlPatterns::tr("The last step in a path must contain either nodes "
110  "or atomic values. It cannot be a mixture between the two."),
112  }
113  else
114  hasFound = found;
115 
116  whenChecked.append(next);
117  next = result->next();
118  }
119 
120  return makeListIterator(whenChecked);
121  }
122  else
123  return result;
124 }
125 
127 {
128  /* This function is called if both operands' cardinality is exactly-one. Therefore
129  * we manually go forward in the focus by calling next().
130  *
131  * We don't check for XPTY0018, only in evaluateSequence(), since if we're guaranteed
132  * to evaluate to one item, we can only evaluate to one node or one atomic value.
133  */
134 
135  /* Note, we use the old context for m_operand1. */
136  const Item::Iterator::Ptr source(m_operand1->evaluateSequence(context));
137 
138  const DynamicContext::Ptr focus(context->createFocus());
139  focus->setFocusIterator(source);
140 
141  /* This test is needed because if the focus is empty, we don't want to(nor can't) evaluate
142  * the next step. */
143  // TODO Why are we at all invoked then?
144  if(source->next())
145  return m_operand2->evaluateSingleton(focus);
146  else
147  return Item();
148 }
149 
151 {
152  /* Note, we use the old context for m_operand1. */
153  const Item::Iterator::Ptr source(m_operand1->evaluateSequence(context));
154 
155  const DynamicContext::Ptr focus(context->createFocus());
156  focus->setFocusIterator(source);
157 
158  while(source->next())
160 }
161 
163 {
164  const Expression::Ptr me(PairContainer::compress(context));
165 
166  /* "./expr" is by now equal to "expr" since we've done
167  * focus/type checks, and a node sorter has been inserted. */
169  return m_operand2;
170 
171  /* We do this as late as we can, such that we pick up the most recent type
172  * from the operand. */
174  m_checkXPTY0018 = true;
175 
176  return me;
177 }
178 
180  const SequenceType::Ptr &reqType)
181 {
183 
184  /* Here we apply the function conversion first, and with the error code
185  * that we want -- XPTY0019 instead of XPTY0004. Unfortunately
186  * PairContainer::typeCheck() will do the type check again, which is
187  * redundant in the case of when we're not XSLTForEach.
188  *
189  * If we're XSLTForEach, it means we're a synthetic "map" expression for
190  * implementing various XSL-T expressions, and hence don't have the
191  * constraint of XPTY0019.
192  *
193  * It's important that typeCheck() is run for the operands(of course), and the call to
194  * PairContainer::typeCheck() ensures that below, in the case that we're XSL-T code.
195  *
196  * The type we expect, CommonSequenceTypes::ZeroOrMoreNodes() needs to be in sync with
197  * what we return in expectedOperandTypes(). */
198  if(m_kind != XSLTForEach)
199  {
202  context,
205  }
206 
207  /* If our step ends with atomic values, we cannot sort.
208  *
209  * We must smack the NodeSortExpression ontop before calling typeCheck(), since the latter
210  * may insert an Atomizer, as possibly mandated by reqType. By doing it after, the Atomizer
211  * will be a parent to NodeSortExpression, as opposed to a child.
212  */
213  if(!m_hasCreatedSorter)
214  {
215  m_hasCreatedSorter = true;
216 
217  return NodeSortExpression::wrapAround(Expression::Ptr(this), context)->typeCheck(context, reqType);
218  }
219  else
220  return PairContainer::typeCheck(context, reqType);
221 }
222 
224 {
225  SequenceType::List result;
226 
227  /* This value needs to be in sync with what we pass to
228  * applyFunctionConversion() in typeCheck() above.
229  *
230  * We don't have the XPTY0019 restriction when we're synthetic XSL-T code.
231  */
232  if(m_kind == XSLTForEach)
234  else
236 
238  return result;
239 }
240 
242 {
243  const SequenceType::Ptr opType(m_operand2->staticType());
244 
245  /* For each parent step, we evaluate the child step. So multiply the two
246  * cardinalities. */
247  return makeGenericSequenceType(opType->itemType(),
248  m_operand1->staticType()->cardinality() * opType->cardinality());
249 }
250 
252 {
253  return visitor->visit(this);
254 }
255 
257 {
259 }
260 
262 {
263  return m_operand1->staticType()->itemType();
264 }
265 
267 {
268  return IDPath;
269 }
270 
virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType)
Definition: qpath.cpp:179
bool m_checkXPTY0018
Definition: qpath_p.h:162
Item::Iterator::Ptr mapToSequence(const Item &item, const DynamicContext::Ptr &context) const
Definition: qpath.cpp:66
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const
Definition: qpath.cpp:77
static const SequenceType::Ptr ZeroOrMoreItems
Path(const Expression::Ptr &operand1, const Expression::Ptr &operand2, const Kind kind=RegularPath)
Definition: qpath.cpp:56
virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const
Definition: qpath.cpp:251
virtual ID id() const
Definition: qpath.cpp:266
virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType)
Definition: qexpression.cpp:70
static const SequenceType::Ptr ZeroOrMoreNodes
QAbstractXmlForwardIterator< T >::Ptr makeListIterator(const QList< T > &list)
virtual ItemType::Ptr newFocusType() const
Definition: qpath.cpp:261
virtual Expression::Ptr compress(const StaticContext::Ptr &context)
Definition: qpath.cpp:162
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
virtual Expression::Ptr compress(const StaticContext::Ptr &context)
virtual SequenceType::Ptr staticType() const
Definition: qpath.cpp:241
DynamicContext::Ptr createFocus()
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void error(const QString &message, const ReportContext::ErrorCode errorCode, const QSourceLocation &sourceLocation)
static const ItemType::Ptr item
The namespace for the internal API of QtXmlPatterns.
virtual void setFocusIterator(const Item::Iterator::Ptr &it)=0
virtual Cardinality cardinality() const =0
QExplicitlySharedDataPointer< const Path > ConstPtr
Definition: qpath_p.h:140
virtual SequenceType::List expectedOperandTypes() const
Definition: qpath.cpp:223
bool isAtomicValue() const
Determines whether this item is an atomic value, or a node.
Definition: qitem_p.h:335
virtual SequenceType::Ptr staticType() const =0
virtual Properties properties() const
Definition: qpath.cpp:256
Contains functions used for formatting arguments, such as keywords and paths, in translated strings...
Represents an item in the XPath 2.0 Data Model.
Definition: qitem_p.h:182
static Expression::Ptr applyFunctionConversion(const Expression::Ptr &operand, const SequenceType::Ptr &reqType, const StaticContext::Ptr &context, const ReportContext::ErrorCode code=ReportContext::XPTY0004, const Options=Options(AutomaticallyConvert|CheckFocus))
Builds a pipeline of artificial AST nodes that ensures operand conforms to the type reqType by applyi...
bool m_hasCreatedSorter
Definition: qpath_p.h:154
virtual Properties properties() const
virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
Definition: qpath.cpp:150
The QFlags class provides a type-safe way of storing OR-combinations of enum values.
Definition: qglobal.h:2313
virtual ItemType::Ptr itemType() const =0
const Kind m_kind
Definition: qpath_p.h:163
bool is(const ID id) const
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
virtual void evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
static Expression::Ptr wrapAround(const Expression::Ptr &operand, const StaticContext::Ptr &context)
Definition: qnodesort.cpp:92
virtual void announceFocusType(const ItemType::Ptr &itemType)
virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const
virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const
Definition: qpath.cpp:126
virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const
Base class for expressions that has exactly two operands.