1
0
mirror of https://gitlab.gnome.org/GNOME/libxml2.git synced 2024-10-26 20:25:14 +03:00

Fixed parsing of xs:decimal to allow/deny special lexical forms. Fixed the

* xmlschemastypes.c: Fixed parsing of xs:decimal to
  allow/deny special lexical forms. Fixed the totalDigits
  for values in the range (x < 1) &&  (x > -1) && (x != 0);
  E.g "0.123" has now a totalDigits of 3 (was 4 previously).
  Adjusted the comparison function for decimals due to this
  change. As a side effect comparison against zeroes was
  optimized.
This commit is contained in:
Kasimier T. Buchcik 2005-11-28 16:36:30 +00:00
parent 132ba5f5da
commit 72f50c18d9
2 changed files with 113 additions and 49 deletions

View File

@ -1,3 +1,13 @@
Mon Nov 28 17:28:53 CET 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
* xmlschemastypes.c: Fixed parsing of xs:decimal to
allow/deny special lexical forms. Fixed the totalDigits
for values in the range (x < 1) && (x > -1) && (x != 0);
E.g "0.123" has now a totalDigits of 3 (was 4 previously).
Adjusted the comparison function for decimals due to this
change. As a side effect comparison against zeroes was
optimized.
Mon Nov 28 13:25:11 CET 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
* xmlschemas.c: An assignment to a local variable, which was

View File

@ -2244,100 +2244,122 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
}
case XML_SCHEMAS_DECIMAL:{
const xmlChar *cur = value;
unsigned int len, neg = 0;
unsigned int len, neg, integ, hasLeadingZeroes;
xmlChar cval[25];
xmlChar *cptr = cval;
unsigned int dec = ~0u;
xmlChar *cptr = cval;
if (cur == NULL)
if ((cur == NULL) || (*cur == 0))
goto return1;
/*
* xs:decimal has a whitespace-facet value of 'collapse'.
*/
if (normOnTheFly)
while IS_WSP_BLANK_CH(*cur) cur++;
/* First we handle an optional sign */
if (*cur == '+')
/*
* First we handle an optional sign.
*/
neg = 0;
if (*cur == '-') {
neg = 1;
cur++;
else if (*cur == '-') {
neg = 1;
} else if (*cur == '+')
cur++;
}
/*
* Disallow: "", "-", "- "
*/
if (*cur == 0)
goto return1;
/*
* Next we "pre-parse" the number, in preparation for calling
* the common routine xmlSchemaParseUInt. We get rid of any
* leading zeroes (because we have reserved only 25 chars),
* and note the position of any decimal point.
* and note the position of a decimal point.
*/
len = 0;
integ = ~0u;
hasLeadingZeroes = 0;
/*
* Skip leading zeroes.
*/
while (*cur == '0')
while (*cur == '0') {
cur++;
hasLeadingZeroes = 1;
}
if (*cur != 0) {
while (len < 24) {
do {
if ((*cur >= '0') && (*cur <= '9')) {
*cptr++ = *cur++;
len++;
} else if (*cur == '.') {
if (len == 0)
len++;
if (dec != ~0u)
goto return1; /* multiple decimal points */
cur++;
if ((*cur == 0) && (cur -1 == value))
integ = len;
do {
if ((*cur >= '0') && (*cur <= '9')) {
*cptr++ = *cur++;
len++;
} else
break;
} while (len < 24);
/*
* Disallow "." but allow "00."
*/
if ((len == 0) && (!hasLeadingZeroes))
goto return1;
dec = len;
while ((len < 24) && (*cur >= '0') &&
(*cur <= '9')) {
*cptr++ = *cur++;
len++;
}
break;
} else
break;
}
} while (len < 24);
}
if (normOnTheFly)
while IS_WSP_BLANK_CH(*cur) cur++;
if (*cur != 0)
goto return1; /* error if any extraneous chars */
goto return1; /* error if any extraneous chars */
if (val != NULL) {
v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
if (v != NULL) {
/*
* If a mixed decimal, get rid of trailing zeroes
*/
if (dec != ~0u) {
while ((len > dec) && (cptr > cval) &&
(*(cptr-1) == '0')) {
cptr--;
len--;
}
}
*cptr = 0; /* Terminate our (preparsed) string */
cptr = cval;
/*
* Now evaluate the significant digits of the number
*/
if (*cptr != 0)
xmlSchemaParseUInt((const xmlChar **)&cptr,
&v->value.decimal.lo,
&v->value.decimal.mi,
&v->value.decimal.hi);
if (len != 0) {
if (integ != ~0u) {
/*
* Get rid of trailing zeroes in the
* fractional part.
*/
while ((len != integ) && (*(cptr-1) == '0')) {
cptr--;
len--;
}
}
/*
* Terminate the (preparsed) string.
*/
if (len != 0) {
*cptr = 0;
cptr = cval;
xmlSchemaParseUInt((const xmlChar **)&cptr,
&v->value.decimal.lo,
&v->value.decimal.mi,
&v->value.decimal.hi);
}
}
/*
* Set the total digits to 1 if a zero value.
*/
if (len == 0)
len++;
v->value.decimal.sign = neg;
if (dec == ~0u) {
v->value.decimal.frac = 0;
v->value.decimal.total = len;
if (len == 0) {
/* Speedup for zero values. */
v->value.decimal.total = 1;
} else {
v->value.decimal.frac = len - dec;
v->value.decimal.total = len;
if (integ == ~0u)
v->value.decimal.frac = 0;
else
v->value.decimal.frac = len - integ;
}
*val = v;
}
@ -3402,10 +3424,42 @@ xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
*/
integx = x->value.decimal.total - x->value.decimal.frac;
integy = y->value.decimal.total - y->value.decimal.frac;
/*
* NOTE: We changed the "total" for values like "0.1"
* (or "-0.1" or ".1") to be 1, which was 2 previously.
* Therefore the special case, when such values are
* compared with 0, needs to be handled separately;
* otherwise a zero would be recognized incorrectly as
* greater than those values. This has the nice side effect
* that we gain an overall optimized comparison with zeroes.
* Note that a "0" has a "total" of 1 already.
*/
if (integx == 1) {
if (x->value.decimal.lo == 0) {
if (integy != 1)
return -order;
else if (y->value.decimal.lo != 0)
return -order;
else
return(0);
}
}
if (integy == 1) {
if (y->value.decimal.lo == 0) {
if (integx != 1)
return order;
else if (x->value.decimal.lo != 0)
return order;
else
return(0);
}
}
if (integx > integy)
return order;
else if (integy > integx)
return -order;
/*
* If the number of integral digits is the same for both numbers,
* then things get a little more complicated. We need to "normalize"