You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by db...@locus.apache.org on 2000/12/21 05:00:41 UTC

cvs commit: xml-xalan/c/src/XSLT CountersTable.cpp CountersTable.hpp

dbertoni    00/12/20 20:00:41

  Added:       c/src/XSLT CountersTable.cpp CountersTable.hpp
  Log:
  Moved code from ElemNumber.hpp and ElemNumber.cpp to new files.
  
  Revision  Changes    Path
  1.1                  xml-xalan/c/src/XSLT/CountersTable.cpp
  
  Index: CountersTable.cpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xalan" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    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
   * 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
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  #include "CountersTable.hpp"
  
  
  
  #include <algorithm>
  
  
  
  #include "ElemNumber.hpp"
  #include "StylesheetExecutionContext.hpp"
  
  
  
  inline void
  CountersTable::appendBtoFList(
  			NodeVectorType&		flist,
  			NodeVectorType&		blist)
  {
  #if !defined(XALAN_NO_NAMESPACES)
  	using std::back_inserter;
  	using std::copy;
  #endif
  
  	flist.reserve(flist.size() + blist.size());
  
  	copy(
  		blist.rbegin(),
  		blist.rend(),
  		back_inserter(flist));
  }
  
  
  
  int
  CountersTable::countNode(
  			StylesheetExecutionContext&		support,
  			const ElemNumber*				numberElem,
  			XalanNode*						node)
  {
  	int		count = 0;
  
  	CounterVectorType&	counters = m_counterMap[numberElem];
  
  	const CounterVectorType::size_type	nCounters = counters.size();
  
  	XalanNode*	target = numberElem->getTargetNode(support, node);
  
  	if(0 != target)
  	{
  		for(CounterVectorType::size_type i = 0; i < nCounters; i++)
  		{    
  			const 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(CounterVectorType::size_type i = 0; i < nCounters; ++i)
  				{
  					Counter&	counter = counters[i];
  
  					const unsigned int	cacheLen = counter.m_countNodes.size();
  
  					if(cacheLen > 0 && counter.m_countNodes[cacheLen - 1] == target)
  					{
  						count += cacheLen + counter.m_countNodesStartCount;
  
  						if(cacheLen > 0)
  						{
  							appendBtoFList(counter.m_countNodes, m_newFound);
  						}
  
  						m_newFound.clear();
  
  						return count;
  					}
  				}
  			}
  
  			m_newFound.push_back(target);
  
  			++count;
  		}
  
  		// If we got to this point, then we didn't find a counter, so make 
  		// one and add it to the list.
  		counters.push_back(Counter(numberElem));
  
  		Counter&	counter = counters.back();
  
  		appendBtoFList(counter.m_countNodes, m_newFound);
  
  		m_newFound.clear();
  	}
  
  	return count;
  }
  
  
  
  int
  Counter::getPreviouslyCounted(
  		StylesheetExecutionContext&		executionContext,
  		const XalanNode*				node) const
  {
  	const int	n = m_countNodes.size();
  
  	int			result = 0;
  
  	for(int i = n - 1; i >= 0; --i)
  	{
  		const XalanNode* const	countedNode = m_countNodes[i];
  
  		if(node == countedNode)
  		{
  			// Since the list is in backwards order, the count is 
  			// how many are in the rest of the list.
  			result = 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(executionContext.isNodeAfter(*countedNode, *node))
  			break;
  	}
  
  	return result;
  }
  
  
  
  1.1                  xml-xalan/c/src/XSLT/CountersTable.hpp
  
  Index: CountersTable.hpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xalan" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    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
   * 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
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  #if !defined(XALAN_COUNTERSTABLE_HEADER_GUARD_1357924680)
  #define XALAN_ELEMNUMBER_HEADER_GUARD_1357924680 
  
  /**
   * $Id: CountersTable.hpp,v 1.1 2000/12/21 04:00:41 dbertoni Exp $
   * 
   * $State: Exp $
   * 
   */
  
  // Base include file.  Must be first.
  #include <XSLT/XSLTDefinitions.hpp>
  
  
  
  #include <map>
  #include <vector>
  
  
  
  #include "XPath/MutableNodeRefList.hpp"
  
  
  
  class ElemNumber;
  class StylesheetExecutionContext;
  
  
  
  /**
   * <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
  {
  #if defined(XALAN_NO_NAMESPACES)
  	typedef vector<XalanNode*>			NodeVectorType;
  #else
  	typedef std::vector<XalanNode*>		NodeVectorType;
  #endif
  	/**
  	 * 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.
  	 */
  	NodeVectorType		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.
  	 */
  	const XalanNode*	m_fromNode;
  
  	/**
  	 * The owning xsl:number element.
  	 */
  	const ElemNumber*	m_numberElem;
  
  	/**
  	 * Construct a counter object.
  	 */
  	Counter(
  			const ElemNumber*	numberElem,
  			NodeVectorType&		countNodes) :
  		m_countNodesStartCount(0),
  		m_countNodes(countNodes),
  		m_fromNode(0),
  		m_numberElem(numberElem)
  	{
  	}
  
  	/**
  	 * Construct a counter object.
  	 */
  	Counter(const ElemNumber*	numberElem = 0) :
  		m_countNodesStartCount(0),
  		m_countNodes(),
  		m_fromNode(0),
  		m_numberElem(numberElem)
  	{
  	}
  
  	/**
  	 * 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*				node) const;
  
  	/**
  	 * Get the last node in the list.
  	 */
  	XalanNode*
  	getLast() const
  	{
  		return m_countNodes.size() == 0 ? 0 : m_countNodes.back();
  	}
  };
  
  
  
  /**
   * <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:
  
  #if defined(XALAN_NO_NAMESPACES)
  	typedef vector<Counter>					CounterVectorType;
  	typedef map<const ElemNumber*,
  				CounterVectorType,
  				less<const ElemNumber*> >	ElemToCounterVectorMapType;
  #else
  	typedef std::vector<Counter>			CounterVectorType;
  	typedef std::map<const ElemNumber*,
  					 CounterVectorType>		ElemToCounterVectorMapType;
  #endif
  
  	typedef Counter::NodeVectorType			NodeVectorType;
  
  	/**
  	 * Construct a CountersTable.
  	 */
  	CountersTable() : 
  		m_newFound(),
  		m_counterMap()
  	{
  	};
  
  
  	/**
  	 * Count forward until the given node is found, or until 
  	 * we have looked to the given amount.
  	 *
  	 * @executionContext The current execution context;
  	 * @numberElem The executing ElemNumber
  	 * @node The node to count.
  	 * @return The node count, or 0 if not found.
  	 */
  	int
  	countNode(
  			StylesheetExecutionContext&		executionContext,
  			const ElemNumber*				numberElem,
  			XalanNode*						node);
  
  	/**
  	 * Clear all cached data from the table.
  	 */
  	void
  	reset()
  	{
  		m_newFound.clear();
  
  		m_counterMap.clear();
  	}
  
  private:
  
  	/**
  	 * 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(
  			NodeVectorType&		flist,
  			NodeVectorType&		blist);
  
  	/**
  	 * A map which holds counters for ElemNumber instances.
  	 */
  	ElemToCounterVectorMapType	m_counterMap;
  
  
  	/**
  	 * A vector to use as a temporary buffer.
  	 */
  	NodeVectorType				m_newFound;
  };
  
  
  #endif	// !defined(XALAN_COUNTERSTABLE_HEADER_GUARD_1357924680)