diff options
author | Feng Qian <fqian@google.com> | 2009-06-17 12:12:20 -0700 |
---|---|---|
committer | Feng Qian <fqian@google.com> | 2009-06-17 12:12:20 -0700 |
commit | 5f1ab04193ad0130ca8204aadaceae083aca9881 (patch) | |
tree | 5a92cd389e2cfe7fb67197ce14b38469462379f8 /WebCore/xml/XPathPath.cpp | |
parent | 194315e5a908cc8ed67d597010544803eef1ac59 (diff) | |
download | external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.zip external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.gz external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.bz2 |
Get WebKit r44544.
Diffstat (limited to 'WebCore/xml/XPathPath.cpp')
-rw-r--r-- | WebCore/xml/XPathPath.cpp | 92 |
1 files changed, 50 insertions, 42 deletions
diff --git a/WebCore/xml/XPathPath.cpp b/WebCore/xml/XPathPath.cpp index bc7b153..1a7ed3f 100644 --- a/WebCore/xml/XPathPath.cpp +++ b/WebCore/xml/XPathPath.cpp @@ -1,6 +1,6 @@ /* - * Copyright 2005 Frerich Raabe <raabe@kde.org> - * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2005 Frerich Raabe <raabe@kde.org> + * Copyright (C) 2006, 2009 Apple Inc. * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org> * * Redistribution and use in source and binary forms, with or without @@ -41,6 +41,9 @@ namespace XPath { Filter::Filter(Expression* expr, const Vector<Predicate*>& predicates) : m_expr(expr), m_predicates(predicates) { + setIsContextNodeSensitive(m_expr->isContextNodeSensitive()); + setIsContextPositionSensitive(m_expr->isContextPositionSensitive()); + setIsContextSizeSensitive(m_expr->isContextSizeSensitive()); } Filter::~Filter() @@ -53,9 +56,6 @@ Value Filter::evaluate() const { Value v = m_expr->evaluate(); - if (!v.isNodeSet()) - return v; - NodeSet& nodes = v.modifiableNodeSet(); nodes.sort(); @@ -83,6 +83,7 @@ Value Filter::evaluate() const LocationPath::LocationPath() : m_absolute(false) { + setIsContextNodeSensitive(true); } LocationPath::~LocationPath() @@ -94,9 +95,8 @@ Value LocationPath::evaluate() const { EvaluationContext& evaluationContext = Expression::evaluationContext(); EvaluationContext backupContext = evaluationContext; - /* For absolute location paths, the context node is ignored - the - * document's root node is used instead. - */ + // For absolute location paths, the context node is ignored - the + // document's root node is used instead. Node* context = evaluationContext.node.get(); if (m_absolute && context->nodeType() != Node::DOCUMENT_NODE) context = context->ownerDocument(); @@ -111,18 +111,33 @@ Value LocationPath::evaluate() const void LocationPath::evaluate(NodeSet& nodes) const { + bool resultIsSorted = nodes.isSorted(); + for (unsigned i = 0; i < m_steps.size(); i++) { Step* step = m_steps[i]; NodeSet newNodes; HashSet<Node*> newNodesSet; + bool needToCheckForDuplicateNodes = !nodes.subtreesAreDisjoint() || (step->axis() != Step::ChildAxis && step->axis() != Step::SelfAxis + && step->axis() != Step::DescendantAxis && step->axis() != Step::DescendantOrSelfAxis && step->axis() != Step::AttributeAxis); + + if (needToCheckForDuplicateNodes) + resultIsSorted = false; + + // This is a simplified check that can be improved to handle more cases. + if (nodes.subtreesAreDisjoint() && (step->axis() == Step::ChildAxis || step->axis() == Step::SelfAxis)) + newNodes.markSubtreesDisjoint(true); + for (unsigned j = 0; j < nodes.size(); j++) { NodeSet matches; step->evaluate(nodes[j], matches); - + + if (!matches.isSorted()) + resultIsSorted = false; + for (size_t nodeIndex = 0; nodeIndex < matches.size(); ++nodeIndex) { Node* node = matches[nodeIndex]; - if (newNodesSet.add(node).second) + if (!needToCheckForDuplicateNodes || newNodesSet.add(node).second) newNodes.append(node); } } @@ -130,53 +145,46 @@ void LocationPath::evaluate(NodeSet& nodes) const nodes.swap(newNodes); } - nodes.markSorted(false); + nodes.markSorted(resultIsSorted); } -void LocationPath::optimizeStepPair(unsigned index) +void LocationPath::appendStep(Step* step) { - Step* first = m_steps[index]; - - if (first->axis() == Step::DescendantOrSelfAxis - && first->nodeTest().kind() == Step::NodeTest::AnyNodeTest - && first->predicates().size() == 0) { - - Step* second = m_steps[index + 1]; - if (second->axis() == Step::ChildAxis - && second->nodeTest().namespaceURI().isEmpty() - && second->nodeTest().kind() == Step::NodeTest::NameTest - && second->nodeTest().data() == "*") { - - // Optimize the common case of "//*" AKA descendant-or-self::node()/child::*. - first->setAxis(Step::DescendantAxis); - second->setAxis(Step::SelfAxis); - second->setNodeTest(Step::NodeTest::ElementNodeTest); - ASSERT(second->nodeTest().data().isEmpty()); + unsigned stepCount = m_steps.size(); + if (stepCount) { + bool dropSecondStep; + optimizeStepPair(m_steps[stepCount - 1], step, dropSecondStep); + if (dropSecondStep) { + delete step; + return; } } -} - -void LocationPath::appendStep(Step* step) -{ + step->optimize(); m_steps.append(step); - - unsigned stepCount = m_steps.size(); - if (stepCount > 1) - optimizeStepPair(stepCount - 2); } void LocationPath::insertFirstStep(Step* step) { + if (m_steps.size()) { + bool dropSecondStep; + optimizeStepPair(step, m_steps[0], dropSecondStep); + if (dropSecondStep) { + delete m_steps[0]; + m_steps[0] = step; + return; + } + } + step->optimize(); m_steps.insert(0, step); - - if (m_steps.size() > 1) - optimizeStepPair(0); } Path::Path(Filter* filter, LocationPath* path) - : m_filter(filter), - m_path(path) + : m_filter(filter) + , m_path(path) { + setIsContextNodeSensitive(filter->isContextNodeSensitive()); + setIsContextPositionSensitive(filter->isContextPositionSensitive()); + setIsContextSizeSensitive(filter->isContextSizeSensitive()); } Path::~Path() |