| Index: third_party/libxslt/libxslt/numbers.c
|
| diff --git a/third_party/libxslt/libxslt/numbers.c b/third_party/libxslt/libxslt/numbers.c
|
| deleted file mode 100644
|
| index e78c46b6357b7bc5f0cc4c523a6e359f8f86460b..0000000000000000000000000000000000000000
|
| --- a/third_party/libxslt/libxslt/numbers.c
|
| +++ /dev/null
|
| @@ -1,1361 +0,0 @@
|
| -/*
|
| - * numbers.c: Implementation of the XSLT number functions
|
| - *
|
| - * Reference:
|
| - * http://www.w3.org/TR/1999/REC-xslt-19991116
|
| - *
|
| - * See Copyright for the status of this software.
|
| - *
|
| - * daniel@veillard.com
|
| - * Bjorn Reese <breese@users.sourceforge.net>
|
| - */
|
| -
|
| -#define IN_LIBXSLT
|
| -#include "libxslt.h"
|
| -
|
| -#include <math.h>
|
| -#include <limits.h>
|
| -#include <float.h>
|
| -#include <string.h>
|
| -
|
| -#include <libxml/xmlmemory.h>
|
| -#include <libxml/parserInternals.h>
|
| -#include <libxml/xpath.h>
|
| -#include <libxml/xpathInternals.h>
|
| -#include <libxml/encoding.h>
|
| -#include "xsltutils.h"
|
| -#include "pattern.h"
|
| -#include "templates.h"
|
| -#include "transform.h"
|
| -#include "numbersInternals.h"
|
| -
|
| -#ifndef FALSE
|
| -# define FALSE (0 == 1)
|
| -# define TRUE (1 == 1)
|
| -#endif
|
| -
|
| -#define SYMBOL_QUOTE ((xmlChar)'\'')
|
| -
|
| -#define DEFAULT_TOKEN (xmlChar)'0'
|
| -#define DEFAULT_SEPARATOR "."
|
| -
|
| -#define MAX_TOKENS 1024
|
| -
|
| -typedef struct _xsltFormatToken xsltFormatToken;
|
| -typedef xsltFormatToken *xsltFormatTokenPtr;
|
| -struct _xsltFormatToken {
|
| - xmlChar *separator;
|
| - xmlChar token;
|
| - int width;
|
| -};
|
| -
|
| -typedef struct _xsltFormat xsltFormat;
|
| -typedef xsltFormat *xsltFormatPtr;
|
| -struct _xsltFormat {
|
| - xmlChar *start;
|
| - xsltFormatToken tokens[MAX_TOKENS];
|
| - int nTokens;
|
| - xmlChar *end;
|
| -};
|
| -
|
| -static char alpha_upper_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
| -static char alpha_lower_list[] = "abcdefghijklmnopqrstuvwxyz";
|
| -static xsltFormatToken default_token;
|
| -
|
| -/*
|
| - * **** Start temp insert ****
|
| - *
|
| - * The following two routines (xsltUTF8Size and xsltUTF8Charcmp)
|
| - * will be replaced with calls to the corresponding libxml routines
|
| - * at a later date (when other inter-library dependencies require it)
|
| - */
|
| -
|
| -/**
|
| - * xsltUTF8Size:
|
| - * @utf: pointer to the UTF8 character
|
| - *
|
| - * returns the numbers of bytes in the character, -1 on format error
|
| - */
|
| -static int
|
| -xsltUTF8Size(xmlChar *utf) {
|
| - xmlChar mask;
|
| - int len;
|
| -
|
| - if (utf == NULL)
|
| - return -1;
|
| - if (*utf < 0x80)
|
| - return 1;
|
| - /* check valid UTF8 character */
|
| - if (!(*utf & 0x40))
|
| - return -1;
|
| - /* determine number of bytes in char */
|
| - len = 2;
|
| - for (mask=0x20; mask != 0; mask>>=1) {
|
| - if (!(*utf & mask))
|
| - return len;
|
| - len++;
|
| - }
|
| - return -1;
|
| -}
|
| -
|
| -/**
|
| - * xsltUTF8Charcmp
|
| - * @utf1: pointer to first UTF8 char
|
| - * @utf2: pointer to second UTF8 char
|
| - *
|
| - * returns result of comparing the two UCS4 values
|
| - * as with xmlStrncmp
|
| - */
|
| -static int
|
| -xsltUTF8Charcmp(xmlChar *utf1, xmlChar *utf2) {
|
| -
|
| - if (utf1 == NULL ) {
|
| - if (utf2 == NULL)
|
| - return 0;
|
| - return -1;
|
| - }
|
| - return xmlStrncmp(utf1, utf2, xsltUTF8Size(utf1));
|
| -}
|
| -
|
| -/***** Stop temp insert *****/
|
| -/************************************************************************
|
| - * *
|
| - * Utility functions *
|
| - * *
|
| - ************************************************************************/
|
| -
|
| -#define IS_SPECIAL(self,letter) \
|
| - ((xsltUTF8Charcmp((letter), (self)->zeroDigit) == 0) || \
|
| - (xsltUTF8Charcmp((letter), (self)->digit) == 0) || \
|
| - (xsltUTF8Charcmp((letter), (self)->decimalPoint) == 0) || \
|
| - (xsltUTF8Charcmp((letter), (self)->grouping) == 0) || \
|
| - (xsltUTF8Charcmp((letter), (self)->patternSeparator) == 0))
|
| -
|
| -#define IS_DIGIT_ZERO(x) xsltIsDigitZero(x)
|
| -#define IS_DIGIT_ONE(x) xsltIsDigitZero((xmlChar)(x)-1)
|
| -
|
| -static int
|
| -xsltIsDigitZero(unsigned int ch)
|
| -{
|
| - /*
|
| - * Reference: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
|
| - */
|
| - switch (ch) {
|
| - case 0x0030: case 0x0660: case 0x06F0: case 0x0966:
|
| - case 0x09E6: case 0x0A66: case 0x0AE6: case 0x0B66:
|
| - case 0x0C66: case 0x0CE6: case 0x0D66: case 0x0E50:
|
| - case 0x0E60: case 0x0F20: case 0x1040: case 0x17E0:
|
| - case 0x1810: case 0xFF10:
|
| - return TRUE;
|
| - default:
|
| - return FALSE;
|
| - }
|
| -}
|
| -
|
| -static void
|
| -xsltNumberFormatDecimal(xmlBufferPtr buffer,
|
| - double number,
|
| - int digit_zero,
|
| - int width,
|
| - int digitsPerGroup,
|
| - int groupingCharacter,
|
| - int groupingCharacterLen)
|
| -{
|
| - /*
|
| - * This used to be
|
| - * xmlChar temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 4];
|
| - * which would be length 68 on x86 arch. It was changed to be a longer,
|
| - * fixed length in order to try to cater for (reasonable) UTF8
|
| - * separators and numeric characters. The max UTF8 char size will be
|
| - * 6 or less, so the value used [500] should be *much* larger than needed
|
| - */
|
| - xmlChar temp_string[500];
|
| - xmlChar *pointer;
|
| - xmlChar temp_char[6];
|
| - int i;
|
| - int val;
|
| - int len;
|
| -
|
| - /* Build buffer from back */
|
| - pointer = &temp_string[sizeof(temp_string)] - 1; /* last char */
|
| - *pointer = 0;
|
| - i = 0;
|
| - while (pointer > temp_string) {
|
| - if ((i >= width) && (fabs(number) < 1.0))
|
| - break; /* for */
|
| - if ((i > 0) && (groupingCharacter != 0) &&
|
| - (digitsPerGroup > 0) &&
|
| - ((i % digitsPerGroup) == 0)) {
|
| - if (pointer - groupingCharacterLen < temp_string) {
|
| - i = -1; /* flag error */
|
| - break;
|
| - }
|
| - pointer -= groupingCharacterLen;
|
| - xmlCopyCharMultiByte(pointer, groupingCharacter);
|
| - }
|
| -
|
| - val = digit_zero + (int)fmod(number, 10.0);
|
| - if (val < 0x80) { /* shortcut if ASCII */
|
| - if (pointer <= temp_string) { /* Check enough room */
|
| - i = -1;
|
| - break;
|
| - }
|
| - *(--pointer) = val;
|
| - }
|
| - else {
|
| - /*
|
| - * Here we have a multibyte character. It's a little messy,
|
| - * because until we generate the char we don't know how long
|
| - * it is. So, we generate it into the buffer temp_char, then
|
| - * copy from there into temp_string.
|
| - */
|
| - len = xmlCopyCharMultiByte(temp_char, val);
|
| - if ( (pointer - len) < temp_string ) {
|
| - i = -1;
|
| - break;
|
| - }
|
| - pointer -= len;
|
| - memcpy(pointer, temp_char, len);
|
| - }
|
| - number /= 10.0;
|
| - ++i;
|
| - }
|
| - if (i < 0)
|
| - xsltGenericError(xsltGenericErrorContext,
|
| - "xsltNumberFormatDecimal: Internal buffer size exceeded");
|
| - xmlBufferCat(buffer, pointer);
|
| -}
|
| -
|
| -static void
|
| -xsltNumberFormatAlpha(xsltNumberDataPtr data,
|
| - xmlBufferPtr buffer,
|
| - double number,
|
| - int is_upper)
|
| -{
|
| - char temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 1];
|
| - char *pointer;
|
| - int i;
|
| - char *alpha_list;
|
| - double alpha_size = (double)(sizeof(alpha_upper_list) - 1);
|
| -
|
| - /*
|
| - * XSLT 1.0 isn't clear on how to handle zero, but XSLT 2.0 says:
|
| - *
|
| - * For all format tokens other than the first kind above (one that
|
| - * consists of decimal digits), there may be implementation-defined
|
| - * lower and upper bounds on the range of numbers that can be
|
| - * formatted using this format token; indeed, for some numbering
|
| - * sequences there may be intrinsic limits. [...] Numbers that fall
|
| - * outside this range must be formatted using the format token 1.
|
| - *
|
| - * The "a" token has an intrinsic lower limit of 1.
|
| - */
|
| - if (number < 1.0) {
|
| - xsltNumberFormatDecimal(buffer, number, '0', 1,
|
| - data->digitsPerGroup,
|
| - data->groupingCharacter,
|
| - data->groupingCharacterLen);
|
| - return;
|
| - }
|
| -
|
| - /* Build buffer from back */
|
| - pointer = &temp_string[sizeof(temp_string)];
|
| - *(--pointer) = 0;
|
| - alpha_list = (is_upper) ? alpha_upper_list : alpha_lower_list;
|
| -
|
| - for (i = 1; i < (int)sizeof(temp_string); i++) {
|
| - number--;
|
| - *(--pointer) = alpha_list[((int)fmod(number, alpha_size))];
|
| - number /= alpha_size;
|
| - if (number < 1.0)
|
| - break; /* for */
|
| - }
|
| - xmlBufferCCat(buffer, pointer);
|
| -}
|
| -
|
| -static void
|
| -xsltNumberFormatRoman(xsltNumberDataPtr data,
|
| - xmlBufferPtr buffer,
|
| - double number,
|
| - int is_upper)
|
| -{
|
| - /*
|
| - * See discussion in xsltNumberFormatAlpha. Also use a reasonable upper
|
| - * bound to avoid denial of service.
|
| - */
|
| - if (number < 1.0 || number > 5000.0) {
|
| - xsltNumberFormatDecimal(buffer, number, '0', 1,
|
| - data->digitsPerGroup,
|
| - data->groupingCharacter,
|
| - data->groupingCharacterLen);
|
| - return;
|
| - }
|
| -
|
| - /*
|
| - * Based on an example by Jim Walsh
|
| - */
|
| - while (number >= 1000.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "M" : "m");
|
| - number -= 1000.0;
|
| - }
|
| - if (number >= 900.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "CM" : "cm");
|
| - number -= 900.0;
|
| - }
|
| - while (number >= 500.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "D" : "d");
|
| - number -= 500.0;
|
| - }
|
| - if (number >= 400.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "CD" : "cd");
|
| - number -= 400.0;
|
| - }
|
| - while (number >= 100.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "C" : "c");
|
| - number -= 100.0;
|
| - }
|
| - if (number >= 90.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "XC" : "xc");
|
| - number -= 90.0;
|
| - }
|
| - while (number >= 50.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "L" : "l");
|
| - number -= 50.0;
|
| - }
|
| - if (number >= 40.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "XL" : "xl");
|
| - number -= 40.0;
|
| - }
|
| - while (number >= 10.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "X" : "x");
|
| - number -= 10.0;
|
| - }
|
| - if (number >= 9.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "IX" : "ix");
|
| - number -= 9.0;
|
| - }
|
| - while (number >= 5.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "V" : "v");
|
| - number -= 5.0;
|
| - }
|
| - if (number >= 4.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "IV" : "iv");
|
| - number -= 4.0;
|
| - }
|
| - while (number >= 1.0) {
|
| - xmlBufferCCat(buffer, (is_upper) ? "I" : "i");
|
| - number--;
|
| - }
|
| -}
|
| -
|
| -static void
|
| -xsltNumberFormatTokenize(const xmlChar *format,
|
| - xsltFormatPtr tokens)
|
| -{
|
| - int ix = 0;
|
| - int j;
|
| - int val;
|
| - int len;
|
| -
|
| - default_token.token = DEFAULT_TOKEN;
|
| - default_token.width = 1;
|
| - default_token.separator = BAD_CAST(DEFAULT_SEPARATOR);
|
| -
|
| -
|
| - tokens->start = NULL;
|
| - tokens->tokens[0].separator = NULL;
|
| - tokens->end = NULL;
|
| -
|
| - /*
|
| - * Insert initial non-alphanumeric token.
|
| - * There is always such a token in the list, even if NULL
|
| - */
|
| - while (! (IS_LETTER(val=xmlStringCurrentChar(NULL, format+ix, &len)) ||
|
| - IS_DIGIT(val)) ) {
|
| - if (format[ix] == 0) /* if end of format string */
|
| - break; /* while */
|
| - ix += len;
|
| - }
|
| - if (ix > 0)
|
| - tokens->start = xmlStrndup(format, ix);
|
| -
|
| -
|
| - for (tokens->nTokens = 0; tokens->nTokens < MAX_TOKENS;
|
| - tokens->nTokens++) {
|
| - if (format[ix] == 0)
|
| - break; /* for */
|
| -
|
| - /*
|
| - * separator has already been parsed (except for the first
|
| - * number) in tokens->end, recover it.
|
| - */
|
| - if (tokens->nTokens > 0) {
|
| - tokens->tokens[tokens->nTokens].separator = tokens->end;
|
| - tokens->end = NULL;
|
| - }
|
| -
|
| - val = xmlStringCurrentChar(NULL, format+ix, &len);
|
| - if (IS_DIGIT_ONE(val) ||
|
| - IS_DIGIT_ZERO(val)) {
|
| - tokens->tokens[tokens->nTokens].width = 1;
|
| - while (IS_DIGIT_ZERO(val)) {
|
| - tokens->tokens[tokens->nTokens].width++;
|
| - ix += len;
|
| - val = xmlStringCurrentChar(NULL, format+ix, &len);
|
| - }
|
| - if (IS_DIGIT_ONE(val)) {
|
| - tokens->tokens[tokens->nTokens].token = val - 1;
|
| - ix += len;
|
| - val = xmlStringCurrentChar(NULL, format+ix, &len);
|
| - }
|
| - } else if ( (val == (xmlChar)'A') ||
|
| - (val == (xmlChar)'a') ||
|
| - (val == (xmlChar)'I') ||
|
| - (val == (xmlChar)'i') ) {
|
| - tokens->tokens[tokens->nTokens].token = val;
|
| - ix += len;
|
| - val = xmlStringCurrentChar(NULL, format+ix, &len);
|
| - } else {
|
| - /* XSLT section 7.7
|
| - * "Any other format token indicates a numbering sequence
|
| - * that starts with that token. If an implementation does
|
| - * not support a numbering sequence that starts with that
|
| - * token, it must use a format token of 1."
|
| - */
|
| - tokens->tokens[tokens->nTokens].token = (xmlChar)'0';
|
| - tokens->tokens[tokens->nTokens].width = 1;
|
| - }
|
| - /*
|
| - * Skip over remaining alphanumeric characters from the Nd
|
| - * (Number, decimal digit), Nl (Number, letter), No (Number,
|
| - * other), Lu (Letter, uppercase), Ll (Letter, lowercase), Lt
|
| - * (Letters, titlecase), Lm (Letters, modifiers), and Lo
|
| - * (Letters, other (uncased)) Unicode categories. This happens
|
| - * to correspond to the Letter and Digit classes from XML (and
|
| - * one wonders why XSLT doesn't refer to these instead).
|
| - */
|
| - while (IS_LETTER(val) || IS_DIGIT(val)) {
|
| - ix += len;
|
| - val = xmlStringCurrentChar(NULL, format+ix, &len);
|
| - }
|
| -
|
| - /*
|
| - * Insert temporary non-alphanumeric final tooken.
|
| - */
|
| - j = ix;
|
| - while (! (IS_LETTER(val) || IS_DIGIT(val))) {
|
| - if (val == 0)
|
| - break; /* while */
|
| - ix += len;
|
| - val = xmlStringCurrentChar(NULL, format+ix, &len);
|
| - }
|
| - if (ix > j)
|
| - tokens->end = xmlStrndup(&format[j], ix - j);
|
| - }
|
| -}
|
| -
|
| -static void
|
| -xsltNumberFormatInsertNumbers(xsltNumberDataPtr data,
|
| - double *numbers,
|
| - int numbers_max,
|
| - xsltFormatPtr tokens,
|
| - xmlBufferPtr buffer)
|
| -{
|
| - int i = 0;
|
| - double number;
|
| - xsltFormatTokenPtr token;
|
| -
|
| - /*
|
| - * Handle initial non-alphanumeric token
|
| - */
|
| - if (tokens->start != NULL)
|
| - xmlBufferCat(buffer, tokens->start);
|
| -
|
| - for (i = 0; i < numbers_max; i++) {
|
| - /* Insert number */
|
| - number = numbers[(numbers_max - 1) - i];
|
| - /* Round to nearest like XSLT 2.0 */
|
| - number = floor(number + 0.5);
|
| - /*
|
| - * XSLT 1.0 isn't clear on how to handle negative numbers, but XSLT
|
| - * 2.0 says:
|
| - *
|
| - * It is a non-recoverable dynamic error if any undiscarded item
|
| - * in the atomized sequence supplied as the value of the value
|
| - * attribute of xsl:number cannot be converted to an integer, or
|
| - * if the resulting integer is less than 0 (zero).
|
| - */
|
| - if (number < 0.0) {
|
| - xsltTransformError(NULL, NULL, NULL,
|
| - "xsl-number : negative value\n");
|
| - /* Recover by treating negative values as zero. */
|
| - number = 0.0;
|
| - }
|
| - if (i < tokens->nTokens) {
|
| - /*
|
| - * The "n"th format token will be used to format the "n"th
|
| - * number in the list
|
| - */
|
| - token = &(tokens->tokens[i]);
|
| - } else if (tokens->nTokens > 0) {
|
| - /*
|
| - * If there are more numbers than format tokens, then the
|
| - * last format token will be used to format the remaining
|
| - * numbers.
|
| - */
|
| - token = &(tokens->tokens[tokens->nTokens - 1]);
|
| - } else {
|
| - /*
|
| - * If there are no format tokens, then a format token of
|
| - * 1 is used to format all numbers.
|
| - */
|
| - token = &default_token;
|
| - }
|
| -
|
| - /* Print separator, except for the first number */
|
| - if (i > 0) {
|
| - if (token->separator != NULL)
|
| - xmlBufferCat(buffer, token->separator);
|
| - else
|
| - xmlBufferCCat(buffer, DEFAULT_SEPARATOR);
|
| - }
|
| -
|
| - switch (xmlXPathIsInf(number)) {
|
| - case -1:
|
| - xmlBufferCCat(buffer, "-Infinity");
|
| - break;
|
| - case 1:
|
| - xmlBufferCCat(buffer, "Infinity");
|
| - break;
|
| - default:
|
| - if (xmlXPathIsNaN(number)) {
|
| - xmlBufferCCat(buffer, "NaN");
|
| - } else {
|
| -
|
| - switch (token->token) {
|
| - case 'A':
|
| - xsltNumberFormatAlpha(data, buffer, number, TRUE);
|
| - break;
|
| - case 'a':
|
| - xsltNumberFormatAlpha(data, buffer, number, FALSE);
|
| - break;
|
| - case 'I':
|
| - xsltNumberFormatRoman(data, buffer, number, TRUE);
|
| - break;
|
| - case 'i':
|
| - xsltNumberFormatRoman(data, buffer, number, FALSE);
|
| - break;
|
| - default:
|
| - if (IS_DIGIT_ZERO(token->token)) {
|
| - xsltNumberFormatDecimal(buffer,
|
| - number,
|
| - token->token,
|
| - token->width,
|
| - data->digitsPerGroup,
|
| - data->groupingCharacter,
|
| - data->groupingCharacterLen);
|
| - }
|
| - break;
|
| - }
|
| - }
|
| -
|
| - }
|
| - }
|
| -
|
| - /*
|
| - * Handle final non-alphanumeric token
|
| - */
|
| - if (tokens->end != NULL)
|
| - xmlBufferCat(buffer, tokens->end);
|
| -
|
| -}
|
| -
|
| -static int
|
| -xsltTestCompMatchCount(xsltTransformContextPtr context,
|
| - xmlNodePtr node,
|
| - xsltCompMatchPtr countPat,
|
| - xmlNodePtr cur)
|
| -{
|
| - if (countPat != NULL) {
|
| - return xsltTestCompMatchList(context, node, countPat);
|
| - }
|
| - else {
|
| - /*
|
| - * 7.7 Numbering
|
| - *
|
| - * If count attribute is not specified, then it defaults to the
|
| - * pattern that matches any node with the same node type as the
|
| - * current node and, if the current node has an expanded-name, with
|
| - * the same expanded-name as the current node.
|
| - */
|
| - if (node->type != cur->type)
|
| - return 0;
|
| - if (node->type == XML_NAMESPACE_DECL)
|
| - /*
|
| - * Namespace nodes have no preceding siblings and no parents
|
| - * that are namespace nodes. This means that node == cur.
|
| - */
|
| - return 1;
|
| - /* TODO: Skip node types without expanded names like text nodes. */
|
| - if (!xmlStrEqual(node->name, cur->name))
|
| - return 0;
|
| - if (node->ns == cur->ns)
|
| - return 1;
|
| - if ((node->ns == NULL) || (cur->ns == NULL))
|
| - return 0;
|
| - return (xmlStrEqual(node->ns->href, cur->ns->href));
|
| - }
|
| -}
|
| -
|
| -static int
|
| -xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
|
| - xmlNodePtr node,
|
| - xsltCompMatchPtr countPat,
|
| - xsltCompMatchPtr fromPat,
|
| - double *array)
|
| -{
|
| - int amount = 0;
|
| - int cnt = 0;
|
| - xmlNodePtr cur = node;
|
| -
|
| - while (cur != NULL) {
|
| - /* process current node */
|
| - if (xsltTestCompMatchCount(context, cur, countPat, node))
|
| - cnt++;
|
| - if ((fromPat != NULL) &&
|
| - xsltTestCompMatchList(context, cur, fromPat)) {
|
| - break; /* while */
|
| - }
|
| -
|
| - /* Skip to next preceding or ancestor */
|
| - if ((cur->type == XML_DOCUMENT_NODE) ||
|
| -#ifdef LIBXML_DOCB_ENABLED
|
| - (cur->type == XML_DOCB_DOCUMENT_NODE) ||
|
| -#endif
|
| - (cur->type == XML_HTML_DOCUMENT_NODE))
|
| - break; /* while */
|
| -
|
| - if (cur->type == XML_NAMESPACE_DECL) {
|
| - /*
|
| - * The XPath module stores the parent of a namespace node in
|
| - * the ns->next field.
|
| - */
|
| - cur = (xmlNodePtr) ((xmlNsPtr) cur)->next;
|
| - } else if (cur->type == XML_ATTRIBUTE_NODE) {
|
| - cur = cur->parent;
|
| - } else {
|
| - while ((cur->prev != NULL) && ((cur->prev->type == XML_DTD_NODE) ||
|
| - (cur->prev->type == XML_XINCLUDE_START) ||
|
| - (cur->prev->type == XML_XINCLUDE_END)))
|
| - cur = cur->prev;
|
| - if (cur->prev != NULL) {
|
| - for (cur = cur->prev; cur->last != NULL; cur = cur->last);
|
| - } else {
|
| - cur = cur->parent;
|
| - }
|
| - }
|
| - }
|
| -
|
| - array[amount++] = (double) cnt;
|
| -
|
| - return(amount);
|
| -}
|
| -
|
| -static int
|
| -xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context,
|
| - xmlNodePtr node,
|
| - xsltCompMatchPtr countPat,
|
| - xsltCompMatchPtr fromPat,
|
| - double *array,
|
| - int max)
|
| -{
|
| - int amount = 0;
|
| - int cnt;
|
| - xmlNodePtr ancestor;
|
| - xmlNodePtr preceding;
|
| - xmlXPathParserContextPtr parser;
|
| -
|
| - context->xpathCtxt->node = node;
|
| - parser = xmlXPathNewParserContext(NULL, context->xpathCtxt);
|
| - if (parser) {
|
| - /* ancestor-or-self::*[count] */
|
| - for (ancestor = node;
|
| - (ancestor != NULL) && (ancestor->type != XML_DOCUMENT_NODE);
|
| - ancestor = xmlXPathNextAncestor(parser, ancestor)) {
|
| -
|
| - if ((fromPat != NULL) &&
|
| - xsltTestCompMatchList(context, ancestor, fromPat))
|
| - break; /* for */
|
| -
|
| - if (xsltTestCompMatchCount(context, ancestor, countPat, node)) {
|
| - /* count(preceding-sibling::*) */
|
| - cnt = 1;
|
| - for (preceding =
|
| - xmlXPathNextPrecedingSibling(parser, ancestor);
|
| - preceding != NULL;
|
| - preceding =
|
| - xmlXPathNextPrecedingSibling(parser, preceding)) {
|
| -
|
| - if (xsltTestCompMatchCount(context, preceding, countPat,
|
| - node))
|
| - cnt++;
|
| - }
|
| - array[amount++] = (double)cnt;
|
| - if (amount >= max)
|
| - break; /* for */
|
| - }
|
| - }
|
| - xmlXPathFreeParserContext(parser);
|
| - }
|
| - return amount;
|
| -}
|
| -
|
| -static int
|
| -xsltNumberFormatGetValue(xmlXPathContextPtr context,
|
| - xmlNodePtr node,
|
| - const xmlChar *value,
|
| - double *number)
|
| -{
|
| - int amount = 0;
|
| - xmlBufferPtr pattern;
|
| - xmlXPathObjectPtr obj;
|
| -
|
| - pattern = xmlBufferCreate();
|
| - if (pattern != NULL) {
|
| - xmlBufferCCat(pattern, "number(");
|
| - xmlBufferCat(pattern, value);
|
| - xmlBufferCCat(pattern, ")");
|
| - context->node = node;
|
| - obj = xmlXPathEvalExpression(xmlBufferContent(pattern),
|
| - context);
|
| - if (obj != NULL) {
|
| - *number = obj->floatval;
|
| - amount++;
|
| - xmlXPathFreeObject(obj);
|
| - }
|
| - xmlBufferFree(pattern);
|
| - }
|
| - return amount;
|
| -}
|
| -
|
| -/**
|
| - * xsltNumberFormat:
|
| - * @ctxt: the XSLT transformation context
|
| - * @data: the formatting informations
|
| - * @node: the data to format
|
| - *
|
| - * Convert one number.
|
| - */
|
| -void
|
| -xsltNumberFormat(xsltTransformContextPtr ctxt,
|
| - xsltNumberDataPtr data,
|
| - xmlNodePtr node)
|
| -{
|
| - xmlBufferPtr output = NULL;
|
| - int amount, i;
|
| - double number;
|
| - xsltFormat tokens;
|
| -
|
| - if (data->format != NULL) {
|
| - xsltNumberFormatTokenize(data->format, &tokens);
|
| - }
|
| - else {
|
| - xmlChar *format;
|
| -
|
| - /* The format needs to be recomputed each time */
|
| - if (data->has_format == 0)
|
| - return;
|
| - format = xsltEvalAttrValueTemplate(ctxt, data->node,
|
| - (const xmlChar *) "format",
|
| - XSLT_NAMESPACE);
|
| - if (format == NULL)
|
| - return;
|
| - xsltNumberFormatTokenize(format, &tokens);
|
| - xmlFree(format);
|
| - }
|
| -
|
| - output = xmlBufferCreate();
|
| - if (output == NULL)
|
| - goto XSLT_NUMBER_FORMAT_END;
|
| -
|
| - /*
|
| - * Evaluate the XPath expression to find the value(s)
|
| - */
|
| - if (data->value) {
|
| - amount = xsltNumberFormatGetValue(ctxt->xpathCtxt,
|
| - node,
|
| - data->value,
|
| - &number);
|
| - if (amount == 1) {
|
| - xsltNumberFormatInsertNumbers(data,
|
| - &number,
|
| - 1,
|
| - &tokens,
|
| - output);
|
| - }
|
| -
|
| - } else if (data->level) {
|
| -
|
| - if (xmlStrEqual(data->level, (const xmlChar *) "single")) {
|
| - amount = xsltNumberFormatGetMultipleLevel(ctxt,
|
| - node,
|
| - data->countPat,
|
| - data->fromPat,
|
| - &number,
|
| - 1);
|
| - if (amount == 1) {
|
| - xsltNumberFormatInsertNumbers(data,
|
| - &number,
|
| - 1,
|
| - &tokens,
|
| - output);
|
| - }
|
| - } else if (xmlStrEqual(data->level, (const xmlChar *) "multiple")) {
|
| - double numarray[1024];
|
| - int max = sizeof(numarray)/sizeof(numarray[0]);
|
| - amount = xsltNumberFormatGetMultipleLevel(ctxt,
|
| - node,
|
| - data->countPat,
|
| - data->fromPat,
|
| - numarray,
|
| - max);
|
| - if (amount > 0) {
|
| - xsltNumberFormatInsertNumbers(data,
|
| - numarray,
|
| - amount,
|
| - &tokens,
|
| - output);
|
| - }
|
| - } else if (xmlStrEqual(data->level, (const xmlChar *) "any")) {
|
| - amount = xsltNumberFormatGetAnyLevel(ctxt,
|
| - node,
|
| - data->countPat,
|
| - data->fromPat,
|
| - &number);
|
| - if (amount > 0) {
|
| - xsltNumberFormatInsertNumbers(data,
|
| - &number,
|
| - 1,
|
| - &tokens,
|
| - output);
|
| - }
|
| - }
|
| - }
|
| - /* Insert number as text node */
|
| - xsltCopyTextString(ctxt, ctxt->insert, xmlBufferContent(output), 0);
|
| -
|
| - xmlBufferFree(output);
|
| -
|
| -XSLT_NUMBER_FORMAT_END:
|
| - if (tokens.start != NULL)
|
| - xmlFree(tokens.start);
|
| - if (tokens.end != NULL)
|
| - xmlFree(tokens.end);
|
| - for (i = 0;i < tokens.nTokens;i++) {
|
| - if (tokens.tokens[i].separator != NULL)
|
| - xmlFree(tokens.tokens[i].separator);
|
| - }
|
| -}
|
| -
|
| -static int
|
| -xsltFormatNumberPreSuffix(xsltDecimalFormatPtr self, xmlChar **format, xsltFormatNumberInfoPtr info)
|
| -{
|
| - int count=0; /* will hold total length of prefix/suffix */
|
| - int len;
|
| -
|
| - while (1) {
|
| - /*
|
| - * prefix / suffix ends at end of string or at
|
| - * first 'special' character
|
| - */
|
| - if (**format == 0)
|
| - return count;
|
| - /* if next character 'escaped' just count it */
|
| - if (**format == SYMBOL_QUOTE) {
|
| - if (*++(*format) == 0)
|
| - return -1;
|
| - }
|
| - else if (IS_SPECIAL(self, *format))
|
| - return count;
|
| - /*
|
| - * else treat percent/per-mille as special cases,
|
| - * depending on whether +ve or -ve
|
| - */
|
| - else {
|
| - /*
|
| - * for +ve prefix/suffix, allow only a
|
| - * single occurence of either
|
| - */
|
| - if (xsltUTF8Charcmp(*format, self->percent) == 0) {
|
| - if (info->is_multiplier_set)
|
| - return -1;
|
| - info->multiplier = 100;
|
| - info->is_multiplier_set = TRUE;
|
| - } else if (xsltUTF8Charcmp(*format, self->permille) == 0) {
|
| - if (info->is_multiplier_set)
|
| - return -1;
|
| - info->multiplier = 1000;
|
| - info->is_multiplier_set = TRUE;
|
| - }
|
| - }
|
| -
|
| - if ((len=xsltUTF8Size(*format)) < 1)
|
| - return -1;
|
| - count += len;
|
| - *format += len;
|
| - }
|
| -}
|
| -
|
| -/**
|
| - * xsltFormatNumberConversion:
|
| - * @self: the decimal format
|
| - * @format: the format requested
|
| - * @number: the value to format
|
| - * @result: the place to ouput the result
|
| - *
|
| - * format-number() uses the JDK 1.1 DecimalFormat class:
|
| - *
|
| - * http://java.sun.com/products/jdk/1.1/docs/api/java.text.DecimalFormat.html
|
| - *
|
| - * Structure:
|
| - *
|
| - * pattern := subpattern{;subpattern}
|
| - * subpattern := {prefix}integer{.fraction}{suffix}
|
| - * prefix := '\\u0000'..'\\uFFFD' - specialCharacters
|
| - * suffix := '\\u0000'..'\\uFFFD' - specialCharacters
|
| - * integer := '#'* '0'* '0'
|
| - * fraction := '0'* '#'*
|
| - *
|
| - * Notation:
|
| - * X* 0 or more instances of X
|
| - * (X | Y) either X or Y.
|
| - * X..Y any character from X up to Y, inclusive.
|
| - * S - T characters in S, except those in T
|
| - *
|
| - * Special Characters:
|
| - *
|
| - * Symbol Meaning
|
| - * 0 a digit
|
| - * # a digit, zero shows as absent
|
| - * . placeholder for decimal separator
|
| - * , placeholder for grouping separator.
|
| - * ; separates formats.
|
| - * - default negative prefix.
|
| - * % multiply by 100 and show as percentage
|
| - * ? multiply by 1000 and show as per mille
|
| - * X any other characters can be used in the prefix or suffix
|
| - * ' used to quote special characters in a prefix or suffix.
|
| - *
|
| - * Returns a possible XPath error
|
| - */
|
| -xmlXPathError
|
| -xsltFormatNumberConversion(xsltDecimalFormatPtr self,
|
| - xmlChar *format,
|
| - double number,
|
| - xmlChar **result)
|
| -{
|
| - xmlXPathError status = XPATH_EXPRESSION_OK;
|
| - xmlBufferPtr buffer;
|
| - xmlChar *the_format, *prefix = NULL, *suffix = NULL;
|
| - xmlChar *nprefix, *nsuffix = NULL;
|
| - xmlChar pchar;
|
| - int prefix_length, suffix_length = 0, nprefix_length, nsuffix_length;
|
| - double scale;
|
| - int j, len;
|
| - int self_grouping_len;
|
| - xsltFormatNumberInfo format_info;
|
| - /*
|
| - * delayed_multiplier allows a 'trailing' percent or
|
| - * permille to be treated as suffix
|
| - */
|
| - int delayed_multiplier = 0;
|
| - /* flag to show no -ve format present for -ve number */
|
| - char default_sign = 0;
|
| - /* flag to show error found, should use default format */
|
| - char found_error = 0;
|
| -
|
| - if (xmlStrlen(format) <= 0) {
|
| - xsltTransformError(NULL, NULL, NULL,
|
| - "xsltFormatNumberConversion : "
|
| - "Invalid format (0-length)\n");
|
| - }
|
| - *result = NULL;
|
| - switch (xmlXPathIsInf(number)) {
|
| - case -1:
|
| - if (self->minusSign == NULL)
|
| - *result = xmlStrdup(BAD_CAST "-");
|
| - else
|
| - *result = xmlStrdup(self->minusSign);
|
| - /* no-break on purpose */
|
| - case 1:
|
| - if ((self == NULL) || (self->infinity == NULL))
|
| - *result = xmlStrcat(*result, BAD_CAST "Infinity");
|
| - else
|
| - *result = xmlStrcat(*result, self->infinity);
|
| - return(status);
|
| - default:
|
| - if (xmlXPathIsNaN(number)) {
|
| - if ((self == NULL) || (self->noNumber == NULL))
|
| - *result = xmlStrdup(BAD_CAST "NaN");
|
| - else
|
| - *result = xmlStrdup(self->noNumber);
|
| - return(status);
|
| - }
|
| - }
|
| -
|
| - buffer = xmlBufferCreate();
|
| - if (buffer == NULL) {
|
| - return XPATH_MEMORY_ERROR;
|
| - }
|
| -
|
| - format_info.integer_hash = 0;
|
| - format_info.integer_digits = 0;
|
| - format_info.frac_digits = 0;
|
| - format_info.frac_hash = 0;
|
| - format_info.group = -1;
|
| - format_info.multiplier = 1;
|
| - format_info.add_decimal = FALSE;
|
| - format_info.is_multiplier_set = FALSE;
|
| - format_info.is_negative_pattern = FALSE;
|
| -
|
| - the_format = format;
|
| -
|
| - /*
|
| - * First we process the +ve pattern to get percent / permille,
|
| - * as well as main format
|
| - */
|
| - prefix = the_format;
|
| - prefix_length = xsltFormatNumberPreSuffix(self, &the_format, &format_info);
|
| - if (prefix_length < 0) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| -
|
| - /*
|
| - * Here we process the "number" part of the format. It gets
|
| - * a little messy because of the percent/per-mille - if that
|
| - * appears at the end, it may be part of the suffix instead
|
| - * of part of the number, so the variable delayed_multiplier
|
| - * is used to handle it
|
| - */
|
| - self_grouping_len = xmlStrlen(self->grouping);
|
| - while ((*the_format != 0) &&
|
| - (xsltUTF8Charcmp(the_format, self->decimalPoint) != 0) &&
|
| - (xsltUTF8Charcmp(the_format, self->patternSeparator) != 0)) {
|
| -
|
| - if (delayed_multiplier != 0) {
|
| - format_info.multiplier = delayed_multiplier;
|
| - format_info.is_multiplier_set = TRUE;
|
| - delayed_multiplier = 0;
|
| - }
|
| - if (xsltUTF8Charcmp(the_format, self->digit) == 0) {
|
| - if (format_info.integer_digits > 0) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - format_info.integer_hash++;
|
| - if (format_info.group >= 0)
|
| - format_info.group++;
|
| - } else if (xsltUTF8Charcmp(the_format, self->zeroDigit) == 0) {
|
| - format_info.integer_digits++;
|
| - if (format_info.group >= 0)
|
| - format_info.group++;
|
| - } else if ((self_grouping_len > 0) &&
|
| - (!xmlStrncmp(the_format, self->grouping, self_grouping_len))) {
|
| - /* Reset group count */
|
| - format_info.group = 0;
|
| - the_format += self_grouping_len;
|
| - continue;
|
| - } else if (xsltUTF8Charcmp(the_format, self->percent) == 0) {
|
| - if (format_info.is_multiplier_set) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - delayed_multiplier = 100;
|
| - } else if (xsltUTF8Charcmp(the_format, self->permille) == 0) {
|
| - if (format_info.is_multiplier_set) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - delayed_multiplier = 1000;
|
| - } else
|
| - break; /* while */
|
| -
|
| - if ((len=xsltUTF8Size(the_format)) < 1) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - the_format += len;
|
| -
|
| - }
|
| -
|
| - /* We have finished the integer part, now work on fraction */
|
| - if ( (*the_format != 0) &&
|
| - (xsltUTF8Charcmp(the_format, self->decimalPoint) == 0) ) {
|
| - format_info.add_decimal = TRUE;
|
| - the_format += xsltUTF8Size(the_format); /* Skip over the decimal */
|
| - }
|
| -
|
| - while (*the_format != 0) {
|
| -
|
| - if (xsltUTF8Charcmp(the_format, self->zeroDigit) == 0) {
|
| - if (format_info.frac_hash != 0) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - format_info.frac_digits++;
|
| - } else if (xsltUTF8Charcmp(the_format, self->digit) == 0) {
|
| - format_info.frac_hash++;
|
| - } else if (xsltUTF8Charcmp(the_format, self->percent) == 0) {
|
| - if (format_info.is_multiplier_set) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - delayed_multiplier = 100;
|
| - if ((len = xsltUTF8Size(the_format)) < 1) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - the_format += len;
|
| - continue; /* while */
|
| - } else if (xsltUTF8Charcmp(the_format, self->permille) == 0) {
|
| - if (format_info.is_multiplier_set) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - delayed_multiplier = 1000;
|
| - if ((len = xsltUTF8Size(the_format)) < 1) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - the_format += len;
|
| - continue; /* while */
|
| - } else if (xsltUTF8Charcmp(the_format, self->grouping) != 0) {
|
| - break; /* while */
|
| - }
|
| - if ((len = xsltUTF8Size(the_format)) < 1) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - the_format += len;
|
| - if (delayed_multiplier != 0) {
|
| - format_info.multiplier = delayed_multiplier;
|
| - delayed_multiplier = 0;
|
| - format_info.is_multiplier_set = TRUE;
|
| - }
|
| - }
|
| -
|
| - /*
|
| - * If delayed_multiplier is set after processing the
|
| - * "number" part, should be in suffix
|
| - */
|
| - if (delayed_multiplier != 0) {
|
| - the_format -= len;
|
| - delayed_multiplier = 0;
|
| - }
|
| -
|
| - suffix = the_format;
|
| - suffix_length = xsltFormatNumberPreSuffix(self, &the_format, &format_info);
|
| - if ( (suffix_length < 0) ||
|
| - ((*the_format != 0) &&
|
| - (xsltUTF8Charcmp(the_format, self->patternSeparator) != 0)) ) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| -
|
| - /*
|
| - * We have processed the +ve prefix, number part and +ve suffix.
|
| - * If the number is -ve, we must substitute the -ve prefix / suffix
|
| - */
|
| - if (number < 0) {
|
| - /*
|
| - * Note that j is the number of UTF8 chars before the separator,
|
| - * not the number of bytes! (bug 151975)
|
| - */
|
| - j = xmlUTF8Strloc(format, self->patternSeparator);
|
| - if (j < 0) {
|
| - /* No -ve pattern present, so use default signing */
|
| - default_sign = 1;
|
| - }
|
| - else {
|
| - /* Skip over pattern separator (accounting for UTF8) */
|
| - the_format = (xmlChar *)xmlUTF8Strpos(format, j + 1);
|
| - /*
|
| - * Flag changes interpretation of percent/permille
|
| - * in -ve pattern
|
| - */
|
| - format_info.is_negative_pattern = TRUE;
|
| - format_info.is_multiplier_set = FALSE;
|
| -
|
| - /* First do the -ve prefix */
|
| - nprefix = the_format;
|
| - nprefix_length = xsltFormatNumberPreSuffix(self,
|
| - &the_format, &format_info);
|
| - if (nprefix_length<0) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| -
|
| - while (*the_format != 0) {
|
| - if ( (xsltUTF8Charcmp(the_format, (self)->percent) == 0) ||
|
| - (xsltUTF8Charcmp(the_format, (self)->permille)== 0) ) {
|
| - if (format_info.is_multiplier_set) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - format_info.is_multiplier_set = TRUE;
|
| - delayed_multiplier = 1;
|
| - }
|
| - else if (IS_SPECIAL(self, the_format))
|
| - delayed_multiplier = 0;
|
| - else
|
| - break; /* while */
|
| - if ((len = xsltUTF8Size(the_format)) < 1) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - the_format += len;
|
| - }
|
| - if (delayed_multiplier != 0) {
|
| - format_info.is_multiplier_set = FALSE;
|
| - the_format -= len;
|
| - }
|
| -
|
| - /* Finally do the -ve suffix */
|
| - if (*the_format != 0) {
|
| - nsuffix = the_format;
|
| - nsuffix_length = xsltFormatNumberPreSuffix(self,
|
| - &the_format, &format_info);
|
| - if (nsuffix_length < 0) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - }
|
| - else
|
| - nsuffix_length = 0;
|
| - if (*the_format != 0) {
|
| - found_error = 1;
|
| - goto OUTPUT_NUMBER;
|
| - }
|
| - /*
|
| - * Here's another Java peculiarity:
|
| - * if -ve prefix/suffix == +ve ones, discard & use default
|
| - */
|
| - if ((nprefix_length != prefix_length) ||
|
| - (nsuffix_length != suffix_length) ||
|
| - ((nprefix_length > 0) &&
|
| - (xmlStrncmp(nprefix, prefix, prefix_length) !=0 )) ||
|
| - ((nsuffix_length > 0) &&
|
| - (xmlStrncmp(nsuffix, suffix, suffix_length) !=0 ))) {
|
| - prefix = nprefix;
|
| - prefix_length = nprefix_length;
|
| - suffix = nsuffix;
|
| - suffix_length = nsuffix_length;
|
| - } /* else {
|
| - default_sign = 1;
|
| - }
|
| - */
|
| - }
|
| - }
|
| -
|
| -OUTPUT_NUMBER:
|
| - if (found_error != 0) {
|
| - xsltTransformError(NULL, NULL, NULL,
|
| - "xsltFormatNumberConversion : "
|
| - "error in format string '%s', using default\n", format);
|
| - default_sign = (number < 0.0) ? 1 : 0;
|
| - prefix_length = suffix_length = 0;
|
| - format_info.integer_hash = 0;
|
| - format_info.integer_digits = 1;
|
| - format_info.frac_digits = 1;
|
| - format_info.frac_hash = 4;
|
| - format_info.group = -1;
|
| - format_info.multiplier = 1;
|
| - format_info.add_decimal = TRUE;
|
| - }
|
| -
|
| - /* Ready to output our number. First see if "default sign" is required */
|
| - if (default_sign != 0)
|
| - xmlBufferAdd(buffer, self->minusSign, xsltUTF8Size(self->minusSign));
|
| -
|
| - /* Put the prefix into the buffer */
|
| - for (j = 0; j < prefix_length; j++) {
|
| - if ((pchar = *prefix++) == SYMBOL_QUOTE) {
|
| - len = xsltUTF8Size(prefix);
|
| - xmlBufferAdd(buffer, prefix, len);
|
| - prefix += len;
|
| - j += len - 1; /* length of symbol less length of quote */
|
| - } else
|
| - xmlBufferAdd(buffer, &pchar, 1);
|
| - }
|
| -
|
| - /* Next do the integer part of the number */
|
| - number = fabs(number) * (double)format_info.multiplier;
|
| - scale = pow(10.0, (double)(format_info.frac_digits + format_info.frac_hash));
|
| - number = floor((scale * number + 0.5)) / scale;
|
| - if ((self->grouping != NULL) &&
|
| - (self->grouping[0] != 0)) {
|
| -
|
| - len = xmlStrlen(self->grouping);
|
| - pchar = xsltGetUTF8Char(self->grouping, &len);
|
| - xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
|
| - format_info.integer_digits,
|
| - format_info.group,
|
| - pchar, len);
|
| - } else
|
| - xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
|
| - format_info.integer_digits,
|
| - format_info.group,
|
| - ',', 1);
|
| -
|
| - /* Special case: java treats '.#' like '.0', '.##' like '.0#', etc. */
|
| - if ((format_info.integer_digits + format_info.integer_hash +
|
| - format_info.frac_digits == 0) && (format_info.frac_hash > 0)) {
|
| - ++format_info.frac_digits;
|
| - --format_info.frac_hash;
|
| - }
|
| -
|
| - /* Add leading zero, if required */
|
| - if ((floor(number) == 0) &&
|
| - (format_info.integer_digits + format_info.frac_digits == 0)) {
|
| - xmlBufferAdd(buffer, self->zeroDigit, xsltUTF8Size(self->zeroDigit));
|
| - }
|
| -
|
| - /* Next the fractional part, if required */
|
| - if (format_info.frac_digits + format_info.frac_hash == 0) {
|
| - if (format_info.add_decimal)
|
| - xmlBufferAdd(buffer, self->decimalPoint,
|
| - xsltUTF8Size(self->decimalPoint));
|
| - }
|
| - else {
|
| - number -= floor(number);
|
| - if ((number != 0) || (format_info.frac_digits != 0)) {
|
| - xmlBufferAdd(buffer, self->decimalPoint,
|
| - xsltUTF8Size(self->decimalPoint));
|
| - number = floor(scale * number + 0.5);
|
| - for (j = format_info.frac_hash; j > 0; j--) {
|
| - if (fmod(number, 10.0) >= 1.0)
|
| - break; /* for */
|
| - number /= 10.0;
|
| - }
|
| - xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
|
| - format_info.frac_digits + j,
|
| - 0, 0, 0);
|
| - }
|
| - }
|
| - /* Put the suffix into the buffer */
|
| - for (j = 0; j < suffix_length; j++) {
|
| - if ((pchar = *suffix++) == SYMBOL_QUOTE) {
|
| - len = xsltUTF8Size(suffix);
|
| - xmlBufferAdd(buffer, suffix, len);
|
| - suffix += len;
|
| - j += len - 1; /* length of symbol less length of escape */
|
| - } else
|
| - xmlBufferAdd(buffer, &pchar, 1);
|
| - }
|
| -
|
| - *result = xmlStrdup(xmlBufferContent(buffer));
|
| - xmlBufferFree(buffer);
|
| - return status;
|
| -}
|
| -
|
|
|