ReactOS 0.4.15-dev-5666-gc548b97
numbers.c File Reference
#include "precomp.h"
Include dependency graph for numbers.c:

Go to the source code of this file.

Classes

struct  _xsltFormatToken
 
struct  _xsltFormat
 

Macros

#define FALSE   (0 == 1)
 
#define TRUE   (1 == 1)
 
#define SYMBOL_QUOTE   ((xmlChar)'\'')
 
#define DEFAULT_TOKEN   '0'
 
#define DEFAULT_SEPARATOR   "."
 
#define MAX_TOKENS   1024
 
#define IS_SPECIAL(self, letter)
 
#define IS_DIGIT_ZERO(x)   xsltIsDigitZero(x)
 
#define IS_DIGIT_ONE(x)   xsltIsDigitZero((x)-1)
 

Typedefs

typedef struct _xsltFormatToken xsltFormatToken
 
typedef xsltFormatTokenxsltFormatTokenPtr
 
typedef struct _xsltFormat xsltFormat
 
typedef xsltFormatxsltFormatPtr
 

Functions

static int xsltUTF8Charcmp (xmlChar *utf1, xmlChar *utf2)
 
static int xsltIsLetterDigit (int val)
 
static int xsltIsDigitZero (unsigned int ch)
 
static void xsltNumberFormatDecimal (xmlBufferPtr buffer, double number, int digit_zero, int width, int digitsPerGroup, int groupingCharacter, int groupingCharacterLen)
 
static void xsltNumberFormatAlpha (xsltNumberDataPtr data, xmlBufferPtr buffer, double number, int is_upper)
 
static void xsltNumberFormatRoman (xsltNumberDataPtr data, xmlBufferPtr buffer, double number, int is_upper)
 
static void xsltNumberFormatTokenize (const xmlChar *format, xsltFormatPtr tokens)
 
static void xsltNumberFormatInsertNumbers (xsltNumberDataPtr data, double *numbers, int numbers_max, xsltFormatPtr tokens, xmlBufferPtr buffer)
 
static int xsltTestCompMatchCount (xsltTransformContextPtr context, xmlNodePtr node, xsltCompMatchPtr countPat, xmlNodePtr cur)
 
static int xsltNumberFormatGetAnyLevel (xsltTransformContextPtr context, xmlNodePtr node, xsltCompMatchPtr countPat, xsltCompMatchPtr fromPat, double *array)
 
static int xsltNumberFormatGetMultipleLevel (xsltTransformContextPtr context, xmlNodePtr node, xsltCompMatchPtr countPat, xsltCompMatchPtr fromPat, double *array, int max)
 
static int xsltNumberFormatGetValue (xmlXPathContextPtr context, xmlNodePtr node, const xmlChar *value, double *number)
 
void xsltNumberFormat (xsltTransformContextPtr ctxt, xsltNumberDataPtr data, xmlNodePtr node)
 
static int xsltFormatNumberPreSuffix (xsltDecimalFormatPtr self, xmlChar **format, xsltFormatNumberInfoPtr info)
 
xmlXPathError xsltFormatNumberConversion (xsltDecimalFormatPtr self, xmlChar *format, double number, xmlChar **result)
 

Variables

static char alpha_upper_list [] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 
static char alpha_lower_list [] = "abcdefghijklmnopqrstuvwxyz"
 
static xsltFormatToken default_token
 

Macro Definition Documentation

◆ DEFAULT_SEPARATOR

#define DEFAULT_SEPARATOR   "."

Definition at line 23 of file numbers.c.

◆ DEFAULT_TOKEN

#define DEFAULT_TOKEN   '0'

Definition at line 22 of file numbers.c.

◆ FALSE

#define FALSE   (0 == 1)

Definition at line 16 of file numbers.c.

◆ IS_DIGIT_ONE

#define IS_DIGIT_ONE (   x)    xsltIsDigitZero((x)-1)

Definition at line 99 of file numbers.c.

◆ IS_DIGIT_ZERO

#define IS_DIGIT_ZERO (   x)    xsltIsDigitZero(x)

Definition at line 98 of file numbers.c.

◆ IS_SPECIAL

#define IS_SPECIAL (   self,
  letter 
)
Value:
((xsltUTF8Charcmp((letter), (self)->zeroDigit) == 0) || \
(xsltUTF8Charcmp((letter), (self)->digit) == 0) || \
(xsltUTF8Charcmp((letter), (self)->decimalPoint) == 0) || \
(xsltUTF8Charcmp((letter), (self)->grouping) == 0) || \
(xsltUTF8Charcmp((letter), (self)->patternSeparator) == 0))
static int xsltUTF8Charcmp(xmlChar *utf1, xmlChar *utf2)
Definition: numbers.c:65

Definition at line 91 of file numbers.c.

◆ MAX_TOKENS

#define MAX_TOKENS   1024

Definition at line 25 of file numbers.c.

◆ SYMBOL_QUOTE

#define SYMBOL_QUOTE   ((xmlChar)'\'')

Definition at line 20 of file numbers.c.

◆ TRUE

#define TRUE   (1 == 1)

Definition at line 17 of file numbers.c.

Typedef Documentation

◆ xsltFormat

Definition at line 35 of file numbers.c.

◆ xsltFormatPtr

Definition at line 36 of file numbers.c.

◆ xsltFormatToken

Definition at line 27 of file numbers.c.

◆ xsltFormatTokenPtr

Definition at line 28 of file numbers.c.

Function Documentation

◆ xsltFormatNumberConversion()

xmlXPathError xsltFormatNumberConversion ( xsltDecimalFormatPtr  self,
xmlChar format,
double  number,
xmlChar **  result 
)

xsltFormatNumberConversion: @self: the decimal format @format: the format requested @number: the value to format

Returns
: the place to output the result

format-number() uses the JDK 1.1 DecimalFormat class:

http://java.sun.com/products/jdk/1.1/docs/api/java.text.DecimalFormat.html

Structure:

pattern := subpattern{;subpattern} subpattern := {prefix}integer{.fraction}{suffix} prefix := '\u0000'..'\uFFFD' - specialCharacters suffix := '\u0000'..'\uFFFD' - specialCharacters integer := '#'* '0'* '0' fraction := '0'* '#'*

Notation: X* 0 or more instances of X (X | Y) either X or Y. X..Y any character from X up to Y, inclusive. S - T characters in S, except those in T

Special Characters:

Symbol Meaning 0 a digit

a digit, zero shows as absent

. placeholder for decimal separator , placeholder for grouping separator. ; separates formats.

  • default negative prefix. % multiply by 100 and show as percentage ? multiply by 1000 and show as per mille X any other characters can be used in the prefix or suffix ' used to quote special characters in a prefix or suffix.

Returns a possible XPath error

Definition at line 941 of file numbers.c.

945{
946 xmlXPathError status = XPATH_EXPRESSION_OK;
948 xmlChar *the_format, *prefix = NULL, *suffix = NULL;
949 xmlChar *nprefix, *nsuffix = NULL;
950 int prefix_length, suffix_length = 0, nprefix_length, nsuffix_length;
951 double scale;
952 int j, len = 0;
953 int self_grouping_len;
955 /*
956 * delayed_multiplier allows a 'trailing' percent or
957 * permille to be treated as suffix
958 */
959 int delayed_multiplier = 0;
960 /* flag to show no -ve format present for -ve number */
961 char default_sign = 0;
962 /* flag to show error found, should use default format */
963 char found_error = 0;
964
965 if (xmlStrlen(format) <= 0) {
967 "xsltFormatNumberConversion : "
968 "Invalid format (0-length)\n");
969 }
970 *result = NULL;
971 switch (xmlXPathIsInf(number)) {
972 case -1:
973 if (self->minusSign == NULL)
974 *result = xmlStrdup(BAD_CAST "-");
975 else
976 *result = xmlStrdup(self->minusSign);
977 /* Intentional fall-through */
978 case 1:
979 if ((self == NULL) || (self->infinity == NULL))
980 *result = xmlStrcat(*result, BAD_CAST "Infinity");
981 else
982 *result = xmlStrcat(*result, self->infinity);
983 return(status);
984 default:
985 if (xmlXPathIsNaN(number)) {
986 if ((self == NULL) || (self->noNumber == NULL))
987 *result = xmlStrdup(BAD_CAST "NaN");
988 else
989 *result = xmlStrdup(self->noNumber);
990 return(status);
991 }
992 }
993
995 if (buffer == NULL) {
996 return XPATH_MEMORY_ERROR;
997 }
998
999 format_info.integer_hash = 0;
1000 format_info.integer_digits = 0;
1001 format_info.frac_digits = 0;
1002 format_info.frac_hash = 0;
1003 format_info.group = -1;
1004 format_info.multiplier = 1;
1005 format_info.add_decimal = FALSE;
1006 format_info.is_multiplier_set = FALSE;
1007 format_info.is_negative_pattern = FALSE;
1008
1009 the_format = format;
1010
1011 /*
1012 * First we process the +ve pattern to get percent / permille,
1013 * as well as main format
1014 */
1015 prefix = the_format;
1016 prefix_length = xsltFormatNumberPreSuffix(self, &the_format, &format_info);
1017 if (prefix_length < 0) {
1018 found_error = 1;
1019 goto OUTPUT_NUMBER;
1020 }
1021
1022 /*
1023 * Here we process the "number" part of the format. It gets
1024 * a little messy because of the percent/per-mille - if that
1025 * appears at the end, it may be part of the suffix instead
1026 * of part of the number, so the variable delayed_multiplier
1027 * is used to handle it
1028 */
1029 self_grouping_len = xmlStrlen(self->grouping);
1030 while ((*the_format != 0) &&
1031 (xsltUTF8Charcmp(the_format, self->decimalPoint) != 0) &&
1032 (xsltUTF8Charcmp(the_format, self->patternSeparator) != 0)) {
1033
1034 if (delayed_multiplier != 0) {
1035 format_info.multiplier = delayed_multiplier;
1036 format_info.is_multiplier_set = TRUE;
1037 delayed_multiplier = 0;
1038 }
1039 if (xsltUTF8Charcmp(the_format, self->digit) == 0) {
1040 if (format_info.integer_digits > 0) {
1041 found_error = 1;
1042 goto OUTPUT_NUMBER;
1043 }
1044 format_info.integer_hash++;
1045 if (format_info.group >= 0)
1046 format_info.group++;
1047 } else if (xsltUTF8Charcmp(the_format, self->zeroDigit) == 0) {
1048 format_info.integer_digits++;
1049 if (format_info.group >= 0)
1050 format_info.group++;
1051 } else if ((self_grouping_len > 0) &&
1052 (!xmlStrncmp(the_format, self->grouping, self_grouping_len))) {
1053 /* Reset group count */
1054 format_info.group = 0;
1055 the_format += self_grouping_len;
1056 continue;
1057 } else if (xsltUTF8Charcmp(the_format, self->percent) == 0) {
1058 if (format_info.is_multiplier_set) {
1059 found_error = 1;
1060 goto OUTPUT_NUMBER;
1061 }
1062 delayed_multiplier = 100;
1063 } else if (xsltUTF8Charcmp(the_format, self->permille) == 0) {
1064 if (format_info.is_multiplier_set) {
1065 found_error = 1;
1066 goto OUTPUT_NUMBER;
1067 }
1068 delayed_multiplier = 1000;
1069 } else
1070 break; /* while */
1071
1072 if ((len=xmlUTF8Strsize(the_format, 1)) < 1) {
1073 found_error = 1;
1074 goto OUTPUT_NUMBER;
1075 }
1076 the_format += len;
1077
1078 }
1079
1080 /* We have finished the integer part, now work on fraction */
1081 if ( (*the_format != 0) &&
1082 (xsltUTF8Charcmp(the_format, self->decimalPoint) == 0) ) {
1083 format_info.add_decimal = TRUE;
1084 if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
1085 found_error = 1;
1086 goto OUTPUT_NUMBER;
1087 }
1088 the_format += len; /* Skip over the decimal */
1089 }
1090
1091 while (*the_format != 0) {
1092
1093 if (xsltUTF8Charcmp(the_format, self->zeroDigit) == 0) {
1094 if (format_info.frac_hash != 0) {
1095 found_error = 1;
1096 goto OUTPUT_NUMBER;
1097 }
1098 format_info.frac_digits++;
1099 } else if (xsltUTF8Charcmp(the_format, self->digit) == 0) {
1100 format_info.frac_hash++;
1101 } else if (xsltUTF8Charcmp(the_format, self->percent) == 0) {
1102 if (format_info.is_multiplier_set) {
1103 found_error = 1;
1104 goto OUTPUT_NUMBER;
1105 }
1106 delayed_multiplier = 100;
1107 if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
1108 found_error = 1;
1109 goto OUTPUT_NUMBER;
1110 }
1111 the_format += len;
1112 continue; /* while */
1113 } else if (xsltUTF8Charcmp(the_format, self->permille) == 0) {
1114 if (format_info.is_multiplier_set) {
1115 found_error = 1;
1116 goto OUTPUT_NUMBER;
1117 }
1118 delayed_multiplier = 1000;
1119 if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
1120 found_error = 1;
1121 goto OUTPUT_NUMBER;
1122 }
1123 the_format += len;
1124 continue; /* while */
1125 } else if (xsltUTF8Charcmp(the_format, self->grouping) != 0) {
1126 break; /* while */
1127 }
1128 if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
1129 found_error = 1;
1130 goto OUTPUT_NUMBER;
1131 }
1132 the_format += len;
1133 if (delayed_multiplier != 0) {
1134 format_info.multiplier = delayed_multiplier;
1135 delayed_multiplier = 0;
1136 format_info.is_multiplier_set = TRUE;
1137 }
1138 }
1139
1140 /*
1141 * If delayed_multiplier is set after processing the
1142 * "number" part, should be in suffix
1143 */
1144 if (delayed_multiplier != 0) {
1145 the_format -= len;
1146 delayed_multiplier = 0;
1147 }
1148
1149 suffix = the_format;
1150 suffix_length = xsltFormatNumberPreSuffix(self, &the_format, &format_info);
1151 if ( (suffix_length < 0) ||
1152 ((*the_format != 0) &&
1153 (xsltUTF8Charcmp(the_format, self->patternSeparator) != 0)) ) {
1154 found_error = 1;
1155 goto OUTPUT_NUMBER;
1156 }
1157
1158 /*
1159 * We have processed the +ve prefix, number part and +ve suffix.
1160 * If the number is -ve, we must substitute the -ve prefix / suffix
1161 */
1162 if (number < 0) {
1163 /*
1164 * Note that j is the number of UTF8 chars before the separator,
1165 * not the number of bytes! (bug 151975)
1166 */
1168 if (j < 0) {
1169 /* No -ve pattern present, so use default signing */
1170 default_sign = 1;
1171 }
1172 else {
1173 /* Skip over pattern separator (accounting for UTF8) */
1174 the_format = (xmlChar *)xmlUTF8Strpos(format, j + 1);
1175 /*
1176 * Flag changes interpretation of percent/permille
1177 * in -ve pattern
1178 */
1179 format_info.is_negative_pattern = TRUE;
1180 format_info.is_multiplier_set = FALSE;
1181
1182 /* First do the -ve prefix */
1183 nprefix = the_format;
1184 nprefix_length = xsltFormatNumberPreSuffix(self,
1185 &the_format, &format_info);
1186 if (nprefix_length<0) {
1187 found_error = 1;
1188 goto OUTPUT_NUMBER;
1189 }
1190
1191 while (*the_format != 0) {
1192 if ( (xsltUTF8Charcmp(the_format, (self)->percent) == 0) ||
1193 (xsltUTF8Charcmp(the_format, (self)->permille)== 0) ) {
1194 if (format_info.is_multiplier_set) {
1195 found_error = 1;
1196 goto OUTPUT_NUMBER;
1197 }
1198 format_info.is_multiplier_set = TRUE;
1199 delayed_multiplier = 1;
1200 }
1201 else if (IS_SPECIAL(self, the_format))
1202 delayed_multiplier = 0;
1203 else
1204 break; /* while */
1205 if ((len = xmlUTF8Strsize(the_format, 1)) < 1) {
1206 found_error = 1;
1207 goto OUTPUT_NUMBER;
1208 }
1209 the_format += len;
1210 }
1211 if (delayed_multiplier != 0) {
1212 format_info.is_multiplier_set = FALSE;
1213 the_format -= len;
1214 }
1215
1216 /* Finally do the -ve suffix */
1217 if (*the_format != 0) {
1218 nsuffix = the_format;
1219 nsuffix_length = xsltFormatNumberPreSuffix(self,
1220 &the_format, &format_info);
1221 if (nsuffix_length < 0) {
1222 found_error = 1;
1223 goto OUTPUT_NUMBER;
1224 }
1225 }
1226 else
1227 nsuffix_length = 0;
1228 if (*the_format != 0) {
1229 found_error = 1;
1230 goto OUTPUT_NUMBER;
1231 }
1232 /*
1233 * Here's another Java peculiarity:
1234 * if -ve prefix/suffix == +ve ones, discard & use default
1235 */
1236 if ((nprefix_length != prefix_length) ||
1237 (nsuffix_length != suffix_length) ||
1238 ((nprefix_length > 0) &&
1239 (xmlStrncmp(nprefix, prefix, prefix_length) !=0 )) ||
1240 ((nsuffix_length > 0) &&
1241 (xmlStrncmp(nsuffix, suffix, suffix_length) !=0 ))) {
1242 prefix = nprefix;
1243 prefix_length = nprefix_length;
1244 suffix = nsuffix;
1245 suffix_length = nsuffix_length;
1246 } /* else {
1247 default_sign = 1;
1248 }
1249 */
1250 }
1251 }
1252
1253OUTPUT_NUMBER:
1254 if (found_error != 0) {
1256 "xsltFormatNumberConversion : "
1257 "error in format string '%s', using default\n", format);
1258 default_sign = (number < 0.0) ? 1 : 0;
1259 prefix_length = suffix_length = 0;
1260 format_info.integer_hash = 0;
1261 format_info.integer_digits = 1;
1262 format_info.frac_digits = 1;
1263 format_info.frac_hash = 4;
1264 format_info.group = -1;
1265 format_info.multiplier = 1;
1266 format_info.add_decimal = TRUE;
1267 }
1268
1269 /* Ready to output our number. First see if "default sign" is required */
1270 if (default_sign != 0)
1272
1273 /* Put the prefix into the buffer */
1274 for (j = 0; j < prefix_length; ) {
1275 if (*prefix == SYMBOL_QUOTE)
1276 prefix++;
1277 len = xmlUTF8Strsize(prefix, 1);
1278 xmlBufferAdd(buffer, prefix, len);
1279 prefix += len;
1280 j += len;
1281 }
1282
1283 /* Next do the integer part of the number */
1284 number = fabs(number) * (double)format_info.multiplier;
1285 scale = pow(10.0, (double)(format_info.frac_digits + format_info.frac_hash));
1286 number = floor((scale * number + 0.5)) / scale;
1287 if ((self->grouping != NULL) &&
1288 (self->grouping[0] != 0)) {
1289 int gchar;
1290
1291 len = xmlStrlen(self->grouping);
1292 gchar = xsltGetUTF8Char(self->grouping, &len);
1294 format_info.integer_digits,
1295 format_info.group,
1296 gchar, len);
1297 } else
1299 format_info.integer_digits,
1300 format_info.group,
1301 ',', 1);
1302
1303 /* Special case: java treats '.#' like '.0', '.##' like '.0#', etc. */
1304 if ((format_info.integer_digits + format_info.integer_hash +
1305 format_info.frac_digits == 0) && (format_info.frac_hash > 0)) {
1306 ++format_info.frac_digits;
1307 --format_info.frac_hash;
1308 }
1309
1310 /* Add leading zero, if required */
1311 if ((floor(number) == 0) &&
1312 (format_info.integer_digits + format_info.frac_digits == 0)) {
1314 }
1315
1316 /* Next the fractional part, if required */
1317 if (format_info.frac_digits + format_info.frac_hash == 0) {
1318 if (format_info.add_decimal)
1320 xmlUTF8Strsize(self->decimalPoint, 1));
1321 }
1322 else {
1323 number -= floor(number);
1324 if ((number != 0) || (format_info.frac_digits != 0)) {
1326 xmlUTF8Strsize(self->decimalPoint, 1));
1327 number = floor(scale * number + 0.5);
1328 for (j = format_info.frac_hash; j > 0; j--) {
1329 if (fmod(number, 10.0) >= 1.0)
1330 break; /* for */
1331 number /= 10.0;
1332 }
1334 format_info.frac_digits + j,
1335 0, 0, 0);
1336 }
1337 }
1338 /* Put the suffix into the buffer */
1339 for (j = 0; j < suffix_length; ) {
1340 if (*suffix == SYMBOL_QUOTE)
1341 suffix++;
1342 len = xmlUTF8Strsize(suffix, 1);
1343 xmlBufferAdd(buffer, suffix, len);
1344 suffix += len;
1345 j += len;
1346 }
1347
1350 return status;
1351}
#define SYMBOL_QUOTE
Definition: numbers.c:20
static void xsltNumberFormatDecimal(xmlBufferPtr buffer, double number, int digit_zero, int width, int digitsPerGroup, int groupingCharacter, int groupingCharacterLen)
Definition: numbers.c:122
#define IS_SPECIAL(self, letter)
Definition: numbers.c:91
static int xsltFormatNumberPreSuffix(xsltDecimalFormatPtr self, xmlChar **format, xsltFormatNumberInfoPtr info)
Definition: numbers.c:849
format_info
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
double pow(double x, double y)
Definition: freeldr.c:110
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9032
GLuint buffer
Definition: glext.h:5915
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
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
_Check_return_ _CRT_JIT_INTRINSIC double __cdecl fabs(_In_ double x)
Definition: fabs.c:17
_Check_return_ double __cdecl fmod(_In_ double x, _In_ double y)
_Check_return_ _CRTIMP double __cdecl floor(_In_ double x)
static unsigned int number
Definition: dsound.c:1479
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
XMLPUBFUN void XMLCALL xmlBufferFree(xmlBufferPtr buf)
XMLPUBFUN int XMLCALL xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len)
XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreate(void)
XMLPUBFUN const xmlChar *XMLCALL xmlBufferContent(const xmlBuffer *buf)
xmlChar * decimalPoint
xmlChar * patternSeparator
Definition: ps.c:97
XMLPUBFUN const xmlChar *XMLCALL xmlUTF8Strpos(const xmlChar *utf, int pos)
Definition: xmlstring.c:894
XMLPUBFUN xmlChar *XMLCALL xmlStrcat(xmlChar *cur, const xmlChar *add)
Definition: xmlstring.c:524
XMLPUBFUN int XMLCALL xmlStrncmp(const xmlChar *str1, const xmlChar *str2, int len)
Definition: xmlstring.c:213
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
XMLPUBFUN int XMLCALL xmlUTF8Strsize(const xmlChar *utf, int len)
Definition: xmlstring.c:833
XMLPUBFUN int XMLCALL xmlUTF8Strloc(const xmlChar *utf, const xmlChar *utfchar)
Definition: xmlstring.c:926
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int XMLCALL xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:426
unsigned char xmlChar
Definition: xmlstring.h:28
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:678
int xsltGetUTF8Char(const unsigned char *utf, int *len)
Definition: xsltutils.c:227

Referenced by xsltFormatNumberFunction().

◆ xsltFormatNumberPreSuffix()

static int xsltFormatNumberPreSuffix ( xsltDecimalFormatPtr  self,
xmlChar **  format,
xsltFormatNumberInfoPtr  info 
)
static

Definition at line 849 of file numbers.c.

850{
851 /* will hold total length of prefix/suffix without quote characters */
852 int count=0;
853 int len;
854
855 while (1) {
856 /*
857 * prefix / suffix ends at end of string or at
858 * first 'special' character
859 */
860 if (**format == 0)
861 return count;
862 /* if next character 'escaped' just count it */
863 if (**format == SYMBOL_QUOTE) {
864 if (*++(*format) == 0)
865 return -1;
866 }
867 else if (IS_SPECIAL(self, *format))
868 return count;
869 /*
870 * else treat percent/per-mille as special cases,
871 * depending on whether +ve or -ve
872 */
873 else {
874 /*
875 * for +ve prefix/suffix, allow only a
876 * single occurence of either
877 */
878 if (xsltUTF8Charcmp(*format, self->percent) == 0) {
879 if (info->is_multiplier_set)
880 return -1;
881 info->multiplier = 100;
882 info->is_multiplier_set = TRUE;
883 } else if (xsltUTF8Charcmp(*format, self->permille) == 0) {
884 if (info->is_multiplier_set)
885 return -1;
886 info->multiplier = 1000;
887 info->is_multiplier_set = TRUE;
888 }
889 }
890
891 if ((len=xmlUTF8Strsize(*format, 1)) < 1)
892 return -1;
893 count += len;
894 *format += len;
895 }
896}
GLuint GLuint GLsizei count
Definition: gl.h:1545

Referenced by xsltFormatNumberConversion().

◆ xsltIsDigitZero()

static int xsltIsDigitZero ( unsigned int  ch)
static

Definition at line 102 of file numbers.c.

103{
104 /*
105 * Reference: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
106 *
107 * There a many more digit ranges in newer Unicode versions. These
108 * are only the zeros that match Digit in XML 1.0 (IS_DIGIT macro).
109 */
110 switch (ch) {
111 case 0x0030: case 0x0660: case 0x06F0: case 0x0966:
112 case 0x09E6: case 0x0A66: case 0x0AE6: case 0x0B66:
113 case 0x0C66: case 0x0CE6: case 0x0D66: case 0x0E50:
114 case 0x0ED0: case 0x0F20:
115 return TRUE;
116 default:
117 return FALSE;
118 }
119}

◆ xsltIsLetterDigit()

static int xsltIsLetterDigit ( int  val)
static

Definition at line 79 of file numbers.c.

79 {
82}
#define xmlIsDigitQ(c)
Definition: chvalid.h:152
#define xmlIsIdeographicQ(c)
Definition: chvalid.h:184
#define xmlIsBaseCharQ(c)
Definition: chvalid.h:76
GLuint GLfloat * val
Definition: glext.h:7180

Referenced by xsltNumberFormatTokenize().

◆ xsltNumberFormat()

void xsltNumberFormat ( xsltTransformContextPtr  ctxt,
xsltNumberDataPtr  data,
xmlNodePtr  node 
)

xsltNumberFormat: @ctxt: the XSLT transformation context @data: the formatting information @node: the data to format

Convert one number.

Definition at line 728 of file numbers.c.

731{
732 xmlBufferPtr output = NULL;
733 int amount, i;
734 double number;
735 xsltFormat tokens;
736
737 if (data->format != NULL) {
738 xsltNumberFormatTokenize(data->format, &tokens);
739 }
740 else {
742
743 /* The format needs to be recomputed each time */
744 if (data->has_format == 0)
745 return;
747 (const xmlChar *) "format",
749 if (format == NULL)
750 return;
753 }
754
755 output = xmlBufferCreate();
756 if (output == NULL)
757 goto XSLT_NUMBER_FORMAT_END;
758
759 /*
760 * Evaluate the XPath expression to find the value(s)
761 */
762 if (data->value) {
763 amount = xsltNumberFormatGetValue(ctxt->xpathCtxt,
764 node,
765 data->value,
766 &number);
767 if (amount == 1) {
769 &number,
770 1,
771 &tokens,
772 output);
773 }
774
775 } else if (data->level) {
776
777 if (xmlStrEqual(data->level, (const xmlChar *) "single")) {
779 node,
780 data->countPat,
781 data->fromPat,
782 &number,
783 1);
784 if (amount == 1) {
786 &number,
787 1,
788 &tokens,
789 output);
790 }
791 } else if (xmlStrEqual(data->level, (const xmlChar *) "multiple")) {
792 double numarray[1024];
793 int max = sizeof(numarray)/sizeof(numarray[0]);
795 node,
796 data->countPat,
797 data->fromPat,
798 numarray,
799 max);
800 if (amount > 0) {
802 numarray,
803 amount,
804 &tokens,
805 output);
806 }
807 } else if (xmlStrEqual(data->level, (const xmlChar *) "any")) {
808 amount = xsltNumberFormatGetAnyLevel(ctxt,
809 node,
810 data->countPat,
811 data->fromPat,
812 &number);
813 if (amount > 0) {
815 &number,
816 1,
817 &tokens,
818 output);
819 }
820 }
821
822 /*
823 * Unlike `match` patterns, `count` and `from` patterns can contain
824 * variable references, so we have to clear the pattern match
825 * cache if the "direct" matching algorithm was used.
826 */
827 if (data->countPat != NULL)
828 xsltCompMatchClearCache(ctxt, data->countPat);
829 if (data->fromPat != NULL)
830 xsltCompMatchClearCache(ctxt, data->fromPat);
831 }
832 /* Insert number as text node */
833 xsltCopyTextString(ctxt, ctxt->insert, xmlBufferContent(output), 0);
834
835 xmlBufferFree(output);
836
837XSLT_NUMBER_FORMAT_END:
838 if (tokens.start != NULL)
839 xmlFree(tokens.start);
840 if (tokens.end != NULL)
841 xmlFree(tokens.end);
842 for (i = 0;i < tokens.nTokens;i++) {
843 if (tokens.tokens[i].separator != NULL)
844 xmlFree(tokens.tokens[i].separator);
845 }
846}
static void xsltNumberFormatInsertNumbers(xsltNumberDataPtr data, double *numbers, int numbers_max, xsltFormatPtr tokens, xmlBufferPtr buffer)
Definition: numbers.c:427
static int xsltNumberFormatGetMultipleLevel(xsltTransformContextPtr context, xmlNodePtr node, xsltCompMatchPtr countPat, xsltCompMatchPtr fromPat, double *array, int max)
Definition: numbers.c:634
static int xsltNumberFormatGetValue(xmlXPathContextPtr context, xmlNodePtr node, const xmlChar *value, double *number)
Definition: numbers.c:692
static void xsltNumberFormatTokenize(const xmlChar *format, xsltFormatPtr tokens)
Definition: numbers.c:318
static int xsltNumberFormatGetAnyLevel(xsltTransformContextPtr context, xmlNodePtr node, xsltCompMatchPtr countPat, xsltCompMatchPtr fromPat, double *array)
Definition: numbers.c:580
void xsltCompMatchClearCache(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp)
Definition: pattern.c:1144
xmlNodePtr xsltCopyTextString(xsltTransformContextPtr ctxt, xmlNodePtr target, const xmlChar *string, int noescape)
Definition: transform.c:849
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
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
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
xmlChar * separator
Definition: numbers.c:30
xsltFormatToken tokens[MAX_TOKENS]
Definition: numbers.c:39
xmlChar * start
Definition: numbers.c:38
xmlChar * end
Definition: numbers.c:41
int nTokens
Definition: numbers.c:40
xmlXPathContextPtr xpathCtxt
#define max(a, b)
Definition: svc.c:63
xmlChar * xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr inst, const xmlChar *name, const xmlChar *ns)
Definition: templates.c:392
Definition: dlist.c:348
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
#define XSLT_NAMESPACE
Definition: xslt.h:46

Referenced by xsltNumber().

◆ xsltNumberFormatAlpha()

static void xsltNumberFormatAlpha ( xsltNumberDataPtr  data,
xmlBufferPtr  buffer,
double  number,
int  is_upper 
)
static

Definition at line 196 of file numbers.c.

200{
201 char temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 1];
202 char *pointer;
203 int i;
204 char *alpha_list;
205 double alpha_size = (double)(sizeof(alpha_upper_list) - 1);
206
207 /*
208 * XSLT 1.0 isn't clear on how to handle zero, but XSLT 2.0 says:
209 *
210 * For all format tokens other than the first kind above (one that
211 * consists of decimal digits), there may be implementation-defined
212 * lower and upper bounds on the range of numbers that can be
213 * formatted using this format token; indeed, for some numbering
214 * sequences there may be intrinsic limits. [...] Numbers that fall
215 * outside this range must be formatted using the format token 1.
216 *
217 * The "a" token has an intrinsic lower limit of 1.
218 */
219 if (number < 1.0) {
221 data->digitsPerGroup,
222 data->groupingCharacter,
223 data->groupingCharacterLen);
224 return;
225 }
226
227 /* Build buffer from back */
228 pointer = &temp_string[sizeof(temp_string)];
229 *(--pointer) = 0;
230 alpha_list = (is_upper) ? alpha_upper_list : alpha_lower_list;
231
232 for (i = 1; i < (int)sizeof(temp_string); i++) {
233 number--;
234 *(--pointer) = alpha_list[((int)fmod(number, alpha_size))];
235 number /= alpha_size;
236 if (number < 1.0)
237 break; /* for */
238 }
240}
static char alpha_lower_list[]
Definition: numbers.c:45
static char alpha_upper_list[]
Definition: numbers.c:44
#define is_upper(c)
Definition: astoll.c:45
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define CHAR_BIT
Definition: urlcache.c:62
GLsizei const GLvoid * pointer
Definition: glext.h:5848
XMLPUBFUN int XMLCALL xmlBufferCCat(xmlBufferPtr buf, const char *str)

Referenced by xsltNumberFormatInsertNumbers().

◆ xsltNumberFormatDecimal()

static void xsltNumberFormatDecimal ( xmlBufferPtr  buffer,
double  number,
int  digit_zero,
int  width,
int  digitsPerGroup,
int  groupingCharacter,
int  groupingCharacterLen 
)
static

Definition at line 122 of file numbers.c.

129{
130 /*
131 * This used to be
132 * xmlChar temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 4];
133 * which would be length 68 on x86 arch. It was changed to be a longer,
134 * fixed length in order to try to cater for (reasonable) UTF8
135 * separators and numeric characters. The max UTF8 char size will be
136 * 6 or less, so the value used [500] should be *much* larger than needed
137 */
138 xmlChar temp_string[500];
140 xmlChar temp_char[6];
141 int i;
142 int val;
143 int len;
144
145 /* Build buffer from back */
146 pointer = &temp_string[sizeof(temp_string)] - 1; /* last char */
147 *pointer = 0;
148 i = 0;
149 while (pointer > temp_string) {
150 if ((i >= width) && (fabs(number) < 1.0))
151 break; /* for */
152 if ((i > 0) && (groupingCharacter != 0) &&
153 (digitsPerGroup > 0) &&
154 ((i % digitsPerGroup) == 0)) {
155 if (pointer - groupingCharacterLen < temp_string) {
156 i = -1; /* flag error */
157 break;
158 }
159 pointer -= groupingCharacterLen;
160 xmlCopyCharMultiByte(pointer, groupingCharacter);
161 }
162
163 val = digit_zero + (int)fmod(number, 10.0);
164 if (val < 0x80) { /* shortcut if ASCII */
165 if (pointer <= temp_string) { /* Check enough room */
166 i = -1;
167 break;
168 }
169 *(--pointer) = (xmlChar)val;
170 }
171 else {
172 /*
173 * Here we have a multibyte character. It's a little messy,
174 * because until we generate the char we don't know how long
175 * it is. So, we generate it into the buffer temp_char, then
176 * copy from there into temp_string.
177 */
178 len = xmlCopyCharMultiByte(temp_char, val);
179 if ( (pointer - len) < temp_string ) {
180 i = -1;
181 break;
182 }
183 pointer -= len;
184 memcpy(pointer, temp_char, len);
185 }
186 number /= 10.0;
187 ++i;
188 }
189 if (i < 0)
191 "xsltNumberFormatDecimal: Internal buffer size exceeded\n");
193}
GLint GLint GLsizei width
Definition: gl.h:1546
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
XMLPUBFUN int XMLCALL xmlCopyCharMultiByte(xmlChar *out, int val)
XMLPUBFUN int XMLCALL xmlBufferCat(xmlBufferPtr buf, const xmlChar *str)
xmlGenericErrorFunc xsltGenericError
Definition: xsltutils.c:502
void * xsltGenericErrorContext
Definition: xsltutils.c:503

Referenced by xsltFormatNumberConversion(), xsltNumberFormatAlpha(), xsltNumberFormatInsertNumbers(), and xsltNumberFormatRoman().

◆ xsltNumberFormatGetAnyLevel()

static int xsltNumberFormatGetAnyLevel ( xsltTransformContextPtr  context,
xmlNodePtr  node,
xsltCompMatchPtr  countPat,
xsltCompMatchPtr  fromPat,
double array 
)
static

Definition at line 580 of file numbers.c.

585{
586 int amount = 0;
587 int cnt = 0;
589
590 while (cur != NULL) {
591 /* process current node */
592 if (xsltTestCompMatchCount(context, cur, countPat, node))
593 cnt++;
594 if ((fromPat != NULL) &&
595 xsltTestCompMatchList(context, cur, fromPat)) {
596 break; /* while */
597 }
598
599 /* Skip to next preceding or ancestor */
600 if ((cur->type == XML_DOCUMENT_NODE) ||
601#ifdef LIBXML_DOCB_ENABLED
602 (cur->type == XML_DOCB_DOCUMENT_NODE) ||
603#endif
604 (cur->type == XML_HTML_DOCUMENT_NODE))
605 break; /* while */
606
607 if (cur->type == XML_NAMESPACE_DECL) {
608 /*
609 * The XPath module stores the parent of a namespace node in
610 * the ns->next field.
611 */
612 cur = (xmlNodePtr) ((xmlNsPtr) cur)->next;
613 } else if (cur->type == XML_ATTRIBUTE_NODE) {
614 cur = cur->parent;
615 } else {
616 while ((cur->prev != NULL) && ((cur->prev->type == XML_DTD_NODE) ||
617 (cur->prev->type == XML_XINCLUDE_START) ||
618 (cur->prev->type == XML_XINCLUDE_END)))
619 cur = cur->prev;
620 if (cur->prev != NULL) {
621 for (cur = cur->prev; cur->last != NULL; cur = cur->last);
622 } else {
623 cur = cur->parent;
624 }
625 }
626 }
627
628 array[amount++] = (double) cnt;
629
630 return(amount);
631}
static int xsltTestCompMatchCount(xsltTransformContextPtr context, xmlNodePtr node, xsltCompMatchPtr countPat, xmlNodePtr cur)
Definition: numbers.c:543
int xsltTestCompMatchList(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltCompMatchPtr comp)
Definition: pattern.c:1121
FxCollectionEntry * cur
if(dx< 0)
Definition: linetemp.h:194
static unsigned __int64 next
Definition: rand_nt.c:6
xmlNode * xmlNodePtr
Definition: tree.h:488
#define XML_DOCB_DOCUMENT_NODE
Definition: tree.h:184
@ XML_ATTRIBUTE_NODE
Definition: tree.h:161
@ XML_DOCUMENT_NODE
Definition: tree.h:168
@ XML_XINCLUDE_START
Definition: tree.h:178
@ XML_XINCLUDE_END
Definition: tree.h:179
@ XML_DTD_NODE
Definition: tree.h:173
@ XML_NAMESPACE_DECL
Definition: tree.h:177
@ XML_HTML_DOCUMENT_NODE
Definition: tree.h:172
Definition: tree.h:489
Definition: tree.h:389
Definition: http.c:7252

Referenced by xsltNumberFormat().

◆ xsltNumberFormatGetMultipleLevel()

static int xsltNumberFormatGetMultipleLevel ( xsltTransformContextPtr  context,
xmlNodePtr  node,
xsltCompMatchPtr  countPat,
xsltCompMatchPtr  fromPat,
double array,
int  max 
)
static

Definition at line 634 of file numbers.c.

640{
641 int amount = 0;
642 int cnt;
643 xmlNodePtr oldCtxtNode;
644 xmlNodePtr ancestor;
645 xmlNodePtr preceding;
646 xmlXPathParserContextPtr parser;
647
648 oldCtxtNode = context->xpathCtxt->node;
649 parser = xmlXPathNewParserContext(NULL, context->xpathCtxt);
650 if (parser) {
651 /* ancestor-or-self::*[count] */
652 ancestor = node;
653 while ((ancestor != NULL) && (ancestor->type != XML_DOCUMENT_NODE)) {
654 if ((fromPat != NULL) &&
655 xsltTestCompMatchList(context, ancestor, fromPat))
656 break; /* for */
657
658 /*
659 * The xmlXPathNext* iterators require that the context node is
660 * set to the start node. Calls to xsltTestCompMatch* may also
661 * leave the context node in an undefined state, so make sure
662 * that the context node is reset before each iterator invocation.
663 */
664
665 if (xsltTestCompMatchCount(context, ancestor, countPat, node)) {
666 /* count(preceding-sibling::*) */
667 cnt = 1;
668 context->xpathCtxt->node = ancestor;
669 preceding = xmlXPathNextPrecedingSibling(parser, ancestor);
670 while (preceding != NULL) {
671 if (xsltTestCompMatchCount(context, preceding, countPat,
672 node))
673 cnt++;
674 context->xpathCtxt->node = ancestor;
675 preceding =
676 xmlXPathNextPrecedingSibling(parser, preceding);
677 }
678 array[amount++] = (double)cnt;
679 if (amount >= max)
680 break; /* for */
681 }
682 context->xpathCtxt->node = node;
683 ancestor = xmlXPathNextAncestor(parser, ancestor);
684 }
685 xmlXPathFreeParserContext(parser);
686 }
687 context->xpathCtxt->node = oldCtxtNode;
688 return amount;
689}
xmlElementType type
Definition: tree.h:491
Definition: import.c:81

Referenced by xsltNumberFormat().

◆ xsltNumberFormatGetValue()

static int xsltNumberFormatGetValue ( xmlXPathContextPtr  context,
xmlNodePtr  node,
const xmlChar value,
double number 
)
static

Definition at line 692 of file numbers.c.

696{
697 int amount = 0;
699 xmlXPathObjectPtr obj;
700
702 if (pattern != NULL) {
703 xmlBufferCCat(pattern, "number(");
706 context->node = node;
707 obj = xmlXPathEvalExpression(xmlBufferContent(pattern),
708 context);
709 if (obj != NULL) {
710 *number = obj->floatval;
711 amount++;
712 xmlXPathFreeObject(obj);
713 }
715 }
716 return amount;
717}
GLubyte * pattern
Definition: glext.h:7787
Definition: pdh_main.c:94

Referenced by xsltNumberFormat().

◆ xsltNumberFormatInsertNumbers()

static void xsltNumberFormatInsertNumbers ( xsltNumberDataPtr  data,
double numbers,
int  numbers_max,
xsltFormatPtr  tokens,
xmlBufferPtr  buffer 
)
static

Definition at line 427 of file numbers.c.

432{
433 int i = 0;
434 double number;
436
437 /*
438 * Handle initial non-alphanumeric token
439 */
440 if (tokens->start != NULL)
441 xmlBufferCat(buffer, tokens->start);
442
443 for (i = 0; i < numbers_max; i++) {
444 /* Insert number */
445 number = numbers[(numbers_max - 1) - i];
446 /* Round to nearest like XSLT 2.0 */
447 number = floor(number + 0.5);
448 /*
449 * XSLT 1.0 isn't clear on how to handle negative numbers, but XSLT
450 * 2.0 says:
451 *
452 * It is a non-recoverable dynamic error if any undiscarded item
453 * in the atomized sequence supplied as the value of the value
454 * attribute of xsl:number cannot be converted to an integer, or
455 * if the resulting integer is less than 0 (zero).
456 */
457 if (number < 0.0) {
459 "xsl-number : negative value\n");
460 /* Recover by treating negative values as zero. */
461 number = 0.0;
462 }
463 if (i < tokens->nTokens) {
464 /*
465 * The "n"th format token will be used to format the "n"th
466 * number in the list
467 */
468 token = &(tokens->tokens[i]);
469 } else if (tokens->nTokens > 0) {
470 /*
471 * If there are more numbers than format tokens, then the
472 * last format token will be used to format the remaining
473 * numbers.
474 */
475 token = &(tokens->tokens[tokens->nTokens - 1]);
476 } else {
477 /*
478 * If there are no format tokens, then a format token of
479 * 1 is used to format all numbers.
480 */
482 }
483
484 /* Print separator, except for the first number */
485 if (i > 0) {
486 if (token->separator != NULL)
487 xmlBufferCat(buffer, token->separator);
488 else
490 }
491
492 switch (xmlXPathIsInf(number)) {
493 case -1:
494 xmlBufferCCat(buffer, "-Infinity");
495 break;
496 case 1:
497 xmlBufferCCat(buffer, "Infinity");
498 break;
499 default:
500 if (xmlXPathIsNaN(number)) {
501 xmlBufferCCat(buffer, "NaN");
502 } else {
503
504 switch (token->token) {
505 case 'A':
507 break;
508 case 'a':
510 break;
511 case 'I':
513 break;
514 case 'i':
516 break;
517 default:
518 if (IS_DIGIT_ZERO(token->token)) {
520 number,
521 token->token,
522 token->width,
523 data->digitsPerGroup,
524 data->groupingCharacter,
525 data->groupingCharacterLen);
526 }
527 break;
528 }
529 }
530
531 }
532 }
533
534 /*
535 * Handle final non-alphanumeric token
536 */
537 if (tokens->end != NULL)
538 xmlBufferCat(buffer, tokens->end);
539
540}
#define IS_DIGIT_ZERO(x)
Definition: numbers.c:98
static xsltFormatToken default_token
Definition: numbers.c:46
static void xsltNumberFormatRoman(xsltNumberDataPtr data, xmlBufferPtr buffer, double number, int is_upper)
Definition: numbers.c:243
#define DEFAULT_SEPARATOR
Definition: numbers.c:23
static void xsltNumberFormatAlpha(xsltNumberDataPtr data, xmlBufferPtr buffer, double number, int is_upper)
Definition: numbers.c:196
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

Referenced by xsltNumberFormat().

◆ xsltNumberFormatRoman()

static void xsltNumberFormatRoman ( xsltNumberDataPtr  data,
xmlBufferPtr  buffer,
double  number,
int  is_upper 
)
static

Definition at line 243 of file numbers.c.

247{
248 /*
249 * See discussion in xsltNumberFormatAlpha. Also use a reasonable upper
250 * bound to avoid denial of service.
251 */
252 if (number < 1.0 || number > 5000.0) {
254 data->digitsPerGroup,
255 data->groupingCharacter,
256 data->groupingCharacterLen);
257 return;
258 }
259
260 /*
261 * Based on an example by Jim Walsh
262 */
263 while (number >= 1000.0) {
264 xmlBufferCCat(buffer, (is_upper) ? "M" : "m");
265 number -= 1000.0;
266 }
267 if (number >= 900.0) {
268 xmlBufferCCat(buffer, (is_upper) ? "CM" : "cm");
269 number -= 900.0;
270 }
271 while (number >= 500.0) {
272 xmlBufferCCat(buffer, (is_upper) ? "D" : "d");
273 number -= 500.0;
274 }
275 if (number >= 400.0) {
276 xmlBufferCCat(buffer, (is_upper) ? "CD" : "cd");
277 number -= 400.0;
278 }
279 while (number >= 100.0) {
280 xmlBufferCCat(buffer, (is_upper) ? "C" : "c");
281 number -= 100.0;
282 }
283 if (number >= 90.0) {
284 xmlBufferCCat(buffer, (is_upper) ? "XC" : "xc");
285 number -= 90.0;
286 }
287 while (number >= 50.0) {
288 xmlBufferCCat(buffer, (is_upper) ? "L" : "l");
289 number -= 50.0;
290 }
291 if (number >= 40.0) {
292 xmlBufferCCat(buffer, (is_upper) ? "XL" : "xl");
293 number -= 40.0;
294 }
295 while (number >= 10.0) {
296 xmlBufferCCat(buffer, (is_upper) ? "X" : "x");
297 number -= 10.0;
298 }
299 if (number >= 9.0) {
300 xmlBufferCCat(buffer, (is_upper) ? "IX" : "ix");
301 number -= 9.0;
302 }
303 while (number >= 5.0) {
304 xmlBufferCCat(buffer, (is_upper) ? "V" : "v");
305 number -= 5.0;
306 }
307 if (number >= 4.0) {
308 xmlBufferCCat(buffer, (is_upper) ? "IV" : "iv");
309 number -= 4.0;
310 }
311 while (number >= 1.0) {
312 xmlBufferCCat(buffer, (is_upper) ? "I" : "i");
313 number--;
314 }
315}

Referenced by xsltNumberFormatInsertNumbers().

◆ xsltNumberFormatTokenize()

static void xsltNumberFormatTokenize ( const xmlChar format,
xsltFormatPtr  tokens 
)
static

Definition at line 318 of file numbers.c.

320{
321 int ix = 0;
322 int j;
323 int val;
324 int len;
325
329
330
331 tokens->start = NULL;
332 tokens->tokens[0].separator = NULL;
333 tokens->end = NULL;
334
335 /*
336 * Insert initial non-alphanumeric token.
337 * There is always such a token in the list, even if NULL
338 */
340 &len))) {
341 if (format[ix] == 0) /* if end of format string */
342 break; /* while */
343 ix += len;
344 }
345 if (ix > 0)
346 tokens->start = xmlStrndup(format, ix);
347
348
349 for (tokens->nTokens = 0; tokens->nTokens < MAX_TOKENS;
350 tokens->nTokens++) {
351 if (format[ix] == 0)
352 break; /* for */
353
354 /*
355 * separator has already been parsed (except for the first
356 * number) in tokens->end, recover it.
357 */
358 if (tokens->nTokens > 0) {
359 tokens->tokens[tokens->nTokens].separator = tokens->end;
360 tokens->end = NULL;
361 }
362
364 if (IS_DIGIT_ONE(val) ||
366 tokens->tokens[tokens->nTokens].width = 1;
367 while (IS_DIGIT_ZERO(val)) {
368 tokens->tokens[tokens->nTokens].width++;
369 ix += len;
371 }
372 if (IS_DIGIT_ONE(val)) {
373 tokens->tokens[tokens->nTokens].token = val - 1;
374 ix += len;
376 } else {
377 tokens->tokens[tokens->nTokens].token = '0';
378 tokens->tokens[tokens->nTokens].width = 1;
379 }
380 } else if ( (val == 'A') ||
381 (val == 'a') ||
382 (val == 'I') ||
383 (val == 'i') ) {
384 tokens->tokens[tokens->nTokens].token = val;
385 ix += len;
387 } else {
388 /* XSLT section 7.7
389 * "Any other format token indicates a numbering sequence
390 * that starts with that token. If an implementation does
391 * not support a numbering sequence that starts with that
392 * token, it must use a format token of 1."
393 */
394 tokens->tokens[tokens->nTokens].token = '0';
395 tokens->tokens[tokens->nTokens].width = 1;
396 }
397 /*
398 * Skip over remaining alphanumeric characters from the Nd
399 * (Number, decimal digit), Nl (Number, letter), No (Number,
400 * other), Lu (Letter, uppercase), Ll (Letter, lowercase), Lt
401 * (Letters, titlecase), Lm (Letters, modifiers), and Lo
402 * (Letters, other (uncased)) Unicode categories. This happens
403 * to correspond to the Letter and Digit classes from XML (and
404 * one wonders why XSLT doesn't refer to these instead).
405 */
406 while (xsltIsLetterDigit(val)) {
407 ix += len;
409 }
410
411 /*
412 * Insert temporary non-alphanumeric final tooken.
413 */
414 j = ix;
415 while (!xsltIsLetterDigit(val)) {
416 if (val == 0)
417 break; /* while */
418 ix += len;
420 }
421 if (ix > j)
422 tokens->end = xmlStrndup(&format[j], ix - j);
423 }
424}
#define MAX_TOKENS
Definition: numbers.c:25
#define DEFAULT_TOKEN
Definition: numbers.c:22
static int xsltIsLetterDigit(int val)
Definition: numbers.c:79
#define IS_DIGIT_ONE(x)
Definition: numbers.c:99
XMLPUBFUN int XMLCALL xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar *cur, int *len)
XMLPUBFUN xmlChar *XMLCALL xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:42

Referenced by xsltNumberFormat().

◆ xsltTestCompMatchCount()

static int xsltTestCompMatchCount ( xsltTransformContextPtr  context,
xmlNodePtr  node,
xsltCompMatchPtr  countPat,
xmlNodePtr  cur 
)
static

Definition at line 543 of file numbers.c.

547{
548 if (countPat != NULL) {
549 return xsltTestCompMatchList(context, node, countPat);
550 }
551 else {
552 /*
553 * 7.7 Numbering
554 *
555 * If count attribute is not specified, then it defaults to the
556 * pattern that matches any node with the same node type as the
557 * current node and, if the current node has an expanded-name, with
558 * the same expanded-name as the current node.
559 */
560 if (node->type != cur->type)
561 return 0;
562 if (node->type == XML_NAMESPACE_DECL)
563 /*
564 * Namespace nodes have no preceding siblings and no parents
565 * that are namespace nodes. This means that node == cur.
566 */
567 return 1;
568 /* TODO: Skip node types without expanded names like text nodes. */
569 if (!xmlStrEqual(node->name, cur->name))
570 return 0;
571 if (node->ns == cur->ns)
572 return 1;
573 if ((node->ns == NULL) || (cur->ns == NULL))
574 return 0;
575 return (xmlStrEqual(node->ns->href, cur->ns->href));
576 }
577}

Referenced by xsltNumberFormatGetAnyLevel(), and xsltNumberFormatGetMultipleLevel().

◆ xsltUTF8Charcmp()

static int xsltUTF8Charcmp ( xmlChar utf1,
xmlChar utf2 
)
static

xsltUTF8Charcmp @utf1: pointer to first UTF8 char @utf2: pointer to second UTF8 char

returns result of comparing the two UCS4 values as with xmlStrncmp

Definition at line 65 of file numbers.c.

65 {
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}

Referenced by xsltFormatNumberConversion(), and xsltFormatNumberPreSuffix().

Variable Documentation

◆ alpha_lower_list

char alpha_lower_list[] = "abcdefghijklmnopqrstuvwxyz"
static

Definition at line 45 of file numbers.c.

Referenced by xsltNumberFormatAlpha().

◆ alpha_upper_list

char alpha_upper_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
static

Definition at line 44 of file numbers.c.

Referenced by xsltNumberFormatAlpha().

◆ default_token

xsltFormatToken default_token
static

Definition at line 46 of file numbers.c.

Referenced by xsltNumberFormatInsertNumbers(), and xsltNumberFormatTokenize().