typedef enum {
XML_SCHEMAS_UNKNOWN = 0,
XML_SCHEMAS_STRING,
- XML_SCHEMAS_NMTOKEN,
+ XML_SCHEMAS_NORMSTRING,
XML_SCHEMAS_DECIMAL,
XML_SCHEMAS_TIME,
XML_SCHEMAS_GDAY,
XML_SCHEMAS_FLOAT,
XML_SCHEMAS_DOUBLE,
XML_SCHEMAS_BOOLEAN,
+ XML_SCHEMAS_TOKEN,
+ XML_SCHEMAS_LANGUAGE,
+ XML_SCHEMAS_NMTOKEN,
+ XML_SCHEMAS_NMTOKENS,
+ XML_SCHEMAS_NAME,
+ XML_SCHEMAS_QNAME,
+ XML_SCHEMAS_NCNAME,
+ XML_SCHEMAS_ID,
+ XML_SCHEMAS_IDREF,
+ XML_SCHEMAS_IDREFS,
+ XML_SCHEMAS_ENTITY,
+ XML_SCHEMAS_ENTITIES,
+ XML_SCHEMAS_NOTATION,
+ XML_SCHEMAS_ANYURI,
+ XML_SCHEMAS_INTEGER,
+ XML_SCHEMAS_NPINTEGER,
+ XML_SCHEMAS_NINTEGER,
+ XML_SCHEMAS_NNINTEGER,
+ XML_SCHEMAS_PINTEGER,
XML_SCHEMAS_INT,
- XML_SCHEMAS_,
- XML_SCHEMAS_XXX
+ XML_SCHEMAS_UINT,
+ XML_SCHEMAS_LONG,
+ XML_SCHEMAS_ULONG,
+ XML_SCHEMAS_SHORT,
+ XML_SCHEMAS_USHORT,
+ XML_SCHEMAS_BYTE,
+ XML_SCHEMAS_UBYTE,
+ XML_SCHEMAS_HEXBINARY
} xmlSchemaValType;
-unsigned long powten[10] = {
+static unsigned long powten[10] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000L,
100000000L, 1000000000L
};
unsigned int hour :5; /* 0 <= hour <= 23 */
unsigned int min :6; /* 0 <= min <= 59 */
double sec;
- int tz_flag :1; /* is tzo explicitely set? */
+ unsigned int tz_flag :1; /* is tzo explicitely set? */
int tzo :11; /* -1440 <= tzo <= 1440 */
};
typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
struct _xmlSchemaValDecimal {
/* would use long long but not portable */
- unsigned long base;
+ unsigned long lo;
+ unsigned long mi;
+ unsigned long hi;
unsigned int extra;
unsigned int sign:1;
- int frac:7;
- int total:8;
+ unsigned int frac:7;
+ unsigned int total:8;
+};
+
+typedef struct _xmlSchemaValQName xmlSchemaValQName;
+typedef xmlSchemaValQName *xmlSchemaValQNamePtr;
+struct _xmlSchemaValQName {
+ xmlChar *name;
+ xmlChar *uri;
+};
+
+typedef struct _xmlSchemaValHex xmlSchemaValHex;
+typedef xmlSchemaValHex *xmlSchemaValHexPtr;
+struct _xmlSchemaValHex {
+ xmlChar *str;
+ unsigned int total;
};
struct _xmlSchemaVal {
xmlSchemaValDecimal decimal;
xmlSchemaValDate date;
xmlSchemaValDuration dur;
+ xmlSchemaValQName qname;
+ xmlSchemaValHex hex;
float f;
double d;
int b;
+ xmlChar *str;
} value;
};
static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL;
static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL;
static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL;
-static xmlSchemaTypePtr xmlSchemaTypeNmtoken = NULL;
static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
-static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
-static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
/*
static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL;
static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL;
static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL;
+static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
/*
* xmlSchemaInitBasicType:
* @name: the type name
+ * @type: the value type associated
*
* Initialize one default type
*/
static xmlSchemaTypePtr
-xmlSchemaInitBasicType(const char *name) {
+xmlSchemaInitBasicType(const char *name, xmlSchemaValType type) {
xmlSchemaTypePtr ret;
ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
memset(ret, 0, sizeof(xmlSchemaType));
ret->name = xmlStrdup((const xmlChar *)name);
ret->type = XML_SCHEMA_TYPE_BASIC;
+ ret->flags = type;
ret->contentType = XML_SCHEMA_CONTENT_BASIC;
xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
XML_SCHEMAS_NAMESPACE_NAME, ret);
* Initialize the default XML Schemas type library
*/
void
-xmlSchemaInitTypes(void) {
+xmlSchemaInitTypes(void)
+{
if (xmlSchemaTypesInitialized != 0)
- return;
+ return;
xmlSchemaTypesBank = xmlHashCreate(40);
-
+
/*
* primitive datatypes
*/
- xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string");
- xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType");
- xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType");
- xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal");
- xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date");
- xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime");
- xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time");
- xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear");
- xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth");
- xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth");
- xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay");
- xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay");
- xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration");
- xmlSchemaTypeNmtoken = xmlSchemaInitBasicType("NMTOKEN");
- xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float");
- xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double");
- xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean");
- xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name");
- xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName");
- xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI");
+ xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
+ XML_SCHEMAS_STRING);
+ xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
+ XML_SCHEMAS_UNKNOWN);
+ xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType",
+ XML_SCHEMAS_UNKNOWN);
+ xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
+ XML_SCHEMAS_DECIMAL);
+ xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
+ XML_SCHEMAS_DATE);
+ xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
+ XML_SCHEMAS_DATETIME);
+ xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
+ XML_SCHEMAS_TIME);
+ xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
+ XML_SCHEMAS_GYEAR);
+ xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
+ XML_SCHEMAS_GYEARMONTH);
+ xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
+ XML_SCHEMAS_GMONTH);
+ xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
+ XML_SCHEMAS_GMONTHDAY);
+ xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
+ XML_SCHEMAS_GDAY);
+ xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
+ XML_SCHEMAS_DURATION);
+ xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
+ XML_SCHEMAS_FLOAT);
+ xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
+ XML_SCHEMAS_DOUBLE);
+ xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
+ XML_SCHEMAS_BOOLEAN);
+ xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
+ XML_SCHEMAS_ANYURI);
+ xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
+ XML_SCHEMAS_HEXBINARY);
/*
* derived datatypes
*/
- xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer");;
- xmlSchemaTypeNonPositiveIntegerDef = xmlSchemaInitBasicType("nonPositiveInteger");;
- xmlSchemaTypeNegativeIntegerDef = xmlSchemaInitBasicType("negativeInteger");;
- xmlSchemaTypeLongDef = xmlSchemaInitBasicType("long");;
- xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int");;
- xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short");;
- xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte");;
- xmlSchemaTypeNonNegativeIntegerDef = xmlSchemaInitBasicType("nonNegativeInteger");
- xmlSchemaTypeUnsignedLongDef = xmlSchemaInitBasicType("unsignedLong");;
- xmlSchemaTypeUnsignedIntDef = xmlSchemaInitBasicType("unsignedInt");;
- xmlSchemaTypeUnsignedShortDef = xmlSchemaInitBasicType("insignedShort");;
- xmlSchemaTypeUnsignedByteDef = xmlSchemaInitBasicType("unsignedByte");;
- xmlSchemaTypePositiveIntegerDef = xmlSchemaInitBasicType("positiveInteger");
- xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName");
-
+ xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
+ XML_SCHEMAS_INTEGER);;
+ xmlSchemaTypeNonPositiveIntegerDef =
+ xmlSchemaInitBasicType("nonPositiveInteger",
+ XML_SCHEMAS_NPINTEGER);;
+ xmlSchemaTypeNegativeIntegerDef =
+ xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER);;
+ xmlSchemaTypeLongDef =
+ xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG);;
+ xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT);;
+ xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
+ XML_SCHEMAS_SHORT);;
+ xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
+ XML_SCHEMAS_BYTE);;
+ xmlSchemaTypeNonNegativeIntegerDef =
+ xmlSchemaInitBasicType("nonNegativeInteger",
+ XML_SCHEMAS_NNINTEGER);
+ xmlSchemaTypeUnsignedLongDef =
+ xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG);;
+ xmlSchemaTypeUnsignedIntDef =
+ xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT);;
+ xmlSchemaTypeUnsignedShortDef =
+ xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT);;
+ xmlSchemaTypeUnsignedByteDef =
+ xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE);;
+ xmlSchemaTypePositiveIntegerDef =
+ xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER);
+
+ xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
+ XML_SCHEMAS_NORMSTRING);
+ xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
+ XML_SCHEMAS_TOKEN);
+ xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
+ XML_SCHEMAS_LANGUAGE);
+ xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID);
+ xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
+ XML_SCHEMAS_IDREF);
+ xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
+ XML_SCHEMAS_IDREFS);
+ xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
+ XML_SCHEMAS_ENTITY);
+ xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
+ XML_SCHEMAS_ENTITIES);
+ xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
+ XML_SCHEMAS_NOTATION);
+ xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
+ XML_SCHEMAS_NAME);
+ xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
+ XML_SCHEMAS_QNAME);
+ xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
+ XML_SCHEMAS_NCNAME);
+ xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
+ XML_SCHEMAS_NMTOKEN);
+ xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
+ XML_SCHEMAS_NMTOKENS);
xmlSchemaTypesInitialized = 1;
}
xmlSchemaFreeValue(xmlSchemaValPtr value) {
if (value == NULL)
return;
+ switch (value->type) {
+ case XML_SCHEMAS_STRING:
+ case XML_SCHEMAS_NORMSTRING:
+ case XML_SCHEMAS_TOKEN:
+ case XML_SCHEMAS_LANGUAGE:
+ case XML_SCHEMAS_NMTOKEN:
+ case XML_SCHEMAS_NMTOKENS:
+ case XML_SCHEMAS_NAME:
+ case XML_SCHEMAS_NCNAME:
+ case XML_SCHEMAS_ID:
+ case XML_SCHEMAS_IDREF:
+ case XML_SCHEMAS_IDREFS:
+ case XML_SCHEMAS_ENTITY:
+ case XML_SCHEMAS_ENTITIES:
+ case XML_SCHEMAS_NOTATION:
+ case XML_SCHEMAS_ANYURI:
+ if (value->value.str != NULL)
+ xmlFree(value->value.str);
+ break;
+ case XML_SCHEMAS_QNAME:
+ if (value->value.qname.uri != NULL)
+ xmlFree(value->value.qname.uri);
+ if (value->value.qname.name != NULL)
+ xmlFree(value->value.qname.name);
+ break;
+ case XML_SCHEMAS_HEXBINARY:
+ if (value->value.hex.str != NULL)
+ xmlFree(value->value.hex.str);
+ break;
+ default:
+ break;
+ }
xmlFree(value);
}
/**
* xmlSchemaValidateDates:
- * @type: the predefined type
+ * @type: the expected type or XML_SCHEMAS_UNKNOWN
* @dateTime: string to analyze
* @val: the return computed value
*
* and -1 in case of internal or API error.
*/
static int
-xmlSchemaValidateDates (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
+xmlSchemaValidateDates (xmlSchemaValType type,
const xmlChar *dateTime, xmlSchemaValPtr *val) {
xmlSchemaValPtr dt;
int ret;
if (*cur != 0) \
goto error; \
dt->type = t; \
- if (val != NULL) \
- *val = dt; \
- return 0; \
+ goto done; \
} \
}
/* is it an xs:gDay? */
if (*cur == '-') {
+ if (type == XML_SCHEMAS_GMONTH)
+ goto error;
++cur;
ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
if (ret != 0)
if (ret != 0)
goto error;
- if (*cur != '-')
- goto error;
- cur++;
+ /*
+ * a '-' char could indicate this type is xs:gMonthDay or
+ * a negative time zone offset. Check for xs:gMonthDay first.
+ * Also the first three char's of a negative tzo (-MM:SS) can
+ * appear to be a valid day; so even if the day portion
+ * of the xs:gMonthDay verifies, we must insure it was not
+ * a tzo.
+ */
+ if (*cur == '-') {
+ const xmlChar *rewnd = cur;
+ cur++;
+
+ ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
+ if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) {
+
+ /*
+ * we can use the VALID_MDAY macro to validate the month
+ * and day because the leap year test will flag year zero
+ * as a leap year (even though zero is an invalid year).
+ */
+ if (VALID_MDAY((&(dt->value.date)))) {
+
+ RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
- /* is it an xs:gMonth? */
- if (*cur == '-') {
- cur++;
- RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
- goto error;
- }
+ goto error;
+ }
+ }
- /* it should be an xs:gMonthDay */
- ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
- if (ret != 0)
- goto error;
+ /*
+ * not xs:gMonthDay so rewind and check if just xs:gMonth
+ * with an optional time zone.
+ */
+ cur = rewnd;
+ }
- RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
+ RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
goto error;
}
if ((ret != 0) || (*cur != 0) || !VALID_DATETIME((&(dt->value.date))))
goto error;
+
dt->type = XML_SCHEMAS_DATETIME;
+done:
+#if 1
+ if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
+ goto error;
+#else
+ /*
+ * insure the parsed type is equal to or less significant (right
+ * truncated) than the desired type.
+ */
+ if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) {
+
+ /* time only matches time */
+ if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME))
+ goto error;
+
+ if ((type == XML_SCHEMAS_DATETIME) &&
+ ((dt->type != XML_SCHEMAS_DATE) ||
+ (dt->type != XML_SCHEMAS_GYEARMONTH) ||
+ (dt->type != XML_SCHEMAS_GYEAR)))
+ goto error;
+
+ if ((type == XML_SCHEMAS_DATE) &&
+ ((dt->type != XML_SCHEMAS_GYEAR) ||
+ (dt->type != XML_SCHEMAS_GYEARMONTH)))
+ goto error;
+
+ if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
+ goto error;
+
+ if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
+ goto error;
+ }
+#endif
+
if (val != NULL)
*val = dt;
+ else
+ xmlSchemaFreeValue(dt);
return 0;
xmlSchemaValPtr dur;
int isneg = 0;
unsigned int seq = 0;
+ double num;
+ int num_type = 0; /* -1 = invalid, 0 = int, 1 = floating */
+ const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
+ const double multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
if (duration == NULL)
return -1;
if (*cur++ != 'P')
return 1;
+ if (*cur == 0)
+ return 1;
+
dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
if (dur == NULL)
return -1;
while (*cur != 0) {
- double num;
- int num_type = 0; /* -1 = invalid, 0 = int, 1 = floating */
- const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
- const double multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
/* input string should be empty or invalid date/time item */
if (seq >= sizeof(desig))
if (val != NULL)
*val = dur;
+ else
+ xmlSchemaFreeValue(dur);
return 0;
return 1;
}
+/**
+ * xmlSchemaStrip:
+ * @value: a value
+ *
+ * Removes the leading and ending spaces of a string
+ *
+ * Returns the new string or NULL if no change was required.
+ */
+static xmlChar *
+xmlSchemaStrip(const xmlChar *value) {
+ const xmlChar *start = value, *end, *f;
+
+ if (value == NULL) return(NULL);
+ while ((*start != 0) && (IS_BLANK(*start))) start++;
+ end = start;
+ while (*end != 0) end++;
+ f = end;
+ end--;
+ while ((end > start) && (IS_BLANK(*end))) end--;
+ end++;
+ if ((start == value) && (f == end)) return(NULL);
+ return(xmlStrndup(start, end - start));
+}
/**
- * xmlSchemaValidatePredefinedType:
+ * xmlSchemaCollapseString:
+ * @value: a value
+ *
+ * Removes and normalize white spaces in the string
+ *
+ * Returns the new string or NULL if no change was required.
+ */
+static xmlChar *
+xmlSchemaCollapseString(const xmlChar *value) {
+ const xmlChar *start = value, *end, *f;
+ xmlChar *g;
+ int col = 0;
+
+ if (value == NULL) return(NULL);
+ while ((*start != 0) && (IS_BLANK(*start))) start++;
+ end = start;
+ while (*end != 0) {
+ if ((*end == ' ') && (IS_BLANK(end[1]))) {
+ col = end - start;
+ break;
+ } else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) {
+ col = end - start;
+ break;
+ }
+ end++;
+ }
+ if (col == 0) {
+ f = end;
+ end--;
+ while ((end > start) && (IS_BLANK(*end))) end--;
+ end++;
+ if ((start == value) && (f == end)) return(NULL);
+ return(xmlStrndup(start, end - start));
+ }
+ start = xmlStrdup(start);
+ if (start == NULL) return(NULL);
+ g = (xmlChar *) (start + col);
+ end = g;
+ while (*end != 0) {
+ if (IS_BLANK(*end)) {
+ end++;
+ while (IS_BLANK(*end)) end++;
+ if (*end != 0)
+ *g++ = ' ';
+ } else
+ *g++ = *end++;
+ }
+ *g = 0;
+ return((xmlChar *) start);
+}
+
+/**
+ * xmlSchemaValAtomicListNode:
+ * @type: the predefined atomic type for a token in the list
+ * @value: the list value to check
+ * @ret: the return computed value
+ * @node: the node containing the value
+ *
+ * Check that a value conforms to the lexical space of the predefined
+ * list type. if true a value is computed and returned in @ret.
+ *
+ * Returns the number of items if this validates, a negative error code
+ * number otherwise
+ */
+static int
+xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
+ xmlSchemaValPtr *ret, xmlNodePtr node) {
+ xmlChar *val, *cur, *endval;
+ int nb_values = 0;
+ int tmp = 0;
+
+ if (value == NULL) {
+ return(-1);
+ }
+ val = xmlStrdup(value);
+ if (val == NULL) {
+ return(-1);
+ }
+ cur = val;
+ /*
+ * Split the list
+ */
+ while (IS_BLANK(*cur)) *cur++ = 0;
+ while (*cur != 0) {
+ if (IS_BLANK(*cur)) {
+ *cur = 0;
+ cur++;
+ while (IS_BLANK(*cur)) *cur++ = 0;
+ } else {
+ nb_values++;
+ cur++;
+ while ((*cur != 0) && (!IS_BLANK(*cur))) cur++;
+ }
+ }
+ if (nb_values == 0) {
+ if (ret != NULL) {
+ TODO
+ }
+ xmlFree(val);
+ return(nb_values);
+ }
+ endval = cur;
+ cur = val;
+ while ((*cur == 0) && (cur != endval)) cur++;
+ while (cur != endval) {
+ tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node);
+ if (tmp != 0)
+ break;
+ while (*cur != 0) cur++;
+ while ((*cur == 0) && (cur != endval)) cur++;
+ }
+ xmlFree(val);
+ if (ret != NULL) {
+ TODO
+ }
+ if (tmp == 0)
+ return(nb_values);
+ 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
* @val: the return computed value
+ * @node: the node containing the value
+ * flags: flags to control the vlidation
*
- * Check that a value conforms to the lexical space of the predefined type.
+ * Check that a value conforms to the lexical space of the atomic type.
* if true a value is computed and returned in @val.
*
* Returns 0 if this validates, a positive error code number otherwise
* and -1 in case of internal or API error.
*/
-int
-xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
- xmlSchemaValPtr *val) {
+static int
+xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
+ xmlSchemaValPtr *val, xmlNodePtr node, int flags) {
xmlSchemaValPtr v;
- int ret;
+ xmlChar *norm = NULL;
+ int ret = 0;
if (xmlSchemaTypesInitialized == 0)
return(-1);
if (val != NULL)
*val = NULL;
- if (type == xmlSchemaTypeStringDef) {
- return(0);
- } else if (type == xmlSchemaTypeAnyTypeDef) {
- return(0);
- } else if (type == xmlSchemaTypeAnySimpleTypeDef) {
- return(0);
- } else if (type == xmlSchemaTypeNmtoken) {
- if (xmlValidateNmtokenValue(value))
- return(0);
- return(1);
- } else if (type == xmlSchemaTypeDecimalDef) {
- const xmlChar *cur = value, *tmp;
- int frac = 0, len, neg = 0;
- unsigned long base = 0;
- if (cur == NULL)
- return(1);
- if (*cur == '+')
- cur++;
- else if (*cur == '-') {
- neg = 1;
- cur++;
+ if ((flags == 0) && (value != NULL)) {
+ if ((type->flags != XML_SCHEMAS_STRING) &&
+ (type->flags != XML_SCHEMAS_NORMSTRING)) {
+ norm = xmlSchemaCollapseString(value);
+ if (norm != NULL)
+ value = norm;
}
- tmp = cur;
- while ((*cur >= '0') && (*cur <= '9')) {
- base = base * 10 + (*cur - '0');
- cur++;
- }
- len = cur - tmp;
- if (*cur == '.') {
- cur++;
+ }
+
+ switch (type->flags) {
+ case XML_SCHEMAS_UNKNOWN:
+ if (type == xmlSchemaTypeAnyTypeDef)
+ goto return0;
+ goto error;
+ case XML_SCHEMAS_STRING:
+ goto return0;
+ case XML_SCHEMAS_NORMSTRING:
+ TODO
+ goto return0;
+ case XML_SCHEMAS_DECIMAL: {
+ const xmlChar *cur = value, *tmp;
+ unsigned 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++;
}
- frac = cur - tmp;
- }
- if (*cur != 0)
- return(1);
- if (val != NULL) {
- v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
- if (v != NULL) {
- v->value.decimal.base = base;
- v->value.decimal.sign = neg;
- v->value.decimal.frac = frac;
- v->value.decimal.total = frac + len;
- *val = v;
+ len = cur - tmp;
+ if (*cur == '.') {
+ cur++;
+ tmp = cur;
+ while ((*cur >= '0') && (*cur <= '9')) {
+ base = base * 10 + (*cur - '0');
+ cur++;
+ }
+ frac = cur - tmp;
}
- }
- return(0);
- } else if (type == xmlSchemaTypeDurationDef) {
- return xmlSchemaValidateDuration(type, value, val);
- } else if ((type == xmlSchemaTypeDatetimeDef) ||
- (type == xmlSchemaTypeTimeDef) ||
- (type == xmlSchemaTypeDateDef) ||
- (type == xmlSchemaTypeGYearDef) ||
- (type == xmlSchemaTypeGYearMonthDef) ||
- (type == xmlSchemaTypeGMonthDef) ||
- (type == xmlSchemaTypeGMonthDayDef) ||
- (type == xmlSchemaTypeGDayDef)) {
- return xmlSchemaValidateDates(type, value, val);
- } else if (type == xmlSchemaTypePositiveIntegerDef) {
- const xmlChar *cur = value;
- unsigned long base = 0;
- int total = 0;
- if (cur == NULL)
- return(1);
- if (*cur == '+')
- cur++;
- while ((*cur >= '0') && (*cur <= '9')) {
- base = base * 10 + (*cur - '0');
- total++;
- cur++;
- }
- if (*cur != 0)
- return(1);
- if (val != NULL) {
- v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
- if (v != NULL) {
- v->value.decimal.base = base;
- v->value.decimal.sign = 0;
- v->value.decimal.frac = 0;
- v->value.decimal.total = total;
- *val = v;
+ 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;
}
- return(0);
- } else if (type == xmlSchemaTypeNonNegativeIntegerDef) {
- const xmlChar *cur = value;
- unsigned long base = 0;
- int total = 0;
- int sign = 0;
- if (cur == NULL)
- return(1);
- if (*cur == '-') {
- sign = 1;
- cur++;
- } else if (*cur == '+')
- cur++;
- while ((*cur >= '0') && (*cur <= '9')) {
- base = base * 10 + (*cur - '0');
- total++;
- cur++;
- }
- if (*cur != 0)
- return(1);
- if ((sign == 1) && (base != 0))
- return(1);
- if (val != NULL) {
- v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
- if (v != NULL) {
- v->value.decimal.base = base;
- v->value.decimal.sign = 0;
- v->value.decimal.frac = 0;
- v->value.decimal.total = total;
- *val = v;
+ case XML_SCHEMAS_TIME:
+ case XML_SCHEMAS_GDAY:
+ case XML_SCHEMAS_GMONTH:
+ case XML_SCHEMAS_GMONTHDAY:
+ case XML_SCHEMAS_GYEAR:
+ case XML_SCHEMAS_GYEARMONTH:
+ case XML_SCHEMAS_DATE:
+ case XML_SCHEMAS_DATETIME:
+ ret = xmlSchemaValidateDates(type->flags, value, val);
+ break;
+ case XML_SCHEMAS_DURATION:
+ ret = xmlSchemaValidateDuration(type, value, val);
+ break;
+ case XML_SCHEMAS_FLOAT:
+ case XML_SCHEMAS_DOUBLE: {
+ const xmlChar *cur = value;
+ int neg = 0;
+ if (cur == NULL)
+ goto return1;
+ if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
+ cur += 3;
+ if (*cur != 0)
+ goto return1;
+ if (val != NULL) {
+ if (type == xmlSchemaTypeFloatDef) {
+ v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
+ if (v != NULL) {
+ v->value.f = (float) xmlXPathNAN;
+ } else {
+ xmlSchemaFreeValue(v);
+ goto error;
+ }
+ } else {
+ v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
+ if (v != NULL) {
+ v->value.d = xmlXPathNAN;
+ } else {
+ xmlSchemaFreeValue(v);
+ goto error;
+ }
+ }
+ *val = v;
+ }
+ goto return0;
}
- }
- return(0);
- } else if (type == xmlSchemaTypeIntDef) {
- const xmlChar *cur = value;
- unsigned long base = 0;
- int total = 0;
- int sign = 0;
- if (cur == NULL)
- return(1);
- if (*cur == '-') {
- sign = 1;
- cur++;
- } else if (*cur == '+')
- cur++;
- while (*cur == '0') {
- total++;
- cur++;
- }
- while ((*cur >= '0') && (*cur <= '9')) {
- base = base * 10 + (*cur - '0');
- total++;
- cur++;
- }
- if (*cur != 0)
- return(1);
- if ((sign == 1) && (total == 0))
- return(1);
- if (val != NULL) {
- v = xmlSchemaNewValue(XML_SCHEMAS_INT);
- if (v != NULL) {
- v->value.decimal.base = base;
- v->value.decimal.sign = sign;
- v->value.decimal.frac = 0;
- v->value.decimal.total = total;
- *val = v;
+ if (*cur == '-') {
+ neg = 1;
+ cur++;
+ }
+ if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
+ cur += 3;
+ if (*cur != 0)
+ goto return1;
+ if (val != NULL) {
+ if (type == xmlSchemaTypeFloatDef) {
+ v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
+ if (v != NULL) {
+ if (neg)
+ v->value.f = (float) xmlXPathNINF;
+ else
+ v->value.f = (float) xmlXPathPINF;
+ } else {
+ xmlSchemaFreeValue(v);
+ goto error;
+ }
+ } else {
+ v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
+ if (v != NULL) {
+ if (neg)
+ v->value.d = xmlXPathNINF;
+ else
+ v->value.d = xmlXPathPINF;
+ } else {
+ xmlSchemaFreeValue(v);
+ goto error;
+ }
+ }
+ *val = v;
+ }
+ goto return0;
+ }
+ if ((neg == 0) && (*cur == '+'))
+ cur++;
+ if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
+ goto return1;
+ while ((*cur >= '0') && (*cur <= '9')) {
+ cur++;
+ }
+ if (*cur == '.') {
+ cur++;
+ while ((*cur >= '0') && (*cur <= '9'))
+ cur++;
+ }
+ if ((*cur == 'e') || (*cur == 'E')) {
+ cur++;
+ if ((*cur == '-') || (*cur == '+'))
+ cur++;
+ while ((*cur >= '0') && (*cur <= '9'))
+ cur++;
}
- }
- return(0);
- } else if ((type == xmlSchemaTypeFloatDef) ||
- (type == xmlSchemaTypeDoubleDef)) {
- const xmlChar *cur = value;
- int neg = 0;
- if (cur == NULL)
- return(1);
- if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
- cur += 3;
if (*cur != 0)
- return(1);
+ goto return1;
if (val != NULL) {
if (type == xmlSchemaTypeFloatDef) {
v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
if (v != NULL) {
- v->value.f = (float) xmlXPathNAN;
+ if (sscanf((const char *)value, "%f", &(v->value.f))==1) {
+ *val = v;
+ } else {
+ xmlGenericError(xmlGenericErrorContext,
+ "failed to scanf float %s\n", value);
+ xmlSchemaFreeValue(v);
+ goto return1;
+ }
} else {
- xmlSchemaFreeValue(v);
- return(-1);
+ goto error;
}
} else {
v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
if (v != NULL) {
- v->value.d = xmlXPathNAN;
+ if (sscanf((const char *)value, "%lf", &(v->value.d))==1) {
+ *val = v;
+ } else {
+ xmlGenericError(xmlGenericErrorContext,
+ "failed to scanf double %s\n", value);
+ xmlSchemaFreeValue(v);
+ goto return1;
+ }
} else {
- xmlSchemaFreeValue(v);
- return(-1);
+ goto error;
}
}
- *val = v;
}
- return(0);
+ goto return0;
}
- if (*cur == '+')
- cur++;
- else if (*cur == '-') {
- neg = 1;
- cur++;
+ case XML_SCHEMAS_BOOLEAN: {
+ const xmlChar *cur = value;
+
+ if ((cur[0] == '0') && (cur[1] == 0))
+ ret = 0;
+ else if ((cur[0] == '1') && (cur[1] == 0))
+ ret = 1;
+ else if ((cur[0] == 't') && (cur[1] == 'r') && (cur[2] == 'u') &&
+ (cur[3] == 'e') && (cur[4] == 0))
+ ret = 1;
+ else if ((cur[0] == 'f') && (cur[1] == 'a') && (cur[2] == 'l') &&
+ (cur[3] == 's') && (cur[4] == 'e') && (cur[5] == 0))
+ ret = 0;
+ else
+ goto return1;
+ if (val != NULL) {
+ v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
+ if (v != NULL) {
+ v->value.b = ret;
+ *val = v;
+ } else {
+ goto error;
+ }
+ }
+ goto return0;
}
- if (cur[0] == 0)
- return(1);
- if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
- cur += 3;
- if (*cur != 0)
- return(1);
+ case XML_SCHEMAS_TOKEN: {
+ const xmlChar *cur = value;
+
+ if (IS_BLANK(*cur))
+ goto return1;
+
+ while (*cur != 0) {
+ if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
+ goto return1;
+ } else if (*cur == ' ') {
+ cur++;
+ if (*cur == 0)
+ goto return1;
+ if (*cur == ' ')
+ goto return1;
+ } else {
+ cur++;
+ }
+ }
if (val != NULL) {
- if (type == xmlSchemaTypeFloatDef) {
- v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
+ v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
+ if (v != NULL) {
+ v->value.str = xmlStrdup(value);
+ *val = v;
+ } else {
+ goto error;
+ }
+ }
+ goto return0;
+ }
+ case XML_SCHEMAS_LANGUAGE:
+ if (xmlCheckLanguageID(value) == 1) {
+ if (val != NULL) {
+ v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
if (v != NULL) {
- if (neg)
- v->value.f = (float) xmlXPathNINF;
- else
- v->value.f = (float) xmlXPathPINF;
+ v->value.str = xmlStrdup(value);
+ *val = v;
} else {
- xmlSchemaFreeValue(v);
- return(-1);
+ goto error;
}
- } else {
- v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
+ }
+ goto return0;
+ }
+ goto return1;
+ case XML_SCHEMAS_NMTOKEN:
+ if (xmlValidateNMToken(value, 1) == 0) {
+ if (val != NULL) {
+ v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
if (v != NULL) {
- if (neg)
- v->value.d = xmlXPathNINF;
- else
- v->value.d = xmlXPathPINF;
+ v->value.str = xmlStrdup(value);
+ *val = v;
} else {
- xmlSchemaFreeValue(v);
- return(-1);
+ goto error;
}
}
- *val = v;
+ goto return0;
}
- return(0);
- }
- while ((*cur >= '0') && (*cur <= '9')) {
- cur++;
- }
- if (*cur == '.') {
- cur++;
- while ((*cur >= '0') && (*cur <= '9'))
- cur++;
- }
- if ((*cur == 'e') || (*cur == 'E')) {
- cur++;
- if (*cur == '-')
- cur++;
- while ((*cur >= '0') && (*cur <= '9'))
- cur++;
+ goto return1;
+ case XML_SCHEMAS_NMTOKENS:
+ ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
+ value, val, node);
+ if (ret > 0)
+ ret = 0;
+ else
+ ret = 1;
+ goto done;
+ case XML_SCHEMAS_NAME:
+ ret = xmlValidateName(value, 1);
+ if ((ret == 0) && (val != NULL)) {
+ TODO;
+ }
+ goto done;
+ case XML_SCHEMAS_QNAME: {
+ xmlChar *uri = NULL;
+ xmlChar *local = NULL;
+
+ ret = xmlValidateQName(value, 1);
+ if ((ret == 0) && (node != NULL)) {
+ xmlChar *prefix;
+ local = xmlSplitQName2(value, &prefix);
+ if (prefix != NULL) {
+ xmlNsPtr ns;
+
+ ns = xmlSearchNs(node->doc, node, prefix);
+ if (ns == NULL)
+ ret = 1;
+ else if (val != NULL)
+ uri = xmlStrdup(ns->href);
+ }
+ if ((local != NULL) && ((val == NULL) || (ret != 0)))
+ xmlFree(local);
+ if (prefix != NULL)
+ xmlFree(prefix);
+ }
+ if ((ret == 0) && (val != NULL)) {
+ v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
+ if (v != NULL) {
+ if (local != NULL)
+ v->value.qname.name = local;
+ else
+ v->value.qname.name = xmlStrdup(value);
+ if (uri != NULL)
+ v->value.qname.uri = uri;
+
+ *val = v;
+ } else {
+ if (local != NULL)
+ xmlFree(local);
+ if (uri != NULL)
+ xmlFree(uri);
+ goto error;
+ }
+ }
+ goto done;
}
- if (*cur != 0)
- return(1);
- if (val != NULL) {
- if (type == xmlSchemaTypeFloatDef) {
- v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
+ case XML_SCHEMAS_NCNAME:
+ ret = xmlValidateNCName(value, 1);
+ if ((ret == 0) && (val != NULL)) {
+ v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
if (v != NULL) {
- if (sscanf((const char *)value, "%f", &(v->value.f))==1) {
- *val = v;
- } else {
- xmlGenericError(xmlGenericErrorContext,
- "failed to scanf float %s\n", value);
- xmlSchemaFreeValue(v);
- return(1);
- }
+ v->value.str = xmlStrdup(value);
+ *val = v;
} else {
- return(-1);
+ goto error;
}
- } else {
- v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
+ }
+ goto done;
+ case XML_SCHEMAS_ID:
+ ret = xmlValidateNCName(value, 1);
+ if ((ret == 0) && (val != NULL)) {
+ v = xmlSchemaNewValue(XML_SCHEMAS_ID);
if (v != NULL) {
- if (sscanf((const char *)value, "%lf", &(v->value.d))==1) {
- *val = v;
+ v->value.str = xmlStrdup(value);
+ *val = v;
+ } else {
+ goto error;
+ }
+ }
+ if ((ret == 0) && (node != NULL) &&
+ (node->type == XML_ATTRIBUTE_NODE)) {
+ xmlAttrPtr attr = (xmlAttrPtr) node;
+ /*
+ * NOTE: the IDness might have already be declared in the DTD
+ */
+ if (attr->atype != XML_ATTRIBUTE_ID) {
+ xmlIDPtr res;
+ xmlChar *strip;
+
+ strip = xmlSchemaStrip(value);
+ if (strip != NULL) {
+ res = xmlAddID(NULL, node->doc, strip, attr);
+ xmlFree(strip);
+ } else
+ res = xmlAddID(NULL, node->doc, value, attr);
+ if (res == NULL) {
+ ret = 2;
} else {
- xmlGenericError(xmlGenericErrorContext,
- "failed to scanf double %s\n", value);
- xmlSchemaFreeValue(v);
- return(1);
+ attr->atype = XML_ATTRIBUTE_ID;
}
+ }
+ }
+ goto done;
+ case XML_SCHEMAS_IDREF:
+ ret = xmlValidateNCName(value, 1);
+ if ((ret == 0) && (val != NULL)) {
+ TODO;
+ }
+ if ((ret == 0) && (node != NULL) &&
+ (node->type == XML_ATTRIBUTE_NODE)) {
+ xmlAttrPtr attr = (xmlAttrPtr) node;
+ xmlChar *strip;
+
+ strip = xmlSchemaStrip(value);
+ if (strip != NULL) {
+ xmlAddRef(NULL, node->doc, strip, attr);
+ xmlFree(strip);
+ } else
+ xmlAddRef(NULL, node->doc, value, attr);
+ attr->atype = XML_ATTRIBUTE_IDREF;
+ }
+ goto done;
+ case XML_SCHEMAS_IDREFS:
+ ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
+ value, val, node);
+ if (ret < 0)
+ ret = 2;
+ else
+ ret = 0;
+ if ((ret == 0) && (node != NULL) &&
+ (node->type == XML_ATTRIBUTE_NODE)) {
+ xmlAttrPtr attr = (xmlAttrPtr) node;
+
+ attr->atype = XML_ATTRIBUTE_IDREFS;
+ }
+ goto done;
+ case XML_SCHEMAS_ENTITY: {
+ xmlChar *strip;
+ ret = xmlValidateNCName(value, 1);
+ if ((node == NULL) || (node->doc == NULL))
+ ret = 3;
+ if (ret == 0) {
+ xmlEntityPtr ent;
+
+ strip = xmlSchemaStrip(value);
+ if (strip != NULL) {
+ ent = xmlGetDocEntity(node->doc, strip);
+ xmlFree(strip);
} else {
- return(-1);
+ ent = xmlGetDocEntity(node->doc, value);
}
+ if ((ent == NULL) ||
+ (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
+ ret = 4;
}
+ if ((ret == 0) && (val != NULL)) {
+ TODO;
+ }
+ if ((ret == 0) && (node != NULL) &&
+ (node->type == XML_ATTRIBUTE_NODE)) {
+ xmlAttrPtr attr = (xmlAttrPtr) node;
+
+ attr->atype = XML_ATTRIBUTE_ENTITY;
+ }
+ goto done;
}
- return(0);
- } else if (type == xmlSchemaTypeNameDef) {
- ret = xmlValidateName(value, 1);
- if ((ret == 0) && (val != NULL)) {
- TODO;
- }
- return(ret);
- } else if (type == xmlSchemaTypeQNameDef) {
- ret = xmlValidateQName(value, 1);
- if ((ret == 0) && (val != NULL)) {
- TODO;
- }
- return(ret);
- } else if (type == xmlSchemaTypeNCNameDef) {
- ret = xmlValidateNCName(value, 1);
- if ((ret == 0) && (val != NULL)) {
- TODO;
+ case XML_SCHEMAS_ENTITIES:
+ if ((node == NULL) || (node->doc == NULL))
+ goto return3;
+ ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
+ value, val, node);
+ if (ret <= 0)
+ ret = 1;
+ else
+ ret = 0;
+ if ((ret == 0) && (node != NULL) &&
+ (node->type == XML_ATTRIBUTE_NODE)) {
+ xmlAttrPtr attr = (xmlAttrPtr) node;
+
+ attr->atype = XML_ATTRIBUTE_ENTITIES;
+ }
+ goto done;
+ case XML_SCHEMAS_NOTATION: {
+ xmlChar *uri = NULL;
+ xmlChar *local = NULL;
+
+ ret = xmlValidateQName(value, 1);
+ if ((ret == 0) && (node != NULL)) {
+ xmlChar *prefix;
+ local = xmlSplitQName2(value, &prefix);
+ if (prefix != NULL) {
+ xmlNsPtr ns;
+
+ ns = xmlSearchNs(node->doc, node, prefix);
+ if (ns == NULL)
+ ret = 1;
+ else if (val != NULL)
+ uri = xmlStrdup(ns->href);
+ }
+ if ((local != NULL) && ((val == NULL) || (ret != 0)))
+ xmlFree(local);
+ if (prefix != NULL)
+ xmlFree(prefix);
+ }
+ if ((node == NULL) || (node->doc == NULL))
+ ret = 3;
+ if (ret == 0) {
+ ret = xmlValidateNotationUse(NULL, node->doc, value);
+ if (ret == 1)
+ ret = 0;
+ else
+ ret = 1;
+ }
+ if ((ret == 0) && (val != NULL)) {
+ v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
+ if (v != NULL) {
+ if (local != NULL)
+ v->value.qname.name = local;
+ else
+ v->value.qname.name = xmlStrdup(value);
+ if (uri != NULL)
+ v->value.qname.uri = uri;
+
+ *val = v;
+ } else {
+ if (local != NULL)
+ xmlFree(local);
+ if (uri != NULL)
+ xmlFree(uri);
+ goto error;
+ }
+ }
+ goto done;
}
- return(ret);
- } else if (type == xmlSchemaTypeAnyURIDef) {
- xmlURIPtr uri;
+ case XML_SCHEMAS_ANYURI: {
+ xmlURIPtr uri;
- uri = xmlParseURI((const char *) value);
- if (uri == NULL)
- return(1);
- if (val != NULL) {
- TODO;
+ uri = xmlParseURI((const char *) value);
+ if (uri == NULL)
+ goto return1;
+ if (val != NULL) {
+ TODO;
+ }
+ xmlFreeURI(uri);
+ goto return0;
}
- xmlFreeURI(uri);
- return(0);
- } else if (type == xmlSchemaTypeBooleanDef) {
- const xmlChar *cur = value;
-
- if ((cur[0] == '0') && (cur[1] == 0))
- ret = 0;
- else if ((cur[0] == '1') && (cur[1] == 0))
- ret = 1;
- else if ((cur[0] == 't') && (cur[1] == 'r') && (cur[2] == 'u') &&
- (cur[3] == 'e') && (cur[4] == 0))
- ret = 1;
- else if ((cur[0] == 'f') && (cur[1] == 'a') && (cur[2] == 'l') &&
- (cur[3] == 's') && (cur[4] == 'e') && (cur[5] == 0))
- ret = 0;
- else
- return(1);
- if (val != NULL) {
- v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
- if (v != NULL) {
- v->value.b = ret;
+ case XML_SCHEMAS_HEXBINARY: {
+ const xmlChar *cur = value;
+ xmlChar *base;
+ int total, i = 0;
+
+ if (cur == NULL)
+ goto return1;
+
+ while (((*cur >= '0') && (*cur <= '9')) ||
+ ((*cur >= 'A') && (*cur <= 'F')) ||
+ ((*cur >= 'a') && (*cur <= 'f'))) {
+ i++;cur++;
+ }
+
+ if (*cur != 0)
+ goto return1;
+ if ((i % 2) != 0)
+ goto return1;
+
+ if (val != NULL) {
+
+ v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
+ if (v == NULL)
+ goto error;
+
+ cur = xmlStrdup(value);
+ if (cur == NULL) {
+ xmlFree(v);
+ goto return1;
+ }
+
+ total = i / 2; /* number of octets */
+
+ base = (xmlChar *)cur;
+ while (i-- > 0) {
+ if (*base >= 'a')
+ *base = *base - ('a' - 'A');
+ base++;
+ }
+
+ v->value.hex.str = (xmlChar *)cur;
+ v->value.hex.total = total;
*val = v;
- } else {
- return(-1);
+ }
+ 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;
}
- return(0);
- } else {
- TODO
- return(0);
}
+
+done:
+ if (norm != NULL) xmlFree(norm);
+ return(ret);
+return3:
+ if (norm != NULL) xmlFree(norm);
+ return(3);
+return1:
+ if (norm != NULL) xmlFree(norm);
+ return(1);
+return0:
+ if (norm != NULL) xmlFree(norm);
+ return(0);
+error:
+ if (norm != NULL) xmlFree(norm);
return(-1);
}
/**
+ * xmlSchemaValPredefTypeNode:
+ * @type: the predefined type
+ * @value: the value to check
+ * @val: the return computed value
+ * @node: the node containing the value
+ *
+ * Check that a value conforms to the lexical space of the predefined type.
+ * if true a value is computed and returned in @val.
+ *
+ * Returns 0 if this validates, a positive error code number otherwise
+ * and -1 in case of internal or API error.
+ */
+int
+xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
+ xmlSchemaValPtr *val, xmlNodePtr node) {
+ return(xmlSchemaValAtomicType(type, value, val, node, 0));
+}
+
+/**
+ * xmlSchemaValidatePredefinedType:
+ * @type: the predefined type
+ * @value: the value to check
+ * @val: the return computed value
+ *
+ * Check that a value conforms to the lexical space of the predefined type.
+ * if true a value is computed and returned in @val.
+ *
+ * Returns 0 if this validates, a positive error code number otherwise
+ * and -1 in case of internal or API error.
+ */
+int
+xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
+ xmlSchemaValPtr *val) {
+ return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
+}
+
+/**
* xmlSchemaCompareDecimals:
* @x: a first decimal value
* @y: a second decimal value
xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
{
xmlSchemaValPtr swp;
- int order = 1;
+ int order = 1, p;
unsigned long tmp;
- if ((x->value.decimal.sign) && (x->value.decimal.sign))
- order = -1;
- else if (x->value.decimal.sign)
- return (-1);
- else if (y->value.decimal.sign)
+ 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.base < y->value.decimal.base)
- return (-1);
- return (x->value.decimal.base > y->value.decimal.base);
+ 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;
x = swp;
order = -order;
}
- tmp =
- x->value.decimal.base / powten[x->value.decimal.frac -
- y->value.decimal.frac];
- if (tmp > y->value.decimal.base)
+ 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.base)
+ if (tmp < y->value.decimal.lo)
return (-order);
- tmp =
- y->value.decimal.base * powten[x->value.decimal.frac -
- y->value.decimal.frac];
- if (x->value.decimal.base < tmp)
+ tmp = y->value.decimal.lo * p;
+ if (x->value.decimal.lo < tmp)
return (-order);
- if (x->value.decimal.base == tmp)
+ if (x->value.decimal.lo == tmp)
return (0);
return (order);
}
{
long carry, mon, day;
double sec;
- long xmon, xday, myear, lyear, minday, maxday;
+ int invert = 1;
+ long xmon, xday, myear, minday, maxday;
static const long dayRange [2][12] = {
{ 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
{ 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
} else if ((day <= 0) && (sec <= 0.0)) {
return -1;
} else {
+ invert = -1;
xmon = -mon;
xday = day;
}
myear = xmon / 12;
- lyear = myear / 4;
- minday = (myear * 365) + (lyear != 0 ? lyear - 1 : 0);
- maxday = (myear * 365) + (lyear != 0 ? lyear + 1 : 0);
-
+ if (myear == 0) {
+ minday = 0;
+ maxday = 0;
+ } else {
+ maxday = 366 * ((myear + 3) / 4) +
+ 365 * ((myear - 1) % 4);
+ minday = maxday - 1;
+ }
+
xmon = xmon % 12;
minday += dayRange[0][xmon];
maxday += dayRange[1][xmon];
+ if ((maxday == minday) && (maxday == xday))
+ return(0); /* can this really happen ? */
if (maxday < xday)
- return 1;
- else if (minday > xday)
- return -1;
+ return(-invert);
+ if (minday > xday)
+ return(invert);
/* indeterminate */
return 2;
*/
#define TIME_TO_NUMBER(dt) \
((double)((dt->value.date.hour * SECS_PER_HOUR) + \
- (dt->value.date.min * SECS_PER_MIN)) + dt->value.date.sec)
+ (dt->value.date.min * SECS_PER_MIN) + \
+ (dt->value.date.tzo * SECS_PER_MIN)) + \
+ dt->value.date.sec)
/**
* xmlSchemaCompareDates:
p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
- xmlSchemaFreeValue(p1);
- xmlSchemaFreeValue(q1);
- xmlSchemaFreeValue(p2);
- if (p2d > q1d)
+ if (p2d > q1d) {
+ xmlSchemaFreeValue(p1);
+ xmlSchemaFreeValue(q1);
+ xmlSchemaFreeValue(p2);
return 1;
- else if (p2d == q1d) {
+ } else if (p2d == q1d) {
sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
+ xmlSchemaFreeValue(p1);
+ xmlSchemaFreeValue(q1);
+ xmlSchemaFreeValue(p2);
if (sec > 0.0)
return 1;
else
return 2; /* indeterminate */
}
+ xmlSchemaFreeValue(p1);
+ xmlSchemaFreeValue(q1);
+ xmlSchemaFreeValue(p2);
}
} else {
xmlSchemaFreeValue(p1);
}
/**
+ * xmlSchemaCompareNormStrings:
+ * @x: a first string value
+ * @y: a second string value
+ *
+ * Compare 2 string for their normalized values.
+ *
+ * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
+ * case of error
+ */
+static int
+xmlSchemaCompareNormStrings(xmlSchemaValPtr x, xmlSchemaValPtr y) {
+ const xmlChar *utf1;
+ const xmlChar *utf2;
+ int tmp;
+
+ if ((x == NULL) || (y == NULL))
+ return(-2);
+ utf1 = x->value.str;
+ utf2 = y->value.str;
+
+ while (IS_BLANK(*utf1)) utf1++;
+ while (IS_BLANK(*utf2)) utf2++;
+ while ((*utf1 != 0) && (*utf2 != 0)) {
+ if (IS_BLANK(*utf1)) {
+ if (!IS_BLANK(*utf2)) {
+ tmp = *utf1 - *utf2;
+ return(tmp);
+ }
+ while (IS_BLANK(*utf1)) utf1++;
+ while (IS_BLANK(*utf2)) utf2++;
+ } else {
+ tmp = *utf1++ - *utf2++;
+ if (tmp < 0)
+ return(-1);
+ if (tmp > 0)
+ return(1);
+ }
+ }
+ if (*utf1 != 0) {
+ while (IS_BLANK(*utf1)) utf1++;
+ if (*utf1 != 0)
+ return(1);
+ }
+ if (*utf2 != 0) {
+ while (IS_BLANK(*utf2)) utf2++;
+ if (*utf2 != 0)
+ return(-1);
+ }
+ return(0);
+}
+
+/**
+ * xmlSchemaCompareFloats:
+ * @x: a first float or double value
+ * @y: a second float or double value
+ *
+ * Compare 2 values
+ *
+ * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
+ * case of error
+ */
+static int
+xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
+ double d1, d2;
+
+ if ((x == NULL) || (y == NULL))
+ return(-2);
+
+ /*
+ * Cast everything to doubles.
+ */
+ if (x->type == XML_SCHEMAS_DOUBLE)
+ d1 = x->value.d;
+ else if (x->type == XML_SCHEMAS_FLOAT)
+ d1 = x->value.f;
+ else
+ return(-2);
+
+ if (y->type == XML_SCHEMAS_DOUBLE)
+ d2 = y->value.d;
+ else if (y->type == XML_SCHEMAS_FLOAT)
+ d2 = y->value.f;
+ else
+ return(-2);
+
+ /*
+ * Check for special cases.
+ */
+ if (xmlXPathIsNaN(d1)) {
+ if (xmlXPathIsNaN(d2))
+ return(0);
+ return(1);
+ }
+ if (xmlXPathIsNaN(d2))
+ return(-1);
+ if (d1 == xmlXPathPINF) {
+ if (d2 == xmlXPathPINF)
+ return(0);
+ return(1);
+ }
+ if (d2 == xmlXPathPINF)
+ return(-1);
+ if (d1 == xmlXPathNINF) {
+ if (d2 == xmlXPathNINF)
+ return(0);
+ return(-1);
+ }
+ if (d2 == xmlXPathNINF)
+ return(1);
+
+ /*
+ * basic tests, the last one we should have equality, but
+ * portability is more important than speed and handling
+ * NaN or Inf in a portable way is always a challenge, so ...
+ */
+ if (d1 < d2)
+ return(-1);
+ if (d1 > d2)
+ return(1);
+ if (d1 == d2)
+ return(0);
+ return(2);
+}
+
+/**
* xmlSchemaCompareValues:
* @x: a first value
* @y: a second value
* Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
* case of error
*/
-static int
+int
xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
if ((x == NULL) || (y == NULL))
return(-2);
switch (x->type) {
- case XML_SCHEMAS_STRING:
- TODO
+ case XML_SCHEMAS_UNKNOWN:
+ return(-2);
+ case XML_SCHEMAS_INTEGER:
+ case XML_SCHEMAS_NPINTEGER:
+ case XML_SCHEMAS_NINTEGER:
+ case XML_SCHEMAS_NNINTEGER:
+ case XML_SCHEMAS_PINTEGER:
+ case XML_SCHEMAS_INT:
+ case XML_SCHEMAS_UINT:
+ case XML_SCHEMAS_LONG:
+ case XML_SCHEMAS_ULONG:
+ case XML_SCHEMAS_SHORT:
+ case XML_SCHEMAS_USHORT:
+ case XML_SCHEMAS_BYTE:
+ case XML_SCHEMAS_UBYTE:
case XML_SCHEMAS_DECIMAL:
- if (y->type == XML_SCHEMAS_DECIMAL)
+ if (y->type == x->type)
+ return(xmlSchemaCompareDecimals(x, y));
+ if ((y->type == XML_SCHEMAS_DECIMAL) ||
+ (y->type == XML_SCHEMAS_INTEGER) ||
+ (y->type == XML_SCHEMAS_NPINTEGER) ||
+ (y->type == XML_SCHEMAS_NINTEGER) ||
+ (y->type == XML_SCHEMAS_NNINTEGER) ||
+ (y->type == XML_SCHEMAS_PINTEGER) ||
+ (y->type == XML_SCHEMAS_INT) ||
+ (y->type == XML_SCHEMAS_UINT) ||
+ (y->type == XML_SCHEMAS_LONG) ||
+ (y->type == XML_SCHEMAS_ULONG) ||
+ (y->type == XML_SCHEMAS_SHORT) ||
+ (y->type == XML_SCHEMAS_USHORT) ||
+ (y->type == XML_SCHEMAS_BYTE) ||
+ (y->type == XML_SCHEMAS_UBYTE))
return(xmlSchemaCompareDecimals(x, y));
return(-2);
case XML_SCHEMAS_DURATION:
(y->type == XML_SCHEMAS_DATE) ||
(y->type == XML_SCHEMAS_GYEARMONTH))
return (xmlSchemaCompareDates(x, y));
+ return (-2);
+ 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:
+ case XML_SCHEMAS_IDREF:
+ case XML_SCHEMAS_ENTITY:
+ case XML_SCHEMAS_NOTATION:
+ case XML_SCHEMAS_ANYURI:
+ if ((y->type == XML_SCHEMAS_NORMSTRING) ||
+ (y->type == XML_SCHEMAS_TOKEN) ||
+ (y->type == XML_SCHEMAS_LANGUAGE) ||
+ (y->type == XML_SCHEMAS_NMTOKEN) ||
+ (y->type == XML_SCHEMAS_NAME) ||
+ (y->type == XML_SCHEMAS_QNAME) ||
+ (y->type == XML_SCHEMAS_NCNAME) ||
+ (y->type == XML_SCHEMAS_ID) ||
+ (y->type == XML_SCHEMAS_IDREF) ||
+ (y->type == XML_SCHEMAS_ENTITY) ||
+ (y->type == XML_SCHEMAS_NOTATION) ||
+ (y->type == XML_SCHEMAS_ANYURI))
+ return (xmlSchemaCompareNormStrings(x, y));
+ return (-2);
+ case XML_SCHEMAS_QNAME:
+ if (y->type == XML_SCHEMAS_QNAME) {
+ if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
+ (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
+ return(0);
+ return(2);
+ }
+ return (-2);
+ case XML_SCHEMAS_FLOAT:
+ case XML_SCHEMAS_DOUBLE:
+ if ((y->type == XML_SCHEMAS_FLOAT) ||
+ (y->type == XML_SCHEMAS_DOUBLE))
+ return (xmlSchemaCompareFloats(x, y));
+ return (-2);
+ case XML_SCHEMAS_BOOLEAN:
+ if (y->type == XML_SCHEMAS_BOOLEAN) {
+ if (x->value.b == y->value.b)
+ return(0);
+ if (x->value.b == 0)
+ return(-1);
+ return(1);
+ }
+ return (-2);
+ case XML_SCHEMAS_HEXBINARY:
+ if (y->type == XML_SCHEMAS_HEXBINARY) {
+ if (x->value.hex.total == y->value.hex.total) {
+ int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
+ if (ret > 0)
+ return(1);
+ else if (ret == 0)
+ return(0);
+ }
+ else if (x->value.hex.total > y->value.hex.total)
+ return(1);
+ return(-1);
+ }
return (-2);
- default:
+ case XML_SCHEMAS_STRING:
+ case XML_SCHEMAS_IDREFS:
+ case XML_SCHEMAS_ENTITIES:
+ case XML_SCHEMAS_NMTOKENS:
TODO
+ break;
}
return -2;
}
/**
+ * xmlSchemaNormLen:
+ * @value: a string
+ *
+ * Computes the UTF8 length of the normalized value of the string
+ *
+ * Returns the length or -1 in case of error.
+ */
+static int
+xmlSchemaNormLen(const xmlChar *value) {
+ const xmlChar *utf;
+ int ret = 0;
+
+ if (value == NULL)
+ return(-1);
+ utf = value;
+ while (IS_BLANK(*utf)) utf++;
+ while (*utf != 0) {
+ if (utf[0] & 0x80) {
+ if ((utf[1] & 0xc0) != 0x80)
+ return(-1);
+ if ((utf[0] & 0xe0) == 0xe0) {
+ if ((utf[2] & 0xc0) != 0x80)
+ return(-1);
+ if ((utf[0] & 0xf0) == 0xf0) {
+ if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
+ return(-1);
+ utf += 4;
+ } else {
+ utf += 3;
+ }
+ } else {
+ utf += 2;
+ }
+ } else if (IS_BLANK(*utf)) {
+ while (IS_BLANK(*utf)) utf++;
+ if (*utf == 0)
+ break;
+ } else {
+ utf++;
+ }
+ ret++;
+ }
+ return(ret);
+}
+
+/**
* xmlSchemaValidateFacet:
* @base: the base type
* @facet: the facet to check
if (ret == 1)
return(0);
if (ret == 0) {
- TODO /* error code */
+ /* TODO error code */
return(1);
}
return(ret);
case XML_SCHEMA_FACET_MAXEXCLUSIVE:
ret = xmlSchemaCompareValues(val, facet->val);
if (ret == -2) {
- TODO /* error code */
+ /* TODO error code */
return(-1);
}
if (ret == -1)
case XML_SCHEMA_FACET_MAXINCLUSIVE:
ret = xmlSchemaCompareValues(val, facet->val);
if (ret == -2) {
- TODO /* error code */
+ /* TODO error code */
return(-1);
}
if ((ret == -1) || (ret == 0))
case XML_SCHEMA_FACET_MINEXCLUSIVE:
ret = xmlSchemaCompareValues(val, facet->val);
if (ret == -2) {
- TODO /* error code */
+ /* TODO error code */
return(-1);
}
if (ret == 1)
case XML_SCHEMA_FACET_MININCLUSIVE:
ret = xmlSchemaCompareValues(val, facet->val);
if (ret == -2) {
- TODO /* error code */
+ /* TODO error code */
return(-1);
}
if ((ret == 1) || (ret == 0))
/* error code */
return(1);
case XML_SCHEMA_FACET_WHITESPACE:
- TODO /* whitespaces */
+ /* TODO whitespaces */
return(0);
- case XML_SCHEMA_FACET_MAXLENGTH:
- if ((facet->val != NULL) &&
- (facet->val->type == XML_SCHEMAS_DECIMAL) &&
- (facet->val->value.decimal.frac == 0)) {
- unsigned int len;
-
- if (facet->val->value.decimal.sign == 1)
- return(1);
- len = xmlUTF8Strlen(value);
- if (len > facet->val->value.decimal.base)
- return(1);
- return(0);
- }
- TODO /* error code */
- return(1);
case XML_SCHEMA_FACET_ENUMERATION:
if ((facet->value != NULL) &&
(xmlStrEqual(facet->value, value)))
return(0);
return(1);
+ case XML_SCHEMA_FACET_LENGTH:
+ 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.hex.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) &&
+ (val->type != XML_SCHEMAS_NPINTEGER) &&
+ (val->type != XML_SCHEMAS_NINTEGER) &&
+ (val->type != XML_SCHEMAS_NNINTEGER) &&
+ (val->type != XML_SCHEMAS_PINTEGER) &&
+ (val->type != XML_SCHEMAS_INT) &&
+ (val->type != XML_SCHEMAS_UINT) &&
+ (val->type != XML_SCHEMAS_LONG) &&
+ (val->type != XML_SCHEMAS_ULONG) &&
+ (val->type != XML_SCHEMAS_SHORT) &&
+ (val->type != XML_SCHEMAS_USHORT) &&
+ (val->type != XML_SCHEMAS_BYTE) &&
+ (val->type != XML_SCHEMAS_UBYTE))) {
+ 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
}
return(0);
+
}
#endif /* LIBXML_SCHEMAS_ENABLED */