dbertoni    01/11/07 19:44:57

  Modified:    c/src/XPath XPath.cpp
  Log:
  Optimize predicates with numeric literals.
  
  Revision  Changes    Path
  1.65      +86 -30    xml-xalan/c/src/XPath/XPath.cpp
  
  Index: XPath.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xalan/c/src/XPath/XPath.cpp,v
  retrieving revision 1.64
  retrieving revision 1.65
  diff -u -r1.64 -r1.65
  --- XPath.cpp 2001/11/01 15:57:13     1.64
  +++ XPath.cpp 2001/11/08 03:44:57     1.65
  @@ -1609,18 +1609,27 @@
   
                        while(XPathExpression::eOP_PREDICATE == nextStepType)
                        {
  -                             const XObjectPtr                
pred(predicate(context, opPos, executionContext));
  -                             assert(pred.get() != 0);
  -
  -                             if(XObject::eTypeNumber == pred->getType())
  +                             // This is a quick hack to look ahead and see 
if we have
  +                             // number literal as the predicate, i.e. 
match="foo[1]".
  +                             if (m_expression.getOpCodeMapValue(opPos + 2) 
== XPathExpression::eOP_NUMBERLIT)
                                {
                                        score = 
handleFoundIndex(executionContext, context, startOpPos);
                                }
  -                             else if(pred->boolean() == false)
  +                             else
                                {
  -                                     score = eMatchScoreNone;
  +                                     const XObjectPtr        
pred(predicate(context, opPos, executionContext));
  +                                     assert(pred.get() != 0);
   
  -                                     break;
  +                                     if(XObject::eTypeNumber == 
pred->getType())
  +                                     {
  +                                             score = 
handleFoundIndex(executionContext, context, startOpPos);
  +                                     }
  +                                     else if(pred->boolean() == false)
  +                                     {
  +                                             score = eMatchScoreNone;
  +
  +                                             break;
  +                                     }
                                }
   
                                opPos = 
currentExpression.getNextOpCodePosition(opPos);
  @@ -2877,33 +2886,84 @@
   
        while(XPathExpression::eOP_PREDICATE == nextStepType)
        {
  -             NodeRefListBase::size_type                      i = 0;
  -
                const NodeRefListBase::size_type        theLength = 
subQueryResults.getLength();
   
  -             while(i < theLength)
  -             {
  -                     XalanNode* const        theNode = 
subQueryResults.item(i);
  -                     assert(theNode != 0);
  +             // If we have no nodes left, then there's no point in executing 
any
  +             // predicates.  However, we will continue to loop, since we 
need to
  +             // update endPredicatePos.
  +             if (theLength > 0)
  +             {
  +                     const int predOpPos = opPos + 2;
  +
  +                     // OK, this is a huge hack/optimization.  If the 
predicate is
  +                     // simple a number, such as [2], we can just get the
  +                     // numeric value from the expression, and not bother 
executing
  +                     // the predicate.  Furthermore, we don't need to 
execute the
  +                     // predicate for each node, since the evaluation is no 
dependent
  +                     // on the context node.  All we really have to do is 
remove all
  +                     // nodes from subQueryResults, _except_ for the node at 
that
  +                     // position.  The only trick is that XPath indexes from 
1, while
  +                     // our node lists index from 0.
  +                     if (m_expression.getOpCodeMapValue(predOpPos) == 
XPathExpression::eOP_NUMBERLIT)
  +                     {
  +                             assert(m_expression.m_tokenQueue.size() > 
unsigned(m_expression.m_opMap[predOpPos + 3]));
  +
  +                             // Get the value of the number...
  +                             const double    theIndex =
  +                                     
m_expression.getNumberLiteral(m_expression.getOpCodeMapValue(predOpPos + 2));
  +
  +                             // If the index is out of range, or not an 
integer, just clear subQueryResults...
  +                             if (theIndex <= 0.0 ||
  +                                     NodeRefListBase::size_type(theIndex) > 
theLength ||
  +                                     
double(NodeRefListBase::size_type(theIndex)) != theIndex)
  +                             {
  +                                     subQueryResults.clear();
  +                             }
  +                             else if (theLength > 1)
  +                             {
  +                                     // Save the matching node...
  +                                     XalanNode* const        theNode =
  +                                             
subQueryResults.item(NodeRefListBase::size_type(theIndex) - 1);
   
  -                     const XObjectPtr                pred(predicate(theNode, 
opPos, executionContext));
  -                     assert(pred.get() != 0);
  +                                     // Clear the list...
  +                                     subQueryResults.clear();
   
  -                     // Remove any node that doesn't satisfy the predicate.
  -                     if((XObject::eTypeNumber == pred->getType() && i + 1 != 
pred->num()) ||
  -                        pred->boolean() == false)
  -                     {
  -                             // Set the node to 0.  After we're done,
  -                             // we'll clear it out.
  -                             subQueryResults.setNode(i, 0);
  +                                     // Add the node back in...
  +                                     subQueryResults.addNode(theNode);
  +                             }
  +                             else
  +                             {
  +                                     // OK, if there's only 1 node in the 
list, then
  +                                     // we don't need to bother modifying 
the list.
  +                                     // Just assert that theIndex == 1.0...
  +                                     assert(theIndex == 1.0);
  +                             }
                        }
  +                     else
  +                     {
  +                             for(NodeRefListBase::size_type i = 0; i < 
theLength; ++i)
  +                             {
  +                                     XalanNode* const        theNode = 
subQueryResults.item(i);
  +                                     assert(theNode != 0);
   
  -                     ++i;
  -             }
  +                                     const XObjectPtr                
pred(predicate(theNode, opPos, executionContext));
  +                                     assert(pred.get() != 0);
   
  -             // Clear out any null entries...
  -             subQueryResults.clearNulls();
  +                                     // Remove any node that doesn't satisfy 
the predicate.
  +                                     if((XObject::eTypeNumber == 
pred->getType() && i + 1 != pred->num()) ||
  +                                        pred->boolean() == false)
  +                                     {
  +                                             // Set the node to 0.  After 
we're done,
  +                                             // we'll clear it out.
  +                                             subQueryResults.setNode(i, 0);
  +                                     }
  +                             }
   
  +                             // Clear out any null entries...
  +                             subQueryResults.clearNulls();
  +                     }
  +             }
  +
                opPos = currentExpression.getNextOpCodePosition(opPos);
   
                nextStepType = currentExpression.getOpCodeMapValue(opPos);
  @@ -2911,10 +2971,6 @@
                if(XPathExpression::eOP_PREDICATE == nextStepType)
                {
                        executionContext.setContextNodeList(subQueryResults);
  -
  -                     // Don't break, loop 'till end so that opPos will be 
set to end.
  -                     // if(0 == subQueryResults.getLength())
  -                     //      break;
                }
        }
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to