Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / xml / XPathPath.cpp
1 /*
2  * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
3  * Copyright (C) 2006, 2009, 2013 Apple Inc. All rights reserved.
4  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #include "XPathPath.h"
30
31 #include "Document.h"
32 #include "XPathPredicate.h"
33 #include "XPathStep.h"
34
35 namespace WebCore {
36 namespace XPath {
37         
38 Filter::Filter(std::unique_ptr<Expression> expression, Vector<std::unique_ptr<Expression>> predicates)
39     : m_expression(WTFMove(expression)), m_predicates(WTFMove(predicates))
40 {
41     setIsContextNodeSensitive(m_expression->isContextNodeSensitive());
42     setIsContextPositionSensitive(m_expression->isContextPositionSensitive());
43     setIsContextSizeSensitive(m_expression->isContextSizeSensitive());
44 }
45
46 Value Filter::evaluate() const
47 {
48     Value result = m_expression->evaluate();
49     
50     NodeSet& nodes = result.modifiableNodeSet();
51     nodes.sort();
52
53     EvaluationContext& evaluationContext = Expression::evaluationContext();
54     for (auto& predicate : m_predicates) {
55         NodeSet newNodes;
56         evaluationContext.size = nodes.size();
57         evaluationContext.position = 0;
58         
59         for (auto& node : nodes) {
60             evaluationContext.node = node;
61             ++evaluationContext.position;
62             
63             if (evaluatePredicate(*predicate))
64                 newNodes.append(node.copyRef());
65         }
66         nodes = WTFMove(newNodes);
67     }
68
69     return result;
70 }
71
72 LocationPath::LocationPath()
73     : m_isAbsolute(false)
74 {
75     setIsContextNodeSensitive(true);
76 }
77
78 Value LocationPath::evaluate() const
79 {
80     EvaluationContext& evaluationContext = Expression::evaluationContext();
81     EvaluationContext backupContext = evaluationContext;
82     // http://www.w3.org/TR/xpath/
83     // Section 2, Location Paths:
84     // "/ selects the document root (which is always the parent of the document element)"
85     // "A / by itself selects the root node of the document containing the context node."
86     // In the case of a tree that is detached from the document, we violate
87     // the spec and treat / as the root node of the detached tree.
88     // This is for compatibility with Firefox, and also seems like a more
89     // logical treatment of where you would expect the "root" to be.
90     Node* context = evaluationContext.node.get();
91     if (m_isAbsolute && !context->isDocumentNode())  {
92         if (context->inDocument())
93             context = context->ownerDocument();
94         else
95             context = context->highestAncestor();
96     }
97
98     NodeSet nodes;
99     nodes.append(context);
100     evaluate(nodes);
101     
102     evaluationContext = backupContext;
103     return Value(WTFMove(nodes));
104 }
105
106 void LocationPath::evaluate(NodeSet& nodes) const
107 {
108     bool resultIsSorted = nodes.isSorted();
109
110     for (auto& step : m_steps) {
111         NodeSet newNodes;
112         HashSet<Node*> newNodesSet;
113
114         bool needToCheckForDuplicateNodes = !nodes.subtreesAreDisjoint() || (step->axis() != Step::ChildAxis && step->axis() != Step::SelfAxis
115             && step->axis() != Step::DescendantAxis && step->axis() != Step::DescendantOrSelfAxis && step->axis() != Step::AttributeAxis);
116
117         if (needToCheckForDuplicateNodes)
118             resultIsSorted = false;
119
120         // This is a simplified check that can be improved to handle more cases.
121         if (nodes.subtreesAreDisjoint() && (step->axis() == Step::ChildAxis || step->axis() == Step::SelfAxis))
122             newNodes.markSubtreesDisjoint(true);
123
124         for (auto& node : nodes) {
125             NodeSet matches;
126             step->evaluate(*node, matches);
127
128             if (!matches.isSorted())
129                 resultIsSorted = false;
130
131             for (auto& match : matches) {
132                 if (!needToCheckForDuplicateNodes || newNodesSet.add(match.get()).isNewEntry)
133                     newNodes.append(match.copyRef());
134             }
135         }
136         
137         nodes = WTFMove(newNodes);
138     }
139
140     nodes.markSorted(resultIsSorted);
141 }
142
143 void LocationPath::appendStep(std::unique_ptr<Step> step)
144 {
145     unsigned stepCount = m_steps.size();
146     if (stepCount) {
147         bool dropSecondStep;
148         optimizeStepPair(*m_steps[stepCount - 1], *step, dropSecondStep);
149         if (dropSecondStep)
150             return;
151     }
152     step->optimize();
153     m_steps.append(WTFMove(step));
154 }
155
156 void LocationPath::prependStep(std::unique_ptr<Step> step)
157 {
158     if (m_steps.size()) {
159         bool dropSecondStep;
160         optimizeStepPair(*step, *m_steps[0], dropSecondStep);
161         if (dropSecondStep) {
162             m_steps[0] = WTFMove(step);
163             return;
164         }
165     }
166     step->optimize();
167     m_steps.insert(0, WTFMove(step));
168 }
169
170 Path::Path(std::unique_ptr<Expression> filter, std::unique_ptr<LocationPath> path)
171     : m_filter(WTFMove(filter))
172     , m_path(WTFMove(path))
173 {
174     setIsContextNodeSensitive(m_filter->isContextNodeSensitive());
175     setIsContextPositionSensitive(m_filter->isContextPositionSensitive());
176     setIsContextSizeSensitive(m_filter->isContextSizeSensitive());
177 }
178
179 Value Path::evaluate() const
180 {
181     Value result = m_filter->evaluate();
182
183     NodeSet& nodes = result.modifiableNodeSet();
184     m_path->evaluate(nodes);
185     
186     return result;
187 }
188
189 }
190 }