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