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