Index: xmlschemastypes.c =================================================================== RCS file: /cvs/gnome/libxml2/xmlschemastypes.c,v retrieving revision 1.41 diff -c -r1.41 xmlschemastypes.c *** xmlschemastypes.c 15 Jul 2003 13:34:05 -0000 1.41 --- xmlschemastypes.c 1 Aug 2003 03:13:02 -0000 *************** *** 86,96 **** XML_SCHEMAS_HEXBINARY } xmlSchemaValType; - static unsigned long powten[10] = { - 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000L, - 100000000L, 1000000000L - }; - /* Date value */ typedef struct _xmlSchemaValDate xmlSchemaValDate; typedef xmlSchemaValDate *xmlSchemaValDatePtr; --- 86,91 ---- *************** *** 117,130 **** typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal; typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr; struct _xmlSchemaValDecimal { ! /* would use long long but not portable */ ! unsigned long lo; ! unsigned long mi; ! unsigned long hi; ! unsigned int extra; ! unsigned int sign:1; ! int frac:7; ! int total:8; }; typedef struct _xmlSchemaValQName xmlSchemaValQName; --- 112,123 ---- typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal; typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr; struct _xmlSchemaValDecimal { ! xmlChar *istr; /* integer string */ ! xmlChar *fstr; /* fraction string */ ! unsigned int sign :1; /* 1 => negative */ ! unsigned int fsize :31; /* trailing zeros are not counted */ ! unsigned int isize; ! unsigned int total; }; typedef struct _xmlSchemaValQName xmlSchemaValQName; *************** *** 413,418 **** --- 406,431 ---- if (value->value.qname.name != NULL) xmlFree(value->value.qname.name); break; + case XML_SCHEMAS_HEXBINARY: + case XML_SCHEMAS_DECIMAL: + case XML_SCHEMAS_INTEGER: + case XML_SCHEMAS_PINTEGER: + case XML_SCHEMAS_NPINTEGER: + case XML_SCHEMAS_NINTEGER: + case XML_SCHEMAS_NNINTEGER: + case XML_SCHEMAS_LONG: + case XML_SCHEMAS_BYTE: + case XML_SCHEMAS_SHORT: + case XML_SCHEMAS_INT: + case XML_SCHEMAS_ULONG: + case XML_SCHEMAS_UBYTE: + case XML_SCHEMAS_USHORT: + case XML_SCHEMAS_UINT: + if (value->value.decimal.istr != NULL) + xmlFree(value->value.decimal.istr); + if (value->value.decimal.fstr != NULL) + xmlFree(value->value.decimal.fstr); + break; default: break; } *************** *** 1314,1370 **** return(-1); } /** ! * xmlSchemaParseUInt: ! * @str: pointer to the string R/W ! * @llo: pointer to the low result ! * @lmi: pointer to the mid result ! * @lhi: pointer to the high result * ! * Parse an unsigned long into 3 fields. ! * ! * Returns the number of chars parsed or -1 if overflow of the capacity */ static int ! xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo, ! unsigned long *lmi, unsigned long *lhi) { ! unsigned long lo = 0, mi = 0, hi = 0; ! const xmlChar *tmp, *cur = *str; ! int ret = 0, i = 0; while (*cur == '0') { - ret++; cur++; } tmp = cur; ! while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) { i++;tmp++;ret++; } ! if (i > 24) { ! *str = tmp; ! return(-1); } ! while (i > 16) { ! hi = hi * 10 + (*cur++ - '0'); ! i--; ! } ! while (i > 8) { ! mi = mi * 10 + (*cur++ - '0'); ! i--; ! } ! while (i > 0) { ! lo = lo * 10 + (*cur++ - '0'); ! i--; } ! *str = cur; ! *llo = lo; ! *lmi = mi; ! *lhi = hi; return(ret); } /** * xmlSchemaValAtomicType: * @type: the predefined type * @value: the value to check --- 1327,1442 ---- return(-1); } + /** ! * xmlSchemaParseDecimal: ! * @istr: pointer to integer string ! * @idig: pointer to the resulting number of integer digits ! * @fstr: pointer to fraction string ! * @fdig: pointer to the resulting number of fraction digits ! * @iszero: pointer to flag indicating value is zero ! * ! * Parse a decimal type into it's cononical constituent integer and fraction ! * portions. This routine moves the @istr pointer (which is the initial source ! * of the string to parse) to the point where there are not leading zeros. The ! * @fstr parameter will point to the '.' or NULL if the fraction does not ! * exist. The string passed in @istr is not modified in any way. * ! * Returns the number of chars parsed or -1 if error */ static int ! xmlSchemaParseDecimal(const xmlChar **istr, int *idig, ! const xmlChar **fstr, int *fdig, int *iszero) { ! const xmlChar *tmp, *ftmp = 0, *cur = *istr; ! int ret = 0, i = 0, j = 0, z = 1; + /* remove leading zeros */ while (*cur == '0') { cur++; } + /* insure there is at least one zero */ + if ((*cur == 0) || (*cur == '.')) { + cur--; + if (*cur != '0') + return(-1); + } + + /* validate the integer portion */ tmp = cur; ! while ((*tmp >= '0') && (*tmp <= '9')) { ! if (*tmp != '0') ! z = 0; i++;tmp++;ret++; } ! ! /* validate the fraction portion */ ! ftmp = tmp; ! if (*tmp == '.') { ! tmp++; ! while ((*tmp >= '0') && (*tmp <= '9')) { ! if (*tmp != '0') ! z = 0; ! j++;tmp++;ret++; ! } } ! ! /* is the string terminated properly */ ! if (*tmp != 0) ! return(-1); ! ! /* remove trailing zeros from the fractional size */ ! if (j > 0) { ! /* note: ftmp includes the decimal point */ ! while ((j > 0) && (ftmp[j] == '0')) ! j--; } ! /* set return values */ ! *istr = cur; ! *idig = i; ! *fstr = ftmp; ! *fdig = j; ! *iszero = z; ! return(ret); } /** + * xmlSchemaCompareIntStr: + * @xsign: sign of the x value + * @xstr: pointer to string of x value + * @xlen: length of the x value + * @ysign: sign of the y value + * @ystr: pointer to string of y value + * @ylen: length of the y value + * + * Compare 2 integer or hexBinary values (strings). This routine assumes there + * is no negative zero. + * + * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error + */ + static int + xmlSchemaCompareIntStr(int xsign, const xmlChar *xstr, unsigned int xlen, + int ysign, const xmlChar *ystr, unsigned int ylen) { + int ret = 1, sign_adjust = (xsign ? -1 : 1); + + if (xsign == ysign) { + if (xlen == ylen) { + + /* compare string values */ + ret = xmlStrcmp(xstr, ystr); + + if (ret == 0) + return(0); + } + if (xlen < ylen) + ret = -1; + } + + return(ret * sign_adjust); + } + + /** * xmlSchemaValAtomicType: * @type: the predefined type * @value: the value to check *************** *** 1411,1454 **** case XML_SCHEMAS_NORMSTRING: TODO goto return0; case XML_SCHEMAS_DECIMAL: { ! const xmlChar *cur = value, *tmp; ! int frac = 0, len, neg = 0; ! unsigned long base = 0; if (cur == NULL) goto return1; if (*cur == '+') cur++; else if (*cur == '-') { neg = 1; cur++; } ! tmp = cur; ! while ((*cur >= '0') && (*cur <= '9')) { ! base = base * 10 + (*cur - '0'); ! cur++; ! } ! len = cur - tmp; ! if (*cur == '.') { ! cur++; ! tmp = cur; ! while ((*cur >= '0') && (*cur <= '9')) { ! base = base * 10 + (*cur - '0'); ! cur++; ! } ! frac = cur - tmp; ! } ! if (*cur != 0) ! goto return1; if (val != NULL) { ! v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL); ! if (v != NULL) { ! v->value.decimal.lo = base; ! v->value.decimal.sign = neg; ! v->value.decimal.frac = frac; ! v->value.decimal.total = frac + len; *val = v; ! } } goto return0; } --- 1483,1649 ---- case XML_SCHEMAS_NORMSTRING: TODO goto return0; + case XML_SCHEMAS_UINT: + case XML_SCHEMAS_ULONG: + case XML_SCHEMAS_USHORT: + case XML_SCHEMAS_UBYTE: + case XML_SCHEMAS_LONG: + case XML_SCHEMAS_BYTE: + case XML_SCHEMAS_SHORT: + case XML_SCHEMAS_INT: + case XML_SCHEMAS_INTEGER: + case XML_SCHEMAS_PINTEGER: + case XML_SCHEMAS_NPINTEGER: + case XML_SCHEMAS_NINTEGER: + case XML_SCHEMAS_NNINTEGER: case XML_SCHEMAS_DECIMAL: { ! const xmlChar *cur = value, *fstr; ! xmlChar *iptr, *fptr = NULL; ! int idig, fdig, total, iszero; ! int neg = 0; if (cur == NULL) goto return1; if (*cur == '+') cur++; else if (*cur == '-') { + if ((type->flags == XML_SCHEMAS_UINT) || + (type->flags == XML_SCHEMAS_ULONG) || + (type->flags == XML_SCHEMAS_USHORT) || + (type->flags == XML_SCHEMAS_UBYTE)) + goto return1; + neg = 1; cur++; } ! total = xmlSchemaParseDecimal(&cur, &idig, &fstr, &fdig, &iszero); ! if (total < 0) ! goto return1; ! if (idig == 0) ! goto return1; ! if ((type->flags != XML_SCHEMAS_DECIMAL) && ! ((fdig > 0) || (*fstr == '.'))) ! goto return1; ! /* constrain derived types */ ! switch (type->flags) { ! case XML_SCHEMAS_NPINTEGER: ! if ((neg == 0) && (!iszero)) ! goto return1; ! break; ! case XML_SCHEMAS_PINTEGER: ! if ((neg == 1) || (iszero)) ! goto return1; ! break; ! case XML_SCHEMAS_NINTEGER: ! if ((neg == 0) || (iszero)) ! goto return1; ! break; ! case XML_SCHEMAS_NNINTEGER: ! if ((neg == 1) && (!iszero)) ! goto return1; ! break; ! case XML_SCHEMAS_LONG: ! case XML_SCHEMAS_BYTE: ! case XML_SCHEMAS_SHORT: ! case XML_SCHEMAS_INT: { ! static const xmlChar lpos[] = "9223372036854775807"; ! static const xmlChar lneg[] = "9223372036854775808"; ! static const xmlChar ipos[] = "2147483647"; ! static const xmlChar ineg[] = "2147483648"; ! static const xmlChar spos[] = "32767"; ! static const xmlChar sneg[] = "32768"; ! static const xmlChar bpos[] = "127"; ! static const xmlChar bneg[] = "128"; ! const xmlChar *pstr, *nstr; ! int ret; ! unsigned int len; ! ! if (type->flags == XML_SCHEMAS_LONG) { ! pstr = lpos; nstr = lneg; len = xmlStrlen(lpos); ! } ! else if (type->flags == XML_SCHEMAS_INT) { ! pstr = ipos; nstr = ineg; len = xmlStrlen(ipos); ! } ! else if (type->flags == XML_SCHEMAS_SHORT) { ! pstr = spos; nstr = sneg; len = xmlStrlen(spos); ! } ! else if (type->flags == XML_SCHEMAS_BYTE) { ! pstr = bpos; nstr = bneg; len = xmlStrlen(bpos); ! } ! else ! goto return1; ! ! ret = xmlSchemaCompareIntStr(neg, cur, idig, 0, pstr, len); ! if (ret > 0) ! goto return1; ! ret = xmlSchemaCompareIntStr(neg, cur, idig, 1, nstr, len); ! if (ret < 0) ! goto return1; ! break; ! } ! case XML_SCHEMAS_UINT: ! case XML_SCHEMAS_ULONG: ! case XML_SCHEMAS_USHORT: ! case XML_SCHEMAS_UBYTE: { ! static const xmlChar lpos[] = "1844674407379551615"; ! static const xmlChar ipos[] = "4294967295"; ! static const xmlChar spos[] = "65535"; ! static const xmlChar bpos[] = "255"; ! const xmlChar *pstr; ! int ret; ! unsigned int len; ! ! if (type->flags == XML_SCHEMAS_ULONG) { ! pstr = lpos; len = xmlStrlen(lpos); ! } ! else if (type->flags == XML_SCHEMAS_UINT) { ! pstr = ipos; len = xmlStrlen(ipos); ! } ! else if (type->flags == XML_SCHEMAS_USHORT) { ! pstr = spos; len = xmlStrlen(spos); ! } ! else if (type->flags == XML_SCHEMAS_UBYTE) { ! pstr = bpos; len = xmlStrlen(bpos); ! } ! else ! goto return1; ! ! ret = xmlSchemaCompareIntStr(0, cur, idig, 0, pstr, len); ! if (ret > 0) ! goto return1; ! } ! break; ! ! case XML_SCHEMAS_DECIMAL: ! default: ! break; ! } ! ! iptr = xmlStrndup(cur, idig); ! if (iptr == NULL) ! goto return1; ! ! if (fdig > 0) { ! if (*fstr == '.') ! fstr++; ! ! fptr = xmlStrndup(fstr, fdig); ! if (fptr == NULL) { ! xmlFree(iptr); ! goto return1; ! } ! } ! if (val != NULL) { ! v = xmlSchemaNewValue(type->flags); ! if (v != NULL) { ! v->value.decimal.sign = neg; ! v->value.decimal.istr = iptr; ! v->value.decimal.fstr = fptr; ! v->value.decimal.isize = idig; ! v->value.decimal.fsize = fdig; ! v->value.decimal.total = total; *val = v; ! } } goto return0; } *************** *** 1590,1595 **** --- 1785,1792 ---- case XML_SCHEMAS_BOOLEAN: { const xmlChar *cur = value; + if (cur == NULL) + goto return1; if ((cur[0] == '0') && (cur[1] == 0)) ret = 0; else if ((cur[0] == '1') && (cur[1] == 0)) *************** *** 1920,1931 **** } case XML_SCHEMAS_HEXBINARY: { const xmlChar *tmp, *cur = value; int total, i = 0; - unsigned long lo = 0, mi = 0, hi = 0; - unsigned long *base; ! if (cur == NULL) ! goto return1; tmp = cur; while (((*tmp >= '0') && (*tmp <= '9')) || ((*tmp >= 'A') && (*tmp <= 'F')) || --- 2117,2131 ---- } case XML_SCHEMAS_HEXBINARY: { const xmlChar *tmp, *cur = value; + xmlChar *base; int total, i = 0; ! if (cur == NULL) ! goto return1; ! ! while ((cur[0] == '0') && (cur[1] == '0') && (cur[2] != 0)) ! cur += 2; ! tmp = cur; while (((*tmp >= '0') && (*tmp <= '9')) || ((*tmp >= 'A') && (*tmp <= 'F')) || *************** *** 1935,1979 **** if (*tmp != 0) goto return1; - if (i > 24) - goto return1; if ((i % 2) != 0) goto return1; ! total = i / 2; /* number of octets */ ! if (i >= 16) ! base = &hi; ! else if (i >= 8) ! base = &mi; ! else ! base = &lo; while (i > 0) { ! if ((*cur >= '0') && (*cur <= '9')) { ! *base = *base * 16 + (*cur - '0'); ! } else if ((*cur >= 'A') && (*cur <= 'F')) { ! *base = *base * 16 + (*cur - 'A') + 10; } else if ((*cur >= 'a') && (*cur <= 'f')) { ! *base = *base * 16 + (*cur - 'a') + 10; ! } else ! break; ! cur++; i--; - if (i == 16) - base = &mi; - else if (i == 8) - base = &lo; } if (val != NULL) { v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY); if (v != NULL) { ! v->value.decimal.lo = lo; ! v->value.decimal.mi = mi; ! v->value.decimal.hi = hi; v->value.decimal.total = total; *val = v; } else { goto error; --- 2135,2169 ---- if (*tmp != 0) goto return1; if ((i % 2) != 0) goto return1; ! tmp = xmlMalloc(i+1); ! if (tmp == NULL) ! goto return1; ! total = i / 2; /* number of octets */ + base = (xmlChar *)tmp; while (i > 0) { ! if (((*cur >= '0') && (*cur <= '9')) || ! ((*cur >= 'A') && (*cur <= 'F'))) { ! *base = *cur; } else if ((*cur >= 'a') && (*cur <= 'f')) { ! *base = *cur - ('a' - 'A'); ! } ! cur++;base++; i--; } + *base = 0; if (val != NULL) { v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY); if (v != NULL) { ! v->value.decimal.istr = (xmlChar *)tmp; v->value.decimal.total = total; + v->value.decimal.isize = total; *val = v; } else { goto error; *************** *** 1981,2174 **** } goto return0; } - case XML_SCHEMAS_INTEGER: - case XML_SCHEMAS_PINTEGER: - case XML_SCHEMAS_NPINTEGER: - case XML_SCHEMAS_NINTEGER: - case XML_SCHEMAS_NNINTEGER: { - const xmlChar *cur = value; - unsigned long lo, mi, hi; - int sign = 0; - if (cur == NULL) - goto return1; - if (*cur == '-') { - sign = 1; - cur++; - } else if (*cur == '+') - cur++; - ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); - if (ret == 0) - goto return1; - if (*cur != 0) - goto return1; - if (type->flags == XML_SCHEMAS_NPINTEGER) { - if ((sign == 0) && - ((hi != 0) || (mi != 0) || (lo != 0))) - goto return1; - } else if (type->flags == XML_SCHEMAS_PINTEGER) { - if (sign == 1) - goto return1; - if ((hi == 0) && (mi == 0) && (lo == 0)) - goto return1; - } else if (type->flags == XML_SCHEMAS_NINTEGER) { - if (sign == 0) - goto return1; - if ((hi == 0) && (mi == 0) && (lo == 0)) - goto return1; - } else if (type->flags == XML_SCHEMAS_NNINTEGER) { - if ((sign == 1) && - ((hi != 0) || (mi != 0) || (lo != 0))) - goto return1; - } - /* - * We can store a value only if no overflow occured - */ - if ((ret > 0) && (val != NULL)) { - v = xmlSchemaNewValue(type->flags); - if (v != NULL) { - v->value.decimal.lo = lo; - v->value.decimal.mi = lo; - v->value.decimal.hi = lo; - v->value.decimal.sign = sign; - v->value.decimal.frac = 0; - v->value.decimal.total = cur - value; - *val = v; - } - } - goto return0; - } - case XML_SCHEMAS_LONG: - case XML_SCHEMAS_BYTE: - case XML_SCHEMAS_SHORT: - case XML_SCHEMAS_INT: { - const xmlChar *cur = value; - unsigned long lo, mi, hi; - int total = 0; - int sign = 0; - if (cur == NULL) - goto return1; - if (*cur == '-') { - sign = 1; - cur++; - } else if (*cur == '+') - cur++; - ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); - if (ret <= 0) - goto return1; - if (*cur != 0) - goto return1; - if (type->flags == XML_SCHEMAS_LONG) { - if (hi >= 922) { - if (hi > 922) - goto return1; - if (mi >= 33720368) { - if (mi > 33720368) - goto return1; - if ((sign == 0) && (lo > 54775807)) - goto return1; - if ((sign == 1) && (lo > 54775808)) - goto return1; - } - } - } else if (type->flags == XML_SCHEMAS_INT) { - if (hi != 0) - goto return1; - if (mi >= 21) { - if (mi > 21) - goto return1; - if ((sign == 0) && (lo > 47483647)) - goto return1; - if ((sign == 1) && (lo > 47483648)) - goto return1; - } - } else if (type->flags == XML_SCHEMAS_SHORT) { - if ((mi != 0) || (hi != 0)) - goto return1; - if ((sign == 1) && (lo > 32768)) - goto return1; - if ((sign == 0) && (lo > 32767)) - goto return1; - } else if (type->flags == XML_SCHEMAS_BYTE) { - if ((mi != 0) || (hi != 0)) - goto return1; - if ((sign == 1) && (lo > 128)) - goto return1; - if ((sign == 0) && (lo > 127)) - goto return1; - } - if (val != NULL) { - v = xmlSchemaNewValue(type->flags); - if (v != NULL) { - v->value.decimal.lo = lo; - v->value.decimal.mi = lo; - v->value.decimal.hi = lo; - v->value.decimal.sign = sign; - v->value.decimal.frac = 0; - v->value.decimal.total = total; - *val = v; - } - } - goto return0; - } - case XML_SCHEMAS_UINT: - case XML_SCHEMAS_ULONG: - case XML_SCHEMAS_USHORT: - case XML_SCHEMAS_UBYTE: { - const xmlChar *cur = value; - unsigned long lo, mi, hi; - int total = 0; - if (cur == NULL) - goto return1; - ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); - if (ret <= 0) - goto return1; - if (*cur != 0) - goto return1; - if (type->flags == XML_SCHEMAS_ULONG) { - if (hi >= 1844) { - if (hi > 1844) - goto return1; - if (mi >= 67440737) { - if (mi > 67440737) - goto return1; - if (lo > 9551615) - goto return1; - } - } - } else if (type->flags == XML_SCHEMAS_UINT) { - if (hi != 0) - goto return1; - if (mi >= 42) { - if (mi > 42) - goto return1; - if (lo > 94967295) - goto return1; - } - } else if (type->flags == XML_SCHEMAS_USHORT) { - if ((mi != 0) || (hi != 0)) - goto return1; - if (lo > 65535) - goto return1; - } else if (type->flags == XML_SCHEMAS_UBYTE) { - if ((mi != 0) || (hi != 0)) - goto return1; - if (lo > 255) - goto return1; - } - if (val != NULL) { - v = xmlSchemaNewValue(type->flags); - if (v != NULL) { - v->value.decimal.lo = lo; - v->value.decimal.mi = mi; - v->value.decimal.hi = hi; - v->value.decimal.sign = 0; - v->value.decimal.frac = 0; - v->value.decimal.total = total; - *val = v; - } - } - goto return0; - } } done: --- 2171,2176 ---- *************** *** 2230,2296 **** * @x: a first decimal value * @y: a second decimal value * ! * Compare 2 decimals * * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error */ static int xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y) { ! xmlSchemaValPtr swp; ! int order = 1, p; ! unsigned long tmp; ! ! if ((x->value.decimal.sign) && ! ((x->value.decimal.lo != 0) || ! (x->value.decimal.mi != 0) || ! (x->value.decimal.hi != 0))) { ! if ((y->value.decimal.sign) && ! ((y->value.decimal.lo != 0) || ! (y->value.decimal.mi != 0) || ! (y->value.decimal.hi != 0))) ! order = -1; ! else ! return (-1); ! } else if ((y->value.decimal.sign) && ! ((y->value.decimal.lo != 0) || ! (y->value.decimal.mi != 0) || ! (y->value.decimal.hi != 0))) { ! return (1); ! } ! if (x->value.decimal.frac == y->value.decimal.frac) { ! if (x->value.decimal.hi < y->value.decimal.hi) ! return (-order); ! if (x->value.decimal.hi < y->value.decimal.hi) ! return (order); ! if (x->value.decimal.mi < y->value.decimal.mi) ! return (-order); ! if (x->value.decimal.mi < y->value.decimal.mi) ! return (order); ! if (x->value.decimal.lo < y->value.decimal.lo) ! return (-order); ! if (x->value.decimal.lo > y->value.decimal.lo) ! return(order); ! return(0); } ! if (y->value.decimal.frac > x->value.decimal.frac) { ! swp = y; ! y = x; ! x = swp; ! order = -order; ! } ! p = powten[x->value.decimal.frac - y->value.decimal.frac]; ! tmp = x->value.decimal.lo / p; ! if (tmp > y->value.decimal.lo) ! return (order); ! if (tmp < y->value.decimal.lo) ! return (-order); ! tmp = y->value.decimal.lo * p; ! if (x->value.decimal.lo < tmp) ! return (-order); ! if (x->value.decimal.lo == tmp) ! return (0); ! return (order); } /** --- 2232,2272 ---- * @x: a first decimal value * @y: a second decimal value * ! * Compare 2 numbers * * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error */ static int xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y) { ! int ret, sign_adjust = 1; ! ! if ((x->value.decimal.istr == NULL) || (y->value.decimal.istr == NULL)) ! return(-2); ! ! /* compare the integer portions */ ! ret = xmlSchemaCompareIntStr(x->value.decimal.sign, ! x->value.decimal.istr, ! x->value.decimal.isize, ! y->value.decimal.sign, ! y->value.decimal.istr, ! y->value.decimal.isize); ! if (ret == 0) { ! int dif; ! ! sign_adjust = (x->value.decimal.sign ? -1 : 1); ! ! dif = x->value.decimal.fsize - y->value.decimal.fsize; ! if (dif < 0) ! ret = -1; ! else if (dif > 0) ! ret = 1; ! else ! ret = xmlStrncmp(x->value.decimal.fstr, ! y->value.decimal.fstr, ! y->value.decimal.fsize); } ! return(ret * sign_adjust); } /** *************** *** 3189,3194 **** --- 3165,3200 ---- } /** + * xmlSchemaValDecimal2ULong + * @number: pointer to xmlSchemaValDecimal type + * @result: pointer to result of conversion + * + * Convert the integer portion of the decimal string to an unsigned long + * value. This function assumes the integer string in the decimal type + * is unsigned and non-negative. + * + * Returns 0 if successful, -1 if API error, or positive error code + * on conversion error. + */ + int xmlSchemaValDecimal2ULong(xmlSchemaValDecimalPtr decimal, + unsigned long *result) + { + unsigned long base = 0; + + if (decimal == NULL || result == NULL) + return (-1); + if (decimal->sign || (decimal->fsize > 0) || (decimal->istr == NULL)) + return (-1); + + if (sscanf((const char *)decimal->istr, "%lu", &base) != 1) + return (1); + + *result = base; + + return (0); + } + + /** * xmlSchemaValidateFacet: * @base: the base type * @facet: the facet to check *************** *** 3269,3323 **** case XML_SCHEMA_FACET_MAXLENGTH: case XML_SCHEMA_FACET_MINLENGTH: { unsigned int len = 0; if ((facet->val == NULL) || ((facet->val->type != XML_SCHEMAS_DECIMAL) && (facet->val->type != XML_SCHEMAS_NNINTEGER)) || ! (facet->val->value.decimal.frac != 0)) { return(-1); } ! if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY)) ! len = val->value.decimal.total; ! else { ! switch (base->flags) { ! case XML_SCHEMAS_IDREF: ! case XML_SCHEMAS_NORMSTRING: ! case XML_SCHEMAS_TOKEN: ! case XML_SCHEMAS_LANGUAGE: ! case XML_SCHEMAS_NMTOKEN: ! case XML_SCHEMAS_NAME: ! case XML_SCHEMAS_NCNAME: ! case XML_SCHEMAS_ID: ! len = xmlSchemaNormLen(value); ! break; ! case XML_SCHEMAS_STRING: ! len = xmlUTF8Strlen(value); ! break; ! default: ! TODO ! } } if (facet->type == XML_SCHEMA_FACET_LENGTH) { ! if (len != facet->val->value.decimal.lo) return(1); } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { ! if (len < facet->val->value.decimal.lo) return(1); } else { ! if (len > facet->val->value.decimal.lo) return(1); } break; } - case XML_SCHEMA_FACET_TOTALDIGITS: case XML_SCHEMA_FACET_FRACTIONDIGITS: if ((facet->val == NULL) || ((facet->val->type != XML_SCHEMAS_DECIMAL) && (facet->val->type != XML_SCHEMAS_NNINTEGER)) || ! (facet->val->value.decimal.frac != 0)) { return(-1); } if ((val == NULL) || ((val->type != XML_SCHEMAS_DECIMAL) && (val->type != XML_SCHEMAS_INTEGER) && --- 3275,3355 ---- case XML_SCHEMA_FACET_MAXLENGTH: case XML_SCHEMA_FACET_MINLENGTH: { unsigned int len = 0; + unsigned long facet_len = 0; if ((facet->val == NULL) || ((facet->val->type != XML_SCHEMAS_DECIMAL) && (facet->val->type != XML_SCHEMAS_NNINTEGER)) || ! (facet->val->value.decimal.fsize != 0)) { return(-1); } ! ret = xmlSchemaValDecimal2ULong( ! &facet->val->value.decimal, ! &facet_len); ! if (ret != 0) ! return (-1); ! switch (base->flags) { ! case XML_SCHEMAS_IDREF: ! case XML_SCHEMAS_NORMSTRING: ! case XML_SCHEMAS_TOKEN: ! case XML_SCHEMAS_LANGUAGE: ! case XML_SCHEMAS_NMTOKEN: ! case XML_SCHEMAS_NAME: ! case XML_SCHEMAS_NCNAME: ! case XML_SCHEMAS_ID: ! len = xmlSchemaNormLen(value); ! break; ! case XML_SCHEMAS_STRING: ! len = xmlUTF8Strlen(value); ! break; ! case XML_SCHEMAS_HEXBINARY: ! case XML_SCHEMAS_DECIMAL: ! case XML_SCHEMAS_INTEGER: ! case XML_SCHEMAS_PINTEGER: ! case XML_SCHEMAS_NPINTEGER: ! case XML_SCHEMAS_NINTEGER: ! case XML_SCHEMAS_NNINTEGER: ! case XML_SCHEMAS_LONG: ! case XML_SCHEMAS_BYTE: ! case XML_SCHEMAS_SHORT: ! case XML_SCHEMAS_INT: ! case XML_SCHEMAS_ULONG: ! case XML_SCHEMAS_UBYTE: ! case XML_SCHEMAS_USHORT: ! case XML_SCHEMAS_UINT: ! len = val->value.decimal.total; ! break; ! default: ! TODO } if (facet->type == XML_SCHEMA_FACET_LENGTH) { ! if (len != facet_len) return(1); } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { ! if (len < facet_len) return(1); } else { ! if (len > facet_len) return(1); } break; } case XML_SCHEMA_FACET_FRACTIONDIGITS: + if (val->type != XML_SCHEMAS_DECIMAL) + return(1); + case XML_SCHEMA_FACET_TOTALDIGITS: { + unsigned long facet_len = 0; if ((facet->val == NULL) || ((facet->val->type != XML_SCHEMAS_DECIMAL) && (facet->val->type != XML_SCHEMAS_NNINTEGER)) || ! (facet->val->value.decimal.fsize != 0)) { return(-1); } + ret = xmlSchemaValDecimal2ULong(&facet->val->value.decimal, + &facet_len); + if (ret != 0) + return(-1); if ((val == NULL) || ((val->type != XML_SCHEMAS_DECIMAL) && (val->type != XML_SCHEMAS_INTEGER) && *************** *** 3336,3348 **** return(-1); } if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) { ! if (val->value.decimal.total > facet->val->value.decimal.lo) return(1); } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) { ! if (val->value.decimal.frac > facet->val->value.decimal.lo) return(1); } break; default: TODO --- 3368,3383 ---- return(-1); } if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) { ! if (val->value.decimal.total > facet_len) return(1); } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) { ! /* note: the fsize does not count trailing zeros */ ! if ((val->value.decimal.total - ! val->value.decimal.isize) > facet_len) return(1); } + } break; default: TODO