2 * schemastypes.c : implementation of the XML Schema Datatypes
3 * definition and validity checking
5 * See Copyright for the status of this software.
7 * Daniel Veillard <veillard@redhat.com>
13 #ifdef LIBXML_SCHEMAS_ENABLED
16 #include <libxml/xmlmemory.h>
17 #include <libxml/parser.h>
18 #include <libxml/parserInternals.h>
19 #include <libxml/hash.h>
20 #include <libxml/valid.h>
21 #include <libxml/xpath.h>
22 #include <libxml/uri.h>
24 #include <libxml/xmlschemas.h>
25 #include <libxml/schemasInternals.h>
26 #include <libxml/xmlschemastypes.h>
35 xmlGenericError(xmlGenericErrorContext, \
36 "Unimplemented block at %s:%d\n", \
39 #define XML_SCHEMAS_NAMESPACE_NAME \
40 (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
43 XML_SCHEMAS_UNKNOWN = 0,
45 XML_SCHEMAS_NORMSTRING,
50 XML_SCHEMAS_GMONTHDAY,
52 XML_SCHEMAS_GYEARMONTH,
74 XML_SCHEMAS_NPINTEGER,
76 XML_SCHEMAS_NNINTEGER,
89 static unsigned long powten[10] = {
90 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000L,
91 100000000L, 1000000000L
95 typedef struct _xmlSchemaValDate xmlSchemaValDate;
96 typedef xmlSchemaValDate *xmlSchemaValDatePtr;
97 struct _xmlSchemaValDate {
99 unsigned int mon :4; /* 1 <= mon <= 12 */
100 unsigned int day :5; /* 1 <= day <= 31 */
101 unsigned int hour :5; /* 0 <= hour <= 23 */
102 unsigned int min :6; /* 0 <= min <= 59 */
104 unsigned int tz_flag :1; /* is tzo explicitely set? */
105 int tzo :11; /* -1440 <= tzo <= 1440 */
109 typedef struct _xmlSchemaValDuration xmlSchemaValDuration;
110 typedef xmlSchemaValDuration *xmlSchemaValDurationPtr;
111 struct _xmlSchemaValDuration {
112 long mon; /* mon stores years also */
114 double sec; /* sec stores min and hour also */
117 typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
118 typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
119 struct _xmlSchemaValDecimal {
120 /* would use long long but not portable */
127 unsigned int total:8;
130 typedef struct _xmlSchemaValQName xmlSchemaValQName;
131 typedef xmlSchemaValQName *xmlSchemaValQNamePtr;
132 struct _xmlSchemaValQName {
137 typedef struct _xmlSchemaValHex xmlSchemaValHex;
138 typedef xmlSchemaValHex *xmlSchemaValHexPtr;
139 struct _xmlSchemaValHex {
144 struct _xmlSchemaVal {
145 xmlSchemaValType type;
147 xmlSchemaValDecimal decimal;
148 xmlSchemaValDate date;
149 xmlSchemaValDuration dur;
150 xmlSchemaValQName qname;
159 static int xmlSchemaTypesInitialized = 0;
160 static xmlHashTablePtr xmlSchemaTypesBank = NULL;
165 static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL;
166 static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL;
167 static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL;
168 static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL;
169 static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL;
170 static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL;
171 static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL;
172 static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL;
173 static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL;
174 static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL;
175 static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL;
176 static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL;
177 static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL;
178 static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
179 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
180 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
181 static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
182 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
187 static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL;
188 static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL;
189 static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL;
190 static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL;
191 static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL;
192 static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL;
193 static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL;
194 static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL;
195 static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL;
196 static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL;
197 static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL;
198 static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL;
199 static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL;
200 static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL;
201 static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL;
202 static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL;
203 static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
204 static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
205 static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL;
206 static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL;
207 static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL;
208 static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL;
209 static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL;
210 static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL;
211 static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL;
212 static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL;
213 static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
216 * xmlSchemaInitBasicType:
217 * @name: the type name
218 * @type: the value type associated
220 * Initialize one default type
222 static xmlSchemaTypePtr
223 xmlSchemaInitBasicType(const char *name, xmlSchemaValType type) {
224 xmlSchemaTypePtr ret;
226 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
228 xmlGenericError(xmlGenericErrorContext,
229 "Could not initilize type %s: out of memory\n", name);
232 memset(ret, 0, sizeof(xmlSchemaType));
233 ret->name = xmlStrdup((const xmlChar *)name);
234 ret->type = XML_SCHEMA_TYPE_BASIC;
236 ret->contentType = XML_SCHEMA_CONTENT_BASIC;
237 xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
238 XML_SCHEMAS_NAMESPACE_NAME, ret);
243 * xmlSchemaInitTypes:
245 * Initialize the default XML Schemas type library
248 xmlSchemaInitTypes(void)
250 if (xmlSchemaTypesInitialized != 0)
252 xmlSchemaTypesBank = xmlHashCreate(40);
255 * primitive datatypes
257 xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
259 xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
260 XML_SCHEMAS_UNKNOWN);
261 xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType",
262 XML_SCHEMAS_UNKNOWN);
263 xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
264 XML_SCHEMAS_DECIMAL);
265 xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
267 xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
268 XML_SCHEMAS_DATETIME);
269 xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
271 xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
273 xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
274 XML_SCHEMAS_GYEARMONTH);
275 xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
277 xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
278 XML_SCHEMAS_GMONTHDAY);
279 xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
281 xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
282 XML_SCHEMAS_DURATION);
283 xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
285 xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
287 xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
288 XML_SCHEMAS_BOOLEAN);
289 xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
291 xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
292 XML_SCHEMAS_HEXBINARY);
297 xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
298 XML_SCHEMAS_INTEGER);;
299 xmlSchemaTypeNonPositiveIntegerDef =
300 xmlSchemaInitBasicType("nonPositiveInteger",
301 XML_SCHEMAS_NPINTEGER);;
302 xmlSchemaTypeNegativeIntegerDef =
303 xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER);;
304 xmlSchemaTypeLongDef =
305 xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG);;
306 xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT);;
307 xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
309 xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
311 xmlSchemaTypeNonNegativeIntegerDef =
312 xmlSchemaInitBasicType("nonNegativeInteger",
313 XML_SCHEMAS_NNINTEGER);
314 xmlSchemaTypeUnsignedLongDef =
315 xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG);;
316 xmlSchemaTypeUnsignedIntDef =
317 xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT);;
318 xmlSchemaTypeUnsignedShortDef =
319 xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT);;
320 xmlSchemaTypeUnsignedByteDef =
321 xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE);;
322 xmlSchemaTypePositiveIntegerDef =
323 xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER);
325 xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
326 XML_SCHEMAS_NORMSTRING);
327 xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
329 xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
330 XML_SCHEMAS_LANGUAGE);
331 xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID);
332 xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
334 xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
336 xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
338 xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
339 XML_SCHEMAS_ENTITIES);
340 xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
341 XML_SCHEMAS_NOTATION);
342 xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
344 xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
346 xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
348 xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
349 XML_SCHEMAS_NMTOKEN);
350 xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
351 XML_SCHEMAS_NMTOKENS);
352 xmlSchemaTypesInitialized = 1;
356 * xmlSchemaCleanupTypes:
358 * Cleanup the default XML Schemas type library
361 xmlSchemaCleanupTypes(void) {
362 if (xmlSchemaTypesInitialized == 0)
364 xmlHashFree(xmlSchemaTypesBank, (xmlHashDeallocator) xmlSchemaFreeType);
365 xmlSchemaTypesInitialized = 0;
370 * @type: the value type
372 * Allocate a new simple type value
374 * Returns a pointer to the new value or NULL in case of error
376 static xmlSchemaValPtr
377 xmlSchemaNewValue(xmlSchemaValType type) {
378 xmlSchemaValPtr value;
380 value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
384 memset(value, 0, sizeof(xmlSchemaVal));
390 * xmlSchemaFreeValue:
391 * @value: the value to free
393 * Cleanup the default XML Schemas type library
396 xmlSchemaFreeValue(xmlSchemaValPtr value) {
399 switch (value->type) {
400 case XML_SCHEMAS_STRING:
401 case XML_SCHEMAS_NORMSTRING:
402 case XML_SCHEMAS_TOKEN:
403 case XML_SCHEMAS_LANGUAGE:
404 case XML_SCHEMAS_NMTOKEN:
405 case XML_SCHEMAS_NMTOKENS:
406 case XML_SCHEMAS_NAME:
407 case XML_SCHEMAS_NCNAME:
409 case XML_SCHEMAS_IDREF:
410 case XML_SCHEMAS_IDREFS:
411 case XML_SCHEMAS_ENTITY:
412 case XML_SCHEMAS_ENTITIES:
413 case XML_SCHEMAS_NOTATION:
414 case XML_SCHEMAS_ANYURI:
415 if (value->value.str != NULL)
416 xmlFree(value->value.str);
418 case XML_SCHEMAS_QNAME:
419 if (value->value.qname.uri != NULL)
420 xmlFree(value->value.qname.uri);
421 if (value->value.qname.name != NULL)
422 xmlFree(value->value.qname.name);
424 case XML_SCHEMAS_HEXBINARY:
425 if (value->value.hex.str != NULL)
426 xmlFree(value->value.hex.str);
435 * xmlSchemaGetPredefinedType:
436 * @name: the type name
437 * @ns: the URI of the namespace usually "http://www.w3.org/2001/XMLSchema"
439 * Lookup a type in the default XML Schemas type library
441 * Returns the type if found, NULL otherwise
444 xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
445 if (xmlSchemaTypesInitialized == 0)
446 xmlSchemaInitTypes();
449 return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
452 /****************************************************************
454 * Convenience macros and functions *
456 ****************************************************************/
458 #define IS_TZO_CHAR(c) \
459 ((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
461 #define VALID_YEAR(yr) (yr != 0)
462 #define VALID_MONTH(mon) ((mon >= 1) && (mon <= 12))
463 /* VALID_DAY should only be used when month is unknown */
464 #define VALID_DAY(day) ((day >= 1) && (day <= 31))
465 #define VALID_HOUR(hr) ((hr >= 0) && (hr <= 23))
466 #define VALID_MIN(min) ((min >= 0) && (min <= 59))
467 #define VALID_SEC(sec) ((sec >= 0) && (sec < 60))
468 #define VALID_TZO(tzo) ((tzo > -1440) && (tzo < 1440))
470 (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
472 static const long daysInMonth[12] =
473 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
474 static const long daysInMonthLeap[12] =
475 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
477 #define MAX_DAYINMONTH(yr,mon) \
478 (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
480 #define VALID_MDAY(dt) \
481 (IS_LEAP(dt->year) ? \
482 (dt->day <= daysInMonthLeap[dt->mon - 1]) : \
483 (dt->day <= daysInMonth[dt->mon - 1]))
485 #define VALID_DATE(dt) \
486 (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
488 #define VALID_TIME(dt) \
489 (VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \
490 VALID_SEC(dt->sec) && VALID_TZO(dt->tzo))
492 #define VALID_DATETIME(dt) \
493 (VALID_DATE(dt) && VALID_TIME(dt))
495 #define SECS_PER_MIN (60)
496 #define SECS_PER_HOUR (60 * SECS_PER_MIN)
497 #define SECS_PER_DAY (24 * SECS_PER_HOUR)
499 static const long dayInYearByMonth[12] =
500 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
501 static const long dayInLeapYearByMonth[12] =
502 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
504 #define DAY_IN_YEAR(day, month, year) \
506 dayInLeapYearByMonth[month - 1] : \
507 dayInYearByMonth[month - 1]) + day)
510 #define DEBUG_DATE(dt) \
511 xmlGenericError(xmlGenericErrorContext, \
512 "type=%o %04ld-%02u-%02uT%02u:%02u:%03f", \
513 dt->type,dt->value.date.year,dt->value.date.mon, \
514 dt->value.date.day,dt->value.date.hour,dt->value.date.min, \
515 dt->value.date.sec); \
516 if (dt->value.date.tz_flag) \
517 if (dt->value.date.tzo != 0) \
518 xmlGenericError(xmlGenericErrorContext, \
519 "%+05d\n",dt->value.date.tzo); \
521 xmlGenericError(xmlGenericErrorContext, "Z\n"); \
523 xmlGenericError(xmlGenericErrorContext,"\n")
525 #define DEBUG_DATE(dt)
529 * _xmlSchemaParseGYear:
530 * @dt: pointer to a date structure
531 * @str: pointer to the string to analyze
533 * Parses a xs:gYear without time zone and fills in the appropriate
534 * field of the @dt structure. @str is updated to point just after the
535 * xs:gYear. It is supposed that @dt->year is big enough to contain
538 * Returns 0 or the error code
541 _xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
542 const xmlChar *cur = *str, *firstChar;
543 int isneg = 0, digcnt = 0;
545 if (((*cur < '0') || (*cur > '9')) &&
546 (*cur != '-') && (*cur != '+'))
556 while ((*cur >= '0') && (*cur <= '9')) {
557 dt->year = dt->year * 10 + (*cur - '0');
562 /* year must be at least 4 digits (CCYY); over 4
563 * digits cannot have a leading zero. */
564 if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0')))
568 dt->year = - dt->year;
570 if (!VALID_YEAR(dt->year))
579 * @num: the integer to fill in
580 * @cur: an #xmlChar *
581 * @invalid: an integer
583 * Parses a 2-digits integer and updates @num with the value. @cur is
584 * updated to point just after the integer.
585 * In case of error, @invalid is set to %TRUE, values of @num and
586 * @cur are undefined.
588 #define PARSE_2_DIGITS(num, cur, invalid) \
589 if ((cur[0] < '0') || (cur[0] > '9') || \
590 (cur[1] < '0') || (cur[1] > '9')) \
593 num = (cur[0] - '0') * 10 + (cur[1] - '0'); \
598 * @num: the double to fill in
599 * @cur: an #xmlChar *
600 * @invalid: an integer
602 * Parses a float and updates @num with the value. @cur is
603 * updated to point just after the float. The float must have a
604 * 2-digits integer part and may or may not have a decimal part.
605 * In case of error, @invalid is set to %TRUE, values of @num and
606 * @cur are undefined.
608 #define PARSE_FLOAT(num, cur, invalid) \
609 PARSE_2_DIGITS(num, cur, invalid); \
610 if (!invalid && (*cur == '.')) { \
613 if ((*cur < '0') || (*cur > '9')) \
615 while ((*cur >= '0') && (*cur <= '9')) { \
617 num += (*cur - '0') * mult; \
623 * _xmlSchemaParseGMonth:
624 * @dt: pointer to a date structure
625 * @str: pointer to the string to analyze
627 * Parses a xs:gMonth without time zone and fills in the appropriate
628 * field of the @dt structure. @str is updated to point just after the
631 * Returns 0 or the error code
634 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) {
635 const xmlChar *cur = *str;
638 PARSE_2_DIGITS(dt->mon, cur, ret);
642 if (!VALID_MONTH(dt->mon))
650 * _xmlSchemaParseGDay:
651 * @dt: pointer to a date structure
652 * @str: pointer to the string to analyze
654 * Parses a xs:gDay without time zone and fills in the appropriate
655 * field of the @dt structure. @str is updated to point just after the
658 * Returns 0 or the error code
661 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) {
662 const xmlChar *cur = *str;
665 PARSE_2_DIGITS(dt->day, cur, ret);
669 if (!VALID_DAY(dt->day))
677 * _xmlSchemaParseTime:
678 * @dt: pointer to a date structure
679 * @str: pointer to the string to analyze
681 * Parses a xs:time without time zone and fills in the appropriate
682 * fields of the @dt structure. @str is updated to point just after the
684 * In case of error, values of @dt fields are undefined.
686 * Returns 0 or the error code
689 _xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) {
690 const xmlChar *cur = *str;
691 unsigned int hour = 0; /* use temp var in case str is not xs:time */
694 PARSE_2_DIGITS(hour, cur, ret);
702 /* the ':' insures this string is xs:time */
705 PARSE_2_DIGITS(dt->min, cur, ret);
713 PARSE_FLOAT(dt->sec, cur, ret);
725 * _xmlSchemaParseTimeZone:
726 * @dt: pointer to a date structure
727 * @str: pointer to the string to analyze
729 * Parses a time zone without time zone and fills in the appropriate
730 * field of the @dt structure. @str is updated to point just after the
733 * Returns 0 or the error code
736 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
737 const xmlChar *cur = *str;
757 int isneg = 0, tmp = 0;
758 isneg = (*cur == '-');
762 PARSE_2_DIGITS(tmp, cur, ret);
765 if (!VALID_HOUR(tmp))
774 PARSE_2_DIGITS(tmp, cur, ret);
784 if (!VALID_TZO(dt->tzo))
798 /****************************************************************
800 * XML Schema Dates/Times Datatypes Handling *
802 ****************************************************************/
806 * @num: the integer to fill in
807 * @cur: an #xmlChar *
808 * @num_type: an integer flag
810 * Parses a digits integer and updates @num with the value. @cur is
811 * updated to point just after the integer.
812 * In case of error, @num_type is set to -1, values of @num and
813 * @cur are undefined.
815 #define PARSE_DIGITS(num, cur, num_type) \
816 if ((*cur < '0') || (*cur > '9')) \
819 while ((*cur >= '0') && (*cur <= '9')) { \
820 num = num * 10 + (*cur - '0'); \
826 * @num: the double to fill in
827 * @cur: an #xmlChar *
828 * @num_type: an integer flag
830 * Parses a float or integer and updates @num with the value. @cur is
831 * updated to point just after the number. If the number is a float,
832 * then it must have an integer part and a decimal part; @num_type will
833 * be set to 1. If there is no decimal part, @num_type is set to zero.
834 * In case of error, @num_type is set to -1, values of @num and
835 * @cur are undefined.
837 #define PARSE_NUM(num, cur, num_type) \
839 PARSE_DIGITS(num, cur, num_type); \
840 if (!num_type && (*cur == '.')) { \
843 if ((*cur < '0') || (*cur > '9')) \
847 while ((*cur >= '0') && (*cur <= '9')) { \
849 num += (*cur - '0') * mult; \
855 * xmlSchemaValidateDates:
856 * @type: the expected type or XML_SCHEMAS_UNKNOWN
857 * @dateTime: string to analyze
858 * @val: the return computed value
860 * Check that @dateTime conforms to the lexical space of one of the date types.
861 * if true a value is computed and returned in @val.
863 * Returns 0 if this validates, a positive error code number otherwise
864 * and -1 in case of internal or API error.
867 xmlSchemaValidateDates (xmlSchemaValType type,
868 const xmlChar *dateTime, xmlSchemaValPtr *val) {
871 const xmlChar *cur = dateTime;
873 #define RETURN_TYPE_IF_VALID(t) \
874 if (IS_TZO_CHAR(*cur)) { \
875 ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); \
884 if (dateTime == NULL)
887 if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
890 dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN);
894 if ((cur[0] == '-') && (cur[1] == '-')) {
896 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
901 /* is it an xs:gDay? */
903 if (type == XML_SCHEMAS_GMONTH)
906 ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
910 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY);
916 * it should be an xs:gMonthDay or xs:gMonth
918 ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
923 * a '-' char could indicate this type is xs:gMonthDay or
924 * a negative time zone offset. Check for xs:gMonthDay first.
925 * Also the first three char's of a negative tzo (-MM:SS) can
926 * appear to be a valid day; so even if the day portion
927 * of the xs:gMonthDay verifies, we must insure it was not
931 const xmlChar *rewnd = cur;
934 ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
935 if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) {
938 * we can use the VALID_MDAY macro to validate the month
939 * and day because the leap year test will flag year zero
940 * as a leap year (even though zero is an invalid year).
942 if (VALID_MDAY((&(dt->value.date)))) {
944 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
951 * not xs:gMonthDay so rewind and check if just xs:gMonth
952 * with an optional time zone.
957 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
963 * It's a right-truncated date or an xs:time.
964 * Try to parse an xs:time then fallback on right-truncated dates.
966 if ((*cur >= '0') && (*cur <= '9')) {
967 ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
969 /* it's an xs:time */
970 RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME);
974 /* fallback on date parsing */
977 ret = _xmlSchemaParseGYear(&(dt->value.date), &cur);
981 /* is it an xs:gYear? */
982 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR);
988 ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
992 /* is it an xs:gYearMonth? */
993 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH);
999 ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1000 if ((ret != 0) || !VALID_DATE((&(dt->value.date))))
1003 /* is it an xs:date? */
1004 RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE);
1010 /* it should be an xs:dateTime */
1011 ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1015 ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);
1016 if ((ret != 0) || (*cur != 0) || !VALID_DATETIME((&(dt->value.date))))
1020 dt->type = XML_SCHEMAS_DATETIME;
1024 if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
1028 * insure the parsed type is equal to or less significant (right
1029 * truncated) than the desired type.
1031 if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) {
1033 /* time only matches time */
1034 if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME))
1037 if ((type == XML_SCHEMAS_DATETIME) &&
1038 ((dt->type != XML_SCHEMAS_DATE) ||
1039 (dt->type != XML_SCHEMAS_GYEARMONTH) ||
1040 (dt->type != XML_SCHEMAS_GYEAR)))
1043 if ((type == XML_SCHEMAS_DATE) &&
1044 ((dt->type != XML_SCHEMAS_GYEAR) ||
1045 (dt->type != XML_SCHEMAS_GYEARMONTH)))
1048 if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
1051 if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
1059 xmlSchemaFreeValue(dt);
1065 xmlSchemaFreeValue(dt);
1070 * xmlSchemaValidateDuration:
1071 * @type: the predefined type
1072 * @duration: string to analyze
1073 * @val: the return computed value
1075 * Check that @duration conforms to the lexical space of the duration type.
1076 * if true a value is computed and returned in @val.
1078 * Returns 0 if this validates, a positive error code number otherwise
1079 * and -1 in case of internal or API error.
1082 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1083 const xmlChar *duration, xmlSchemaValPtr *val) {
1084 const xmlChar *cur = duration;
1085 xmlSchemaValPtr dur;
1087 unsigned int seq = 0;
1089 int num_type = 0; /* -1 = invalid, 0 = int, 1 = floating */
1090 const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
1091 const double multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
1093 if (duration == NULL)
1101 /* duration must start with 'P' (after sign) */
1108 dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
1114 /* input string should be empty or invalid date/time item */
1115 if (seq >= sizeof(desig))
1118 /* T designator must be present for time items */
1125 } else if (seq == 3)
1128 /* parse the number portion of the item */
1129 PARSE_NUM(num, cur, num_type);
1131 if ((num_type == -1) || (*cur == 0))
1134 /* update duration based on item type */
1135 while (seq < sizeof(desig)) {
1136 if (*cur == desig[seq]) {
1138 /* verify numeric type; only seconds can be float */
1139 if ((num_type != 0) && (seq < (sizeof(desig)-1)))
1144 dur->value.dur.mon = (long)num * 12;
1147 dur->value.dur.mon += (long)num;
1150 /* convert to seconds using multiplier */
1151 dur->value.dur.sec += num * multi[seq];
1156 break; /* exit loop */
1158 /* no date designators found? */
1166 dur->value.dur.mon = -dur->value.dur.mon;
1167 dur->value.dur.day = -dur->value.dur.day;
1168 dur->value.dur.sec = -dur->value.dur.sec;
1174 xmlSchemaFreeValue(dur);
1180 xmlSchemaFreeValue(dur);
1188 * Removes the leading and ending spaces of a string
1190 * Returns the new string or NULL if no change was required.
1193 xmlSchemaStrip(const xmlChar *value) {
1194 const xmlChar *start = value, *end, *f;
1196 if (value == NULL) return(NULL);
1197 while ((*start != 0) && (IS_BLANK(*start))) start++;
1199 while (*end != 0) end++;
1202 while ((end > start) && (IS_BLANK(*end))) end--;
1204 if ((start == value) && (f == end)) return(NULL);
1205 return(xmlStrndup(start, end - start));
1209 * xmlSchemaCollapseString:
1212 * Removes and normalize white spaces in the string
1214 * Returns the new string or NULL if no change was required.
1217 xmlSchemaCollapseString(const xmlChar *value) {
1218 const xmlChar *start = value, *end, *f;
1222 if (value == NULL) return(NULL);
1223 while ((*start != 0) && (IS_BLANK(*start))) start++;
1226 if ((*end == ' ') && (IS_BLANK(end[1]))) {
1229 } else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) {
1238 while ((end > start) && (IS_BLANK(*end))) end--;
1240 if ((start == value) && (f == end)) return(NULL);
1241 return(xmlStrndup(start, end - start));
1243 start = xmlStrdup(start);
1244 if (start == NULL) return(NULL);
1245 g = (xmlChar *) (start + col);
1248 if (IS_BLANK(*end)) {
1250 while (IS_BLANK(*end)) end++;
1257 return((xmlChar *) start);
1261 * xmlSchemaValAtomicListNode:
1262 * @type: the predefined atomic type for a token in the list
1263 * @value: the list value to check
1264 * @ret: the return computed value
1265 * @node: the node containing the value
1267 * Check that a value conforms to the lexical space of the predefined
1268 * list type. if true a value is computed and returned in @ret.
1270 * Returns the number of items if this validates, a negative error code
1274 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
1275 xmlSchemaValPtr *ret, xmlNodePtr node) {
1276 xmlChar *val, *cur, *endval;
1280 if (value == NULL) {
1283 val = xmlStrdup(value);
1291 while (IS_BLANK(*cur)) *cur++ = 0;
1293 if (IS_BLANK(*cur)) {
1296 while (IS_BLANK(*cur)) *cur++ = 0;
1300 while ((*cur != 0) && (!IS_BLANK(*cur))) cur++;
1303 if (nb_values == 0) {
1312 while ((*cur == 0) && (cur != endval)) cur++;
1313 while (cur != endval) {
1314 tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node);
1317 while (*cur != 0) cur++;
1318 while ((*cur == 0) && (cur != endval)) cur++;
1330 * xmlSchemaParseUInt:
1331 * @str: pointer to the string R/W
1332 * @llo: pointer to the low result
1333 * @lmi: pointer to the mid result
1334 * @lhi: pointer to the high result
1336 * Parse an unsigned long into 3 fields.
1338 * Returns the number of chars parsed or -1 if overflow of the capacity
1341 xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
1342 unsigned long *lmi, unsigned long *lhi) {
1343 unsigned long lo = 0, mi = 0, hi = 0;
1344 const xmlChar *tmp, *cur = *str;
1347 while (*cur == '0') {
1352 while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
1360 hi = hi * 10 + (*cur++ - '0');
1364 mi = mi * 10 + (*cur++ - '0');
1368 lo = lo * 10 + (*cur++ - '0');
1380 * xmlSchemaValAtomicType:
1381 * @type: the predefined type
1382 * @value: the value to check
1383 * @val: the return computed value
1384 * @node: the node containing the value
1385 * flags: flags to control the vlidation
1387 * Check that a value conforms to the lexical space of the atomic type.
1388 * if true a value is computed and returned in @val.
1390 * Returns 0 if this validates, a positive error code number otherwise
1391 * and -1 in case of internal or API error.
1394 xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar *value,
1395 xmlSchemaValPtr *val, xmlNodePtr node, int flags) {
1397 xmlChar *norm = NULL;
1400 if (xmlSchemaTypesInitialized == 0)
1407 if ((flags == 0) && (value != NULL)) {
1408 if ((type->flags != XML_SCHEMAS_STRING) &&
1409 (type->flags != XML_SCHEMAS_NORMSTRING)) {
1410 norm = xmlSchemaCollapseString(value);
1416 switch (type->flags) {
1417 case XML_SCHEMAS_UNKNOWN:
1418 if (type == xmlSchemaTypeAnyTypeDef)
1421 case XML_SCHEMAS_STRING:
1423 case XML_SCHEMAS_NORMSTRING:
1426 case XML_SCHEMAS_DECIMAL: {
1427 const xmlChar *cur = value, *tmp;
1428 unsigned int frac = 0, len, neg = 0;
1429 unsigned long base = 0;
1434 else if (*cur == '-') {
1439 while ((*cur >= '0') && (*cur <= '9')) {
1440 base = base * 10 + (*cur - '0');
1447 while ((*cur >= '0') && (*cur <= '9')) {
1448 base = base * 10 + (*cur - '0');
1456 v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
1458 v->value.decimal.lo = base;
1459 v->value.decimal.sign = neg;
1460 v->value.decimal.frac = frac;
1461 v->value.decimal.total = frac + len;
1467 case XML_SCHEMAS_TIME:
1468 case XML_SCHEMAS_GDAY:
1469 case XML_SCHEMAS_GMONTH:
1470 case XML_SCHEMAS_GMONTHDAY:
1471 case XML_SCHEMAS_GYEAR:
1472 case XML_SCHEMAS_GYEARMONTH:
1473 case XML_SCHEMAS_DATE:
1474 case XML_SCHEMAS_DATETIME:
1475 ret = xmlSchemaValidateDates(type->flags, value, val);
1477 case XML_SCHEMAS_DURATION:
1478 ret = xmlSchemaValidateDuration(type, value, val);
1480 case XML_SCHEMAS_FLOAT:
1481 case XML_SCHEMAS_DOUBLE: {
1482 const xmlChar *cur = value;
1486 if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
1491 if (type == xmlSchemaTypeFloatDef) {
1492 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
1494 v->value.f = (float) xmlXPathNAN;
1496 xmlSchemaFreeValue(v);
1500 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
1502 v->value.d = xmlXPathNAN;
1504 xmlSchemaFreeValue(v);
1516 if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
1521 if (type == xmlSchemaTypeFloatDef) {
1522 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
1525 v->value.f = (float) xmlXPathNINF;
1527 v->value.f = (float) xmlXPathPINF;
1529 xmlSchemaFreeValue(v);
1533 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
1536 v->value.d = xmlXPathNINF;
1538 v->value.d = xmlXPathPINF;
1540 xmlSchemaFreeValue(v);
1548 if ((neg == 0) && (*cur == '+'))
1550 if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
1552 while ((*cur >= '0') && (*cur <= '9')) {
1557 while ((*cur >= '0') && (*cur <= '9'))
1560 if ((*cur == 'e') || (*cur == 'E')) {
1562 if ((*cur == '-') || (*cur == '+'))
1564 while ((*cur >= '0') && (*cur <= '9'))
1570 if (type == xmlSchemaTypeFloatDef) {
1571 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
1573 if (sscanf((const char *)value, "%f", &(v->value.f))==1) {
1576 xmlGenericError(xmlGenericErrorContext,
1577 "failed to scanf float %s\n", value);
1578 xmlSchemaFreeValue(v);
1585 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
1587 if (sscanf((const char *)value, "%lf", &(v->value.d))==1) {
1590 xmlGenericError(xmlGenericErrorContext,
1591 "failed to scanf double %s\n", value);
1592 xmlSchemaFreeValue(v);
1602 case XML_SCHEMAS_BOOLEAN: {
1603 const xmlChar *cur = value;
1605 if ((cur[0] == '0') && (cur[1] == 0))
1607 else if ((cur[0] == '1') && (cur[1] == 0))
1609 else if ((cur[0] == 't') && (cur[1] == 'r') && (cur[2] == 'u') &&
1610 (cur[3] == 'e') && (cur[4] == 0))
1612 else if ((cur[0] == 'f') && (cur[1] == 'a') && (cur[2] == 'l') &&
1613 (cur[3] == 's') && (cur[4] == 'e') && (cur[5] == 0))
1618 v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
1628 case XML_SCHEMAS_TOKEN: {
1629 const xmlChar *cur = value;
1635 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
1637 } else if (*cur == ' ') {
1648 v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
1650 v->value.str = xmlStrdup(value);
1658 case XML_SCHEMAS_LANGUAGE:
1659 if (xmlCheckLanguageID(value) == 1) {
1661 v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
1663 v->value.str = xmlStrdup(value);
1672 case XML_SCHEMAS_NMTOKEN:
1673 if (xmlValidateNMToken(value, 1) == 0) {
1675 v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
1677 v->value.str = xmlStrdup(value);
1686 case XML_SCHEMAS_NMTOKENS:
1687 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
1694 case XML_SCHEMAS_NAME:
1695 ret = xmlValidateName(value, 1);
1696 if ((ret == 0) && (val != NULL)) {
1700 case XML_SCHEMAS_QNAME: {
1701 xmlChar *uri = NULL;
1702 xmlChar *local = NULL;
1704 ret = xmlValidateQName(value, 1);
1705 if ((ret == 0) && (node != NULL)) {
1707 local = xmlSplitQName2(value, &prefix);
1708 if (prefix != NULL) {
1711 ns = xmlSearchNs(node->doc, node, prefix);
1714 else if (val != NULL)
1715 uri = xmlStrdup(ns->href);
1717 if ((local != NULL) && ((val == NULL) || (ret != 0)))
1722 if ((ret == 0) && (val != NULL)) {
1723 v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
1726 v->value.qname.name = local;
1728 v->value.qname.name = xmlStrdup(value);
1730 v->value.qname.uri = uri;
1743 case XML_SCHEMAS_NCNAME:
1744 ret = xmlValidateNCName(value, 1);
1745 if ((ret == 0) && (val != NULL)) {
1746 v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
1748 v->value.str = xmlStrdup(value);
1755 case XML_SCHEMAS_ID:
1756 ret = xmlValidateNCName(value, 1);
1757 if ((ret == 0) && (val != NULL)) {
1758 v = xmlSchemaNewValue(XML_SCHEMAS_ID);
1760 v->value.str = xmlStrdup(value);
1766 if ((ret == 0) && (node != NULL) &&
1767 (node->type == XML_ATTRIBUTE_NODE)) {
1768 xmlAttrPtr attr = (xmlAttrPtr) node;
1770 * NOTE: the IDness might have already be declared in the DTD
1772 if (attr->atype != XML_ATTRIBUTE_ID) {
1776 strip = xmlSchemaStrip(value);
1777 if (strip != NULL) {
1778 res = xmlAddID(NULL, node->doc, strip, attr);
1781 res = xmlAddID(NULL, node->doc, value, attr);
1785 attr->atype = XML_ATTRIBUTE_ID;
1790 case XML_SCHEMAS_IDREF:
1791 ret = xmlValidateNCName(value, 1);
1792 if ((ret == 0) && (val != NULL)) {
1795 if ((ret == 0) && (node != NULL) &&
1796 (node->type == XML_ATTRIBUTE_NODE)) {
1797 xmlAttrPtr attr = (xmlAttrPtr) node;
1800 strip = xmlSchemaStrip(value);
1801 if (strip != NULL) {
1802 xmlAddRef(NULL, node->doc, strip, attr);
1805 xmlAddRef(NULL, node->doc, value, attr);
1806 attr->atype = XML_ATTRIBUTE_IDREF;
1809 case XML_SCHEMAS_IDREFS:
1810 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
1816 if ((ret == 0) && (node != NULL) &&
1817 (node->type == XML_ATTRIBUTE_NODE)) {
1818 xmlAttrPtr attr = (xmlAttrPtr) node;
1820 attr->atype = XML_ATTRIBUTE_IDREFS;
1823 case XML_SCHEMAS_ENTITY: {
1825 ret = xmlValidateNCName(value, 1);
1826 if ((node == NULL) || (node->doc == NULL))
1831 strip = xmlSchemaStrip(value);
1832 if (strip != NULL) {
1833 ent = xmlGetDocEntity(node->doc, strip);
1836 ent = xmlGetDocEntity(node->doc, value);
1838 if ((ent == NULL) ||
1839 (ent->etype != XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
1842 if ((ret == 0) && (val != NULL)) {
1845 if ((ret == 0) && (node != NULL) &&
1846 (node->type == XML_ATTRIBUTE_NODE)) {
1847 xmlAttrPtr attr = (xmlAttrPtr) node;
1849 attr->atype = XML_ATTRIBUTE_ENTITY;
1853 case XML_SCHEMAS_ENTITIES:
1854 if ((node == NULL) || (node->doc == NULL))
1856 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
1862 if ((ret == 0) && (node != NULL) &&
1863 (node->type == XML_ATTRIBUTE_NODE)) {
1864 xmlAttrPtr attr = (xmlAttrPtr) node;
1866 attr->atype = XML_ATTRIBUTE_ENTITIES;
1869 case XML_SCHEMAS_NOTATION: {
1870 xmlChar *uri = NULL;
1871 xmlChar *local = NULL;
1873 ret = xmlValidateQName(value, 1);
1874 if ((ret == 0) && (node != NULL)) {
1876 local = xmlSplitQName2(value, &prefix);
1877 if (prefix != NULL) {
1880 ns = xmlSearchNs(node->doc, node, prefix);
1883 else if (val != NULL)
1884 uri = xmlStrdup(ns->href);
1886 if ((local != NULL) && ((val == NULL) || (ret != 0)))
1891 if ((node == NULL) || (node->doc == NULL))
1894 ret = xmlValidateNotationUse(NULL, node->doc, value);
1900 if ((ret == 0) && (val != NULL)) {
1901 v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
1904 v->value.qname.name = local;
1906 v->value.qname.name = xmlStrdup(value);
1908 v->value.qname.uri = uri;
1921 case XML_SCHEMAS_ANYURI: {
1924 uri = xmlParseURI((const char *) value);
1933 case XML_SCHEMAS_HEXBINARY: {
1934 const xmlChar *cur = value;
1941 while (((*cur >= '0') && (*cur <= '9')) ||
1942 ((*cur >= 'A') && (*cur <= 'F')) ||
1943 ((*cur >= 'a') && (*cur <= 'f'))) {
1954 v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
1958 cur = xmlStrdup(value);
1964 total = i / 2; /* number of octets */
1966 base = (xmlChar *)cur;
1969 *base = *base - ('a' - 'A');
1973 v->value.hex.str = (xmlChar *)cur;
1974 v->value.hex.total = total;
1979 case XML_SCHEMAS_INTEGER:
1980 case XML_SCHEMAS_PINTEGER:
1981 case XML_SCHEMAS_NPINTEGER:
1982 case XML_SCHEMAS_NINTEGER:
1983 case XML_SCHEMAS_NNINTEGER: {
1984 const xmlChar *cur = value;
1985 unsigned long lo, mi, hi;
1992 } else if (*cur == '+')
1994 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
1999 if (type->flags == XML_SCHEMAS_NPINTEGER) {
2001 ((hi != 0) || (mi != 0) || (lo != 0)))
2003 } else if (type->flags == XML_SCHEMAS_PINTEGER) {
2006 if ((hi == 0) && (mi == 0) && (lo == 0))
2008 } else if (type->flags == XML_SCHEMAS_NINTEGER) {
2011 if ((hi == 0) && (mi == 0) && (lo == 0))
2013 } else if (type->flags == XML_SCHEMAS_NNINTEGER) {
2015 ((hi != 0) || (mi != 0) || (lo != 0)))
2019 * We can store a value only if no overflow occured
2021 if ((ret > 0) && (val != NULL)) {
2022 v = xmlSchemaNewValue(type->flags);
2024 v->value.decimal.lo = lo;
2025 v->value.decimal.mi = lo;
2026 v->value.decimal.hi = lo;
2027 v->value.decimal.sign = sign;
2028 v->value.decimal.frac = 0;
2029 v->value.decimal.total = cur - value;
2035 case XML_SCHEMAS_LONG:
2036 case XML_SCHEMAS_BYTE:
2037 case XML_SCHEMAS_SHORT:
2038 case XML_SCHEMAS_INT: {
2039 const xmlChar *cur = value;
2040 unsigned long lo, mi, hi;
2048 } else if (*cur == '+')
2050 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
2055 if (type->flags == XML_SCHEMAS_LONG) {
2059 if (mi >= 33720368) {
2062 if ((sign == 0) && (lo > 54775807))
2064 if ((sign == 1) && (lo > 54775808))
2068 } else if (type->flags == XML_SCHEMAS_INT) {
2074 if ((sign == 0) && (lo > 47483647))
2076 if ((sign == 1) && (lo > 47483648))
2079 } else if (type->flags == XML_SCHEMAS_SHORT) {
2080 if ((mi != 0) || (hi != 0))
2082 if ((sign == 1) && (lo > 32768))
2084 if ((sign == 0) && (lo > 32767))
2086 } else if (type->flags == XML_SCHEMAS_BYTE) {
2087 if ((mi != 0) || (hi != 0))
2089 if ((sign == 1) && (lo > 128))
2091 if ((sign == 0) && (lo > 127))
2095 v = xmlSchemaNewValue(type->flags);
2097 v->value.decimal.lo = lo;
2098 v->value.decimal.mi = lo;
2099 v->value.decimal.hi = lo;
2100 v->value.decimal.sign = sign;
2101 v->value.decimal.frac = 0;
2102 v->value.decimal.total = total;
2108 case XML_SCHEMAS_UINT:
2109 case XML_SCHEMAS_ULONG:
2110 case XML_SCHEMAS_USHORT:
2111 case XML_SCHEMAS_UBYTE: {
2112 const xmlChar *cur = value;
2113 unsigned long lo, mi, hi;
2117 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
2122 if (type->flags == XML_SCHEMAS_ULONG) {
2126 if (mi >= 67440737) {
2133 } else if (type->flags == XML_SCHEMAS_UINT) {
2142 } else if (type->flags == XML_SCHEMAS_USHORT) {
2143 if ((mi != 0) || (hi != 0))
2147 } else if (type->flags == XML_SCHEMAS_UBYTE) {
2148 if ((mi != 0) || (hi != 0))
2154 v = xmlSchemaNewValue(type->flags);
2156 v->value.decimal.lo = lo;
2157 v->value.decimal.mi = mi;
2158 v->value.decimal.hi = hi;
2159 v->value.decimal.sign = 0;
2160 v->value.decimal.frac = 0;
2161 v->value.decimal.total = total;
2170 if (norm != NULL) xmlFree(norm);
2173 if (norm != NULL) xmlFree(norm);
2176 if (norm != NULL) xmlFree(norm);
2179 if (norm != NULL) xmlFree(norm);
2182 if (norm != NULL) xmlFree(norm);
2187 * xmlSchemaValPredefTypeNode:
2188 * @type: the predefined type
2189 * @value: the value to check
2190 * @val: the return computed value
2191 * @node: the node containing the value
2193 * Check that a value conforms to the lexical space of the predefined type.
2194 * if true a value is computed and returned in @val.
2196 * Returns 0 if this validates, a positive error code number otherwise
2197 * and -1 in case of internal or API error.
2200 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
2201 xmlSchemaValPtr *val, xmlNodePtr node) {
2202 return(xmlSchemaValAtomicType(type, value, val, node, 0));
2206 * xmlSchemaValidatePredefinedType:
2207 * @type: the predefined type
2208 * @value: the value to check
2209 * @val: the return computed value
2211 * Check that a value conforms to the lexical space of the predefined type.
2212 * if true a value is computed and returned in @val.
2214 * Returns 0 if this validates, a positive error code number otherwise
2215 * and -1 in case of internal or API error.
2218 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
2219 xmlSchemaValPtr *val) {
2220 return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
2224 * xmlSchemaCompareDecimals:
2225 * @x: a first decimal value
2226 * @y: a second decimal value
2228 * Compare 2 decimals
2230 * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
2233 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
2235 xmlSchemaValPtr swp;
2239 if ((x->value.decimal.sign) &&
2240 ((x->value.decimal.lo != 0) ||
2241 (x->value.decimal.mi != 0) ||
2242 (x->value.decimal.hi != 0))) {
2243 if ((y->value.decimal.sign) &&
2244 ((y->value.decimal.lo != 0) ||
2245 (y->value.decimal.mi != 0) ||
2246 (y->value.decimal.hi != 0)))
2250 } else if ((y->value.decimal.sign) &&
2251 ((y->value.decimal.lo != 0) ||
2252 (y->value.decimal.mi != 0) ||
2253 (y->value.decimal.hi != 0))) {
2256 if (x->value.decimal.frac == y->value.decimal.frac) {
2257 if (x->value.decimal.hi < y->value.decimal.hi)
2259 if (x->value.decimal.hi < y->value.decimal.hi)
2261 if (x->value.decimal.mi < y->value.decimal.mi)
2263 if (x->value.decimal.mi < y->value.decimal.mi)
2265 if (x->value.decimal.lo < y->value.decimal.lo)
2267 if (x->value.decimal.lo > y->value.decimal.lo)
2271 if (y->value.decimal.frac > x->value.decimal.frac) {
2277 p = powten[x->value.decimal.frac - y->value.decimal.frac];
2278 tmp = x->value.decimal.lo / p;
2279 if (tmp > y->value.decimal.lo)
2281 if (tmp < y->value.decimal.lo)
2283 tmp = y->value.decimal.lo * p;
2284 if (x->value.decimal.lo < tmp)
2286 if (x->value.decimal.lo == tmp)
2292 * xmlSchemaCompareDurations:
2293 * @x: a first duration value
2294 * @y: a second duration value
2296 * Compare 2 durations
2298 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
2302 xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
2304 long carry, mon, day;
2307 long xmon, xday, myear, minday, maxday;
2308 static const long dayRange [2][12] = {
2309 { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
2310 { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
2312 if ((x == NULL) || (y == NULL))
2316 mon = x->value.dur.mon - y->value.dur.mon;
2319 sec = x->value.dur.sec - y->value.dur.sec;
2320 carry = (long)sec / SECS_PER_DAY;
2321 sec -= (double)(carry * SECS_PER_DAY);
2324 day = x->value.dur.day - y->value.dur.day + carry;
2342 if ((day >= 0) && (sec >= 0.0))
2348 } else if ((day <= 0) && (sec <= 0.0)) {
2361 maxday = 366 * ((myear + 3) / 4) +
2362 365 * ((myear - 1) % 4);
2363 minday = maxday - 1;
2367 minday += dayRange[0][xmon];
2368 maxday += dayRange[1][xmon];
2370 if ((maxday == minday) && (maxday == xday))
2371 return(0); /* can this really happen ? */
2382 * macros for adding date/times and durations
2384 #define FQUOTIENT(a,b) (floor(((double)a/(double)b)))
2385 #define MODULO(a,b) (a - FQUOTIENT(a,b) * b)
2386 #define FQUOTIENT_RANGE(a,low,high) (FQUOTIENT((a-low),(high-low)))
2387 #define MODULO_RANGE(a,low,high) ((MODULO((a-low),(high-low)))+low)
2390 * _xmlSchemaDateAdd:
2391 * @dt: an #xmlSchemaValPtr
2392 * @dur: an #xmlSchemaValPtr of type #XS_DURATION
2394 * Compute a new date/time from @dt and @dur. This function assumes @dt
2395 * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
2396 * or #XML_SCHEMAS_GYEAR.
2398 * Returns date/time pointer or NULL.
2400 static xmlSchemaValPtr
2401 _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
2403 xmlSchemaValPtr ret;
2404 long carry, tempdays, temp;
2405 xmlSchemaValDatePtr r, d;
2406 xmlSchemaValDurationPtr u;
2408 if ((dt == NULL) || (dur == NULL))
2411 ret = xmlSchemaNewValue(dt->type);
2415 r = &(ret->value.date);
2416 d = &(dt->value.date);
2417 u = &(dur->value.dur);
2423 /* normalize for time zone offset */
2424 u->sec -= (d->tzo * 60);
2432 carry = d->mon + u->mon;
2433 r->mon = MODULO_RANGE(carry, 1, 13);
2434 carry = FQUOTIENT_RANGE(carry, 1, 13);
2436 /* year (may be modified later) */
2437 r->year = d->year + carry;
2447 r->tz_flag = d->tz_flag;
2450 r->sec = d->sec + u->sec;
2451 carry = FQUOTIENT((long)r->sec, 60);
2452 if (r->sec != 0.0) {
2453 r->sec = MODULO(r->sec, 60.0);
2458 r->min = MODULO(carry, 60);
2459 carry = FQUOTIENT(carry, 60);
2463 r->hour = MODULO(carry, 24);
2464 carry = FQUOTIENT(carry, 24);
2468 * Note we use tempdays because the temporary values may need more
2471 if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
2472 (d->day > MAX_DAYINMONTH(r->year, r->mon)))
2473 tempdays = MAX_DAYINMONTH(r->year, r->mon);
2474 else if (d->day < 1)
2479 tempdays += u->day + carry;
2483 long tmon = MODULO_RANGE(r->mon-1, 1, 13);
2484 long tyr = r->year + FQUOTIENT_RANGE(r->mon-1, 1, 13);
2487 tempdays += MAX_DAYINMONTH(tyr, tmon);
2489 } else if (tempdays > MAX_DAYINMONTH(r->year, r->mon)) {
2490 tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
2495 temp = r->mon + carry;
2496 r->mon = MODULO_RANGE(temp, 1, 13);
2497 r->year = r->year + FQUOTIENT_RANGE(temp, 1, 13);
2509 * adjust the date/time type to the date values
2511 if (ret->type != XML_SCHEMAS_DATETIME) {
2512 if ((r->hour) || (r->min) || (r->sec))
2513 ret->type = XML_SCHEMAS_DATETIME;
2514 else if (ret->type != XML_SCHEMAS_DATE) {
2515 if ((r->mon != 1) && (r->day != 1))
2516 ret->type = XML_SCHEMAS_DATE;
2517 else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
2518 ret->type = XML_SCHEMAS_GYEARMONTH;
2527 * @v: value to duplicate
2529 * returns a duplicated value.
2531 static xmlSchemaValPtr
2532 xmlSchemaDupVal (xmlSchemaValPtr v)
2534 xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
2538 memcpy(ret, v, sizeof(xmlSchemaVal));
2543 * xmlSchemaDateNormalize:
2544 * @dt: an #xmlSchemaValPtr
2546 * Normalize @dt to GMT time.
2549 static xmlSchemaValPtr
2550 xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
2552 xmlSchemaValPtr dur, ret;
2557 if (((dt->type != XML_SCHEMAS_TIME) &&
2558 (dt->type != XML_SCHEMAS_DATETIME)) || (dt->value.date.tzo == 0))
2559 return xmlSchemaDupVal(dt);
2561 dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
2565 dur->value.date.sec -= offset;
2567 ret = _xmlSchemaDateAdd(dt, dur);
2571 xmlSchemaFreeValue(dur);
2573 /* ret->value.date.tzo = 0; */
2578 * _xmlSchemaDateCastYMToDays:
2579 * @dt: an #xmlSchemaValPtr
2581 * Convert mon and year of @dt to total number of days. Take the
2582 * number of years since (or before) 1 AD and add the number of leap
2583 * years. This is a function because negative
2584 * years must be handled a little differently and there is no zero year.
2586 * Returns number of days.
2589 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
2593 if (dt->value.date.year < 0)
2594 ret = (dt->value.date.year * 365) +
2595 (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
2596 ((dt->value.date.year+1)/400)) +
2597 DAY_IN_YEAR(0, dt->value.date.mon, dt->value.date.year);
2599 ret = ((dt->value.date.year-1) * 365) +
2600 (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
2601 ((dt->value.date.year-1)/400)) +
2602 DAY_IN_YEAR(0, dt->value.date.mon, dt->value.date.year);
2609 * @dt: an #xmlSchemaValPtr
2611 * Calculates the number of seconds in the time portion of @dt.
2615 #define TIME_TO_NUMBER(dt) \
2616 ((double)((dt->value.date.hour * SECS_PER_HOUR) + \
2617 (dt->value.date.min * SECS_PER_MIN) + \
2618 (dt->value.date.tzo * SECS_PER_MIN)) + \
2622 * xmlSchemaCompareDates:
2623 * @x: a first date/time value
2624 * @y: a second date/time value
2626 * Compare 2 date/times
2628 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
2632 xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
2634 unsigned char xmask, ymask, xor_mask, and_mask;
2635 xmlSchemaValPtr p1, p2, q1, q2;
2636 long p1d, p2d, q1d, q2d;
2638 if ((x == NULL) || (y == NULL))
2641 if (x->value.date.tz_flag) {
2643 if (!y->value.date.tz_flag) {
2644 p1 = xmlSchemaDateNormalize(x, 0);
2645 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
2646 /* normalize y + 14:00 */
2647 q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
2649 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
2651 xmlSchemaFreeValue(p1);
2652 xmlSchemaFreeValue(q1);
2654 } else if (p1d == q1d) {
2657 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
2659 xmlSchemaFreeValue(p1);
2660 xmlSchemaFreeValue(q1);
2663 /* normalize y - 14:00 */
2664 q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
2665 q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
2666 xmlSchemaFreeValue(p1);
2667 xmlSchemaFreeValue(q1);
2668 xmlSchemaFreeValue(q2);
2671 else if (p1d == q2d) {
2672 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
2676 return 2; /* indeterminate */
2680 xmlSchemaFreeValue(p1);
2681 xmlSchemaFreeValue(q1);
2684 } else if (y->value.date.tz_flag) {
2685 q1 = xmlSchemaDateNormalize(y, 0);
2686 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
2688 /* normalize x - 14:00 */
2689 p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
2690 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
2693 xmlSchemaFreeValue(p1);
2694 xmlSchemaFreeValue(q1);
2696 } else if (p1d == q1d) {
2699 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
2701 xmlSchemaFreeValue(p1);
2702 xmlSchemaFreeValue(q1);
2705 /* normalize x + 14:00 */
2706 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
2707 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
2710 xmlSchemaFreeValue(p1);
2711 xmlSchemaFreeValue(q1);
2712 xmlSchemaFreeValue(p2);
2714 } else if (p2d == q1d) {
2715 sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
2716 xmlSchemaFreeValue(p1);
2717 xmlSchemaFreeValue(q1);
2718 xmlSchemaFreeValue(p2);
2722 return 2; /* indeterminate */
2724 xmlSchemaFreeValue(p1);
2725 xmlSchemaFreeValue(q1);
2726 xmlSchemaFreeValue(p2);
2729 xmlSchemaFreeValue(p1);
2730 xmlSchemaFreeValue(q1);
2735 * if the same type then calculate the difference
2737 if (x->type == y->type) {
2738 q1 = xmlSchemaDateNormalize(y, 0);
2739 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
2741 p1 = xmlSchemaDateNormalize(x, 0);
2742 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
2745 xmlSchemaFreeValue(p1);
2746 xmlSchemaFreeValue(q1);
2748 } else if (p1d > q1d) {
2749 xmlSchemaFreeValue(p1);
2750 xmlSchemaFreeValue(q1);
2755 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
2756 xmlSchemaFreeValue(p1);
2757 xmlSchemaFreeValue(q1);
2768 case XML_SCHEMAS_DATETIME:
2771 case XML_SCHEMAS_DATE:
2774 case XML_SCHEMAS_GYEAR:
2777 case XML_SCHEMAS_GMONTH:
2780 case XML_SCHEMAS_GDAY:
2783 case XML_SCHEMAS_GYEARMONTH:
2786 case XML_SCHEMAS_GMONTHDAY:
2789 case XML_SCHEMAS_TIME:
2798 case XML_SCHEMAS_DATETIME:
2801 case XML_SCHEMAS_DATE:
2804 case XML_SCHEMAS_GYEAR:
2807 case XML_SCHEMAS_GMONTH:
2810 case XML_SCHEMAS_GDAY:
2813 case XML_SCHEMAS_GYEARMONTH:
2816 case XML_SCHEMAS_GMONTHDAY:
2819 case XML_SCHEMAS_TIME:
2827 xor_mask = xmask ^ ymask; /* mark type differences */
2828 and_mask = xmask & ymask; /* mark field specification */
2832 return 2; /* indeterminate */
2833 else if (and_mask & 1) {
2834 if (x->value.date.year < y->value.date.year)
2836 else if (x->value.date.year > y->value.date.year)
2842 return 2; /* indeterminate */
2843 else if (and_mask & 2) {
2844 if (x->value.date.mon < y->value.date.mon)
2846 else if (x->value.date.mon > y->value.date.mon)
2852 return 2; /* indeterminate */
2853 else if (and_mask & 4) {
2854 if (x->value.date.day < y->value.date.day)
2856 else if (x->value.date.day > y->value.date.day)
2862 return 2; /* indeterminate */
2863 else if (and_mask & 8) {
2864 if (x->value.date.hour < y->value.date.hour)
2866 else if (x->value.date.hour > y->value.date.hour)
2868 else if (x->value.date.min < y->value.date.min)
2870 else if (x->value.date.min > y->value.date.min)
2872 else if (x->value.date.sec < y->value.date.sec)
2874 else if (x->value.date.sec > y->value.date.sec)
2882 * xmlSchemaCompareNormStrings:
2883 * @x: a first string value
2884 * @y: a second string value
2886 * Compare 2 string for their normalized values.
2888 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
2892 xmlSchemaCompareNormStrings(xmlSchemaValPtr x, xmlSchemaValPtr y) {
2893 const xmlChar *utf1;
2894 const xmlChar *utf2;
2897 if ((x == NULL) || (y == NULL))
2899 utf1 = x->value.str;
2900 utf2 = y->value.str;
2902 while (IS_BLANK(*utf1)) utf1++;
2903 while (IS_BLANK(*utf2)) utf2++;
2904 while ((*utf1 != 0) && (*utf2 != 0)) {
2905 if (IS_BLANK(*utf1)) {
2906 if (!IS_BLANK(*utf2)) {
2907 tmp = *utf1 - *utf2;
2910 while (IS_BLANK(*utf1)) utf1++;
2911 while (IS_BLANK(*utf2)) utf2++;
2913 tmp = *utf1++ - *utf2++;
2921 while (IS_BLANK(*utf1)) utf1++;
2926 while (IS_BLANK(*utf2)) utf2++;
2934 * xmlSchemaCompareFloats:
2935 * @x: a first float or double value
2936 * @y: a second float or double value
2940 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
2944 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
2947 if ((x == NULL) || (y == NULL))
2951 * Cast everything to doubles.
2953 if (x->type == XML_SCHEMAS_DOUBLE)
2955 else if (x->type == XML_SCHEMAS_FLOAT)
2960 if (y->type == XML_SCHEMAS_DOUBLE)
2962 else if (y->type == XML_SCHEMAS_FLOAT)
2968 * Check for special cases.
2970 if (xmlXPathIsNaN(d1)) {
2971 if (xmlXPathIsNaN(d2))
2975 if (xmlXPathIsNaN(d2))
2977 if (d1 == xmlXPathPINF) {
2978 if (d2 == xmlXPathPINF)
2982 if (d2 == xmlXPathPINF)
2984 if (d1 == xmlXPathNINF) {
2985 if (d2 == xmlXPathNINF)
2989 if (d2 == xmlXPathNINF)
2993 * basic tests, the last one we should have equality, but
2994 * portability is more important than speed and handling
2995 * NaN or Inf in a portable way is always a challenge, so ...
3007 * xmlSchemaCompareValues:
3009 * @y: a second value
3013 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3017 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
3018 if ((x == NULL) || (y == NULL))
3022 case XML_SCHEMAS_UNKNOWN:
3024 case XML_SCHEMAS_INTEGER:
3025 case XML_SCHEMAS_NPINTEGER:
3026 case XML_SCHEMAS_NINTEGER:
3027 case XML_SCHEMAS_NNINTEGER:
3028 case XML_SCHEMAS_PINTEGER:
3029 case XML_SCHEMAS_INT:
3030 case XML_SCHEMAS_UINT:
3031 case XML_SCHEMAS_LONG:
3032 case XML_SCHEMAS_ULONG:
3033 case XML_SCHEMAS_SHORT:
3034 case XML_SCHEMAS_USHORT:
3035 case XML_SCHEMAS_BYTE:
3036 case XML_SCHEMAS_UBYTE:
3037 case XML_SCHEMAS_DECIMAL:
3038 if (y->type == x->type)
3039 return(xmlSchemaCompareDecimals(x, y));
3040 if ((y->type == XML_SCHEMAS_DECIMAL) ||
3041 (y->type == XML_SCHEMAS_INTEGER) ||
3042 (y->type == XML_SCHEMAS_NPINTEGER) ||
3043 (y->type == XML_SCHEMAS_NINTEGER) ||
3044 (y->type == XML_SCHEMAS_NNINTEGER) ||
3045 (y->type == XML_SCHEMAS_PINTEGER) ||
3046 (y->type == XML_SCHEMAS_INT) ||
3047 (y->type == XML_SCHEMAS_UINT) ||
3048 (y->type == XML_SCHEMAS_LONG) ||
3049 (y->type == XML_SCHEMAS_ULONG) ||
3050 (y->type == XML_SCHEMAS_SHORT) ||
3051 (y->type == XML_SCHEMAS_USHORT) ||
3052 (y->type == XML_SCHEMAS_BYTE) ||
3053 (y->type == XML_SCHEMAS_UBYTE))
3054 return(xmlSchemaCompareDecimals(x, y));
3056 case XML_SCHEMAS_DURATION:
3057 if (y->type == XML_SCHEMAS_DURATION)
3058 return(xmlSchemaCompareDurations(x, y));
3060 case XML_SCHEMAS_TIME:
3061 case XML_SCHEMAS_GDAY:
3062 case XML_SCHEMAS_GMONTH:
3063 case XML_SCHEMAS_GMONTHDAY:
3064 case XML_SCHEMAS_GYEAR:
3065 case XML_SCHEMAS_GYEARMONTH:
3066 case XML_SCHEMAS_DATE:
3067 case XML_SCHEMAS_DATETIME:
3068 if ((y->type == XML_SCHEMAS_DATETIME) ||
3069 (y->type == XML_SCHEMAS_TIME) ||
3070 (y->type == XML_SCHEMAS_GDAY) ||
3071 (y->type == XML_SCHEMAS_GMONTH) ||
3072 (y->type == XML_SCHEMAS_GMONTHDAY) ||
3073 (y->type == XML_SCHEMAS_GYEAR) ||
3074 (y->type == XML_SCHEMAS_DATE) ||
3075 (y->type == XML_SCHEMAS_GYEARMONTH))
3076 return (xmlSchemaCompareDates(x, y));
3078 case XML_SCHEMAS_NORMSTRING:
3079 case XML_SCHEMAS_TOKEN:
3080 case XML_SCHEMAS_LANGUAGE:
3081 case XML_SCHEMAS_NMTOKEN:
3082 case XML_SCHEMAS_NAME:
3083 case XML_SCHEMAS_NCNAME:
3084 case XML_SCHEMAS_ID:
3085 case XML_SCHEMAS_IDREF:
3086 case XML_SCHEMAS_ENTITY:
3087 case XML_SCHEMAS_NOTATION:
3088 case XML_SCHEMAS_ANYURI:
3089 if ((y->type == XML_SCHEMAS_NORMSTRING) ||
3090 (y->type == XML_SCHEMAS_TOKEN) ||
3091 (y->type == XML_SCHEMAS_LANGUAGE) ||
3092 (y->type == XML_SCHEMAS_NMTOKEN) ||
3093 (y->type == XML_SCHEMAS_NAME) ||
3094 (y->type == XML_SCHEMAS_QNAME) ||
3095 (y->type == XML_SCHEMAS_NCNAME) ||
3096 (y->type == XML_SCHEMAS_ID) ||
3097 (y->type == XML_SCHEMAS_IDREF) ||
3098 (y->type == XML_SCHEMAS_ENTITY) ||
3099 (y->type == XML_SCHEMAS_NOTATION) ||
3100 (y->type == XML_SCHEMAS_ANYURI))
3101 return (xmlSchemaCompareNormStrings(x, y));
3103 case XML_SCHEMAS_QNAME:
3104 if (y->type == XML_SCHEMAS_QNAME) {
3105 if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
3106 (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
3111 case XML_SCHEMAS_FLOAT:
3112 case XML_SCHEMAS_DOUBLE:
3113 if ((y->type == XML_SCHEMAS_FLOAT) ||
3114 (y->type == XML_SCHEMAS_DOUBLE))
3115 return (xmlSchemaCompareFloats(x, y));
3117 case XML_SCHEMAS_BOOLEAN:
3118 if (y->type == XML_SCHEMAS_BOOLEAN) {
3119 if (x->value.b == y->value.b)
3121 if (x->value.b == 0)
3126 case XML_SCHEMAS_HEXBINARY:
3127 if (y->type == XML_SCHEMAS_HEXBINARY) {
3128 if (x->value.hex.total == y->value.hex.total) {
3129 int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
3135 else if (x->value.hex.total > y->value.hex.total)
3141 case XML_SCHEMAS_STRING:
3142 case XML_SCHEMAS_IDREFS:
3143 case XML_SCHEMAS_ENTITIES:
3144 case XML_SCHEMAS_NMTOKENS:
3155 * Computes the UTF8 length of the normalized value of the string
3157 * Returns the length or -1 in case of error.
3160 xmlSchemaNormLen(const xmlChar *value) {
3167 while (IS_BLANK(*utf)) utf++;
3169 if (utf[0] & 0x80) {
3170 if ((utf[1] & 0xc0) != 0x80)
3172 if ((utf[0] & 0xe0) == 0xe0) {
3173 if ((utf[2] & 0xc0) != 0x80)
3175 if ((utf[0] & 0xf0) == 0xf0) {
3176 if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
3185 } else if (IS_BLANK(*utf)) {
3186 while (IS_BLANK(*utf)) utf++;
3198 * xmlSchemaValidateFacet:
3199 * @base: the base type
3200 * @facet: the facet to check
3201 * @value: the lexical repr of the value to validate
3202 * @val: the precomputed value
3204 * Check a value against a facet condition
3206 * Returns 0 if the element is schemas valid, a positive error code
3207 * number otherwise and -1 in case of internal or API error.
3210 xmlSchemaValidateFacet(xmlSchemaTypePtr base ATTRIBUTE_UNUSED,
3211 xmlSchemaFacetPtr facet,
3212 const xmlChar *value, xmlSchemaValPtr val)
3216 switch (facet->type) {
3217 case XML_SCHEMA_FACET_PATTERN:
3218 ret = xmlRegexpExec(facet->regexp, value);
3222 /* TODO error code */
3226 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3227 ret = xmlSchemaCompareValues(val, facet->val);
3229 /* TODO error code */
3236 case XML_SCHEMA_FACET_MAXINCLUSIVE:
3237 ret = xmlSchemaCompareValues(val, facet->val);
3239 /* TODO error code */
3242 if ((ret == -1) || (ret == 0))
3246 case XML_SCHEMA_FACET_MINEXCLUSIVE:
3247 ret = xmlSchemaCompareValues(val, facet->val);
3249 /* TODO error code */
3256 case XML_SCHEMA_FACET_MININCLUSIVE:
3257 ret = xmlSchemaCompareValues(val, facet->val);
3259 /* TODO error code */
3262 if ((ret == 1) || (ret == 0))
3266 case XML_SCHEMA_FACET_WHITESPACE:
3267 /* TODO whitespaces */
3269 case XML_SCHEMA_FACET_ENUMERATION:
3270 if ((facet->value != NULL) &&
3271 (xmlStrEqual(facet->value, value)))
3274 case XML_SCHEMA_FACET_LENGTH:
3275 case XML_SCHEMA_FACET_MAXLENGTH:
3276 case XML_SCHEMA_FACET_MINLENGTH: {
3277 unsigned int len = 0;
3279 if ((facet->val == NULL) ||
3280 ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
3281 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
3282 (facet->val->value.decimal.frac != 0)) {
3285 if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
3286 len = val->value.hex.total;
3288 switch (base->flags) {
3289 case XML_SCHEMAS_IDREF:
3290 case XML_SCHEMAS_NORMSTRING:
3291 case XML_SCHEMAS_TOKEN:
3292 case XML_SCHEMAS_LANGUAGE:
3293 case XML_SCHEMAS_NMTOKEN:
3294 case XML_SCHEMAS_NAME:
3295 case XML_SCHEMAS_NCNAME:
3296 case XML_SCHEMAS_ID:
3297 len = xmlSchemaNormLen(value);
3299 case XML_SCHEMAS_STRING:
3300 len = xmlUTF8Strlen(value);
3306 if (facet->type == XML_SCHEMA_FACET_LENGTH) {
3307 if (len != facet->val->value.decimal.lo)
3309 } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
3310 if (len < facet->val->value.decimal.lo)
3313 if (len > facet->val->value.decimal.lo)
3318 case XML_SCHEMA_FACET_TOTALDIGITS:
3319 case XML_SCHEMA_FACET_FRACTIONDIGITS:
3321 if ((facet->val == NULL) ||
3322 ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
3323 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
3324 (facet->val->value.decimal.frac != 0)) {
3327 if ((val == NULL) ||
3328 ((val->type != XML_SCHEMAS_DECIMAL) &&
3329 (val->type != XML_SCHEMAS_INTEGER) &&
3330 (val->type != XML_SCHEMAS_NPINTEGER) &&
3331 (val->type != XML_SCHEMAS_NINTEGER) &&
3332 (val->type != XML_SCHEMAS_NNINTEGER) &&
3333 (val->type != XML_SCHEMAS_PINTEGER) &&
3334 (val->type != XML_SCHEMAS_INT) &&
3335 (val->type != XML_SCHEMAS_UINT) &&
3336 (val->type != XML_SCHEMAS_LONG) &&
3337 (val->type != XML_SCHEMAS_ULONG) &&
3338 (val->type != XML_SCHEMAS_SHORT) &&
3339 (val->type != XML_SCHEMAS_USHORT) &&
3340 (val->type != XML_SCHEMAS_BYTE) &&
3341 (val->type != XML_SCHEMAS_UBYTE))) {
3344 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
3345 if (val->value.decimal.total > facet->val->value.decimal.lo)
3348 } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
3349 if (val->value.decimal.frac > facet->val->value.decimal.lo)
3360 #endif /* LIBXML_SCHEMAS_ENABLED */