jdonohue    00/04/19 08:59:27

  Modified:    c/src/XSLT ElemNumber.cpp ElemNumber.hpp
  Log:
  Replaced with version derived from newer java source
  
  Revision  Changes    Path
  1.10      +485 -333  xml-xalan/c/src/XSLT/ElemNumber.cpp
  
  Index: ElemNumber.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xalan/c/src/XSLT/ElemNumber.cpp,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- ElemNumber.cpp    2000/04/12 19:40:59     1.9
  +++ ElemNumber.cpp    2000/04/19 15:59:25     1.10
  @@ -69,6 +69,7 @@
   #include <PlatformSupport/DOMStringHelper.hpp>
   #include <PlatformSupport/NumberFormat.hpp>
   
  +#include <DOMSupport/DOMServices.hpp>
   
   
   #include <XPath/XPath.hpp>
  @@ -85,6 +86,7 @@
   #endif
   
   
  +
   const XalanDOMString 
ElemNumber::s_alphaCountTable(XALAN_STATIC_UCODE_STRING("ZABCDEFGHIJKLMNOPQRSTUVWXY"));
   
   
  @@ -119,11 +121,11 @@
        m_fromMatchPattern(0),
        m_valueExpr(0),
        m_level(Constants::NUMBERLEVEL_SINGLE),
  -     m_format_avt(),
  -     m_lang_avt(),  
  -     m_lettervalue_avt(),
  -     m_groupingSeparator_avt(),
  -     m_groupingSize_avt()
  +     m_format_avt(0),
  +     m_lang_avt(0),
  +     m_lettervalue_avt(0),
  +     m_groupingSeparator_avt(0),
  +     m_groupingSize_avt(0)
        
   {
        const unsigned int      nAttrs = atts.getLength();
  @@ -159,25 +161,31 @@
                }
                else if(equals(aname, Constants::ATTRNAME_FORMAT))
                {
  -                     m_format_avt = atts.getValue(i);
  +                     m_format_avt = new AVT(aname, atts.getType(i),
  +                                             atts.getValue(i), *this, 
constructionContext);
  +
                }
                else if(equals(aname, Constants::ATTRNAME_LANG))
                {
  -                     m_lang_avt = atts.getValue(i);
  +                     m_lang_avt = new AVT(aname, atts.getType(i),
  +                                             atts.getValue(i), *this, 
constructionContext);
                }
                else if(equals(aname, Constants::ATTRNAME_LETTERVALUE))
                {
                        
constructionContext.warn(Constants::ATTRNAME_LETTERVALUE + " not supported 
yet!");
   
  -                     m_lettervalue_avt = atts.getValue(i);
  +                     m_lettervalue_avt = new AVT(aname, atts.getType(i),
  +                                             atts.getValue(i), *this, 
constructionContext);
                } 
                else if(equals(aname,Constants::ATTRNAME_GROUPINGSEPARATOR))
                {
  -                     m_groupingSeparator_avt = atts.getValue(i);
  +                     m_groupingSeparator_avt = new AVT(aname, 
atts.getType(i),
  +                                             atts.getValue(i), *this, 
constructionContext);
                }
                else if(equals(aname,Constants::ATTRNAME_GROUPINGSIZE))
                {
  -                     m_groupingSize_avt = atts.getValue(i);
  +                     m_groupingSize_avt = new AVT(aname, atts.getType(i),
  +                                             atts.getValue(i), *this, 
constructionContext);
                }
                else if(!isAttrOK(aname, atts, i, constructionContext))
                {
  @@ -186,6 +194,15 @@
        }
   }
   
  +     
  +ElemNumber::~ElemNumber()
  +{
  +     delete  m_format_avt;
  +     delete  m_lang_avt;
  +     delete  m_lettervalue_avt;
  +     delete  m_groupingSeparator_avt;
  +     delete  m_groupingSize_avt;
  +}
   
   
   void
  @@ -207,25 +224,21 @@
   }
   
   
  -
  -
   XalanNode*
   ElemNumber::findAncestor(
                        StylesheetExecutionContext&             
executionContext,
                        const XPath*                                    
fromMatchPattern,
                        const XPath*                                    
countMatchPattern,
  -                     XalanNode*                                              
context,
  +                     const XalanNode* const                  context,
                        const XalanElement*                             /* 
namespaceContext */) const
   {
  -     XalanNode*      contextCopy = context;
  -
  +     XalanNode*      contextCopy = const_cast<XalanNode*>(context);
        while(contextCopy != 0)
        {
                if(0 != fromMatchPattern)
                {
  -                     if(fromMatchPattern->getMatchScore(contextCopy,
  -                                                                             
           *this,
  -                                                                             
           executionContext.getXPathExecutionContext()) !=
  +                     if(fromMatchPattern->getMatchScore(contextCopy, *this,
  +                                             
executionContext.getXPathExecutionContext()) !=
                                                        XPath::s_MatchScoreNone)
                        {
                                break;
  @@ -234,9 +247,8 @@
                
                if(0 != countMatchPattern)
                {
  -                     if(countMatchPattern->getMatchScore(context,
  -                                                                             
            *this,
  -                                                                             
                executionContext.getXPathExecutionContext()) !=
  +                     if(countMatchPattern->getMatchScore(contextCopy, *this,
  +                                             
executionContext.getXPathExecutionContext()) !=
                                                        XPath::s_MatchScoreNone)
                        {
                                break;
  @@ -245,7 +257,6 @@
                
                contextCopy = executionContext.getParentOfNode(*contextCopy);
        }
  -
        return contextCopy;
   }                                    
   
  @@ -253,21 +264,20 @@
   
   XalanNode*
   ElemNumber::findPrecedingOrAncestorOrSelf(
  -                     StylesheetExecutionContext&             
executionContext,
  -                     const XPath*                                    
fromMatchPattern,
  -                     const XPath*                                    
countMatchPattern,
  -                     XalanNode*                                              
context,
  +                     StylesheetExecutionContext&     executionContext,
  +                     const XPath*                                            
fromMatchPattern,
  +                     const XPath*                                            
countMatchPattern,
  +                     const XalanNode* const                  context,
                        const XalanElement*                             /* 
namespaceContext */) const
   {  
  -     XalanNode*      contextCopy = context;
  -
  +     XalanNode*      contextCopy = const_cast<XalanNode*>(context);
        while(contextCopy != 0)
        {
                if(0 != fromMatchPattern)
                {
  -                     if(fromMatchPattern->getMatchScore(contextCopy,
  -                                             *this,
  -                                             
executionContext.getXPathExecutionContext()) != XPath::s_MatchScoreNone)
  +                     if(fromMatchPattern->getMatchScore(contextCopy, *this,
  +                                             
executionContext.getXPathExecutionContext()) !=
  +                                                     XPath::s_MatchScoreNone)
                        {
                                contextCopy = 0;
                                break;
  @@ -276,26 +286,26 @@
                
                if(0 != countMatchPattern)
                {
  -                     if(countMatchPattern->getMatchScore(contextCopy,
  -                                                                             
            *this,
  -                                                                             
            executionContext.getXPathExecutionContext()) != 
XPath::s_MatchScoreNone)
  +                     if(countMatchPattern->getMatchScore(contextCopy, *this,
  +                                             
executionContext.getXPathExecutionContext()) !=
  +                                                     XPath::s_MatchScoreNone)
                        {
                                break;
                        }
                }
  -
                XalanNode* const        prevSibling = 
contextCopy->getPreviousSibling();
  -
                if(prevSibling == 0)
                {
                        contextCopy = 
executionContext.getParentOfNode(*contextCopy);
                }
                else
                {
  -                     contextCopy = prevSibling;
  +                     // Now go down the chain of children of this sibling 
  +                     contextCopy = prevSibling->getLastChild();
  +                     if (contextCopy == 0)
  +                             contextCopy = prevSibling;
                }
        }
  -
        return contextCopy;
   }
   
  @@ -304,53 +314,51 @@
   const XPath*
   ElemNumber::getCountMatchPattern(
                        StylesheetExecutionContext&             
executionContext,
  -                     XalanNode*                                              
contextNode) const
  +                     const XalanNode* const                          
contextNode) const
   {
        const XPath*    countMatchPattern = m_countMatchPattern;
  -
        if(0 == countMatchPattern)
        {
                switch(contextNode->getNodeType())
                {
                case XalanNode::ELEMENT_NODE:
  -                     countMatchPattern = 
executionContext.createMatchPattern(contextNode->getNodeName(),
  -                             *this);
  +                     countMatchPattern =
  +                             
executionContext.createMatchPattern(contextNode->getNodeName(), *this);
                        break;
   
                case XalanNode::ATTRIBUTE_NODE:
  -                     countMatchPattern = 
executionContext.createMatchPattern(XalanDOMString(XALAN_STATIC_UCODE_STRING("@"))
 +
  -                                                                             
                                                        
contextNode->getNodeName(),
  -                             *this);
  +                     countMatchPattern = executionContext.createMatchPattern(
  +                                             
XalanDOMString(XALAN_STATIC_UCODE_STRING("@")) + contextNode->getNodeName(),
  +                                             *this);
                        break;
   
                case XalanNode::CDATA_SECTION_NODE:
                case XalanNode::TEXT_NODE:
  -                     countMatchPattern = 
executionContext.createMatchPattern(XalanDOMString(XALAN_STATIC_UCODE_STRING("text()")),
  -                             *this);
  +                     countMatchPattern = executionContext.createMatchPattern(
  +                                     
XalanDOMString(XALAN_STATIC_UCODE_STRING("text()")), *this);
                        break;
   
                case XalanNode::COMMENT_NODE:
  -                     countMatchPattern = 
executionContext.createMatchPattern(XalanDOMString(XALAN_STATIC_UCODE_STRING("comment()")),
  -                             *this);
  +                     countMatchPattern = executionContext.createMatchPattern(
  +                                     
XalanDOMString(XALAN_STATIC_UCODE_STRING("comment()")), *this);
                        break;
   
                case XalanNode::DOCUMENT_NODE:
  -                     countMatchPattern = 
executionContext.createMatchPattern(XalanDOMString(XALAN_STATIC_UCODE_STRING("/")),
  -                             *this);
  +                     countMatchPattern = executionContext.createMatchPattern(
  +                                     
XalanDOMString(XALAN_STATIC_UCODE_STRING("/")), *this);
                        break;
   
                case XalanNode::PROCESSING_INSTRUCTION_NODE:
  -                     countMatchPattern = 
executionContext.createMatchPattern(XalanDOMString(XALAN_STATIC_UCODE_STRING("pi("))
 + 
  -                             contextNode->getNodeName() + 
XalanDOMString(XALAN_STATIC_UCODE_STRING(")")),
  -                             *this);
  +                     countMatchPattern = executionContext.createMatchPattern(
  +                             
XalanDOMString(XALAN_STATIC_UCODE_STRING("pi(")) + 
  +                             contextNode->getNodeName() +
  +                             XalanDOMString(XALAN_STATIC_UCODE_STRING(")")), 
*this);
                        break;
   
                default:
  -                     assert(false);
                        break;
                }
        }
  -
        return countMatchPattern;
   }
   
  @@ -359,14 +367,13 @@
   XalanDOMString
   ElemNumber::getCountString(
                        StylesheetExecutionContext&             
executionContext,
  -                     XalanNode*                                              
/* sourceTree */, 
  -                     XalanNode*                                              
sourceNode) const
  +                     XalanNode* const                                        
/* sourceTree */, 
  +                     XalanNode* const                                        
sourceNode) const
   {
        assert(sourceNode != 0);
        IntArrayType    numberList;
  +     CountersTable ctable;
   
  -     IntArrayType    list;
  -
        if(0 != m_valueExpr)
        {
                const XObject* const    countObj =
  @@ -378,279 +385,179 @@
        }
        else
        {
  -             const XPath* const      countMatchPattern =
  -                     getCountMatchPattern(executionContext, sourceNode);
  -
  -             if((Constants::NUMBERLEVEL_ANY == m_level) || 
  -                     (Constants::NUMBERLEVEL_SINGLE == m_level))
  +             if(Constants::NUMBERLEVEL_ANY == m_level)
                {
  -                     int numberFound;
  -                     if(Constants::NUMBERLEVEL_SINGLE == m_level)
  -                     {
  -                             XalanNode*      target =
  -                                     findAncestor(executionContext,
  -                                                              
m_fromMatchPattern, 
  -                                                              
countMatchPattern,
  -                                                              sourceNode,
  -                                                              this);
  -
  -                             if(target == 0) 
  -                                     target = 
executionContext.getParentOfNode(*sourceNode);
  -
  -                             if(target != 0)
  -                             {
  -                                     numberFound = 
getSiblingNumber(executionContext, countMatchPattern, target);
  -                                     if (numberFound > 0)
  -                                             
numberList.push_back(numberFound);
  -                             }
  -                             else
  -                             {
  -                                     
executionContext.warn(XalanDOMString("Warning: count attribute does not match 
an ancestor in xsl:number! Target = ") 
  -                                                                             
                        + sourceNode->getNodeName(),
  -                                                                             
  sourceNode,
  -                                                                             
  0);
  -                             }
  -                     }
  -                     else // if NUMBERLEVEL_ANY
  +                     numberList.push_back(ctable.countNode(executionContext, 
  +                     const_cast<ElemNumber* const>(this), sourceNode));
  +             }
  +             else
  +             {
  +                     MutableNodeRefList ancestors = 
getMatchingAncestors(executionContext, sourceNode,
  +                                     Constants.NUMBERLEVEL_SINGLE == 
m_level);
  +                     int lastIndex = ancestors.getLength();
  +                     if(lastIndex > 0)
                        {
  -                             XalanNode*      from = 0;
  -
  -                             if(0 != m_fromMatchPattern)
  +                     /*
  +                             numberList.reserve(lastIndex+1);
  +                             for(int i = lastIndex; i >= 0; i--)
                                {
  -                                     from = 
findPrecedingOrAncestorOrSelf(executionContext, m_fromMatchPattern, 
countMatchPattern,
  -                                             sourceNode, this);
  -
  -                                     if(from == 0)
  -                                     {
  -                                             from = sourceNode;
  -                                     }
  +                                     const XalanNode* target = 
ancestors.item(i);
  +                                     numberList[lastIndex-i] = 
ctable.countNode(executionContext,
  +                                                     const_cast<ElemNumber* 
const>(this), target);
                                }
  -                             else
  +                     */
  +                             for(int i = 0; i < lastIndex; i++)
                                {
  -                                     from = sourceNode->getOwnerDocument();
  +                                     const XalanNode* target = 
ancestors.item(lastIndex - i -1);
  +                                     
numberList.push_back(ctable.countNode(executionContext,
  +                                                     const_cast<ElemNumber* 
const>(this), target));
                                }
  -
  -                             XalanNode* const        fromPos = (from != 
sourceNode) ? getNextInTree(from, from) : from;
  -
  -                             numberFound = 
getNumberInTree(executionContext.getXPathExecutionContext(),
  -                                             countMatchPattern, fromPos, 
from, sourceNode, 0);
  -                             if (numberFound > 0)
  -                                     numberList.push_back(numberFound);
                        }
                }
  -             else // if NUMBERLEVEL_MULTI
  -             {
  -                      numberList = getAncestorNumbers(executionContext, 
m_fromMatchPattern,
  -                             countMatchPattern, sourceNode);
  -             }
        }
  -
        return numberList.size() > 0 ? formatNumberList(executionContext, 
numberList, sourceNode) : XalanDOMString();
   }
   
  -
  -
   XalanNode*
  -ElemNumber::getNextInTree(
  -                     XalanNode*      pos,
  -                     XalanNode*      from)
  -{
  -     assert(pos != 0);
  -     assert(from != 0);
  -
  -     XalanNode*      posCopy = pos;
  -
  -     XalanNode*      nextNode = posCopy->getFirstChild();
  -
  -     while(nextNode == 0)
  -     {
  -             nextNode = posCopy->getNextSibling();
  -
  -             if(nextNode == 0)
  -             {
  -                     posCopy = posCopy->getParentNode();
  +ElemNumber::getPreviousNode(
  +             StylesheetExecutionContext&             executionContext,
  +             XalanNode* pos)
  +{    
  +     const XPath* countMatchPattern = getCountMatchPattern(executionContext, 
pos);
  +     if(Constants::NUMBERLEVEL_ANY == m_level)
  +     {
  +             const XPath* fromMatchPattern = m_fromMatchPattern;
  +
  +             // Do a backwards document-order walk 'till a node is found 
that matches 
  +             // the 'from' pattern, or a node is found that matches the 
'count' pattern, 
  +             // or the top of the tree is found.
  +             while(0 != pos)
  +             {            
  +                     // Get the previous sibling, if there is no previous 
sibling, 
  +                     // then count the parent, but if there is a previous 
sibling, 
  +                     // dive down to the lowest right-hand (last) child of 
that sibling.
  +                     XalanNode* next = pos->getPreviousSibling();
  +                     if(0 == next)
  +                     {
  +                             next = pos->getParentNode();
  +                             if((0 != next) && ((((0 != fromMatchPattern) &&
  +                                             
(fromMatchPattern->getMatchScore(next, *this,
  +                                             
executionContext.getXPathExecutionContext()) !=
  +                                                                      
XPath::s_MatchScoreNone))) || 
  +                                                     (next->getNodeType() == 
XalanNode::DOCUMENT_NODE)))
  +                             {
  +                                     pos = 0; // return 0 from function.
  +                                     break; // from while loop
  +                             }
  +                     }
  +                     else
  +                     {
  +                             // dive down to the lowest right child.
  +                             XalanNode* child = next;
  +                             while(0 != child)
  +                             {
  +                                     child = next->getLastChild();
  +                                     if(0 != child)
  +                                             next = child;
  +                             }
  +                     }
  +                     pos = next;
   
  -                     if(posCopy == from)
  +                     if((0 != pos) && ((0 == countMatchPattern) ||
  +                                             
(countMatchPattern->getMatchScore(pos, *this,
  +                                             
executionContext.getXPathExecutionContext()) !=
  +                                              XPath::s_MatchScoreNone)))
                        {
                                break;
                        }
                }
        }
  -
  -     return nextNode;
  -}
  -
  -
  -
  -unsigned int
  -ElemNumber::getNumberInTree( 
  -                     XPathExecutionContext&  executionContext,
  -                     const XPath*                    countMatchPattern, 
  -                     XalanNode*                              pos, 
  -                     XalanNode*                              from, 
  -                     XalanNode*                              target,
  -                     int                                             
countFrom) const
  -{
  -     XalanNode*      posCopy = pos;
  -
  -     int                     count = countFrom;
  -
  -     if(posCopy != 0)
  +     else // NUMBERLEVEL_MULTI or NUMBERLEVEL_SINGLE
        {
  -             do
  -             {          
  -                     if( (0 == countMatchPattern) || 
  -                             (countMatchPattern->getMatchScore(posCopy,
  -                                                                             
                  *this,
  -                                                                             
                  executionContext) != XPath::s_MatchScoreNone))
  +             while(0 != pos)
  +             {            
  +                     pos = pos->getPreviousSibling();
  +                     if((0 != pos) && ((0 == countMatchPattern) ||
  +                                             
(countMatchPattern->getMatchScore(pos, *this,
  +                                             
executionContext.getXPathExecutionContext()) !=
  +                                              XPath::s_MatchScoreNone)))
                        {
  -                             count++;
  +                             break;
                        }
                }
  -
  -             while(posCopy != target && 
  -                             (posCopy = getNextInTree(posCopy, from)) != 0);
        }
  -
  -     return count;
  +     return pos;
   }
   
  -
   
  -unsigned int
  -ElemNumber::getSiblingNumber(
  -                     StylesheetExecutionContext&             
executionContext,
  -                     const XPath*                                    
countMatchPattern, 
  -                     XalanNode*                                              
target) const
  +XalanNode*
  +ElemNumber::getTargetNode(
  +             StylesheetExecutionContext& executionContext,
  +             const XalanNode* const sourceNode)
   {
  -     assert(target != 0);
  -
  -     int number = 0;
  -
  -     const XalanNode* const  theParent = 
executionContext.getParentOfNode(*target);
  -     assert(theParent != 0);
  -
  -     // TODO: If target is an Attr, implement special handling. 
  -     XalanNode*              child = theParent->getFirstChild();
  -
  -     while(child != 0)
  +     XalanNode* target = 0;
  +     const XPath* countMatchPattern =
  +             getCountMatchPattern(executionContext, sourceNode);
  +     if(Constants::NUMBERLEVEL_ANY == m_level)
        {
  -             if(child == target)
  -             {
  -                     number++; // always count the target
  -                     break;
  -             }
  -             else if(0 == countMatchPattern || 
  -                             countMatchPattern->getMatchScore(child,
  -                                                                             
                 *this,
  -                                                                             
                 executionContext.getXPathExecutionContext()) != 
XPath::s_MatchScoreNone)
  -             {
  -                     number++;
  -             }
  -
  -             child = child->getNextSibling();
  +             target = findPrecedingOrAncestorOrSelf(executionContext,
  +                             m_fromMatchPattern, countMatchPattern, 
sourceNode, this);
        }
  -
  -     return number;
  -}
  -
  -
  -
  -unsigned int
  -ElemNumber::countMatchingAncestors(
  -                     StylesheetExecutionContext&             
executionContext,
  -                     const XPath*                                    
patterns,
  -                     XalanNode*                                              
node) const
  -{
  -     int                     count = 0;
  -
  -     XalanNode*      nodeCopy = node;
  -
  -     while(nodeCopy != 0)
  +     else
        {
  -             if(0 != patterns)
  -             {
  -                     if(patterns->getMatchScore(nodeCopy,
  -                                                                        
*this,
  -                                                                        
executionContext.getXPathExecutionContext()) != XPath::s_MatchScoreNone)
  -                     {
  -                             count++;
  -                     }  
  -             }
  -             else
  -             {
  -                     count++;
  -             }
  -
  -             nodeCopy = executionContext.getParentOfNode(*nodeCopy);
  +             target = findAncestor(executionContext, m_fromMatchPattern,
  +                             countMatchPattern, sourceNode, this);
        }
  -
  -     return count;
  +     return target;
   }
   
  -
   
  -ElemNumber::IntArrayType
  -ElemNumber::getAncestorNumbers(
  -                     StylesheetExecutionContext&             
executionContext,
  -                     const XPath*                                    
fromMatchPattern,
  -                     const XPath*                                    
countMatchPattern, 
  -                     XalanNode*                                              
node) const
  +/**
  + * Get the ancestors, up to the root, that match the
  + * pattern.
  + * @param patterns if non-0, count only nodes
  + * that match this pattern, if 0 count all ancestors.
  + * @param node Count this node and it's ancestors.
  + * @return The number of ancestors that match the pattern.
  + */
  +MutableNodeRefList
  +ElemNumber::getMatchingAncestors(
  +             StylesheetExecutionContext&             executionContext,
  +             XalanNode* node, 
  +             bool stopAtFirstFound) const
   {
  -     XalanNode*                      nodeCopy = node;
  -
  -     const unsigned int      nMatchingAncestors =
  -                             countMatchingAncestors(executionContext,
  -                                                                        
countMatchPattern,
  -                                                                        
nodeCopy);
  +     MutableNodeRefList ancestors;
  +     const XPath* countMatchPattern = getCountMatchPattern(executionContext, 
node);
  +     while( 0 != node )
  +     {
  +             if((0 != m_fromMatchPattern) &&
  +                             (m_fromMatchPattern->getMatchScore(node, *this, 
executionContext.getXPathExecutionContext()) !=
  +                              XPath::s_MatchScoreNone))
  +             { 
  +                     // The following if statement gives level="single" 
different 
  +                     // behavior from level="multiple", which seems 
incorrect according 
  +                     // to the XSLT spec.  For now we are leaving this in to 
replicate 
  +                     // the same behavior in XT, but, for all intents and 
purposes we 
  +                     // think this is a bug, or there is something about 
level="single" 
  +                     // that we still don't understand.
  +                     if(!stopAtFirstFound)
  +                             break;
  +             }  
   
  -     IntArrayType    counts(nMatchingAncestors);
  +             if(0 == countMatchPattern)
  +                     error(XalanDOMString("Programmers error! 
countMatchPattern should never be 0!"));
   
  -     if(nMatchingAncestors > 0)
  -     {
  -             int             countIndex = counts.size() - 1; // position to 
put count into
  -
  -             while(nodeCopy != 0)
  +             if(countMatchPattern->getMatchScore(node, *this, 
executionContext.getXPathExecutionContext()) !=
  +                             XPath::s_MatchScoreNone)
                {
  -                     bool    countIt = false;
  -
  -                     if(0 != countMatchPattern)
  -                     {
  -                             if(countMatchPattern->getMatchScore(nodeCopy,
  -                                                                             
                        *this,
  -                                                                             
                        executionContext.getXPathExecutionContext()) != 
XPath::s_MatchScoreNone)
  -                             {
  -                                     countIt = true;
  -                             } 
  -                     }
  -                     else
  -                     {
  -                             countIt = true;
  -                     }
  -
  -                     if(countIt == true)
  -                     {
  -                             XalanNode*      target =
  -                                             findAncestor(executionContext,
  -                                                                      
fromMatchPattern,
  -                                                                      
countMatchPattern,
  -                                                                      
nodeCopy,
  -                                                                      this);
  -
  -                             if(target == 0)
  -                                     target = nodeCopy;
  -
  -                             counts[countIndex] = 
getSiblingNumber(executionContext, countMatchPattern, target);
  -                             countIndex--;
  -                     }
  -
  -                     nodeCopy = executionContext.getParentOfNode(*nodeCopy);
  -             } // end while
  -     } // end if nMatchingAncestors > 0
  -
  -     return counts;
  -}
  -
  +                     ancestors.addNode(node);
  +                     if(stopAtFirstFound)
  +                             break;
  +             }
  +             node = executionContext.getParentOfNode(*node);
  +     }
  +     return ancestors;
  +} // end getMatchingAncestors method
   
   
   #if ! defined(__GNUC__)
  @@ -679,31 +586,31 @@
       // Helper to format local specific numbers to strings.
        std::auto_ptr<NumberFormat>             formatter(new NumberFormat);
   
  -     const XalanDOMString    digitGroupSepValue = 
(!isEmpty(m_groupingSeparator_avt))
  -                                  ?  
executionContext.evaluateAttrVal(contextNode,
  -                                                                             
                                                          *this,
  -                                                                             
                                                          
m_groupingSeparator_avt) :
  -                                                                      
XalanDOMString();
  -
  -    const XalanDOMString     nDigitsPerGroupValue = 
(!isEmpty(m_groupingSize_avt))
  -                                  ?  
executionContext.evaluateAttrVal(contextNode,
  -                                                                             
                                                          *this, 
  -                                                                             
                                                          m_groupingSize_avt) :
  -                                                                      
XalanDOMString();
  +     XalanDOMString  digitGroupSepValue;
  +     if (0 != m_groupingSeparator_avt)
  +              m_groupingSeparator_avt->evaluate(digitGroupSepValue, 
contextNode,
  +                              *this, 
executionContext.getXPathExecutionContext());
  +                                                                      
  +     XalanDOMString  nDigitsPerGroupValue;
  +     if (0 != m_groupingSize_avt)
  +             m_groupingSize_avt->evaluate(nDigitsPerGroupValue, contextNode, 
*this,
  +                             executionContext.getXPathExecutionContext());
   
       // TODO: Handle digit-group attributes
  -    if(!isEmpty(digitGroupSepValue) || !isEmpty(nDigitsPerGroupValue))
  -    {
  +     // 7.7.1 If one is empty, it is ignored (numb81 conf test)
  +     if(!isEmpty(digitGroupSepValue) && !isEmpty(nDigitsPerGroupValue))
  +     {
                formatter->setGroupingUsed(true);
  -             formatter->setGroupingSeparator(m_groupingSeparator_avt);
  -             formatter->setGroupingSize(m_groupingSize_avt);
  -    }
  -    
  -    return formatter.release();
  -}
  +             formatter->setGroupingSeparator(digitGroupSepValue);
  +             formatter->setGroupingSize(nDigitsPerGroupValue);
  +     }
   
  +     return formatter.release();
  +}
   
   
  +//@@ JMD: this is different from the java version, but seems to work, so I'll
  +//leave it alone
   XalanDOMString
   ElemNumber::formatNumberList(
                        StylesheetExecutionContext&             
executionContext,
  @@ -723,16 +630,14 @@
        if (nNumbers == 0) return formattedNumber;
        if (contextNode == 0) return formattedNumber;
   
  -     XalanDOMString  formatValue = !isEmpty(m_format_avt)
  -             ? executionContext.evaluateAttrVal(contextNode,
  -                                                                             
   *this,
  -                                                                             
   m_format_avt)
  -             : XalanDOMString();
  +     XalanDOMString  formatValue;
  +     if (m_format_avt != 0)
  +              m_format_avt->evaluate(formatValue, contextNode, *this, 
executionContext.getXPathExecutionContext());
   
        if(isEmpty(formatValue)) 
                formatValue = XALAN_STATIC_UCODE_STRING("1");
   
  -     NumeratorFormatter::NumberFormatStringTokenizer         
formatTokenizer(formatValue);
  +     NumberFormatStringTokenizer             formatTokenizer(formatValue);
   
   #if ! defined(__GNUC__)
        std::locale             loc = getLocale(executionContext, contextNode);
  @@ -806,10 +711,14 @@
                        int                                                     
        listElement) const
   {
   
  -     std::auto_ptr<NumberFormat> 
formatter(getNumberFormatter(executionContext, contextNode));
  +     std::auto_ptr<NumberFormat> formatter(
  +                     getNumberFormatter(executionContext, contextNode));
   
        XalanDOMString  padString = formatter->format(0);
  -     XalanDOMString  lookahead;
  +     XalanDOMString letterVal;
  +     if (m_lettervalue_avt != 0)
  +             m_lettervalue_avt->evaluate(letterVal, contextNode, *this,
  +                             executionContext.getXPathExecutionContext());
   
        XalanDOMString  formattedNumber;
   
  @@ -827,7 +736,18 @@
                case 'i':
                        formattedNumber += toLowerCase(long2roman(listElement, 
true));
                        break;
  -
  +             case 0x3042:
  +             case 0x3044:
  +             case 0x30A2:
  +             case 0x30A4:
  +             case 0x4E00:
  +             case 0x58F9:
  +             case 0x0E51:
  +             case 0x05D0:
  +             case 0x10D0:
  +             case 0x03B1:
  +             case 0x0430:
  +                     executionContext.error(LongToDOMString(numberType) + " 
format not supported yet!");
                default: // "1"
                        {
                                const XalanDOMString            numString =
  @@ -848,19 +768,21 @@
        return formattedNumber;  
   }
   
  +XalanDOMString ElemNumber::int2singlealphaCount(int val, 
  +             const XalanDOMString&   table)
  +{
  +     const int               radix = length(table);
   
  +     // TODO:  throw error on out of range input
  +     if (val > radix)
  +             return XalanDOMString(XALAN_STATIC_UCODE_STRING("#E(") +
  +                             LongToDOMString(val) +
  +                             XALAN_STATIC_UCODE_STRING(")"));
  +     else
  +             return XalanDOMString(charAt(table, val-1));
   
  -/**
  - * Convert a long integer into alphabetic counting, in other words 
  - * count using the sequence A B C ... Z AA AB AC.... etc.
  - * @param val Value to convert -- must be greater than zero.
  - * @param table a table containing one character for each digit in the radix
  - * @return String representing alpha count of number.
  - * @see XSLTEngineImpl#DecimalToRoman
  - * 
  - * Note that the radix of the conversion is inferred from the size
  - * of the table.
  - */
  +}
  +
   XalanDOMString
   ElemNumber::int2alphaCount(
                        int                                             val,
  @@ -939,6 +861,12 @@
        return retStr;
   }
   
  +XalanDOMString ElemNumber::tradAlphaCount(int val)
  +{
  +//   @@ JMD: We don't do languages yet, so this is just a placeholder
  +     assert(0);
  +     return XalanDOMString();        // To keep compiler happy
  +}
   
   
   XalanDOMString
  @@ -990,4 +918,228 @@
        }
   
        return roman;
  +}
  +
  +
  +/*
  + *                           NumberFormatStringTokenizer Class Implementation
  + */
  +
  +ElemNumber::NumberFormatStringTokenizer::NumberFormatStringTokenizer(
  +                     const XalanDOMString&   theStr) :
  +     m_currentPosition(0),
  +     m_maxPosition(length(theStr)),
  +     m_str(theStr)
  +{
  +}
  +
  +
  +
  +/*
  +@@ Obsolete ??
  +void
  +ElemNumber::NumberFormatStringTokenizer::setString(const XalanDOMString&     
theString)
  +{
  +     m_str = theString;
  +
  +     m_currentPosition = 0;
  +     m_maxPosition = length(theString);
  +}
  +
  +*/
  +
  +// @@ JMD: This seemed to be working OK in previous version and is
  +// functionally equivalent to java, so I left it alone.  Other java methods 
do
  +// not seem to be needed in this implementation
  +
  +XalanDOMString
  +ElemNumber::NumberFormatStringTokenizer::nextToken() 
  +{
  +     if (m_currentPosition >= m_maxPosition) 
  +     {
  +             // $$$ Todo: Implement!
  +//                           throw new NoSuchElementException();
  +     }
  +
  +     const int       start = m_currentPosition;
  +
  +     if (isLetterOrDigit(charAt(m_str, m_currentPosition)))
  +     {
  +             while ((m_currentPosition < m_maxPosition) &&
  +                             isLetterOrDigit(charAt(m_str, 
m_currentPosition))) 
  +                     m_currentPosition++;
  +     }
  +     else
  +     {
  +             while ((m_currentPosition < m_maxPosition) &&
  +                             !isLetterOrDigit(charAt(m_str, 
m_currentPosition))) 
  +                     m_currentPosition++;
  +     }
  +
  +     // @@ This wasn't working right when start=current=0 with DOMStrings
  +     // need to check it with XalanDOMString's
  +     return substring(m_str, start, m_currentPosition);
  +}
  +
  +
  +
  +int
  +ElemNumber::NumberFormatStringTokenizer::countTokens() const
  +{
  +     int     count = 0;
  +     int     currpos = m_currentPosition;
  +
  +     // Tokens consist of sequences of alphabetic characters and sequences of
  +     // non-alphabetic characters
  +     while (currpos < m_maxPosition) 
  +     {
  +             if (isLetterOrDigit(charAt(m_str, currpos)))
  +             {
  +                     while ((currpos < m_maxPosition) &&
  +                                     isLetterOrDigit(charAt(m_str, 
currpos))) 
  +                             currpos++;
  +             }
  +             else
  +             {
  +                     while ((currpos < m_maxPosition) &&
  +                                     !isLetterOrDigit(charAt(m_str, 
currpos))) 
  +                             currpos++;
  +             }
  +             count++;
  +     }
  +     return count;
  +}
  +
  +/*
  + *                                   CountersTable Class Implementation
  + */
  +
  +ElemNumber::CounterVectorType& 
ElemNumber::CountersTable::getCounters(ElemNumber* const numberElem)
  +{
  +     Ptr2CounterVectorMapType::iterator it = m_hashTable.find(numberElem);
  +     return (m_hashTable.end() == it) ? putElemNumber(numberElem) : 
(*it).second;
  +}
  +
  +ElemNumber::CounterVectorType& 
ElemNumber::CountersTable::putElemNumber(ElemNumber* const numberElem)
  +{
  +#if !defined(XALAN_NO_NAMESPACES)
  +     using std::make_pair;
  +#endif
  +     m_hashTable.insert(make_pair(numberElem, CounterVectorType()));
  +     return (*m_hashTable.find(numberElem)).second;
  +}
  +
  +void ElemNumber::CountersTable::appendBtoFList(MutableNodeRefList& flist, 
MutableNodeRefList& blist)
  +{
  +     int n = blist.getLength();
  +     for(int i = (n-1); i >= 0; i--)
  +     {
  +             flist.addNode(blist.item(i));
  +     }
  +}
  +
  +/**
  + * Count forward until the given node is found, or until 
  + * we have looked to the given amount.
  + * @node The node to count.
  + * @return The node count, or 0 if not found.
  + */
  +int ElemNumber::CountersTable::countNode(
  +             StylesheetExecutionContext& support,
  +             ElemNumber* const numberElem,
  +             const XalanNode* const node)
  +{
  +     int count = 0;
  +     CounterVectorType& counters = getCounters(numberElem);
  +     int nCounters = counters.size();
  +
  +     XalanNode* target = numberElem->getTargetNode(support, node);
  +     if(0 != target)
  +     {
  +             for(int i = 0; i < nCounters; i++)
  +             {    
  +                     Counter counter = counters[i];
  +
  +                     count = counter.getPreviouslyCounted(support, target);
  +                     if(count > 0)
  +                             return count;
  +             }
  +
  +             // In the loop below, we collect the nodes in backwards doc 
order, so 
  +             // we don't have to do inserts, but then we store the nodes in 
forwards 
  +             // document order, so we don't have to insert nodes into that 
list, 
  +             // so that's what the appendBtoFList stuff is all about.  In 
cases 
  +             // of forward counting by one, this will mean a single node 
copy from 
  +             // the backwards list (m_newFound) to the forwards list
  +             // (counter.m_countNodes).
  +             count = 0;
  +             for(; 0 != target; target = 
numberElem->getPreviousNode(support, target))
  +             {   
  +                     // First time in, we should not have to check for 
previous counts, 
  +                     // since the original target node was already checked 
in the 
  +                     // block above.
  +                     if(0 != count)  
  +                     {
  +                             for(int i = 0; i < nCounters; i++)
  +                             {    
  +                                     Counter counter = counters[i];
  +                                     int cacheLen = 
counter.m_countNodes.getLength();
  +                                     if((cacheLen > 0) &&
  +                                                     
(counter.m_countNodes.item(cacheLen-1) == target))
  +                                     {
  +                                             count += 
(cacheLen+counter.m_countNodesStartCount);
  +                                             if(cacheLen > 0)
  +                                                     
appendBtoFList(counter.m_countNodes, m_newFound);
  +                                             m_newFound.clear();
  +                                             return count;
  +                                     }
  +                             }
  +                     }
  +                     m_newFound.addNode(target);
  +                     count++;
  +             }
  +             // If we got to this point, then we didn't find a counter, so 
make 
  +             // one and add it to the list.
  +             ElemNumber::Counter counter(numberElem);
  +             m_countersMade++; // for diagnostics
  +             appendBtoFList(counter.m_countNodes, m_newFound);
  +             m_newFound.clear();
  +             counters.push_back(counter);
  +     }
  +
  +     return count;
  +}
  +
  +/*
  + *                                   Counters Class Implementation
  + */
  +    
  +int ElemNumber::Counter::getPreviouslyCounted(
  +             StylesheetExecutionContext& /*support */,
  +             const XalanNode* const node)
  +{
  +     int n = m_countNodes.getLength();
  +     m_countResult = 0;
  +     for(int i = n-1;i >= 0; i--)
  +     {
  +             const XalanNode* countedNode = m_countNodes.item(i);
  +             if(node == countedNode)
  +             {
  +                     // Since the list is in backwards order, the count is 
  +                     // how many are in the rest of the list.
  +                     m_countResult = i+1+m_countNodesStartCount;
  +                     break;
  +             }
  +             // Try to see if the given node falls after the counted node...
  +             // if it does, don't keep searching backwards.
  +             if(DOMServices::isNodeAfter(*countedNode, *node))
  +                     break;
  +     }
  +     return m_countResult;
  +}
  +
  +XalanNode* ElemNumber::Counter::getLast()
  +{
  +     int size = m_countNodes.getLength();
  +     return (size > 0) ? m_countNodes.item(size-1) : 0;
   }
  
  
  
  1.9       +300 -94   xml-xalan/c/src/XSLT/ElemNumber.hpp
  
  Index: ElemNumber.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xalan/c/src/XSLT/ElemNumber.hpp,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- ElemNumber.hpp    2000/04/11 15:09:25     1.8
  +++ ElemNumber.hpp    2000/04/19 15:59:25     1.9
  @@ -33,7 +33,7 @@
    *    nor may "Apache" appear in their name, without prior written
    *    permission of the Apache Software Foundation.
    *
  - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  +  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  @@ -58,7 +58,7 @@
   #define XALAN_ELEMNUMBER_HEADER_GUARD 
   
   /**
  - * $Id: ElemNumber.hpp,v 1.8 2000/04/11 15:09:25 dbertoni Exp $
  + * $Id: ElemNumber.hpp,v 1.9 2000/04/19 15:59:25 jdonohue Exp $
    * 
    * $State: Exp $
    * 
  @@ -72,9 +72,12 @@
   
   // Base class header file.
   #include "ElemTemplateElement.hpp"
  +#include "AVT.hpp"
   
  +#include "XPath/MutableNodeRefList.hpp"
   
   
  +
   // Just locale.h in G++
   #if ! defined(__GNUC__)
   #include <locale>
  @@ -95,6 +98,10 @@
   
   class ElemNumber: public ElemTemplateElement
   {
  +private:
  +
  +struct Counter;
  +
   public:
   
   #if defined(XALAN_NO_NAMESPACES)
  @@ -103,8 +110,10 @@
   #     define XALAN_STD std::
   #endif
        typedef XALAN_STD vector<int> IntArrayType;
  +     typedef XALAN_STD vector<Counter> CounterVectorType;
  +     typedef XALAN_STD map<ElemNumber*, 
CounterVectorType>Ptr2CounterVectorMapType;
   #    if ! defined(__GNUC__)
  -             typedef XALAN_STD locale LocaleType;
  +     typedef XALAN_STD locale LocaleType;
   #    endif
   #undef XALAN_STD     
   
  @@ -126,6 +135,9 @@
                        int                                                     
        lineNumber,
                        int                                                     
        columnNumber);
   
  +     virtual
  +     ~ElemNumber();
  +
        // These methods are inherited from ElemTemplateElement ...
        
        virtual void
  @@ -148,10 +160,10 @@
         */
        XalanNode*
        findAncestor(
  -                     StylesheetExecutionContext&             
executionContext,
  -                     const XPath*                                    
fromMatchPattern,
  -                     const XPath*                                    
countMatchPattern,
  -                     XalanNode*                                              
context,
  +                     StylesheetExecutionContext&     executionContext,
  +                     const XPath*                                            
fromMatchPattern,
  +                     const XPath*                                            
countMatchPattern,
  +                     const XalanNode* const                  context,
                        const XalanElement*                             
namespaceContext) const;
   
          /**
  @@ -165,10 +177,10 @@
           */
        XalanNode*
        findPrecedingOrAncestorOrSelf(
  -                     StylesheetExecutionContext&             
executionContext,
  -                     const XPath*                                    
fromMatchPattern,
  -                     const XPath*                                    
countMatchPattern,
  -                     XalanNode*                                              
context,
  +                     StylesheetExecutionContext&     executionContext,
  +                     const XPath*                                            
fromMatchPattern,
  +                     const XPath*                                            
countMatchPattern,
  +                     const XalanNode* const                  context,
                        const XalanElement*                             
namespaceContext) const;
   
        /**
  @@ -177,7 +189,7 @@
        const XPath*
        getCountMatchPattern(
                        StylesheetExecutionContext&             
executionContext,
  -                     XalanNode*                                              
contextNode) const;
  +                     const XalanNode* const                          
contextNode) const;
   
        /**
         * Given an XML source node, get the count according to the 
  @@ -186,93 +198,35 @@
        XalanDOMString
        getCountString(
                        StylesheetExecutionContext&             
executionContext,
  -                     XalanNode*                                              
sourceTree, 
  -                     XalanNode*                                              
sourceNode) const;
  +                     XalanNode* const                                        
sourceTree, 
  +                     XalanNode* const                                        
sourceNode) const;
   
        /**
  -      * from any position in the tree, return the 
  -      * next node in the tree, assuming preorder 
  -      * traversal preceded, or null if at the end.
  -      */
  -     static XalanNode*
  -     getNextInTree(
  -                     XalanNode*      pos,
  -                     XalanNode*      from);
  -
  -     /**
  -      * Get a number that represents a node based on the
  -      * position of that node among within the document tree,  
  -      * and taking into account the count and from patterns as 
  -      * specified in the XSL specification.
  -      * @param fromMatchPattern if non-null, where to 
  -      * start counting from.
  -      * @param countMatchPattern if non-null, count only nodes 
  -      * that match this pattern.
  -      * @param target count this node and preceding nodes.
  -      * @return A number that counts target and preceding 
  -      * nodes that qualify.
  -      */
  -     unsigned int
  -     getNumberInTree(
  -                     XPathExecutionContext&  executionContext,
  -                     const XPath*                    countMatchPattern,
  -                     XalanNode*                              pos,
  -                     XalanNode*                              from,
  -                     XalanNode*                              target,
  -                     int                                             
countFrom) const;
  -
  -     /**
  -      * Get a number that represents a node based on the
  -      * position of that node among it's siblings, and 
  -      * taking into account the count and from patterns.
  -      * @param fromMatchPattern if non-null, where to 
  -      * start counting from.
  -      * @param countMatchPattern if non-null, count only nodes 
  -      * that match this pattern.
  -      * @param target count this node and preceding siblings.
  -      * @return A number that counts target and preceding 
  -      * siblings that qualify.
  +      * Get the previous node to be counted.
         */
  -     unsigned int
  -     getSiblingNumber(
  +     XalanNode* getPreviousNode(
                        StylesheetExecutionContext&             
executionContext,
  -                     const XPath*                                    
countMatchPattern, 
  -                     XalanNode*                                              
target) const;
  +                     XalanNode* pos);
   
        /**
  -      * Count the ancestors, up to the root, that match the 
  -      * pattern.
  -      * @param patterns if non-null, count only nodes 
  -      * that match this pattern, if null count all ancestors.
  -      * @param node Count this node and it's ancestors.
  -      * @return The number of ancestors that match the pattern.
  +      * Get the target node that will be counted..
         */
  -     unsigned int
  -     countMatchingAncestors( 
  -                     StylesheetExecutionContext&             
executionContext,
  -                     const XPath*                                    
patterns,
  -                     XalanNode*                                              
node) const;
  +     XalanNode* getTargetNode(
  +                     StylesheetExecutionContext& executionContext,
  +                     const XalanNode* const sourceNode);
   
        /**
  -      * Climb up the ancestor tree, collecting sibling position 
  -      * numbers (as modified by the fromMatchPattern and 
  -      * countMatchPattern patterns).
  -      * @param fromMatchPattern if non-null, where to 
  -      * start counting from in each sibling list.
  -      * @param countMatchPattern if non-null, count only ancestors 
  -      * and siblings that match this pattern.
  -      * @param node count this node and ancestors that match the 
countMatchPattern.
  -      * @return An array of ints of length that matches exactly the number 
  -      * of ancestors that match countMatchPattern.
  -      * @exception XSLProcessorException thrown if the active 
ProblemListener and XMLParserLiaison decide 
  -      * the error condition is severe enough to halt processing.
  +      * Get the ancestors, up to the root, that match the
  +      * pattern.
  +      * @param patterns if non-0, count only nodes
  +      * that match this pattern, if 0 count all ancestors.
  +      * @param node Count this node and it's ancestors.
  +      * @return The number of ancestors that match the pattern.
         */
  -     IntArrayType
  -     getAncestorNumbers(
  +     MutableNodeRefList getMatchingAncestors(
                        StylesheetExecutionContext&             
executionContext,
  -                     const XPath*                                    
fromMatchPattern,
  -                     const XPath*                                    
countMatchPattern, 
  -                     XalanNode*                                              
node) const;
  +                     XalanNode* node, 
  +                     bool stopAtFirstFound) const;
   
   #if ! defined(__GNUC__)
        /**
  @@ -305,6 +259,20 @@
                        XalanNode*                                              
contextNode) const;
   
        /**
  +      * Convert a long integer into alphabetic counting, in other words
  +      * count using the sequence A B C ... Z.
  +      * @param val Value to convert -- must be greater than zero.
  +      * @param table a table containing one character for each digit in the 
radix
  +      * @return String representing alpha count of number.
  +      * @see XSLTEngineImpl#DecimalToRoman
  +      *
  +      * Note that the radix of the conversion is inferred from the size
  +      * of the table.
  +      */
  +     XalanDOMString int2singlealphaCount(int val, 
  +                     const XalanDOMString&   table);
  +             
  +     /**
         * Convert a long integer into alphabetic counting, in other words 
         * count using the sequence A B C ... Z AA AB AC.... etc.
         * @param val Value to convert -- must be greater than zero.
  @@ -321,6 +289,20 @@
                        const XalanDOMString&   table);
   
        /**
  +      * Convert a long integer into traditional alphabetic counting, in 
other words
  +      * count using the traditional numbering.
  +      * @param val Value to convert -- must be greater than zero.
  +      * @param table a table containing one character for each digit in the 
radix
  +      * @return String representing alpha count of number.
  +      * @see XSLProcessor#DecimalToRoman
  +      *
  +      * Note that the radix of the conversion is inferred from the size
  +      * of the table.
  +      */
  +     static XalanDOMString
  +     tradAlphaCount(int val);
  +
  +     /**
         * Convert a long integer into roman numerals.
         * @param val Value to convert.
         * @param prefixesAreOK true_ to enable prefix notation (e.g. 4 = "IV"),
  @@ -354,11 +336,11 @@
   
        int                             m_level; // = 
Constants.NUMBERLEVEL_SINGLE;
        
  -     XalanDOMString  m_format_avt;
  -     XalanDOMString  m_lang_avt;
  -     XalanDOMString  m_lettervalue_avt;
  -     XalanDOMString  m_groupingSeparator_avt;
  -     XalanDOMString  m_groupingSize_avt;
  +     AVT*    m_format_avt;
  +     AVT*    m_lang_avt;
  +     AVT*    m_lettervalue_avt;
  +     AVT*    m_groupingSeparator_avt;
  +     AVT*    m_groupingSize_avt;
   
        /**
        * Chars for converting integers into alpha counts.
  @@ -372,8 +354,232 @@
         * @see XSLTEngineImpl#long2roman
         */
        static const DecimalToRoman             s_romanConvertTable[];
  -};
   
   
  +
  +// Inner classes
  +
  +
  +     /**
  +      * This class returns tokens using non-alphanumberic characters as
  +      * delimiters. 
  +      */
  +     class NumberFormatStringTokenizer
  +     {
  +             public:
  +
  +                     /**
  +                      * Construct a NumberFormatStringTokenizer.
  +                      *
  +                      * @param theStr string to tokenize
  +                      */
  +                     explicit
  +                             NumberFormatStringTokenizer(const DOMString&    
theStr = DOMString());
  +
  +                     /**
  +                      * Sets the string to tokenize.
  +                      *
  +                      * @param theString  new string to tokenize
  +                      */
  +                     void
  +                             setString(const DOMString&      theString);
  +
  +                     /**
  +                      * Reset tokenizer so that nextToken() starts from the 
beginning.
  +                      */
  +                     void
  +                             reset()
  +                             {
  +                                     m_currentPosition = 0;
  +                             }
  +
  +                     /**
  +                      * Retrieve the next token to be parsed; behavior is 
undefined if there
  +                      * are no more tokens
  +                      * 
  +                      * @return next token string
  +                      */
  +                     DOMString
  +                             nextToken();
  +
  +                     /**
  +                      * Determine if there are tokens remaining
  +                      * 
  +                      * @return true if there are more tokens
  +                      */
  +                     bool
  +                             hasMoreTokens() const
  +                             {
  +                                     return (m_currentPosition >= 
m_maxPosition) ? false : true;
  +                             }
  +
  +                     /**
  +                      * Count the number of tokens yet to be parsed
  +                      * 
  +                      * @return number of remaining tokens
  +                      */
  +                     int
  +                             countTokens() const;
  +
  +             private:
  +
  +                     int                     m_currentPosition;
  +                     int                     m_maxPosition;
  +                     DOMString       m_str;
  +     }; // end NumberFormatStringTokenizer
  +
  +     /**
  +      * <meta name="usage" content="internal"/>
  +      * This is a table of counters, keyed by ElemNumber objects, each 
  +      * of which has a list of Counter objects.  This really isn't a true 
  +      * table, it is more like a list of lists (there must be a technical 
  +      * term for that...).
  +      */
  +     class CountersTable
  +     {
  +             public:
  +
  +                     /**
  +                      * Construct a CountersTable.
  +                      */
  +                     CountersTable() : 
  +                             m_countersMade(0)
  +                             {
  +                             };
  +
  +
  +                     /**
  +                      * Count forward until the given node is found, or 
until 
  +                      * we have looked to the given amount.
  +                      * @node The node to count.
  +                      * @return The node count, or 0 if not found.
  +                      */
  +                     int CountersTable::countNode(
  +                                     StylesheetExecutionContext& support,
  +                                     ElemNumber* const numberElem,
  +                                     const XalanNode* const node);
  +
  +             private:
  +
  +                     /**
  +                      * Get the list of counters that corresponds to 
  +                      * the given ElemNumber object.
  +                      */
  +                     CounterVectorType& getCounters(ElemNumber* const 
numberElem);
  +
  +
  +                     /**
  +                      * Put a counter into the table and create an empty 
  +                      * vector as it's value.
  +                      */
  +                     CounterVectorType& putElemNumber(ElemNumber* const 
numberElem);
  +
  +                     /**
  +                      * Add a list of counted nodes that were built in 
backwards document 
  +                      * order, or a list of counted nodes that are in 
forwards document 
  +                      * order.
  +                      */
  +                     void appendBtoFList(MutableNodeRefList& flist, 
MutableNodeRefList& blist);
  +
  +                     /**
  +                      * Place to collect new counters.
  +                      */
  +                     MutableNodeRefList m_newFound;
  +
  +                     // For diagnostics
  +                     int m_countersMade;
  +
  +                     // Since we're not really a hash table like in java, we 
need this
  +                     Ptr2CounterVectorMapType m_hashTable;
  +
  +     }; // end CountersTable
  +
  +     friend class CountersTable;
  +
  +     /**
  +      * <meta name="usage" content="internal"/>
  +      * A class that does incremental counting for support of xsl:number.
  +      * This class stores a cache of counted nodes (m_countNodes). 
  +      * It tries to cache the counted nodes in document order... 
  +      * the node count is based on its position in the cache list 
  +      */
  +     struct Counter
  +     {
  +             /**
  +              * The start count from where m_countNodes counts 
  +              * from.  In other words, the count of a given node 
  +              * in the m_countNodes vector is node position + 
  +              * m_countNodesStartCount.
  +              */
  +             int m_countNodesStartCount;
  +
  +             /**
  +              * A vector of all nodes counted so far.
  +              */
  +             MutableNodeRefList m_countNodes;
  +
  +             /**
  +              * The node from where the counting starts.  This is needed to 
  +              * find a counter if the node being counted is not immediatly
  +              * found in the m_countNodes vector.
  +              */
  +             XalanNode* m_fromNode;
  +
  +             /**
  +              * The owning xsl:number element.
  +              */
  +             ElemNumber* m_numberElem;
  +
  +             /**
  +              * Value to store result of last getCount call, for benifit
  +              * of returning val from CountersTable.getCounterByCounted, 
  +              * who calls getCount.
  +              */
  +             int m_countResult;
  +
  +             /**
  +              * Construct a counter object.
  +              */
  +             Counter(ElemNumber* numberElem, MutableNodeRefList& countNodes) 
:
  +                     m_countNodesStartCount(0),
  +             m_countNodes(countNodes),
  +             m_fromNode(0),
  +             m_numberElem(numberElem),
  +             m_countResult(0)
  +             {
  +             }
  +
  +             /**
  +              * Construct a counter object.
  +              */
  +             Counter(ElemNumber* numberElem) :
  +                     m_countNodesStartCount(0),
  +             m_countNodes(),
  +             m_fromNode(0),
  +             m_numberElem(numberElem),
  +             m_countResult(0)
  +             {
  +             }
  +
  +             /**
  +              * Try to find a node that was previously counted. If found, 
return a
  +              * positive integer that corresponds to the count.
  +              * @param node The node to be counted.
  +              * @returns The count of the node, or -1 if not found.
  +              */
  +             int getPreviouslyCounted(
  +                             StylesheetExecutionContext& support,
  +                             const XalanNode* const node);
  +
  +             /**
  +              * Get the last node in the list.
  +              */
  +             XalanNode* getLast();
  +
  +     }; // end Counter
  +
  +     friend struct Counter;
  +
  +}; // end ElemNumber
   
   #endif       // XALAN_ELEMNUMBER_HEADER_GUARD
  
  
  

Reply via email to