mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-10-21 14:53:44 +03:00
enhanced the parsing of XML_SCHEMAS_DECIMAL and much of the routine
* xmlschemastypes.c: enhanced the parsing of XML_SCHEMAS_DECIMAL and much of the routine xmlSchemaCompareDecimals. The changes were necessary to fix a problem reported on the mailing list by John Hockaday.
This commit is contained in:
@@ -1,3 +1,10 @@
|
|||||||
|
Fri Mar 11 23:53:13 HKT 2005 William Brack <wbrack@mmm.com.hk>
|
||||||
|
|
||||||
|
* xmlschemastypes.c: enhanced the parsing of XML_SCHEMAS_DECIMAL
|
||||||
|
and much of the routine xmlSchemaCompareDecimals. The
|
||||||
|
changes were necessary to fix a problem reported on the
|
||||||
|
mailing list by John Hockaday.
|
||||||
|
|
||||||
Fri Mar 11 13:22:52 CET 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
|
Fri Mar 11 13:22:52 CET 2005 Kasimier Buchcik <libxml2-cvs@cazic.net>
|
||||||
|
|
||||||
* xmlschemas.c: The schema parser will stop if components could
|
* xmlschemas.c: The schema parser will stop if components could
|
||||||
|
@@ -50,13 +50,6 @@ extern double xmlXPathNINF;
|
|||||||
|
|
||||||
#define IS_WSP_SPACE_CH(c) ((c) == 0x20)
|
#define IS_WSP_SPACE_CH(c) ((c) == 0x20)
|
||||||
|
|
||||||
|
|
||||||
static unsigned long powten[10] = {
|
|
||||||
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000L,
|
|
||||||
100000000L, 1000000000L
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Date value */
|
/* Date value */
|
||||||
typedef struct _xmlSchemaValDate xmlSchemaValDate;
|
typedef struct _xmlSchemaValDate xmlSchemaValDate;
|
||||||
typedef xmlSchemaValDate *xmlSchemaValDatePtr;
|
typedef xmlSchemaValDate *xmlSchemaValDatePtr;
|
||||||
@@ -1890,42 +1883,76 @@ xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
|
|||||||
goto return0;
|
goto return0;
|
||||||
}
|
}
|
||||||
case XML_SCHEMAS_DECIMAL:{
|
case XML_SCHEMAS_DECIMAL:{
|
||||||
const xmlChar *cur = value, *tmp;
|
const xmlChar *cur = value;
|
||||||
unsigned int frac = 0, len, neg = 0;
|
unsigned int len, neg = 0;
|
||||||
unsigned long base = 0;
|
xmlChar cval[25];
|
||||||
|
xmlChar *cptr = cval;
|
||||||
|
int dec = -1;
|
||||||
|
|
||||||
if (cur == NULL)
|
if (cur == NULL)
|
||||||
goto return1;
|
goto return1;
|
||||||
|
/* First we handle an optional sign */
|
||||||
if (*cur == '+')
|
if (*cur == '+')
|
||||||
cur++;
|
cur++;
|
||||||
else if (*cur == '-') {
|
else if (*cur == '-') {
|
||||||
neg = 1;
|
neg = 1;
|
||||||
cur++;
|
cur++;
|
||||||
}
|
}
|
||||||
tmp = cur;
|
/*
|
||||||
while ((*cur >= '0') && (*cur <= '9')) {
|
* Next we "pre-parse" the number, in preparation for calling
|
||||||
base = base * 10 + (*cur - '0');
|
* the common routine xmlSchemaParseUInt. We get rid of any
|
||||||
cur++;
|
* leading zeroes (because we have reserved only 25 chars),
|
||||||
}
|
* and note the position of any decimal point.
|
||||||
len = cur - tmp;
|
*/
|
||||||
if (*cur == '.') {
|
len = 0;
|
||||||
cur++;
|
while (len < 24) {
|
||||||
tmp = cur;
|
if ((*cur >= '0') && (*cur <= '9')) {
|
||||||
while ((*cur >= '0') && (*cur <= '9')) {
|
*cptr++ = *cur;
|
||||||
base = base * 10 + (*cur - '0');
|
len++;
|
||||||
cur++;
|
} else if (*cur == '.') {
|
||||||
}
|
if (dec != -1)
|
||||||
frac = cur - tmp;
|
goto return1; /* multiple decimal points */
|
||||||
}
|
if (!len) { /* num starts with '.' */
|
||||||
if (*cur != 0)
|
*cptr++ = '0';
|
||||||
goto return1;
|
len++;
|
||||||
|
}
|
||||||
|
dec = len++;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
if (*cur != 0)
|
||||||
|
goto return1; /* error if any extraneous chars */
|
||||||
|
|
||||||
if (val != NULL) {
|
if (val != NULL) {
|
||||||
v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
|
v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
|
||||||
if (v != NULL) {
|
if (v != NULL) {
|
||||||
v->value.decimal.lo = base;
|
/*
|
||||||
|
* If a mixed decimal, get rid of trailing zeroes
|
||||||
|
*/
|
||||||
|
if (dec) {
|
||||||
|
while ((cptr > cval) && (*(cptr-1) == '0')) {
|
||||||
|
cptr--;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*cptr = 0; /* Terminate our (preparsed) string */
|
||||||
|
cptr = cval;
|
||||||
|
/*
|
||||||
|
* Now evaluate the significant digits of the number
|
||||||
|
*/
|
||||||
|
xmlSchemaParseUInt((const xmlChar **)&cptr,
|
||||||
|
&v->value.decimal.lo,
|
||||||
|
&v->value.decimal.mi,
|
||||||
|
&v->value.decimal.hi);
|
||||||
v->value.decimal.sign = neg;
|
v->value.decimal.sign = neg;
|
||||||
v->value.decimal.frac = frac;
|
if (dec == -1) {
|
||||||
v->value.decimal.total = frac + len;
|
v->value.decimal.frac = 0;
|
||||||
|
v->value.decimal.total = len;
|
||||||
|
} else {
|
||||||
|
v->value.decimal.frac = len - dec - 1;
|
||||||
|
v->value.decimal.total = len - 1;
|
||||||
|
}
|
||||||
*val = v;
|
*val = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2879,59 +2906,106 @@ static int
|
|||||||
xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
|
xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
|
||||||
{
|
{
|
||||||
xmlSchemaValPtr swp;
|
xmlSchemaValPtr swp;
|
||||||
int order = 1, p;
|
int order = 1, integx, integy, dlen;
|
||||||
unsigned long tmp;
|
unsigned long hi, mi, lo;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First test: If x is -ve and not zero
|
||||||
|
*/
|
||||||
if ((x->value.decimal.sign) &&
|
if ((x->value.decimal.sign) &&
|
||||||
((x->value.decimal.lo != 0) ||
|
((x->value.decimal.lo != 0) ||
|
||||||
(x->value.decimal.mi != 0) ||
|
(x->value.decimal.mi != 0) ||
|
||||||
(x->value.decimal.hi != 0))) {
|
(x->value.decimal.hi != 0))) {
|
||||||
|
/*
|
||||||
|
* Then if y is -ve and not zero reverse the compare
|
||||||
|
*/
|
||||||
if ((y->value.decimal.sign) &&
|
if ((y->value.decimal.sign) &&
|
||||||
((y->value.decimal.lo != 0) ||
|
((y->value.decimal.lo != 0) ||
|
||||||
(y->value.decimal.mi != 0) ||
|
(y->value.decimal.mi != 0) ||
|
||||||
(y->value.decimal.hi != 0)))
|
(y->value.decimal.hi != 0)))
|
||||||
order = -1;
|
order = -1;
|
||||||
|
/*
|
||||||
|
* Otherwise (y >= 0) we have the answer
|
||||||
|
*/
|
||||||
else
|
else
|
||||||
return (-1);
|
return (-1);
|
||||||
|
/*
|
||||||
|
* If x is not -ve and y is -ve we have the answer
|
||||||
|
*/
|
||||||
} else if ((y->value.decimal.sign) &&
|
} else if ((y->value.decimal.sign) &&
|
||||||
((y->value.decimal.lo != 0) ||
|
((y->value.decimal.lo != 0) ||
|
||||||
(y->value.decimal.mi != 0) ||
|
(y->value.decimal.mi != 0) ||
|
||||||
(y->value.decimal.hi != 0))) {
|
(y->value.decimal.hi != 0))) {
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
if (x->value.decimal.frac == y->value.decimal.frac) {
|
/*
|
||||||
if (x->value.decimal.hi < y->value.decimal.hi)
|
* If it's not simply determined by a difference in sign,
|
||||||
return (-order);
|
* then we need to compare the actual values of the two nums.
|
||||||
if (x->value.decimal.hi > y->value.decimal.hi)
|
* To do this, we start by looking at the integral parts.
|
||||||
return (order);
|
* If the number of integral digits differ, then we have our
|
||||||
if (x->value.decimal.mi < y->value.decimal.mi)
|
* answer.
|
||||||
return (-order);
|
*/
|
||||||
if (x->value.decimal.mi > y->value.decimal.mi)
|
integx = x->value.decimal.total - x->value.decimal.frac;
|
||||||
return (order);
|
integy = y->value.decimal.total - y->value.decimal.frac;
|
||||||
if (x->value.decimal.lo < y->value.decimal.lo)
|
if (integx > integy)
|
||||||
return (-order);
|
return order;
|
||||||
if (x->value.decimal.lo > y->value.decimal.lo)
|
else if (integy > integx)
|
||||||
return(order);
|
return -order;
|
||||||
return(0);
|
/*
|
||||||
|
* If the number of integral digits is the same for both numbers,
|
||||||
|
* then things get a little more complicated. We need to "normalize"
|
||||||
|
* the numbers in order to properly compare them. To do this, we
|
||||||
|
* look at the total length of each number (length => number of
|
||||||
|
* significant digits), and divide the "shorter" by 10 (decreasing
|
||||||
|
* the length) until they are of equal length.
|
||||||
|
*/
|
||||||
|
dlen = x->value.decimal.total - y->value.decimal.total;
|
||||||
|
if (dlen < 0) { /* y has more digits than x */
|
||||||
|
swp = x;
|
||||||
|
hi = y->value.decimal.hi;
|
||||||
|
mi = y->value.decimal.mi;
|
||||||
|
lo = y->value.decimal.lo;
|
||||||
|
dlen = -dlen;
|
||||||
|
order = -order;
|
||||||
|
} else { /* x has more digits than y */
|
||||||
|
swp = y;
|
||||||
|
hi = x->value.decimal.hi;
|
||||||
|
mi = x->value.decimal.mi;
|
||||||
|
lo = x->value.decimal.lo;
|
||||||
}
|
}
|
||||||
if (y->value.decimal.frac > x->value.decimal.frac) {
|
while (dlen > 8) { /* in effect, right shift by 10**8 */
|
||||||
swp = y;
|
lo = mi;
|
||||||
y = x;
|
mi = hi;
|
||||||
x = swp;
|
hi = 0;
|
||||||
order = -order;
|
dlen -= 8;
|
||||||
}
|
}
|
||||||
p = powten[x->value.decimal.frac - y->value.decimal.frac];
|
while (dlen > 0) {
|
||||||
tmp = x->value.decimal.lo / p;
|
unsigned long rem1, rem2;
|
||||||
if (tmp > y->value.decimal.lo)
|
rem1 = (hi % 10) * 100000000L;
|
||||||
return (order);
|
hi = hi / 10;
|
||||||
if (tmp < y->value.decimal.lo)
|
rem2 = (mi % 10) * 100000000L;
|
||||||
return (-order);
|
mi = (mi + rem1) / 10;
|
||||||
tmp = y->value.decimal.lo * p;
|
lo = (lo + rem2) / 10;
|
||||||
if (x->value.decimal.lo < tmp)
|
dlen--;
|
||||||
return (-order);
|
}
|
||||||
if (x->value.decimal.lo == tmp)
|
if (hi > swp->value.decimal.hi) {
|
||||||
return (0);
|
return order;
|
||||||
return (order);
|
} else if (hi == swp->value.decimal.hi) {
|
||||||
|
if (mi > swp->value.decimal.mi) {
|
||||||
|
return order;
|
||||||
|
} else if (mi == swp->value.decimal.mi) {
|
||||||
|
if (lo > swp->value.decimal.lo) {
|
||||||
|
return order;
|
||||||
|
} else if (lo == swp->value.decimal.lo) {
|
||||||
|
if (x->value.decimal.total == y->value.decimal.total) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -order;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user