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>
10 /* To avoid EBCDIC trouble when parsing on zOS */
12 #pragma convert("ISO8859-1")
18 #ifdef LIBXML_SCHEMAS_ENABLED
21 #include <libxml/xmlmemory.h>
22 #include <libxml/parser.h>
23 #include <libxml/parserInternals.h>
24 #include <libxml/hash.h>
25 #include <libxml/valid.h>
26 #include <libxml/xpath.h>
27 #include <libxml/uri.h>
29 #include <libxml/xmlschemas.h>
30 #include <libxml/schemasInternals.h>
31 #include <libxml/xmlschemastypes.h>
42 #ifndef LIBXML_XPATH_ENABLED
43 extern double xmlXPathNAN;
44 extern double xmlXPathPINF;
45 extern double xmlXPathNINF;
49 xmlGenericError(xmlGenericErrorContext, \
50 "Unimplemented block at %s:%d\n", \
53 #define XML_SCHEMAS_NAMESPACE_NAME \
54 (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
56 #define IS_WSP_REPLACE_CH(c) ((((c) == 0x9) || ((c) == 0xa)) || \
59 #define IS_WSP_SPACE_CH(c) ((c) == 0x20)
61 #define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c)
64 typedef struct _xmlSchemaValDate xmlSchemaValDate;
65 typedef xmlSchemaValDate *xmlSchemaValDatePtr;
66 struct _xmlSchemaValDate {
68 unsigned int mon :4; /* 1 <= mon <= 12 */
69 unsigned int day :5; /* 1 <= day <= 31 */
70 unsigned int hour :5; /* 0 <= hour <= 24 */
71 unsigned int min :6; /* 0 <= min <= 59 */
73 unsigned int tz_flag :1; /* is tzo explicitely set? */
74 signed int tzo :12; /* -1440 <= tzo <= 1440;
75 currently only -840 to +840 are needed */
79 typedef struct _xmlSchemaValDuration xmlSchemaValDuration;
80 typedef xmlSchemaValDuration *xmlSchemaValDurationPtr;
81 struct _xmlSchemaValDuration {
82 long mon; /* mon stores years also */
84 double sec; /* sec stores min and hour also */
87 typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
88 typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
89 struct _xmlSchemaValDecimal {
90 /* would use long long but not portable */
100 typedef struct _xmlSchemaValQName xmlSchemaValQName;
101 typedef xmlSchemaValQName *xmlSchemaValQNamePtr;
102 struct _xmlSchemaValQName {
107 typedef struct _xmlSchemaValHex xmlSchemaValHex;
108 typedef xmlSchemaValHex *xmlSchemaValHexPtr;
109 struct _xmlSchemaValHex {
114 typedef struct _xmlSchemaValBase64 xmlSchemaValBase64;
115 typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr;
116 struct _xmlSchemaValBase64 {
121 struct _xmlSchemaVal {
122 xmlSchemaValType type;
123 struct _xmlSchemaVal *next;
125 xmlSchemaValDecimal decimal;
126 xmlSchemaValDate date;
127 xmlSchemaValDuration dur;
128 xmlSchemaValQName qname;
130 xmlSchemaValBase64 base64;
138 static int xmlSchemaTypesInitialized = 0;
139 static xmlHashTablePtr xmlSchemaTypesBank = NULL;
144 static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL;
145 static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL;
146 static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL;
147 static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL;
148 static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL;
149 static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL;
150 static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL;
151 static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL;
152 static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL;
153 static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL;
154 static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL;
155 static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL;
156 static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL;
157 static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
158 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
159 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
160 static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
161 static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL;
162 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
167 static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL;
168 static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL;
169 static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL;
170 static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL;
171 static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL;
172 static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL;
173 static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL;
174 static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL;
175 static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL;
176 static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL;
177 static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL;
178 static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL;
179 static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL;
180 static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL;
181 static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL;
182 static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL;
183 static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
184 static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
185 static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL;
186 static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL;
187 static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL;
188 static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL;
189 static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL;
190 static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL;
191 static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL;
192 static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL;
193 static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
195 /************************************************************************
197 * Datatype error handlers *
199 ************************************************************************/
201 * xmlSchemaTypeErrMemory:
202 * @extra: extra informations
204 * Handle an out of memory condition
207 xmlSchemaTypeErrMemory(xmlNodePtr node, const char *extra)
209 __xmlSimpleError(XML_FROM_DATATYPE, XML_ERR_NO_MEMORY, node, NULL, extra);
212 /************************************************************************
214 * Base types support *
216 ************************************************************************/
220 * @type: the value type
222 * Allocate a new simple type value
224 * Returns a pointer to the new value or NULL in case of error
226 static xmlSchemaValPtr
227 xmlSchemaNewValue(xmlSchemaValType type) {
228 xmlSchemaValPtr value;
230 value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
234 memset(value, 0, sizeof(xmlSchemaVal));
239 static xmlSchemaFacetPtr
240 xmlSchemaNewMinLengthFacet(int value)
242 xmlSchemaFacetPtr ret;
244 ret = xmlSchemaNewFacet();
248 ret->type = XML_SCHEMA_FACET_MINLENGTH;
249 ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER);
250 if (ret->val == NULL) {
254 ret->val->value.decimal.lo = value;
259 * xmlSchemaInitBasicType:
260 * @name: the type name
261 * @type: the value type associated
263 * Initialize one primitive built-in type
265 static xmlSchemaTypePtr
266 xmlSchemaInitBasicType(const char *name, xmlSchemaValType type,
267 xmlSchemaTypePtr baseType) {
268 xmlSchemaTypePtr ret;
270 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
272 xmlSchemaTypeErrMemory(NULL, "could not initialize basic types");
275 memset(ret, 0, sizeof(xmlSchemaType));
276 ret->name = (const xmlChar *)name;
277 ret->targetNamespace = XML_SCHEMAS_NAMESPACE_NAME;
278 ret->type = XML_SCHEMA_TYPE_BASIC;
279 ret->baseType = baseType;
280 ret->contentType = XML_SCHEMA_CONTENT_BASIC;
285 case XML_SCHEMAS_STRING:
286 case XML_SCHEMAS_DECIMAL:
287 case XML_SCHEMAS_DATE:
288 case XML_SCHEMAS_DATETIME:
289 case XML_SCHEMAS_TIME:
290 case XML_SCHEMAS_GYEAR:
291 case XML_SCHEMAS_GYEARMONTH:
292 case XML_SCHEMAS_GMONTH:
293 case XML_SCHEMAS_GMONTHDAY:
294 case XML_SCHEMAS_GDAY:
295 case XML_SCHEMAS_DURATION:
296 case XML_SCHEMAS_FLOAT:
297 case XML_SCHEMAS_DOUBLE:
298 case XML_SCHEMAS_BOOLEAN:
299 case XML_SCHEMAS_ANYURI:
300 case XML_SCHEMAS_HEXBINARY:
301 case XML_SCHEMAS_BASE64BINARY:
302 case XML_SCHEMAS_QNAME:
303 case XML_SCHEMAS_NOTATION:
304 ret->flags |= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE;
313 case XML_SCHEMAS_ANYTYPE:
314 case XML_SCHEMAS_ANYSIMPLETYPE:
316 case XML_SCHEMAS_IDREFS:
317 case XML_SCHEMAS_NMTOKENS:
318 case XML_SCHEMAS_ENTITIES:
319 ret->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
320 ret->facets = xmlSchemaNewMinLengthFacet(1);
321 ret->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
324 ret->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
327 xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
328 XML_SCHEMAS_NAMESPACE_NAME, ret);
329 ret->builtInType = type;
334 * WARNING: Those type reside normally in xmlschemas.c but are
335 * redefined here locally in oder of being able to use them for xs:anyType-
336 * TODO: Remove those definition if we move the types to a header file.
337 * TODO: Always keep those structs up-to-date with the originals.
339 #define UNBOUNDED (1 << 30)
341 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
342 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
343 struct _xmlSchemaTreeItem {
344 xmlSchemaTypeType type;
345 xmlSchemaAnnotPtr annot;
346 xmlSchemaTreeItemPtr next;
347 xmlSchemaTreeItemPtr children;
350 typedef struct _xmlSchemaParticle xmlSchemaParticle;
351 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
352 struct _xmlSchemaParticle {
353 xmlSchemaTypeType type;
354 xmlSchemaAnnotPtr annot;
355 xmlSchemaTreeItemPtr next;
356 xmlSchemaTreeItemPtr children;
362 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
363 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
364 struct _xmlSchemaModelGroup {
365 xmlSchemaTypeType type;
366 xmlSchemaAnnotPtr annot;
367 xmlSchemaTreeItemPtr next;
368 xmlSchemaTreeItemPtr children;
372 static xmlSchemaParticlePtr
373 xmlSchemaAddParticle(void)
375 xmlSchemaParticlePtr ret = NULL;
377 ret = (xmlSchemaParticlePtr)
378 xmlMalloc(sizeof(xmlSchemaParticle));
380 xmlSchemaTypeErrMemory(NULL, "allocating particle component");
383 memset(ret, 0, sizeof(xmlSchemaParticle));
384 ret->type = XML_SCHEMA_TYPE_PARTICLE;
391 * xmlSchemaInitTypes:
393 * Initialize the default XML Schemas type library
396 xmlSchemaInitTypes(void)
398 if (xmlSchemaTypesInitialized != 0)
400 xmlSchemaTypesBank = xmlHashCreate(40);
404 * 3.4.7 Built-in Complex Type Definition
406 xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
409 xmlSchemaTypeAnyTypeDef->baseType = xmlSchemaTypeAnyTypeDef;
410 xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
412 * Init the content type.
414 xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
416 xmlSchemaParticlePtr particle;
417 xmlSchemaModelGroupPtr sequence;
418 xmlSchemaWildcardPtr wild;
419 /* First particle. */
420 particle = xmlSchemaAddParticle();
421 if (particle == NULL)
423 xmlSchemaTypeAnyTypeDef->subtypes = (xmlSchemaTypePtr) particle;
424 /* Sequence model group. */
425 sequence = (xmlSchemaModelGroupPtr)
426 xmlMalloc(sizeof(xmlSchemaModelGroup));
427 if (sequence == NULL) {
428 xmlSchemaTypeErrMemory(NULL, "allocating model group component");
431 memset(sequence, 0, sizeof(xmlSchemaModelGroup));
432 sequence->type = XML_SCHEMA_TYPE_SEQUENCE;
433 particle->children = (xmlSchemaTreeItemPtr) sequence;
434 /* Second particle. */
435 particle = xmlSchemaAddParticle();
436 if (particle == NULL)
438 particle->minOccurs = 0;
439 particle->maxOccurs = UNBOUNDED;
440 sequence->children = (xmlSchemaTreeItemPtr) particle;
442 wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
444 xmlSchemaTypeErrMemory(NULL, "allocating wildcard component");
447 memset(wild, 0, sizeof(xmlSchemaWildcard));
448 wild->type = XML_SCHEMA_TYPE_ANY;
450 wild->processContents = XML_SCHEMAS_ANY_LAX;
451 particle->children = (xmlSchemaTreeItemPtr) wild;
453 * Create the attribute wildcard.
455 wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
457 xmlSchemaTypeErrMemory(NULL, "could not create an attribute "
458 "wildcard on anyType");
461 memset(wild, 0, sizeof(xmlSchemaWildcard));
463 wild->processContents = XML_SCHEMAS_ANY_LAX;
464 xmlSchemaTypeAnyTypeDef->attributeWildcard = wild;
466 xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType",
467 XML_SCHEMAS_ANYSIMPLETYPE,
468 xmlSchemaTypeAnyTypeDef);
470 * primitive datatypes
472 xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
474 xmlSchemaTypeAnySimpleTypeDef);
475 xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
477 xmlSchemaTypeAnySimpleTypeDef);
478 xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
480 xmlSchemaTypeAnySimpleTypeDef);
481 xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
482 XML_SCHEMAS_DATETIME,
483 xmlSchemaTypeAnySimpleTypeDef);
484 xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
486 xmlSchemaTypeAnySimpleTypeDef);
487 xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
489 xmlSchemaTypeAnySimpleTypeDef);
490 xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
491 XML_SCHEMAS_GYEARMONTH,
492 xmlSchemaTypeAnySimpleTypeDef);
493 xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
495 xmlSchemaTypeAnySimpleTypeDef);
496 xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
497 XML_SCHEMAS_GMONTHDAY,
498 xmlSchemaTypeAnySimpleTypeDef);
499 xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
501 xmlSchemaTypeAnySimpleTypeDef);
502 xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
503 XML_SCHEMAS_DURATION,
504 xmlSchemaTypeAnySimpleTypeDef);
505 xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
507 xmlSchemaTypeAnySimpleTypeDef);
508 xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
510 xmlSchemaTypeAnySimpleTypeDef);
511 xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
513 xmlSchemaTypeAnySimpleTypeDef);
514 xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
516 xmlSchemaTypeAnySimpleTypeDef);
517 xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
518 XML_SCHEMAS_HEXBINARY,
519 xmlSchemaTypeAnySimpleTypeDef);
520 xmlSchemaTypeBase64BinaryDef
521 = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY,
522 xmlSchemaTypeAnySimpleTypeDef);
523 xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
524 XML_SCHEMAS_NOTATION,
525 xmlSchemaTypeAnySimpleTypeDef);
526 xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
528 xmlSchemaTypeAnySimpleTypeDef);
533 xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
535 xmlSchemaTypeDecimalDef);
536 xmlSchemaTypeNonPositiveIntegerDef =
537 xmlSchemaInitBasicType("nonPositiveInteger",
538 XML_SCHEMAS_NPINTEGER,
539 xmlSchemaTypeIntegerDef);
540 xmlSchemaTypeNegativeIntegerDef =
541 xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER,
542 xmlSchemaTypeNonPositiveIntegerDef);
543 xmlSchemaTypeLongDef =
544 xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG,
545 xmlSchemaTypeIntegerDef);
546 xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT,
547 xmlSchemaTypeLongDef);
548 xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
550 xmlSchemaTypeIntDef);
551 xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
553 xmlSchemaTypeShortDef);
554 xmlSchemaTypeNonNegativeIntegerDef =
555 xmlSchemaInitBasicType("nonNegativeInteger",
556 XML_SCHEMAS_NNINTEGER,
557 xmlSchemaTypeIntegerDef);
558 xmlSchemaTypeUnsignedLongDef =
559 xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG,
560 xmlSchemaTypeNonNegativeIntegerDef);
561 xmlSchemaTypeUnsignedIntDef =
562 xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT,
563 xmlSchemaTypeUnsignedLongDef);
564 xmlSchemaTypeUnsignedShortDef =
565 xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT,
566 xmlSchemaTypeUnsignedIntDef);
567 xmlSchemaTypeUnsignedByteDef =
568 xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE,
569 xmlSchemaTypeUnsignedShortDef);
570 xmlSchemaTypePositiveIntegerDef =
571 xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER,
572 xmlSchemaTypeNonNegativeIntegerDef);
573 xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
574 XML_SCHEMAS_NORMSTRING,
575 xmlSchemaTypeStringDef);
576 xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
578 xmlSchemaTypeNormStringDef);
579 xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
580 XML_SCHEMAS_LANGUAGE,
581 xmlSchemaTypeTokenDef);
582 xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
584 xmlSchemaTypeTokenDef);
585 xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
587 xmlSchemaTypeTokenDef);
588 xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
590 xmlSchemaTypeNameDef);
591 xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID,
592 xmlSchemaTypeNCNameDef);
593 xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
595 xmlSchemaTypeNCNameDef);
596 xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
598 xmlSchemaTypeNCNameDef);
600 * Derived list types.
603 xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
604 XML_SCHEMAS_ENTITIES,
605 xmlSchemaTypeAnySimpleTypeDef);
606 xmlSchemaTypeEntitiesDef->subtypes = xmlSchemaTypeEntityDef;
608 xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
610 xmlSchemaTypeAnySimpleTypeDef);
611 xmlSchemaTypeIdrefsDef->subtypes = xmlSchemaTypeIdrefDef;
614 xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
615 XML_SCHEMAS_NMTOKENS,
616 xmlSchemaTypeAnySimpleTypeDef);
617 xmlSchemaTypeNmtokensDef->subtypes = xmlSchemaTypeNmtokenDef;
619 xmlSchemaTypesInitialized = 1;
623 * xmlSchemaCleanupTypes:
625 * Cleanup the default XML Schemas type library
628 xmlSchemaCleanupTypes(void) {
629 if (xmlSchemaTypesInitialized == 0)
635 xmlSchemaParticlePtr particle;
636 /* Attribute wildcard. */
637 xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard);
639 particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes;
641 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr)
642 particle->children->children->children);
643 xmlFree((xmlSchemaParticlePtr) particle->children->children);
644 /* Sequence model group. */
645 xmlFree((xmlSchemaModelGroupPtr) particle->children);
646 xmlFree((xmlSchemaParticlePtr) particle);
647 xmlSchemaTypeAnyTypeDef->subtypes = NULL;
649 xmlHashFree(xmlSchemaTypesBank, (xmlHashDeallocator) xmlSchemaFreeType);
650 xmlSchemaTypesInitialized = 0;
654 * xmlSchemaIsBuiltInTypeFacet:
655 * @type: the built-in type
656 * @facetType: the facet type
658 * Evaluates if a specific facet can be
659 * used in conjunction with a type.
661 * Returns 1 if the facet can be used with the given built-in type,
662 * 0 otherwise and -1 in case the type is not a built-in type.
665 xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type, int facetType)
669 if (type->type != XML_SCHEMA_TYPE_BASIC)
671 switch (type->builtInType) {
672 case XML_SCHEMAS_BOOLEAN:
673 if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
674 (facetType == XML_SCHEMA_FACET_WHITESPACE))
678 case XML_SCHEMAS_STRING:
679 case XML_SCHEMAS_NOTATION:
680 case XML_SCHEMAS_QNAME:
681 case XML_SCHEMAS_ANYURI:
682 case XML_SCHEMAS_BASE64BINARY:
683 case XML_SCHEMAS_HEXBINARY:
684 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
685 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
686 (facetType == XML_SCHEMA_FACET_MAXLENGTH) ||
687 (facetType == XML_SCHEMA_FACET_PATTERN) ||
688 (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
689 (facetType == XML_SCHEMA_FACET_WHITESPACE))
693 case XML_SCHEMAS_DECIMAL:
694 if ((facetType == XML_SCHEMA_FACET_TOTALDIGITS) ||
695 (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) ||
696 (facetType == XML_SCHEMA_FACET_PATTERN) ||
697 (facetType == XML_SCHEMA_FACET_WHITESPACE) ||
698 (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
699 (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
700 (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
701 (facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
702 (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
706 case XML_SCHEMAS_TIME:
707 case XML_SCHEMAS_GDAY:
708 case XML_SCHEMAS_GMONTH:
709 case XML_SCHEMAS_GMONTHDAY:
710 case XML_SCHEMAS_GYEAR:
711 case XML_SCHEMAS_GYEARMONTH:
712 case XML_SCHEMAS_DATE:
713 case XML_SCHEMAS_DATETIME:
714 case XML_SCHEMAS_DURATION:
715 case XML_SCHEMAS_FLOAT:
716 case XML_SCHEMAS_DOUBLE:
717 if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
718 (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
719 (facetType == XML_SCHEMA_FACET_WHITESPACE) ||
720 (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
721 (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
722 (facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
723 (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
734 * xmlSchemaGetBuiltInType:
735 * @type: the type of the built in type
737 * Gives you the type struct for a built-in
738 * type by its type id.
740 * Returns the type if found, NULL otherwise.
743 xmlSchemaGetBuiltInType(xmlSchemaValType type)
745 if (xmlSchemaTypesInitialized == 0)
746 xmlSchemaInitTypes();
749 case XML_SCHEMAS_ANYSIMPLETYPE:
750 return (xmlSchemaTypeAnySimpleTypeDef);
751 case XML_SCHEMAS_STRING:
752 return (xmlSchemaTypeStringDef);
753 case XML_SCHEMAS_NORMSTRING:
754 return (xmlSchemaTypeNormStringDef);
755 case XML_SCHEMAS_DECIMAL:
756 return (xmlSchemaTypeDecimalDef);
757 case XML_SCHEMAS_TIME:
758 return (xmlSchemaTypeTimeDef);
759 case XML_SCHEMAS_GDAY:
760 return (xmlSchemaTypeGDayDef);
761 case XML_SCHEMAS_GMONTH:
762 return (xmlSchemaTypeGMonthDef);
763 case XML_SCHEMAS_GMONTHDAY:
764 return (xmlSchemaTypeGMonthDayDef);
765 case XML_SCHEMAS_GYEAR:
766 return (xmlSchemaTypeGYearDef);
767 case XML_SCHEMAS_GYEARMONTH:
768 return (xmlSchemaTypeGYearMonthDef);
769 case XML_SCHEMAS_DATE:
770 return (xmlSchemaTypeDateDef);
771 case XML_SCHEMAS_DATETIME:
772 return (xmlSchemaTypeDatetimeDef);
773 case XML_SCHEMAS_DURATION:
774 return (xmlSchemaTypeDurationDef);
775 case XML_SCHEMAS_FLOAT:
776 return (xmlSchemaTypeFloatDef);
777 case XML_SCHEMAS_DOUBLE:
778 return (xmlSchemaTypeDoubleDef);
779 case XML_SCHEMAS_BOOLEAN:
780 return (xmlSchemaTypeBooleanDef);
781 case XML_SCHEMAS_TOKEN:
782 return (xmlSchemaTypeTokenDef);
783 case XML_SCHEMAS_LANGUAGE:
784 return (xmlSchemaTypeLanguageDef);
785 case XML_SCHEMAS_NMTOKEN:
786 return (xmlSchemaTypeNmtokenDef);
787 case XML_SCHEMAS_NMTOKENS:
788 return (xmlSchemaTypeNmtokensDef);
789 case XML_SCHEMAS_NAME:
790 return (xmlSchemaTypeNameDef);
791 case XML_SCHEMAS_QNAME:
792 return (xmlSchemaTypeQNameDef);
793 case XML_SCHEMAS_NCNAME:
794 return (xmlSchemaTypeNCNameDef);
796 return (xmlSchemaTypeIdDef);
797 case XML_SCHEMAS_IDREF:
798 return (xmlSchemaTypeIdrefDef);
799 case XML_SCHEMAS_IDREFS:
800 return (xmlSchemaTypeIdrefsDef);
801 case XML_SCHEMAS_ENTITY:
802 return (xmlSchemaTypeEntityDef);
803 case XML_SCHEMAS_ENTITIES:
804 return (xmlSchemaTypeEntitiesDef);
805 case XML_SCHEMAS_NOTATION:
806 return (xmlSchemaTypeNotationDef);
807 case XML_SCHEMAS_ANYURI:
808 return (xmlSchemaTypeAnyURIDef);
809 case XML_SCHEMAS_INTEGER:
810 return (xmlSchemaTypeIntegerDef);
811 case XML_SCHEMAS_NPINTEGER:
812 return (xmlSchemaTypeNonPositiveIntegerDef);
813 case XML_SCHEMAS_NINTEGER:
814 return (xmlSchemaTypeNegativeIntegerDef);
815 case XML_SCHEMAS_NNINTEGER:
816 return (xmlSchemaTypeNonNegativeIntegerDef);
817 case XML_SCHEMAS_PINTEGER:
818 return (xmlSchemaTypePositiveIntegerDef);
819 case XML_SCHEMAS_INT:
820 return (xmlSchemaTypeIntDef);
821 case XML_SCHEMAS_UINT:
822 return (xmlSchemaTypeUnsignedIntDef);
823 case XML_SCHEMAS_LONG:
824 return (xmlSchemaTypeLongDef);
825 case XML_SCHEMAS_ULONG:
826 return (xmlSchemaTypeUnsignedLongDef);
827 case XML_SCHEMAS_SHORT:
828 return (xmlSchemaTypeShortDef);
829 case XML_SCHEMAS_USHORT:
830 return (xmlSchemaTypeUnsignedShortDef);
831 case XML_SCHEMAS_BYTE:
832 return (xmlSchemaTypeByteDef);
833 case XML_SCHEMAS_UBYTE:
834 return (xmlSchemaTypeUnsignedByteDef);
835 case XML_SCHEMAS_HEXBINARY:
836 return (xmlSchemaTypeHexBinaryDef);
837 case XML_SCHEMAS_BASE64BINARY:
838 return (xmlSchemaTypeBase64BinaryDef);
839 case XML_SCHEMAS_ANYTYPE:
840 return (xmlSchemaTypeAnyTypeDef);
847 * xmlSchemaValueAppend:
849 * @cur: the value to be appended
851 * Appends a next sibling to a list of computed values.
853 * Returns 0 if succeeded and -1 on API errors.
856 xmlSchemaValueAppend(xmlSchemaValPtr prev, xmlSchemaValPtr cur) {
858 if ((prev == NULL) || (cur == NULL))
865 * xmlSchemaValueGetNext:
868 * Accessor for the next sibling of a list of computed values.
870 * Returns the next value or NULL if there was none, or on
874 xmlSchemaValueGetNext(xmlSchemaValPtr cur) {
882 * xmlSchemaValueGetAsString:
885 * Accessor for the string value of a computed value.
887 * Returns the string value or NULL if there was none, or on
891 xmlSchemaValueGetAsString(xmlSchemaValPtr val)
896 case XML_SCHEMAS_STRING:
897 case XML_SCHEMAS_NORMSTRING:
898 case XML_SCHEMAS_ANYSIMPLETYPE:
899 case XML_SCHEMAS_TOKEN:
900 case XML_SCHEMAS_LANGUAGE:
901 case XML_SCHEMAS_NMTOKEN:
902 case XML_SCHEMAS_NAME:
903 case XML_SCHEMAS_NCNAME:
905 case XML_SCHEMAS_IDREF:
906 case XML_SCHEMAS_ENTITY:
907 case XML_SCHEMAS_ANYURI:
908 return (BAD_CAST val->value.str);
916 * xmlSchemaValueGetAsBoolean:
919 * Accessor for the boolean value of a computed value.
921 * Returns 1 if true and 0 if false, or in case of an error. Hmm.
924 xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val)
926 if ((val == NULL) || (val->type != XML_SCHEMAS_BOOLEAN))
928 return (val->value.b);
932 * xmlSchemaNewStringValue:
933 * @type: the value type
936 * Allocate a new simple type value. The type can be
937 * of XML_SCHEMAS_STRING.
938 * WARNING: This one is intended to be expanded for other
939 * string based types. We need this for anySimpleType as well.
940 * The given value is consumed and freed with the struct.
942 * Returns a pointer to the new value or NULL in case of error
945 xmlSchemaNewStringValue(xmlSchemaValType type,
946 const xmlChar *value)
950 if (type != XML_SCHEMAS_STRING)
952 val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
956 memset(val, 0, sizeof(xmlSchemaVal));
958 val->value.str = (xmlChar *) value;
963 * xmlSchemaNewNOTATIONValue:
964 * @name: the notation name
965 * @ns: the notation namespace name or NULL
967 * Allocate a new NOTATION value.
968 * The given values are consumed and freed with the struct.
970 * Returns a pointer to the new value or NULL in case of error
973 xmlSchemaNewNOTATIONValue(const xmlChar *name,
978 val = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
982 val->value.qname.name = (xmlChar *)name;
984 val->value.qname.uri = (xmlChar *)ns;
989 * xmlSchemaNewQNameValue:
990 * @namespaceName: the namespace name
991 * @localName: the local name
993 * Allocate a new QName value.
994 * The given values are consumed and freed with the struct.
996 * Returns a pointer to the new value or NULL in case of an error.
999 xmlSchemaNewQNameValue(const xmlChar *namespaceName,
1000 const xmlChar *localName)
1002 xmlSchemaValPtr val;
1004 val = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
1008 val->value.qname.name = (xmlChar *) localName;
1009 val->value.qname.uri = (xmlChar *) namespaceName;
1014 * xmlSchemaFreeValue:
1015 * @value: the value to free
1017 * Cleanup the default XML Schemas type library
1020 xmlSchemaFreeValue(xmlSchemaValPtr value) {
1021 xmlSchemaValPtr prev;
1023 while (value != NULL) {
1024 switch (value->type) {
1025 case XML_SCHEMAS_STRING:
1026 case XML_SCHEMAS_NORMSTRING:
1027 case XML_SCHEMAS_TOKEN:
1028 case XML_SCHEMAS_LANGUAGE:
1029 case XML_SCHEMAS_NMTOKEN:
1030 case XML_SCHEMAS_NMTOKENS:
1031 case XML_SCHEMAS_NAME:
1032 case XML_SCHEMAS_NCNAME:
1033 case XML_SCHEMAS_ID:
1034 case XML_SCHEMAS_IDREF:
1035 case XML_SCHEMAS_IDREFS:
1036 case XML_SCHEMAS_ENTITY:
1037 case XML_SCHEMAS_ENTITIES:
1038 case XML_SCHEMAS_ANYURI:
1039 case XML_SCHEMAS_ANYSIMPLETYPE:
1040 if (value->value.str != NULL)
1041 xmlFree(value->value.str);
1043 case XML_SCHEMAS_NOTATION:
1044 case XML_SCHEMAS_QNAME:
1045 if (value->value.qname.uri != NULL)
1046 xmlFree(value->value.qname.uri);
1047 if (value->value.qname.name != NULL)
1048 xmlFree(value->value.qname.name);
1050 case XML_SCHEMAS_HEXBINARY:
1051 if (value->value.hex.str != NULL)
1052 xmlFree(value->value.hex.str);
1054 case XML_SCHEMAS_BASE64BINARY:
1055 if (value->value.base64.str != NULL)
1056 xmlFree(value->value.base64.str);
1062 value = value->next;
1068 * xmlSchemaGetPredefinedType:
1069 * @name: the type name
1070 * @ns: the URI of the namespace usually "http://www.w3.org/2001/XMLSchema"
1072 * Lookup a type in the default XML Schemas type library
1074 * Returns the type if found, NULL otherwise
1077 xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
1078 if (xmlSchemaTypesInitialized == 0)
1079 xmlSchemaInitTypes();
1082 return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
1086 * xmlSchemaGetBuiltInListSimpleTypeItemType:
1087 * @type: the built-in simple type.
1091 * Returns the item type of @type as defined by the built-in datatype
1092 * hierarchy of XML Schema Part 2: Datatypes, or NULL in case of an error.
1095 xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type)
1097 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_BASIC))
1099 switch (type->builtInType) {
1100 case XML_SCHEMAS_NMTOKENS:
1101 return (xmlSchemaTypeNmtokenDef );
1102 case XML_SCHEMAS_IDREFS:
1103 return (xmlSchemaTypeIdrefDef);
1104 case XML_SCHEMAS_ENTITIES:
1105 return (xmlSchemaTypeEntityDef);
1111 /****************************************************************
1113 * Convenience macros and functions *
1115 ****************************************************************/
1117 #define IS_TZO_CHAR(c) \
1118 ((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
1120 #define VALID_YEAR(yr) (yr != 0)
1121 #define VALID_MONTH(mon) ((mon >= 1) && (mon <= 12))
1122 /* VALID_DAY should only be used when month is unknown */
1123 #define VALID_DAY(day) ((day >= 1) && (day <= 31))
1124 #define VALID_HOUR(hr) ((hr >= 0) && (hr <= 23))
1125 #define VALID_MIN(min) ((min >= 0) && (min <= 59))
1126 #define VALID_SEC(sec) ((sec >= 0) && (sec < 60))
1127 #define VALID_TZO(tzo) ((tzo > -840) && (tzo < 840))
1128 #define IS_LEAP(y) \
1129 (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
1131 static const unsigned int daysInMonth[12] =
1132 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1133 static const unsigned int daysInMonthLeap[12] =
1134 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1136 #define MAX_DAYINMONTH(yr,mon) \
1137 (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
1139 #define VALID_MDAY(dt) \
1140 (IS_LEAP(dt->year) ? \
1141 (dt->day <= daysInMonthLeap[dt->mon - 1]) : \
1142 (dt->day <= daysInMonth[dt->mon - 1]))
1144 #define VALID_DATE(dt) \
1145 (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
1147 #define VALID_END_OF_DAY(dt) \
1148 ((dt)->hour == 24 && (dt)->min == 0 && (dt)->sec == 0)
1150 #define VALID_TIME(dt) \
1151 (((VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \
1152 VALID_SEC(dt->sec)) || VALID_END_OF_DAY(dt)) && \
1155 #define VALID_DATETIME(dt) \
1156 (VALID_DATE(dt) && VALID_TIME(dt))
1158 #define SECS_PER_MIN (60)
1159 #define SECS_PER_HOUR (60 * SECS_PER_MIN)
1160 #define SECS_PER_DAY (24 * SECS_PER_HOUR)
1162 static const long dayInYearByMonth[12] =
1163 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1164 static const long dayInLeapYearByMonth[12] =
1165 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
1167 #define DAY_IN_YEAR(day, month, year) \
1169 dayInLeapYearByMonth[month - 1] : \
1170 dayInYearByMonth[month - 1]) + day)
1173 #define DEBUG_DATE(dt) \
1174 xmlGenericError(xmlGenericErrorContext, \
1175 "type=%o %04ld-%02u-%02uT%02u:%02u:%03f", \
1176 dt->type,dt->value.date.year,dt->value.date.mon, \
1177 dt->value.date.day,dt->value.date.hour,dt->value.date.min, \
1178 dt->value.date.sec); \
1179 if (dt->value.date.tz_flag) \
1180 if (dt->value.date.tzo != 0) \
1181 xmlGenericError(xmlGenericErrorContext, \
1182 "%+05d\n",dt->value.date.tzo); \
1184 xmlGenericError(xmlGenericErrorContext, "Z\n"); \
1186 xmlGenericError(xmlGenericErrorContext,"\n")
1188 #define DEBUG_DATE(dt)
1192 * _xmlSchemaParseGYear:
1193 * @dt: pointer to a date structure
1194 * @str: pointer to the string to analyze
1196 * Parses a xs:gYear without time zone and fills in the appropriate
1197 * field of the @dt structure. @str is updated to point just after the
1198 * xs:gYear. It is supposed that @dt->year is big enough to contain
1201 * Returns 0 or the error code
1204 _xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
1205 const xmlChar *cur = *str, *firstChar;
1206 int isneg = 0, digcnt = 0;
1208 if (((*cur < '0') || (*cur > '9')) &&
1209 (*cur != '-') && (*cur != '+'))
1219 while ((*cur >= '0') && (*cur <= '9')) {
1220 dt->year = dt->year * 10 + (*cur - '0');
1225 /* year must be at least 4 digits (CCYY); over 4
1226 * digits cannot have a leading zero. */
1227 if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0')))
1231 dt->year = - dt->year;
1233 if (!VALID_YEAR(dt->year))
1242 * @num: the integer to fill in
1243 * @cur: an #xmlChar *
1244 * @invalid: an integer
1246 * Parses a 2-digits integer and updates @num with the value. @cur is
1247 * updated to point just after the integer.
1248 * In case of error, @invalid is set to %TRUE, values of @num and
1249 * @cur are undefined.
1251 #define PARSE_2_DIGITS(num, cur, invalid) \
1252 if ((cur[0] < '0') || (cur[0] > '9') || \
1253 (cur[1] < '0') || (cur[1] > '9')) \
1256 num = (cur[0] - '0') * 10 + (cur[1] - '0'); \
1261 * @num: the double to fill in
1262 * @cur: an #xmlChar *
1263 * @invalid: an integer
1265 * Parses a float and updates @num with the value. @cur is
1266 * updated to point just after the float. The float must have a
1267 * 2-digits integer part and may or may not have a decimal part.
1268 * In case of error, @invalid is set to %TRUE, values of @num and
1269 * @cur are undefined.
1271 #define PARSE_FLOAT(num, cur, invalid) \
1272 PARSE_2_DIGITS(num, cur, invalid); \
1273 if (!invalid && (*cur == '.')) { \
1276 if ((*cur < '0') || (*cur > '9')) \
1278 while ((*cur >= '0') && (*cur <= '9')) { \
1280 num += (*cur - '0') * mult; \
1286 * _xmlSchemaParseGMonth:
1287 * @dt: pointer to a date structure
1288 * @str: pointer to the string to analyze
1290 * Parses a xs:gMonth without time zone and fills in the appropriate
1291 * field of the @dt structure. @str is updated to point just after the
1294 * Returns 0 or the error code
1297 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) {
1298 const xmlChar *cur = *str;
1300 unsigned int value = 0;
1302 PARSE_2_DIGITS(value, cur, ret);
1306 if (!VALID_MONTH(value))
1316 * _xmlSchemaParseGDay:
1317 * @dt: pointer to a date structure
1318 * @str: pointer to the string to analyze
1320 * Parses a xs:gDay without time zone and fills in the appropriate
1321 * field of the @dt structure. @str is updated to point just after the
1324 * Returns 0 or the error code
1327 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) {
1328 const xmlChar *cur = *str;
1330 unsigned int value = 0;
1332 PARSE_2_DIGITS(value, cur, ret);
1336 if (!VALID_DAY(value))
1345 * _xmlSchemaParseTime:
1346 * @dt: pointer to a date structure
1347 * @str: pointer to the string to analyze
1349 * Parses a xs:time without time zone and fills in the appropriate
1350 * fields of the @dt structure. @str is updated to point just after the
1352 * In case of error, values of @dt fields are undefined.
1354 * Returns 0 or the error code
1357 _xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) {
1358 const xmlChar *cur = *str;
1362 PARSE_2_DIGITS(value, cur, ret);
1367 if (!VALID_HOUR(value) && value != 24 /* Allow end-of-day hour */)
1371 /* the ':' insures this string is xs:time */
1374 PARSE_2_DIGITS(value, cur, ret);
1377 if (!VALID_MIN(value))
1385 PARSE_FLOAT(dt->sec, cur, ret);
1389 if (!VALID_TIME(dt))
1397 * _xmlSchemaParseTimeZone:
1398 * @dt: pointer to a date structure
1399 * @str: pointer to the string to analyze
1401 * Parses a time zone without time zone and fills in the appropriate
1402 * field of the @dt structure. @str is updated to point just after the
1405 * Returns 0 or the error code
1408 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
1430 int isneg = 0, tmp = 0;
1431 isneg = (*cur == '-');
1435 PARSE_2_DIGITS(tmp, cur, ret);
1438 if (!VALID_HOUR(tmp))
1447 PARSE_2_DIGITS(tmp, cur, ret);
1450 if (!VALID_MIN(tmp))
1455 dt->tzo = - dt->tzo;
1457 if (!VALID_TZO(dt->tzo))
1472 * _xmlSchemaBase64Decode:
1475 * Converts a base64 encoded character to its base 64 value.
1477 * Returns 0-63 (value), 64 (pad), or -1 (not recognized)
1480 _xmlSchemaBase64Decode (const xmlChar ch) {
1481 if (('A' <= ch) && (ch <= 'Z')) return ch - 'A';
1482 if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26;
1483 if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52;
1484 if ('+' == ch) return 62;
1485 if ('/' == ch) return 63;
1486 if ('=' == ch) return 64;
1490 /****************************************************************
1492 * XML Schema Dates/Times Datatypes Handling *
1494 ****************************************************************/
1498 * @num: the integer to fill in
1499 * @cur: an #xmlChar *
1500 * @num_type: an integer flag
1502 * Parses a digits integer and updates @num with the value. @cur is
1503 * updated to point just after the integer.
1504 * In case of error, @num_type is set to -1, values of @num and
1505 * @cur are undefined.
1507 #define PARSE_DIGITS(num, cur, num_type) \
1508 if ((*cur < '0') || (*cur > '9')) \
1511 while ((*cur >= '0') && (*cur <= '9')) { \
1512 num = num * 10 + (*cur - '0'); \
1518 * @num: the double to fill in
1519 * @cur: an #xmlChar *
1520 * @num_type: an integer flag
1522 * Parses a float or integer and updates @num with the value. @cur is
1523 * updated to point just after the number. If the number is a float,
1524 * then it must have an integer part and a decimal part; @num_type will
1525 * be set to 1. If there is no decimal part, @num_type is set to zero.
1526 * In case of error, @num_type is set to -1, values of @num and
1527 * @cur are undefined.
1529 #define PARSE_NUM(num, cur, num_type) \
1531 PARSE_DIGITS(num, cur, num_type); \
1532 if (!num_type && (*cur == '.')) { \
1535 if ((*cur < '0') || (*cur > '9')) \
1539 while ((*cur >= '0') && (*cur <= '9')) { \
1541 num += (*cur - '0') * mult; \
1547 * xmlSchemaValidateDates:
1548 * @type: the expected type or XML_SCHEMAS_UNKNOWN
1549 * @dateTime: string to analyze
1550 * @val: the return computed value
1552 * Check that @dateTime conforms to the lexical space of one of the date types.
1553 * if true a value is computed and returned in @val.
1555 * Returns 0 if this validates, a positive error code number otherwise
1556 * and -1 in case of internal or API error.
1559 xmlSchemaValidateDates (xmlSchemaValType type,
1560 const xmlChar *dateTime, xmlSchemaValPtr *val,
1564 const xmlChar *cur = dateTime;
1566 #define RETURN_TYPE_IF_VALID(t) \
1567 if (IS_TZO_CHAR(*cur)) { \
1568 ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); \
1577 if (dateTime == NULL)
1581 while IS_WSP_BLANK_CH(*cur) cur++;
1583 if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
1586 dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN);
1590 if ((cur[0] == '-') && (cur[1] == '-')) {
1592 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
1597 /* is it an xs:gDay? */
1599 if (type == XML_SCHEMAS_GMONTH)
1602 ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1606 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY);
1612 * it should be an xs:gMonthDay or xs:gMonth
1614 ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1619 * a '-' char could indicate this type is xs:gMonthDay or
1620 * a negative time zone offset. Check for xs:gMonthDay first.
1621 * Also the first three char's of a negative tzo (-MM:SS) can
1622 * appear to be a valid day; so even if the day portion
1623 * of the xs:gMonthDay verifies, we must insure it was not
1627 const xmlChar *rewnd = cur;
1630 ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1631 if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) {
1634 * we can use the VALID_MDAY macro to validate the month
1635 * and day because the leap year test will flag year zero
1636 * as a leap year (even though zero is an invalid year).
1637 * FUTURE TODO: Zero will become valid in XML Schema 1.1
1640 if (VALID_MDAY((&(dt->value.date)))) {
1642 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
1649 * not xs:gMonthDay so rewind and check if just xs:gMonth
1650 * with an optional time zone.
1655 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
1661 * It's a right-truncated date or an xs:time.
1662 * Try to parse an xs:time then fallback on right-truncated dates.
1664 if ((*cur >= '0') && (*cur <= '9')) {
1665 ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1667 /* it's an xs:time */
1668 RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME);
1672 /* fallback on date parsing */
1675 ret = _xmlSchemaParseGYear(&(dt->value.date), &cur);
1679 /* is it an xs:gYear? */
1680 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR);
1686 ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1690 /* is it an xs:gYearMonth? */
1691 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH);
1697 ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1698 if ((ret != 0) || !VALID_DATE((&(dt->value.date))))
1701 /* is it an xs:date? */
1702 RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE);
1708 /* it should be an xs:dateTime */
1709 ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1713 ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);
1715 while IS_WSP_BLANK_CH(*cur) cur++;
1716 if ((ret != 0) || (*cur != 0) || (!(VALID_DATETIME((&(dt->value.date))))))
1720 dt->type = XML_SCHEMAS_DATETIME;
1724 if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
1728 * insure the parsed type is equal to or less significant (right
1729 * truncated) than the desired type.
1731 if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) {
1733 /* time only matches time */
1734 if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME))
1737 if ((type == XML_SCHEMAS_DATETIME) &&
1738 ((dt->type != XML_SCHEMAS_DATE) ||
1739 (dt->type != XML_SCHEMAS_GYEARMONTH) ||
1740 (dt->type != XML_SCHEMAS_GYEAR)))
1743 if ((type == XML_SCHEMAS_DATE) &&
1744 ((dt->type != XML_SCHEMAS_GYEAR) ||
1745 (dt->type != XML_SCHEMAS_GYEARMONTH)))
1748 if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
1751 if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
1759 xmlSchemaFreeValue(dt);
1765 xmlSchemaFreeValue(dt);
1770 * xmlSchemaValidateDuration:
1771 * @type: the predefined type
1772 * @duration: string to analyze
1773 * @val: the return computed value
1775 * Check that @duration conforms to the lexical space of the duration type.
1776 * if true a value is computed and returned in @val.
1778 * Returns 0 if this validates, a positive error code number otherwise
1779 * and -1 in case of internal or API error.
1782 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1783 const xmlChar *duration, xmlSchemaValPtr *val,
1785 const xmlChar *cur = duration;
1786 xmlSchemaValPtr dur;
1788 unsigned int seq = 0;
1790 int num_type = 0; /* -1 = invalid, 0 = int, 1 = floating */
1791 const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
1792 const double multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
1794 if (duration == NULL)
1798 while IS_WSP_BLANK_CH(*cur) cur++;
1805 /* duration must start with 'P' (after sign) */
1812 dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
1818 /* input string should be empty or invalid date/time item */
1819 if (seq >= sizeof(desig))
1822 /* T designator must be present for time items */
1829 } else if (seq == 3)
1832 /* parse the number portion of the item */
1833 PARSE_NUM(num, cur, num_type);
1835 if ((num_type == -1) || (*cur == 0))
1838 /* update duration based on item type */
1839 while (seq < sizeof(desig)) {
1840 if (*cur == desig[seq]) {
1842 /* verify numeric type; only seconds can be float */
1843 if ((num_type != 0) && (seq < (sizeof(desig)-1)))
1848 dur->value.dur.mon = (long)num * 12;
1851 dur->value.dur.mon += (long)num;
1854 /* convert to seconds using multiplier */
1855 dur->value.dur.sec += num * multi[seq];
1860 break; /* exit loop */
1862 /* no date designators found? */
1863 if ((++seq == 3) || (seq == 6))
1868 while IS_WSP_BLANK_CH(*cur) cur++;
1872 dur->value.dur.mon = -dur->value.dur.mon;
1873 dur->value.dur.day = -dur->value.dur.day;
1874 dur->value.dur.sec = -dur->value.dur.sec;
1880 xmlSchemaFreeValue(dur);
1886 xmlSchemaFreeValue(dur);
1894 * Removes the leading and ending spaces of a string
1896 * Returns the new string or NULL if no change was required.
1899 xmlSchemaStrip(const xmlChar *value) {
1900 const xmlChar *start = value, *end, *f;
1902 if (value == NULL) return(NULL);
1903 while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
1905 while (*end != 0) end++;
1908 while ((end > start) && (IS_BLANK_CH(*end))) end--;
1910 if ((start == value) && (f == end)) return(NULL);
1911 return(xmlStrndup(start, end - start));
1915 * xmlSchemaWhiteSpaceReplace:
1918 * Replaces 0xd, 0x9 and 0xa with a space.
1920 * Returns the new string or NULL if no change was required.
1923 xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
1924 const xmlChar *cur = value;
1925 xmlChar *ret = NULL, *mcur;
1930 while ((*cur != 0) &&
1931 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
1936 ret = xmlStrdup(value);
1937 /* TODO FIXME: I guess gcc will bark at this. */
1938 mcur = (xmlChar *) (ret + (cur - value));
1940 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
1943 } while (*mcur != 0);
1948 * xmlSchemaCollapseString:
1951 * Removes and normalize white spaces in the string
1953 * Returns the new string or NULL if no change was required.
1956 xmlSchemaCollapseString(const xmlChar *value) {
1957 const xmlChar *start = value, *end, *f;
1961 if (value == NULL) return(NULL);
1962 while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
1965 if ((*end == ' ') && (IS_BLANK_CH(end[1]))) {
1968 } else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) {
1977 while ((end > start) && (IS_BLANK_CH(*end))) end--;
1979 if ((start == value) && (f == end)) return(NULL);
1980 return(xmlStrndup(start, end - start));
1982 start = xmlStrdup(start);
1983 if (start == NULL) return(NULL);
1984 g = (xmlChar *) (start + col);
1987 if (IS_BLANK_CH(*end)) {
1989 while (IS_BLANK_CH(*end)) end++;
1996 return((xmlChar *) start);
2000 * xmlSchemaValAtomicListNode:
2001 * @type: the predefined atomic type for a token in the list
2002 * @value: the list value to check
2003 * @ret: the return computed value
2004 * @node: the node containing the value
2006 * Check that a value conforms to the lexical space of the predefined
2007 * list type. if true a value is computed and returned in @ret.
2009 * Returns the number of items if this validates, a negative error code
2013 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
2014 xmlSchemaValPtr *ret, xmlNodePtr node) {
2015 xmlChar *val, *cur, *endval;
2019 if (value == NULL) {
2022 val = xmlStrdup(value);
2033 while (IS_BLANK_CH(*cur)) *cur++ = 0;
2035 if (IS_BLANK_CH(*cur)) {
2038 while (IS_BLANK_CH(*cur)) *cur++ = 0;
2042 while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
2045 if (nb_values == 0) {
2051 while ((*cur == 0) && (cur != endval)) cur++;
2052 while (cur != endval) {
2053 tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node);
2056 while (*cur != 0) cur++;
2057 while ((*cur == 0) && (cur != endval)) cur++;
2059 /* TODO what return value ? c.f. bug #158628
2070 * xmlSchemaParseUInt:
2071 * @str: pointer to the string R/W
2072 * @llo: pointer to the low result
2073 * @lmi: pointer to the mid result
2074 * @lhi: pointer to the high result
2076 * Parse an unsigned long into 3 fields.
2078 * Returns the number of significant digits in the number or
2079 * -1 if overflow of the capacity and -2 if it's not a number.
2082 xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
2083 unsigned long *lmi, unsigned long *lhi) {
2084 unsigned long lo = 0, mi = 0, hi = 0;
2085 const xmlChar *tmp, *cur = *str;
2088 if (!((*cur >= '0') && (*cur <= '9')))
2091 while (*cur == '0') { /* ignore leading zeroes */
2095 while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
2103 hi = hi * 10 + (*cur++ - '0');
2107 mi = mi * 10 + (*cur++ - '0');
2111 lo = lo * 10 + (*cur++ - '0');
2123 * xmlSchemaValAtomicType:
2124 * @type: the predefined type
2125 * @value: the value to check
2126 * @val: the return computed value
2127 * @node: the node containing the value
2128 * flags: flags to control the vlidation
2130 * Check that a value conforms to the lexical space of the atomic type.
2131 * if true a value is computed and returned in @val.
2132 * This checks the value space for list types as well (IDREFS, NMTOKENS).
2134 * Returns 0 if this validates, a positive error code number otherwise
2135 * and -1 in case of internal or API error.
2138 xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
2139 xmlSchemaValPtr * val, xmlNodePtr node, int flags,
2140 xmlSchemaWhitespaceValueType ws,
2141 int normOnTheFly, int applyNorm, int createStringValue)
2144 xmlChar *norm = NULL;
2147 if (xmlSchemaTypesInitialized == 0)
2148 xmlSchemaInitTypes();
2153 * validating a non existant text node is similar to validating
2157 value = BAD_CAST "";
2161 if ((flags == 0) && (value != NULL)) {
2163 if ((type->builtInType != XML_SCHEMAS_STRING) &&
2164 (type->builtInType != XML_SCHEMAS_ANYTYPE) &&
2165 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
2166 if (type->builtInType == XML_SCHEMAS_NORMSTRING)
2167 norm = xmlSchemaWhiteSpaceReplace(value);
2169 norm = xmlSchemaCollapseString(value);
2175 switch (type->builtInType) {
2176 case XML_SCHEMAS_UNKNOWN:
2178 case XML_SCHEMAS_ANYTYPE:
2179 case XML_SCHEMAS_ANYSIMPLETYPE:
2180 if ((createStringValue) && (val != NULL)) {
2181 v = xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE);
2183 v->value.str = xmlStrdup(value);
2190 case XML_SCHEMAS_STRING:
2191 if (! normOnTheFly) {
2192 const xmlChar *cur = value;
2194 if (ws == XML_SCHEMA_WHITESPACE_REPLACE) {
2196 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2202 } else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
2204 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2206 } else if IS_WSP_SPACE_CH(*cur) {
2208 if IS_WSP_SPACE_CH(*cur)
2216 if (createStringValue && (val != NULL)) {
2218 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
2219 norm = xmlSchemaCollapseString(value);
2220 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
2221 norm = xmlSchemaWhiteSpaceReplace(value);
2225 v = xmlSchemaNewValue(XML_SCHEMAS_STRING);
2227 v->value.str = xmlStrdup(value);
2234 case XML_SCHEMAS_NORMSTRING:{
2237 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
2238 norm = xmlSchemaCollapseString(value);
2240 norm = xmlSchemaWhiteSpaceReplace(value);
2245 const xmlChar *cur = value;
2247 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2255 v = xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING);
2257 v->value.str = xmlStrdup(value);
2265 case XML_SCHEMAS_DECIMAL:{
2266 const xmlChar *cur = value;
2267 unsigned int len, neg, integ, hasLeadingZeroes;
2269 xmlChar *cptr = cval;
2271 if ((cur == NULL) || (*cur == 0))
2275 * xs:decimal has a whitespace-facet value of 'collapse'.
2278 while IS_WSP_BLANK_CH(*cur) cur++;
2281 * First we handle an optional sign.
2287 } else if (*cur == '+')
2290 * Disallow: "", "-", "- "
2295 * Next we "pre-parse" the number, in preparation for calling
2296 * the common routine xmlSchemaParseUInt. We get rid of any
2297 * leading zeroes (because we have reserved only 25 chars),
2298 * and note the position of a decimal point.
2302 hasLeadingZeroes = 0;
2304 * Skip leading zeroes.
2306 while (*cur == '0') {
2308 hasLeadingZeroes = 1;
2312 if ((*cur >= '0') && (*cur <= '9')) {
2315 } else if (*cur == '.') {
2319 if ((*cur >= '0') && (*cur <= '9')) {
2326 * Disallow "." but allow "00."
2328 if ((len == 0) && (!hasLeadingZeroes))
2336 while IS_WSP_BLANK_CH(*cur) cur++;
2338 goto return1; /* error if any extraneous chars */
2340 v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
2343 * Now evaluate the significant digits of the number
2349 * Get rid of trailing zeroes in the
2352 while ((len != integ) && (*(cptr-1) == '0')) {
2358 * Terminate the (preparsed) string.
2364 xmlSchemaParseUInt((const xmlChar **)&cptr,
2365 &v->value.decimal.lo,
2366 &v->value.decimal.mi,
2367 &v->value.decimal.hi);
2371 * Set the total digits to 1 if a zero value.
2373 v->value.decimal.sign = neg;
2375 /* Speedup for zero values. */
2376 v->value.decimal.total = 1;
2378 v->value.decimal.total = len;
2380 v->value.decimal.frac = 0;
2382 v->value.decimal.frac = len - integ;
2389 case XML_SCHEMAS_TIME:
2390 case XML_SCHEMAS_GDAY:
2391 case XML_SCHEMAS_GMONTH:
2392 case XML_SCHEMAS_GMONTHDAY:
2393 case XML_SCHEMAS_GYEAR:
2394 case XML_SCHEMAS_GYEARMONTH:
2395 case XML_SCHEMAS_DATE:
2396 case XML_SCHEMAS_DATETIME:
2397 ret = xmlSchemaValidateDates(type->builtInType, value, val,
2400 case XML_SCHEMAS_DURATION:
2401 ret = xmlSchemaValidateDuration(type, value, val,
2404 case XML_SCHEMAS_FLOAT:
2405 case XML_SCHEMAS_DOUBLE: {
2406 const xmlChar *cur = value;
2408 int digits_before = 0;
2409 int digits_after = 0;
2412 while IS_WSP_BLANK_CH(*cur) cur++;
2414 if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
2419 if (type == xmlSchemaTypeFloatDef) {
2420 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2422 v->value.f = (float) xmlXPathNAN;
2424 xmlSchemaFreeValue(v);
2428 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2430 v->value.d = xmlXPathNAN;
2432 xmlSchemaFreeValue(v);
2444 if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
2449 if (type == xmlSchemaTypeFloatDef) {
2450 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2453 v->value.f = (float) xmlXPathNINF;
2455 v->value.f = (float) xmlXPathPINF;
2457 xmlSchemaFreeValue(v);
2461 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2464 v->value.d = xmlXPathNINF;
2466 v->value.d = xmlXPathPINF;
2468 xmlSchemaFreeValue(v);
2476 if ((neg == 0) && (*cur == '+'))
2478 if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
2480 while ((*cur >= '0') && (*cur <= '9')) {
2486 while ((*cur >= '0') && (*cur <= '9')) {
2491 if ((digits_before == 0) && (digits_after == 0))
2493 if ((*cur == 'e') || (*cur == 'E')) {
2495 if ((*cur == '-') || (*cur == '+'))
2497 while ((*cur >= '0') && (*cur <= '9'))
2501 while IS_WSP_BLANK_CH(*cur) cur++;
2506 if (type == xmlSchemaTypeFloatDef) {
2507 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2510 * TODO: sscanf seems not to give the correct
2511 * value for extremely high/low values.
2512 * E.g. "1E-149" results in zero.
2514 if (sscanf((const char *) value, "%f",
2515 &(v->value.f)) == 1) {
2518 xmlSchemaFreeValue(v);
2525 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2528 * TODO: sscanf seems not to give the correct
2529 * value for extremely high/low values.
2531 if (sscanf((const char *) value, "%lf",
2532 &(v->value.d)) == 1) {
2535 xmlSchemaFreeValue(v);
2545 case XML_SCHEMAS_BOOLEAN:{
2546 const xmlChar *cur = value;
2549 while IS_WSP_BLANK_CH(*cur) cur++;
2553 } else if (*cur == '1') {
2556 } else if (*cur == 't') {
2558 if ((*cur++ == 'r') && (*cur++ == 'u') &&
2563 } else if (*cur == 'f') {
2565 if ((*cur++ == 'a') && (*cur++ == 'l') &&
2566 (*cur++ == 's') && (*cur++ == 'e')) {
2573 while IS_WSP_BLANK_CH(*cur) cur++;
2578 if ((cur[0] == '0') && (cur[1] == 0))
2580 else if ((cur[0] == '1') && (cur[1] == 0))
2582 else if ((cur[0] == 't') && (cur[1] == 'r')
2583 && (cur[2] == 'u') && (cur[3] == 'e')
2586 else if ((cur[0] == 'f') && (cur[1] == 'a')
2587 && (cur[2] == 'l') && (cur[3] == 's')
2588 && (cur[4] == 'e') && (cur[5] == 0))
2594 v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
2604 case XML_SCHEMAS_TOKEN:{
2605 const xmlChar *cur = value;
2607 if (! normOnTheFly) {
2609 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2611 } else if (*cur == ' ') {
2623 v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
2625 v->value.str = xmlStrdup(value);
2633 case XML_SCHEMAS_LANGUAGE:
2635 norm = xmlSchemaCollapseString(value);
2639 if (xmlCheckLanguageID(value) == 1) {
2641 v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
2643 v->value.str = xmlStrdup(value);
2652 case XML_SCHEMAS_NMTOKEN:
2653 if (xmlValidateNMToken(value, 1) == 0) {
2655 v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
2657 v->value.str = xmlStrdup(value);
2666 case XML_SCHEMAS_NMTOKENS:
2667 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
2674 case XML_SCHEMAS_NAME:
2675 ret = xmlValidateName(value, 1);
2676 if ((ret == 0) && (val != NULL) && (value != NULL)) {
2677 v = xmlSchemaNewValue(XML_SCHEMAS_NAME);
2679 const xmlChar *start = value, *end;
2680 while (IS_BLANK_CH(*start)) start++;
2682 while ((*end != 0) && (!IS_BLANK_CH(*end))) end++;
2683 v->value.str = xmlStrndup(start, end - start);
2690 case XML_SCHEMAS_QNAME:{
2691 const xmlChar *uri = NULL;
2692 xmlChar *local = NULL;
2694 ret = xmlValidateQName(value, 1);
2701 local = xmlSplitQName2(value, &prefix);
2702 ns = xmlSearchNs(node->doc, node, prefix);
2703 if ((ns == NULL) && (prefix != NULL)) {
2715 v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
2722 v->value.qname.name = local;
2724 v->value.qname.name = xmlStrdup(value);
2726 v->value.qname.uri = xmlStrdup(uri);
2733 case XML_SCHEMAS_NCNAME:
2734 ret = xmlValidateNCName(value, 1);
2735 if ((ret == 0) && (val != NULL)) {
2736 v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
2738 v->value.str = xmlStrdup(value);
2745 case XML_SCHEMAS_ID:
2746 ret = xmlValidateNCName(value, 1);
2747 if ((ret == 0) && (val != NULL)) {
2748 v = xmlSchemaNewValue(XML_SCHEMAS_ID);
2750 v->value.str = xmlStrdup(value);
2756 if ((ret == 0) && (node != NULL) &&
2757 (node->type == XML_ATTRIBUTE_NODE)) {
2758 xmlAttrPtr attr = (xmlAttrPtr) node;
2761 * NOTE: the IDness might have already be declared in the DTD
2763 if (attr->atype != XML_ATTRIBUTE_ID) {
2767 strip = xmlSchemaStrip(value);
2768 if (strip != NULL) {
2769 res = xmlAddID(NULL, node->doc, strip, attr);
2772 res = xmlAddID(NULL, node->doc, value, attr);
2776 attr->atype = XML_ATTRIBUTE_ID;
2781 case XML_SCHEMAS_IDREF:
2782 ret = xmlValidateNCName(value, 1);
2783 if ((ret == 0) && (val != NULL)) {
2784 v = xmlSchemaNewValue(XML_SCHEMAS_IDREF);
2787 v->value.str = xmlStrdup(value);
2790 if ((ret == 0) && (node != NULL) &&
2791 (node->type == XML_ATTRIBUTE_NODE)) {
2792 xmlAttrPtr attr = (xmlAttrPtr) node;
2795 strip = xmlSchemaStrip(value);
2796 if (strip != NULL) {
2797 xmlAddRef(NULL, node->doc, strip, attr);
2800 xmlAddRef(NULL, node->doc, value, attr);
2801 attr->atype = XML_ATTRIBUTE_IDREF;
2804 case XML_SCHEMAS_IDREFS:
2805 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
2811 if ((ret == 0) && (node != NULL) &&
2812 (node->type == XML_ATTRIBUTE_NODE)) {
2813 xmlAttrPtr attr = (xmlAttrPtr) node;
2815 attr->atype = XML_ATTRIBUTE_IDREFS;
2818 case XML_SCHEMAS_ENTITY:{
2821 ret = xmlValidateNCName(value, 1);
2822 if ((node == NULL) || (node->doc == NULL))
2827 strip = xmlSchemaStrip(value);
2828 if (strip != NULL) {
2829 ent = xmlGetDocEntity(node->doc, strip);
2832 ent = xmlGetDocEntity(node->doc, value);
2834 if ((ent == NULL) ||
2836 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
2839 if ((ret == 0) && (val != NULL)) {
2842 if ((ret == 0) && (node != NULL) &&
2843 (node->type == XML_ATTRIBUTE_NODE)) {
2844 xmlAttrPtr attr = (xmlAttrPtr) node;
2846 attr->atype = XML_ATTRIBUTE_ENTITY;
2850 case XML_SCHEMAS_ENTITIES:
2851 if ((node == NULL) || (node->doc == NULL))
2853 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
2859 if ((ret == 0) && (node != NULL) &&
2860 (node->type == XML_ATTRIBUTE_NODE)) {
2861 xmlAttrPtr attr = (xmlAttrPtr) node;
2863 attr->atype = XML_ATTRIBUTE_ENTITIES;
2866 case XML_SCHEMAS_NOTATION:{
2867 xmlChar *uri = NULL;
2868 xmlChar *local = NULL;
2870 ret = xmlValidateQName(value, 1);
2871 if ((ret == 0) && (node != NULL)) {
2874 local = xmlSplitQName2(value, &prefix);
2875 if (prefix != NULL) {
2878 ns = xmlSearchNs(node->doc, node, prefix);
2881 else if (val != NULL)
2882 uri = xmlStrdup(ns->href);
2884 if ((local != NULL) && ((val == NULL) || (ret != 0)))
2889 if ((node == NULL) || (node->doc == NULL))
2892 ret = xmlValidateNotationUse(NULL, node->doc, value);
2898 if ((ret == 0) && (val != NULL)) {
2899 v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
2902 v->value.qname.name = local;
2904 v->value.qname.name = xmlStrdup(value);
2906 v->value.qname.uri = uri;
2919 case XML_SCHEMAS_ANYURI:{
2922 xmlChar *tmpval, *cur;
2924 norm = xmlSchemaCollapseString(value);
2928 tmpval = xmlStrdup(value);
2929 for (cur = tmpval; *cur; ++cur) {
2930 if (*cur < 32 || *cur >= 127 || *cur == ' ' ||
2931 *cur == '<' || *cur == '>' || *cur == '"' ||
2932 *cur == '{' || *cur == '}' || *cur == '|' ||
2933 *cur == '\\' || *cur == '^' || *cur == '`' ||
2937 uri = xmlParseURI((const char *) tmpval);
2945 v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI);
2948 v->value.str = xmlStrdup(value);
2953 case XML_SCHEMAS_HEXBINARY:{
2954 const xmlChar *cur = value, *start;
2962 while IS_WSP_BLANK_CH(*cur) cur++;
2965 while (((*cur >= '0') && (*cur <= '9')) ||
2966 ((*cur >= 'A') && (*cur <= 'F')) ||
2967 ((*cur >= 'a') && (*cur <= 'f'))) {
2972 while IS_WSP_BLANK_CH(*cur) cur++;
2981 v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
2985 * Copy only the normalized piece.
2986 * CRITICAL TODO: Check this.
2988 cur = xmlStrndup(start, i);
2990 xmlSchemaTypeErrMemory(node, "allocating hexbin data");
2995 total = i / 2; /* number of octets */
2997 base = (xmlChar *) cur;
3000 *base = *base - ('a' - 'A');
3004 v->value.hex.str = (xmlChar *) cur;
3005 v->value.hex.total = total;
3010 case XML_SCHEMAS_BASE64BINARY:{
3013 * Ignore all stray characters? (yes, currently)
3014 * Worry about long lines? (no, currently)
3018 * "The encoded output stream must be represented in lines of
3019 * no more than 76 characters each. All line breaks or other
3020 * characters not found in Table 1 must be ignored by decoding
3021 * software. In base64 data, characters other than those in
3022 * Table 1, line breaks, and other white space probably
3023 * indicate a transmission error, about which a warning
3024 * message or even a message rejection might be appropriate
3025 * under some circumstances." */
3026 const xmlChar *cur = value;
3028 int total, i = 0, pad = 0;
3033 for (; *cur; ++cur) {
3036 decc = _xmlSchemaBase64Decode(*cur);
3043 for (; *cur; ++cur) {
3046 decc = _xmlSchemaBase64Decode(*cur);
3054 /* rfc2045.txt: "Special processing is performed if fewer than
3055 * 24 bits are available at the end of the data being encoded.
3056 * A full encoding quantum is always completed at the end of a
3057 * body. When fewer than 24 input bits are available in an
3058 * input group, zero bits are added (on the right) to form an
3059 * integral number of 6-bit groups. Padding at the end of the
3060 * data is performed using the "=" character. Since all
3061 * base64 input is an integral number of octets, only the
3062 * following cases can arise: (1) the final quantum of
3063 * encoding input is an integral multiple of 24 bits; here,
3064 * the final unit of encoded output will be an integral
3065 * multiple ofindent: Standard input:701: Warning:old style
3066 * assignment ambiguity in "=*". Assuming "= *" 4 characters
3067 * with no "=" padding, (2) the final
3068 * quantum of encoding input is exactly 8 bits; here, the
3069 * final unit of encoded output will be two characters
3070 * followed by two "=" padding characters, or (3) the final
3071 * quantum of encoding input is exactly 16 bits; here, the
3072 * final unit of encoded output will be three characters
3073 * followed by one "=" padding character." */
3075 total = 3 * (i / 4);
3079 } else if (pad == 1) {
3084 for (decc = _xmlSchemaBase64Decode(*cur);
3085 (decc < 0) || (decc > 63);
3086 decc = _xmlSchemaBase64Decode(*cur))
3088 /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
3089 /* 00111100 -> 0x3c */
3093 } else if (pad == 2) {
3098 for (decc = _xmlSchemaBase64Decode(*cur);
3099 (decc < 0) || (decc > 63);
3100 decc = _xmlSchemaBase64Decode(*cur))
3102 /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
3103 /* 00110000 -> 0x30 */
3111 v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
3115 (xmlChar *) xmlMallocAtomic((i + pad + 1) *
3118 xmlSchemaTypeErrMemory(node, "allocating base64 data");
3122 v->value.base64.str = base;
3123 for (cur = value; *cur; ++cur)
3124 if (_xmlSchemaBase64Decode(*cur) >= 0) {
3129 v->value.base64.total = total;
3134 case XML_SCHEMAS_INTEGER:
3135 case XML_SCHEMAS_PINTEGER:
3136 case XML_SCHEMAS_NPINTEGER:
3137 case XML_SCHEMAS_NINTEGER:
3138 case XML_SCHEMAS_NNINTEGER:{
3139 const xmlChar *cur = value;
3140 unsigned long lo, mi, hi;
3146 while IS_WSP_BLANK_CH(*cur) cur++;
3150 } else if (*cur == '+')
3152 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3156 while IS_WSP_BLANK_CH(*cur) cur++;
3159 if (type->builtInType == XML_SCHEMAS_NPINTEGER) {
3161 ((hi != 0) || (mi != 0) || (lo != 0)))
3163 } else if (type->builtInType == XML_SCHEMAS_PINTEGER) {
3166 if ((hi == 0) && (mi == 0) && (lo == 0))
3168 } else if (type->builtInType == XML_SCHEMAS_NINTEGER) {
3171 if ((hi == 0) && (mi == 0) && (lo == 0))
3173 } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) {
3175 ((hi != 0) || (mi != 0) || (lo != 0)))
3179 v = xmlSchemaNewValue(type->builtInType);
3183 v->value.decimal.lo = lo;
3184 v->value.decimal.mi = mi;
3185 v->value.decimal.hi = hi;
3186 v->value.decimal.sign = sign;
3187 v->value.decimal.frac = 0;
3188 v->value.decimal.total = ret;
3194 case XML_SCHEMAS_LONG:
3195 case XML_SCHEMAS_BYTE:
3196 case XML_SCHEMAS_SHORT:
3197 case XML_SCHEMAS_INT:{
3198 const xmlChar *cur = value;
3199 unsigned long lo, mi, hi;
3207 } else if (*cur == '+')
3209 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3214 if (type->builtInType == XML_SCHEMAS_LONG) {
3218 if (mi >= 33720368) {
3221 if ((sign == 0) && (lo > 54775807))
3223 if ((sign == 1) && (lo > 54775808))
3227 } else if (type->builtInType == XML_SCHEMAS_INT) {
3233 if ((sign == 0) && (lo > 47483647))
3235 if ((sign == 1) && (lo > 47483648))
3238 } else if (type->builtInType == XML_SCHEMAS_SHORT) {
3239 if ((mi != 0) || (hi != 0))
3241 if ((sign == 1) && (lo > 32768))
3243 if ((sign == 0) && (lo > 32767))
3245 } else if (type->builtInType == XML_SCHEMAS_BYTE) {
3246 if ((mi != 0) || (hi != 0))
3248 if ((sign == 1) && (lo > 128))
3250 if ((sign == 0) && (lo > 127))
3254 v = xmlSchemaNewValue(type->builtInType);
3256 v->value.decimal.lo = lo;
3257 v->value.decimal.mi = mi;
3258 v->value.decimal.hi = hi;
3259 v->value.decimal.sign = sign;
3260 v->value.decimal.frac = 0;
3261 v->value.decimal.total = ret;
3267 case XML_SCHEMAS_UINT:
3268 case XML_SCHEMAS_ULONG:
3269 case XML_SCHEMAS_USHORT:
3270 case XML_SCHEMAS_UBYTE:{
3271 const xmlChar *cur = value;
3272 unsigned long lo, mi, hi;
3276 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3281 if (type->builtInType == XML_SCHEMAS_ULONG) {
3285 if (mi >= 67440737) {
3292 } else if (type->builtInType == XML_SCHEMAS_UINT) {
3301 } else if (type->builtInType == XML_SCHEMAS_USHORT) {
3302 if ((mi != 0) || (hi != 0))
3306 } else if (type->builtInType == XML_SCHEMAS_UBYTE) {
3307 if ((mi != 0) || (hi != 0))
3313 v = xmlSchemaNewValue(type->builtInType);
3315 v->value.decimal.lo = lo;
3316 v->value.decimal.mi = mi;
3317 v->value.decimal.hi = hi;
3318 v->value.decimal.sign = 0;
3319 v->value.decimal.frac = 0;
3320 v->value.decimal.total = ret;
3351 * xmlSchemaValPredefTypeNode:
3352 * @type: the predefined type
3353 * @value: the value to check
3354 * @val: the return computed value
3355 * @node: the node containing the value
3357 * Check that a value conforms to the lexical space of the predefined type.
3358 * if true a value is computed and returned in @val.
3360 * Returns 0 if this validates, a positive error code number otherwise
3361 * and -1 in case of internal or API error.
3364 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
3365 xmlSchemaValPtr *val, xmlNodePtr node) {
3366 return(xmlSchemaValAtomicType(type, value, val, node, 0,
3367 XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 1, 0));
3371 * xmlSchemaValPredefTypeNodeNoNorm:
3372 * @type: the predefined type
3373 * @value: the value to check
3374 * @val: the return computed value
3375 * @node: the node containing the value
3377 * Check that a value conforms to the lexical space of the predefined type.
3378 * if true a value is computed and returned in @val.
3379 * This one does apply any normalization to the value.
3381 * Returns 0 if this validates, a positive error code number otherwise
3382 * and -1 in case of internal or API error.
3385 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value,
3386 xmlSchemaValPtr *val, xmlNodePtr node) {
3387 return(xmlSchemaValAtomicType(type, value, val, node, 1,
3388 XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 0, 1));
3392 * xmlSchemaValidatePredefinedType:
3393 * @type: the predefined type
3394 * @value: the value to check
3395 * @val: the return computed value
3397 * Check that a value conforms to the lexical space of the predefined type.
3398 * if true a value is computed and returned in @val.
3400 * Returns 0 if this validates, a positive error code number otherwise
3401 * and -1 in case of internal or API error.
3404 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
3405 xmlSchemaValPtr *val) {
3406 return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
3410 * xmlSchemaCompareDecimals:
3411 * @x: a first decimal value
3412 * @y: a second decimal value
3414 * Compare 2 decimals
3416 * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
3419 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
3421 xmlSchemaValPtr swp;
3422 int order = 1, integx, integy, dlen;
3423 unsigned long hi, mi, lo;
3426 * First test: If x is -ve and not zero
3428 if ((x->value.decimal.sign) &&
3429 ((x->value.decimal.lo != 0) ||
3430 (x->value.decimal.mi != 0) ||
3431 (x->value.decimal.hi != 0))) {
3433 * Then if y is -ve and not zero reverse the compare
3435 if ((y->value.decimal.sign) &&
3436 ((y->value.decimal.lo != 0) ||
3437 (y->value.decimal.mi != 0) ||
3438 (y->value.decimal.hi != 0)))
3441 * Otherwise (y >= 0) we have the answer
3446 * If x is not -ve and y is -ve we have the answer
3448 } else if ((y->value.decimal.sign) &&
3449 ((y->value.decimal.lo != 0) ||
3450 (y->value.decimal.mi != 0) ||
3451 (y->value.decimal.hi != 0))) {
3455 * If it's not simply determined by a difference in sign,
3456 * then we need to compare the actual values of the two nums.
3457 * To do this, we start by looking at the integral parts.
3458 * If the number of integral digits differ, then we have our
3461 integx = x->value.decimal.total - x->value.decimal.frac;
3462 integy = y->value.decimal.total - y->value.decimal.frac;
3464 * NOTE: We changed the "total" for values like "0.1"
3465 * (or "-0.1" or ".1") to be 1, which was 2 previously.
3466 * Therefore the special case, when such values are
3467 * compared with 0, needs to be handled separately;
3468 * otherwise a zero would be recognized incorrectly as
3469 * greater than those values. This has the nice side effect
3470 * that we gain an overall optimized comparison with zeroes.
3471 * Note that a "0" has a "total" of 1 already.
3474 if (x->value.decimal.lo == 0) {
3477 else if (y->value.decimal.lo != 0)
3484 if (y->value.decimal.lo == 0) {
3487 else if (x->value.decimal.lo != 0)
3494 if (integx > integy)
3496 else if (integy > integx)
3500 * If the number of integral digits is the same for both numbers,
3501 * then things get a little more complicated. We need to "normalize"
3502 * the numbers in order to properly compare them. To do this, we
3503 * look at the total length of each number (length => number of
3504 * significant digits), and divide the "shorter" by 10 (decreasing
3505 * the length) until they are of equal length.
3507 dlen = x->value.decimal.total - y->value.decimal.total;
3508 if (dlen < 0) { /* y has more digits than x */
3510 hi = y->value.decimal.hi;
3511 mi = y->value.decimal.mi;
3512 lo = y->value.decimal.lo;
3515 } else { /* x has more digits than y */
3517 hi = x->value.decimal.hi;
3518 mi = x->value.decimal.mi;
3519 lo = x->value.decimal.lo;
3521 while (dlen > 8) { /* in effect, right shift by 10**8 */
3528 unsigned long rem1, rem2;
3529 rem1 = (hi % 10) * 100000000L;
3531 rem2 = (mi % 10) * 100000000L;
3532 mi = (mi + rem1) / 10;
3533 lo = (lo + rem2) / 10;
3536 if (hi > swp->value.decimal.hi) {
3538 } else if (hi == swp->value.decimal.hi) {
3539 if (mi > swp->value.decimal.mi) {
3541 } else if (mi == swp->value.decimal.mi) {
3542 if (lo > swp->value.decimal.lo) {
3544 } else if (lo == swp->value.decimal.lo) {
3545 if (x->value.decimal.total == y->value.decimal.total) {
3557 * xmlSchemaCompareDurations:
3558 * @x: a first duration value
3559 * @y: a second duration value
3561 * Compare 2 durations
3563 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3567 xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
3569 long carry, mon, day;
3572 long xmon, xday, myear, minday, maxday;
3573 static const long dayRange [2][12] = {
3574 { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
3575 { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
3577 if ((x == NULL) || (y == NULL))
3581 mon = x->value.dur.mon - y->value.dur.mon;
3584 sec = x->value.dur.sec - y->value.dur.sec;
3585 carry = (long)(sec / SECS_PER_DAY);
3586 sec -= ((double)carry) * SECS_PER_DAY;
3589 day = x->value.dur.day - y->value.dur.day + carry;
3607 if ((day >= 0) && (sec >= 0.0))
3613 } else if ((day <= 0) && (sec <= 0.0)) {
3626 maxday = 366 * ((myear + 3) / 4) +
3627 365 * ((myear - 1) % 4);
3628 minday = maxday - 1;
3632 minday += dayRange[0][xmon];
3633 maxday += dayRange[1][xmon];
3635 if ((maxday == minday) && (maxday == xday))
3636 return(0); /* can this really happen ? */
3647 * macros for adding date/times and durations
3649 #define FQUOTIENT(a,b) (floor(((double)a/(double)b)))
3650 #define MODULO(a,b) (a - FQUOTIENT(a,b) * b)
3651 #define FQUOTIENT_RANGE(a,low,high) (FQUOTIENT((a-low),(high-low)))
3652 #define MODULO_RANGE(a,low,high) ((MODULO((a-low),(high-low)))+low)
3656 * @v: the #xmlSchemaValPtr value to duplicate
3658 * Makes a copy of @v. The calling program is responsible for freeing
3659 * the returned value.
3661 * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error.
3663 static xmlSchemaValPtr
3664 xmlSchemaDupVal (xmlSchemaValPtr v)
3666 xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
3670 memcpy(ret, v, sizeof(xmlSchemaVal));
3676 * xmlSchemaCopyValue:
3677 * @val: the precomputed value to be copied
3679 * Copies the precomputed value. This duplicates any string within.
3681 * Returns the copy or NULL if a copy for a data-type is not implemented.
3684 xmlSchemaCopyValue(xmlSchemaValPtr val)
3686 xmlSchemaValPtr ret = NULL, prev = NULL, cur;
3689 * Copy the string values.
3691 while (val != NULL) {
3692 switch (val->type) {
3693 case XML_SCHEMAS_ANYTYPE:
3694 case XML_SCHEMAS_IDREFS:
3695 case XML_SCHEMAS_ENTITIES:
3696 case XML_SCHEMAS_NMTOKENS:
3697 xmlSchemaFreeValue(ret);
3699 case XML_SCHEMAS_ANYSIMPLETYPE:
3700 case XML_SCHEMAS_STRING:
3701 case XML_SCHEMAS_NORMSTRING:
3702 case XML_SCHEMAS_TOKEN:
3703 case XML_SCHEMAS_LANGUAGE:
3704 case XML_SCHEMAS_NAME:
3705 case XML_SCHEMAS_NCNAME:
3706 case XML_SCHEMAS_ID:
3707 case XML_SCHEMAS_IDREF:
3708 case XML_SCHEMAS_ENTITY:
3709 case XML_SCHEMAS_NMTOKEN:
3710 case XML_SCHEMAS_ANYURI:
3711 cur = xmlSchemaDupVal(val);
3712 if (val->value.str != NULL)
3713 cur->value.str = xmlStrdup(BAD_CAST val->value.str);
3715 case XML_SCHEMAS_QNAME:
3716 case XML_SCHEMAS_NOTATION:
3717 cur = xmlSchemaDupVal(val);
3718 if (val->value.qname.name != NULL)
3719 cur->value.qname.name =
3720 xmlStrdup(BAD_CAST val->value.qname.name);
3721 if (val->value.qname.uri != NULL)
3722 cur->value.qname.uri =
3723 xmlStrdup(BAD_CAST val->value.qname.uri);
3725 case XML_SCHEMAS_HEXBINARY:
3726 cur = xmlSchemaDupVal(val);
3727 if (val->value.hex.str != NULL)
3728 cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str);
3730 case XML_SCHEMAS_BASE64BINARY:
3731 cur = xmlSchemaDupVal(val);
3732 if (val->value.base64.str != NULL)
3733 cur->value.base64.str =
3734 xmlStrdup(BAD_CAST val->value.base64.str);
3737 cur = xmlSchemaDupVal(val);
3751 * _xmlSchemaDateAdd:
3752 * @dt: an #xmlSchemaValPtr
3753 * @dur: an #xmlSchemaValPtr of type #XS_DURATION
3755 * Compute a new date/time from @dt and @dur. This function assumes @dt
3756 * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
3757 * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as
3758 * @dt. The calling program is responsible for freeing the returned value.
3760 * Returns a pointer to a new #xmlSchemaVal or NULL if error.
3762 static xmlSchemaValPtr
3763 _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
3765 xmlSchemaValPtr ret, tmp;
3766 long carry, tempdays, temp;
3767 xmlSchemaValDatePtr r, d;
3768 xmlSchemaValDurationPtr u;
3770 if ((dt == NULL) || (dur == NULL))
3773 ret = xmlSchemaNewValue(dt->type);
3777 /* make a copy so we don't alter the original value */
3778 tmp = xmlSchemaDupVal(dt);
3780 xmlSchemaFreeValue(ret);
3784 r = &(ret->value.date);
3785 d = &(tmp->value.date);
3786 u = &(dur->value.dur);
3792 /* normalize for time zone offset */
3793 u->sec -= (d->tzo * 60);
3801 carry = d->mon + u->mon;
3802 r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13);
3803 carry = (long) FQUOTIENT_RANGE(carry, 1, 13);
3805 /* year (may be modified later) */
3806 r->year = d->year + carry;
3816 r->tz_flag = d->tz_flag;
3819 r->sec = d->sec + u->sec;
3820 carry = (long) FQUOTIENT((long)r->sec, 60);
3821 if (r->sec != 0.0) {
3822 r->sec = MODULO(r->sec, 60.0);
3827 r->min = (unsigned int) MODULO(carry, 60);
3828 carry = (long) FQUOTIENT(carry, 60);
3832 r->hour = (unsigned int) MODULO(carry, 24);
3833 carry = (long)FQUOTIENT(carry, 24);
3837 * Note we use tempdays because the temporary values may need more
3840 if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
3841 (d->day > MAX_DAYINMONTH(r->year, r->mon)))
3842 tempdays = MAX_DAYINMONTH(r->year, r->mon);
3843 else if (d->day < 1)
3848 tempdays += u->day + carry;
3852 long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13);
3853 long tyr = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13);
3857 * Coverity detected an overrun in daysInMonth
3858 * of size 12 at position 12 with index variable "((r)->mon - 1)"
3864 tempdays += MAX_DAYINMONTH(tyr, tmon);
3866 } else if (VALID_YEAR(r->year) && VALID_MONTH(r->mon) &&
3867 tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) {
3868 tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
3873 temp = r->mon + carry;
3874 r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13);
3875 r->year = r->year + (unsigned int) FQUOTIENT_RANGE(temp, 1, 13);
3887 * adjust the date/time type to the date values
3889 if (ret->type != XML_SCHEMAS_DATETIME) {
3890 if ((r->hour) || (r->min) || (r->sec))
3891 ret->type = XML_SCHEMAS_DATETIME;
3892 else if (ret->type != XML_SCHEMAS_DATE) {
3893 if ((r->mon != 1) && (r->day != 1))
3894 ret->type = XML_SCHEMAS_DATE;
3895 else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
3896 ret->type = XML_SCHEMAS_GYEARMONTH;
3900 xmlSchemaFreeValue(tmp);
3906 * xmlSchemaDateNormalize:
3907 * @dt: an #xmlSchemaValPtr of a date/time type value.
3908 * @offset: number of seconds to adjust @dt by.
3910 * Normalize @dt to GMT time. The @offset parameter is subtracted from
3911 * the return value is a time-zone offset is present on @dt.
3913 * Returns a normalized copy of @dt or NULL if error.
3915 static xmlSchemaValPtr
3916 xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
3918 xmlSchemaValPtr dur, ret;
3923 if (((dt->type != XML_SCHEMAS_TIME) &&
3924 (dt->type != XML_SCHEMAS_DATETIME) &&
3925 (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0))
3926 return xmlSchemaDupVal(dt);
3928 dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
3932 dur->value.date.sec -= offset;
3934 ret = _xmlSchemaDateAdd(dt, dur);
3938 xmlSchemaFreeValue(dur);
3940 /* ret->value.date.tzo = 0; */
3945 * _xmlSchemaDateCastYMToDays:
3946 * @dt: an #xmlSchemaValPtr
3948 * Convert mon and year of @dt to total number of days. Take the
3949 * number of years since (or before) 1 AD and add the number of leap
3950 * years. This is a function because negative
3951 * years must be handled a little differently and there is no zero year.
3953 * Returns number of days.
3956 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
3961 mon = dt->value.date.mon;
3962 if (mon <= 0) mon = 1; /* normalization */
3964 if (dt->value.date.year <= 0)
3965 ret = (dt->value.date.year * 365) +
3966 (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
3967 ((dt->value.date.year+1)/400)) +
3968 DAY_IN_YEAR(0, mon, dt->value.date.year);
3970 ret = ((dt->value.date.year-1) * 365) +
3971 (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
3972 ((dt->value.date.year-1)/400)) +
3973 DAY_IN_YEAR(0, mon, dt->value.date.year);
3980 * @dt: an #xmlSchemaValPtr
3982 * Calculates the number of seconds in the time portion of @dt.
3986 #define TIME_TO_NUMBER(dt) \
3987 ((double)((dt->value.date.hour * SECS_PER_HOUR) + \
3988 (dt->value.date.min * SECS_PER_MIN) + \
3989 (dt->value.date.tzo * SECS_PER_MIN)) + \
3993 * xmlSchemaCompareDates:
3994 * @x: a first date/time value
3995 * @y: a second date/time value
3997 * Compare 2 date/times
3999 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4003 xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
4005 unsigned char xmask, ymask, xor_mask, and_mask;
4006 xmlSchemaValPtr p1, p2, q1, q2;
4007 long p1d, p2d, q1d, q2d;
4009 if ((x == NULL) || (y == NULL))
4012 if (x->value.date.tz_flag) {
4014 if (!y->value.date.tz_flag) {
4015 p1 = xmlSchemaDateNormalize(x, 0);
4016 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4017 /* normalize y + 14:00 */
4018 q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
4020 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4022 xmlSchemaFreeValue(p1);
4023 xmlSchemaFreeValue(q1);
4025 } else if (p1d == q1d) {
4028 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4030 xmlSchemaFreeValue(p1);
4031 xmlSchemaFreeValue(q1);
4035 /* normalize y - 14:00 */
4036 q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
4037 q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
4040 else if (p1d == q2d) {
4041 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
4045 ret = 2; /* indeterminate */
4047 xmlSchemaFreeValue(p1);
4048 xmlSchemaFreeValue(q1);
4049 xmlSchemaFreeValue(q2);
4054 xmlSchemaFreeValue(p1);
4055 xmlSchemaFreeValue(q1);
4058 } else if (y->value.date.tz_flag) {
4059 q1 = xmlSchemaDateNormalize(y, 0);
4060 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4062 /* normalize x - 14:00 */
4063 p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
4064 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4067 xmlSchemaFreeValue(p1);
4068 xmlSchemaFreeValue(q1);
4070 } else if (p1d == q1d) {
4073 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4075 xmlSchemaFreeValue(p1);
4076 xmlSchemaFreeValue(q1);
4080 /* normalize x + 14:00 */
4081 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
4082 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
4086 } else if (p2d == q1d) {
4087 sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
4091 ret = 2; /* indeterminate */
4093 xmlSchemaFreeValue(p1);
4094 xmlSchemaFreeValue(q1);
4095 xmlSchemaFreeValue(p2);
4100 xmlSchemaFreeValue(p1);
4101 xmlSchemaFreeValue(q1);
4106 * if the same type then calculate the difference
4108 if (x->type == y->type) {
4110 q1 = xmlSchemaDateNormalize(y, 0);
4111 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4113 p1 = xmlSchemaDateNormalize(x, 0);
4114 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4118 } else if (p1d > q1d) {
4123 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4130 xmlSchemaFreeValue(p1);
4131 xmlSchemaFreeValue(q1);
4136 case XML_SCHEMAS_DATETIME:
4139 case XML_SCHEMAS_DATE:
4142 case XML_SCHEMAS_GYEAR:
4145 case XML_SCHEMAS_GMONTH:
4148 case XML_SCHEMAS_GDAY:
4151 case XML_SCHEMAS_GYEARMONTH:
4154 case XML_SCHEMAS_GMONTHDAY:
4157 case XML_SCHEMAS_TIME:
4166 case XML_SCHEMAS_DATETIME:
4169 case XML_SCHEMAS_DATE:
4172 case XML_SCHEMAS_GYEAR:
4175 case XML_SCHEMAS_GMONTH:
4178 case XML_SCHEMAS_GDAY:
4181 case XML_SCHEMAS_GYEARMONTH:
4184 case XML_SCHEMAS_GMONTHDAY:
4187 case XML_SCHEMAS_TIME:
4195 xor_mask = xmask ^ ymask; /* mark type differences */
4196 and_mask = xmask & ymask; /* mark field specification */
4200 return 2; /* indeterminate */
4201 else if (and_mask & 1) {
4202 if (x->value.date.year < y->value.date.year)
4204 else if (x->value.date.year > y->value.date.year)
4210 return 2; /* indeterminate */
4211 else if (and_mask & 2) {
4212 if (x->value.date.mon < y->value.date.mon)
4214 else if (x->value.date.mon > y->value.date.mon)
4220 return 2; /* indeterminate */
4221 else if (and_mask & 4) {
4222 if (x->value.date.day < y->value.date.day)
4224 else if (x->value.date.day > y->value.date.day)
4230 return 2; /* indeterminate */
4231 else if (and_mask & 8) {
4232 if (x->value.date.hour < y->value.date.hour)
4234 else if (x->value.date.hour > y->value.date.hour)
4236 else if (x->value.date.min < y->value.date.min)
4238 else if (x->value.date.min > y->value.date.min)
4240 else if (x->value.date.sec < y->value.date.sec)
4242 else if (x->value.date.sec > y->value.date.sec)
4250 * xmlSchemaComparePreserveReplaceStrings:
4251 * @x: a first string value
4252 * @y: a second string value
4253 * @invert: inverts the result if x < y or x > y.
4255 * Compare 2 string for their normalized values.
4256 * @x is a string with whitespace of "preserve", @y is
4257 * a string with a whitespace of "replace". I.e. @x could
4258 * be an "xsd:string" and @y an "xsd:normalizedString".
4260 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4264 xmlSchemaComparePreserveReplaceStrings(const xmlChar *x,
4270 while ((*x != 0) && (*y != 0)) {
4271 if (IS_WSP_REPLACE_CH(*y)) {
4272 if (! IS_WSP_SPACE_CH(*x)) {
4273 if ((*x - 0x20) < 0) {
4319 * xmlSchemaComparePreserveCollapseStrings:
4320 * @x: a first string value
4321 * @y: a second string value
4323 * Compare 2 string for their normalized values.
4324 * @x is a string with whitespace of "preserve", @y is
4325 * a string with a whitespace of "collapse". I.e. @x could
4326 * be an "xsd:string" and @y an "xsd:normalizedString".
4328 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4332 xmlSchemaComparePreserveCollapseStrings(const xmlChar *x,
4339 * Skip leading blank chars of the collapsed string.
4341 while IS_WSP_BLANK_CH(*y)
4344 while ((*x != 0) && (*y != 0)) {
4345 if IS_WSP_BLANK_CH(*y) {
4346 if (! IS_WSP_SPACE_CH(*x)) {
4348 * The yv character would have been replaced to 0x20.
4350 if ((*x - 0x20) < 0) {
4365 * Skip contiguous blank chars of the collapsed string.
4367 while IS_WSP_BLANK_CH(*y)
4393 * Skip trailing blank chars of the collapsed string.
4395 while IS_WSP_BLANK_CH(*y)
4408 * xmlSchemaComparePreserveCollapseStrings:
4409 * @x: a first string value
4410 * @y: a second string value
4412 * Compare 2 string for their normalized values.
4413 * @x is a string with whitespace of "preserve", @y is
4414 * a string with a whitespace of "collapse". I.e. @x could
4415 * be an "xsd:string" and @y an "xsd:normalizedString".
4417 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4421 xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x,
4428 * Skip leading blank chars of the collapsed string.
4430 while IS_WSP_BLANK_CH(*y)
4433 while ((*x != 0) && (*y != 0)) {
4434 if IS_WSP_BLANK_CH(*y) {
4435 if (! IS_WSP_BLANK_CH(*x)) {
4437 * The yv character would have been replaced to 0x20.
4439 if ((*x - 0x20) < 0) {
4454 * Skip contiguous blank chars of the collapsed string.
4456 while IS_WSP_BLANK_CH(*y)
4459 if IS_WSP_BLANK_CH(*x) {
4461 * The xv character would have been replaced to 0x20.
4463 if ((0x20 - *y) < 0) {
4490 * Skip trailing blank chars of the collapsed string.
4492 while IS_WSP_BLANK_CH(*y)
4506 * xmlSchemaCompareReplacedStrings:
4507 * @x: a first string value
4508 * @y: a second string value
4510 * Compare 2 string for their normalized values.
4512 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4516 xmlSchemaCompareReplacedStrings(const xmlChar *x,
4521 while ((*x != 0) && (*y != 0)) {
4522 if IS_WSP_BLANK_CH(*y) {
4523 if (! IS_WSP_BLANK_CH(*x)) {
4524 if ((*x - 0x20) < 0)
4530 if IS_WSP_BLANK_CH(*x) {
4531 if ((0x20 - *y) < 0)
4553 * xmlSchemaCompareNormStrings:
4554 * @x: a first string value
4555 * @y: a second string value
4557 * Compare 2 string for their normalized values.
4559 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4563 xmlSchemaCompareNormStrings(const xmlChar *x,
4567 while (IS_BLANK_CH(*x)) x++;
4568 while (IS_BLANK_CH(*y)) y++;
4569 while ((*x != 0) && (*y != 0)) {
4570 if (IS_BLANK_CH(*x)) {
4571 if (!IS_BLANK_CH(*y)) {
4575 while (IS_BLANK_CH(*x)) x++;
4576 while (IS_BLANK_CH(*y)) y++;
4586 while (IS_BLANK_CH(*x)) x++;
4591 while (IS_BLANK_CH(*y)) y++;
4599 * xmlSchemaCompareFloats:
4600 * @x: a first float or double value
4601 * @y: a second float or double value
4605 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4609 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
4612 if ((x == NULL) || (y == NULL))
4616 * Cast everything to doubles.
4618 if (x->type == XML_SCHEMAS_DOUBLE)
4620 else if (x->type == XML_SCHEMAS_FLOAT)
4625 if (y->type == XML_SCHEMAS_DOUBLE)
4627 else if (y->type == XML_SCHEMAS_FLOAT)
4633 * Check for special cases.
4635 if (xmlXPathIsNaN(d1)) {
4636 if (xmlXPathIsNaN(d2))
4640 if (xmlXPathIsNaN(d2))
4642 if (d1 == xmlXPathPINF) {
4643 if (d2 == xmlXPathPINF)
4647 if (d2 == xmlXPathPINF)
4649 if (d1 == xmlXPathNINF) {
4650 if (d2 == xmlXPathNINF)
4654 if (d2 == xmlXPathNINF)
4658 * basic tests, the last one we should have equality, but
4659 * portability is more important than speed and handling
4660 * NaN or Inf in a portable way is always a challenge, so ...
4672 * xmlSchemaCompareValues:
4674 * @xvalue: the first value as a string (optional)
4675 * @xwtsp: the whitespace type
4676 * @y: a second value
4677 * @xvalue: the second value as a string (optional)
4678 * @ywtsp: the whitespace type
4682 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not
4683 * comparable and -2 in case of error
4686 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
4688 const xmlChar *xvalue,
4689 xmlSchemaWhitespaceValueType xws,
4690 xmlSchemaValType ytype,
4692 const xmlChar *yvalue,
4693 xmlSchemaWhitespaceValueType yws)
4696 case XML_SCHEMAS_UNKNOWN:
4697 case XML_SCHEMAS_ANYTYPE:
4699 case XML_SCHEMAS_INTEGER:
4700 case XML_SCHEMAS_NPINTEGER:
4701 case XML_SCHEMAS_NINTEGER:
4702 case XML_SCHEMAS_NNINTEGER:
4703 case XML_SCHEMAS_PINTEGER:
4704 case XML_SCHEMAS_INT:
4705 case XML_SCHEMAS_UINT:
4706 case XML_SCHEMAS_LONG:
4707 case XML_SCHEMAS_ULONG:
4708 case XML_SCHEMAS_SHORT:
4709 case XML_SCHEMAS_USHORT:
4710 case XML_SCHEMAS_BYTE:
4711 case XML_SCHEMAS_UBYTE:
4712 case XML_SCHEMAS_DECIMAL:
4713 if ((x == NULL) || (y == NULL))
4716 return(xmlSchemaCompareDecimals(x, y));
4717 if ((ytype == XML_SCHEMAS_DECIMAL) ||
4718 (ytype == XML_SCHEMAS_INTEGER) ||
4719 (ytype == XML_SCHEMAS_NPINTEGER) ||
4720 (ytype == XML_SCHEMAS_NINTEGER) ||
4721 (ytype == XML_SCHEMAS_NNINTEGER) ||
4722 (ytype == XML_SCHEMAS_PINTEGER) ||
4723 (ytype == XML_SCHEMAS_INT) ||
4724 (ytype == XML_SCHEMAS_UINT) ||
4725 (ytype == XML_SCHEMAS_LONG) ||
4726 (ytype == XML_SCHEMAS_ULONG) ||
4727 (ytype == XML_SCHEMAS_SHORT) ||
4728 (ytype == XML_SCHEMAS_USHORT) ||
4729 (ytype == XML_SCHEMAS_BYTE) ||
4730 (ytype == XML_SCHEMAS_UBYTE))
4731 return(xmlSchemaCompareDecimals(x, y));
4733 case XML_SCHEMAS_DURATION:
4734 if ((x == NULL) || (y == NULL))
4736 if (ytype == XML_SCHEMAS_DURATION)
4737 return(xmlSchemaCompareDurations(x, y));
4739 case XML_SCHEMAS_TIME:
4740 case XML_SCHEMAS_GDAY:
4741 case XML_SCHEMAS_GMONTH:
4742 case XML_SCHEMAS_GMONTHDAY:
4743 case XML_SCHEMAS_GYEAR:
4744 case XML_SCHEMAS_GYEARMONTH:
4745 case XML_SCHEMAS_DATE:
4746 case XML_SCHEMAS_DATETIME:
4747 if ((x == NULL) || (y == NULL))
4749 if ((ytype == XML_SCHEMAS_DATETIME) ||
4750 (ytype == XML_SCHEMAS_TIME) ||
4751 (ytype == XML_SCHEMAS_GDAY) ||
4752 (ytype == XML_SCHEMAS_GMONTH) ||
4753 (ytype == XML_SCHEMAS_GMONTHDAY) ||
4754 (ytype == XML_SCHEMAS_GYEAR) ||
4755 (ytype == XML_SCHEMAS_DATE) ||
4756 (ytype == XML_SCHEMAS_GYEARMONTH))
4757 return (xmlSchemaCompareDates(x, y));
4760 * Note that we will support comparison of string types against
4761 * anySimpleType as well.
4763 case XML_SCHEMAS_ANYSIMPLETYPE:
4764 case XML_SCHEMAS_STRING:
4765 case XML_SCHEMAS_NORMSTRING:
4766 case XML_SCHEMAS_TOKEN:
4767 case XML_SCHEMAS_LANGUAGE:
4768 case XML_SCHEMAS_NMTOKEN:
4769 case XML_SCHEMAS_NAME:
4770 case XML_SCHEMAS_NCNAME:
4771 case XML_SCHEMAS_ID:
4772 case XML_SCHEMAS_IDREF:
4773 case XML_SCHEMAS_ENTITY:
4774 case XML_SCHEMAS_ANYURI:
4776 const xmlChar *xv, *yv;
4787 * TODO: Compare those against QName.
4789 if (ytype == XML_SCHEMAS_QNAME) {
4795 if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) ||
4796 (ytype == XML_SCHEMAS_STRING) ||
4797 (ytype == XML_SCHEMAS_NORMSTRING) ||
4798 (ytype == XML_SCHEMAS_TOKEN) ||
4799 (ytype == XML_SCHEMAS_LANGUAGE) ||
4800 (ytype == XML_SCHEMAS_NMTOKEN) ||
4801 (ytype == XML_SCHEMAS_NAME) ||
4802 (ytype == XML_SCHEMAS_NCNAME) ||
4803 (ytype == XML_SCHEMAS_ID) ||
4804 (ytype == XML_SCHEMAS_IDREF) ||
4805 (ytype == XML_SCHEMAS_ENTITY) ||
4806 (ytype == XML_SCHEMAS_ANYURI)) {
4808 if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) {
4810 if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) {
4811 /* TODO: What about x < y or x > y. */
4812 if (xmlStrEqual(xv, yv))
4816 } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4817 return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0));
4818 else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4819 return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0));
4821 } else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) {
4823 if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
4824 return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1));
4825 if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4826 return (xmlSchemaCompareReplacedStrings(xv, yv));
4827 if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4828 return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0));
4830 } else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
4832 if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
4833 return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1));
4834 if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4835 return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1));
4836 if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4837 return (xmlSchemaCompareNormStrings(xv, yv));
4844 case XML_SCHEMAS_QNAME:
4845 case XML_SCHEMAS_NOTATION:
4846 if ((x == NULL) || (y == NULL))
4848 if ((ytype == XML_SCHEMAS_QNAME) ||
4849 (ytype == XML_SCHEMAS_NOTATION)) {
4850 if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
4851 (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
4856 case XML_SCHEMAS_FLOAT:
4857 case XML_SCHEMAS_DOUBLE:
4858 if ((x == NULL) || (y == NULL))
4860 if ((ytype == XML_SCHEMAS_FLOAT) ||
4861 (ytype == XML_SCHEMAS_DOUBLE))
4862 return (xmlSchemaCompareFloats(x, y));
4864 case XML_SCHEMAS_BOOLEAN:
4865 if ((x == NULL) || (y == NULL))
4867 if (ytype == XML_SCHEMAS_BOOLEAN) {
4868 if (x->value.b == y->value.b)
4870 if (x->value.b == 0)
4875 case XML_SCHEMAS_HEXBINARY:
4876 if ((x == NULL) || (y == NULL))
4878 if (ytype == XML_SCHEMAS_HEXBINARY) {
4879 if (x->value.hex.total == y->value.hex.total) {
4880 int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
4886 else if (x->value.hex.total > y->value.hex.total)
4892 case XML_SCHEMAS_BASE64BINARY:
4893 if ((x == NULL) || (y == NULL))
4895 if (ytype == XML_SCHEMAS_BASE64BINARY) {
4896 if (x->value.base64.total == y->value.base64.total) {
4897 int ret = xmlStrcmp(x->value.base64.str,
4898 y->value.base64.str);
4906 else if (x->value.base64.total > y->value.base64.total)
4912 case XML_SCHEMAS_IDREFS:
4913 case XML_SCHEMAS_ENTITIES:
4914 case XML_SCHEMAS_NMTOKENS:
4922 * xmlSchemaCompareValues:
4924 * @y: a second value
4928 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4932 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
4933 xmlSchemaWhitespaceValueType xws, yws;
4935 if ((x == NULL) || (y == NULL))
4937 if (x->type == XML_SCHEMAS_STRING)
4938 xws = XML_SCHEMA_WHITESPACE_PRESERVE;
4939 else if (x->type == XML_SCHEMAS_NORMSTRING)
4940 xws = XML_SCHEMA_WHITESPACE_REPLACE;
4942 xws = XML_SCHEMA_WHITESPACE_COLLAPSE;
4944 if (y->type == XML_SCHEMAS_STRING)
4945 yws = XML_SCHEMA_WHITESPACE_PRESERVE;
4946 else if (y->type == XML_SCHEMAS_NORMSTRING)
4947 yws = XML_SCHEMA_WHITESPACE_REPLACE;
4949 yws = XML_SCHEMA_WHITESPACE_COLLAPSE;
4951 return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
4956 * xmlSchemaCompareValuesWhtsp:
4958 * @xws: the whitespace value of x
4959 * @y: a second value
4960 * @yws: the whitespace value of y
4964 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4968 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,
4969 xmlSchemaWhitespaceValueType xws,
4971 xmlSchemaWhitespaceValueType yws)
4973 if ((x == NULL) || (y == NULL))
4975 return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
4980 * xmlSchemaCompareValuesWhtspExt:
4982 * @xws: the whitespace value of x
4983 * @y: a second value
4984 * @yws: the whitespace value of y
4988 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4992 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,
4994 const xmlChar *xvalue,
4995 xmlSchemaWhitespaceValueType xws,
4996 xmlSchemaValType ytype,
4998 const xmlChar *yvalue,
4999 xmlSchemaWhitespaceValueType yws)
5001 return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y,
5009 * Computes the UTF8 length of the normalized value of the string
5011 * Returns the length or -1 in case of error.
5014 xmlSchemaNormLen(const xmlChar *value) {
5021 while (IS_BLANK_CH(*utf)) utf++;
5023 if (utf[0] & 0x80) {
5024 if ((utf[1] & 0xc0) != 0x80)
5026 if ((utf[0] & 0xe0) == 0xe0) {
5027 if ((utf[2] & 0xc0) != 0x80)
5029 if ((utf[0] & 0xf0) == 0xf0) {
5030 if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
5039 } else if (IS_BLANK_CH(*utf)) {
5040 while (IS_BLANK_CH(*utf)) utf++;
5052 * xmlSchemaGetFacetValueAsULong:
5053 * @facet: an schemas type facet
5055 * Extract the value of a facet
5057 * Returns the value as a long
5060 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
5063 * TODO: Check if this is a decimal.
5067 return ((unsigned long) facet->val->value.decimal.lo);
5071 * xmlSchemaValidateListSimpleTypeFacet:
5072 * @facet: the facet to check
5073 * @value: the lexical repr of the value to validate
5074 * @actualLen: the number of list items
5075 * @expectedLen: the resulting expected number of list items
5077 * Checks the value of a list simple type against a facet.
5079 * Returns 0 if the value is valid, a positive error code
5080 * number otherwise and -1 in case of an internal error.
5083 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,
5084 const xmlChar *value,
5085 unsigned long actualLen,
5086 unsigned long *expectedLen)
5091 * TODO: Check if this will work with large numbers.
5092 * (compare value.decimal.mi and value.decimal.hi as well?).
5094 if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5095 if (actualLen != facet->val->value.decimal.lo) {
5096 if (expectedLen != NULL)
5097 *expectedLen = facet->val->value.decimal.lo;
5098 return (XML_SCHEMAV_CVC_LENGTH_VALID);
5100 } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5101 if (actualLen < facet->val->value.decimal.lo) {
5102 if (expectedLen != NULL)
5103 *expectedLen = facet->val->value.decimal.lo;
5104 return (XML_SCHEMAV_CVC_MINLENGTH_VALID);
5106 } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
5107 if (actualLen > facet->val->value.decimal.lo) {
5108 if (expectedLen != NULL)
5109 *expectedLen = facet->val->value.decimal.lo;
5110 return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5114 * NOTE: That we can pass NULL as xmlSchemaValPtr to
5115 * xmlSchemaValidateFacet, since the remaining facet types
5116 * are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
5118 return(xmlSchemaValidateFacet(NULL, facet, value, NULL));
5123 * xmlSchemaValidateLengthFacet:
5124 * @type: the built-in type
5125 * @facet: the facet to check
5126 * @value: the lexical repr. of the value to be validated
5127 * @val: the precomputed value
5128 * @ws: the whitespace type of the value
5129 * @length: the actual length of the value
5131 * Checka a value against a "length", "minLength" and "maxLength"
5132 * facet; sets @length to the computed length of @value.
5134 * Returns 0 if the value is valid, a positive error code
5135 * otherwise and -1 in case of an internal or API error.
5138 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
5139 xmlSchemaValType valType,
5140 const xmlChar *value,
5141 xmlSchemaValPtr val,
5142 unsigned long *length,
5143 xmlSchemaWhitespaceValueType ws)
5145 unsigned int len = 0;
5147 if ((length == NULL) || (facet == NULL))
5150 if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
5151 (facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
5152 (facet->type != XML_SCHEMA_FACET_MINLENGTH))
5156 * TODO: length, maxLength and minLength must be of type
5157 * nonNegativeInteger only. Check if decimal is used somehow.
5159 if ((facet->val == NULL) ||
5160 ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5161 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5162 (facet->val->value.decimal.frac != 0)) {
5165 if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5166 len = val->value.hex.total;
5167 else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5168 len = val->value.base64.total;
5171 case XML_SCHEMAS_STRING:
5172 case XML_SCHEMAS_NORMSTRING:
5173 if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5175 * This is to ensure API compatibility with the old
5176 * xmlSchemaValidateLengthFacet(). Anyway, this was and
5177 * is not the correct handling.
5178 * TODO: Get rid of this case somehow.
5180 if (valType == XML_SCHEMAS_STRING)
5181 len = xmlUTF8Strlen(value);
5183 len = xmlSchemaNormLen(value);
5184 } else if (value != NULL) {
5185 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5186 len = xmlSchemaNormLen(value);
5189 * Should be OK for "preserve" as well.
5191 len = xmlUTF8Strlen(value);
5194 case XML_SCHEMAS_IDREF:
5195 case XML_SCHEMAS_TOKEN:
5196 case XML_SCHEMAS_LANGUAGE:
5197 case XML_SCHEMAS_NMTOKEN:
5198 case XML_SCHEMAS_NAME:
5199 case XML_SCHEMAS_NCNAME:
5200 case XML_SCHEMAS_ID:
5202 * FIXME: What exactly to do with anyURI?
5204 case XML_SCHEMAS_ANYURI:
5206 len = xmlSchemaNormLen(value);
5208 case XML_SCHEMAS_QNAME:
5209 case XML_SCHEMAS_NOTATION:
5211 * For QName and NOTATION, those facets are
5212 * deprecated and should be ignored.
5219 *length = (unsigned long) len;
5221 * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
5223 if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5224 if (len != facet->val->value.decimal.lo)
5225 return(XML_SCHEMAV_CVC_LENGTH_VALID);
5226 } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5227 if (len < facet->val->value.decimal.lo)
5228 return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
5230 if (len > facet->val->value.decimal.lo)
5231 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5238 * xmlSchemaValidateLengthFacet:
5239 * @type: the built-in type
5240 * @facet: the facet to check
5241 * @value: the lexical repr. of the value to be validated
5242 * @val: the precomputed value
5243 * @length: the actual length of the value
5245 * Checka a value against a "length", "minLength" and "maxLength"
5246 * facet; sets @length to the computed length of @value.
5248 * Returns 0 if the value is valid, a positive error code
5249 * otherwise and -1 in case of an internal or API error.
5252 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,
5253 xmlSchemaFacetPtr facet,
5254 const xmlChar *value,
5255 xmlSchemaValPtr val,
5256 unsigned long *length)
5260 return (xmlSchemaValidateLengthFacetInternal(facet,
5261 type->builtInType, value, val, length,
5262 XML_SCHEMA_WHITESPACE_UNKNOWN));
5266 * xmlSchemaValidateLengthFacetWhtsp:
5267 * @facet: the facet to check
5268 * @valType: the built-in type
5269 * @value: the lexical repr. of the value to be validated
5270 * @val: the precomputed value
5271 * @ws: the whitespace type of the value
5272 * @length: the actual length of the value
5274 * Checka a value against a "length", "minLength" and "maxLength"
5275 * facet; sets @length to the computed length of @value.
5277 * Returns 0 if the value is valid, a positive error code
5278 * otherwise and -1 in case of an internal or API error.
5281 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
5282 xmlSchemaValType valType,
5283 const xmlChar *value,
5284 xmlSchemaValPtr val,
5285 unsigned long *length,
5286 xmlSchemaWhitespaceValueType ws)
5288 return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val,
5293 * xmlSchemaValidateFacetInternal:
5294 * @facet: the facet to check
5295 * @fws: the whitespace type of the facet's value
5296 * @valType: the built-in type of the value
5297 * @value: the lexical repr of the value to validate
5298 * @val: the precomputed value
5299 * @ws: the whitespace type of the value
5301 * Check a value against a facet condition
5303 * Returns 0 if the element is schemas valid, a positive error code
5304 * number otherwise and -1 in case of internal or API error.
5307 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
5308 xmlSchemaWhitespaceValueType fws,
5309 xmlSchemaValType valType,
5310 const xmlChar *value,
5311 xmlSchemaValPtr val,
5312 xmlSchemaWhitespaceValueType ws)
5320 switch (facet->type) {
5321 case XML_SCHEMA_FACET_PATTERN:
5323 * NOTE that for patterns, the @value needs to be the normalized
5324 * value, *not* the lexical initial value or the canonical value.
5329 * If string-derived type, regexp must be tested on the value space of
5331 * See https://www.w3.org/TR/xmlschema-2/#rf-pattern
5333 stringType = val && ((val->type >= XML_SCHEMAS_STRING && val->type <= XML_SCHEMAS_NORMSTRING)
5334 || (val->type >= XML_SCHEMAS_TOKEN && val->type <= XML_SCHEMAS_NCNAME));
5335 ret = xmlRegexpExec(facet->regexp,
5336 (stringType && val->value.str) ? val->value.str : value);
5340 return(XML_SCHEMAV_CVC_PATTERN_VALID);
5342 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5343 ret = xmlSchemaCompareValues(val, facet->val);
5348 return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID);
5349 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5350 ret = xmlSchemaCompareValues(val, facet->val);
5353 if ((ret == -1) || (ret == 0))
5355 return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID);
5356 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5357 ret = xmlSchemaCompareValues(val, facet->val);
5362 return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID);
5363 case XML_SCHEMA_FACET_MININCLUSIVE:
5364 ret = xmlSchemaCompareValues(val, facet->val);
5367 if ((ret == 1) || (ret == 0))
5369 return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID);
5370 case XML_SCHEMA_FACET_WHITESPACE:
5371 /* TODO whitespaces */
5373 * NOTE: Whitespace should be handled to normalize
5374 * the value to be validated against a the facets;
5375 * not to normalize the value in-between.
5378 case XML_SCHEMA_FACET_ENUMERATION:
5379 if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5381 * This is to ensure API compatibility with the old
5382 * xmlSchemaValidateFacet().
5383 * TODO: Get rid of this case.
5385 if ((facet->value != NULL) &&
5386 (xmlStrEqual(facet->value, value)))
5389 ret = xmlSchemaCompareValuesWhtspExt(facet->val->type,
5390 facet->val, facet->value, fws, valType, val,
5397 return(XML_SCHEMAV_CVC_ENUMERATION_VALID);
5398 case XML_SCHEMA_FACET_LENGTH:
5400 * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
5401 * then any {value} is facet-valid."
5403 if ((valType == XML_SCHEMAS_QNAME) ||
5404 (valType == XML_SCHEMAS_NOTATION))
5406 /* No break on purpose. */
5407 case XML_SCHEMA_FACET_MAXLENGTH:
5408 case XML_SCHEMA_FACET_MINLENGTH: {
5409 unsigned int len = 0;
5411 if ((valType == XML_SCHEMAS_QNAME) ||
5412 (valType == XML_SCHEMAS_NOTATION))
5415 * TODO: length, maxLength and minLength must be of type
5416 * nonNegativeInteger only. Check if decimal is used somehow.
5418 if ((facet->val == NULL) ||
5419 ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5420 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5421 (facet->val->value.decimal.frac != 0)) {
5424 if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5425 len = val->value.hex.total;
5426 else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5427 len = val->value.base64.total;
5430 case XML_SCHEMAS_STRING:
5431 case XML_SCHEMAS_NORMSTRING:
5432 if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5434 * This is to ensure API compatibility with the old
5435 * xmlSchemaValidateFacet(). Anyway, this was and
5436 * is not the correct handling.
5437 * TODO: Get rid of this case somehow.
5439 if (valType == XML_SCHEMAS_STRING)
5440 len = xmlUTF8Strlen(value);
5442 len = xmlSchemaNormLen(value);
5443 } else if (value != NULL) {
5444 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5445 len = xmlSchemaNormLen(value);
5448 * Should be OK for "preserve" as well.
5450 len = xmlUTF8Strlen(value);
5453 case XML_SCHEMAS_IDREF:
5454 case XML_SCHEMAS_TOKEN:
5455 case XML_SCHEMAS_LANGUAGE:
5456 case XML_SCHEMAS_NMTOKEN:
5457 case XML_SCHEMAS_NAME:
5458 case XML_SCHEMAS_NCNAME:
5459 case XML_SCHEMAS_ID:
5460 case XML_SCHEMAS_ANYURI:
5462 len = xmlSchemaNormLen(value);
5468 if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5469 if (len != facet->val->value.decimal.lo)
5470 return(XML_SCHEMAV_CVC_LENGTH_VALID);
5471 } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5472 if (len < facet->val->value.decimal.lo)
5473 return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
5475 if (len > facet->val->value.decimal.lo)
5476 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5480 case XML_SCHEMA_FACET_TOTALDIGITS:
5481 case XML_SCHEMA_FACET_FRACTIONDIGITS:
5483 if ((facet->val == NULL) ||
5484 ((facet->val->type != XML_SCHEMAS_PINTEGER) &&
5485 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5486 (facet->val->value.decimal.frac != 0)) {
5489 if ((val == NULL) ||
5490 ((val->type != XML_SCHEMAS_DECIMAL) &&
5491 (val->type != XML_SCHEMAS_INTEGER) &&
5492 (val->type != XML_SCHEMAS_NPINTEGER) &&
5493 (val->type != XML_SCHEMAS_NINTEGER) &&
5494 (val->type != XML_SCHEMAS_NNINTEGER) &&
5495 (val->type != XML_SCHEMAS_PINTEGER) &&
5496 (val->type != XML_SCHEMAS_INT) &&
5497 (val->type != XML_SCHEMAS_UINT) &&
5498 (val->type != XML_SCHEMAS_LONG) &&
5499 (val->type != XML_SCHEMAS_ULONG) &&
5500 (val->type != XML_SCHEMAS_SHORT) &&
5501 (val->type != XML_SCHEMAS_USHORT) &&
5502 (val->type != XML_SCHEMAS_BYTE) &&
5503 (val->type != XML_SCHEMAS_UBYTE))) {
5506 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
5507 if (val->value.decimal.total > facet->val->value.decimal.lo)
5508 return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID);
5510 } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
5511 if (val->value.decimal.frac > facet->val->value.decimal.lo)
5512 return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID);
5523 * xmlSchemaValidateFacet:
5524 * @base: the base type
5525 * @facet: the facet to check
5526 * @value: the lexical repr of the value to validate
5527 * @val: the precomputed value
5529 * Check a value against a facet condition
5531 * Returns 0 if the element is schemas valid, a positive error code
5532 * number otherwise and -1 in case of internal or API error.
5535 xmlSchemaValidateFacet(xmlSchemaTypePtr base,
5536 xmlSchemaFacetPtr facet,
5537 const xmlChar *value,
5538 xmlSchemaValPtr val)
5541 * This tries to ensure API compatibility regarding the old
5542 * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
5543 * xmlSchemaValidateFacetWhtsp().
5546 return(xmlSchemaValidateFacetInternal(facet,
5547 XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val,
5548 XML_SCHEMA_WHITESPACE_UNKNOWN));
5549 else if (base != NULL)
5550 return(xmlSchemaValidateFacetInternal(facet,
5551 XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val,
5552 XML_SCHEMA_WHITESPACE_UNKNOWN));
5557 * xmlSchemaValidateFacetWhtsp:
5558 * @facet: the facet to check
5559 * @fws: the whitespace type of the facet's value
5560 * @valType: the built-in type of the value
5561 * @value: the lexical (or normalized for pattern) repr of the value to validate
5562 * @val: the precomputed value
5563 * @ws: the whitespace type of the value
5565 * Check a value against a facet condition. This takes value normalization
5566 * according to the specified whitespace types into account.
5567 * Note that @value needs to be the *normalized* value if the facet
5568 * is of type "pattern".
5570 * Returns 0 if the element is schemas valid, a positive error code
5571 * number otherwise and -1 in case of internal or API error.
5574 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,
5575 xmlSchemaWhitespaceValueType fws,
5576 xmlSchemaValType valType,
5577 const xmlChar *value,
5578 xmlSchemaValPtr val,
5579 xmlSchemaWhitespaceValueType ws)
5581 return(xmlSchemaValidateFacetInternal(facet, fws, valType,
5590 #define DBL_EPSILON 1E-9
5593 #define INTEGER_DIGITS DBL_DIG
5594 #define FRACTION_DIGITS (DBL_DIG + 1)
5595 #define EXPONENT_DIGITS (3 + 2)
5598 * xmlXPathFormatNumber:
5599 * @number: number to format
5600 * @buffer: output buffer
5601 * @buffersize: size of output buffer
5603 * Convert the number into a string representation.
5606 xmlSchemaFormatFloat(double number, char buffer[], int buffersize)
5608 switch (xmlXPathIsInf(number)) {
5610 if (buffersize > (int)sizeof("INF"))
5611 snprintf(buffer, buffersize, "INF");
5614 if (buffersize > (int)sizeof("-INF"))
5615 snprintf(buffer, buffersize, "-INF");
5618 if (xmlXPathIsNaN(number)) {
5619 if (buffersize > (int)sizeof("NaN"))
5620 snprintf(buffer, buffersize, "NaN");
5621 } else if (number == 0) {
5622 snprintf(buffer, buffersize, "0.0E0");
5624 /* 3 is sign, decimal point, and terminating zero */
5625 char work[DBL_DIG + EXPONENT_DIGITS + 3];
5626 int integer_place, fraction_place;
5628 char *after_fraction;
5629 double absolute_value;
5632 absolute_value = fabs(number);
5635 * Result is in work, and after_fraction points
5636 * just past the fractional part.
5637 * Use scientific notation
5639 integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
5640 fraction_place = DBL_DIG - 1;
5641 snprintf(work, sizeof(work),"%*.*e",
5642 integer_place, fraction_place, number);
5643 after_fraction = strchr(work + DBL_DIG, 'e');
5644 /* Remove fractional trailing zeroes */
5645 ptr = after_fraction;
5646 while (*(--ptr) == '0')
5650 while ((*ptr++ = *after_fraction++) != 0);
5652 /* Finally copy result back to caller */
5653 size = strlen(work) + 1;
5654 if (size > buffersize) {
5655 work[buffersize - 1] = 0;
5658 memmove(buffer, work, size);
5666 * xmlSchemaGetCanonValue:
5667 * @val: the precomputed value
5668 * @retValue: the returned value
5670 * Get the canonical lexical representation of the value.
5671 * The caller has to FREE the returned retValue.
5673 * WARNING: Some value types are not supported yet, resulting
5674 * in a @retValue of "???".
5676 * TODO: XML Schema 1.0 does not define canonical representations
5677 * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay,
5678 * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1.
5681 * Returns 0 if the value could be built, 1 if the value type is
5682 * not supported yet and -1 in case of API errors.
5685 xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
5687 if ((retValue == NULL) || (val == NULL))
5690 switch (val->type) {
5691 case XML_SCHEMAS_STRING:
5692 if (val->value.str == NULL)
5693 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5696 BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5698 case XML_SCHEMAS_NORMSTRING:
5699 if (val->value.str == NULL)
5700 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5702 *retValue = xmlSchemaWhiteSpaceReplace(
5703 (const xmlChar *) val->value.str);
5704 if ((*retValue) == NULL)
5705 *retValue = BAD_CAST xmlStrdup(
5706 (const xmlChar *) val->value.str);
5709 case XML_SCHEMAS_TOKEN:
5710 case XML_SCHEMAS_LANGUAGE:
5711 case XML_SCHEMAS_NMTOKEN:
5712 case XML_SCHEMAS_NAME:
5713 case XML_SCHEMAS_NCNAME:
5714 case XML_SCHEMAS_ID:
5715 case XML_SCHEMAS_IDREF:
5716 case XML_SCHEMAS_ENTITY:
5717 case XML_SCHEMAS_NOTATION: /* Unclear */
5718 case XML_SCHEMAS_ANYURI: /* Unclear */
5719 if (val->value.str == NULL)
5722 BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str);
5723 if (*retValue == NULL)
5725 BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5727 case XML_SCHEMAS_QNAME:
5728 /* TODO: Unclear in XML Schema 1.0. */
5729 if (val->value.qname.uri == NULL) {
5730 *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name);
5733 *retValue = BAD_CAST xmlStrdup(BAD_CAST "{");
5734 *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5735 BAD_CAST val->value.qname.uri);
5736 *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5738 *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5739 BAD_CAST val->value.qname.uri);
5742 case XML_SCHEMAS_DECIMAL:
5744 * TODO: Lookout for a more simple implementation.
5746 if ((val->value.decimal.total == 1) &&
5747 (val->value.decimal.lo == 0)) {
5748 *retValue = xmlStrdup(BAD_CAST "0.0");
5750 xmlSchemaValDecimal dec = val->value.decimal;
5752 char *buf = NULL, *offs;
5754 /* Add room for the decimal point as well. */
5755 bufsize = dec.total + 2;
5758 /* Add room for leading/trailing zero. */
5759 if ((dec.frac == 0) || (dec.frac == dec.total))
5761 buf = xmlMalloc(bufsize);
5767 if (dec.frac == dec.total) {
5772 snprintf(offs, bufsize - (offs - buf),
5773 "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5774 else if (dec.mi != 0)
5775 snprintf(offs, bufsize - (offs - buf),
5776 "%lu%lu", dec.mi, dec.lo);
5778 snprintf(offs, bufsize - (offs - buf),
5781 if (dec.frac != 0) {
5782 if (dec.frac != dec.total) {
5783 int diff = dec.total - dec.frac;
5785 * Insert the decimal point.
5787 memmove(offs + diff + 1, offs + diff, dec.frac +1);
5792 * Insert missing zeroes behind the decimal point.
5794 while (*(offs + i) != 0)
5796 if (i < dec.total) {
5797 memmove(offs + (dec.total - i), offs, i +1);
5798 memset(offs, '0', dec.total - i);
5803 * Append decimal point and zero.
5805 offs = buf + bufsize - 1;
5810 *retValue = BAD_CAST buf;
5813 case XML_SCHEMAS_INTEGER:
5814 case XML_SCHEMAS_PINTEGER:
5815 case XML_SCHEMAS_NPINTEGER:
5816 case XML_SCHEMAS_NINTEGER:
5817 case XML_SCHEMAS_NNINTEGER:
5818 case XML_SCHEMAS_LONG:
5819 case XML_SCHEMAS_BYTE:
5820 case XML_SCHEMAS_SHORT:
5821 case XML_SCHEMAS_INT:
5822 case XML_SCHEMAS_UINT:
5823 case XML_SCHEMAS_ULONG:
5824 case XML_SCHEMAS_USHORT:
5825 case XML_SCHEMAS_UBYTE:
5826 if ((val->value.decimal.total == 1) &&
5827 (val->value.decimal.lo == 0))
5828 *retValue = xmlStrdup(BAD_CAST "0");
5830 xmlSchemaValDecimal dec = val->value.decimal;
5831 int bufsize = dec.total + 1;
5833 /* Add room for the decimal point as well. */
5836 *retValue = xmlMalloc(bufsize);
5837 if (*retValue == NULL)
5841 snprintf((char *) *retValue, bufsize,
5842 "-%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5844 snprintf((char *) *retValue, bufsize,
5845 "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5846 } else if (dec.mi != 0) {
5848 snprintf((char *) *retValue, bufsize,
5849 "-%lu%lu", dec.mi, dec.lo);
5851 snprintf((char *) *retValue, bufsize,
5852 "%lu%lu", dec.mi, dec.lo);
5855 snprintf((char *) *retValue, bufsize, "-%lu", dec.lo);
5857 snprintf((char *) *retValue, bufsize, "%lu", dec.lo);
5861 case XML_SCHEMAS_BOOLEAN:
5863 *retValue = BAD_CAST xmlStrdup(BAD_CAST "true");
5865 *retValue = BAD_CAST xmlStrdup(BAD_CAST "false");
5867 case XML_SCHEMAS_DURATION: {
5870 unsigned long mon, day, hour = 0, min = 0;
5871 double sec = 0, left;
5873 /* TODO: Unclear in XML Schema 1.0 */
5875 * TODO: This results in a normalized output of the value
5876 * - which is NOT conformant to the spec -
5877 * since the exact values of each property are not
5878 * recoverable. Think about extending the structure to
5879 * provide a field for every property.
5881 year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12);
5882 mon = labs(val->value.dur.mon) - 12 * year;
5884 day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400);
5885 left = fabs(val->value.dur.sec) - day * 86400;
5887 hour = (unsigned long) FQUOTIENT(left, 3600);
5888 left = left - (hour * 3600);
5890 min = (unsigned long) FQUOTIENT(left, 60);
5891 sec = left - (min * 60);
5894 if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0))
5895 snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS",
5896 year, mon, day, hour, min, sec);
5898 snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
5899 year, mon, day, hour, min, sec);
5900 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5903 case XML_SCHEMAS_GYEAR: {
5905 /* TODO: Unclear in XML Schema 1.0 */
5906 /* TODO: What to do with the timezone? */
5907 snprintf(buf, 30, "%04ld", val->value.date.year);
5908 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5911 case XML_SCHEMAS_GMONTH: {
5912 /* TODO: Unclear in XML Schema 1.0 */
5913 /* TODO: What to do with the timezone? */
5914 *retValue = xmlMalloc(6);
5915 if (*retValue == NULL)
5917 snprintf((char *) *retValue, 6, "--%02u",
5918 val->value.date.mon);
5921 case XML_SCHEMAS_GDAY: {
5922 /* TODO: Unclear in XML Schema 1.0 */
5923 /* TODO: What to do with the timezone? */
5924 *retValue = xmlMalloc(6);
5925 if (*retValue == NULL)
5927 snprintf((char *) *retValue, 6, "---%02u",
5928 val->value.date.day);
5931 case XML_SCHEMAS_GMONTHDAY: {
5932 /* TODO: Unclear in XML Schema 1.0 */
5933 /* TODO: What to do with the timezone? */
5934 *retValue = xmlMalloc(8);
5935 if (*retValue == NULL)
5937 snprintf((char *) *retValue, 8, "--%02u-%02u",
5938 val->value.date.mon, val->value.date.day);
5941 case XML_SCHEMAS_GYEARMONTH: {
5943 /* TODO: Unclear in XML Schema 1.0 */
5944 /* TODO: What to do with the timezone? */
5945 if (val->value.date.year < 0)
5946 snprintf(buf, 35, "-%04ld-%02u",
5947 labs(val->value.date.year),
5948 val->value.date.mon);
5950 snprintf(buf, 35, "%04ld-%02u",
5951 val->value.date.year, val->value.date.mon);
5952 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5955 case XML_SCHEMAS_TIME:
5959 if (val->value.date.tz_flag) {
5960 xmlSchemaValPtr norm;
5962 norm = xmlSchemaDateNormalize(val, 0);
5966 * TODO: Check if "%.14g" is portable.
5969 "%02u:%02u:%02.14gZ",
5970 norm->value.date.hour,
5971 norm->value.date.min,
5972 norm->value.date.sec);
5973 xmlSchemaFreeValue(norm);
5976 "%02u:%02u:%02.14g",
5977 val->value.date.hour,
5978 val->value.date.min,
5979 val->value.date.sec);
5981 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5984 case XML_SCHEMAS_DATE:
5988 if (val->value.date.tz_flag) {
5989 xmlSchemaValPtr norm;
5991 norm = xmlSchemaDateNormalize(val, 0);
5995 * TODO: Append the canonical value of the
5996 * recoverable timezone and not "Z".
6000 norm->value.date.year, norm->value.date.mon,
6001 norm->value.date.day);
6002 xmlSchemaFreeValue(norm);
6006 val->value.date.year, val->value.date.mon,
6007 val->value.date.day);
6009 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6012 case XML_SCHEMAS_DATETIME:
6016 if (val->value.date.tz_flag) {
6017 xmlSchemaValPtr norm;
6019 norm = xmlSchemaDateNormalize(val, 0);
6023 * TODO: Check if "%.14g" is portable.
6026 "%04ld:%02u:%02uT%02u:%02u:%02.14gZ",
6027 norm->value.date.year, norm->value.date.mon,
6028 norm->value.date.day, norm->value.date.hour,
6029 norm->value.date.min, norm->value.date.sec);
6030 xmlSchemaFreeValue(norm);
6033 "%04ld:%02u:%02uT%02u:%02u:%02.14g",
6034 val->value.date.year, val->value.date.mon,
6035 val->value.date.day, val->value.date.hour,
6036 val->value.date.min, val->value.date.sec);
6038 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6041 case XML_SCHEMAS_HEXBINARY:
6042 *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str);
6044 case XML_SCHEMAS_BASE64BINARY:
6046 * TODO: Is the following spec piece implemented?:
6047 * SPEC: "Note: For some values the canonical form defined
6048 * above does not conform to [RFC 2045], which requires breaking
6049 * with linefeeds at appropriate intervals."
6051 *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str);
6053 case XML_SCHEMAS_FLOAT: {
6056 * |m| < 16777216, -149 <= e <= 104.
6057 * TODO: Handle, NaN, INF, -INF. The format is not
6058 * yet conformant. The c type float does not cover
6061 snprintf(buf, 30, "%01.14e", val->value.f);
6062 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6065 case XML_SCHEMAS_DOUBLE: {
6067 /* |m| < 9007199254740992, -1075 <= e <= 970 */
6069 * TODO: Handle, NaN, INF, -INF. The format is not
6070 * yet conformant. The c type float does not cover
6073 snprintf(buf, 40, "%01.14e", val->value.d);
6074 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6078 *retValue = BAD_CAST xmlStrdup(BAD_CAST "???");
6081 if (*retValue == NULL)
6087 * xmlSchemaGetCanonValueWhtsp:
6088 * @val: the precomputed value
6089 * @retValue: the returned value
6090 * @ws: the whitespace type of the value
6092 * Get the canonical representation of the value.
6093 * The caller has to free the returned @retValue.
6095 * Returns 0 if the value could be built, 1 if the value type is
6096 * not supported yet and -1 in case of API errors.
6099 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,
6100 const xmlChar **retValue,
6101 xmlSchemaWhitespaceValueType ws)
6103 if ((retValue == NULL) || (val == NULL))
6105 if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) ||
6106 (ws > XML_SCHEMA_WHITESPACE_COLLAPSE))
6110 switch (val->type) {
6111 case XML_SCHEMAS_STRING:
6112 if (val->value.str == NULL)
6113 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6114 else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6115 *retValue = xmlSchemaCollapseString(val->value.str);
6116 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
6117 *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6118 if ((*retValue) == NULL)
6119 *retValue = BAD_CAST xmlStrdup(val->value.str);
6121 case XML_SCHEMAS_NORMSTRING:
6122 if (val->value.str == NULL)
6123 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6125 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6126 *retValue = xmlSchemaCollapseString(val->value.str);
6128 *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6129 if ((*retValue) == NULL)
6130 *retValue = BAD_CAST xmlStrdup(val->value.str);
6134 return (xmlSchemaGetCanonValue(val, retValue));
6140 * xmlSchemaGetValType:
6141 * @val: a schemas value
6143 * Accessor for the type of a value
6145 * Returns the xmlSchemaValType of the value
6148 xmlSchemaGetValType(xmlSchemaValPtr val)
6151 return(XML_SCHEMAS_UNKNOWN);
6155 #define bottom_xmlschemastypes
6156 #include "elfgcchack.h"
6157 #endif /* LIBXML_SCHEMAS_ENABLED */