OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2005 Frerich Raabe <raabe@kde.org> | 2 * Copyright (C) 2005 Frerich Raabe <raabe@kde.org> |
3 * Copyright (C) 2006, 2009 Apple Inc. All rights reserved. | 3 * Copyright (C) 2006, 2009 Apple Inc. All rights reserved. |
4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> | 4 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * | 9 * |
10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
(...skipping 21 matching lines...) Expand all Loading... |
32 #include "core/dom/Attr.h" | 32 #include "core/dom/Attr.h" |
33 #include "core/dom/Document.h" | 33 #include "core/dom/Document.h" |
34 #include "core/dom/Element.h" | 34 #include "core/dom/Element.h" |
35 #include "core/dom/NodeTraversal.h" | 35 #include "core/dom/NodeTraversal.h" |
36 #include "core/xml/XPathParser.h" | 36 #include "core/xml/XPathParser.h" |
37 #include "core/xml/XPathUtil.h" | 37 #include "core/xml/XPathUtil.h" |
38 | 38 |
39 namespace WebCore { | 39 namespace WebCore { |
40 namespace XPath { | 40 namespace XPath { |
41 | 41 |
42 Step::Step(Axis axis, const NodeTest& nodeTest, const Vector<Predicate*>& predic
ates) | 42 Step::Step(Axis axis, const NodeTest& nodeTest) |
43 : m_axis(axis) | 43 : m_axis(axis) |
44 , m_nodeTest(nodeTest) | 44 , m_nodeTest(nodeTest) |
45 , m_predicates(predicates) | |
46 { | 45 { |
47 } | 46 } |
48 | 47 |
| 48 Step::Step(Axis axis, const NodeTest& nodeTest, Vector<OwnPtr<Predicate> >& pred
icates) |
| 49 : m_axis(axis) |
| 50 , m_nodeTest(nodeTest) |
| 51 { |
| 52 m_predicates.swap(predicates); |
| 53 } |
| 54 |
49 Step::~Step() | 55 Step::~Step() |
50 { | 56 { |
51 deleteAllValues(m_predicates); | |
52 deleteAllValues(m_nodeTest.mergedPredicates()); | |
53 } | 57 } |
54 | 58 |
55 void Step::optimize() | 59 void Step::optimize() |
56 { | 60 { |
57 // Evaluate predicates as part of node test if possible to avoid building un
necessary NodeSets. | 61 // Evaluate predicates as part of node test if possible to avoid building un
necessary NodeSets. |
58 // E.g., there is no need to build a set of all "foo" nodes to evaluate "foo
[@bar]", we can check the predicate while enumerating. | 62 // E.g., there is no need to build a set of all "foo" nodes to evaluate "foo
[@bar]", we can check the predicate while enumerating. |
59 // This optimization can be applied to predicates that are not context node
list sensitive, or to first predicate that is only context position sensitive, e
.g. foo[position() mod 2 = 0]. | 63 // This optimization can be applied to predicates that are not context node
list sensitive, or to first predicate that is only context position sensitive, e
.g. foo[position() mod 2 = 0]. |
60 Vector<Predicate*> remainingPredicates; | 64 Vector<OwnPtr<Predicate> > remainingPredicates; |
61 for (size_t i = 0; i < m_predicates.size(); ++i) { | 65 for (size_t i = 0; i < m_predicates.size(); ++i) { |
62 Predicate* predicate = m_predicates[i]; | 66 OwnPtr<Predicate> predicate(m_predicates[i].release()); |
63 if ((!predicate->isContextPositionSensitive() || m_nodeTest.mergedPredic
ates().isEmpty()) && !predicate->isContextSizeSensitive() && remainingPredicates
.isEmpty()) { | 67 if ((!predicate->isContextPositionSensitive() || m_nodeTest.mergedPredic
ates().isEmpty()) && !predicate->isContextSizeSensitive() && remainingPredicates
.isEmpty()) { |
64 m_nodeTest.mergedPredicates().append(predicate); | 68 m_nodeTest.mergedPredicates().append(predicate.release()); |
65 } else | 69 } else { |
66 remainingPredicates.append(predicate); | 70 remainingPredicates.append(predicate.release()); |
| 71 } |
67 } | 72 } |
68 swap(remainingPredicates, m_predicates); | 73 swap(remainingPredicates, m_predicates); |
69 } | 74 } |
70 | 75 |
71 void optimizeStepPair(Step* first, Step* second, bool& dropSecondStep) | 76 void optimizeStepPair(Step* first, Step* second, bool& dropSecondStep) |
72 { | 77 { |
73 dropSecondStep = false; | 78 dropSecondStep = false; |
74 | 79 |
75 if (first->m_axis == Step::DescendantOrSelfAxis | 80 if (first->m_axis == Step::DescendantOrSelfAxis |
76 && first->m_nodeTest.kind() == Step::NodeTest::AnyNodeTest | 81 && first->m_nodeTest.kind() == Step::NodeTest::AnyNodeTest |
(...skipping 11 matching lines...) Expand all Loading... |
88 swap(second->m_predicates, first->m_predicates); | 93 swap(second->m_predicates, first->m_predicates); |
89 first->optimize(); | 94 first->optimize(); |
90 dropSecondStep = true; | 95 dropSecondStep = true; |
91 } | 96 } |
92 } | 97 } |
93 } | 98 } |
94 | 99 |
95 bool Step::predicatesAreContextListInsensitive() const | 100 bool Step::predicatesAreContextListInsensitive() const |
96 { | 101 { |
97 for (size_t i = 0; i < m_predicates.size(); ++i) { | 102 for (size_t i = 0; i < m_predicates.size(); ++i) { |
98 Predicate* predicate = m_predicates[i]; | 103 Predicate* predicate = m_predicates[i].get(); |
99 if (predicate->isContextPositionSensitive() || predicate->isContextSizeS
ensitive()) | 104 if (predicate->isContextPositionSensitive() || predicate->isContextSizeS
ensitive()) |
100 return false; | 105 return false; |
101 } | 106 } |
102 | 107 |
103 for (size_t i = 0; i < m_nodeTest.mergedPredicates().size(); ++i) { | 108 for (size_t i = 0; i < m_nodeTest.mergedPredicates().size(); ++i) { |
104 Predicate* predicate = m_nodeTest.mergedPredicates()[i]; | 109 Predicate* predicate = m_nodeTest.mergedPredicates()[i].get(); |
105 if (predicate->isContextPositionSensitive() || predicate->isContextSizeS
ensitive()) | 110 if (predicate->isContextPositionSensitive() || predicate->isContextSizeS
ensitive()) |
106 return false; | 111 return false; |
107 } | 112 } |
108 | 113 |
109 return true; | 114 return true; |
110 } | 115 } |
111 | 116 |
112 void Step::evaluate(Node* context, NodeSet& nodes) const | 117 void Step::evaluate(Node* context, NodeSet& nodes) const |
113 { | 118 { |
114 EvaluationContext& evaluationContext = Expression::evaluationContext(); | 119 EvaluationContext& evaluationContext = Expression::evaluationContext(); |
115 evaluationContext.position = 0; | 120 evaluationContext.position = 0; |
116 | 121 |
117 nodesInAxis(context, nodes); | 122 nodesInAxis(context, nodes); |
118 | 123 |
119 // Check predicates that couldn't be merged into node test. | 124 // Check predicates that couldn't be merged into node test. |
120 for (unsigned i = 0; i < m_predicates.size(); i++) { | 125 for (unsigned i = 0; i < m_predicates.size(); i++) { |
121 Predicate* predicate = m_predicates[i]; | 126 Predicate* predicate = m_predicates[i].get(); |
122 | 127 |
123 NodeSet newNodes; | 128 NodeSet newNodes; |
124 if (!nodes.isSorted()) | 129 if (!nodes.isSorted()) |
125 newNodes.markSorted(false); | 130 newNodes.markSorted(false); |
126 | 131 |
127 for (unsigned j = 0; j < nodes.size(); j++) { | 132 for (unsigned j = 0; j < nodes.size(); j++) { |
128 Node* node = nodes[j]; | 133 Node* node = nodes[j]; |
129 | 134 |
130 evaluationContext.node = node; | 135 evaluationContext.node = node; |
131 evaluationContext.size = nodes.size(); | 136 evaluationContext.size = nodes.size(); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
210 static inline bool nodeMatches(Node* node, Step::Axis axis, const Step::NodeTest
& nodeTest) | 215 static inline bool nodeMatches(Node* node, Step::Axis axis, const Step::NodeTest
& nodeTest) |
211 { | 216 { |
212 if (!nodeMatchesBasicTest(node, axis, nodeTest)) | 217 if (!nodeMatchesBasicTest(node, axis, nodeTest)) |
213 return false; | 218 return false; |
214 | 219 |
215 EvaluationContext& evaluationContext = Expression::evaluationContext(); | 220 EvaluationContext& evaluationContext = Expression::evaluationContext(); |
216 | 221 |
217 // Only the first merged predicate may depend on position. | 222 // Only the first merged predicate may depend on position. |
218 ++evaluationContext.position; | 223 ++evaluationContext.position; |
219 | 224 |
220 const Vector<Predicate*>& mergedPredicates = nodeTest.mergedPredicates(); | 225 const Vector<OwnPtr<Predicate> >& mergedPredicates = nodeTest.mergedPredicat
es(); |
221 for (unsigned i = 0; i < mergedPredicates.size(); i++) { | 226 for (unsigned i = 0; i < mergedPredicates.size(); i++) { |
222 Predicate* predicate = mergedPredicates[i]; | 227 Predicate* predicate = mergedPredicates[i].get(); |
223 | 228 |
224 evaluationContext.node = node; | 229 evaluationContext.node = node; |
225 // No need to set context size - we only get here when evaluating predic
ates that do not depend on it. | 230 // No need to set context size - we only get here when evaluating predic
ates that do not depend on it. |
226 if (!predicate->evaluate()) | 231 if (!predicate->evaluate()) |
227 return false; | 232 return false; |
228 } | 233 } |
229 | 234 |
230 return true; | 235 return true; |
231 } | 236 } |
232 | 237 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 nodes.markSorted(false); | 392 nodes.markSorted(false); |
388 return; | 393 return; |
389 } | 394 } |
390 } | 395 } |
391 ASSERT_NOT_REACHED(); | 396 ASSERT_NOT_REACHED(); |
392 } | 397 } |
393 | 398 |
394 | 399 |
395 } | 400 } |
396 } | 401 } |
OLD | NEW |