зеркало из https://github.com/mozilla/pjs.git
Bug 94036: Rewrite implementation of xsl:number. Also implement errorhandling for txList and NS_ConvertASCIItoUCS2 for standalone.
r=Pike sr=jst
This commit is contained in:
Родитель
2fb2f5a3a7
Коммит
78bde3fdf9
|
@ -62,6 +62,19 @@ typedef PRUint32 nsresult;
|
|||
#define NS_ERROR_ILLEGAL_VALUE ((nsresult) 0x80070057L)
|
||||
#define NS_ERROR_INVALID_ARG NS_ERROR_ILLEGAL_VALUE
|
||||
|
||||
#define NS_ENSURE_TRUE(value, result) \
|
||||
do { \
|
||||
if (!(value)) { \
|
||||
return (result); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define NS_ENSURE_FALSE(value, result) \
|
||||
NS_ENSURE_TRUE(!(value), result)
|
||||
|
||||
#define NS_ENSURE_SUCCESS(value, result) \
|
||||
NS_ENSURE_TRUE(NS_SUCCEEDED(value), result)
|
||||
|
||||
#else // TX_EXE
|
||||
|
||||
#include "nsError.h"
|
||||
|
|
|
@ -51,30 +51,24 @@ txList::txList() {
|
|||
* references
|
||||
*/
|
||||
txList::~txList() {
|
||||
ListItem* item = firstItem;
|
||||
while (item) {
|
||||
ListItem* tItem = item;
|
||||
item = item->nextItem;
|
||||
delete tItem;
|
||||
}
|
||||
clear();
|
||||
} //-- ~txList
|
||||
|
||||
void txList::insert(int index, void* objPtr) {
|
||||
|
||||
nsresult txList::insert(int index, void* objPtr)
|
||||
{
|
||||
if (index >= itemCount) {
|
||||
insertBefore(objPtr, 0);
|
||||
}
|
||||
else {
|
||||
//-- add to middle of list
|
||||
ListItem* nextItem = firstItem;
|
||||
for (int i = 0; i < index; i++)
|
||||
nextItem = nextItem->nextItem;
|
||||
insertBefore(objPtr, nextItem);
|
||||
return insertBefore(objPtr, 0);
|
||||
}
|
||||
// add inside the list
|
||||
ListItem* nextItem = firstItem;
|
||||
for (int i = 0; i < index; i++)
|
||||
nextItem = nextItem->nextItem;
|
||||
return insertBefore(objPtr, nextItem);
|
||||
} //-- insert
|
||||
|
||||
void txList::add(void* objPtr) {
|
||||
insertBefore(objPtr, 0);
|
||||
nsresult txList::add(void* objPtr)
|
||||
{
|
||||
return insertBefore(objPtr, 0);
|
||||
} //-- add
|
||||
|
||||
/**
|
||||
|
@ -126,12 +120,12 @@ PRInt32 List::getLength() {
|
|||
* This method assumes refItem is a member of this list, and since this
|
||||
* is a private method, I feel that's a valid assumption
|
||||
**/
|
||||
void txList::insertAfter(void* objPtr, ListItem* refItem) {
|
||||
nsresult txList::insertAfter(void* objPtr, ListItem* refItem)
|
||||
{
|
||||
//-- if refItem == null insert at front
|
||||
if (!refItem)
|
||||
insertBefore(objPtr, firstItem);
|
||||
else
|
||||
insertBefore(objPtr, refItem->nextItem);
|
||||
return insertBefore(objPtr, firstItem);
|
||||
return insertBefore(objPtr, refItem->nextItem);
|
||||
} //-- insertAfter
|
||||
|
||||
/**
|
||||
|
@ -141,11 +135,10 @@ void txList::insertAfter(void* objPtr, ListItem* refItem) {
|
|||
* This method assumes refItem is a member of this list, and since this
|
||||
* is a private method, I feel that's a valid assumption
|
||||
**/
|
||||
void txList::insertBefore(void* objPtr, ListItem* refItem) {
|
||||
|
||||
nsresult txList::insertBefore(void* objPtr, ListItem* refItem)
|
||||
{
|
||||
ListItem* item = new ListItem;
|
||||
if (!item)
|
||||
return;
|
||||
NS_ENSURE_TRUE(item, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
item->objPtr = objPtr;
|
||||
item->nextItem = 0;
|
||||
|
@ -176,6 +169,8 @@ void txList::insertBefore(void* objPtr, ListItem* refItem) {
|
|||
|
||||
// increase the item count
|
||||
++itemCount;
|
||||
|
||||
return NS_OK;
|
||||
} //-- insertBefore
|
||||
|
||||
void* txList::remove(void* objPtr) {
|
||||
|
@ -217,6 +212,19 @@ txList::ListItem* txList::remove(ListItem* item) {
|
|||
return item;
|
||||
} //-- remove
|
||||
|
||||
void txList::clear()
|
||||
{
|
||||
ListItem* item = firstItem;
|
||||
while (item) {
|
||||
ListItem* tItem = item;
|
||||
item = item->nextItem;
|
||||
delete tItem;
|
||||
}
|
||||
firstItem = 0;
|
||||
lastItem = 0;
|
||||
itemCount = 0;
|
||||
}
|
||||
|
||||
//------------------------------------/
|
||||
//- Implementation of txListIterator -/
|
||||
//------------------------------------/
|
||||
|
@ -242,12 +250,11 @@ txListIterator::~txListIterator() {
|
|||
* based on the current position within the txList
|
||||
* @param objPtr the Object pointer to add to the list
|
||||
**/
|
||||
void txListIterator::addAfter(void* objPtr) {
|
||||
|
||||
nsresult txListIterator::addAfter(void* objPtr)
|
||||
{
|
||||
if (currentItem || !atEndOfList)
|
||||
list->insertAfter(objPtr, currentItem);
|
||||
else
|
||||
list->insertBefore(objPtr, 0);
|
||||
return list->insertAfter(objPtr, currentItem);
|
||||
return list->insertBefore(objPtr, 0);
|
||||
|
||||
} //-- addAfter
|
||||
|
||||
|
@ -257,12 +264,11 @@ void txListIterator::addAfter(void* objPtr) {
|
|||
* based on the current position within the txList
|
||||
* @param objPtr the Object pointer to add to the list
|
||||
**/
|
||||
void txListIterator::addBefore(void* objPtr) {
|
||||
|
||||
nsresult txListIterator::addBefore(void* objPtr)
|
||||
{
|
||||
if (currentItem || atEndOfList)
|
||||
list->insertBefore(objPtr, currentItem);
|
||||
else
|
||||
list->insertAfter(objPtr, 0);
|
||||
return list->insertBefore(objPtr, currentItem);
|
||||
return list->insertAfter(objPtr, 0);
|
||||
|
||||
} //-- addBefore
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "baseutils.h"
|
||||
#include "TxObject.h"
|
||||
#include "txError.h"
|
||||
|
||||
class txListIterator;
|
||||
|
||||
|
@ -69,18 +70,23 @@ public:
|
|||
/**
|
||||
* Adds the given Object to the specified position in the list
|
||||
**/
|
||||
void insert(int index, void* objPtr);
|
||||
nsresult insert(int index, void* objPtr);
|
||||
|
||||
/**
|
||||
* Adds the given Object to the list
|
||||
**/
|
||||
void add(void* objPtr);
|
||||
nsresult add(void* objPtr);
|
||||
|
||||
/**
|
||||
* Removes the given Object pointer from the list
|
||||
**/
|
||||
void* remove(void* objPtr);
|
||||
|
||||
/*
|
||||
* Removes all the objects from the list
|
||||
*/
|
||||
void clear();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -104,9 +110,8 @@ private:
|
|||
ListItem* lastItem;
|
||||
PRInt32 itemCount;
|
||||
|
||||
void insertAfter(void* objPtr, ListItem* sItem);
|
||||
void insertBefore(void* objPtr, ListItem* sItem);
|
||||
|
||||
nsresult insertAfter(void* objPtr, ListItem* sItem);
|
||||
nsresult insertBefore(void* objPtr, ListItem* sItem);
|
||||
};
|
||||
|
||||
|
||||
|
@ -134,7 +139,7 @@ public:
|
|||
* based on the current position within the txList
|
||||
* @param objPtr the Object pointer to add to the list
|
||||
**/
|
||||
void addAfter(void* objPtr);
|
||||
nsresult addAfter(void* objPtr);
|
||||
|
||||
/**
|
||||
* Adds the Object pointer to the txList pointed to by this txListIterator.
|
||||
|
@ -142,7 +147,7 @@ public:
|
|||
* based on the current position within the txList
|
||||
* @param objPtr the Object pointer to add to the list
|
||||
**/
|
||||
void addBefore(void* objPtr);
|
||||
nsresult addBefore(void* objPtr);
|
||||
|
||||
/**
|
||||
* Returns true if a sucessful call to the next() method can be made
|
||||
|
|
|
@ -97,7 +97,6 @@ OBJS =../base/ArrayList.$(OBJ_SUFFIX) \
|
|||
../xml/parser/XMLParser.$(OBJ_SUFFIX) \
|
||||
../xslt/txOutputFormat.$(OBJ_SUFFIX) \
|
||||
../xslt/Names.$(OBJ_SUFFIX) \
|
||||
../xslt/Numbering.$(OBJ_SUFFIX) \
|
||||
../xslt/ProcessorState.$(OBJ_SUFFIX) \
|
||||
../xslt/txHTMLOutput.$(OBJ_SUFFIX) \
|
||||
../xslt/txRtfHandler.$(OBJ_SUFFIX) \
|
||||
|
@ -105,6 +104,8 @@ OBJS =../base/ArrayList.$(OBJ_SUFFIX) \
|
|||
../xslt/txTextOutput.$(OBJ_SUFFIX) \
|
||||
../xslt/txUnknownHandler.$(OBJ_SUFFIX) \
|
||||
../xslt/txXMLOutput.$(OBJ_SUFFIX) \
|
||||
../xslt/txXSLTNumber.$(OBJ_SUFFIX) \
|
||||
../xslt/txXSLTNumberCounters.$(OBJ_SUFFIX) \
|
||||
../xslt/txXSLTPatterns.$(OBJ_SUFFIX) \
|
||||
../xslt/txPatternParser.$(OBJ_SUFFIX) \
|
||||
../xslt/XSLTProcessor.$(OBJ_SUFFIX) \
|
||||
|
|
|
@ -46,11 +46,12 @@ REQUIRES = string \
|
|||
endif
|
||||
|
||||
CPPSRCS = Names.cpp \
|
||||
Numbering.cpp \
|
||||
txOutputFormat.cpp \
|
||||
ProcessorState.cpp \
|
||||
txRtfHandler.cpp \
|
||||
txTextHandler.cpp \
|
||||
txXSLTNumber.cpp \
|
||||
txXSLTNumberCounters.cpp \
|
||||
txXSLTPatterns.cpp \
|
||||
txPatternParser.cpp \
|
||||
XSLTProcessor.cpp
|
||||
|
|
|
@ -88,6 +88,7 @@ TX_ATOM(encoding, "encoding");
|
|||
TX_ATOM(format, "format");
|
||||
TX_ATOM(from, "from");
|
||||
TX_ATOM(groupingSeparator, "grouping-separator");
|
||||
TX_ATOM(groupingSize, "grouping-size");
|
||||
TX_ATOM(href, "href");
|
||||
TX_ATOM(indent, "indent");
|
||||
TX_ATOM(infinity, "infinity");
|
||||
|
@ -129,3 +130,8 @@ TX_ATOM(systemProperty, "system-property");
|
|||
// XSLT properties
|
||||
TX_ATOM(vendor, "vendor");
|
||||
TX_ATOM(vendorUrl, "vendor-url");
|
||||
|
||||
// XSLT attribute values
|
||||
TX_ATOM(any, "any");
|
||||
TX_ATOM(multiple, "multiple");
|
||||
TX_ATOM(single, "single");
|
||||
|
|
|
@ -0,0 +1,784 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is TransforMiiX XSLT processor.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Jonas Sicking.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* Jonas Sicking. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <sicking@bigfoot.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "txXSLTNumber.h"
|
||||
#include "txAtoms.h"
|
||||
#include "primitives.h"
|
||||
#include <math.h>
|
||||
#include "Names.h"
|
||||
|
||||
nsresult txXSLTNumber::createNumber(Element* aNumberElement,
|
||||
ProcessorState* aPs,
|
||||
String& aResult)
|
||||
{
|
||||
aResult.clear();
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// Parse format
|
||||
txList counters;
|
||||
String head, tail;
|
||||
rv = getCounters(aNumberElement, aPs, counters, head, tail);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Create list of values to format
|
||||
txList values;
|
||||
String valueString;
|
||||
rv = getValueList(aNumberElement, aPs, values, valueString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (valueString.length()) {
|
||||
// XXX Xalan and XSLT2 says this, but XSLT1 says otherwise
|
||||
aResult = head;
|
||||
aResult.append(valueString);
|
||||
aResult.append(tail);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create resulting string
|
||||
aResult = head;
|
||||
MBool first = MB_TRUE;
|
||||
txListIterator valueIter(&values);
|
||||
txListIterator counterIter(&counters);
|
||||
valueIter.resetToEnd();
|
||||
PRInt32 value;
|
||||
txFormattedCounter* counter = 0;
|
||||
while ((value = NS_PTR_TO_INT32(valueIter.previous()))) {
|
||||
if (counterIter.hasNext()) {
|
||||
counter = (txFormattedCounter*)counterIter.next();
|
||||
}
|
||||
|
||||
if (!first) {
|
||||
aResult.append(counter->mSeparator);
|
||||
}
|
||||
|
||||
counter->appendNumber(value, aResult);
|
||||
first = MB_FALSE;
|
||||
}
|
||||
|
||||
aResult.append(tail);
|
||||
|
||||
txListIterator iter(&counters);
|
||||
while (iter.hasNext()) {
|
||||
delete (txFormattedCounter*)iter.next();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult txXSLTNumber::getValueList(Element* aNumberElement,
|
||||
ProcessorState* aPs, txList& aValues,
|
||||
String& aValueString)
|
||||
{
|
||||
aValueString.clear();
|
||||
|
||||
// If the value attribute exists then use that
|
||||
if (aNumberElement->hasAttr(txXSLTAtoms::value, kNameSpaceID_None)) {
|
||||
Expr* expr = aPs->getExpr(aNumberElement, ProcessorState::ValueAttr);
|
||||
NS_ENSURE_TRUE(expr, NS_ERROR_FAILURE);
|
||||
|
||||
ExprResult* result = expr->evaluate(aPs->getEvalContext());
|
||||
if (!result) {
|
||||
// XXX error reporting, evaluate failed
|
||||
delete expr;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
double value = result->numberValue();
|
||||
delete result;
|
||||
|
||||
if (Double::isInfinite(value) || Double::isNaN(value) ||
|
||||
value < 0.5) {
|
||||
Double::toString(value, aValueString);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aValues.add(NS_INT32_TO_PTR((PRInt32)floor(value + 0.5)));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// Otherwise use count/from/level
|
||||
|
||||
txPattern *countPattern = 0, *fromPattern = 0;
|
||||
MBool ownsCountPattern = MB_FALSE;
|
||||
Node* currNode = aPs->getEvalContext()->getContextNode();
|
||||
|
||||
// Parse count- and from-attributes
|
||||
|
||||
if (aNumberElement->hasAttr(txXSLTAtoms::count, kNameSpaceID_None)) {
|
||||
countPattern = aPs->getPattern(aNumberElement,
|
||||
ProcessorState::CountAttr);
|
||||
NS_ENSURE_TRUE(countPattern, NS_ERROR_FAILURE);
|
||||
}
|
||||
else {
|
||||
ownsCountPattern = MB_TRUE;
|
||||
txNodeTest* nodeTest = 0;
|
||||
switch (currNode->getNodeType()) {
|
||||
case Node::ELEMENT_NODE:
|
||||
{
|
||||
txAtom* localName = 0;
|
||||
currNode->getLocalName(&localName);
|
||||
nodeTest = new txNameTest(0, localName,
|
||||
currNode->getNamespaceID(),
|
||||
Node::ELEMENT_NODE);
|
||||
TX_IF_RELEASE_ATOM(localName);
|
||||
break;
|
||||
}
|
||||
case Node::TEXT_NODE:
|
||||
case Node::CDATA_SECTION_NODE:
|
||||
{
|
||||
nodeTest = new txNodeTypeTest(txNodeTypeTest::TEXT_TYPE);
|
||||
break;
|
||||
}
|
||||
case Node::PROCESSING_INSTRUCTION_NODE:
|
||||
{
|
||||
txNodeTypeTest* typeTest;
|
||||
typeTest = new txNodeTypeTest(txNodeTypeTest::PI_TYPE);
|
||||
if (typeTest)
|
||||
typeTest->setNodeName(currNode->getNodeName());
|
||||
nodeTest = typeTest;
|
||||
break;
|
||||
}
|
||||
case Node::COMMENT_NODE:
|
||||
{
|
||||
nodeTest = new txNodeTypeTest(txNodeTypeTest::COMMENT_TYPE);
|
||||
break;
|
||||
}
|
||||
case Node::DOCUMENT_NODE:
|
||||
case Node::ATTRIBUTE_NODE:
|
||||
default:
|
||||
{
|
||||
// this won't match anything as we walk up the tree
|
||||
// but it's what the spec says to do
|
||||
nodeTest = new txNameTest(0, txXPathAtoms::_asterix, 0,
|
||||
(Node::NodeType)currNode->getNodeType());
|
||||
break;
|
||||
}
|
||||
}
|
||||
NS_ENSURE_TRUE(nodeTest, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
countPattern = new txStepPattern(nodeTest, MB_FALSE);
|
||||
if (!countPattern) {
|
||||
// XXX error reporting
|
||||
delete nodeTest;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (aNumberElement->hasAttr(txXSLTAtoms::from, kNameSpaceID_None)) {
|
||||
fromPattern = aPs->getPattern(aNumberElement,
|
||||
ProcessorState::FromAttr);
|
||||
if (!fromPattern) {
|
||||
// XXX error reporting, parse failed
|
||||
if (ownsCountPattern) {
|
||||
delete countPattern;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Generate list of values depending on the value of the level-attribute
|
||||
|
||||
String levelStr;
|
||||
txAtom* level = 0;
|
||||
if (aNumberElement->getAttr(txXSLTAtoms::level, kNameSpaceID_None, levelStr)) {
|
||||
level = TX_GET_ATOM(levelStr);
|
||||
}
|
||||
|
||||
// level = "single"
|
||||
if (!level || level == txXSLTAtoms::single) {
|
||||
Node* node = currNode;
|
||||
while (node) {
|
||||
if (fromPattern && node != currNode &&
|
||||
fromPattern->matches(node, aPs)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (countPattern->matches(node, aPs)) {
|
||||
aValues.add(NS_INT32_TO_PTR(getSiblingCount(node, countPattern,
|
||||
aPs)));
|
||||
break;
|
||||
}
|
||||
|
||||
node = node->getXPathParent();
|
||||
}
|
||||
|
||||
// Spec says to only match ancestors that are decendants of the
|
||||
// ancestor that matches the from-pattern, so keep going to make
|
||||
// sure that there is an ancestor that does.
|
||||
if (fromPattern && aValues.getLength()) {
|
||||
node = node->getXPathParent();
|
||||
while (node) {
|
||||
if (fromPattern->matches(node, aPs)) {
|
||||
break;
|
||||
}
|
||||
|
||||
node = node->getXPathParent();
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
aValues.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
// level = "multiple"
|
||||
else if (level == txXSLTAtoms::multiple) {
|
||||
// find all ancestor-or-selfs that matches count until...
|
||||
Node* node = currNode;
|
||||
MBool matchedFrom = MB_FALSE;
|
||||
while (node) {
|
||||
if (fromPattern && node != currNode &&
|
||||
fromPattern->matches(node, aPs)) {
|
||||
//... we find one that matches from
|
||||
matchedFrom = MB_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (countPattern->matches(node, aPs)) {
|
||||
aValues.add(NS_INT32_TO_PTR(getSiblingCount(node, countPattern,
|
||||
aPs)));
|
||||
}
|
||||
|
||||
node = node->getXPathParent();
|
||||
}
|
||||
|
||||
// Spec says to only match ancestors that are decendants of the
|
||||
// ancestor that matches the from-pattern, so if none did then
|
||||
// we shouldn't search anything
|
||||
if (fromPattern && !matchedFrom) {
|
||||
aValues.clear();
|
||||
}
|
||||
}
|
||||
// level = "any"
|
||||
else if (level == txXSLTAtoms::any) {
|
||||
Node* node = currNode;
|
||||
PRInt32 value = 0;
|
||||
MBool matchedFrom = MB_FALSE;
|
||||
while (node) {
|
||||
if (fromPattern && node != currNode &&
|
||||
fromPattern->matches(node, aPs)) {
|
||||
matchedFrom = MB_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (countPattern->matches(node, aPs)) {
|
||||
++value;
|
||||
}
|
||||
|
||||
node = getPrevInDocumentOrder(node);
|
||||
}
|
||||
|
||||
// Spec says to only count nodes that follows the first node that
|
||||
// matches the from pattern. So so if none did then we shouldn't
|
||||
// count any
|
||||
if (fromPattern && !matchedFrom) {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
aValues.add(NS_INT32_TO_PTR(value));
|
||||
}
|
||||
}
|
||||
else {
|
||||
aPs->receiveError(String("unknown value for format attribute"),
|
||||
NS_ERROR_FAILURE);
|
||||
}
|
||||
|
||||
if (ownsCountPattern) {
|
||||
delete countPattern;
|
||||
}
|
||||
TX_IF_RELEASE_ATOM(level);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
txXSLTNumber::getCounters(Element* aNumberElement, ProcessorState* aPs,
|
||||
txList& aCounters, String& aHead, String& aTail)
|
||||
{
|
||||
aHead.clear();
|
||||
aTail.clear();
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
String groupSizeStrAVT, groupSeparatorAVT, groupSizeStr, groupSeparator;
|
||||
PRInt32 groupSize = 0;
|
||||
if (aNumberElement->getAttr(txXSLTAtoms::groupingSeparator,
|
||||
kNameSpaceID_None, groupSeparatorAVT) &&
|
||||
aNumberElement->getAttr(txXSLTAtoms::groupingSize,
|
||||
kNameSpaceID_None, groupSizeStrAVT)) {
|
||||
aPs->processAttrValueTemplate(groupSeparatorAVT, aNumberElement,
|
||||
groupSeparator);
|
||||
aPs->processAttrValueTemplate(groupSizeStrAVT, aNumberElement,
|
||||
groupSizeStr);
|
||||
double size = Double::toDouble(groupSizeStr);
|
||||
groupSize = (PRInt32)size;
|
||||
if ((double)groupSize != size) {
|
||||
groupSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
String formatAVT, format;
|
||||
if (aNumberElement->getAttr(txXSLTAtoms::format, kNameSpaceID_None,
|
||||
formatAVT)) {
|
||||
aPs->processAttrValueTemplate(formatAVT, aNumberElement, format);
|
||||
}
|
||||
PRUint32 formatLen = format.length();
|
||||
PRUint32 formatPos = 0;
|
||||
UNICODE_CHAR ch = 0;
|
||||
|
||||
// start with header
|
||||
while (formatPos < formatLen &&
|
||||
!isAlphaNumeric(ch = format.charAt(formatPos))) {
|
||||
aHead.append(ch);
|
||||
++formatPos;
|
||||
}
|
||||
|
||||
// If there are no formatting tokens we need to create a default one.
|
||||
if (formatPos == formatLen) {
|
||||
txFormattedCounter* defaultCounter;
|
||||
rv = txFormattedCounter::getCounterFor(String("1"), groupSize,
|
||||
groupSeparator, defaultCounter);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
defaultCounter->mSeparator = String(".");
|
||||
rv = aCounters.add(defaultCounter);
|
||||
if (NS_FAILED(rv)) {
|
||||
// XXX ErrorReport: out of memory
|
||||
delete defaultCounter;
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
while (formatPos < formatLen) {
|
||||
String sepToken;
|
||||
// parse separator token
|
||||
if (!aCounters.getLength()) {
|
||||
// Set the first counters separator to default value so that if
|
||||
// there is only one formatting token and we're formatting a
|
||||
// value-list longer then one we use the default separator. This
|
||||
// won't be used when formatting the first value anyway.
|
||||
sepToken = String(".");
|
||||
}
|
||||
else {
|
||||
while (formatPos < formatLen &&
|
||||
!isAlphaNumeric(ch = format.charAt(formatPos))) {
|
||||
sepToken.append(ch);
|
||||
++formatPos;
|
||||
}
|
||||
}
|
||||
|
||||
// if we're at the end of the string then the previous token was the tail
|
||||
if (formatPos == formatLen) {
|
||||
aTail = sepToken;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// parse formatting token
|
||||
String numToken;
|
||||
while (formatPos < formatLen &&
|
||||
isAlphaNumeric(ch = format.charAt(formatPos))) {
|
||||
numToken.append(ch);
|
||||
++formatPos;
|
||||
}
|
||||
|
||||
txFormattedCounter* counter = 0;
|
||||
rv = txFormattedCounter::getCounterFor(numToken, groupSize,
|
||||
groupSeparator, counter);
|
||||
if (NS_FAILED(rv)) {
|
||||
txListIterator iter(&aCounters);
|
||||
while (iter.hasNext()) {
|
||||
delete (txFormattedCounter*)iter.next();
|
||||
}
|
||||
aCounters.clear();
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Add to list of counters
|
||||
counter->mSeparator = sepToken;
|
||||
rv = aCounters.add(counter);
|
||||
if (NS_FAILED(rv)) {
|
||||
// XXX ErrorReport: out of memory
|
||||
txListIterator iter(&aCounters);
|
||||
while (iter.hasNext()) {
|
||||
delete (txFormattedCounter*)iter.next();
|
||||
}
|
||||
aCounters.clear();
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
txXSLTNumber::getSiblingCount(Node* aNode, txPattern* aCountPattern,
|
||||
txIMatchContext* aContext)
|
||||
{
|
||||
PRInt32 value = 1;
|
||||
Node* node = aNode->getPreviousSibling();
|
||||
|
||||
while (node) {
|
||||
if (aCountPattern->matches(node, aContext)) {
|
||||
++value;
|
||||
}
|
||||
node = node->getPreviousSibling();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
Node*
|
||||
txXSLTNumber::getPrevInDocumentOrder(Node* aNode)
|
||||
{
|
||||
Node* prev = aNode->getPreviousSibling();
|
||||
if (prev) {
|
||||
Node* lastChild = prev->getLastChild();
|
||||
while (lastChild) {
|
||||
prev = lastChild;
|
||||
lastChild = prev->getLastChild();
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
return aNode->getXPathParent();
|
||||
}
|
||||
|
||||
|
||||
#define TX_CHAR_RANGE(ch, a, b) if (ch < a) return MB_FALSE; \
|
||||
if (ch <= b) return MB_TRUE
|
||||
#define TX_MATCH_CHAR(ch, a) if (ch < a) return MB_FALSE; \
|
||||
if (ch == a) return MB_TRUE
|
||||
|
||||
MBool txXSLTNumber::isAlphaNumeric(UNICODE_CHAR ch)
|
||||
{
|
||||
TX_CHAR_RANGE(ch, 0x0030, 0x0039);
|
||||
TX_CHAR_RANGE(ch, 0x0041, 0x005A);
|
||||
TX_CHAR_RANGE(ch, 0x0061, 0x007A);
|
||||
TX_MATCH_CHAR(ch, 0x00AA);
|
||||
TX_CHAR_RANGE(ch, 0x00B2, 0x00B3);
|
||||
TX_MATCH_CHAR(ch, 0x00B5);
|
||||
TX_CHAR_RANGE(ch, 0x00B9, 0x00BA);
|
||||
TX_CHAR_RANGE(ch, 0x00BC, 0x00BE);
|
||||
TX_CHAR_RANGE(ch, 0x00C0, 0x00D6);
|
||||
TX_CHAR_RANGE(ch, 0x00D8, 0x00F6);
|
||||
TX_CHAR_RANGE(ch, 0x00F8, 0x021F);
|
||||
TX_CHAR_RANGE(ch, 0x0222, 0x0233);
|
||||
TX_CHAR_RANGE(ch, 0x0250, 0x02AD);
|
||||
TX_CHAR_RANGE(ch, 0x02B0, 0x02B8);
|
||||
TX_CHAR_RANGE(ch, 0x02BB, 0x02C1);
|
||||
TX_CHAR_RANGE(ch, 0x02D0, 0x02D1);
|
||||
TX_CHAR_RANGE(ch, 0x02E0, 0x02E4);
|
||||
TX_MATCH_CHAR(ch, 0x02EE);
|
||||
TX_MATCH_CHAR(ch, 0x037A);
|
||||
TX_MATCH_CHAR(ch, 0x0386);
|
||||
TX_CHAR_RANGE(ch, 0x0388, 0x038A);
|
||||
TX_MATCH_CHAR(ch, 0x038C);
|
||||
TX_CHAR_RANGE(ch, 0x038E, 0x03A1);
|
||||
TX_CHAR_RANGE(ch, 0x03A3, 0x03CE);
|
||||
TX_CHAR_RANGE(ch, 0x03D0, 0x03D7);
|
||||
TX_CHAR_RANGE(ch, 0x03DA, 0x03F3);
|
||||
TX_CHAR_RANGE(ch, 0x0400, 0x0481);
|
||||
TX_CHAR_RANGE(ch, 0x048C, 0x04C4);
|
||||
TX_CHAR_RANGE(ch, 0x04C7, 0x04C8);
|
||||
TX_CHAR_RANGE(ch, 0x04CB, 0x04CC);
|
||||
TX_CHAR_RANGE(ch, 0x04D0, 0x04F5);
|
||||
TX_CHAR_RANGE(ch, 0x04F8, 0x04F9);
|
||||
TX_CHAR_RANGE(ch, 0x0531, 0x0556);
|
||||
TX_MATCH_CHAR(ch, 0x0559);
|
||||
TX_CHAR_RANGE(ch, 0x0561, 0x0587);
|
||||
TX_CHAR_RANGE(ch, 0x05D0, 0x05EA);
|
||||
TX_CHAR_RANGE(ch, 0x05F0, 0x05F2);
|
||||
TX_CHAR_RANGE(ch, 0x0621, 0x063A);
|
||||
TX_CHAR_RANGE(ch, 0x0640, 0x064A);
|
||||
TX_CHAR_RANGE(ch, 0x0660, 0x0669);
|
||||
TX_CHAR_RANGE(ch, 0x0671, 0x06D3);
|
||||
TX_MATCH_CHAR(ch, 0x06D5);
|
||||
TX_CHAR_RANGE(ch, 0x06E5, 0x06E6);
|
||||
TX_CHAR_RANGE(ch, 0x06F0, 0x06FC);
|
||||
TX_MATCH_CHAR(ch, 0x0710);
|
||||
TX_CHAR_RANGE(ch, 0x0712, 0x072C);
|
||||
TX_CHAR_RANGE(ch, 0x0780, 0x07A5);
|
||||
TX_CHAR_RANGE(ch, 0x0905, 0x0939);
|
||||
TX_MATCH_CHAR(ch, 0x093D);
|
||||
TX_MATCH_CHAR(ch, 0x0950);
|
||||
TX_CHAR_RANGE(ch, 0x0958, 0x0961);
|
||||
TX_CHAR_RANGE(ch, 0x0966, 0x096F);
|
||||
TX_CHAR_RANGE(ch, 0x0985, 0x098C);
|
||||
TX_CHAR_RANGE(ch, 0x098F, 0x0990);
|
||||
TX_CHAR_RANGE(ch, 0x0993, 0x09A8);
|
||||
TX_CHAR_RANGE(ch, 0x09AA, 0x09B0);
|
||||
TX_MATCH_CHAR(ch, 0x09B2);
|
||||
TX_CHAR_RANGE(ch, 0x09B6, 0x09B9);
|
||||
TX_CHAR_RANGE(ch, 0x09DC, 0x09DD);
|
||||
TX_CHAR_RANGE(ch, 0x09DF, 0x09E1);
|
||||
TX_CHAR_RANGE(ch, 0x09E6, 0x09F1);
|
||||
TX_CHAR_RANGE(ch, 0x09F4, 0x09F9);
|
||||
TX_CHAR_RANGE(ch, 0x0A05, 0x0A0A);
|
||||
TX_CHAR_RANGE(ch, 0x0A0F, 0x0A10);
|
||||
TX_CHAR_RANGE(ch, 0x0A13, 0x0A28);
|
||||
TX_CHAR_RANGE(ch, 0x0A2A, 0x0A30);
|
||||
TX_CHAR_RANGE(ch, 0x0A32, 0x0A33);
|
||||
TX_CHAR_RANGE(ch, 0x0A35, 0x0A36);
|
||||
TX_CHAR_RANGE(ch, 0x0A38, 0x0A39);
|
||||
TX_CHAR_RANGE(ch, 0x0A59, 0x0A5C);
|
||||
TX_MATCH_CHAR(ch, 0x0A5E);
|
||||
TX_CHAR_RANGE(ch, 0x0A66, 0x0A6F);
|
||||
TX_CHAR_RANGE(ch, 0x0A72, 0x0A74);
|
||||
TX_CHAR_RANGE(ch, 0x0A85, 0x0A8B);
|
||||
TX_MATCH_CHAR(ch, 0x0A8D);
|
||||
TX_CHAR_RANGE(ch, 0x0A8F, 0x0A91);
|
||||
TX_CHAR_RANGE(ch, 0x0A93, 0x0AA8);
|
||||
TX_CHAR_RANGE(ch, 0x0AAA, 0x0AB0);
|
||||
TX_CHAR_RANGE(ch, 0x0AB2, 0x0AB3);
|
||||
TX_CHAR_RANGE(ch, 0x0AB5, 0x0AB9);
|
||||
TX_MATCH_CHAR(ch, 0x0ABD);
|
||||
TX_MATCH_CHAR(ch, 0x0AD0);
|
||||
TX_MATCH_CHAR(ch, 0x0AE0);
|
||||
TX_CHAR_RANGE(ch, 0x0AE6, 0x0AEF);
|
||||
TX_CHAR_RANGE(ch, 0x0B05, 0x0B0C);
|
||||
TX_CHAR_RANGE(ch, 0x0B0F, 0x0B10);
|
||||
TX_CHAR_RANGE(ch, 0x0B13, 0x0B28);
|
||||
TX_CHAR_RANGE(ch, 0x0B2A, 0x0B30);
|
||||
TX_CHAR_RANGE(ch, 0x0B32, 0x0B33);
|
||||
TX_CHAR_RANGE(ch, 0x0B36, 0x0B39);
|
||||
TX_MATCH_CHAR(ch, 0x0B3D);
|
||||
TX_CHAR_RANGE(ch, 0x0B5C, 0x0B5D);
|
||||
TX_CHAR_RANGE(ch, 0x0B5F, 0x0B61);
|
||||
TX_CHAR_RANGE(ch, 0x0B66, 0x0B6F);
|
||||
TX_CHAR_RANGE(ch, 0x0B85, 0x0B8A);
|
||||
TX_CHAR_RANGE(ch, 0x0B8E, 0x0B90);
|
||||
TX_CHAR_RANGE(ch, 0x0B92, 0x0B95);
|
||||
TX_CHAR_RANGE(ch, 0x0B99, 0x0B9A);
|
||||
TX_MATCH_CHAR(ch, 0x0B9C);
|
||||
TX_CHAR_RANGE(ch, 0x0B9E, 0x0B9F);
|
||||
TX_CHAR_RANGE(ch, 0x0BA3, 0x0BA4);
|
||||
TX_CHAR_RANGE(ch, 0x0BA8, 0x0BAA);
|
||||
TX_CHAR_RANGE(ch, 0x0BAE, 0x0BB5);
|
||||
TX_CHAR_RANGE(ch, 0x0BB7, 0x0BB9);
|
||||
TX_CHAR_RANGE(ch, 0x0BE7, 0x0BF2);
|
||||
TX_CHAR_RANGE(ch, 0x0C05, 0x0C0C);
|
||||
TX_CHAR_RANGE(ch, 0x0C0E, 0x0C10);
|
||||
TX_CHAR_RANGE(ch, 0x0C12, 0x0C28);
|
||||
TX_CHAR_RANGE(ch, 0x0C2A, 0x0C33);
|
||||
TX_CHAR_RANGE(ch, 0x0C35, 0x0C39);
|
||||
TX_CHAR_RANGE(ch, 0x0C60, 0x0C61);
|
||||
TX_CHAR_RANGE(ch, 0x0C66, 0x0C6F);
|
||||
TX_CHAR_RANGE(ch, 0x0C85, 0x0C8C);
|
||||
TX_CHAR_RANGE(ch, 0x0C8E, 0x0C90);
|
||||
TX_CHAR_RANGE(ch, 0x0C92, 0x0CA8);
|
||||
TX_CHAR_RANGE(ch, 0x0CAA, 0x0CB3);
|
||||
TX_CHAR_RANGE(ch, 0x0CB5, 0x0CB9);
|
||||
TX_MATCH_CHAR(ch, 0x0CDE);
|
||||
TX_CHAR_RANGE(ch, 0x0CE0, 0x0CE1);
|
||||
TX_CHAR_RANGE(ch, 0x0CE6, 0x0CEF);
|
||||
TX_CHAR_RANGE(ch, 0x0D05, 0x0D0C);
|
||||
TX_CHAR_RANGE(ch, 0x0D0E, 0x0D10);
|
||||
TX_CHAR_RANGE(ch, 0x0D12, 0x0D28);
|
||||
TX_CHAR_RANGE(ch, 0x0D2A, 0x0D39);
|
||||
TX_CHAR_RANGE(ch, 0x0D60, 0x0D61);
|
||||
TX_CHAR_RANGE(ch, 0x0D66, 0x0D6F);
|
||||
TX_CHAR_RANGE(ch, 0x0D85, 0x0D96);
|
||||
TX_CHAR_RANGE(ch, 0x0D9A, 0x0DB1);
|
||||
TX_CHAR_RANGE(ch, 0x0DB3, 0x0DBB);
|
||||
TX_MATCH_CHAR(ch, 0x0DBD);
|
||||
TX_CHAR_RANGE(ch, 0x0DC0, 0x0DC6);
|
||||
TX_CHAR_RANGE(ch, 0x0E01, 0x0E30);
|
||||
TX_CHAR_RANGE(ch, 0x0E32, 0x0E33);
|
||||
TX_CHAR_RANGE(ch, 0x0E40, 0x0E46);
|
||||
TX_CHAR_RANGE(ch, 0x0E50, 0x0E59);
|
||||
TX_CHAR_RANGE(ch, 0x0E81, 0x0E82);
|
||||
TX_MATCH_CHAR(ch, 0x0E84);
|
||||
TX_CHAR_RANGE(ch, 0x0E87, 0x0E88);
|
||||
TX_MATCH_CHAR(ch, 0x0E8A);
|
||||
TX_MATCH_CHAR(ch, 0x0E8D);
|
||||
TX_CHAR_RANGE(ch, 0x0E94, 0x0E97);
|
||||
TX_CHAR_RANGE(ch, 0x0E99, 0x0E9F);
|
||||
TX_CHAR_RANGE(ch, 0x0EA1, 0x0EA3);
|
||||
TX_MATCH_CHAR(ch, 0x0EA5);
|
||||
TX_MATCH_CHAR(ch, 0x0EA7);
|
||||
TX_CHAR_RANGE(ch, 0x0EAA, 0x0EAB);
|
||||
TX_CHAR_RANGE(ch, 0x0EAD, 0x0EB0);
|
||||
TX_CHAR_RANGE(ch, 0x0EB2, 0x0EB3);
|
||||
TX_MATCH_CHAR(ch, 0x0EBD);
|
||||
TX_CHAR_RANGE(ch, 0x0EC0, 0x0EC4);
|
||||
TX_MATCH_CHAR(ch, 0x0EC6);
|
||||
TX_CHAR_RANGE(ch, 0x0ED0, 0x0ED9);
|
||||
TX_CHAR_RANGE(ch, 0x0EDC, 0x0EDD);
|
||||
TX_MATCH_CHAR(ch, 0x0F00);
|
||||
TX_CHAR_RANGE(ch, 0x0F20, 0x0F33);
|
||||
TX_CHAR_RANGE(ch, 0x0F40, 0x0F47);
|
||||
TX_CHAR_RANGE(ch, 0x0F49, 0x0F6A);
|
||||
TX_CHAR_RANGE(ch, 0x0F88, 0x0F8B);
|
||||
TX_CHAR_RANGE(ch, 0x1000, 0x1021);
|
||||
TX_CHAR_RANGE(ch, 0x1023, 0x1027);
|
||||
TX_CHAR_RANGE(ch, 0x1029, 0x102A);
|
||||
TX_CHAR_RANGE(ch, 0x1040, 0x1049);
|
||||
TX_CHAR_RANGE(ch, 0x1050, 0x1055);
|
||||
TX_CHAR_RANGE(ch, 0x10A0, 0x10C5);
|
||||
TX_CHAR_RANGE(ch, 0x10D0, 0x10F6);
|
||||
TX_CHAR_RANGE(ch, 0x1100, 0x1159);
|
||||
TX_CHAR_RANGE(ch, 0x115F, 0x11A2);
|
||||
TX_CHAR_RANGE(ch, 0x11A8, 0x11F9);
|
||||
TX_CHAR_RANGE(ch, 0x1200, 0x1206);
|
||||
TX_CHAR_RANGE(ch, 0x1208, 0x1246);
|
||||
TX_MATCH_CHAR(ch, 0x1248);
|
||||
TX_CHAR_RANGE(ch, 0x124A, 0x124D);
|
||||
TX_CHAR_RANGE(ch, 0x1250, 0x1256);
|
||||
TX_MATCH_CHAR(ch, 0x1258);
|
||||
TX_CHAR_RANGE(ch, 0x125A, 0x125D);
|
||||
TX_CHAR_RANGE(ch, 0x1260, 0x1286);
|
||||
TX_MATCH_CHAR(ch, 0x1288);
|
||||
TX_CHAR_RANGE(ch, 0x128A, 0x128D);
|
||||
TX_CHAR_RANGE(ch, 0x1290, 0x12AE);
|
||||
TX_MATCH_CHAR(ch, 0x12B0);
|
||||
TX_CHAR_RANGE(ch, 0x12B2, 0x12B5);
|
||||
TX_CHAR_RANGE(ch, 0x12B8, 0x12BE);
|
||||
TX_MATCH_CHAR(ch, 0x12C0);
|
||||
TX_CHAR_RANGE(ch, 0x12C2, 0x12C5);
|
||||
TX_CHAR_RANGE(ch, 0x12C8, 0x12CE);
|
||||
TX_CHAR_RANGE(ch, 0x12D0, 0x12D6);
|
||||
TX_CHAR_RANGE(ch, 0x12D8, 0x12EE);
|
||||
TX_CHAR_RANGE(ch, 0x12F0, 0x130E);
|
||||
TX_MATCH_CHAR(ch, 0x1310);
|
||||
TX_CHAR_RANGE(ch, 0x1312, 0x1315);
|
||||
TX_CHAR_RANGE(ch, 0x1318, 0x131E);
|
||||
TX_CHAR_RANGE(ch, 0x1320, 0x1346);
|
||||
TX_CHAR_RANGE(ch, 0x1348, 0x135A);
|
||||
TX_CHAR_RANGE(ch, 0x1369, 0x137C);
|
||||
TX_CHAR_RANGE(ch, 0x13A0, 0x13F4);
|
||||
TX_CHAR_RANGE(ch, 0x1401, 0x166C);
|
||||
TX_CHAR_RANGE(ch, 0x166F, 0x1676);
|
||||
TX_CHAR_RANGE(ch, 0x1681, 0x169A);
|
||||
TX_CHAR_RANGE(ch, 0x16A0, 0x16EA);
|
||||
TX_CHAR_RANGE(ch, 0x16EE, 0x16F0);
|
||||
TX_CHAR_RANGE(ch, 0x1780, 0x17B3);
|
||||
TX_CHAR_RANGE(ch, 0x17E0, 0x17E9);
|
||||
TX_CHAR_RANGE(ch, 0x1810, 0x1819);
|
||||
TX_CHAR_RANGE(ch, 0x1820, 0x1877);
|
||||
TX_CHAR_RANGE(ch, 0x1880, 0x18A8);
|
||||
TX_CHAR_RANGE(ch, 0x1E00, 0x1E9B);
|
||||
TX_CHAR_RANGE(ch, 0x1EA0, 0x1EF9);
|
||||
TX_CHAR_RANGE(ch, 0x1F00, 0x1F15);
|
||||
TX_CHAR_RANGE(ch, 0x1F18, 0x1F1D);
|
||||
TX_CHAR_RANGE(ch, 0x1F20, 0x1F45);
|
||||
TX_CHAR_RANGE(ch, 0x1F48, 0x1F4D);
|
||||
TX_CHAR_RANGE(ch, 0x1F50, 0x1F57);
|
||||
TX_MATCH_CHAR(ch, 0x1F59);
|
||||
TX_MATCH_CHAR(ch, 0x1F5B);
|
||||
TX_MATCH_CHAR(ch, 0x1F5D);
|
||||
TX_CHAR_RANGE(ch, 0x1F5F, 0x1F7D);
|
||||
TX_CHAR_RANGE(ch, 0x1F80, 0x1FB4);
|
||||
TX_CHAR_RANGE(ch, 0x1FB6, 0x1FBC);
|
||||
TX_MATCH_CHAR(ch, 0x1FBE);
|
||||
TX_CHAR_RANGE(ch, 0x1FC2, 0x1FC4);
|
||||
TX_CHAR_RANGE(ch, 0x1FC6, 0x1FCC);
|
||||
TX_CHAR_RANGE(ch, 0x1FD0, 0x1FD3);
|
||||
TX_CHAR_RANGE(ch, 0x1FD6, 0x1FDB);
|
||||
TX_CHAR_RANGE(ch, 0x1FE0, 0x1FEC);
|
||||
TX_CHAR_RANGE(ch, 0x1FF2, 0x1FF4);
|
||||
TX_CHAR_RANGE(ch, 0x1FF6, 0x1FFC);
|
||||
TX_MATCH_CHAR(ch, 0x2070);
|
||||
TX_CHAR_RANGE(ch, 0x2074, 0x2079);
|
||||
TX_CHAR_RANGE(ch, 0x207F, 0x2089);
|
||||
TX_MATCH_CHAR(ch, 0x2102);
|
||||
TX_MATCH_CHAR(ch, 0x2107);
|
||||
TX_CHAR_RANGE(ch, 0x210A, 0x2113);
|
||||
TX_MATCH_CHAR(ch, 0x2115);
|
||||
TX_CHAR_RANGE(ch, 0x2119, 0x211D);
|
||||
TX_MATCH_CHAR(ch, 0x2124);
|
||||
TX_MATCH_CHAR(ch, 0x2126);
|
||||
TX_MATCH_CHAR(ch, 0x2128);
|
||||
TX_CHAR_RANGE(ch, 0x212A, 0x212D);
|
||||
TX_CHAR_RANGE(ch, 0x212F, 0x2131);
|
||||
TX_CHAR_RANGE(ch, 0x2133, 0x2139);
|
||||
TX_CHAR_RANGE(ch, 0x2153, 0x2183);
|
||||
TX_CHAR_RANGE(ch, 0x2460, 0x249B);
|
||||
TX_MATCH_CHAR(ch, 0x24EA);
|
||||
TX_CHAR_RANGE(ch, 0x2776, 0x2793);
|
||||
TX_CHAR_RANGE(ch, 0x3005, 0x3007);
|
||||
TX_CHAR_RANGE(ch, 0x3021, 0x3029);
|
||||
TX_CHAR_RANGE(ch, 0x3031, 0x3035);
|
||||
TX_CHAR_RANGE(ch, 0x3038, 0x303A);
|
||||
TX_CHAR_RANGE(ch, 0x3041, 0x3094);
|
||||
TX_CHAR_RANGE(ch, 0x309D, 0x309E);
|
||||
TX_CHAR_RANGE(ch, 0x30A1, 0x30FA);
|
||||
TX_CHAR_RANGE(ch, 0x30FC, 0x30FE);
|
||||
TX_CHAR_RANGE(ch, 0x3105, 0x312C);
|
||||
TX_CHAR_RANGE(ch, 0x3131, 0x318E);
|
||||
TX_CHAR_RANGE(ch, 0x3192, 0x3195);
|
||||
TX_CHAR_RANGE(ch, 0x31A0, 0x31B7);
|
||||
TX_CHAR_RANGE(ch, 0x3220, 0x3229);
|
||||
TX_CHAR_RANGE(ch, 0x3280, 0x3289);
|
||||
TX_MATCH_CHAR(ch, 0x3400);
|
||||
TX_MATCH_CHAR(ch, 0x4DB5);
|
||||
TX_MATCH_CHAR(ch, 0x4E00);
|
||||
TX_MATCH_CHAR(ch, 0x9FA5);
|
||||
TX_CHAR_RANGE(ch, 0xA000, 0xA48C);
|
||||
TX_MATCH_CHAR(ch, 0xAC00);
|
||||
TX_MATCH_CHAR(ch, 0xD7A3);
|
||||
TX_CHAR_RANGE(ch, 0xF900, 0xFA2D);
|
||||
TX_CHAR_RANGE(ch, 0xFB00, 0xFB06);
|
||||
TX_CHAR_RANGE(ch, 0xFB13, 0xFB17);
|
||||
TX_MATCH_CHAR(ch, 0xFB1D);
|
||||
TX_CHAR_RANGE(ch, 0xFB1F, 0xFB28);
|
||||
TX_CHAR_RANGE(ch, 0xFB2A, 0xFB36);
|
||||
TX_CHAR_RANGE(ch, 0xFB38, 0xFB3C);
|
||||
TX_MATCH_CHAR(ch, 0xFB3E);
|
||||
TX_CHAR_RANGE(ch, 0xFB40, 0xFB41);
|
||||
TX_CHAR_RANGE(ch, 0xFB43, 0xFB44);
|
||||
TX_CHAR_RANGE(ch, 0xFB46, 0xFBB1);
|
||||
TX_CHAR_RANGE(ch, 0xFBD3, 0xFD3D);
|
||||
TX_CHAR_RANGE(ch, 0xFD50, 0xFD8F);
|
||||
TX_CHAR_RANGE(ch, 0xFD92, 0xFDC7);
|
||||
TX_CHAR_RANGE(ch, 0xFDF0, 0xFDFB);
|
||||
TX_CHAR_RANGE(ch, 0xFE70, 0xFE72);
|
||||
TX_MATCH_CHAR(ch, 0xFE74);
|
||||
TX_CHAR_RANGE(ch, 0xFE76, 0xFEFC);
|
||||
TX_CHAR_RANGE(ch, 0xFF10, 0xFF19);
|
||||
TX_CHAR_RANGE(ch, 0xFF21, 0xFF3A);
|
||||
TX_CHAR_RANGE(ch, 0xFF41, 0xFF5A);
|
||||
TX_CHAR_RANGE(ch, 0xFF66, 0xFFBE);
|
||||
TX_CHAR_RANGE(ch, 0xFFC2, 0xFFC7);
|
||||
TX_CHAR_RANGE(ch, 0xFFCA, 0xFFCF);
|
||||
TX_CHAR_RANGE(ch, 0xFFD2, 0xFFD7);
|
||||
return MB_FALSE;
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is TransforMiiX XSLT processor.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Jonas Sicking.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* Jonas Sicking. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <sicking@bigfoot.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef TRANSFRMX_TXXSLTNUMBER_H
|
||||
#define TRANSFRMX_TXXSLTNUMBER_H
|
||||
|
||||
#include "ProcessorState.h"
|
||||
#include "txError.h"
|
||||
|
||||
class txXSLTNumber {
|
||||
|
||||
public:
|
||||
static nsresult createNumber(Element* aNumberElement, ProcessorState* aPs,
|
||||
String& aResult);
|
||||
private:
|
||||
static nsresult getValueList(Element* aNumberElement, ProcessorState* aPs,
|
||||
txList& aValues, String& aValueString);
|
||||
|
||||
static nsresult getCounters(Element* aNumberElement, ProcessorState* aPs,
|
||||
txList& aCounters,
|
||||
String& aHead, String& aTail);
|
||||
|
||||
static PRInt32 getSiblingCount(Node* aNode, txPattern* aCountPattern,
|
||||
txIMatchContext* aContext);
|
||||
|
||||
static Node* getPrevInDocumentOrder(Node* aNode);
|
||||
|
||||
static MBool isAlphaNumeric(UNICODE_CHAR ch);
|
||||
};
|
||||
|
||||
class txFormattedCounter {
|
||||
public:
|
||||
virtual ~txFormattedCounter()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void appendNumber(PRInt32 aNumber, String& aDest) = 0;
|
||||
|
||||
static nsresult getCounterFor(const String& aToken, int aGroupSize,
|
||||
const String& aGroupSeparator,
|
||||
txFormattedCounter*& aCounter);
|
||||
|
||||
String mSeparator;
|
||||
};
|
||||
|
||||
#endif //TRANSFRMX_TXXSLTNUMBER_H
|
|
@ -0,0 +1,251 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is TransforMiiX XSLT processor.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Jonas Sicking.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* Jonas Sicking. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jonas Sicking <sicking@bigfoot.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "txXSLTNumber.h"
|
||||
#include "primitives.h"
|
||||
#include "Names.h"
|
||||
|
||||
class txDecimalCounter : public txFormattedCounter {
|
||||
public:
|
||||
txDecimalCounter() : mMinLength(1), mGroupSize(50)
|
||||
{
|
||||
}
|
||||
|
||||
txDecimalCounter(PRInt32 aMinLength, PRInt32 aGroupSize,
|
||||
const String& mGroupSeparator);
|
||||
|
||||
virtual void appendNumber(PRInt32 aNumber, String& aDest);
|
||||
|
||||
private:
|
||||
PRInt32 mMinLength;
|
||||
PRInt32 mGroupSize;
|
||||
String mGroupSeparator;
|
||||
};
|
||||
|
||||
class txAlphaCounter : public txFormattedCounter {
|
||||
public:
|
||||
txAlphaCounter(UNICODE_CHAR aOffset) : mOffset(aOffset)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void appendNumber(PRInt32 aNumber, String& aDest);
|
||||
|
||||
private:
|
||||
UNICODE_CHAR mOffset;
|
||||
};
|
||||
|
||||
class txRomanCounter : public txFormattedCounter {
|
||||
public:
|
||||
txRomanCounter(MBool aUpper) : mTableOffset(aUpper ? 30 : 0)
|
||||
{
|
||||
}
|
||||
|
||||
void appendNumber(PRInt32 aNumber, String& aDest);
|
||||
|
||||
private:
|
||||
PRInt32 mTableOffset;
|
||||
};
|
||||
|
||||
|
||||
nsresult
|
||||
txFormattedCounter::getCounterFor(const String& aToken, PRInt32 aGroupSize,
|
||||
const String& aGroupSeparator,
|
||||
txFormattedCounter*& aCounter)
|
||||
{
|
||||
PRInt32 length = aToken.length();
|
||||
NS_ASSERTION(length, "getting counter for empty token");
|
||||
aCounter = 0;
|
||||
|
||||
if (length == 1) {
|
||||
UNICODE_CHAR ch = aToken.charAt(0);
|
||||
switch (ch) {
|
||||
|
||||
case 'i':
|
||||
case 'I':
|
||||
aCounter = new txRomanCounter(ch == 'I');
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
aCounter = new txAlphaCounter(ch);
|
||||
break;
|
||||
|
||||
case '1':
|
||||
default:
|
||||
// if we don't recognize the token then use "1"
|
||||
aCounter = new txDecimalCounter(1, aGroupSize, aGroupSeparator);
|
||||
break;
|
||||
}
|
||||
return aCounter ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// for now, the only multi-char token we support are decimals
|
||||
PRInt32 i;
|
||||
for (i = 0; i < length-1; ++i) {
|
||||
if (aToken.charAt(i) != '0')
|
||||
break;
|
||||
}
|
||||
if (i == length-1 && aToken.charAt(i) == '1') {
|
||||
aCounter = new txDecimalCounter(length, aGroupSize, aGroupSeparator);
|
||||
}
|
||||
else {
|
||||
// if we don't recognize the token then use '1'
|
||||
aCounter = new txDecimalCounter(1, aGroupSize, aGroupSeparator);
|
||||
}
|
||||
|
||||
return aCounter ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
txDecimalCounter::txDecimalCounter(PRInt32 aMinLength, PRInt32 aGroupSize,
|
||||
const String& aGroupSeparator)
|
||||
: mMinLength(aMinLength), mGroupSize(aGroupSize),
|
||||
mGroupSeparator(aGroupSeparator)
|
||||
{
|
||||
if (mGroupSize <= 0) {
|
||||
mGroupSize = aMinLength + 10;
|
||||
}
|
||||
}
|
||||
|
||||
void txDecimalCounter::appendNumber(PRInt32 aNumber, String& aDest)
|
||||
{
|
||||
String num;
|
||||
|
||||
const PRInt32 bufsize = 10; //must be able to fit an PRInt32
|
||||
UNICODE_CHAR buf[bufsize];
|
||||
PRInt32 pos = bufsize;
|
||||
while (aNumber > 0) {
|
||||
PRInt32 ch = aNumber % 10;
|
||||
aNumber /= 10;
|
||||
buf[--pos] = ch + '0';
|
||||
}
|
||||
|
||||
// in case we didn't get a long enough string
|
||||
PRInt32 end = (bufsize > mMinLength) ? bufsize - mMinLength : 0;
|
||||
while (pos > end) {
|
||||
buf[--pos] = '0';
|
||||
}
|
||||
|
||||
// in case we *still* didn't get a long enough string.
|
||||
// this should be very rare since it only happens if mMinLength is bigger
|
||||
// then the length of any PRInt32.
|
||||
// pos will always be zero
|
||||
PRInt32 extraPos = mMinLength;
|
||||
while (extraPos > bufsize) {
|
||||
aDest.append('0');
|
||||
--extraPos;
|
||||
if (extraPos % mGroupSize == 0) {
|
||||
aDest.append(mGroupSeparator);
|
||||
}
|
||||
}
|
||||
|
||||
// copy string to buffer
|
||||
if (mGroupSize >= bufsize - pos) {
|
||||
// no grouping will occur
|
||||
aDest.append(buf + pos, (PRUint32)(bufsize - pos));
|
||||
}
|
||||
else {
|
||||
// append chars up to first grouping separator
|
||||
PRInt32 len = ((bufsize - pos - 1) % mGroupSize) + 1;
|
||||
aDest.append(buf + pos, len);
|
||||
pos += len;
|
||||
while (bufsize - pos > 0) {
|
||||
aDest.append(mGroupSeparator);
|
||||
aDest.append(buf + pos, mGroupSize);
|
||||
pos += mGroupSize;
|
||||
}
|
||||
NS_ASSERTION(bufsize == pos, "error while grouping");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void txAlphaCounter::appendNumber(PRInt32 aNumber, String& aDest)
|
||||
{
|
||||
String num;
|
||||
|
||||
UNICODE_CHAR buf[11];
|
||||
buf[11] = 0;
|
||||
PRInt32 pos = 11;
|
||||
while (aNumber > 0) {
|
||||
--aNumber;
|
||||
PRInt32 ch = aNumber % 26;
|
||||
aNumber /= 26;
|
||||
buf[--pos] = ch + mOffset;
|
||||
}
|
||||
|
||||
aDest.append(buf + pos, (PRUint32)(11 - pos));
|
||||
}
|
||||
|
||||
|
||||
const char* kTxRomanNumbers[] =
|
||||
{"", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm",
|
||||
"", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc",
|
||||
"", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix",
|
||||
"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM",
|
||||
"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC",
|
||||
"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
|
||||
|
||||
void txRomanCounter::appendNumber(PRInt32 aNumber, String& aDest)
|
||||
{
|
||||
// Numbers bigger then 3999 can't be done in roman
|
||||
if (aNumber >= 4000) {
|
||||
txDecimalCounter().appendNumber(aNumber, aDest);
|
||||
return;
|
||||
}
|
||||
|
||||
while (aNumber >= 1000) {
|
||||
aDest.append(!mTableOffset ? 'm' : 'M');
|
||||
aNumber -= 1000;
|
||||
}
|
||||
|
||||
PRInt32 posValue;
|
||||
|
||||
// Hundreds
|
||||
posValue = aNumber / 100;
|
||||
aNumber %= 100;
|
||||
aDest.append(NS_ConvertASCIItoUCS2(kTxRomanNumbers[posValue +
|
||||
mTableOffset]));
|
||||
// Tens
|
||||
posValue = aNumber / 10;
|
||||
aNumber %= 10;
|
||||
aDest.append(NS_ConvertASCIItoUCS2(kTxRomanNumbers[10 + posValue +
|
||||
mTableOffset]));
|
||||
// Ones
|
||||
aDest.append(NS_ConvertASCIItoUCS2(kTxRomanNumbers[20 + aNumber +
|
||||
mTableOffset]));
|
||||
}
|
Загрузка…
Ссылка в новой задаче