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...@apache.org on 2001/06/14 21:17:28 UTC

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

dbertoni    01/06/14 12:17:28

  Modified:    c/src/XSLT ElemNumber.cpp ElemNumber.hpp
  Log:
  Drastically improved performance.
  
  Revision  Changes    Path
  1.43      +423 -220  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.42
  retrieving revision 1.43
  diff -u -r1.42 -r1.43
  --- ElemNumber.cpp	2001/03/09 16:20:00	1.42
  +++ ElemNumber.cpp	2001/06/14 19:17:23	1.43
  @@ -217,8 +217,14 @@
   {
   	ElemTemplateElement::execute(executionContext);
   
  -	const XalanDOMString	countString = getCountString(executionContext);
  +	typedef XPathExecutionContext::GetAndReleaseCachedString	GetAndReleaseCachedString;
   
  +	GetAndReleaseCachedString	theGuard(executionContext);
  +
  +	XalanDOMString&				countString = theGuard.get();
  +
  +	getCountString(executionContext, countString);
  +
   	if (!isEmpty(countString))
   	{
   		executionContext.characters(toCharArray(countString), 0, length(countString));
  @@ -314,6 +320,7 @@
   				contextCopy = prevSibling;
   		}
   	}
  +
   	return contextCopy;
   }
   
  @@ -371,15 +378,45 @@
   
   
   
  -XalanDOMString
  -ElemNumber::getCountString(StylesheetExecutionContext&		executionContext) const
  +inline void
  +ElemNumber::getCountString(
  +			StylesheetExecutionContext&		executionContext,
  +			XalanNode*						sourceNode,
  +			const MutableNodeRefList&		ancestors,
  +			CountersTable&					ctable,
  +			int								numberList[],
  +			unsigned int					numberListLength,
  +			XalanDOMString&					theResult) const
  +{
  +	for(unsigned int i = 0; i < numberListLength; i++)
  +	{
  +		XalanNode* const target = ancestors.item(numberListLength - i - 1);
  +
  +		numberList[i] = ctable.countNode(
  +							executionContext,
  +							this,
  +							target);
  +	}
  +
  +	formatNumberList(
  +			executionContext,
  +			numberList,
  +			numberListLength,
  +			sourceNode,
  +			theResult);
  +}
  +
  +
  +
  +void
  +ElemNumber::getCountString(
  +			StylesheetExecutionContext&		executionContext,
  +			XalanDOMString&					theResult) const
   {
   	XalanNode* sourceNode = executionContext.getCurrentNode();
   
   	assert(sourceNode != 0);
   
  -	IntArrayType	numberList;
  -
   	if(0 != m_valueExpr)
   	{
   		const XObjectPtr	countObj(m_valueExpr->execute(sourceNode, *this, executionContext));
  @@ -387,14 +424,19 @@
   
   		const double	theValue = countObj->num();
   
  -		if (DoubleSupport::isNaN(theValue) == true)
  -		{
  -			numberList.push_back(0);
  -		}
  -		else
  +		int	theNumber = 0;
  +
  +		if (DoubleSupport::isNaN(theValue) == false)
   		{
  -			numberList.push_back(int(DoubleSupport::round(theValue)));
  +			theNumber = int(DoubleSupport::round(theValue));
   		}
  +
  +		formatNumberList(
  +				executionContext,
  +				&theNumber,
  +				1,
  +				sourceNode,
  +				theResult);
   	}
   	else
   	{
  @@ -402,34 +444,65 @@
   
   		if(Constants::NUMBERLEVEL_ANY == m_level)
   		{
  -			numberList.push_back(ctable.countNode(
  -						executionContext, 
  -						this,
  -						sourceNode));
  +			const int	theNumber =
  +				ctable.countNode(executionContext, this, sourceNode);
  +
  +			formatNumberList(
  +				executionContext,
  +				&theNumber,
  +				1,
  +				sourceNode,
  +				theResult);
   		}
   		else
   		{
  -			const MutableNodeRefList	ancestors = getMatchingAncestors(executionContext, sourceNode,
  -				Constants::NUMBERLEVEL_SINGLE == m_level);
  +			typedef XPathExecutionContext::BorrowReturnMutableNodeRefList	BorrowReturnMutableNodeRefList;
   
  -			const unsigned int	lastIndex = ancestors.getLength();
  +			BorrowReturnMutableNodeRefList	ancestors(executionContext);
  +
  +			getMatchingAncestors(
  +				executionContext,
  +				sourceNode,
  +				Constants::NUMBERLEVEL_SINGLE == m_level,
  +				*ancestors.get());
   
  +			const unsigned int	lastIndex = ancestors->getLength();
  +
   			if(lastIndex > 0)
   			{
  -				for(unsigned int i = 0; i < lastIndex; i++)
  +				const unsigned int	theStackArrayThreshold = 100;
  +
  +				if (lastIndex < theStackArrayThreshold)
   				{
  -					XalanNode* const target = ancestors.item(lastIndex - i - 1);
  +					int		numberList[theStackArrayThreshold];
   
  -					numberList.push_back(ctable.countNode(
  +					getCountString(
   						executionContext,
  -						this,
  -						target));
  +						sourceNode,
  +						*ancestors.get(),
  +						ctable,
  +						numberList,
  +						lastIndex,
  +						theResult);
   				}
  +				else
  +				{
  +					IntArrayType	numberList;
  +
  +					numberList.resize(lastIndex);
  +
  +					getCountString(
  +						executionContext,
  +						sourceNode,
  +						*ancestors.get(),
  +						ctable,
  +						&*numberList.begin(),
  +						lastIndex,
  +						theResult);
  +				}
   			}
   		}
   	}
  -
  -	return numberList.size() > 0 ? formatNumberList(executionContext, numberList, sourceNode) : XalanDOMString();
   }
   
   
  @@ -456,7 +529,7 @@
   
   	if(Constants::NUMBERLEVEL_ANY == m_level)
   	{
  -		const XPath* fromMatchPattern = m_fromMatchPattern;
  +		const XPath* const	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, 
  @@ -467,16 +540,21 @@
   			// 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) !=
  -									 XPath::s_MatchScoreNone))) || 
  -							(next->getNodeType() == XalanNode::DOCUMENT_NODE)))
  +
  +				if(0 != next &&
  +				   next->getNodeType() == XalanNode::DOCUMENT_NODE ||
  +				   (0 != fromMatchPattern &&
  +						fromMatchPattern->getMatchScore(
  +							next,
  +							*this,
  +							executionContext) != XPath::s_MatchScoreNone))
   				{
   					pos = 0; // return 0 from function.
  +
   					break; // from while loop
   				}
   			}
  @@ -484,19 +562,24 @@
   			{
   				// dive down to the lowest right child.
   				XalanNode* child = next;
  +
   				while(0 != child)
   				{
   					child = next->getLastChild();
  +
   					if(0 != child)
   						next = child;
   				}
   			}
  +
   			pos = next;
   
  -			if((0 != pos) && ((0 == countMatchPattern) ||
  -						(countMatchPattern->getMatchScore(pos, *this,
  -						executionContext) !=
  -						 XPath::s_MatchScoreNone)))
  +			if(0 != pos &&
  +			   (0 == countMatchPattern ||
  +				countMatchPattern->getMatchScore(
  +						pos,
  +						*this,
  +						executionContext) != XPath::s_MatchScoreNone))
   			{
   				break;
   			}
  @@ -507,19 +590,24 @@
   		while(0 != pos)
   		{            
   			pos = pos->getPreviousSibling();
  -			if((0 != pos) && ((0 == countMatchPattern) ||
  -						(countMatchPattern->getMatchScore(pos, *this,
  -						executionContext) !=
  -						 XPath::s_MatchScoreNone)))
  +
  +			if(0 != pos &&
  +			   (0 == countMatchPattern ||
  +				countMatchPattern->getMatchScore(
  +						pos,
  +						*this,
  +						executionContext) != XPath::s_MatchScoreNone))
   			{
   				break;
   			}
   		}
   	}
  +
   	return pos;
   }
   
   
  +
   XalanNode*
   ElemNumber::getTargetNode(
   		StylesheetExecutionContext&		executionContext,
  @@ -564,23 +652,15 @@
   	return target;
   }
   
  +
   
  -/**
  - * 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
  +void
   ElemNumber::getMatchingAncestors(
  -		StylesheetExecutionContext&		executionContext,
  -		XalanNode* node, 
  -		bool stopAtFirstFound) const
  +			StylesheetExecutionContext&		executionContext,
  +			XalanNode*						node, 
  +			bool							stopAtFirstFound,
  +			MutableNodeRefList&				ancestors) const
   {
  -	MutableNodeRefList ancestors;
  -
   	// Create an XPathGuard, since we may need to
   	// create a new XPath...
   	StylesheetExecutionContext::XPathGuard	xpathGuard(
  @@ -596,7 +676,7 @@
   		countMatchPattern = xpathGuard.get();
   	}
   
  -	while( 0 != node )
  +	while(0 != node)
   	{
   		if((0 != m_fromMatchPattern) &&
   				(m_fromMatchPattern->getMatchScore(node, *this, executionContext) !=
  @@ -619,13 +699,14 @@
   				XPath::s_MatchScoreNone)
   		{
   			ancestors.addNode(node);
  +
   			if(stopAtFirstFound)
   				break;
   		}
  +
   		node = DOMServices::getParentOfNode(*node);
   	}
  -	return ancestors;
  -} // end getMatchingAncestors method
  +}
   
   
   
  @@ -636,13 +717,22 @@
   {
       // Helper to format local specific numbers to strings.
   	XalanAutoPtr<XalanNumberFormat>		formatter(executionContext.createXalanNumberFormat());
  +
  +	typedef XPathExecutionContext::GetAndReleaseCachedString	GetAndReleaseCachedString;
  +
  +	GetAndReleaseCachedString	theGuard1(executionContext);
  +
  +	XalanDOMString&				digitGroupSepValue = theGuard1.get();
   
  -	XalanDOMString	digitGroupSepValue;
   	if (0 != m_groupingSeparator_avt)
   		 m_groupingSeparator_avt->evaluate(digitGroupSepValue, contextNode,
   				 *this, executionContext);
   									 
  -	XalanDOMString	nDigitsPerGroupValue;
  +
  +	GetAndReleaseCachedString	theGuard2(executionContext);
  +
  +	XalanDOMString&				nDigitsPerGroupValue = theGuard2.get();
  +
   	if (0 != m_groupingSize_avt)
   		m_groupingSize_avt->evaluate(nDigitsPerGroupValue, contextNode, *this,
   				executionContext);
  @@ -660,69 +750,98 @@
   }
   
   
  -//@@ JMD: this is different from the java version, but seems to work, so I'll
  -//leave it alone
  -XalanDOMString
  +
  +void
   ElemNumber::formatNumberList(
   			StylesheetExecutionContext&		executionContext,
  -			const IntArrayType&				theList,
  -			XalanNode*						contextNode) const
  +			const int						theList[],
  +			unsigned int					theListLength,
  +			XalanNode*						contextNode,
  +			XalanDOMString&					theResult) const
   {
  -	const IntArrayType::size_type	nNumbers = theList.size();
  -	XalanDOMChar	numberType(XalanUnicode::charDigit_1);
  -	int			numberWidth = 1;
  +	assert(theListLength > 0);
   
  -	XalanDOMString	formattedNumber;
  -	XalanDOMString	formatToken;
  -	XalanDOMString	sepString(XALAN_STATIC_UCODE_STRING("."));
  -	XalanDOMString	lastSepString;
  -
   	// Pathological cases
  -	if (nNumbers == 0) return formattedNumber;
  -	if (contextNode == 0) return formattedNumber;
  -
  -	XalanDOMString	formatValue;
  -	if (m_format_avt != 0)
  -		 m_format_avt->evaluate(formatValue, contextNode, *this, executionContext);
  +	if (contextNode == 0) return;
   
  -	if(isEmpty(formatValue)) 
  -		formatValue = XALAN_STATIC_UCODE_STRING("1");
  +	XalanDOMChar	numberType = XalanUnicode::charDigit_1;
   
  -	NumberFormatStringTokenizer		formatTokenizer(formatValue);
  +	int			numberWidth = 1;
   
   	typedef vector<XalanDOMString>		StringVectorType;
   	typedef StringVectorType::iterator	StringVectorTypeIterator;
   
   	// Construct an array of tokens.  We need to be able to check if the last
   	// token in non-alphabetic, in which case the penultimate non-alphabetic is
  -	// the repeating separator
  -	StringVectorType tokenVector;
  -	while(formatTokenizer.hasMoreTokens())
  -		tokenVector.push_back(formatTokenizer.nextToken());
  -
  -	// Get rid of the leading and trailing non-alphabetics, save for later
  -	XalanDOMString leaderStr;
  -	XalanDOMString trailerStr;
  -	StringVectorTypeIterator it;
  +	// the repeating separator.
  +	//
  +	// We should be able to replace this with a vector of the indexes in
  +	// the evaluated string where the tokens start.  But for now, this will
  +	// have to do...
  +	StringVectorType	tokenVector;
   
  -	if (tokenVector.size() > 0)
   	{
  -		it = tokenVector.begin();
  +		typedef XPathExecutionContext::GetAndReleaseCachedString	GetAndReleaseCachedString;
   
  -		if(!isXMLLetterOrDigit(charAt(*it, 0)))
  +		GetAndReleaseCachedString	theGuard1(executionContext);
  +
  +		XalanDOMString&				formatValue = theGuard1.get();
  +
  +		if (m_format_avt != 0)
  +		{
  +			 m_format_avt->evaluate(formatValue, contextNode, *this, executionContext);
  +		}
  +
  +		if(isEmpty(formatValue) == true)
   		{
  -			leaderStr = *it;
  -			tokenVector.erase(it);
  +			formatValue = XalanUnicode::charDigit_1;
   		}
  +
  +		NumberFormatStringTokenizer		formatTokenizer(formatValue);
  +
  +		const unsigned int	theTokenCount = formatTokenizer.countTokens();
  +
  +		tokenVector.resize(theTokenCount);
   
  -		if (tokenVector.size() > 0)
  +		// Tokenize directly into the vector...
  +		for(unsigned int i = 0; i < theTokenCount; ++i)
   		{
  -			it = tokenVector.end() - 1;
  +			formatTokenizer.nextToken(tokenVector[i]);
  +		}
  +
  +		assert(theTokenCount == tokenVector.size());
  +	}
   
  -			if(!isXMLLetterOrDigit(charAt(*it, 0)))
  +	// These are iterators which will either point to tokenVector.end(),
  +	// or the appropriate string in the vector...
  +	StringVectorTypeIterator		leaderStrIt = tokenVector.end();
  +	StringVectorTypeIterator		trailerStrIt = leaderStrIt;
  +	StringVectorTypeIterator		sepStringIt = leaderStrIt;
  +	const StringVectorTypeIterator	endIt = leaderStrIt;
  +
  +	StringVectorTypeIterator	it = tokenVector.begin();
  +
  +	const StringVectorType::size_type	theVectorSize =
  +		tokenVector.size();
  +
  +	if (theVectorSize > 0)
  +	{
  +		if(!isXMLLetterOrDigit(charAt(*it, 0)))
  +		{
  +			leaderStrIt = it;
  +
  +			// Move the iterator up one, so it
  +			// points at the first numbering token...
  +			++it;
  +		}
  +
  +		if (theVectorSize > 1)
  +		{
  +			if(!isXMLLetterOrDigit(charAt(tokenVector.back(), 0)))
   			{
  -				trailerStr = *it;
  -				tokenVector.erase(it);
  +				// Move the iterator back one, so it's pointing
  +				// at the trailing string...
  +				--trailerStrIt;
   			}
   		}
   	}
  @@ -730,35 +849,70 @@
   	// Now we're left with a sequence of alpha,non-alpha tokens, format them
   	// with the corresponding entry in the format string, or the last one if no
   	// more matching ones
  -	formattedNumber = leaderStr;
  -	it = tokenVector.begin();
  -	for(unsigned int i = 0; i < nNumbers; i++)
  -	{
  -		if (it != tokenVector.end())
  -		{
  -			// $$$ ToDo: This assert is commented out until we get
  -			// out character classification problems fixed.
  -			// assert(isXMLLetterOrDigit(charAt((*it), 0)));
  -			formatToken = *it++;
  -			numberWidth = length(formatToken);
  -			numberType = charAt(formatToken, numberWidth - 1);
  -		}
  -		if (it != tokenVector.end())
  -		{
  -			// $$$ ToDo: This assert is commented out until we get
  -			// out character classification problems fixed.
  -			//assert(!isXMLLetterOrDigit(charAt((*it), 0)));
  -			sepString = *it++;
  +
  +	if (leaderStrIt != endIt)
  +	{
  +		theResult += *leaderStrIt;
  +	}
  +
  +	typedef XPathExecutionContext::GetAndReleaseCachedString	GetAndReleaseCachedString;
  +
  +	GetAndReleaseCachedString	theGuard2(executionContext);
  +
  +	XalanDOMString&				theIntermediateResult = theGuard2.get();
  +
  +	for(unsigned int i = 0; i < theListLength; i++)
  +	{
  +		if (it != trailerStrIt)
  +		{
  +			assert(isXMLLetterOrDigit(charAt(*it, 0)));
  +
  +			numberWidth = length(*it);
  +
  +			numberType = charAt(*it, numberWidth - 1);
  +
  +			++it;
   		}
  -		formattedNumber += getFormattedNumber(executionContext, contextNode,
  -				numberType, numberWidth, theList[i]);
  +
  +		if (it != trailerStrIt)
  +		{
  +			assert(!isXMLLetterOrDigit(charAt(*it, 0)));
  +
  +			sepStringIt = it;
  +
  +			++it;
  +		}
  +
  +		getFormattedNumber(
  +				executionContext,
  +				contextNode,
  +				numberType,
  +				numberWidth,
  +				theList[i],
  +				theIntermediateResult);
  +
  +		theResult += theIntermediateResult;
  +
   		// All but the last one
  -		if (i < nNumbers-1)
  -			formattedNumber += sepString;
  +		if (i < theListLength - 1)
  +		{
  +			if (sepStringIt != endIt)
  +			{
  +				theResult += *sepStringIt;
  +			}
  +			else
  +			{
  +				theResult += s_defaultSeparatorString;
  +			}
  +
  +			clear(theIntermediateResult);
  +		}
   	}
  -	formattedNumber += trailerStr;
   
  -	return formattedNumber;  
  +	if (trailerStrIt != endIt)
  +	{
  +		theResult += *trailerStrIt;
  +	}
   }
   
   
  @@ -790,16 +944,19 @@
   
   
   
  -XalanDOMString
  +void
   ElemNumber::traditionalAlphaCount(
   			int										theValue,
  -			const XalanNumberingResourceBundle&		theResourceBundle) const
  +			const XalanNumberingResourceBundle&		theResourceBundle,
  +			XalanDOMString&							theResult) const
   {
   	typedef XalanNumberingResourceBundle::IntVectorType			IntVectorType;
   	typedef XalanNumberingResourceBundle::DigitsTableVectorType	DigitsTableVectorType;
   	typedef XalanNumberingResourceBundle::eNumberingMethod		eNumberingMethod;
   	typedef XalanNumberingResourceBundle::eMultiplierOrder		eMultiplierOrder;
   
  +	bool	fError = false;
  +
   	// if this number is larger than the largest number we can represent, error!
   	//if (val > theResourceBundle.getMaxNumericalValue())
   	//return XSLTErrorResources.ERROR_STRING;
  @@ -809,7 +966,7 @@
   	IntVectorType::size_type	lookupIndex = 1;  // start off with anything other than zero to make correction work
   
   	// Create a buffer to hold the result
  -	// TODO:  size of the table can be detereined by computing
  +	// TODO:  size of the table can be determined by computing
   	// logs of the radix.  For now, we fake it.
   	XalanDOMChar	buf[100];
   
  @@ -954,17 +1111,19 @@
   								}
   								else
   								{
  -									buf[charPos++] =  table[lookupIndex];
  +									buf[charPos++] = table[lookupIndex];
   								}
   
  -								buf[charPos++] =	multiplierChar ;
  +								buf[charPos++] = multiplierChar;
   							}
   
   							break;		 // all done!
   						}
   						else
   						{
  -							return XALAN_STATIC_UCODE_STRING("#error");
  +							fError = true;
  +
  +							break;
   						}
   					} //end else
   				} // end while	
  @@ -973,11 +1132,10 @@
   
   			} // end else if
   		} // end do while
  -		while ( i < multiplierSize);		
  +		while (i < multiplierSize && fError == false);		
   	}
   
   	// Now do additive part...
  -
   	IntVectorType::size_type	count = 0;
   
   	// do this for each table of hundreds, tens, digits...
  @@ -1027,15 +1185,23 @@
   			}
   			else
   			{
  -				return XALAN_STATIC_UCODE_STRING("#error");
  +				fError = true;
  +
  +				break;
   			}
   
   			count++;
   		}
   	} // end while
   
  -	// String s = new String(buf, 0, charPos);
  -	return XalanDOMString(buf, charPos);
  +	if (fError == true)
  +	{
  +		theResult = XALAN_STATIC_UCODE_STRING("#error");
  +	}
  +	else
  +	{
  +		assign(theResult, buf, charPos);
  +	}
   }
   
   
  @@ -1044,30 +1210,35 @@
   
   
   
  -XalanDOMString
  +void
   ElemNumber::getFormattedNumber(
   			StylesheetExecutionContext&		executionContext,
   			XalanNode*						contextNode,
   			XalanDOMChar					numberType,
   			int								numberWidth,
  -			int								listElement) const
  +			int								listElement,
  +			XalanDOMString&					theResult) const
   {
   	switch(numberType)
   	{
   		case XalanUnicode::charLetter_A:
  -			return int2alphaCount(listElement, s_alphaCountTable);
  +			int2alphaCount(listElement, s_alphaCountTable, theResult);
   			break;
   
   		case XalanUnicode::charLetter_a:
  -			return toLowerCase(int2alphaCount(listElement, s_alphaCountTable));
  +			int2alphaCount(listElement, s_alphaCountTable, theResult);
  +
  +			theResult = toLowerCase(theResult);
   			break;
   
   		case XalanUnicode::charLetter_I:
  -			return long2roman(listElement, true);
  +			long2roman(listElement, true, theResult);
   			break;
   
   		case XalanUnicode::charLetter_i:
  -			return toLowerCase(long2roman(listElement, true));
  +			long2roman(listElement, true, theResult);
  +
  +			theResult = toLowerCase(theResult);
   			break;
   
   		case 0x3042:
  @@ -1081,7 +1252,6 @@
   		case 0x10D0:
   		case 0x0430:
   			executionContext.error(LongToDOMString(numberType) + " format not supported yet!");
  -			return XalanDOMString();
   			break;
   
   		// Handle the special case of Greek letters for now
  @@ -1091,17 +1261,13 @@
   				NumberingResourceBundleMapType::const_iterator	i = s_resourceBundles.find(0x03B1);
   
   				if (i != s_resourceBundles.end())
  -				{
  -					return traditionalAlphaCount(listElement, (*i).second);
  -				}
  -				else
   				{
  -					return XalanDOMString();
  +					traditionalAlphaCount(listElement, (*i).second, theResult);
   				}
   			}
   			else
   			{
  -				return int2alphaCount(listElement, s_elalphaCountTable);
  +				int2alphaCount(listElement, s_elalphaCountTable, theResult);
   			}
   			break;
   
  @@ -1110,10 +1276,9 @@
   				StylesheetExecutionContext::XalanNumberFormatAutoPtr	formatter(
   						getNumberFormatter(executionContext, contextNode));
   
  -				XalanDOMString	numString =
  -					formatter->format(listElement);
  +				formatter->format(listElement, theResult);
   
  -				const unsigned int	lengthNumString = length(numString);
  +				const unsigned int	lengthNumString = length(theResult);
   
   				const int	nPadding = numberWidth - lengthNumString;
   
  @@ -1121,15 +1286,13 @@
   				{
   					const XalanDOMString	padString = formatter->format(0);
   
  -					reserve(numString, nPadding * length(padString) + lengthNumString + 1);
  +					reserve(theResult, nPadding * length(padString) + lengthNumString + 1);
   
   					for(int i = 0; i < nPadding; i++)
   					{
  -						insert(numString, 0, padString);
  +						insert(theResult, 0, padString);
   					}
   				}
  -
  -				return numString;
   			}
   			break;
   	}
  @@ -1137,17 +1300,18 @@
   
   
   
  -XalanDOMString
  +void
   ElemNumber::int2singlealphaCount(
   		int						val, 
  -		const XalanDOMString&	table)
  +		const XalanDOMString&	table,
  +		XalanDOMString&			theResult)
   {
   	const int		radix = length(table);
   
   	// TODO:  throw error on out of range input
   	if (val > radix)
   	{
  -		return XalanDOMString(XALAN_STATIC_UCODE_STRING("#E(") +
  +		theResult = XalanDOMString(XALAN_STATIC_UCODE_STRING("#E(") +
   				LongToDOMString(val) +
   				XALAN_STATIC_UCODE_STRING(")"));
   	}
  @@ -1155,16 +1319,17 @@
   	{
   		const XalanDOMChar	theChar = charAt(table, val - 1);
   
  -		return XalanDOMString(&theChar, 1);
  +		assign(theResult, &theChar, 1);
   	}
   }
   
   
   
  -XalanDOMString
  +void
   ElemNumber::int2alphaCount(
   			int						val,
  -			const XalanDOMString&	table)
  +			const XalanDOMString&	table,
  +			XalanDOMString&			theResult)
   {
   	const int		radix = length(table);
   
  @@ -1234,157 +1399,188 @@
   	}
   	while (val > 0);
   
  -	const XalanDOMString	retStr(buf + charPos + 1, (buflen - charPos - 1));
  -
  -	return retStr;
  +	assign(theResult, buf + charPos + 1, buflen - charPos - 1);
   }
  +
   
  -XalanDOMString ElemNumber::tradAlphaCount(int	/* val */)
  +
  +void
  +ElemNumber::tradAlphaCount(
  +			int					/* val */,
  +			XalanDOMString&		/* theResult */)
   {
   //	@@ JMD: We don't do languages yet, so this is just a placeholder
  -	assert(0);
  -	return XalanDOMString();	// To keep compiler happy
  +	assert(false);
   }
   
   
  -XalanDOMString
  +
  +void
   ElemNumber::long2roman(
  -			long	val,
  -			bool	prefixesAreOK)
  +			long				val,
  +			bool				prefixesAreOK,
  +			XalanDOMString&		theResult)
   {
   	if(val < 0)
   	{
  -		return XalanDOMString(XALAN_STATIC_UCODE_STRING("#E(") +
  +		theResult = XalanDOMString(XALAN_STATIC_UCODE_STRING("#E(") +
   								LongToDOMString(val) +
   								XALAN_STATIC_UCODE_STRING(")"));
   	}
  -	// Make this match the conformance test
   	else if(val == 0)
   	{
  -		return XalanDOMString(XALAN_STATIC_UCODE_STRING("0"));
  +		theResult = XALAN_STATIC_UCODE_STRING("0");
   	}
  -
  -
  -	XalanDOMString	roman;
  +	else if (val <= 3999L)
  +	{
  +		clear(theResult);
   
  -	int			place = 0;
  +		int	place = 0;
   
  -	if (val <= 3999L)
  -	{
   		do      
   		{
  -			while (val >= s_romanConvertTable[place].m_postValue)            
  +			while (val >= s_romanConvertTable[place].m_postValue)
   			{
  -				roman += s_romanConvertTable[place].m_postLetter;
  +				theResult += s_romanConvertTable[place].m_postLetter;
   				val -= s_romanConvertTable[place].m_postValue;
   			}
  -			if (prefixesAreOK)            
  +
  +			if (prefixesAreOK)
   			{
  -				if (val >= s_romanConvertTable[place].m_preValue)                  
  +				if (val >= s_romanConvertTable[place].m_preValue)
   				{
  -					roman += s_romanConvertTable[place].m_preLetter;
  +					theResult += s_romanConvertTable[place].m_preLetter;
   					val -= s_romanConvertTable[place].m_preValue;
   				}
   			} 
  -			place++;      
  +
  +			++place;      
   		}
   		while (val > 0);
   	}
   	else
   	{
  -		roman = XALAN_STATIC_UCODE_STRING("#error");
  +		theResult = XALAN_STATIC_UCODE_STRING("#error");
   	}
  -
  -	return roman;
   }
   
   
  -/*
  - *				NumberFormatStringTokenizer Class Implementation
  - */
   
   ElemNumber::NumberFormatStringTokenizer::NumberFormatStringTokenizer(
  -			const XalanDOMString&	theStr) :
  +			const XalanDOMString&	theString) :
   	m_currentPosition(0),
  -	m_maxPosition(length(theStr)),
  -	m_str(theStr)
  +	m_maxPosition(length(theString)),
  +	m_string(&theString)
   {
   }
   
   
   
  -/*
  -@@ Obsolete ??
   void
   ElemNumber::NumberFormatStringTokenizer::setString(const XalanDOMString&	theString)
   {
  -	m_str = theString;
  +	m_string = &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) 
  +	{
  +		return XalanDOMString();
  +	}
  +
  +	const unsigned int	start = m_currentPosition;
  +
  +	if (isXMLLetterOrDigit(charAt(*m_string, m_currentPosition)))
  +	{
  +		while (m_currentPosition < m_maxPosition &&
  +			   isXMLLetterOrDigit(charAt(*m_string, m_currentPosition)))
  +		{
  +			m_currentPosition++;
  +		}
  +	}
  +	else
  +	{
  +		while (m_currentPosition < m_maxPosition &&
  +			   !isXMLLetterOrDigit(charAt(*m_string, m_currentPosition)))
  +		{
  +			m_currentPosition++;
  +		}
  +	}
  +
  +	return substring(*m_string, start, m_currentPosition);
  +}
  +
  +
  +
  +void
  +ElemNumber::NumberFormatStringTokenizer::nextToken(XalanDOMString&	theToken)
  +{
  +	if (m_currentPosition >= m_maxPosition) 
   	{
  -		// $$$ Todo: Implement!
  -//				throw new NoSuchElementException();
  +		clear(theToken);
   	}
   
  -	const int	start = m_currentPosition;
  +	const unsigned int	start = m_currentPosition;
   
  -	if (isXMLLetterOrDigit(charAt(m_str, m_currentPosition)))
  +	if (isXMLLetterOrDigit(charAt(*m_string, m_currentPosition)))
   	{
  -		while ((m_currentPosition < m_maxPosition) &&
  -				isXMLLetterOrDigit(charAt(m_str, m_currentPosition))) 
  +		while (m_currentPosition < m_maxPosition &&
  +			   isXMLLetterOrDigit(charAt(*m_string, m_currentPosition)))
  +		{
   			m_currentPosition++;
  +		}
   	}
   	else
   	{
  -		while ((m_currentPosition < m_maxPosition) &&
  -				!isXMLLetterOrDigit(charAt(m_str, m_currentPosition))) 
  +		while (m_currentPosition < m_maxPosition &&
  +			   !isXMLLetterOrDigit(charAt(*m_string, 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);
  +	substring(*m_string, theToken, start, m_currentPosition);
   }
   
   
   
  -int
  +unsigned int
   ElemNumber::NumberFormatStringTokenizer::countTokens() const
   {
  -	int 	count = 0;
  -	int 	currpos = m_currentPosition;
  +	unsigned int 	count = 0;
  +	unsigned int 	currpos = m_currentPosition;
   
   	// Tokens consist of sequences of alphabetic characters and sequences of
   	// non-alphabetic characters
   	while (currpos < m_maxPosition) 
   	{
  -		if (isXMLLetterOrDigit(charAt(m_str, currpos)))
  +		if (isXMLLetterOrDigit(charAt(*m_string, currpos)))
   		{
  -			while ((currpos < m_maxPosition) &&
  -					isXMLLetterOrDigit(charAt(m_str, currpos))) 
  +			while (currpos < m_maxPosition &&
  +				   isXMLLetterOrDigit(charAt(*m_string, currpos)))
  +			{
   				currpos++;
  +			}
   		}
   		else
   		{
  -			while ((currpos < m_maxPosition) &&
  -					!isXMLLetterOrDigit(charAt(m_str, currpos))) 
  +			while (currpos < m_maxPosition &&
  +				   !isXMLLetterOrDigit(charAt(*m_string, currpos)))
  +			{
   				currpos++;
  +			}
   		}
  +
   		count++;
   	}
  +
   	return count;
   }
   
  @@ -1471,6 +1667,8 @@
   
   static XalanDOMString								s_oneString;
   
  +static XalanDOMString								s_defaultSeparatorString;
  +
   static XalanDOMString								s_alphaCountTable;
   
   static XalanDOMString								s_elalphaCountTable;
  @@ -1498,6 +1696,8 @@
   
   const XalanDOMString&	ElemNumber::s_oneString = ::s_oneString;
   
  +const XalanDOMString&	ElemNumber::s_defaultSeparatorString = ::s_defaultSeparatorString;
  +
   const XalanDOMString&	ElemNumber::s_alphaCountTable = ::s_alphaCountTable;
   
   const XalanDOMString&	ElemNumber::s_elalphaCountTable = ::s_elalphaCountTable;
  @@ -1634,6 +1834,8 @@
   
   	::s_oneString = XALAN_STATIC_UCODE_STRING("1");
   
  +	::s_defaultSeparatorString = XALAN_STATIC_UCODE_STRING(".");
  +
   	::s_alphaCountTable = alphaCountTable;
   
   	::s_elalphaCountTable = elalphaCountTable;
  @@ -1705,6 +1907,7 @@
   	releaseMemory(::s_leftParenString);
   	releaseMemory(::s_dotString);
   	releaseMemory(::s_oneString);
  +	releaseMemory(::s_defaultSeparatorString);
   
   	releaseMemory(::s_alphaCountTable);
   	releaseMemory(::s_elalphaCountTable);
  
  
  
  1.29      +136 -102  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.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- ElemNumber.hpp	2001/03/09 16:19:59	1.28
  +++ ElemNumber.hpp	2001/06/14 19:17:25	1.29
  @@ -57,14 +57,8 @@
   #if !defined(XALAN_ELEMNUMBER_HEADER_GUARD)
   #define XALAN_ELEMNUMBER_HEADER_GUARD 
   
  -/**
  - * $Id: ElemNumber.hpp,v 1.28 2001/03/09 16:19:59 auriemma Exp $
  - * 
  - * $State: Exp $
  - * 
  - * @author Myriam Midy (Myriam_Midy @lotus.com 
  - */
   
  +
   // Base include file.  Must be first.
   #include <XSLT/XSLTDefinitions.hpp>
   
  @@ -85,6 +79,7 @@
   
   
   class AVT;
  +class CountersTable;
   class QName;
   class XalanNumberFormat;
   class XPath;
  @@ -96,7 +91,7 @@
   {
   private:
   
  -struct Counter;
  +	struct Counter;
   
   public:
   
  @@ -214,8 +209,20 @@
   	 * Given an XML source node, get the count according to the 
   	 * parameters set up by the xsl:number attributes.
   	 */
  -	XalanDOMString
  -	getCountString(StylesheetExecutionContext&		executionContext) const;
  +	void
  +	getCountString(
  +			StylesheetExecutionContext&		executionContext,
  +			XalanDOMString&					theResult) const;
  +
  +	void
  +	getCountString(
  +			StylesheetExecutionContext&		executionContext,
  +			XalanNode*						sourceNode,
  +			const MutableNodeRefList&		ancestors,
  +			CountersTable&					ctable,
  +			int								numberList[],
  +			unsigned int					numberListLength,
  +			XalanDOMString&					theResult) const;
   
   	/**
   	 * Get the ancestors, up to the root, that match the
  @@ -223,12 +230,15 @@
   	 * @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.
  +	 * @param stopAtFirstFound If true, only get the first matching ancestor
  +	 * @param ancestors The ancestors that match the pattern.
   	 */
  -	MutableNodeRefList getMatchingAncestors(
  +	void
  +	getMatchingAncestors(
   			StylesheetExecutionContext&		executionContext,
   			XalanNode*						node, 
  -			bool							stopAtFirstFound) const;
  +			bool							stopAtFirstFound,
  +			MutableNodeRefList&				ancestors) const;
   
   	/**
   	 * Get a formatter.
  @@ -242,50 +252,55 @@
   			XalanNode*						contextNode) const;
   
   	/**
  -	 * Format a vector of numbers into a formatted string.
  +	 * Format an array of integers into a formatted string.
  +	 *
   	 * @param executionContext The current execution context.
  -	 * @param xslNumberElement Element that takes %conversion-atts; attributes.
  -	 * @param list Array of one or more integer numbers.
  -	 * @return String that represents list according to 
  -	 * %conversion-atts; attributes.
  -	 * TODO: Optimize formatNumberList so that it caches the last count and
  -	 * reuses that info for the next count.
  +	 * @param theList Array of one or more integer numbers.
  +	 * @param theListLength The length of the array.
  +	 * @param contextNode The context node.
  +	 * @param formattedNumber The formatted number result.
   	 */
  -	XalanDOMString
  +	void
   	formatNumberList(	
   			StylesheetExecutionContext&		executionContext,
  -			const IntArrayType&				theList,
  -			XalanNode*						contextNode) const;
  +			const int						theList[],
  +			unsigned int					theListLength,
  +			XalanNode*						contextNode,
  +			XalanDOMString&					formattedNumber) 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.
  +	 * @param theResult A 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);
  +	static void
  +	int2singlealphaCount(
  +			int						val,
  +			const XalanDOMString&	table,
  +			XalanDOMString&			theResult);
   		
   	/**
   	 * 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.
  +	 * @param result returns the stringrepresenting alpha count of number.
   	 * @see XSLTEngineImpl#DecimalToRoman
   	 * 
   	 * Note that the radix of the conversion is inferred from the size
   	 * of the table.
   	 */
  -	static XalanDOMString
  +	static void
   	int2alphaCount(
   			int						val,
  -			const XalanDOMString&	table);
  +			const XalanDOMString&	table,
  +			XalanDOMString&			theResult);
   
   	/**
   	 * Convert a long integer into traditional alphabetic counting, in other words
  @@ -298,22 +313,24 @@
   	 * Note that the radix of the conversion is inferred from the size
   	 * of the table.
   	 */
  -	static XalanDOMString
  -	tradAlphaCount(int val);
  +	static void
  +	tradAlphaCount(
  +			int					val,
  +			XalanDOMString&		theResult);
   
   	/**
   	 * Convert a long integer into roman numerals.
   	 * @param val Value to convert.
  -	 * @param prefixesAreOK true_ to enable prefix notation (e.g. 4 = "IV"),
  -	 * false_ to disable prefix notation (e.g. 4 = "IIII").
  -	 * @return Roman numeral string.
  +	 * @param prefixesAreOK true to enable prefix notation (e.g. 4 = "IV"), false to disable prefix notation (e.g. 4 = "IIII").
  +	 * @param theResult The formatted Roman numeral string.
   	 * @see DecimalToRoman
   	 * @see m_romanConvertTable
   	 */
  -	static XalanDOMString
  +	static void
   	long2roman(
  -			long	val,
  -			bool	prefixesAreOK);
  +			long				val,
  +			bool				prefixesAreOK,
  +			XalanDOMString&		theResult);
   
   private:
   
  @@ -323,21 +340,23 @@
   			XalanNode* 						contextNode,
   			const XalanDOMString&			compareValue) const;
   
  -	XalanDOMString
  +	void
   	traditionalAlphaCount(
   			int										theValue,
  -			const XalanNumberingResourceBundle&		theResourceBundle) const;
  +			const XalanNumberingResourceBundle&		theResourceBundle,
  +			XalanDOMString&							theResult) const;
   
   	/*
   	 * Get Formatted number
   	 */
  -	XalanDOMString 
  +	void
   	getFormattedNumber(
   			StylesheetExecutionContext&		executionContext,
   			XalanNode*						contextNode,
   			XalanDOMChar					numberType,
   			int								numberWidth,
  -			int								listElement) const;
  +			int								listElement,
  +			XalanDOMString&					theResult) const;
   
   	const XPath*	m_countMatchPattern;
   	const XPath*	m_fromMatchPattern;
  @@ -392,6 +411,11 @@
    	static const XalanDOMString&			s_oneString;
   
   	/**
  + 	 * The string ".".
  + 	 */
  + 	static const XalanDOMString&			s_defaultSeparatorString;
  +
  +	/**
   	* Chars for converting integers into alpha counts.
   	* @see XSLTEngineImpl#int2alphaCount
   	*/
  @@ -418,68 +442,78 @@
   	 */
   	class NumberFormatStringTokenizer
   	{
  -		public:
  +	public:
  +
  +		/**
  +		 * Construct a NumberFormatStringTokenizer.
  +		 *
  +		 * @param theString string to tokenize
  +		 */
  +		NumberFormatStringTokenizer(const XalanDOMString&	theString);
  +
  +		/**
  +		 * Sets the string to tokenize.
  +		 *
  +		 * @param theString  new string to tokenize
  +		 */
  +		void
  +		setString(const XalanDOMString&	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
  +		 */
  +		XalanDOMString
  +		nextToken();
  +
  +		/**
  +		 * Retrieve the next token to be parsed.
  +		 * 
  +		 * @param theToken The next token string
  +		 */
  +		void
  +		nextToken(XalanDOMString&	theToken);
  +
  +		/**
  +		 * 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
  +		 */
  +		unsigned int
  +		countTokens() const;
  +
  +	private:
  +
  +		unsigned int			m_currentPosition;
  +
  +		unsigned int			m_maxPosition;
  +
  +		const XalanDOMString*	m_string;
  +	};
  +};
   
  -			/**
  -			 * Construct a NumberFormatStringTokenizer.
  -			 *
  -			 * @param theStr string to tokenize
  -			 */
  -			explicit
  -				NumberFormatStringTokenizer(const XalanDOMString&	theStr = XalanDOMString());
  -
  -			/**
  -			 * Sets the string to tokenize.
  -			 *
  -			 * @param theString  new string to tokenize
  -			 */
  -			void
  -				setString(const XalanDOMString&	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
  -			 */
  -			XalanDOMString
  -				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;
  -			XalanDOMString	m_str;
  -	}; // end NumberFormatStringTokenizer
   
  -}; // end ElemNumber
   
   #endif	// XALAN_ELEMNUMBER_HEADER_GUARD
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org