e769c42b057058b8c998379b620da635591dec69
[platform/upstream/libxslt.git] / libxslt / numbers.c
1 /*
2  * numbers.c: Implementation of the XSLT number functions
3  *
4  * Reference:
5  *   http://www.w3.org/TR/1999/REC-xslt-19991116
6  *
7  * See Copyright for the status of this software.
8  *
9  * daniel@veillard.com
10  * Bjorn Reese <breese@users.sourceforge.net>
11  */
12
13 #define IN_LIBXSLT
14 #include "libxslt.h"
15
16 #include <math.h>
17 #include <limits.h>
18 #include <float.h>
19 #include <string.h>
20
21 #include <libxml/xmlmemory.h>
22 #include <libxml/parserInternals.h>
23 #include <libxml/xpath.h>
24 #include <libxml/xpathInternals.h>
25 #include <libxml/encoding.h>
26 #include "xsltutils.h"
27 #include "pattern.h"
28 #include "templates.h"
29 #include "transform.h"
30 #include "numbersInternals.h"
31
32 #ifndef FALSE
33 # define FALSE (0 == 1)
34 # define TRUE (1 == 1)
35 #endif
36
37 #define SYMBOL_QUOTE            ((xmlChar)'\'')
38
39 #define DEFAULT_TOKEN           (xmlChar)'0'
40 #define DEFAULT_SEPARATOR       "."
41
42 #define MAX_TOKENS              1024
43
44 typedef struct _xsltFormatToken xsltFormatToken;
45 typedef xsltFormatToken *xsltFormatTokenPtr;
46 struct _xsltFormatToken {
47     xmlChar     *separator;
48     xmlChar      token;
49     int          width;
50 };
51
52 typedef struct _xsltFormat xsltFormat;
53 typedef xsltFormat *xsltFormatPtr;
54 struct _xsltFormat {
55     xmlChar             *start;
56     xsltFormatToken      tokens[MAX_TOKENS];
57     int                  nTokens;
58     xmlChar             *end;
59 };
60
61 static char alpha_upper_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
62 static char alpha_lower_list[] = "abcdefghijklmnopqrstuvwxyz";
63 static xsltFormatToken default_token;
64
65 /*
66  * **** Start temp insert ****
67  *
68  * The following two routines (xsltUTF8Size and xsltUTF8Charcmp)
69  * will be replaced with calls to the corresponding libxml routines
70  * at a later date (when other inter-library dependencies require it)
71  */
72
73 /**
74  * xsltUTF8Size:
75  * @utf: pointer to the UTF8 character
76  *
77  * returns the numbers of bytes in the character, -1 on format error
78  */
79 static int
80 xsltUTF8Size(xmlChar *utf) {
81     xmlChar mask;
82     int len;
83
84     if (utf == NULL)
85         return -1;
86     if (*utf < 0x80)
87         return 1;
88     /* check valid UTF8 character */
89     if (!(*utf & 0x40))
90         return -1;
91     /* determine number of bytes in char */
92     len = 2;
93     for (mask=0x20; mask != 0; mask>>=1) {
94         if (!(*utf & mask))
95             return len;
96         len++;
97     }
98     return -1;
99 }
100
101 /**
102  * xsltUTF8Charcmp
103  * @utf1: pointer to first UTF8 char
104  * @utf2: pointer to second UTF8 char
105  *
106  * returns result of comparing the two UCS4 values
107  * as with xmlStrncmp
108  */
109 static int
110 xsltUTF8Charcmp(xmlChar *utf1, xmlChar *utf2) {
111
112     if (utf1 == NULL ) {
113         if (utf2 == NULL)
114             return 0;
115         return -1;
116     }
117     return xmlStrncmp(utf1, utf2, xsltUTF8Size(utf1));
118 }
119
120 /***** Stop temp insert *****/
121 /************************************************************************
122  *                                                                      *
123  *                      Utility functions                               *
124  *                                                                      *
125  ************************************************************************/
126
127 #define IS_SPECIAL(self,letter)                 \
128     ((xsltUTF8Charcmp((letter), (self)->zeroDigit) == 0)            ||  \
129      (xsltUTF8Charcmp((letter), (self)->digit) == 0)        ||  \
130      (xsltUTF8Charcmp((letter), (self)->decimalPoint) == 0)  || \
131      (xsltUTF8Charcmp((letter), (self)->grouping) == 0)     ||  \
132      (xsltUTF8Charcmp((letter), (self)->patternSeparator) == 0))
133
134 #define IS_DIGIT_ZERO(x) xsltIsDigitZero(x)
135 #define IS_DIGIT_ONE(x) xsltIsDigitZero((xmlChar)(x)-1)
136
137 static int
138 xsltIsDigitZero(unsigned int ch)
139 {
140     /*
141      * Reference: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
142      */
143     switch (ch) {
144     case 0x0030: case 0x0660: case 0x06F0: case 0x0966:
145     case 0x09E6: case 0x0A66: case 0x0AE6: case 0x0B66:
146     case 0x0C66: case 0x0CE6: case 0x0D66: case 0x0E50:
147     case 0x0E60: case 0x0F20: case 0x1040: case 0x17E0:
148     case 0x1810: case 0xFF10:
149         return TRUE;
150     default:
151         return FALSE;
152     }
153 }
154
155 static void
156 xsltNumberFormatDecimal(xmlBufferPtr buffer,
157                         double number,
158                         int digit_zero,
159                         int width,
160                         int digitsPerGroup,
161                         int groupingCharacter,
162                         int groupingCharacterLen)
163 {
164     /*
165      * This used to be
166      *  xmlChar temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 4];
167      * which would be length 68 on x86 arch.  It was changed to be a longer,
168      * fixed length in order to try to cater for (reasonable) UTF8
169      * separators and numeric characters.  The max UTF8 char size will be
170      * 6 or less, so the value used [500] should be *much* larger than needed
171      */
172     xmlChar temp_string[500];
173     xmlChar *pointer;
174     xmlChar temp_char[6];
175     int i;
176     int val;
177     int len;
178
179     /* Build buffer from back */
180     pointer = &temp_string[sizeof(temp_string)] - 1;    /* last char */
181     *pointer = 0;
182     i = 0;
183     while (pointer > temp_string) {
184         if ((i >= width) && (fabs(number) < 1.0))
185             break; /* for */
186         if ((i > 0) && (groupingCharacter != 0) &&
187             (digitsPerGroup > 0) &&
188             ((i % digitsPerGroup) == 0)) {
189             if (pointer - groupingCharacterLen < temp_string) {
190                 i = -1;         /* flag error */
191                 break;
192             }
193             pointer -= groupingCharacterLen;
194             xmlCopyCharMultiByte(pointer, groupingCharacter);
195         }
196
197         val = digit_zero + (int)fmod(number, 10.0);
198         if (val < 0x80) {                       /* shortcut if ASCII */
199             if (pointer <= temp_string) {       /* Check enough room */
200                 i = -1;
201                 break;
202             }
203             *(--pointer) = val;
204         }
205         else {
206         /*
207          * Here we have a multibyte character.  It's a little messy,
208          * because until we generate the char we don't know how long
209          * it is.  So, we generate it into the buffer temp_char, then
210          * copy from there into temp_string.
211          */
212             len = xmlCopyCharMultiByte(temp_char, val);
213             if ( (pointer - len) < temp_string ) {
214                 i = -1;
215                 break;
216             }
217             pointer -= len;
218             memcpy(pointer, temp_char, len);
219         }
220         number /= 10.0;
221         ++i;
222     }
223     if (i < 0)
224         xsltGenericError(xsltGenericErrorContext,
225                 "xsltNumberFormatDecimal: Internal buffer size exceeded");
226     xmlBufferCat(buffer, pointer);
227 }
228
229 static void
230 xsltNumberFormatAlpha(xsltNumberDataPtr data,
231                       xmlBufferPtr buffer,
232                       double number,
233                       int is_upper)
234 {
235     char temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 1];
236     char *pointer;
237     int i;
238     char *alpha_list;
239     double alpha_size = (double)(sizeof(alpha_upper_list) - 1);
240
241     /*
242      * XSLT 1.0 isn't clear on how to handle zero, but XSLT 2.0 says:
243      *
244      *     For all format tokens other than the first kind above (one that
245      *     consists of decimal digits), there may be implementation-defined
246      *     lower and upper bounds on the range of numbers that can be
247      *     formatted using this format token; indeed, for some numbering
248      *     sequences there may be intrinsic limits. [...] Numbers that fall
249      *     outside this range must be formatted using the format token 1.
250      *
251      * The "a" token has an intrinsic lower limit of 1.
252      */
253     if (number < 1.0) {
254         xsltNumberFormatDecimal(buffer, number, '0', 1,
255                                 data->digitsPerGroup,
256                                 data->groupingCharacter,
257                                 data->groupingCharacterLen);
258         return;
259     }
260
261     /* Build buffer from back */
262     pointer = &temp_string[sizeof(temp_string)];
263     *(--pointer) = 0;
264     alpha_list = (is_upper) ? alpha_upper_list : alpha_lower_list;
265
266     for (i = 1; i < (int)sizeof(temp_string); i++) {
267         number--;
268         *(--pointer) = alpha_list[((int)fmod(number, alpha_size))];
269         number /= alpha_size;
270         if (number < 1.0)
271             break; /* for */
272     }
273     xmlBufferCCat(buffer, pointer);
274 }
275
276 static void
277 xsltNumberFormatRoman(xsltNumberDataPtr data,
278                       xmlBufferPtr buffer,
279                       double number,
280                       int is_upper)
281 {
282     /*
283      * See discussion in xsltNumberFormatAlpha. Also use a reasonable upper
284      * bound to avoid denial of service.
285      */
286     if (number < 1.0 || number > 5000.0) {
287         xsltNumberFormatDecimal(buffer, number, '0', 1,
288                                 data->digitsPerGroup,
289                                 data->groupingCharacter,
290                                 data->groupingCharacterLen);
291         return;
292     }
293
294     /*
295      * Based on an example by Jim Walsh
296      */
297     while (number >= 1000.0) {
298         xmlBufferCCat(buffer, (is_upper) ? "M" : "m");
299         number -= 1000.0;
300     }
301     if (number >= 900.0) {
302         xmlBufferCCat(buffer, (is_upper) ? "CM" : "cm");
303         number -= 900.0;
304     }
305     while (number >= 500.0) {
306         xmlBufferCCat(buffer, (is_upper) ? "D" : "d");
307         number -= 500.0;
308     }
309     if (number >= 400.0) {
310         xmlBufferCCat(buffer, (is_upper) ? "CD" : "cd");
311         number -= 400.0;
312     }
313     while (number >= 100.0) {
314         xmlBufferCCat(buffer, (is_upper) ? "C" : "c");
315         number -= 100.0;
316     }
317     if (number >= 90.0) {
318         xmlBufferCCat(buffer, (is_upper) ? "XC" : "xc");
319         number -= 90.0;
320     }
321     while (number >= 50.0) {
322         xmlBufferCCat(buffer, (is_upper) ? "L" : "l");
323         number -= 50.0;
324     }
325     if (number >= 40.0) {
326         xmlBufferCCat(buffer, (is_upper) ? "XL" : "xl");
327         number -= 40.0;
328     }
329     while (number >= 10.0) {
330         xmlBufferCCat(buffer, (is_upper) ? "X" : "x");
331         number -= 10.0;
332     }
333     if (number >= 9.0) {
334         xmlBufferCCat(buffer, (is_upper) ? "IX" : "ix");
335         number -= 9.0;
336     }
337     while (number >= 5.0) {
338         xmlBufferCCat(buffer, (is_upper) ? "V" : "v");
339         number -= 5.0;
340     }
341     if (number >= 4.0) {
342         xmlBufferCCat(buffer, (is_upper) ? "IV" : "iv");
343         number -= 4.0;
344     }
345     while (number >= 1.0) {
346         xmlBufferCCat(buffer, (is_upper) ? "I" : "i");
347         number--;
348     }
349 }
350
351 static void
352 xsltNumberFormatTokenize(const xmlChar *format,
353                          xsltFormatPtr tokens)
354 {
355     int ix = 0;
356     int j;
357     int val;
358     int len;
359
360     default_token.token = DEFAULT_TOKEN;
361     default_token.width = 1;
362     default_token.separator = BAD_CAST(DEFAULT_SEPARATOR);
363
364
365     tokens->start = NULL;
366     tokens->tokens[0].separator = NULL;
367     tokens->end = NULL;
368
369     /*
370      * Insert initial non-alphanumeric token.
371      * There is always such a token in the list, even if NULL
372      */
373     while (! (IS_LETTER(val=xmlStringCurrentChar(NULL, format+ix, &len)) ||
374               IS_DIGIT(val)) ) {
375         if (format[ix] == 0)            /* if end of format string */
376             break; /* while */
377         ix += len;
378     }
379     if (ix > 0)
380         tokens->start = xmlStrndup(format, ix);
381
382
383     for (tokens->nTokens = 0; tokens->nTokens < MAX_TOKENS;
384          tokens->nTokens++) {
385         if (format[ix] == 0)
386             break; /* for */
387
388         /*
389          * separator has already been parsed (except for the first
390          * number) in tokens->end, recover it.
391          */
392         if (tokens->nTokens > 0) {
393             tokens->tokens[tokens->nTokens].separator = tokens->end;
394             tokens->end = NULL;
395         }
396
397         val = xmlStringCurrentChar(NULL, format+ix, &len);
398         if (IS_DIGIT_ONE(val) ||
399                  IS_DIGIT_ZERO(val)) {
400             tokens->tokens[tokens->nTokens].width = 1;
401             while (IS_DIGIT_ZERO(val)) {
402                 tokens->tokens[tokens->nTokens].width++;
403                 ix += len;
404                 val = xmlStringCurrentChar(NULL, format+ix, &len);
405             }
406             if (IS_DIGIT_ONE(val)) {
407                 tokens->tokens[tokens->nTokens].token = val - 1;
408                 ix += len;
409                 val = xmlStringCurrentChar(NULL, format+ix, &len);
410             }
411         } else if ( (val == (xmlChar)'A') ||
412                     (val == (xmlChar)'a') ||
413                     (val == (xmlChar)'I') ||
414                     (val == (xmlChar)'i') ) {
415             tokens->tokens[tokens->nTokens].token = val;
416             ix += len;
417             val = xmlStringCurrentChar(NULL, format+ix, &len);
418         } else {
419             /* XSLT section 7.7
420              * "Any other format token indicates a numbering sequence
421              *  that starts with that token. If an implementation does
422              *  not support a numbering sequence that starts with that
423              *  token, it must use a format token of 1."
424              */
425             tokens->tokens[tokens->nTokens].token = (xmlChar)'0';
426             tokens->tokens[tokens->nTokens].width = 1;
427         }
428         /*
429          * Skip over remaining alphanumeric characters from the Nd
430          * (Number, decimal digit), Nl (Number, letter), No (Number,
431          * other), Lu (Letter, uppercase), Ll (Letter, lowercase), Lt
432          * (Letters, titlecase), Lm (Letters, modifiers), and Lo
433          * (Letters, other (uncased)) Unicode categories. This happens
434          * to correspond to the Letter and Digit classes from XML (and
435          * one wonders why XSLT doesn't refer to these instead).
436          */
437         while (IS_LETTER(val) || IS_DIGIT(val)) {
438             ix += len;
439             val = xmlStringCurrentChar(NULL, format+ix, &len);
440         }
441
442         /*
443          * Insert temporary non-alphanumeric final tooken.
444          */
445         j = ix;
446         while (! (IS_LETTER(val) || IS_DIGIT(val))) {
447             if (val == 0)
448                 break; /* while */
449             ix += len;
450             val = xmlStringCurrentChar(NULL, format+ix, &len);
451         }
452         if (ix > j)
453             tokens->end = xmlStrndup(&format[j], ix - j);
454     }
455 }
456
457 static void
458 xsltNumberFormatInsertNumbers(xsltNumberDataPtr data,
459                               double *numbers,
460                               int numbers_max,
461                               xsltFormatPtr tokens,
462                               xmlBufferPtr buffer)
463 {
464     int i = 0;
465     double number;
466     xsltFormatTokenPtr token;
467
468     /*
469      * Handle initial non-alphanumeric token
470      */
471     if (tokens->start != NULL)
472          xmlBufferCat(buffer, tokens->start);
473
474     for (i = 0; i < numbers_max; i++) {
475         /* Insert number */
476         number = numbers[(numbers_max - 1) - i];
477         /* Round to nearest like XSLT 2.0 */
478         number = floor(number + 0.5);
479         /*
480          * XSLT 1.0 isn't clear on how to handle negative numbers, but XSLT
481          * 2.0 says:
482          *
483          *     It is a non-recoverable dynamic error if any undiscarded item
484          *     in the atomized sequence supplied as the value of the value
485          *     attribute of xsl:number cannot be converted to an integer, or
486          *     if the resulting integer is less than 0 (zero).
487          */
488         if (number < 0.0) {
489             xsltTransformError(NULL, NULL, NULL,
490                     "xsl-number : negative value\n");
491             /* Recover by treating negative values as zero. */
492             number = 0.0;
493         }
494         if (i < tokens->nTokens) {
495           /*
496            * The "n"th format token will be used to format the "n"th
497            * number in the list
498            */
499           token = &(tokens->tokens[i]);
500         } else if (tokens->nTokens > 0) {
501           /*
502            * If there are more numbers than format tokens, then the
503            * last format token will be used to format the remaining
504            * numbers.
505            */
506           token = &(tokens->tokens[tokens->nTokens - 1]);
507         } else {
508           /*
509            * If there are no format tokens, then a format token of
510            * 1 is used to format all numbers.
511            */
512           token = &default_token;
513         }
514
515         /* Print separator, except for the first number */
516         if (i > 0) {
517             if (token->separator != NULL)
518                 xmlBufferCat(buffer, token->separator);
519             else
520                 xmlBufferCCat(buffer, DEFAULT_SEPARATOR);
521         }
522
523         switch (xmlXPathIsInf(number)) {
524         case -1:
525             xmlBufferCCat(buffer, "-Infinity");
526             break;
527         case 1:
528             xmlBufferCCat(buffer, "Infinity");
529             break;
530         default:
531             if (xmlXPathIsNaN(number)) {
532                 xmlBufferCCat(buffer, "NaN");
533             } else {
534
535                 switch (token->token) {
536                 case 'A':
537                     xsltNumberFormatAlpha(data, buffer, number, TRUE);
538                     break;
539                 case 'a':
540                     xsltNumberFormatAlpha(data, buffer, number, FALSE);
541                     break;
542                 case 'I':
543                     xsltNumberFormatRoman(data, buffer, number, TRUE);
544                     break;
545                 case 'i':
546                     xsltNumberFormatRoman(data, buffer, number, FALSE);
547                     break;
548                 default:
549                     if (IS_DIGIT_ZERO(token->token)) {
550                         xsltNumberFormatDecimal(buffer,
551                                                 number,
552                                                 token->token,
553                                                 token->width,
554                                                 data->digitsPerGroup,
555                                                 data->groupingCharacter,
556                                                 data->groupingCharacterLen);
557                     }
558                     break;
559                 }
560             }
561
562         }
563     }
564
565     /*
566      * Handle final non-alphanumeric token
567      */
568     if (tokens->end != NULL)
569          xmlBufferCat(buffer, tokens->end);
570
571 }
572
573 static int
574 xsltTestCompMatchCount(xsltTransformContextPtr context,
575                        xmlNodePtr node,
576                        xsltCompMatchPtr countPat,
577                        xmlNodePtr cur)
578 {
579     if (countPat != NULL) {
580         return xsltTestCompMatchList(context, node, countPat);
581     }
582     else {
583         /*
584          * 7.7 Numbering
585          *
586          * If count attribute is not specified, then it defaults to the
587          * pattern that matches any node with the same node type as the
588          * current node and, if the current node has an expanded-name, with
589          * the same expanded-name as the current node.
590          */
591         if (node->type != cur->type)
592             return 0;
593         if (node->type == XML_NAMESPACE_DECL)
594             /*
595              * Namespace nodes have no preceding siblings and no parents
596              * that are namespace nodes. This means that node == cur.
597              */
598             return 1;
599         /* TODO: Skip node types without expanded names like text nodes. */
600         if (!xmlStrEqual(node->name, cur->name))
601             return 0;
602         if (node->ns == cur->ns)
603             return 1;
604         if ((node->ns == NULL) || (cur->ns == NULL))
605             return 0;
606         return (xmlStrEqual(node->ns->href, cur->ns->href));
607     }
608 }
609
610 static int
611 xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context,
612                             xmlNodePtr node,
613                             xsltCompMatchPtr countPat,
614                             xsltCompMatchPtr fromPat,
615                             double *array)
616 {
617     int amount = 0;
618     int cnt = 0;
619     xmlNodePtr cur;
620
621     /* select the starting node */
622     switch (node->type) {
623         case XML_ELEMENT_NODE:
624             cur = node;
625             break;
626         case XML_ATTRIBUTE_NODE:
627             cur = ((xmlAttrPtr) node)->parent;
628             break;
629         case XML_TEXT_NODE:
630         case XML_PI_NODE:
631         case XML_COMMENT_NODE:
632             cur = node->parent;
633             break;
634         default:
635             cur = NULL;
636             break;
637     }
638
639     while (cur != NULL) {
640         /* process current node */
641         if (xsltTestCompMatchCount(context, cur, countPat, node))
642             cnt++;
643         if ((fromPat != NULL) &&
644             xsltTestCompMatchList(context, cur, fromPat)) {
645             break; /* while */
646         }
647
648         /* Skip to next preceding or ancestor */
649         if ((cur->type == XML_DOCUMENT_NODE) ||
650 #ifdef LIBXML_DOCB_ENABLED
651             (cur->type == XML_DOCB_DOCUMENT_NODE) ||
652 #endif
653             (cur->type == XML_HTML_DOCUMENT_NODE))
654             break; /* while */
655
656         while ((cur->prev != NULL) && ((cur->prev->type == XML_DTD_NODE) ||
657                (cur->prev->type == XML_XINCLUDE_START) ||
658                (cur->prev->type == XML_XINCLUDE_END)))
659             cur = cur->prev;
660         if (cur->prev != NULL) {
661             for (cur = cur->prev; cur->last != NULL; cur = cur->last);
662         } else {
663             cur = cur->parent;
664         }
665
666     }
667
668     array[amount++] = (double) cnt;
669
670     return(amount);
671 }
672
673 static int
674 xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context,
675                                  xmlNodePtr node,
676                                  xsltCompMatchPtr countPat,
677                                  xsltCompMatchPtr fromPat,
678                                  double *array,
679                                  int max)
680 {
681     int amount = 0;
682     int cnt;
683     xmlNodePtr ancestor;
684     xmlNodePtr preceding;
685     xmlXPathParserContextPtr parser;
686
687     context->xpathCtxt->node = node;
688     parser = xmlXPathNewParserContext(NULL, context->xpathCtxt);
689     if (parser) {
690         /* ancestor-or-self::*[count] */
691         for (ancestor = node;
692              (ancestor != NULL) && (ancestor->type != XML_DOCUMENT_NODE);
693              ancestor = xmlXPathNextAncestor(parser, ancestor)) {
694
695             if ((fromPat != NULL) &&
696                 xsltTestCompMatchList(context, ancestor, fromPat))
697                 break; /* for */
698
699             if (xsltTestCompMatchCount(context, ancestor, countPat, node)) {
700                 /* count(preceding-sibling::*) */
701                 cnt = 1;
702                 for (preceding =
703                         xmlXPathNextPrecedingSibling(parser, ancestor);
704                      preceding != NULL;
705                      preceding =
706                         xmlXPathNextPrecedingSibling(parser, preceding)) {
707
708                     if (xsltTestCompMatchCount(context, preceding, countPat,
709                                                node))
710                         cnt++;
711                 }
712                 array[amount++] = (double)cnt;
713                 if (amount >= max)
714                     break; /* for */
715             }
716         }
717         xmlXPathFreeParserContext(parser);
718     }
719     return amount;
720 }
721
722 static int
723 xsltNumberFormatGetValue(xmlXPathContextPtr context,
724                          xmlNodePtr node,
725                          const xmlChar *value,
726                          double *number)
727 {
728     int amount = 0;
729     xmlBufferPtr pattern;
730     xmlXPathObjectPtr obj;
731
732     pattern = xmlBufferCreate();
733     if (pattern != NULL) {
734         xmlBufferCCat(pattern, "number(");
735         xmlBufferCat(pattern, value);
736         xmlBufferCCat(pattern, ")");
737         context->node = node;
738         obj = xmlXPathEvalExpression(xmlBufferContent(pattern),
739                                      context);
740         if (obj != NULL) {
741             *number = obj->floatval;
742             amount++;
743             xmlXPathFreeObject(obj);
744         }
745         xmlBufferFree(pattern);
746     }
747     return amount;
748 }
749
750 /**
751  * xsltNumberFormat:
752  * @ctxt: the XSLT transformation context
753  * @data: the formatting informations
754  * @node: the data to format
755  *
756  * Convert one number.
757  */
758 void
759 xsltNumberFormat(xsltTransformContextPtr ctxt,
760                  xsltNumberDataPtr data,
761                  xmlNodePtr node)
762 {
763     xmlBufferPtr output = NULL;
764     int amount, i;
765     double number;
766     xsltFormat tokens;
767
768     if (data->format != NULL) {
769         xsltNumberFormatTokenize(data->format, &tokens);
770     }
771     else {
772         xmlChar *format;
773
774         /* The format needs to be recomputed each time */
775         if (data->has_format == 0)
776             return;
777         format = xsltEvalAttrValueTemplate(ctxt, data->node,
778                                              (const xmlChar *) "format",
779                                              XSLT_NAMESPACE);
780         if (format == NULL)
781             return;
782         xsltNumberFormatTokenize(format, &tokens);
783         xmlFree(format);
784     }
785
786     output = xmlBufferCreate();
787     if (output == NULL)
788         goto XSLT_NUMBER_FORMAT_END;
789
790     /*
791      * Evaluate the XPath expression to find the value(s)
792      */
793     if (data->value) {
794         amount = xsltNumberFormatGetValue(ctxt->xpathCtxt,
795                                           node,
796                                           data->value,
797                                           &number);
798         if (amount == 1) {
799             xsltNumberFormatInsertNumbers(data,
800                                           &number,
801                                           1,
802                                           &tokens,
803                                           output);
804         }
805
806     } else if (data->level) {
807
808         if (xmlStrEqual(data->level, (const xmlChar *) "single")) {
809             amount = xsltNumberFormatGetMultipleLevel(ctxt,
810                                                       node,
811                                                       data->countPat,
812                                                       data->fromPat,
813                                                       &number,
814                                                       1);
815             if (amount == 1) {
816                 xsltNumberFormatInsertNumbers(data,
817                                               &number,
818                                               1,
819                                               &tokens,
820                                               output);
821             }
822         } else if (xmlStrEqual(data->level, (const xmlChar *) "multiple")) {
823             double numarray[1024];
824             int max = sizeof(numarray)/sizeof(numarray[0]);
825             amount = xsltNumberFormatGetMultipleLevel(ctxt,
826                                                       node,
827                                                       data->countPat,
828                                                       data->fromPat,
829                                                       numarray,
830                                                       max);
831             if (amount > 0) {
832                 xsltNumberFormatInsertNumbers(data,
833                                               numarray,
834                                               amount,
835                                               &tokens,
836                                               output);
837             }
838         } else if (xmlStrEqual(data->level, (const xmlChar *) "any")) {
839             amount = xsltNumberFormatGetAnyLevel(ctxt,
840                                                  node,
841                                                  data->countPat,
842                                                  data->fromPat,
843                                                  &number);
844             if (amount > 0) {
845                 xsltNumberFormatInsertNumbers(data,
846                                               &number,
847                                               1,
848                                               &tokens,
849                                               output);
850             }
851         }
852     }
853     /* Insert number as text node */
854     xsltCopyTextString(ctxt, ctxt->insert, xmlBufferContent(output), 0);
855
856     xmlBufferFree(output);
857
858 XSLT_NUMBER_FORMAT_END:
859     if (tokens.start != NULL)
860         xmlFree(tokens.start);
861     if (tokens.end != NULL)
862         xmlFree(tokens.end);
863     for (i = 0;i < tokens.nTokens;i++) {
864         if (tokens.tokens[i].separator != NULL)
865             xmlFree(tokens.tokens[i].separator);
866     }
867 }
868
869 static int
870 xsltFormatNumberPreSuffix(xsltDecimalFormatPtr self, xmlChar **format, xsltFormatNumberInfoPtr info)
871 {
872     int count=0;        /* will hold total length of prefix/suffix */
873     int len;
874
875     while (1) {
876         /*
877          * prefix / suffix ends at end of string or at
878          * first 'special' character
879          */
880         if (**format == 0)
881             return count;
882         /* if next character 'escaped' just count it */
883         if (**format == SYMBOL_QUOTE) {
884             if (*++(*format) == 0)
885                 return -1;
886         }
887         else if (IS_SPECIAL(self, *format))
888             return count;
889         /*
890          * else treat percent/per-mille as special cases,
891          * depending on whether +ve or -ve
892          */
893         else {
894             /*
895              * for +ve prefix/suffix, allow only a
896              * single occurence of either
897              */
898             if (xsltUTF8Charcmp(*format, self->percent) == 0) {
899                 if (info->is_multiplier_set)
900                     return -1;
901                 info->multiplier = 100;
902                 info->is_multiplier_set = TRUE;
903             } else if (xsltUTF8Charcmp(*format, self->permille) == 0) {
904                 if (info->is_multiplier_set)
905                     return -1;
906                 info->multiplier = 1000;
907                 info->is_multiplier_set = TRUE;
908             }
909         }
910
911         if ((len=xsltUTF8Size(*format)) < 1)
912             return -1;
913         count += len;
914         *format += len;
915     }
916 }
917
918 /**
919  * xsltFormatNumberConversion:
920  * @self: the decimal format
921  * @format: the format requested
922  * @number: the value to format
923  * @result: the place to ouput the result
924  *
925  * format-number() uses the JDK 1.1 DecimalFormat class:
926  *
927  * http://java.sun.com/products/jdk/1.1/docs/api/java.text.DecimalFormat.html
928  *
929  * Structure:
930  *
931  *   pattern    := subpattern{;subpattern}
932  *   subpattern := {prefix}integer{.fraction}{suffix}
933  *   prefix     := '\\u0000'..'\\uFFFD' - specialCharacters
934  *   suffix     := '\\u0000'..'\\uFFFD' - specialCharacters
935  *   integer    := '#'* '0'* '0'
936  *   fraction   := '0'* '#'*
937  *
938  *   Notation:
939  *    X*       0 or more instances of X
940  *    (X | Y)  either X or Y.
941  *    X..Y     any character from X up to Y, inclusive.
942  *    S - T    characters in S, except those in T
943  *
944  * Special Characters:
945  *
946  *   Symbol Meaning
947  *   0      a digit
948  *   #      a digit, zero shows as absent
949  *   .      placeholder for decimal separator
950  *   ,      placeholder for grouping separator.
951  *   ;      separates formats.
952  *   -      default negative prefix.
953  *   %      multiply by 100 and show as percentage
954  *   ?      multiply by 1000 and show as per mille
955  *   X      any other characters can be used in the prefix or suffix
956  *   '      used to quote special characters in a prefix or suffix.
957  *
958  * Returns a possible XPath error
959  */
960 xmlXPathError
961 xsltFormatNumberConversion(xsltDecimalFormatPtr self,
962                            xmlChar *format,
963                            double number,
964                            xmlChar **result)
965 {
966     xmlXPathError status = XPATH_EXPRESSION_OK;
967     xmlBufferPtr buffer;
968     xmlChar *the_format, *prefix = NULL, *suffix = NULL;
969     xmlChar *nprefix, *nsuffix = NULL;
970     xmlChar pchar;
971     int     prefix_length, suffix_length = 0, nprefix_length, nsuffix_length;
972     double  scale;
973     int     j, len;
974     int     self_grouping_len;
975     xsltFormatNumberInfo format_info;
976     /*
977      * delayed_multiplier allows a 'trailing' percent or
978      * permille to be treated as suffix
979      */
980     int         delayed_multiplier = 0;
981     /* flag to show no -ve format present for -ve number */
982     char        default_sign = 0;
983     /* flag to show error found, should use default format */
984     char        found_error = 0;
985
986     if (xmlStrlen(format) <= 0) {
987         xsltTransformError(NULL, NULL, NULL,
988                 "xsltFormatNumberConversion : "
989                 "Invalid format (0-length)\n");
990     }
991     *result = NULL;
992     switch (xmlXPathIsInf(number)) {
993         case -1:
994             if (self->minusSign == NULL)
995                 *result = xmlStrdup(BAD_CAST "-");
996             else
997                 *result = xmlStrdup(self->minusSign);
998             /* no-break on purpose */
999         case 1:
1000             if ((self == NULL) || (self->infinity == NULL))
1001                 *result = xmlStrcat(*result, BAD_CAST "Infinity");
1002             else
1003                 *result = xmlStrcat(*result, self->infinity);
1004             return(status);
1005         default:
1006             if (xmlXPathIsNaN(number)) {
1007                 if ((self == NULL) || (self->noNumber == NULL))
1008                     *result = xmlStrdup(BAD_CAST "NaN");
1009                 else
1010                     *result = xmlStrdup(self->noNumber);
1011                 return(status);
1012             }
1013     }
1014
1015     buffer = xmlBufferCreate();
1016     if (buffer == NULL) {
1017         return XPATH_MEMORY_ERROR;
1018     }
1019
1020     format_info.integer_hash = 0;
1021     format_info.integer_digits = 0;
1022     format_info.frac_digits = 0;
1023     format_info.frac_hash = 0;
1024     format_info.group = -1;
1025     format_info.multiplier = 1;
1026     format_info.add_decimal = FALSE;
1027     format_info.is_multiplier_set = FALSE;
1028     format_info.is_negative_pattern = FALSE;
1029
1030     the_format = format;
1031
1032     /*
1033      * First we process the +ve pattern to get percent / permille,
1034      * as well as main format
1035      */
1036     prefix = the_format;
1037     prefix_length = xsltFormatNumberPreSuffix(self, &the_format, &format_info);
1038     if (prefix_length < 0) {
1039         found_error = 1;
1040         goto OUTPUT_NUMBER;
1041     }
1042
1043     /*
1044      * Here we process the "number" part of the format.  It gets
1045      * a little messy because of the percent/per-mille - if that
1046      * appears at the end, it may be part of the suffix instead
1047      * of part of the number, so the variable delayed_multiplier
1048      * is used to handle it
1049      */
1050     self_grouping_len = xmlStrlen(self->grouping);
1051     while ((*the_format != 0) &&
1052            (xsltUTF8Charcmp(the_format, self->decimalPoint) != 0) &&
1053            (xsltUTF8Charcmp(the_format, self->patternSeparator) != 0)) {
1054
1055         if (delayed_multiplier != 0) {
1056             format_info.multiplier = delayed_multiplier;
1057             format_info.is_multiplier_set = TRUE;
1058             delayed_multiplier = 0;
1059         }
1060         if (xsltUTF8Charcmp(the_format, self->digit) == 0) {
1061             if (format_info.integer_digits > 0) {
1062                 found_error = 1;
1063                 goto OUTPUT_NUMBER;
1064             }
1065             format_info.integer_hash++;
1066             if (format_info.group >= 0)
1067                 format_info.group++;
1068         } else if (xsltUTF8Charcmp(the_format, self->zeroDigit) == 0) {
1069             format_info.integer_digits++;
1070             if (format_info.group >= 0)
1071                 format_info.group++;
1072         } else if ((self_grouping_len > 0) &&
1073             (!xmlStrncmp(the_format, self->grouping, self_grouping_len))) {
1074             /* Reset group count */
1075             format_info.group = 0;
1076             the_format += self_grouping_len;
1077             continue;
1078         } else if (xsltUTF8Charcmp(the_format, self->percent) == 0) {
1079             if (format_info.is_multiplier_set) {
1080                 found_error = 1;
1081                 goto OUTPUT_NUMBER;
1082             }
1083             delayed_multiplier = 100;
1084         } else  if (xsltUTF8Charcmp(the_format, self->permille) == 0) {
1085             if (format_info.is_multiplier_set) {
1086                 found_error = 1;
1087                 goto OUTPUT_NUMBER;
1088             }
1089             delayed_multiplier = 1000;
1090         } else
1091             break; /* while */
1092
1093         if ((len=xsltUTF8Size(the_format)) < 1) {
1094             found_error = 1;
1095             goto OUTPUT_NUMBER;
1096         }
1097         the_format += len;
1098
1099     }
1100
1101     /* We have finished the integer part, now work on fraction */
1102     if (xsltUTF8Charcmp(the_format, self->decimalPoint) == 0) {
1103         format_info.add_decimal = TRUE;
1104         the_format += xsltUTF8Size(the_format); /* Skip over the decimal */
1105     }
1106
1107     while (*the_format != 0) {
1108
1109         if (xsltUTF8Charcmp(the_format, self->zeroDigit) == 0) {
1110             if (format_info.frac_hash != 0) {
1111                 found_error = 1;
1112                 goto OUTPUT_NUMBER;
1113             }
1114             format_info.frac_digits++;
1115         } else if (xsltUTF8Charcmp(the_format, self->digit) == 0) {
1116             format_info.frac_hash++;
1117         } else if (xsltUTF8Charcmp(the_format, self->percent) == 0) {
1118             if (format_info.is_multiplier_set) {
1119                 found_error = 1;
1120                 goto OUTPUT_NUMBER;
1121             }
1122             delayed_multiplier = 100;
1123             if ((len = xsltUTF8Size(the_format)) < 1) {
1124                 found_error = 1;
1125                 goto OUTPUT_NUMBER;
1126             }
1127             the_format += len;
1128             continue; /* while */
1129         } else if (xsltUTF8Charcmp(the_format, self->permille) == 0) {
1130             if (format_info.is_multiplier_set) {
1131                 found_error = 1;
1132                 goto OUTPUT_NUMBER;
1133             }
1134             delayed_multiplier = 1000;
1135             if  ((len = xsltUTF8Size(the_format)) < 1) {
1136                 found_error = 1;
1137                 goto OUTPUT_NUMBER;
1138             }
1139             the_format += len;
1140             continue; /* while */
1141         } else if (xsltUTF8Charcmp(the_format, self->grouping) != 0) {
1142             break; /* while */
1143         }
1144         if ((len = xsltUTF8Size(the_format)) < 1) {
1145             found_error = 1;
1146             goto OUTPUT_NUMBER;
1147         }
1148         the_format += len;
1149         if (delayed_multiplier != 0) {
1150             format_info.multiplier = delayed_multiplier;
1151             delayed_multiplier = 0;
1152             format_info.is_multiplier_set = TRUE;
1153         }
1154     }
1155
1156     /*
1157      * If delayed_multiplier is set after processing the
1158      * "number" part, should be in suffix
1159      */
1160     if (delayed_multiplier != 0) {
1161         the_format -= len;
1162         delayed_multiplier = 0;
1163     }
1164
1165     suffix = the_format;
1166     suffix_length = xsltFormatNumberPreSuffix(self, &the_format, &format_info);
1167     if ( (suffix_length < 0) ||
1168          ((*the_format != 0) &&
1169           (xsltUTF8Charcmp(the_format, self->patternSeparator) != 0)) ) {
1170         found_error = 1;
1171         goto OUTPUT_NUMBER;
1172     }
1173
1174     /*
1175      * We have processed the +ve prefix, number part and +ve suffix.
1176      * If the number is -ve, we must substitute the -ve prefix / suffix
1177      */
1178     if (number < 0) {
1179         /*
1180          * Note that j is the number of UTF8 chars before the separator,
1181          * not the number of bytes! (bug 151975)
1182          */
1183         j =  xmlUTF8Strloc(format, self->patternSeparator);
1184         if (j < 0) {
1185         /* No -ve pattern present, so use default signing */
1186             default_sign = 1;
1187         }
1188         else {
1189             /* Skip over pattern separator (accounting for UTF8) */
1190             the_format = (xmlChar *)xmlUTF8Strpos(format, j + 1);
1191             /*
1192              * Flag changes interpretation of percent/permille
1193              * in -ve pattern
1194              */
1195             format_info.is_negative_pattern = TRUE;
1196             format_info.is_multiplier_set = FALSE;
1197
1198             /* First do the -ve prefix */
1199             nprefix = the_format;
1200             nprefix_length = xsltFormatNumberPreSuffix(self,
1201                                         &the_format, &format_info);
1202             if (nprefix_length<0) {
1203                 found_error = 1;
1204                 goto OUTPUT_NUMBER;
1205             }
1206
1207             while (*the_format != 0) {
1208                 if ( (xsltUTF8Charcmp(the_format, (self)->percent) == 0) ||
1209                      (xsltUTF8Charcmp(the_format, (self)->permille)== 0) ) {
1210                     if (format_info.is_multiplier_set) {
1211                         found_error = 1;
1212                         goto OUTPUT_NUMBER;
1213                     }
1214                     format_info.is_multiplier_set = TRUE;
1215                     delayed_multiplier = 1;
1216                 }
1217                 else if (IS_SPECIAL(self, the_format))
1218                     delayed_multiplier = 0;
1219                 else
1220                     break; /* while */
1221                 if ((len = xsltUTF8Size(the_format)) < 1) {
1222                     found_error = 1;
1223                     goto OUTPUT_NUMBER;
1224                 }
1225                 the_format += len;
1226             }
1227             if (delayed_multiplier != 0) {
1228                 format_info.is_multiplier_set = FALSE;
1229                 the_format -= len;
1230             }
1231
1232             /* Finally do the -ve suffix */
1233             if (*the_format != 0) {
1234                 nsuffix = the_format;
1235                 nsuffix_length = xsltFormatNumberPreSuffix(self,
1236                                         &the_format, &format_info);
1237                 if (nsuffix_length < 0) {
1238                     found_error = 1;
1239                     goto OUTPUT_NUMBER;
1240                 }
1241             }
1242             else
1243                 nsuffix_length = 0;
1244             if (*the_format != 0) {
1245                 found_error = 1;
1246                 goto OUTPUT_NUMBER;
1247             }
1248             /*
1249              * Here's another Java peculiarity:
1250              * if -ve prefix/suffix == +ve ones, discard & use default
1251              */
1252             if ((nprefix_length != prefix_length) ||
1253                 (nsuffix_length != suffix_length) ||
1254                 ((nprefix_length > 0) &&
1255                  (xmlStrncmp(nprefix, prefix, prefix_length) !=0 )) ||
1256                 ((nsuffix_length > 0) &&
1257                  (xmlStrncmp(nsuffix, suffix, suffix_length) !=0 ))) {
1258                 prefix = nprefix;
1259                 prefix_length = nprefix_length;
1260                 suffix = nsuffix;
1261                 suffix_length = nsuffix_length;
1262             } /* else {
1263                 default_sign = 1;
1264             }
1265             */
1266         }
1267     }
1268
1269 OUTPUT_NUMBER:
1270     if (found_error != 0) {
1271         xsltTransformError(NULL, NULL, NULL,
1272                 "xsltFormatNumberConversion : "
1273                 "error in format string '%s', using default\n", format);
1274         default_sign = (number < 0.0) ? 1 : 0;
1275         prefix_length = suffix_length = 0;
1276         format_info.integer_hash = 0;
1277         format_info.integer_digits = 1;
1278         format_info.frac_digits = 1;
1279         format_info.frac_hash = 4;
1280         format_info.group = -1;
1281         format_info.multiplier = 1;
1282         format_info.add_decimal = TRUE;
1283     }
1284
1285     /* Ready to output our number.  First see if "default sign" is required */
1286     if (default_sign != 0)
1287         xmlBufferAdd(buffer, self->minusSign, xsltUTF8Size(self->minusSign));
1288
1289     /* Put the prefix into the buffer */
1290     for (j = 0; j < prefix_length; j++) {
1291         if ((pchar = *prefix++) == SYMBOL_QUOTE) {
1292             len = xsltUTF8Size(prefix);
1293             xmlBufferAdd(buffer, prefix, len);
1294             prefix += len;
1295             j += len - 1;       /* length of symbol less length of quote */
1296         } else
1297             xmlBufferAdd(buffer, &pchar, 1);
1298     }
1299
1300     /* Next do the integer part of the number */
1301     number = fabs(number) * (double)format_info.multiplier;
1302     scale = pow(10.0, (double)(format_info.frac_digits + format_info.frac_hash));
1303     number = floor((scale * number + 0.5)) / scale;
1304     if ((self->grouping != NULL) &&
1305         (self->grouping[0] != 0)) {
1306
1307         len = xmlStrlen(self->grouping);
1308         pchar = xsltGetUTF8Char(self->grouping, &len);
1309         xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
1310                                 format_info.integer_digits,
1311                                 format_info.group,
1312                                 pchar, len);
1313     } else
1314         xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
1315                                 format_info.integer_digits,
1316                                 format_info.group,
1317                                 ',', 1);
1318
1319     /* Special case: java treats '.#' like '.0', '.##' like '.0#', etc. */
1320     if ((format_info.integer_digits + format_info.integer_hash +
1321          format_info.frac_digits == 0) && (format_info.frac_hash > 0)) {
1322         ++format_info.frac_digits;
1323         --format_info.frac_hash;
1324     }
1325
1326     /* Add leading zero, if required */
1327     if ((floor(number) == 0) &&
1328         (format_info.integer_digits + format_info.frac_digits == 0)) {
1329         xmlBufferAdd(buffer, self->zeroDigit, xsltUTF8Size(self->zeroDigit));
1330     }
1331
1332     /* Next the fractional part, if required */
1333     if (format_info.frac_digits + format_info.frac_hash == 0) {
1334         if (format_info.add_decimal)
1335             xmlBufferAdd(buffer, self->decimalPoint,
1336                          xsltUTF8Size(self->decimalPoint));
1337     }
1338     else {
1339       number -= floor(number);
1340         if ((number != 0) || (format_info.frac_digits != 0)) {
1341             xmlBufferAdd(buffer, self->decimalPoint,
1342                          xsltUTF8Size(self->decimalPoint));
1343             number = floor(scale * number + 0.5);
1344             for (j = format_info.frac_hash; j > 0; j--) {
1345                 if (fmod(number, 10.0) >= 1.0)
1346                     break; /* for */
1347                 number /= 10.0;
1348             }
1349             xsltNumberFormatDecimal(buffer, floor(number), self->zeroDigit[0],
1350                                 format_info.frac_digits + j,
1351                                 0, 0, 0);
1352         }
1353     }
1354     /* Put the suffix into the buffer */
1355     for (j = 0; j < suffix_length; j++) {
1356         if ((pchar = *suffix++) == SYMBOL_QUOTE) {
1357             len = xsltUTF8Size(suffix);
1358             xmlBufferAdd(buffer, suffix, len);
1359             suffix += len;
1360             j += len - 1;       /* length of symbol less length of escape */
1361         } else
1362             xmlBufferAdd(buffer, &pchar, 1);
1363     }
1364
1365     *result = xmlStrdup(xmlBufferContent(buffer));
1366     xmlBufferFree(buffer);
1367     return status;
1368 }
1369