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 explicitly 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 information
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 xmlSchemaFreeTypeEntry(void *type
, const xmlChar
*name ATTRIBUTE_UNUSED
) {
624 xmlSchemaFreeType((xmlSchemaTypePtr
) type
);
628 * xmlSchemaCleanupTypes:
630 * Cleanup the default XML Schemas type library
633 xmlSchemaCleanupTypes(void) {
634 if (xmlSchemaTypesInitialized
== 0)
640 xmlSchemaParticlePtr particle
;
641 /* Attribute wildcard. */
642 xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef
->attributeWildcard
);
644 particle
= (xmlSchemaParticlePtr
) xmlSchemaTypeAnyTypeDef
->subtypes
;
646 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr
)
647 particle
->children
->children
->children
);
648 xmlFree((xmlSchemaParticlePtr
) particle
->children
->children
);
649 /* Sequence model group. */
650 xmlFree((xmlSchemaModelGroupPtr
) particle
->children
);
651 xmlFree((xmlSchemaParticlePtr
) particle
);
652 xmlSchemaTypeAnyTypeDef
->subtypes
= NULL
;
654 xmlHashFree(xmlSchemaTypesBank
, xmlSchemaFreeTypeEntry
);
655 xmlSchemaTypesInitialized
= 0;
659 * xmlSchemaIsBuiltInTypeFacet:
660 * @type: the built-in type
661 * @facetType: the facet type
663 * Evaluates if a specific facet can be
664 * used in conjunction with a type.
666 * Returns 1 if the facet can be used with the given built-in type,
667 * 0 otherwise and -1 in case the type is not a built-in type.
670 xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type
, int facetType
)
674 if (type
->type
!= XML_SCHEMA_TYPE_BASIC
)
676 switch (type
->builtInType
) {
677 case XML_SCHEMAS_BOOLEAN
:
678 if ((facetType
== XML_SCHEMA_FACET_PATTERN
) ||
679 (facetType
== XML_SCHEMA_FACET_WHITESPACE
))
683 case XML_SCHEMAS_STRING
:
684 case XML_SCHEMAS_NOTATION
:
685 case XML_SCHEMAS_QNAME
:
686 case XML_SCHEMAS_ANYURI
:
687 case XML_SCHEMAS_BASE64BINARY
:
688 case XML_SCHEMAS_HEXBINARY
:
689 if ((facetType
== XML_SCHEMA_FACET_LENGTH
) ||
690 (facetType
== XML_SCHEMA_FACET_MINLENGTH
) ||
691 (facetType
== XML_SCHEMA_FACET_MAXLENGTH
) ||
692 (facetType
== XML_SCHEMA_FACET_PATTERN
) ||
693 (facetType
== XML_SCHEMA_FACET_ENUMERATION
) ||
694 (facetType
== XML_SCHEMA_FACET_WHITESPACE
))
698 case XML_SCHEMAS_DECIMAL
:
699 if ((facetType
== XML_SCHEMA_FACET_TOTALDIGITS
) ||
700 (facetType
== XML_SCHEMA_FACET_FRACTIONDIGITS
) ||
701 (facetType
== XML_SCHEMA_FACET_PATTERN
) ||
702 (facetType
== XML_SCHEMA_FACET_WHITESPACE
) ||
703 (facetType
== XML_SCHEMA_FACET_ENUMERATION
) ||
704 (facetType
== XML_SCHEMA_FACET_MAXINCLUSIVE
) ||
705 (facetType
== XML_SCHEMA_FACET_MAXEXCLUSIVE
) ||
706 (facetType
== XML_SCHEMA_FACET_MININCLUSIVE
) ||
707 (facetType
== XML_SCHEMA_FACET_MINEXCLUSIVE
))
711 case XML_SCHEMAS_TIME
:
712 case XML_SCHEMAS_GDAY
:
713 case XML_SCHEMAS_GMONTH
:
714 case XML_SCHEMAS_GMONTHDAY
:
715 case XML_SCHEMAS_GYEAR
:
716 case XML_SCHEMAS_GYEARMONTH
:
717 case XML_SCHEMAS_DATE
:
718 case XML_SCHEMAS_DATETIME
:
719 case XML_SCHEMAS_DURATION
:
720 case XML_SCHEMAS_FLOAT
:
721 case XML_SCHEMAS_DOUBLE
:
722 if ((facetType
== XML_SCHEMA_FACET_PATTERN
) ||
723 (facetType
== XML_SCHEMA_FACET_ENUMERATION
) ||
724 (facetType
== XML_SCHEMA_FACET_WHITESPACE
) ||
725 (facetType
== XML_SCHEMA_FACET_MAXINCLUSIVE
) ||
726 (facetType
== XML_SCHEMA_FACET_MAXEXCLUSIVE
) ||
727 (facetType
== XML_SCHEMA_FACET_MININCLUSIVE
) ||
728 (facetType
== XML_SCHEMA_FACET_MINEXCLUSIVE
))
739 * xmlSchemaGetBuiltInType:
740 * @type: the type of the built in type
742 * Gives you the type struct for a built-in
743 * type by its type id.
745 * Returns the type if found, NULL otherwise.
748 xmlSchemaGetBuiltInType(xmlSchemaValType type
)
750 if (xmlSchemaTypesInitialized
== 0)
751 xmlSchemaInitTypes();
754 case XML_SCHEMAS_ANYSIMPLETYPE
:
755 return (xmlSchemaTypeAnySimpleTypeDef
);
756 case XML_SCHEMAS_STRING
:
757 return (xmlSchemaTypeStringDef
);
758 case XML_SCHEMAS_NORMSTRING
:
759 return (xmlSchemaTypeNormStringDef
);
760 case XML_SCHEMAS_DECIMAL
:
761 return (xmlSchemaTypeDecimalDef
);
762 case XML_SCHEMAS_TIME
:
763 return (xmlSchemaTypeTimeDef
);
764 case XML_SCHEMAS_GDAY
:
765 return (xmlSchemaTypeGDayDef
);
766 case XML_SCHEMAS_GMONTH
:
767 return (xmlSchemaTypeGMonthDef
);
768 case XML_SCHEMAS_GMONTHDAY
:
769 return (xmlSchemaTypeGMonthDayDef
);
770 case XML_SCHEMAS_GYEAR
:
771 return (xmlSchemaTypeGYearDef
);
772 case XML_SCHEMAS_GYEARMONTH
:
773 return (xmlSchemaTypeGYearMonthDef
);
774 case XML_SCHEMAS_DATE
:
775 return (xmlSchemaTypeDateDef
);
776 case XML_SCHEMAS_DATETIME
:
777 return (xmlSchemaTypeDatetimeDef
);
778 case XML_SCHEMAS_DURATION
:
779 return (xmlSchemaTypeDurationDef
);
780 case XML_SCHEMAS_FLOAT
:
781 return (xmlSchemaTypeFloatDef
);
782 case XML_SCHEMAS_DOUBLE
:
783 return (xmlSchemaTypeDoubleDef
);
784 case XML_SCHEMAS_BOOLEAN
:
785 return (xmlSchemaTypeBooleanDef
);
786 case XML_SCHEMAS_TOKEN
:
787 return (xmlSchemaTypeTokenDef
);
788 case XML_SCHEMAS_LANGUAGE
:
789 return (xmlSchemaTypeLanguageDef
);
790 case XML_SCHEMAS_NMTOKEN
:
791 return (xmlSchemaTypeNmtokenDef
);
792 case XML_SCHEMAS_NMTOKENS
:
793 return (xmlSchemaTypeNmtokensDef
);
794 case XML_SCHEMAS_NAME
:
795 return (xmlSchemaTypeNameDef
);
796 case XML_SCHEMAS_QNAME
:
797 return (xmlSchemaTypeQNameDef
);
798 case XML_SCHEMAS_NCNAME
:
799 return (xmlSchemaTypeNCNameDef
);
801 return (xmlSchemaTypeIdDef
);
802 case XML_SCHEMAS_IDREF
:
803 return (xmlSchemaTypeIdrefDef
);
804 case XML_SCHEMAS_IDREFS
:
805 return (xmlSchemaTypeIdrefsDef
);
806 case XML_SCHEMAS_ENTITY
:
807 return (xmlSchemaTypeEntityDef
);
808 case XML_SCHEMAS_ENTITIES
:
809 return (xmlSchemaTypeEntitiesDef
);
810 case XML_SCHEMAS_NOTATION
:
811 return (xmlSchemaTypeNotationDef
);
812 case XML_SCHEMAS_ANYURI
:
813 return (xmlSchemaTypeAnyURIDef
);
814 case XML_SCHEMAS_INTEGER
:
815 return (xmlSchemaTypeIntegerDef
);
816 case XML_SCHEMAS_NPINTEGER
:
817 return (xmlSchemaTypeNonPositiveIntegerDef
);
818 case XML_SCHEMAS_NINTEGER
:
819 return (xmlSchemaTypeNegativeIntegerDef
);
820 case XML_SCHEMAS_NNINTEGER
:
821 return (xmlSchemaTypeNonNegativeIntegerDef
);
822 case XML_SCHEMAS_PINTEGER
:
823 return (xmlSchemaTypePositiveIntegerDef
);
824 case XML_SCHEMAS_INT
:
825 return (xmlSchemaTypeIntDef
);
826 case XML_SCHEMAS_UINT
:
827 return (xmlSchemaTypeUnsignedIntDef
);
828 case XML_SCHEMAS_LONG
:
829 return (xmlSchemaTypeLongDef
);
830 case XML_SCHEMAS_ULONG
:
831 return (xmlSchemaTypeUnsignedLongDef
);
832 case XML_SCHEMAS_SHORT
:
833 return (xmlSchemaTypeShortDef
);
834 case XML_SCHEMAS_USHORT
:
835 return (xmlSchemaTypeUnsignedShortDef
);
836 case XML_SCHEMAS_BYTE
:
837 return (xmlSchemaTypeByteDef
);
838 case XML_SCHEMAS_UBYTE
:
839 return (xmlSchemaTypeUnsignedByteDef
);
840 case XML_SCHEMAS_HEXBINARY
:
841 return (xmlSchemaTypeHexBinaryDef
);
842 case XML_SCHEMAS_BASE64BINARY
:
843 return (xmlSchemaTypeBase64BinaryDef
);
844 case XML_SCHEMAS_ANYTYPE
:
845 return (xmlSchemaTypeAnyTypeDef
);
852 * xmlSchemaValueAppend:
854 * @cur: the value to be appended
856 * Appends a next sibling to a list of computed values.
858 * Returns 0 if succeeded and -1 on API errors.
861 xmlSchemaValueAppend(xmlSchemaValPtr prev
, xmlSchemaValPtr cur
) {
863 if ((prev
== NULL
) || (cur
== NULL
))
870 * xmlSchemaValueGetNext:
873 * Accessor for the next sibling of a list of computed values.
875 * Returns the next value or NULL if there was none, or on
879 xmlSchemaValueGetNext(xmlSchemaValPtr cur
) {
887 * xmlSchemaValueGetAsString:
890 * Accessor for the string value of a computed value.
892 * Returns the string value or NULL if there was none, or on
896 xmlSchemaValueGetAsString(xmlSchemaValPtr val
)
901 case XML_SCHEMAS_STRING
:
902 case XML_SCHEMAS_NORMSTRING
:
903 case XML_SCHEMAS_ANYSIMPLETYPE
:
904 case XML_SCHEMAS_TOKEN
:
905 case XML_SCHEMAS_LANGUAGE
:
906 case XML_SCHEMAS_NMTOKEN
:
907 case XML_SCHEMAS_NAME
:
908 case XML_SCHEMAS_NCNAME
:
910 case XML_SCHEMAS_IDREF
:
911 case XML_SCHEMAS_ENTITY
:
912 case XML_SCHEMAS_ANYURI
:
913 return (BAD_CAST val
->value
.str
);
921 * xmlSchemaValueGetAsBoolean:
924 * Accessor for the boolean value of a computed value.
926 * Returns 1 if true and 0 if false, or in case of an error. Hmm.
929 xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val
)
931 if ((val
== NULL
) || (val
->type
!= XML_SCHEMAS_BOOLEAN
))
933 return (val
->value
.b
);
937 * xmlSchemaNewStringValue:
938 * @type: the value type
941 * Allocate a new simple type value. The type can be
942 * of XML_SCHEMAS_STRING.
943 * WARNING: This one is intended to be expanded for other
944 * string based types. We need this for anySimpleType as well.
945 * The given value is consumed and freed with the struct.
947 * Returns a pointer to the new value or NULL in case of error
950 xmlSchemaNewStringValue(xmlSchemaValType type
,
951 const xmlChar
*value
)
955 if (type
!= XML_SCHEMAS_STRING
)
957 val
= (xmlSchemaValPtr
) xmlMalloc(sizeof(xmlSchemaVal
));
961 memset(val
, 0, sizeof(xmlSchemaVal
));
963 val
->value
.str
= (xmlChar
*) value
;
968 * xmlSchemaNewNOTATIONValue:
969 * @name: the notation name
970 * @ns: the notation namespace name or NULL
972 * Allocate a new NOTATION value.
973 * The given values are consumed and freed with the struct.
975 * Returns a pointer to the new value or NULL in case of error
978 xmlSchemaNewNOTATIONValue(const xmlChar
*name
,
983 val
= xmlSchemaNewValue(XML_SCHEMAS_NOTATION
);
987 val
->value
.qname
.name
= (xmlChar
*)name
;
989 val
->value
.qname
.uri
= (xmlChar
*)ns
;
994 * xmlSchemaNewQNameValue:
995 * @namespaceName: the namespace name
996 * @localName: the local name
998 * Allocate a new QName value.
999 * The given values are consumed and freed with the struct.
1001 * Returns a pointer to the new value or NULL in case of an error.
1004 xmlSchemaNewQNameValue(const xmlChar
*namespaceName
,
1005 const xmlChar
*localName
)
1007 xmlSchemaValPtr val
;
1009 val
= xmlSchemaNewValue(XML_SCHEMAS_QNAME
);
1013 val
->value
.qname
.name
= (xmlChar
*) localName
;
1014 val
->value
.qname
.uri
= (xmlChar
*) namespaceName
;
1019 * xmlSchemaFreeValue:
1020 * @value: the value to free
1022 * Cleanup the default XML Schemas type library
1025 xmlSchemaFreeValue(xmlSchemaValPtr value
) {
1026 xmlSchemaValPtr prev
;
1028 while (value
!= NULL
) {
1029 switch (value
->type
) {
1030 case XML_SCHEMAS_STRING
:
1031 case XML_SCHEMAS_NORMSTRING
:
1032 case XML_SCHEMAS_TOKEN
:
1033 case XML_SCHEMAS_LANGUAGE
:
1034 case XML_SCHEMAS_NMTOKEN
:
1035 case XML_SCHEMAS_NMTOKENS
:
1036 case XML_SCHEMAS_NAME
:
1037 case XML_SCHEMAS_NCNAME
:
1038 case XML_SCHEMAS_ID
:
1039 case XML_SCHEMAS_IDREF
:
1040 case XML_SCHEMAS_IDREFS
:
1041 case XML_SCHEMAS_ENTITY
:
1042 case XML_SCHEMAS_ENTITIES
:
1043 case XML_SCHEMAS_ANYURI
:
1044 case XML_SCHEMAS_ANYSIMPLETYPE
:
1045 if (value
->value
.str
!= NULL
)
1046 xmlFree(value
->value
.str
);
1048 case XML_SCHEMAS_NOTATION
:
1049 case XML_SCHEMAS_QNAME
:
1050 if (value
->value
.qname
.uri
!= NULL
)
1051 xmlFree(value
->value
.qname
.uri
);
1052 if (value
->value
.qname
.name
!= NULL
)
1053 xmlFree(value
->value
.qname
.name
);
1055 case XML_SCHEMAS_HEXBINARY
:
1056 if (value
->value
.hex
.str
!= NULL
)
1057 xmlFree(value
->value
.hex
.str
);
1059 case XML_SCHEMAS_BASE64BINARY
:
1060 if (value
->value
.base64
.str
!= NULL
)
1061 xmlFree(value
->value
.base64
.str
);
1067 value
= value
->next
;
1073 * xmlSchemaGetPredefinedType:
1074 * @name: the type name
1075 * @ns: the URI of the namespace usually "http://www.w3.org/2001/XMLSchema"
1077 * Lookup a type in the default XML Schemas type library
1079 * Returns the type if found, NULL otherwise
1082 xmlSchemaGetPredefinedType(const xmlChar
*name
, const xmlChar
*ns
) {
1083 if (xmlSchemaTypesInitialized
== 0)
1084 xmlSchemaInitTypes();
1087 return((xmlSchemaTypePtr
) xmlHashLookup2(xmlSchemaTypesBank
, name
, ns
));
1091 * xmlSchemaGetBuiltInListSimpleTypeItemType:
1092 * @type: the built-in simple type.
1096 * Returns the item type of @type as defined by the built-in datatype
1097 * hierarchy of XML Schema Part 2: Datatypes, or NULL in case of an error.
1100 xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type
)
1102 if ((type
== NULL
) || (type
->type
!= XML_SCHEMA_TYPE_BASIC
))
1104 switch (type
->builtInType
) {
1105 case XML_SCHEMAS_NMTOKENS
:
1106 return (xmlSchemaTypeNmtokenDef
);
1107 case XML_SCHEMAS_IDREFS
:
1108 return (xmlSchemaTypeIdrefDef
);
1109 case XML_SCHEMAS_ENTITIES
:
1110 return (xmlSchemaTypeEntityDef
);
1116 /****************************************************************
1118 * Convenience macros and functions *
1120 ****************************************************************/
1122 #define IS_TZO_CHAR(c) \
1123 ((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
1125 #define VALID_YEAR(yr) (yr != 0)
1126 #define VALID_MONTH(mon) ((mon >= 1) && (mon <= 12))
1127 /* VALID_DAY should only be used when month is unknown */
1128 #define VALID_DAY(day) ((day >= 1) && (day <= 31))
1129 #define VALID_HOUR(hr) ((hr >= 0) && (hr <= 23))
1130 #define VALID_MIN(min) ((min >= 0) && (min <= 59))
1131 #define VALID_SEC(sec) ((sec >= 0) && (sec < 60))
1132 #define VALID_TZO(tzo) ((tzo >= -840) && (tzo <= 840))
1133 #define IS_LEAP(y) \
1134 (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
1136 static const unsigned int daysInMonth
[12] =
1137 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1138 static const unsigned int daysInMonthLeap
[12] =
1139 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1141 #define MAX_DAYINMONTH(yr,mon) \
1142 (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
1144 #define VALID_MDAY(dt) \
1145 (IS_LEAP(dt->year) ? \
1146 (dt->day <= daysInMonthLeap[dt->mon - 1]) : \
1147 (dt->day <= daysInMonth[dt->mon - 1]))
1149 #define VALID_DATE(dt) \
1150 (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
1152 #define VALID_END_OF_DAY(dt) \
1153 ((dt)->hour == 24 && (dt)->min == 0 && (dt)->sec == 0)
1155 #define VALID_TIME(dt) \
1156 (((VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \
1157 VALID_SEC(dt->sec)) || VALID_END_OF_DAY(dt)) && \
1160 #define VALID_DATETIME(dt) \
1161 (VALID_DATE(dt) && VALID_TIME(dt))
1163 #define SECS_PER_MIN 60
1164 #define MINS_PER_HOUR 60
1165 #define HOURS_PER_DAY 24
1166 #define SECS_PER_HOUR (MINS_PER_HOUR * SECS_PER_MIN)
1167 #define SECS_PER_DAY (HOURS_PER_DAY * SECS_PER_HOUR)
1168 #define MINS_PER_DAY (HOURS_PER_DAY * MINS_PER_HOUR)
1170 static const long dayInYearByMonth
[12] =
1171 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1172 static const long dayInLeapYearByMonth
[12] =
1173 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
1175 #define DAY_IN_YEAR(day, month, year) \
1177 dayInLeapYearByMonth[month - 1] : \
1178 dayInYearByMonth[month - 1]) + day)
1181 #define DEBUG_DATE(dt) \
1182 xmlGenericError(xmlGenericErrorContext, \
1183 "type=%o %04ld-%02u-%02uT%02u:%02u:%03f", \
1184 dt->type,dt->value.date.year,dt->value.date.mon, \
1185 dt->value.date.day,dt->value.date.hour,dt->value.date.min, \
1186 dt->value.date.sec); \
1187 if (dt->value.date.tz_flag) \
1188 if (dt->value.date.tzo != 0) \
1189 xmlGenericError(xmlGenericErrorContext, \
1190 "%+05d\n",dt->value.date.tzo); \
1192 xmlGenericError(xmlGenericErrorContext, "Z\n"); \
1194 xmlGenericError(xmlGenericErrorContext,"\n")
1196 #define DEBUG_DATE(dt)
1200 * _xmlSchemaParseGYear:
1201 * @dt: pointer to a date structure
1202 * @str: pointer to the string to analyze
1204 * Parses a xs:gYear without time zone and fills in the appropriate
1205 * field of the @dt structure. @str is updated to point just after the
1206 * xs:gYear. It is supposed that @dt->year is big enough to contain
1209 * Returns 0 or the error code
1212 _xmlSchemaParseGYear (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1213 const xmlChar
*cur
= *str
, *firstChar
;
1214 int isneg
= 0, digcnt
= 0;
1216 if (((*cur
< '0') || (*cur
> '9')) &&
1217 (*cur
!= '-') && (*cur
!= '+'))
1227 while ((*cur
>= '0') && (*cur
<= '9')) {
1228 int digit
= *cur
- '0';
1230 if (dt
->year
> LONG_MAX
/ 10)
1233 if (dt
->year
> LONG_MAX
- digit
)
1240 /* year must be at least 4 digits (CCYY); over 4
1241 * digits cannot have a leading zero. */
1242 if ((digcnt
< 4) || ((digcnt
> 4) && (*firstChar
== '0')))
1246 dt
->year
= - dt
->year
;
1248 if (!VALID_YEAR(dt
->year
))
1257 * @num: the integer to fill in
1258 * @cur: an #xmlChar *
1259 * @invalid: an integer
1261 * Parses a 2-digits integer and updates @num with the value. @cur is
1262 * updated to point just after the integer.
1263 * In case of error, @invalid is set to %TRUE, values of @num and
1264 * @cur are undefined.
1266 #define PARSE_2_DIGITS(num, cur, invalid) \
1267 if ((cur[0] < '0') || (cur[0] > '9') || \
1268 (cur[1] < '0') || (cur[1] > '9')) \
1271 num = (cur[0] - '0') * 10 + (cur[1] - '0'); \
1276 * @num: the double to fill in
1277 * @cur: an #xmlChar *
1278 * @invalid: an integer
1280 * Parses a float and updates @num with the value. @cur is
1281 * updated to point just after the float. The float must have a
1282 * 2-digits integer part and may or may not have a decimal part.
1283 * In case of error, @invalid is set to %TRUE, values of @num and
1284 * @cur are undefined.
1286 #define PARSE_FLOAT(num, cur, invalid) \
1287 PARSE_2_DIGITS(num, cur, invalid); \
1288 if (!invalid && (*cur == '.')) { \
1291 if ((*cur < '0') || (*cur > '9')) \
1293 while ((*cur >= '0') && (*cur <= '9')) { \
1295 num += (*cur - '0') * mult; \
1301 * _xmlSchemaParseGMonth:
1302 * @dt: pointer to a date structure
1303 * @str: pointer to the string to analyze
1305 * Parses a xs:gMonth without time zone and fills in the appropriate
1306 * field of the @dt structure. @str is updated to point just after the
1309 * Returns 0 or the error code
1312 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1313 const xmlChar
*cur
= *str
;
1315 unsigned int value
= 0;
1317 PARSE_2_DIGITS(value
, cur
, ret
);
1321 if (!VALID_MONTH(value
))
1331 * _xmlSchemaParseGDay:
1332 * @dt: pointer to a date structure
1333 * @str: pointer to the string to analyze
1335 * Parses a xs:gDay without time zone and fills in the appropriate
1336 * field of the @dt structure. @str is updated to point just after the
1339 * Returns 0 or the error code
1342 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1343 const xmlChar
*cur
= *str
;
1345 unsigned int value
= 0;
1347 PARSE_2_DIGITS(value
, cur
, ret
);
1351 if (!VALID_DAY(value
))
1360 * _xmlSchemaParseTime:
1361 * @dt: pointer to a date structure
1362 * @str: pointer to the string to analyze
1364 * Parses a xs:time without time zone and fills in the appropriate
1365 * fields of the @dt structure. @str is updated to point just after the
1367 * In case of error, values of @dt fields are undefined.
1369 * Returns 0 or the error code
1372 _xmlSchemaParseTime (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1373 const xmlChar
*cur
= *str
;
1377 PARSE_2_DIGITS(value
, cur
, ret
);
1382 if (!VALID_HOUR(value
) && value
!= 24 /* Allow end-of-day hour */)
1386 /* the ':' insures this string is xs:time */
1389 PARSE_2_DIGITS(value
, cur
, ret
);
1392 if (!VALID_MIN(value
))
1400 PARSE_FLOAT(dt
->sec
, cur
, ret
);
1404 if (!VALID_TIME(dt
))
1412 * _xmlSchemaParseTimeZone:
1413 * @dt: pointer to a date structure
1414 * @str: pointer to the string to analyze
1416 * Parses a time zone without time zone and fills in the appropriate
1417 * field of the @dt structure. @str is updated to point just after the
1420 * Returns 0 or the error code
1423 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1445 int isneg
= 0, tmp
= 0;
1446 isneg
= (*cur
== '-');
1450 PARSE_2_DIGITS(tmp
, cur
, ret
);
1453 if (!VALID_HOUR(tmp
))
1462 PARSE_2_DIGITS(tmp
, cur
, ret
);
1465 if (!VALID_MIN(tmp
))
1470 dt
->tzo
= - dt
->tzo
;
1472 if (!VALID_TZO(dt
->tzo
))
1487 * _xmlSchemaBase64Decode:
1490 * Converts a base64 encoded character to its base 64 value.
1492 * Returns 0-63 (value), 64 (pad), or -1 (not recognized)
1495 _xmlSchemaBase64Decode (const xmlChar ch
) {
1496 if (('A' <= ch
) && (ch
<= 'Z')) return ch
- 'A';
1497 if (('a' <= ch
) && (ch
<= 'z')) return ch
- 'a' + 26;
1498 if (('0' <= ch
) && (ch
<= '9')) return ch
- '0' + 52;
1499 if ('+' == ch
) return 62;
1500 if ('/' == ch
) return 63;
1501 if ('=' == ch
) return 64;
1505 /****************************************************************
1507 * XML Schema Dates/Times Datatypes Handling *
1509 ****************************************************************/
1513 * @num: the integer to fill in
1514 * @cur: an #xmlChar *
1515 * @num_type: an integer flag
1517 * Parses a digits integer and updates @num with the value. @cur is
1518 * updated to point just after the integer.
1519 * In case of error, @num_type is set to -1, values of @num and
1520 * @cur are undefined.
1522 #define PARSE_DIGITS(num, cur, num_type) \
1523 if ((*cur < '0') || (*cur > '9')) \
1526 while ((*cur >= '0') && (*cur <= '9')) { \
1527 num = num * 10 + (*cur - '0'); \
1533 * @num: the double to fill in
1534 * @cur: an #xmlChar *
1535 * @num_type: an integer flag
1537 * Parses a float or integer and updates @num with the value. @cur is
1538 * updated to point just after the number. If the number is a float,
1539 * then it must have an integer part and a decimal part; @num_type will
1540 * be set to 1. If there is no decimal part, @num_type is set to zero.
1541 * In case of error, @num_type is set to -1, values of @num and
1542 * @cur are undefined.
1544 #define PARSE_NUM(num, cur, num_type) \
1546 PARSE_DIGITS(num, cur, num_type); \
1547 if (!num_type && (*cur == '.')) { \
1550 if ((*cur < '0') || (*cur > '9')) \
1554 while ((*cur >= '0') && (*cur <= '9')) { \
1556 num += (*cur - '0') * mult; \
1562 * xmlSchemaValidateDates:
1563 * @type: the expected type or XML_SCHEMAS_UNKNOWN
1564 * @dateTime: string to analyze
1565 * @val: the return computed value
1567 * Check that @dateTime conforms to the lexical space of one of the date types.
1568 * if true a value is computed and returned in @val.
1570 * Returns 0 if this validates, a positive error code number otherwise
1571 * and -1 in case of internal or API error.
1574 xmlSchemaValidateDates (xmlSchemaValType type
,
1575 const xmlChar
*dateTime
, xmlSchemaValPtr
*val
,
1579 const xmlChar
*cur
= dateTime
;
1581 #define RETURN_TYPE_IF_VALID(t) \
1582 if (IS_TZO_CHAR(*cur)) { \
1583 ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); \
1592 if (dateTime
== NULL
)
1596 while IS_WSP_BLANK_CH(*cur
) cur
++;
1598 if ((*cur
!= '-') && (*cur
< '0') && (*cur
> '9'))
1601 dt
= xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN
);
1605 if ((cur
[0] == '-') && (cur
[1] == '-')) {
1607 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
1612 /* is it an xs:gDay? */
1614 if (type
== XML_SCHEMAS_GMONTH
)
1617 ret
= _xmlSchemaParseGDay(&(dt
->value
.date
), &cur
);
1621 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY
);
1627 * it should be an xs:gMonthDay or xs:gMonth
1629 ret
= _xmlSchemaParseGMonth(&(dt
->value
.date
), &cur
);
1634 * a '-' char could indicate this type is xs:gMonthDay or
1635 * a negative time zone offset. Check for xs:gMonthDay first.
1636 * Also the first three char's of a negative tzo (-MM:SS) can
1637 * appear to be a valid day; so even if the day portion
1638 * of the xs:gMonthDay verifies, we must insure it was not
1642 const xmlChar
*rewnd
= cur
;
1645 ret
= _xmlSchemaParseGDay(&(dt
->value
.date
), &cur
);
1646 if ((ret
== 0) && ((*cur
== 0) || (*cur
!= ':'))) {
1649 * we can use the VALID_MDAY macro to validate the month
1650 * and day because the leap year test will flag year zero
1651 * as a leap year (even though zero is an invalid year).
1652 * FUTURE TODO: Zero will become valid in XML Schema 1.1
1655 if (VALID_MDAY((&(dt
->value
.date
)))) {
1657 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY
);
1664 * not xs:gMonthDay so rewind and check if just xs:gMonth
1665 * with an optional time zone.
1670 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH
);
1676 * It's a right-truncated date or an xs:time.
1677 * Try to parse an xs:time then fallback on right-truncated dates.
1679 if ((*cur
>= '0') && (*cur
<= '9')) {
1680 ret
= _xmlSchemaParseTime(&(dt
->value
.date
), &cur
);
1682 /* it's an xs:time */
1683 RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME
);
1687 /* fallback on date parsing */
1690 ret
= _xmlSchemaParseGYear(&(dt
->value
.date
), &cur
);
1694 /* is it an xs:gYear? */
1695 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR
);
1701 ret
= _xmlSchemaParseGMonth(&(dt
->value
.date
), &cur
);
1705 /* is it an xs:gYearMonth? */
1706 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH
);
1712 ret
= _xmlSchemaParseGDay(&(dt
->value
.date
), &cur
);
1713 if ((ret
!= 0) || !VALID_DATE((&(dt
->value
.date
))))
1716 /* is it an xs:date? */
1717 RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE
);
1723 /* it should be an xs:dateTime */
1724 ret
= _xmlSchemaParseTime(&(dt
->value
.date
), &cur
);
1728 ret
= _xmlSchemaParseTimeZone(&(dt
->value
.date
), &cur
);
1730 while IS_WSP_BLANK_CH(*cur
) cur
++;
1731 if ((ret
!= 0) || (*cur
!= 0) || (!(VALID_DATETIME((&(dt
->value
.date
))))))
1735 dt
->type
= XML_SCHEMAS_DATETIME
;
1739 if ((type
!= XML_SCHEMAS_UNKNOWN
) && (type
!= dt
->type
))
1743 * insure the parsed type is equal to or less significant (right
1744 * truncated) than the desired type.
1746 if ((type
!= XML_SCHEMAS_UNKNOWN
) && (type
!= dt
->type
)) {
1748 /* time only matches time */
1749 if ((type
== XML_SCHEMAS_TIME
) && (dt
->type
== XML_SCHEMAS_TIME
))
1752 if ((type
== XML_SCHEMAS_DATETIME
) &&
1753 ((dt
->type
!= XML_SCHEMAS_DATE
) ||
1754 (dt
->type
!= XML_SCHEMAS_GYEARMONTH
) ||
1755 (dt
->type
!= XML_SCHEMAS_GYEAR
)))
1758 if ((type
== XML_SCHEMAS_DATE
) &&
1759 ((dt
->type
!= XML_SCHEMAS_GYEAR
) ||
1760 (dt
->type
!= XML_SCHEMAS_GYEARMONTH
)))
1763 if ((type
== XML_SCHEMAS_GYEARMONTH
) && (dt
->type
!= XML_SCHEMAS_GYEAR
))
1766 if ((type
== XML_SCHEMAS_GMONTHDAY
) && (dt
->type
!= XML_SCHEMAS_GMONTH
))
1774 xmlSchemaFreeValue(dt
);
1780 xmlSchemaFreeValue(dt
);
1785 * xmlSchemaValidateDuration:
1786 * @type: the predefined type
1787 * @duration: string to analyze
1788 * @val: the return computed value
1790 * Check that @duration conforms to the lexical space of the duration type.
1791 * if true a value is computed and returned in @val.
1793 * Returns 0 if this validates, a positive error code number otherwise
1794 * and -1 in case of internal or API error.
1797 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED
,
1798 const xmlChar
*duration
, xmlSchemaValPtr
*val
,
1800 const xmlChar
*cur
= duration
;
1801 xmlSchemaValPtr dur
;
1803 unsigned int seq
= 0;
1804 long days
, secs
= 0;
1805 double sec_frac
= 0.0;
1807 if (duration
== NULL
)
1811 while IS_WSP_BLANK_CH(*cur
) cur
++;
1818 /* duration must start with 'P' (after sign) */
1825 dur
= xmlSchemaNewValue(XML_SCHEMAS_DURATION
);
1831 size_t has_digits
= 0;
1833 const xmlChar desig
[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
1835 /* input string should be empty or invalid date/time item */
1836 if (seq
>= sizeof(desig
))
1839 /* T designator must be present for time items */
1845 } else if (seq
== 3)
1848 /* Parse integral part. */
1849 while (*cur
>= '0' && *cur
<= '9') {
1850 long digit
= *cur
- '0';
1852 if (num
> LONG_MAX
/ 10)
1855 if (num
> LONG_MAX
- digit
)
1864 /* Parse fractional part. */
1868 while (*cur
>= '0' && *cur
<= '9') {
1870 sec_frac
+= (*cur
- '0') * mult
;
1876 while (*cur
!= desig
[seq
]) {
1878 /* No T designator or invalid char. */
1879 if (seq
== 3 || seq
== sizeof(desig
))
1884 if (!has_digits
|| (has_frac
&& (seq
!= 5)))
1890 if (num
> LONG_MAX
/ 12)
1892 dur
->value
.dur
.mon
= num
* 12;
1896 if (dur
->value
.dur
.mon
> LONG_MAX
- num
)
1898 dur
->value
.dur
.mon
+= num
;
1902 dur
->value
.dur
.day
= num
;
1906 days
= num
/ HOURS_PER_DAY
;
1907 if (dur
->value
.dur
.day
> LONG_MAX
- days
)
1909 dur
->value
.dur
.day
+= days
;
1910 secs
= (num
% HOURS_PER_DAY
) * SECS_PER_HOUR
;
1914 days
= num
/ MINS_PER_DAY
;
1915 if (dur
->value
.dur
.day
> LONG_MAX
- days
)
1917 dur
->value
.dur
.day
+= days
;
1918 secs
+= (num
% MINS_PER_DAY
) * SECS_PER_MIN
;
1922 days
= num
/ SECS_PER_DAY
;
1923 if (dur
->value
.dur
.day
> LONG_MAX
- days
)
1925 dur
->value
.dur
.day
+= days
;
1926 secs
+= num
% SECS_PER_DAY
;
1933 days
= secs
/ SECS_PER_DAY
;
1934 if (dur
->value
.dur
.day
> LONG_MAX
- days
)
1936 dur
->value
.dur
.day
+= days
;
1937 dur
->value
.dur
.sec
= (secs
% SECS_PER_DAY
) + sec_frac
;
1940 dur
->value
.dur
.mon
= -dur
->value
.dur
.mon
;
1941 dur
->value
.dur
.day
= -dur
->value
.dur
.day
;
1942 dur
->value
.dur
.sec
= -dur
->value
.dur
.sec
;
1948 xmlSchemaFreeValue(dur
);
1954 xmlSchemaFreeValue(dur
);
1962 * Removes the leading and ending spaces of a string
1964 * Returns the new string or NULL if no change was required.
1967 xmlSchemaStrip(const xmlChar
*value
) {
1968 const xmlChar
*start
= value
, *end
, *f
;
1970 if (value
== NULL
) return(NULL
);
1971 while ((*start
!= 0) && (IS_BLANK_CH(*start
))) start
++;
1973 while (*end
!= 0) end
++;
1976 while ((end
> start
) && (IS_BLANK_CH(*end
))) end
--;
1978 if ((start
== value
) && (f
== end
)) return(NULL
);
1979 return(xmlStrndup(start
, end
- start
));
1983 * xmlSchemaWhiteSpaceReplace:
1986 * Replaces 0xd, 0x9 and 0xa with a space.
1988 * Returns the new string or NULL if no change was required.
1991 xmlSchemaWhiteSpaceReplace(const xmlChar
*value
) {
1992 const xmlChar
*cur
= value
;
1993 xmlChar
*ret
= NULL
, *mcur
;
1998 while ((*cur
!= 0) &&
1999 (((*cur
) != 0xd) && ((*cur
) != 0x9) && ((*cur
) != 0xa))) {
2004 ret
= xmlStrdup(value
);
2005 /* TODO FIXME: I guess gcc will bark at this. */
2006 mcur
= (xmlChar
*) (ret
+ (cur
- value
));
2008 if ( ((*mcur
) == 0xd) || ((*mcur
) == 0x9) || ((*mcur
) == 0xa) )
2011 } while (*mcur
!= 0);
2016 * xmlSchemaCollapseString:
2019 * Removes and normalize white spaces in the string
2021 * Returns the new string or NULL if no change was required.
2024 xmlSchemaCollapseString(const xmlChar
*value
) {
2025 const xmlChar
*start
= value
, *end
, *f
;
2029 if (value
== NULL
) return(NULL
);
2030 while ((*start
!= 0) && (IS_BLANK_CH(*start
))) start
++;
2033 if ((*end
== ' ') && (IS_BLANK_CH(end
[1]))) {
2036 } else if ((*end
== 0xa) || (*end
== 0x9) || (*end
== 0xd)) {
2045 while ((end
> start
) && (IS_BLANK_CH(*end
))) end
--;
2047 if ((start
== value
) && (f
== end
)) return(NULL
);
2048 return(xmlStrndup(start
, end
- start
));
2050 start
= xmlStrdup(start
);
2051 if (start
== NULL
) return(NULL
);
2052 g
= (xmlChar
*) (start
+ col
);
2055 if (IS_BLANK_CH(*end
)) {
2057 while (IS_BLANK_CH(*end
)) end
++;
2064 return((xmlChar
*) start
);
2068 * xmlSchemaValAtomicListNode:
2069 * @type: the predefined atomic type for a token in the list
2070 * @value: the list value to check
2071 * @ret: the return computed value
2072 * @node: the node containing the value
2074 * Check that a value conforms to the lexical space of the predefined
2075 * list type. if true a value is computed and returned in @ret.
2077 * Returns the number of items if this validates, a negative error code
2081 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type
, const xmlChar
*value
,
2082 xmlSchemaValPtr
*ret
, xmlNodePtr node
) {
2083 xmlChar
*val
, *cur
, *endval
;
2087 if (value
== NULL
) {
2090 val
= xmlStrdup(value
);
2101 while (IS_BLANK_CH(*cur
)) *cur
++ = 0;
2103 if (IS_BLANK_CH(*cur
)) {
2106 while (IS_BLANK_CH(*cur
)) *cur
++ = 0;
2110 while ((*cur
!= 0) && (!IS_BLANK_CH(*cur
))) cur
++;
2113 if (nb_values
== 0) {
2119 while ((*cur
== 0) && (cur
!= endval
)) cur
++;
2120 while (cur
!= endval
) {
2121 tmp
= xmlSchemaValPredefTypeNode(type
, cur
, NULL
, node
);
2124 while (*cur
!= 0) cur
++;
2125 while ((*cur
== 0) && (cur
!= endval
)) cur
++;
2127 /* TODO what return value ? c.f. bug #158628
2138 * xmlSchemaParseUInt:
2139 * @str: pointer to the string R/W
2140 * @llo: pointer to the low result
2141 * @lmi: pointer to the mid result
2142 * @lhi: pointer to the high result
2144 * Parse an unsigned long into 3 fields.
2146 * Returns the number of significant digits in the number or
2147 * -1 if overflow of the capacity and -2 if it's not a number.
2150 xmlSchemaParseUInt(const xmlChar
**str
, unsigned long *llo
,
2151 unsigned long *lmi
, unsigned long *lhi
) {
2152 unsigned long lo
= 0, mi
= 0, hi
= 0;
2153 const xmlChar
*tmp
, *cur
= *str
;
2156 if (!((*cur
>= '0') && (*cur
<= '9')))
2159 while (*cur
== '0') { /* ignore leading zeroes */
2163 while ((*tmp
!= 0) && (*tmp
>= '0') && (*tmp
<= '9')) {
2171 hi
= hi
* 10 + (*cur
++ - '0');
2175 mi
= mi
* 10 + (*cur
++ - '0');
2179 lo
= lo
* 10 + (*cur
++ - '0');
2191 * xmlSchemaCheckLanguageType
2192 * @value: the value to check
2194 * Check that a value conforms to the lexical space of the language datatype.
2195 * Must conform to [a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*
2197 * Returns 1 if this validates, 0 otherwise.
2200 xmlSchemaCheckLanguageType(const xmlChar
* value
) {
2201 int first
= 1, len
= 0;
2202 const xmlChar
* cur
= value
;
2207 while (cur
[0] != 0) {
2208 if (!( ((cur
[0] >= 'a') && (cur
[0] <= 'z')) || ((cur
[0] >= 'A') && (cur
[0] <= 'Z'))
2210 || ((first
== 0) && (xmlIsDigit_ch(cur
[0]))) ))
2212 if (cur
[0] == '-') {
2213 if ((len
< 1) || (len
> 8))
2222 if ((len
< 1) || (len
> 8))
2229 * xmlSchemaValAtomicType:
2230 * @type: the predefined type
2231 * @value: the value to check
2232 * @val: the return computed value
2233 * @node: the node containing the value
2234 * flags: flags to control the validation
2236 * Check that a value conforms to the lexical space of the atomic type.
2237 * if true a value is computed and returned in @val.
2238 * This checks the value space for list types as well (IDREFS, NMTOKENS).
2240 * Returns 0 if this validates, a positive error code number otherwise
2241 * and -1 in case of internal or API error.
2244 xmlSchemaValAtomicType(xmlSchemaTypePtr type
, const xmlChar
* value
,
2245 xmlSchemaValPtr
* val
, xmlNodePtr node
, int flags
,
2246 xmlSchemaWhitespaceValueType ws
,
2247 int normOnTheFly
, int applyNorm
, int createStringValue
)
2250 xmlChar
*norm
= NULL
;
2253 if (xmlSchemaTypesInitialized
== 0)
2254 xmlSchemaInitTypes();
2259 * validating a non existent text node is similar to validating
2263 value
= BAD_CAST
"";
2267 if ((flags
== 0) && (value
!= NULL
)) {
2269 if ((type
->builtInType
!= XML_SCHEMAS_STRING
) &&
2270 (type
->builtInType
!= XML_SCHEMAS_ANYTYPE
) &&
2271 (type
->builtInType
!= XML_SCHEMAS_ANYSIMPLETYPE
)) {
2272 if (type
->builtInType
== XML_SCHEMAS_NORMSTRING
)
2273 norm
= xmlSchemaWhiteSpaceReplace(value
);
2275 norm
= xmlSchemaCollapseString(value
);
2281 switch (type
->builtInType
) {
2282 case XML_SCHEMAS_UNKNOWN
:
2284 case XML_SCHEMAS_ANYTYPE
:
2285 case XML_SCHEMAS_ANYSIMPLETYPE
:
2286 if ((createStringValue
) && (val
!= NULL
)) {
2287 v
= xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE
);
2289 v
->value
.str
= xmlStrdup(value
);
2296 case XML_SCHEMAS_STRING
:
2297 if (! normOnTheFly
) {
2298 const xmlChar
*cur
= value
;
2300 if (ws
== XML_SCHEMA_WHITESPACE_REPLACE
) {
2302 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2308 } else if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
) {
2310 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2312 } else if IS_WSP_SPACE_CH(*cur
) {
2314 if IS_WSP_SPACE_CH(*cur
)
2322 if (createStringValue
&& (val
!= NULL
)) {
2324 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
2325 norm
= xmlSchemaCollapseString(value
);
2326 else if (ws
== XML_SCHEMA_WHITESPACE_REPLACE
)
2327 norm
= xmlSchemaWhiteSpaceReplace(value
);
2331 v
= xmlSchemaNewValue(XML_SCHEMAS_STRING
);
2333 v
->value
.str
= xmlStrdup(value
);
2340 case XML_SCHEMAS_NORMSTRING
:{
2343 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
2344 norm
= xmlSchemaCollapseString(value
);
2346 norm
= xmlSchemaWhiteSpaceReplace(value
);
2351 const xmlChar
*cur
= value
;
2353 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2361 v
= xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING
);
2363 v
->value
.str
= xmlStrdup(value
);
2371 case XML_SCHEMAS_DECIMAL
:{
2372 const xmlChar
*cur
= value
;
2373 unsigned int len
, neg
, integ
, hasLeadingZeroes
;
2375 xmlChar
*cptr
= cval
;
2377 if ((cur
== NULL
) || (*cur
== 0))
2381 * xs:decimal has a whitespace-facet value of 'collapse'.
2384 while IS_WSP_BLANK_CH(*cur
) cur
++;
2387 * First we handle an optional sign.
2393 } else if (*cur
== '+')
2396 * Disallow: "", "-", "- "
2401 * Next we "pre-parse" the number, in preparation for calling
2402 * the common routine xmlSchemaParseUInt. We get rid of any
2403 * leading zeroes (because we have reserved only 25 chars),
2404 * and note the position of a decimal point.
2408 hasLeadingZeroes
= 0;
2410 * Skip leading zeroes.
2412 while (*cur
== '0') {
2414 hasLeadingZeroes
= 1;
2418 if ((*cur
>= '0') && (*cur
<= '9')) {
2421 } else if (*cur
== '.') {
2425 if ((*cur
>= '0') && (*cur
<= '9')) {
2432 * Disallow "." but allow "00."
2434 if ((len
== 0) && (!hasLeadingZeroes
))
2442 while IS_WSP_BLANK_CH(*cur
) cur
++;
2444 goto return1
; /* error if any extraneous chars */
2446 v
= xmlSchemaNewValue(XML_SCHEMAS_DECIMAL
);
2449 * Now evaluate the significant digits of the number
2455 * Get rid of trailing zeroes in the
2458 while ((len
!= integ
) && (*(cptr
-1) == '0')) {
2464 * Terminate the (preparsed) string.
2470 xmlSchemaParseUInt((const xmlChar
**)&cptr
,
2471 &v
->value
.decimal
.lo
,
2472 &v
->value
.decimal
.mi
,
2473 &v
->value
.decimal
.hi
);
2477 * Set the total digits to 1 if a zero value.
2479 v
->value
.decimal
.sign
= neg
;
2481 /* Speedup for zero values. */
2482 v
->value
.decimal
.total
= 1;
2484 v
->value
.decimal
.total
= len
;
2486 v
->value
.decimal
.frac
= 0;
2488 v
->value
.decimal
.frac
= len
- integ
;
2495 case XML_SCHEMAS_TIME
:
2496 case XML_SCHEMAS_GDAY
:
2497 case XML_SCHEMAS_GMONTH
:
2498 case XML_SCHEMAS_GMONTHDAY
:
2499 case XML_SCHEMAS_GYEAR
:
2500 case XML_SCHEMAS_GYEARMONTH
:
2501 case XML_SCHEMAS_DATE
:
2502 case XML_SCHEMAS_DATETIME
:
2503 ret
= xmlSchemaValidateDates(type
->builtInType
, value
, val
,
2506 case XML_SCHEMAS_DURATION
:
2507 ret
= xmlSchemaValidateDuration(type
, value
, val
,
2510 case XML_SCHEMAS_FLOAT
:
2511 case XML_SCHEMAS_DOUBLE
: {
2512 const xmlChar
*cur
= value
;
2514 int digits_before
= 0;
2515 int digits_after
= 0;
2518 while IS_WSP_BLANK_CH(*cur
) cur
++;
2520 if ((cur
[0] == 'N') && (cur
[1] == 'a') && (cur
[2] == 'N')) {
2525 if (type
== xmlSchemaTypeFloatDef
) {
2526 v
= xmlSchemaNewValue(XML_SCHEMAS_FLOAT
);
2528 v
->value
.f
= (float) xmlXPathNAN
;
2530 xmlSchemaFreeValue(v
);
2534 v
= xmlSchemaNewValue(XML_SCHEMAS_DOUBLE
);
2536 v
->value
.d
= xmlXPathNAN
;
2538 xmlSchemaFreeValue(v
);
2550 if ((cur
[0] == 'I') && (cur
[1] == 'N') && (cur
[2] == 'F')) {
2555 if (type
== xmlSchemaTypeFloatDef
) {
2556 v
= xmlSchemaNewValue(XML_SCHEMAS_FLOAT
);
2559 v
->value
.f
= (float) xmlXPathNINF
;
2561 v
->value
.f
= (float) xmlXPathPINF
;
2563 xmlSchemaFreeValue(v
);
2567 v
= xmlSchemaNewValue(XML_SCHEMAS_DOUBLE
);
2570 v
->value
.d
= xmlXPathNINF
;
2572 v
->value
.d
= xmlXPathPINF
;
2574 xmlSchemaFreeValue(v
);
2582 if ((neg
== 0) && (*cur
== '+'))
2584 if ((cur
[0] == 0) || (cur
[0] == '+') || (cur
[0] == '-'))
2586 while ((*cur
>= '0') && (*cur
<= '9')) {
2592 while ((*cur
>= '0') && (*cur
<= '9')) {
2597 if ((digits_before
== 0) && (digits_after
== 0))
2599 if ((*cur
== 'e') || (*cur
== 'E')) {
2601 if ((*cur
== '-') || (*cur
== '+'))
2603 while ((*cur
>= '0') && (*cur
<= '9'))
2607 while IS_WSP_BLANK_CH(*cur
) cur
++;
2612 if (type
== xmlSchemaTypeFloatDef
) {
2613 v
= xmlSchemaNewValue(XML_SCHEMAS_FLOAT
);
2616 * TODO: sscanf seems not to give the correct
2617 * value for extremely high/low values.
2618 * E.g. "1E-149" results in zero.
2620 if (sscanf((const char *) value
, "%f",
2621 &(v
->value
.f
)) == 1) {
2624 xmlSchemaFreeValue(v
);
2631 v
= xmlSchemaNewValue(XML_SCHEMAS_DOUBLE
);
2634 * TODO: sscanf seems not to give the correct
2635 * value for extremely high/low values.
2637 if (sscanf((const char *) value
, "%lf",
2638 &(v
->value
.d
)) == 1) {
2641 xmlSchemaFreeValue(v
);
2651 case XML_SCHEMAS_BOOLEAN
:{
2652 const xmlChar
*cur
= value
;
2655 while IS_WSP_BLANK_CH(*cur
) cur
++;
2659 } else if (*cur
== '1') {
2662 } else if (*cur
== 't') {
2664 if ((*cur
++ == 'r') && (*cur
++ == 'u') &&
2669 } else if (*cur
== 'f') {
2671 if ((*cur
++ == 'a') && (*cur
++ == 'l') &&
2672 (*cur
++ == 's') && (*cur
++ == 'e')) {
2679 while IS_WSP_BLANK_CH(*cur
) cur
++;
2684 if ((cur
[0] == '0') && (cur
[1] == 0))
2686 else if ((cur
[0] == '1') && (cur
[1] == 0))
2688 else if ((cur
[0] == 't') && (cur
[1] == 'r')
2689 && (cur
[2] == 'u') && (cur
[3] == 'e')
2692 else if ((cur
[0] == 'f') && (cur
[1] == 'a')
2693 && (cur
[2] == 'l') && (cur
[3] == 's')
2694 && (cur
[4] == 'e') && (cur
[5] == 0))
2700 v
= xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN
);
2710 case XML_SCHEMAS_TOKEN
:{
2711 const xmlChar
*cur
= value
;
2713 if (! normOnTheFly
) {
2715 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2717 } else if (*cur
== ' ') {
2729 v
= xmlSchemaNewValue(XML_SCHEMAS_TOKEN
);
2731 v
->value
.str
= xmlStrdup(value
);
2739 case XML_SCHEMAS_LANGUAGE
:
2740 if ((norm
== NULL
) && (normOnTheFly
)) {
2741 norm
= xmlSchemaCollapseString(value
);
2746 if (xmlSchemaCheckLanguageType(value
) == 1) {
2748 v
= xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE
);
2750 v
->value
.str
= xmlStrdup(value
);
2759 case XML_SCHEMAS_NMTOKEN
:
2760 if (xmlValidateNMToken(value
, 1) == 0) {
2762 v
= xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN
);
2764 v
->value
.str
= xmlStrdup(value
);
2773 case XML_SCHEMAS_NMTOKENS
:
2774 ret
= xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef
,
2781 case XML_SCHEMAS_NAME
:
2782 ret
= xmlValidateName(value
, 1);
2783 if ((ret
== 0) && (val
!= NULL
) && (value
!= NULL
)) {
2784 v
= xmlSchemaNewValue(XML_SCHEMAS_NAME
);
2786 const xmlChar
*start
= value
, *end
;
2787 while (IS_BLANK_CH(*start
)) start
++;
2789 while ((*end
!= 0) && (!IS_BLANK_CH(*end
))) end
++;
2790 v
->value
.str
= xmlStrndup(start
, end
- start
);
2797 case XML_SCHEMAS_QNAME
:{
2798 const xmlChar
*uri
= NULL
;
2799 xmlChar
*local
= NULL
;
2801 ret
= xmlValidateQName(value
, 1);
2808 local
= xmlSplitQName2(value
, &prefix
);
2809 ns
= xmlSearchNs(node
->doc
, node
, prefix
);
2810 if ((ns
== NULL
) && (prefix
!= NULL
)) {
2822 v
= xmlSchemaNewValue(XML_SCHEMAS_QNAME
);
2829 v
->value
.qname
.name
= local
;
2831 v
->value
.qname
.name
= xmlStrdup(value
);
2833 v
->value
.qname
.uri
= xmlStrdup(uri
);
2840 case XML_SCHEMAS_NCNAME
:
2841 ret
= xmlValidateNCName(value
, 1);
2842 if ((ret
== 0) && (val
!= NULL
)) {
2843 v
= xmlSchemaNewValue(XML_SCHEMAS_NCNAME
);
2845 v
->value
.str
= xmlStrdup(value
);
2852 case XML_SCHEMAS_ID
:
2853 ret
= xmlValidateNCName(value
, 1);
2854 if ((ret
== 0) && (val
!= NULL
)) {
2855 v
= xmlSchemaNewValue(XML_SCHEMAS_ID
);
2857 v
->value
.str
= xmlStrdup(value
);
2863 if ((ret
== 0) && (node
!= NULL
) &&
2864 (node
->type
== XML_ATTRIBUTE_NODE
)) {
2865 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
2868 * NOTE: the IDness might have already be declared in the DTD
2870 if (attr
->atype
!= XML_ATTRIBUTE_ID
) {
2874 strip
= xmlSchemaStrip(value
);
2875 if (strip
!= NULL
) {
2876 res
= xmlAddID(NULL
, node
->doc
, strip
, attr
);
2879 res
= xmlAddID(NULL
, node
->doc
, value
, attr
);
2883 attr
->atype
= XML_ATTRIBUTE_ID
;
2888 case XML_SCHEMAS_IDREF
:
2889 ret
= xmlValidateNCName(value
, 1);
2890 if ((ret
== 0) && (val
!= NULL
)) {
2891 v
= xmlSchemaNewValue(XML_SCHEMAS_IDREF
);
2894 v
->value
.str
= xmlStrdup(value
);
2897 if ((ret
== 0) && (node
!= NULL
) &&
2898 (node
->type
== XML_ATTRIBUTE_NODE
)) {
2899 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
2902 strip
= xmlSchemaStrip(value
);
2903 if (strip
!= NULL
) {
2904 xmlAddRef(NULL
, node
->doc
, strip
, attr
);
2907 xmlAddRef(NULL
, node
->doc
, value
, attr
);
2908 attr
->atype
= XML_ATTRIBUTE_IDREF
;
2911 case XML_SCHEMAS_IDREFS
:
2912 ret
= xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef
,
2918 if ((ret
== 0) && (node
!= NULL
) &&
2919 (node
->type
== XML_ATTRIBUTE_NODE
)) {
2920 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
2922 attr
->atype
= XML_ATTRIBUTE_IDREFS
;
2925 case XML_SCHEMAS_ENTITY
:{
2928 ret
= xmlValidateNCName(value
, 1);
2929 if ((node
== NULL
) || (node
->doc
== NULL
))
2934 strip
= xmlSchemaStrip(value
);
2935 if (strip
!= NULL
) {
2936 ent
= xmlGetDocEntity(node
->doc
, strip
);
2939 ent
= xmlGetDocEntity(node
->doc
, value
);
2941 if ((ent
== NULL
) ||
2943 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
))
2946 if ((ret
== 0) && (val
!= NULL
)) {
2949 if ((ret
== 0) && (node
!= NULL
) &&
2950 (node
->type
== XML_ATTRIBUTE_NODE
)) {
2951 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
2953 attr
->atype
= XML_ATTRIBUTE_ENTITY
;
2957 case XML_SCHEMAS_ENTITIES
:
2958 if ((node
== NULL
) || (node
->doc
== NULL
))
2960 ret
= xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef
,
2966 if ((ret
== 0) && (node
!= NULL
) &&
2967 (node
->type
== XML_ATTRIBUTE_NODE
)) {
2968 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
2970 attr
->atype
= XML_ATTRIBUTE_ENTITIES
;
2973 case XML_SCHEMAS_NOTATION
:{
2974 xmlChar
*uri
= NULL
;
2975 xmlChar
*local
= NULL
;
2977 ret
= xmlValidateQName(value
, 1);
2978 if ((ret
== 0) && (node
!= NULL
)) {
2981 local
= xmlSplitQName2(value
, &prefix
);
2982 if (prefix
!= NULL
) {
2985 ns
= xmlSearchNs(node
->doc
, node
, prefix
);
2988 else if (val
!= NULL
)
2989 uri
= xmlStrdup(ns
->href
);
2991 if ((local
!= NULL
) && ((val
== NULL
) || (ret
!= 0)))
2996 if ((node
== NULL
) || (node
->doc
== NULL
))
2999 ret
= xmlValidateNotationUse(NULL
, node
->doc
, value
);
3005 if ((ret
== 0) && (val
!= NULL
)) {
3006 v
= xmlSchemaNewValue(XML_SCHEMAS_NOTATION
);
3009 v
->value
.qname
.name
= local
;
3011 v
->value
.qname
.name
= xmlStrdup(value
);
3013 v
->value
.qname
.uri
= uri
;
3026 case XML_SCHEMAS_ANYURI
:{
3029 xmlChar
*tmpval
, *cur
;
3030 if ((norm
== NULL
) && (normOnTheFly
)) {
3031 norm
= xmlSchemaCollapseString(value
);
3035 tmpval
= xmlStrdup(value
);
3036 for (cur
= tmpval
; *cur
; ++cur
) {
3037 if (*cur
< 32 || *cur
>= 127 || *cur
== ' ' ||
3038 *cur
== '<' || *cur
== '>' || *cur
== '"' ||
3039 *cur
== '{' || *cur
== '}' || *cur
== '|' ||
3040 *cur
== '\\' || *cur
== '^' || *cur
== '`' ||
3044 uri
= xmlParseURI((const char *) tmpval
);
3052 v
= xmlSchemaNewValue(XML_SCHEMAS_ANYURI
);
3055 v
->value
.str
= xmlStrdup(value
);
3060 case XML_SCHEMAS_HEXBINARY
:{
3061 const xmlChar
*cur
= value
, *start
;
3069 while IS_WSP_BLANK_CH(*cur
) cur
++;
3072 while (((*cur
>= '0') && (*cur
<= '9')) ||
3073 ((*cur
>= 'A') && (*cur
<= 'F')) ||
3074 ((*cur
>= 'a') && (*cur
<= 'f'))) {
3079 while IS_WSP_BLANK_CH(*cur
) cur
++;
3088 v
= xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY
);
3092 * Copy only the normalized piece.
3093 * CRITICAL TODO: Check this.
3095 cur
= xmlStrndup(start
, i
);
3097 xmlSchemaTypeErrMemory(node
, "allocating hexbin data");
3102 total
= i
/ 2; /* number of octets */
3104 base
= (xmlChar
*) cur
;
3107 *base
= *base
- ('a' - 'A');
3111 v
->value
.hex
.str
= (xmlChar
*) cur
;
3112 v
->value
.hex
.total
= total
;
3117 case XML_SCHEMAS_BASE64BINARY
:{
3120 * Ignore all stray characters? (yes, currently)
3121 * Worry about long lines? (no, currently)
3125 * "The encoded output stream must be represented in lines of
3126 * no more than 76 characters each. All line breaks or other
3127 * characters not found in Table 1 must be ignored by decoding
3128 * software. In base64 data, characters other than those in
3129 * Table 1, line breaks, and other white space probably
3130 * indicate a transmission error, about which a warning
3131 * message or even a message rejection might be appropriate
3132 * under some circumstances." */
3133 const xmlChar
*cur
= value
;
3135 int total
, i
= 0, pad
= 0;
3140 for (; *cur
; ++cur
) {
3143 decc
= _xmlSchemaBase64Decode(*cur
);
3150 for (; *cur
; ++cur
) {
3153 decc
= _xmlSchemaBase64Decode(*cur
);
3161 /* rfc2045.txt: "Special processing is performed if fewer than
3162 * 24 bits are available at the end of the data being encoded.
3163 * A full encoding quantum is always completed at the end of a
3164 * body. When fewer than 24 input bits are available in an
3165 * input group, zero bits are added (on the right) to form an
3166 * integral number of 6-bit groups. Padding at the end of the
3167 * data is performed using the "=" character. Since all
3168 * base64 input is an integral number of octets, only the
3169 * following cases can arise: (1) the final quantum of
3170 * encoding input is an integral multiple of 24 bits; here,
3171 * the final unit of encoded output will be an integral
3172 * multiple of indent: Standard input:701: Warning:old style
3173 * assignment ambiguity in "=*". Assuming "= *" 4 characters
3174 * with no "=" padding, (2) the final
3175 * quantum of encoding input is exactly 8 bits; here, the
3176 * final unit of encoded output will be two characters
3177 * followed by two "=" padding characters, or (3) the final
3178 * quantum of encoding input is exactly 16 bits; here, the
3179 * final unit of encoded output will be three characters
3180 * followed by one "=" padding character." */
3182 total
= 3 * (i
/ 4);
3186 } else if (pad
== 1) {
3191 for (decc
= _xmlSchemaBase64Decode(*cur
);
3192 (decc
< 0) || (decc
> 63);
3193 decc
= _xmlSchemaBase64Decode(*cur
))
3195 /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
3196 /* 00111100 -> 0x3c */
3200 } else if (pad
== 2) {
3205 for (decc
= _xmlSchemaBase64Decode(*cur
);
3206 (decc
< 0) || (decc
> 63);
3207 decc
= _xmlSchemaBase64Decode(*cur
))
3209 /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
3210 /* 00110000 -> 0x30 */
3218 v
= xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY
);
3222 (xmlChar
*) xmlMallocAtomic((i
+ pad
+ 1) *
3225 xmlSchemaTypeErrMemory(node
, "allocating base64 data");
3229 v
->value
.base64
.str
= base
;
3230 for (cur
= value
; *cur
; ++cur
)
3231 if (_xmlSchemaBase64Decode(*cur
) >= 0) {
3236 v
->value
.base64
.total
= total
;
3241 case XML_SCHEMAS_INTEGER
:
3242 case XML_SCHEMAS_PINTEGER
:
3243 case XML_SCHEMAS_NPINTEGER
:
3244 case XML_SCHEMAS_NINTEGER
:
3245 case XML_SCHEMAS_NNINTEGER
:{
3246 const xmlChar
*cur
= value
;
3247 unsigned long lo
, mi
, hi
;
3253 while IS_WSP_BLANK_CH(*cur
) cur
++;
3257 } else if (*cur
== '+')
3259 ret
= xmlSchemaParseUInt(&cur
, &lo
, &mi
, &hi
);
3263 while IS_WSP_BLANK_CH(*cur
) cur
++;
3266 if (type
->builtInType
== XML_SCHEMAS_NPINTEGER
) {
3268 ((hi
!= 0) || (mi
!= 0) || (lo
!= 0)))
3270 } else if (type
->builtInType
== XML_SCHEMAS_PINTEGER
) {
3273 if ((hi
== 0) && (mi
== 0) && (lo
== 0))
3275 } else if (type
->builtInType
== XML_SCHEMAS_NINTEGER
) {
3278 if ((hi
== 0) && (mi
== 0) && (lo
== 0))
3280 } else if (type
->builtInType
== XML_SCHEMAS_NNINTEGER
) {
3282 ((hi
!= 0) || (mi
!= 0) || (lo
!= 0)))
3286 v
= xmlSchemaNewValue(type
->builtInType
);
3290 v
->value
.decimal
.lo
= lo
;
3291 v
->value
.decimal
.mi
= mi
;
3292 v
->value
.decimal
.hi
= hi
;
3293 v
->value
.decimal
.sign
= sign
;
3294 v
->value
.decimal
.frac
= 0;
3295 v
->value
.decimal
.total
= ret
;
3301 case XML_SCHEMAS_LONG
:
3302 case XML_SCHEMAS_BYTE
:
3303 case XML_SCHEMAS_SHORT
:
3304 case XML_SCHEMAS_INT
:{
3305 const xmlChar
*cur
= value
;
3306 unsigned long lo
, mi
, hi
;
3314 } else if (*cur
== '+')
3316 ret
= xmlSchemaParseUInt(&cur
, &lo
, &mi
, &hi
);
3321 if (type
->builtInType
== XML_SCHEMAS_LONG
) {
3325 if (mi
>= 33720368) {
3328 if ((sign
== 0) && (lo
> 54775807))
3330 if ((sign
== 1) && (lo
> 54775808))
3334 } else if (type
->builtInType
== XML_SCHEMAS_INT
) {
3340 if ((sign
== 0) && (lo
> 47483647))
3342 if ((sign
== 1) && (lo
> 47483648))
3345 } else if (type
->builtInType
== XML_SCHEMAS_SHORT
) {
3346 if ((mi
!= 0) || (hi
!= 0))
3348 if ((sign
== 1) && (lo
> 32768))
3350 if ((sign
== 0) && (lo
> 32767))
3352 } else if (type
->builtInType
== XML_SCHEMAS_BYTE
) {
3353 if ((mi
!= 0) || (hi
!= 0))
3355 if ((sign
== 1) && (lo
> 128))
3357 if ((sign
== 0) && (lo
> 127))
3361 v
= xmlSchemaNewValue(type
->builtInType
);
3363 v
->value
.decimal
.lo
= lo
;
3364 v
->value
.decimal
.mi
= mi
;
3365 v
->value
.decimal
.hi
= hi
;
3366 v
->value
.decimal
.sign
= sign
;
3367 v
->value
.decimal
.frac
= 0;
3368 v
->value
.decimal
.total
= ret
;
3374 case XML_SCHEMAS_UINT
:
3375 case XML_SCHEMAS_ULONG
:
3376 case XML_SCHEMAS_USHORT
:
3377 case XML_SCHEMAS_UBYTE
:{
3378 const xmlChar
*cur
= value
;
3379 unsigned long lo
, mi
, hi
;
3383 ret
= xmlSchemaParseUInt(&cur
, &lo
, &mi
, &hi
);
3388 if (type
->builtInType
== XML_SCHEMAS_ULONG
) {
3392 if (mi
>= 67440737) {
3399 } else if (type
->builtInType
== XML_SCHEMAS_UINT
) {
3408 } else if (type
->builtInType
== XML_SCHEMAS_USHORT
) {
3409 if ((mi
!= 0) || (hi
!= 0))
3413 } else if (type
->builtInType
== XML_SCHEMAS_UBYTE
) {
3414 if ((mi
!= 0) || (hi
!= 0))
3420 v
= xmlSchemaNewValue(type
->builtInType
);
3422 v
->value
.decimal
.lo
= lo
;
3423 v
->value
.decimal
.mi
= mi
;
3424 v
->value
.decimal
.hi
= hi
;
3425 v
->value
.decimal
.sign
= 0;
3426 v
->value
.decimal
.frac
= 0;
3427 v
->value
.decimal
.total
= ret
;
3458 * xmlSchemaValPredefTypeNode:
3459 * @type: the predefined type
3460 * @value: the value to check
3461 * @val: the return computed value
3462 * @node: the node containing the value
3464 * Check that a value conforms to the lexical space of the predefined type.
3465 * if true a value is computed and returned in @val.
3467 * Returns 0 if this validates, a positive error code number otherwise
3468 * and -1 in case of internal or API error.
3471 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type
, const xmlChar
*value
,
3472 xmlSchemaValPtr
*val
, xmlNodePtr node
) {
3473 return(xmlSchemaValAtomicType(type
, value
, val
, node
, 0,
3474 XML_SCHEMA_WHITESPACE_UNKNOWN
, 1, 1, 0));
3478 * xmlSchemaValPredefTypeNodeNoNorm:
3479 * @type: the predefined type
3480 * @value: the value to check
3481 * @val: the return computed value
3482 * @node: the node containing the value
3484 * Check that a value conforms to the lexical space of the predefined type.
3485 * if true a value is computed and returned in @val.
3486 * This one does apply any normalization to the value.
3488 * Returns 0 if this validates, a positive error code number otherwise
3489 * and -1 in case of internal or API error.
3492 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type
, const xmlChar
*value
,
3493 xmlSchemaValPtr
*val
, xmlNodePtr node
) {
3494 return(xmlSchemaValAtomicType(type
, value
, val
, node
, 1,
3495 XML_SCHEMA_WHITESPACE_UNKNOWN
, 1, 0, 1));
3499 * xmlSchemaValidatePredefinedType:
3500 * @type: the predefined type
3501 * @value: the value to check
3502 * @val: the return computed value
3504 * Check that a value conforms to the lexical space of the predefined type.
3505 * if true a value is computed and returned in @val.
3507 * Returns 0 if this validates, a positive error code number otherwise
3508 * and -1 in case of internal or API error.
3511 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type
, const xmlChar
*value
,
3512 xmlSchemaValPtr
*val
) {
3513 return(xmlSchemaValPredefTypeNode(type
, value
, val
, NULL
));
3517 * xmlSchemaCompareDecimals:
3518 * @x: a first decimal value
3519 * @y: a second decimal value
3521 * Compare 2 decimals
3523 * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
3526 xmlSchemaCompareDecimals(xmlSchemaValPtr x
, xmlSchemaValPtr y
)
3528 xmlSchemaValPtr swp
;
3529 int order
= 1, integx
, integy
, dlen
;
3530 unsigned long hi
, mi
, lo
;
3533 * First test: If x is -ve and not zero
3535 if ((x
->value
.decimal
.sign
) &&
3536 ((x
->value
.decimal
.lo
!= 0) ||
3537 (x
->value
.decimal
.mi
!= 0) ||
3538 (x
->value
.decimal
.hi
!= 0))) {
3540 * Then if y is -ve and not zero reverse the compare
3542 if ((y
->value
.decimal
.sign
) &&
3543 ((y
->value
.decimal
.lo
!= 0) ||
3544 (y
->value
.decimal
.mi
!= 0) ||
3545 (y
->value
.decimal
.hi
!= 0)))
3548 * Otherwise (y >= 0) we have the answer
3553 * If x is not -ve and y is -ve we have the answer
3555 } else if ((y
->value
.decimal
.sign
) &&
3556 ((y
->value
.decimal
.lo
!= 0) ||
3557 (y
->value
.decimal
.mi
!= 0) ||
3558 (y
->value
.decimal
.hi
!= 0))) {
3562 * If it's not simply determined by a difference in sign,
3563 * then we need to compare the actual values of the two nums.
3564 * To do this, we start by looking at the integral parts.
3565 * If the number of integral digits differ, then we have our
3568 integx
= x
->value
.decimal
.total
- x
->value
.decimal
.frac
;
3569 integy
= y
->value
.decimal
.total
- y
->value
.decimal
.frac
;
3571 * NOTE: We changed the "total" for values like "0.1"
3572 * (or "-0.1" or ".1") to be 1, which was 2 previously.
3573 * Therefore the special case, when such values are
3574 * compared with 0, needs to be handled separately;
3575 * otherwise a zero would be recognized incorrectly as
3576 * greater than those values. This has the nice side effect
3577 * that we gain an overall optimized comparison with zeroes.
3578 * Note that a "0" has a "total" of 1 already.
3581 if (x
->value
.decimal
.lo
== 0) {
3584 else if (y
->value
.decimal
.lo
!= 0)
3591 if (y
->value
.decimal
.lo
== 0) {
3594 else if (x
->value
.decimal
.lo
!= 0)
3601 if (integx
> integy
)
3603 else if (integy
> integx
)
3607 * If the number of integral digits is the same for both numbers,
3608 * then things get a little more complicated. We need to "normalize"
3609 * the numbers in order to properly compare them. To do this, we
3610 * look at the total length of each number (length => number of
3611 * significant digits), and divide the "shorter" by 10 (decreasing
3612 * the length) until they are of equal length.
3614 dlen
= x
->value
.decimal
.total
- y
->value
.decimal
.total
;
3615 if (dlen
< 0) { /* y has more digits than x */
3617 hi
= y
->value
.decimal
.hi
;
3618 mi
= y
->value
.decimal
.mi
;
3619 lo
= y
->value
.decimal
.lo
;
3622 } else { /* x has more digits than y */
3624 hi
= x
->value
.decimal
.hi
;
3625 mi
= x
->value
.decimal
.mi
;
3626 lo
= x
->value
.decimal
.lo
;
3628 while (dlen
> 8) { /* in effect, right shift by 10**8 */
3635 unsigned long rem1
, rem2
;
3636 rem1
= (hi
% 10) * 100000000L;
3638 rem2
= (mi
% 10) * 100000000L;
3639 mi
= (mi
+ rem1
) / 10;
3640 lo
= (lo
+ rem2
) / 10;
3643 if (hi
> swp
->value
.decimal
.hi
) {
3645 } else if (hi
== swp
->value
.decimal
.hi
) {
3646 if (mi
> swp
->value
.decimal
.mi
) {
3648 } else if (mi
== swp
->value
.decimal
.mi
) {
3649 if (lo
> swp
->value
.decimal
.lo
) {
3651 } else if (lo
== swp
->value
.decimal
.lo
) {
3652 if (x
->value
.decimal
.total
== y
->value
.decimal
.total
) {
3664 * xmlSchemaCompareDurations:
3665 * @x: a first duration value
3666 * @y: a second duration value
3668 * Compare 2 durations
3670 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3674 xmlSchemaCompareDurations(xmlSchemaValPtr x
, xmlSchemaValPtr y
)
3676 long carry
, mon
, day
;
3679 long xmon
, xday
, myear
, minday
, maxday
;
3680 static const long dayRange
[2][12] = {
3681 { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
3682 { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
3684 if ((x
== NULL
) || (y
== NULL
))
3688 mon
= x
->value
.dur
.mon
- y
->value
.dur
.mon
;
3691 sec
= x
->value
.dur
.sec
- y
->value
.dur
.sec
;
3692 carry
= (long)(sec
/ SECS_PER_DAY
);
3693 sec
-= ((double)carry
) * SECS_PER_DAY
;
3696 day
= x
->value
.dur
.day
- y
->value
.dur
.day
+ carry
;
3714 if ((day
>= 0) && (sec
>= 0.0))
3720 } else if ((day
<= 0) && (sec
<= 0.0)) {
3733 if (myear
> LONG_MAX
/ 366)
3735 /* FIXME: This doesn't take leap year exceptions every 100/400 years
3737 maxday
= 365 * myear
+ (myear
+ 3) / 4;
3738 /* FIXME: Needs to be calculated separately */
3739 minday
= maxday
- 1;
3743 minday
+= dayRange
[0][xmon
];
3744 maxday
+= dayRange
[1][xmon
];
3746 if ((maxday
== minday
) && (maxday
== xday
))
3747 return(0); /* can this really happen ? */
3758 * macros for adding date/times and durations
3760 #define FQUOTIENT(a,b) (floor(((double)a/(double)b)))
3761 #define MODULO(a,b) (a - FQUOTIENT(a,b) * b)
3762 #define FQUOTIENT_RANGE(a,low,high) (FQUOTIENT((a-low),(high-low)))
3763 #define MODULO_RANGE(a,low,high) ((MODULO((a-low),(high-low)))+low)
3767 * @v: the #xmlSchemaValPtr value to duplicate
3769 * Makes a copy of @v. The calling program is responsible for freeing
3770 * the returned value.
3772 * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error.
3774 static xmlSchemaValPtr
3775 xmlSchemaDupVal (xmlSchemaValPtr v
)
3777 xmlSchemaValPtr ret
= xmlSchemaNewValue(v
->type
);
3781 memcpy(ret
, v
, sizeof(xmlSchemaVal
));
3787 * xmlSchemaCopyValue:
3788 * @val: the precomputed value to be copied
3790 * Copies the precomputed value. This duplicates any string within.
3792 * Returns the copy or NULL if a copy for a data-type is not implemented.
3795 xmlSchemaCopyValue(xmlSchemaValPtr val
)
3797 xmlSchemaValPtr ret
= NULL
, prev
= NULL
, cur
;
3800 * Copy the string values.
3802 while (val
!= NULL
) {
3803 switch (val
->type
) {
3804 case XML_SCHEMAS_ANYTYPE
:
3805 case XML_SCHEMAS_IDREFS
:
3806 case XML_SCHEMAS_ENTITIES
:
3807 case XML_SCHEMAS_NMTOKENS
:
3808 xmlSchemaFreeValue(ret
);
3810 case XML_SCHEMAS_ANYSIMPLETYPE
:
3811 case XML_SCHEMAS_STRING
:
3812 case XML_SCHEMAS_NORMSTRING
:
3813 case XML_SCHEMAS_TOKEN
:
3814 case XML_SCHEMAS_LANGUAGE
:
3815 case XML_SCHEMAS_NAME
:
3816 case XML_SCHEMAS_NCNAME
:
3817 case XML_SCHEMAS_ID
:
3818 case XML_SCHEMAS_IDREF
:
3819 case XML_SCHEMAS_ENTITY
:
3820 case XML_SCHEMAS_NMTOKEN
:
3821 case XML_SCHEMAS_ANYURI
:
3822 cur
= xmlSchemaDupVal(val
);
3823 if (val
->value
.str
!= NULL
)
3824 cur
->value
.str
= xmlStrdup(BAD_CAST val
->value
.str
);
3826 case XML_SCHEMAS_QNAME
:
3827 case XML_SCHEMAS_NOTATION
:
3828 cur
= xmlSchemaDupVal(val
);
3829 if (val
->value
.qname
.name
!= NULL
)
3830 cur
->value
.qname
.name
=
3831 xmlStrdup(BAD_CAST val
->value
.qname
.name
);
3832 if (val
->value
.qname
.uri
!= NULL
)
3833 cur
->value
.qname
.uri
=
3834 xmlStrdup(BAD_CAST val
->value
.qname
.uri
);
3836 case XML_SCHEMAS_HEXBINARY
:
3837 cur
= xmlSchemaDupVal(val
);
3838 if (val
->value
.hex
.str
!= NULL
)
3839 cur
->value
.hex
.str
= xmlStrdup(BAD_CAST val
->value
.hex
.str
);
3841 case XML_SCHEMAS_BASE64BINARY
:
3842 cur
= xmlSchemaDupVal(val
);
3843 if (val
->value
.base64
.str
!= NULL
)
3844 cur
->value
.base64
.str
=
3845 xmlStrdup(BAD_CAST val
->value
.base64
.str
);
3848 cur
= xmlSchemaDupVal(val
);
3862 * _xmlSchemaDateAdd:
3863 * @dt: an #xmlSchemaValPtr
3864 * @dur: an #xmlSchemaValPtr of type #XS_DURATION
3866 * Compute a new date/time from @dt and @dur. This function assumes @dt
3867 * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
3868 * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as
3869 * @dt. The calling program is responsible for freeing the returned value.
3871 * Returns a pointer to a new #xmlSchemaVal or NULL if error.
3873 static xmlSchemaValPtr
3874 _xmlSchemaDateAdd (xmlSchemaValPtr dt
, xmlSchemaValPtr dur
)
3876 xmlSchemaValPtr ret
, tmp
;
3877 long carry
, tempdays
, temp
;
3878 xmlSchemaValDatePtr r
, d
;
3879 xmlSchemaValDurationPtr u
;
3881 if ((dt
== NULL
) || (dur
== NULL
))
3884 ret
= xmlSchemaNewValue(dt
->type
);
3888 /* make a copy so we don't alter the original value */
3889 tmp
= xmlSchemaDupVal(dt
);
3891 xmlSchemaFreeValue(ret
);
3895 r
= &(ret
->value
.date
);
3896 d
= &(tmp
->value
.date
);
3897 u
= &(dur
->value
.dur
);
3903 /* normalize for time zone offset */
3904 u
->sec
-= (d
->tzo
* 60);
3912 carry
= d
->mon
+ u
->mon
;
3913 r
->mon
= (unsigned int) MODULO_RANGE(carry
, 1, 13);
3914 carry
= (long) FQUOTIENT_RANGE(carry
, 1, 13);
3916 /* year (may be modified later) */
3917 r
->year
= d
->year
+ carry
;
3927 r
->tz_flag
= d
->tz_flag
;
3930 r
->sec
= d
->sec
+ u
->sec
;
3931 carry
= (long) FQUOTIENT((long)r
->sec
, 60);
3932 if (r
->sec
!= 0.0) {
3933 r
->sec
= MODULO(r
->sec
, 60.0);
3938 r
->min
= (unsigned int) MODULO(carry
, 60);
3939 carry
= (long) FQUOTIENT(carry
, 60);
3943 r
->hour
= (unsigned int) MODULO(carry
, 24);
3944 carry
= (long)FQUOTIENT(carry
, 24);
3948 * Note we use tempdays because the temporary values may need more
3951 if ((VALID_YEAR(r
->year
)) && (VALID_MONTH(r
->mon
)) &&
3952 (d
->day
> MAX_DAYINMONTH(r
->year
, r
->mon
)))
3953 tempdays
= MAX_DAYINMONTH(r
->year
, r
->mon
);
3954 else if (d
->day
< 1)
3959 tempdays
+= u
->day
+ carry
;
3963 long tmon
= (long) MODULO_RANGE((int)r
->mon
-1, 1, 13);
3964 long tyr
= r
->year
+ (long)FQUOTIENT_RANGE((int)r
->mon
-1, 1, 13);
3968 * Coverity detected an overrun in daysInMonth
3969 * of size 12 at position 12 with index variable "((r)->mon - 1)"
3975 tempdays
+= MAX_DAYINMONTH(tyr
, tmon
);
3977 } else if (VALID_YEAR(r
->year
) && VALID_MONTH(r
->mon
) &&
3978 tempdays
> (long) MAX_DAYINMONTH(r
->year
, r
->mon
)) {
3979 tempdays
= tempdays
- MAX_DAYINMONTH(r
->year
, r
->mon
);
3984 temp
= r
->mon
+ carry
;
3985 r
->mon
= (unsigned int) MODULO_RANGE(temp
, 1, 13);
3986 r
->year
= r
->year
+ (long) FQUOTIENT_RANGE(temp
, 1, 13);
3998 * adjust the date/time type to the date values
4000 if (ret
->type
!= XML_SCHEMAS_DATETIME
) {
4001 if ((r
->hour
) || (r
->min
) || (r
->sec
))
4002 ret
->type
= XML_SCHEMAS_DATETIME
;
4003 else if (ret
->type
!= XML_SCHEMAS_DATE
) {
4004 if ((r
->mon
!= 1) && (r
->day
!= 1))
4005 ret
->type
= XML_SCHEMAS_DATE
;
4006 else if ((ret
->type
!= XML_SCHEMAS_GYEARMONTH
) && (r
->mon
!= 1))
4007 ret
->type
= XML_SCHEMAS_GYEARMONTH
;
4011 xmlSchemaFreeValue(tmp
);
4017 * xmlSchemaDateNormalize:
4018 * @dt: an #xmlSchemaValPtr of a date/time type value.
4019 * @offset: number of seconds to adjust @dt by.
4021 * Normalize @dt to GMT time. The @offset parameter is subtracted from
4022 * the return value is a time-zone offset is present on @dt.
4024 * Returns a normalized copy of @dt or NULL if error.
4026 static xmlSchemaValPtr
4027 xmlSchemaDateNormalize (xmlSchemaValPtr dt
, double offset
)
4029 xmlSchemaValPtr dur
, ret
;
4034 if (((dt
->type
!= XML_SCHEMAS_TIME
) &&
4035 (dt
->type
!= XML_SCHEMAS_DATETIME
) &&
4036 (dt
->type
!= XML_SCHEMAS_DATE
)) || (dt
->value
.date
.tzo
== 0))
4037 return xmlSchemaDupVal(dt
);
4039 dur
= xmlSchemaNewValue(XML_SCHEMAS_DURATION
);
4043 dur
->value
.date
.sec
-= offset
;
4045 ret
= _xmlSchemaDateAdd(dt
, dur
);
4049 xmlSchemaFreeValue(dur
);
4051 /* ret->value.date.tzo = 0; */
4056 * _xmlSchemaDateCastYMToDays:
4057 * @dt: an #xmlSchemaValPtr
4059 * Convert mon and year of @dt to total number of days. Take the
4060 * number of years since (or before) 1 AD and add the number of leap
4061 * years. This is a function because negative
4062 * years must be handled a little differently and there is no zero year.
4064 * Returns number of days.
4067 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt
)
4072 mon
= dt
->value
.date
.mon
;
4073 if (mon
<= 0) mon
= 1; /* normalization */
4075 if (dt
->value
.date
.year
<= 0)
4076 ret
= (dt
->value
.date
.year
* 365) +
4077 (((dt
->value
.date
.year
+1)/4)-((dt
->value
.date
.year
+1)/100)+
4078 ((dt
->value
.date
.year
+1)/400)) +
4079 DAY_IN_YEAR(0, mon
, dt
->value
.date
.year
);
4081 ret
= ((dt
->value
.date
.year
-1) * 365) +
4082 (((dt
->value
.date
.year
-1)/4)-((dt
->value
.date
.year
-1)/100)+
4083 ((dt
->value
.date
.year
-1)/400)) +
4084 DAY_IN_YEAR(0, mon
, dt
->value
.date
.year
);
4091 * @dt: an #xmlSchemaValPtr
4093 * Calculates the number of seconds in the time portion of @dt.
4097 #define TIME_TO_NUMBER(dt) \
4098 ((double)((dt->value.date.hour * SECS_PER_HOUR) + \
4099 (dt->value.date.min * SECS_PER_MIN) + \
4100 (dt->value.date.tzo * SECS_PER_MIN)) + \
4104 * xmlSchemaCompareDates:
4105 * @x: a first date/time value
4106 * @y: a second date/time value
4108 * Compare 2 date/times
4110 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4114 xmlSchemaCompareDates (xmlSchemaValPtr x
, xmlSchemaValPtr y
)
4116 unsigned char xmask
, ymask
, xor_mask
, and_mask
;
4117 xmlSchemaValPtr p1
, p2
, q1
, q2
;
4118 long p1d
, p2d
, q1d
, q2d
;
4120 if ((x
== NULL
) || (y
== NULL
))
4123 if ((x
->value
.date
.year
> LONG_MAX
/ 366) ||
4124 (x
->value
.date
.year
< LONG_MIN
/ 366) ||
4125 (y
->value
.date
.year
> LONG_MAX
/ 366) ||
4126 (y
->value
.date
.year
< LONG_MIN
/ 366)) {
4127 /* Possible overflow when converting to days. */
4131 if (x
->value
.date
.tz_flag
) {
4133 if (!y
->value
.date
.tz_flag
) {
4134 p1
= xmlSchemaDateNormalize(x
, 0);
4135 p1d
= _xmlSchemaDateCastYMToDays(p1
) + p1
->value
.date
.day
;
4136 /* normalize y + 14:00 */
4137 q1
= xmlSchemaDateNormalize(y
, (14 * SECS_PER_HOUR
));
4139 q1d
= _xmlSchemaDateCastYMToDays(q1
) + q1
->value
.date
.day
;
4141 xmlSchemaFreeValue(p1
);
4142 xmlSchemaFreeValue(q1
);
4144 } else if (p1d
== q1d
) {
4147 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q1
);
4149 xmlSchemaFreeValue(p1
);
4150 xmlSchemaFreeValue(q1
);
4154 /* normalize y - 14:00 */
4155 q2
= xmlSchemaDateNormalize(y
, -(14 * SECS_PER_HOUR
));
4156 q2d
= _xmlSchemaDateCastYMToDays(q2
) + q2
->value
.date
.day
;
4159 else if (p1d
== q2d
) {
4160 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q2
);
4164 ret
= 2; /* indeterminate */
4166 xmlSchemaFreeValue(p1
);
4167 xmlSchemaFreeValue(q1
);
4168 xmlSchemaFreeValue(q2
);
4173 xmlSchemaFreeValue(p1
);
4174 xmlSchemaFreeValue(q1
);
4177 } else if (y
->value
.date
.tz_flag
) {
4178 q1
= xmlSchemaDateNormalize(y
, 0);
4179 q1d
= _xmlSchemaDateCastYMToDays(q1
) + q1
->value
.date
.day
;
4181 /* normalize x - 14:00 */
4182 p1
= xmlSchemaDateNormalize(x
, -(14 * SECS_PER_HOUR
));
4183 p1d
= _xmlSchemaDateCastYMToDays(p1
) + p1
->value
.date
.day
;
4186 xmlSchemaFreeValue(p1
);
4187 xmlSchemaFreeValue(q1
);
4189 } else if (p1d
== q1d
) {
4192 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q1
);
4194 xmlSchemaFreeValue(p1
);
4195 xmlSchemaFreeValue(q1
);
4199 /* normalize x + 14:00 */
4200 p2
= xmlSchemaDateNormalize(x
, (14 * SECS_PER_HOUR
));
4201 p2d
= _xmlSchemaDateCastYMToDays(p2
) + p2
->value
.date
.day
;
4205 } else if (p2d
== q1d
) {
4206 sec
= TIME_TO_NUMBER(p2
) - TIME_TO_NUMBER(q1
);
4210 ret
= 2; /* indeterminate */
4212 xmlSchemaFreeValue(p1
);
4213 xmlSchemaFreeValue(q1
);
4214 xmlSchemaFreeValue(p2
);
4219 xmlSchemaFreeValue(p1
);
4220 xmlSchemaFreeValue(q1
);
4225 * if the same type then calculate the difference
4227 if (x
->type
== y
->type
) {
4229 q1
= xmlSchemaDateNormalize(y
, 0);
4230 q1d
= _xmlSchemaDateCastYMToDays(q1
) + q1
->value
.date
.day
;
4232 p1
= xmlSchemaDateNormalize(x
, 0);
4233 p1d
= _xmlSchemaDateCastYMToDays(p1
) + p1
->value
.date
.day
;
4237 } else if (p1d
> q1d
) {
4242 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q1
);
4249 xmlSchemaFreeValue(p1
);
4250 xmlSchemaFreeValue(q1
);
4255 case XML_SCHEMAS_DATETIME
:
4258 case XML_SCHEMAS_DATE
:
4261 case XML_SCHEMAS_GYEAR
:
4264 case XML_SCHEMAS_GMONTH
:
4267 case XML_SCHEMAS_GDAY
:
4270 case XML_SCHEMAS_GYEARMONTH
:
4273 case XML_SCHEMAS_GMONTHDAY
:
4276 case XML_SCHEMAS_TIME
:
4285 case XML_SCHEMAS_DATETIME
:
4288 case XML_SCHEMAS_DATE
:
4291 case XML_SCHEMAS_GYEAR
:
4294 case XML_SCHEMAS_GMONTH
:
4297 case XML_SCHEMAS_GDAY
:
4300 case XML_SCHEMAS_GYEARMONTH
:
4303 case XML_SCHEMAS_GMONTHDAY
:
4306 case XML_SCHEMAS_TIME
:
4314 xor_mask
= xmask
^ ymask
; /* mark type differences */
4315 and_mask
= xmask
& ymask
; /* mark field specification */
4319 return 2; /* indeterminate */
4320 else if (and_mask
& 1) {
4321 if (x
->value
.date
.year
< y
->value
.date
.year
)
4323 else if (x
->value
.date
.year
> y
->value
.date
.year
)
4329 return 2; /* indeterminate */
4330 else if (and_mask
& 2) {
4331 if (x
->value
.date
.mon
< y
->value
.date
.mon
)
4333 else if (x
->value
.date
.mon
> y
->value
.date
.mon
)
4339 return 2; /* indeterminate */
4340 else if (and_mask
& 4) {
4341 if (x
->value
.date
.day
< y
->value
.date
.day
)
4343 else if (x
->value
.date
.day
> y
->value
.date
.day
)
4349 return 2; /* indeterminate */
4350 else if (and_mask
& 8) {
4351 if (x
->value
.date
.hour
< y
->value
.date
.hour
)
4353 else if (x
->value
.date
.hour
> y
->value
.date
.hour
)
4355 else if (x
->value
.date
.min
< y
->value
.date
.min
)
4357 else if (x
->value
.date
.min
> y
->value
.date
.min
)
4359 else if (x
->value
.date
.sec
< y
->value
.date
.sec
)
4361 else if (x
->value
.date
.sec
> y
->value
.date
.sec
)
4369 * xmlSchemaComparePreserveReplaceStrings:
4370 * @x: a first string value
4371 * @y: a second string value
4372 * @invert: inverts the result if x < y or x > y.
4374 * Compare 2 string for their normalized values.
4375 * @x is a string with whitespace of "preserve", @y is
4376 * a string with a whitespace of "replace". I.e. @x could
4377 * be an "xsd:string" and @y an "xsd:normalizedString".
4379 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4383 xmlSchemaComparePreserveReplaceStrings(const xmlChar
*x
,
4389 while ((*x
!= 0) && (*y
!= 0)) {
4390 if (IS_WSP_REPLACE_CH(*y
)) {
4391 if (! IS_WSP_SPACE_CH(*x
)) {
4392 if ((*x
- 0x20) < 0) {
4438 * xmlSchemaComparePreserveCollapseStrings:
4439 * @x: a first string value
4440 * @y: a second string value
4442 * Compare 2 string for their normalized values.
4443 * @x is a string with whitespace of "preserve", @y is
4444 * a string with a whitespace of "collapse". I.e. @x could
4445 * be an "xsd:string" and @y an "xsd:normalizedString".
4447 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4451 xmlSchemaComparePreserveCollapseStrings(const xmlChar
*x
,
4458 * Skip leading blank chars of the collapsed string.
4460 while IS_WSP_BLANK_CH(*y
)
4463 while ((*x
!= 0) && (*y
!= 0)) {
4464 if IS_WSP_BLANK_CH(*y
) {
4465 if (! IS_WSP_SPACE_CH(*x
)) {
4467 * The yv character would have been replaced to 0x20.
4469 if ((*x
- 0x20) < 0) {
4484 * Skip contiguous blank chars of the collapsed string.
4486 while IS_WSP_BLANK_CH(*y
)
4512 * Skip trailing blank chars of the collapsed string.
4514 while IS_WSP_BLANK_CH(*y
)
4527 * xmlSchemaComparePreserveCollapseStrings:
4528 * @x: a first string value
4529 * @y: a second string value
4531 * Compare 2 string for their normalized values.
4532 * @x is a string with whitespace of "preserve", @y is
4533 * a string with a whitespace of "collapse". I.e. @x could
4534 * be an "xsd:string" and @y an "xsd:normalizedString".
4536 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4540 xmlSchemaCompareReplaceCollapseStrings(const xmlChar
*x
,
4547 * Skip leading blank chars of the collapsed string.
4549 while IS_WSP_BLANK_CH(*y
)
4552 while ((*x
!= 0) && (*y
!= 0)) {
4553 if IS_WSP_BLANK_CH(*y
) {
4554 if (! IS_WSP_BLANK_CH(*x
)) {
4556 * The yv character would have been replaced to 0x20.
4558 if ((*x
- 0x20) < 0) {
4573 * Skip contiguous blank chars of the collapsed string.
4575 while IS_WSP_BLANK_CH(*y
)
4578 if IS_WSP_BLANK_CH(*x
) {
4580 * The xv character would have been replaced to 0x20.
4582 if ((0x20 - *y
) < 0) {
4609 * Skip trailing blank chars of the collapsed string.
4611 while IS_WSP_BLANK_CH(*y
)
4625 * xmlSchemaCompareReplacedStrings:
4626 * @x: a first string value
4627 * @y: a second string value
4629 * Compare 2 string for their normalized values.
4631 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4635 xmlSchemaCompareReplacedStrings(const xmlChar
*x
,
4640 while ((*x
!= 0) && (*y
!= 0)) {
4641 if IS_WSP_BLANK_CH(*y
) {
4642 if (! IS_WSP_BLANK_CH(*x
)) {
4643 if ((*x
- 0x20) < 0)
4649 if IS_WSP_BLANK_CH(*x
) {
4650 if ((0x20 - *y
) < 0)
4672 * xmlSchemaCompareNormStrings:
4673 * @x: a first string value
4674 * @y: a second string value
4676 * Compare 2 string for their normalized values.
4678 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4682 xmlSchemaCompareNormStrings(const xmlChar
*x
,
4686 while (IS_BLANK_CH(*x
)) x
++;
4687 while (IS_BLANK_CH(*y
)) y
++;
4688 while ((*x
!= 0) && (*y
!= 0)) {
4689 if (IS_BLANK_CH(*x
)) {
4690 if (!IS_BLANK_CH(*y
)) {
4694 while (IS_BLANK_CH(*x
)) x
++;
4695 while (IS_BLANK_CH(*y
)) y
++;
4705 while (IS_BLANK_CH(*x
)) x
++;
4710 while (IS_BLANK_CH(*y
)) y
++;
4718 * xmlSchemaCompareFloats:
4719 * @x: a first float or double value
4720 * @y: a second float or double value
4724 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4728 xmlSchemaCompareFloats(xmlSchemaValPtr x
, xmlSchemaValPtr y
) {
4731 if ((x
== NULL
) || (y
== NULL
))
4735 * Cast everything to doubles.
4737 if (x
->type
== XML_SCHEMAS_DOUBLE
)
4739 else if (x
->type
== XML_SCHEMAS_FLOAT
)
4744 if (y
->type
== XML_SCHEMAS_DOUBLE
)
4746 else if (y
->type
== XML_SCHEMAS_FLOAT
)
4752 * Check for special cases.
4754 if (xmlXPathIsNaN(d1
)) {
4755 if (xmlXPathIsNaN(d2
))
4759 if (xmlXPathIsNaN(d2
))
4761 if (d1
== xmlXPathPINF
) {
4762 if (d2
== xmlXPathPINF
)
4766 if (d2
== xmlXPathPINF
)
4768 if (d1
== xmlXPathNINF
) {
4769 if (d2
== xmlXPathNINF
)
4773 if (d2
== xmlXPathNINF
)
4777 * basic tests, the last one we should have equality, but
4778 * portability is more important than speed and handling
4779 * NaN or Inf in a portable way is always a challenge, so ...
4791 * xmlSchemaCompareValues:
4793 * @xvalue: the first value as a string (optional)
4794 * @xwtsp: the whitespace type
4795 * @y: a second value
4796 * @xvalue: the second value as a string (optional)
4797 * @ywtsp: the whitespace type
4801 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not
4802 * comparable and -2 in case of error
4805 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype
,
4807 const xmlChar
*xvalue
,
4808 xmlSchemaWhitespaceValueType xws
,
4809 xmlSchemaValType ytype
,
4811 const xmlChar
*yvalue
,
4812 xmlSchemaWhitespaceValueType yws
)
4815 case XML_SCHEMAS_UNKNOWN
:
4816 case XML_SCHEMAS_ANYTYPE
:
4818 case XML_SCHEMAS_INTEGER
:
4819 case XML_SCHEMAS_NPINTEGER
:
4820 case XML_SCHEMAS_NINTEGER
:
4821 case XML_SCHEMAS_NNINTEGER
:
4822 case XML_SCHEMAS_PINTEGER
:
4823 case XML_SCHEMAS_INT
:
4824 case XML_SCHEMAS_UINT
:
4825 case XML_SCHEMAS_LONG
:
4826 case XML_SCHEMAS_ULONG
:
4827 case XML_SCHEMAS_SHORT
:
4828 case XML_SCHEMAS_USHORT
:
4829 case XML_SCHEMAS_BYTE
:
4830 case XML_SCHEMAS_UBYTE
:
4831 case XML_SCHEMAS_DECIMAL
:
4832 if ((x
== NULL
) || (y
== NULL
))
4835 return(xmlSchemaCompareDecimals(x
, y
));
4836 if ((ytype
== XML_SCHEMAS_DECIMAL
) ||
4837 (ytype
== XML_SCHEMAS_INTEGER
) ||
4838 (ytype
== XML_SCHEMAS_NPINTEGER
) ||
4839 (ytype
== XML_SCHEMAS_NINTEGER
) ||
4840 (ytype
== XML_SCHEMAS_NNINTEGER
) ||
4841 (ytype
== XML_SCHEMAS_PINTEGER
) ||
4842 (ytype
== XML_SCHEMAS_INT
) ||
4843 (ytype
== XML_SCHEMAS_UINT
) ||
4844 (ytype
== XML_SCHEMAS_LONG
) ||
4845 (ytype
== XML_SCHEMAS_ULONG
) ||
4846 (ytype
== XML_SCHEMAS_SHORT
) ||
4847 (ytype
== XML_SCHEMAS_USHORT
) ||
4848 (ytype
== XML_SCHEMAS_BYTE
) ||
4849 (ytype
== XML_SCHEMAS_UBYTE
))
4850 return(xmlSchemaCompareDecimals(x
, y
));
4852 case XML_SCHEMAS_DURATION
:
4853 if ((x
== NULL
) || (y
== NULL
))
4855 if (ytype
== XML_SCHEMAS_DURATION
)
4856 return(xmlSchemaCompareDurations(x
, y
));
4858 case XML_SCHEMAS_TIME
:
4859 case XML_SCHEMAS_GDAY
:
4860 case XML_SCHEMAS_GMONTH
:
4861 case XML_SCHEMAS_GMONTHDAY
:
4862 case XML_SCHEMAS_GYEAR
:
4863 case XML_SCHEMAS_GYEARMONTH
:
4864 case XML_SCHEMAS_DATE
:
4865 case XML_SCHEMAS_DATETIME
:
4866 if ((x
== NULL
) || (y
== NULL
))
4868 if ((ytype
== XML_SCHEMAS_DATETIME
) ||
4869 (ytype
== XML_SCHEMAS_TIME
) ||
4870 (ytype
== XML_SCHEMAS_GDAY
) ||
4871 (ytype
== XML_SCHEMAS_GMONTH
) ||
4872 (ytype
== XML_SCHEMAS_GMONTHDAY
) ||
4873 (ytype
== XML_SCHEMAS_GYEAR
) ||
4874 (ytype
== XML_SCHEMAS_DATE
) ||
4875 (ytype
== XML_SCHEMAS_GYEARMONTH
))
4876 return (xmlSchemaCompareDates(x
, y
));
4879 * Note that we will support comparison of string types against
4880 * anySimpleType as well.
4882 case XML_SCHEMAS_ANYSIMPLETYPE
:
4883 case XML_SCHEMAS_STRING
:
4884 case XML_SCHEMAS_NORMSTRING
:
4885 case XML_SCHEMAS_TOKEN
:
4886 case XML_SCHEMAS_LANGUAGE
:
4887 case XML_SCHEMAS_NMTOKEN
:
4888 case XML_SCHEMAS_NAME
:
4889 case XML_SCHEMAS_NCNAME
:
4890 case XML_SCHEMAS_ID
:
4891 case XML_SCHEMAS_IDREF
:
4892 case XML_SCHEMAS_ENTITY
:
4893 case XML_SCHEMAS_ANYURI
:
4895 const xmlChar
*xv
, *yv
;
4906 * TODO: Compare those against QName.
4908 if (ytype
== XML_SCHEMAS_QNAME
) {
4914 if ((ytype
== XML_SCHEMAS_ANYSIMPLETYPE
) ||
4915 (ytype
== XML_SCHEMAS_STRING
) ||
4916 (ytype
== XML_SCHEMAS_NORMSTRING
) ||
4917 (ytype
== XML_SCHEMAS_TOKEN
) ||
4918 (ytype
== XML_SCHEMAS_LANGUAGE
) ||
4919 (ytype
== XML_SCHEMAS_NMTOKEN
) ||
4920 (ytype
== XML_SCHEMAS_NAME
) ||
4921 (ytype
== XML_SCHEMAS_NCNAME
) ||
4922 (ytype
== XML_SCHEMAS_ID
) ||
4923 (ytype
== XML_SCHEMAS_IDREF
) ||
4924 (ytype
== XML_SCHEMAS_ENTITY
) ||
4925 (ytype
== XML_SCHEMAS_ANYURI
)) {
4927 if (xws
== XML_SCHEMA_WHITESPACE_PRESERVE
) {
4929 if (yws
== XML_SCHEMA_WHITESPACE_PRESERVE
) {
4930 /* TODO: What about x < y or x > y. */
4931 if (xmlStrEqual(xv
, yv
))
4935 } else if (yws
== XML_SCHEMA_WHITESPACE_REPLACE
)
4936 return (xmlSchemaComparePreserveReplaceStrings(xv
, yv
, 0));
4937 else if (yws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
4938 return (xmlSchemaComparePreserveCollapseStrings(xv
, yv
, 0));
4940 } else if (xws
== XML_SCHEMA_WHITESPACE_REPLACE
) {
4942 if (yws
== XML_SCHEMA_WHITESPACE_PRESERVE
)
4943 return (xmlSchemaComparePreserveReplaceStrings(yv
, xv
, 1));
4944 if (yws
== XML_SCHEMA_WHITESPACE_REPLACE
)
4945 return (xmlSchemaCompareReplacedStrings(xv
, yv
));
4946 if (yws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
4947 return (xmlSchemaCompareReplaceCollapseStrings(xv
, yv
, 0));
4949 } else if (xws
== XML_SCHEMA_WHITESPACE_COLLAPSE
) {
4951 if (yws
== XML_SCHEMA_WHITESPACE_PRESERVE
)
4952 return (xmlSchemaComparePreserveCollapseStrings(yv
, xv
, 1));
4953 if (yws
== XML_SCHEMA_WHITESPACE_REPLACE
)
4954 return (xmlSchemaCompareReplaceCollapseStrings(yv
, xv
, 1));
4955 if (yws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
4956 return (xmlSchemaCompareNormStrings(xv
, yv
));
4963 case XML_SCHEMAS_QNAME
:
4964 case XML_SCHEMAS_NOTATION
:
4965 if ((x
== NULL
) || (y
== NULL
))
4967 if ((ytype
== XML_SCHEMAS_QNAME
) ||
4968 (ytype
== XML_SCHEMAS_NOTATION
)) {
4969 if ((xmlStrEqual(x
->value
.qname
.name
, y
->value
.qname
.name
)) &&
4970 (xmlStrEqual(x
->value
.qname
.uri
, y
->value
.qname
.uri
)))
4975 case XML_SCHEMAS_FLOAT
:
4976 case XML_SCHEMAS_DOUBLE
:
4977 if ((x
== NULL
) || (y
== NULL
))
4979 if ((ytype
== XML_SCHEMAS_FLOAT
) ||
4980 (ytype
== XML_SCHEMAS_DOUBLE
))
4981 return (xmlSchemaCompareFloats(x
, y
));
4983 case XML_SCHEMAS_BOOLEAN
:
4984 if ((x
== NULL
) || (y
== NULL
))
4986 if (ytype
== XML_SCHEMAS_BOOLEAN
) {
4987 if (x
->value
.b
== y
->value
.b
)
4989 if (x
->value
.b
== 0)
4994 case XML_SCHEMAS_HEXBINARY
:
4995 if ((x
== NULL
) || (y
== NULL
))
4997 if (ytype
== XML_SCHEMAS_HEXBINARY
) {
4998 if (x
->value
.hex
.total
== y
->value
.hex
.total
) {
4999 int ret
= xmlStrcmp(x
->value
.hex
.str
, y
->value
.hex
.str
);
5005 else if (x
->value
.hex
.total
> y
->value
.hex
.total
)
5011 case XML_SCHEMAS_BASE64BINARY
:
5012 if ((x
== NULL
) || (y
== NULL
))
5014 if (ytype
== XML_SCHEMAS_BASE64BINARY
) {
5015 if (x
->value
.base64
.total
== y
->value
.base64
.total
) {
5016 int ret
= xmlStrcmp(x
->value
.base64
.str
,
5017 y
->value
.base64
.str
);
5025 else if (x
->value
.base64
.total
> y
->value
.base64
.total
)
5031 case XML_SCHEMAS_IDREFS
:
5032 case XML_SCHEMAS_ENTITIES
:
5033 case XML_SCHEMAS_NMTOKENS
:
5041 * xmlSchemaCompareValues:
5043 * @y: a second value
5047 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5051 xmlSchemaCompareValues(xmlSchemaValPtr x
, xmlSchemaValPtr y
) {
5052 xmlSchemaWhitespaceValueType xws
, yws
;
5054 if ((x
== NULL
) || (y
== NULL
))
5056 if (x
->type
== XML_SCHEMAS_STRING
)
5057 xws
= XML_SCHEMA_WHITESPACE_PRESERVE
;
5058 else if (x
->type
== XML_SCHEMAS_NORMSTRING
)
5059 xws
= XML_SCHEMA_WHITESPACE_REPLACE
;
5061 xws
= XML_SCHEMA_WHITESPACE_COLLAPSE
;
5063 if (y
->type
== XML_SCHEMAS_STRING
)
5064 yws
= XML_SCHEMA_WHITESPACE_PRESERVE
;
5065 else if (y
->type
== XML_SCHEMAS_NORMSTRING
)
5066 yws
= XML_SCHEMA_WHITESPACE_REPLACE
;
5068 yws
= XML_SCHEMA_WHITESPACE_COLLAPSE
;
5070 return(xmlSchemaCompareValuesInternal(x
->type
, x
, NULL
, xws
, y
->type
,
5075 * xmlSchemaCompareValuesWhtsp:
5077 * @xws: the whitespace value of x
5078 * @y: a second value
5079 * @yws: the whitespace value of y
5083 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5087 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x
,
5088 xmlSchemaWhitespaceValueType xws
,
5090 xmlSchemaWhitespaceValueType yws
)
5092 if ((x
== NULL
) || (y
== NULL
))
5094 return(xmlSchemaCompareValuesInternal(x
->type
, x
, NULL
, xws
, y
->type
,
5099 * xmlSchemaCompareValuesWhtspExt:
5101 * @xws: the whitespace value of x
5102 * @y: a second value
5103 * @yws: the whitespace value of y
5107 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5111 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype
,
5113 const xmlChar
*xvalue
,
5114 xmlSchemaWhitespaceValueType xws
,
5115 xmlSchemaValType ytype
,
5117 const xmlChar
*yvalue
,
5118 xmlSchemaWhitespaceValueType yws
)
5120 return(xmlSchemaCompareValuesInternal(xtype
, x
, xvalue
, xws
, ytype
, y
,
5128 * Computes the UTF8 length of the normalized value of the string
5130 * Returns the length or -1 in case of error.
5133 xmlSchemaNormLen(const xmlChar
*value
) {
5140 while (IS_BLANK_CH(*utf
)) utf
++;
5142 if (utf
[0] & 0x80) {
5143 if ((utf
[1] & 0xc0) != 0x80)
5145 if ((utf
[0] & 0xe0) == 0xe0) {
5146 if ((utf
[2] & 0xc0) != 0x80)
5148 if ((utf
[0] & 0xf0) == 0xf0) {
5149 if ((utf
[0] & 0xf8) != 0xf0 || (utf
[3] & 0xc0) != 0x80)
5158 } else if (IS_BLANK_CH(*utf
)) {
5159 while (IS_BLANK_CH(*utf
)) utf
++;
5171 * xmlSchemaGetFacetValueAsULong:
5172 * @facet: an schemas type facet
5174 * Extract the value of a facet
5176 * Returns the value as a long
5179 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet
)
5182 * TODO: Check if this is a decimal.
5184 if (facet
== NULL
|| facet
->val
== NULL
)
5186 return ((unsigned long) facet
->val
->value
.decimal
.lo
);
5190 * xmlSchemaValidateListSimpleTypeFacet:
5191 * @facet: the facet to check
5192 * @value: the lexical repr of the value to validate
5193 * @actualLen: the number of list items
5194 * @expectedLen: the resulting expected number of list items
5196 * Checks the value of a list simple type against a facet.
5198 * Returns 0 if the value is valid, a positive error code
5199 * number otherwise and -1 in case of an internal error.
5202 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet
,
5203 const xmlChar
*value
,
5204 unsigned long actualLen
,
5205 unsigned long *expectedLen
)
5210 * TODO: Check if this will work with large numbers.
5211 * (compare value.decimal.mi and value.decimal.hi as well?).
5213 if (facet
->type
== XML_SCHEMA_FACET_LENGTH
) {
5214 if (actualLen
!= facet
->val
->value
.decimal
.lo
) {
5215 if (expectedLen
!= NULL
)
5216 *expectedLen
= facet
->val
->value
.decimal
.lo
;
5217 return (XML_SCHEMAV_CVC_LENGTH_VALID
);
5219 } else if (facet
->type
== XML_SCHEMA_FACET_MINLENGTH
) {
5220 if (actualLen
< facet
->val
->value
.decimal
.lo
) {
5221 if (expectedLen
!= NULL
)
5222 *expectedLen
= facet
->val
->value
.decimal
.lo
;
5223 return (XML_SCHEMAV_CVC_MINLENGTH_VALID
);
5225 } else if (facet
->type
== XML_SCHEMA_FACET_MAXLENGTH
) {
5226 if (actualLen
> facet
->val
->value
.decimal
.lo
) {
5227 if (expectedLen
!= NULL
)
5228 *expectedLen
= facet
->val
->value
.decimal
.lo
;
5229 return (XML_SCHEMAV_CVC_MAXLENGTH_VALID
);
5233 * NOTE: That we can pass NULL as xmlSchemaValPtr to
5234 * xmlSchemaValidateFacet, since the remaining facet types
5235 * are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
5237 return(xmlSchemaValidateFacet(NULL
, facet
, value
, NULL
));
5242 * xmlSchemaValidateLengthFacet:
5243 * @type: the built-in type
5244 * @facet: the facet to check
5245 * @value: the lexical repr. of the value to be validated
5246 * @val: the precomputed value
5247 * @ws: the whitespace type of the value
5248 * @length: the actual length of the value
5250 * Checka a value against a "length", "minLength" and "maxLength"
5251 * facet; sets @length to the computed length of @value.
5253 * Returns 0 if the value is valid, a positive error code
5254 * otherwise and -1 in case of an internal or API error.
5257 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet
,
5258 xmlSchemaValType valType
,
5259 const xmlChar
*value
,
5260 xmlSchemaValPtr val
,
5261 unsigned long *length
,
5262 xmlSchemaWhitespaceValueType ws
)
5264 unsigned int len
= 0;
5266 if ((length
== NULL
) || (facet
== NULL
))
5269 if ((facet
->type
!= XML_SCHEMA_FACET_LENGTH
) &&
5270 (facet
->type
!= XML_SCHEMA_FACET_MAXLENGTH
) &&
5271 (facet
->type
!= XML_SCHEMA_FACET_MINLENGTH
))
5275 * TODO: length, maxLength and minLength must be of type
5276 * nonNegativeInteger only. Check if decimal is used somehow.
5278 if ((facet
->val
== NULL
) ||
5279 ((facet
->val
->type
!= XML_SCHEMAS_DECIMAL
) &&
5280 (facet
->val
->type
!= XML_SCHEMAS_NNINTEGER
)) ||
5281 (facet
->val
->value
.decimal
.frac
!= 0)) {
5284 if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_HEXBINARY
))
5285 len
= val
->value
.hex
.total
;
5286 else if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_BASE64BINARY
))
5287 len
= val
->value
.base64
.total
;
5290 case XML_SCHEMAS_STRING
:
5291 case XML_SCHEMAS_NORMSTRING
:
5292 if (ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) {
5294 * This is to ensure API compatibility with the old
5295 * xmlSchemaValidateLengthFacet(). Anyway, this was and
5296 * is not the correct handling.
5297 * TODO: Get rid of this case somehow.
5299 if (valType
== XML_SCHEMAS_STRING
)
5300 len
= xmlUTF8Strlen(value
);
5302 len
= xmlSchemaNormLen(value
);
5303 } else if (value
!= NULL
) {
5304 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
5305 len
= xmlSchemaNormLen(value
);
5308 * Should be OK for "preserve" as well.
5310 len
= xmlUTF8Strlen(value
);
5313 case XML_SCHEMAS_IDREF
:
5314 case XML_SCHEMAS_TOKEN
:
5315 case XML_SCHEMAS_LANGUAGE
:
5316 case XML_SCHEMAS_NMTOKEN
:
5317 case XML_SCHEMAS_NAME
:
5318 case XML_SCHEMAS_NCNAME
:
5319 case XML_SCHEMAS_ID
:
5321 * FIXME: What exactly to do with anyURI?
5323 case XML_SCHEMAS_ANYURI
:
5325 len
= xmlSchemaNormLen(value
);
5327 case XML_SCHEMAS_QNAME
:
5328 case XML_SCHEMAS_NOTATION
:
5330 * For QName and NOTATION, those facets are
5331 * deprecated and should be ignored.
5338 *length
= (unsigned long) len
;
5340 * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
5342 if (facet
->type
== XML_SCHEMA_FACET_LENGTH
) {
5343 if (len
!= facet
->val
->value
.decimal
.lo
)
5344 return(XML_SCHEMAV_CVC_LENGTH_VALID
);
5345 } else if (facet
->type
== XML_SCHEMA_FACET_MINLENGTH
) {
5346 if (len
< facet
->val
->value
.decimal
.lo
)
5347 return(XML_SCHEMAV_CVC_MINLENGTH_VALID
);
5349 if (len
> facet
->val
->value
.decimal
.lo
)
5350 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID
);
5357 * xmlSchemaValidateLengthFacet:
5358 * @type: the built-in type
5359 * @facet: the facet to check
5360 * @value: the lexical repr. of the value to be validated
5361 * @val: the precomputed value
5362 * @length: the actual length of the value
5364 * Checka a value against a "length", "minLength" and "maxLength"
5365 * facet; sets @length to the computed length of @value.
5367 * Returns 0 if the value is valid, a positive error code
5368 * otherwise and -1 in case of an internal or API error.
5371 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type
,
5372 xmlSchemaFacetPtr facet
,
5373 const xmlChar
*value
,
5374 xmlSchemaValPtr val
,
5375 unsigned long *length
)
5379 return (xmlSchemaValidateLengthFacetInternal(facet
,
5380 type
->builtInType
, value
, val
, length
,
5381 XML_SCHEMA_WHITESPACE_UNKNOWN
));
5385 * xmlSchemaValidateLengthFacetWhtsp:
5386 * @facet: the facet to check
5387 * @valType: the built-in type
5388 * @value: the lexical repr. of the value to be validated
5389 * @val: the precomputed value
5390 * @ws: the whitespace type of the value
5391 * @length: the actual length of the value
5393 * Checka a value against a "length", "minLength" and "maxLength"
5394 * facet; sets @length to the computed length of @value.
5396 * Returns 0 if the value is valid, a positive error code
5397 * otherwise and -1 in case of an internal or API error.
5400 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet
,
5401 xmlSchemaValType valType
,
5402 const xmlChar
*value
,
5403 xmlSchemaValPtr val
,
5404 unsigned long *length
,
5405 xmlSchemaWhitespaceValueType ws
)
5407 return (xmlSchemaValidateLengthFacetInternal(facet
, valType
, value
, val
,
5412 * xmlSchemaValidateFacetInternal:
5413 * @facet: the facet to check
5414 * @fws: the whitespace type of the facet's value
5415 * @valType: the built-in type of the value
5416 * @value: the lexical repr of the value to validate
5417 * @val: the precomputed value
5418 * @ws: the whitespace type of the value
5420 * Check a value against a facet condition
5422 * Returns 0 if the element is schemas valid, a positive error code
5423 * number otherwise and -1 in case of internal or API error.
5426 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet
,
5427 xmlSchemaWhitespaceValueType fws
,
5428 xmlSchemaValType valType
,
5429 const xmlChar
*value
,
5430 xmlSchemaValPtr val
,
5431 xmlSchemaWhitespaceValueType ws
)
5439 switch (facet
->type
) {
5440 case XML_SCHEMA_FACET_PATTERN
:
5442 * NOTE that for patterns, the @value needs to be the normalized
5443 * value, *not* the lexical initial value or the canonical value.
5448 * If string-derived type, regexp must be tested on the value space of
5450 * See https://www.w3.org/TR/xmlschema-2/#rf-pattern
5452 stringType
= val
&& ((val
->type
>= XML_SCHEMAS_STRING
&& val
->type
<= XML_SCHEMAS_NORMSTRING
)
5453 || (val
->type
>= XML_SCHEMAS_TOKEN
&& val
->type
<= XML_SCHEMAS_NCNAME
));
5454 ret
= xmlRegexpExec(facet
->regexp
,
5455 (stringType
&& val
->value
.str
) ? val
->value
.str
: value
);
5459 return(XML_SCHEMAV_CVC_PATTERN_VALID
);
5461 case XML_SCHEMA_FACET_MAXEXCLUSIVE
:
5462 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5467 return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID
);
5468 case XML_SCHEMA_FACET_MAXINCLUSIVE
:
5469 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5472 if ((ret
== -1) || (ret
== 0))
5474 return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID
);
5475 case XML_SCHEMA_FACET_MINEXCLUSIVE
:
5476 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5481 return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID
);
5482 case XML_SCHEMA_FACET_MININCLUSIVE
:
5483 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5486 if ((ret
== 1) || (ret
== 0))
5488 return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID
);
5489 case XML_SCHEMA_FACET_WHITESPACE
:
5490 /* TODO whitespaces */
5492 * NOTE: Whitespace should be handled to normalize
5493 * the value to be validated against a the facets;
5494 * not to normalize the value in-between.
5497 case XML_SCHEMA_FACET_ENUMERATION
:
5498 if (ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) {
5500 * This is to ensure API compatibility with the old
5501 * xmlSchemaValidateFacet().
5502 * TODO: Get rid of this case.
5504 if ((facet
->value
!= NULL
) &&
5505 (xmlStrEqual(facet
->value
, value
)))
5508 ret
= xmlSchemaCompareValuesWhtspExt(facet
->val
->type
,
5509 facet
->val
, facet
->value
, fws
, valType
, val
,
5516 return(XML_SCHEMAV_CVC_ENUMERATION_VALID
);
5517 case XML_SCHEMA_FACET_LENGTH
:
5519 * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
5520 * then any {value} is facet-valid."
5522 if ((valType
== XML_SCHEMAS_QNAME
) ||
5523 (valType
== XML_SCHEMAS_NOTATION
))
5525 /* Falls through. */
5526 case XML_SCHEMA_FACET_MAXLENGTH
:
5527 case XML_SCHEMA_FACET_MINLENGTH
: {
5528 unsigned int len
= 0;
5530 if ((valType
== XML_SCHEMAS_QNAME
) ||
5531 (valType
== XML_SCHEMAS_NOTATION
))
5534 * TODO: length, maxLength and minLength must be of type
5535 * nonNegativeInteger only. Check if decimal is used somehow.
5537 if ((facet
->val
== NULL
) ||
5538 ((facet
->val
->type
!= XML_SCHEMAS_DECIMAL
) &&
5539 (facet
->val
->type
!= XML_SCHEMAS_NNINTEGER
)) ||
5540 (facet
->val
->value
.decimal
.frac
!= 0)) {
5543 if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_HEXBINARY
))
5544 len
= val
->value
.hex
.total
;
5545 else if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_BASE64BINARY
))
5546 len
= val
->value
.base64
.total
;
5549 case XML_SCHEMAS_STRING
:
5550 case XML_SCHEMAS_NORMSTRING
:
5551 if (ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) {
5553 * This is to ensure API compatibility with the old
5554 * xmlSchemaValidateFacet(). Anyway, this was and
5555 * is not the correct handling.
5556 * TODO: Get rid of this case somehow.
5558 if (valType
== XML_SCHEMAS_STRING
)
5559 len
= xmlUTF8Strlen(value
);
5561 len
= xmlSchemaNormLen(value
);
5562 } else if (value
!= NULL
) {
5563 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
5564 len
= xmlSchemaNormLen(value
);
5567 * Should be OK for "preserve" as well.
5569 len
= xmlUTF8Strlen(value
);
5572 case XML_SCHEMAS_IDREF
:
5573 case XML_SCHEMAS_TOKEN
:
5574 case XML_SCHEMAS_LANGUAGE
:
5575 case XML_SCHEMAS_NMTOKEN
:
5576 case XML_SCHEMAS_NAME
:
5577 case XML_SCHEMAS_NCNAME
:
5578 case XML_SCHEMAS_ID
:
5579 case XML_SCHEMAS_ANYURI
:
5581 len
= xmlSchemaNormLen(value
);
5587 if (facet
->type
== XML_SCHEMA_FACET_LENGTH
) {
5588 if (len
!= facet
->val
->value
.decimal
.lo
)
5589 return(XML_SCHEMAV_CVC_LENGTH_VALID
);
5590 } else if (facet
->type
== XML_SCHEMA_FACET_MINLENGTH
) {
5591 if (len
< facet
->val
->value
.decimal
.lo
)
5592 return(XML_SCHEMAV_CVC_MINLENGTH_VALID
);
5594 if (len
> facet
->val
->value
.decimal
.lo
)
5595 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID
);
5599 case XML_SCHEMA_FACET_TOTALDIGITS
:
5600 case XML_SCHEMA_FACET_FRACTIONDIGITS
:
5602 if ((facet
->val
== NULL
) ||
5603 ((facet
->val
->type
!= XML_SCHEMAS_PINTEGER
) &&
5604 (facet
->val
->type
!= XML_SCHEMAS_NNINTEGER
)) ||
5605 (facet
->val
->value
.decimal
.frac
!= 0)) {
5608 if ((val
== NULL
) ||
5609 ((val
->type
!= XML_SCHEMAS_DECIMAL
) &&
5610 (val
->type
!= XML_SCHEMAS_INTEGER
) &&
5611 (val
->type
!= XML_SCHEMAS_NPINTEGER
) &&
5612 (val
->type
!= XML_SCHEMAS_NINTEGER
) &&
5613 (val
->type
!= XML_SCHEMAS_NNINTEGER
) &&
5614 (val
->type
!= XML_SCHEMAS_PINTEGER
) &&
5615 (val
->type
!= XML_SCHEMAS_INT
) &&
5616 (val
->type
!= XML_SCHEMAS_UINT
) &&
5617 (val
->type
!= XML_SCHEMAS_LONG
) &&
5618 (val
->type
!= XML_SCHEMAS_ULONG
) &&
5619 (val
->type
!= XML_SCHEMAS_SHORT
) &&
5620 (val
->type
!= XML_SCHEMAS_USHORT
) &&
5621 (val
->type
!= XML_SCHEMAS_BYTE
) &&
5622 (val
->type
!= XML_SCHEMAS_UBYTE
))) {
5625 if (facet
->type
== XML_SCHEMA_FACET_TOTALDIGITS
) {
5626 if (val
->value
.decimal
.total
> facet
->val
->value
.decimal
.lo
)
5627 return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID
);
5629 } else if (facet
->type
== XML_SCHEMA_FACET_FRACTIONDIGITS
) {
5630 if (val
->value
.decimal
.frac
> facet
->val
->value
.decimal
.lo
)
5631 return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID
);
5642 * xmlSchemaValidateFacet:
5643 * @base: the base type
5644 * @facet: the facet to check
5645 * @value: the lexical repr of the value to validate
5646 * @val: the precomputed value
5648 * Check a value against a facet condition
5650 * Returns 0 if the element is schemas valid, a positive error code
5651 * number otherwise and -1 in case of internal or API error.
5654 xmlSchemaValidateFacet(xmlSchemaTypePtr base
,
5655 xmlSchemaFacetPtr facet
,
5656 const xmlChar
*value
,
5657 xmlSchemaValPtr val
)
5660 * This tries to ensure API compatibility regarding the old
5661 * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
5662 * xmlSchemaValidateFacetWhtsp().
5665 return(xmlSchemaValidateFacetInternal(facet
,
5666 XML_SCHEMA_WHITESPACE_UNKNOWN
, val
->type
, value
, val
,
5667 XML_SCHEMA_WHITESPACE_UNKNOWN
));
5668 else if (base
!= NULL
)
5669 return(xmlSchemaValidateFacetInternal(facet
,
5670 XML_SCHEMA_WHITESPACE_UNKNOWN
, base
->builtInType
, value
, val
,
5671 XML_SCHEMA_WHITESPACE_UNKNOWN
));
5676 * xmlSchemaValidateFacetWhtsp:
5677 * @facet: the facet to check
5678 * @fws: the whitespace type of the facet's value
5679 * @valType: the built-in type of the value
5680 * @value: the lexical (or normalized for pattern) repr of the value to validate
5681 * @val: the precomputed value
5682 * @ws: the whitespace type of the value
5684 * Check a value against a facet condition. This takes value normalization
5685 * according to the specified whitespace types into account.
5686 * Note that @value needs to be the *normalized* value if the facet
5687 * is of type "pattern".
5689 * Returns 0 if the element is schemas valid, a positive error code
5690 * number otherwise and -1 in case of internal or API error.
5693 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet
,
5694 xmlSchemaWhitespaceValueType fws
,
5695 xmlSchemaValType valType
,
5696 const xmlChar
*value
,
5697 xmlSchemaValPtr val
,
5698 xmlSchemaWhitespaceValueType ws
)
5700 return(xmlSchemaValidateFacetInternal(facet
, fws
, valType
,
5709 #define DBL_EPSILON 1E-9
5712 #define INTEGER_DIGITS DBL_DIG
5713 #define FRACTION_DIGITS (DBL_DIG + 1)
5714 #define EXPONENT_DIGITS (3 + 2)
5717 * xmlXPathFormatNumber:
5718 * @number: number to format
5719 * @buffer: output buffer
5720 * @buffersize: size of output buffer
5722 * Convert the number into a string representation.
5725 xmlSchemaFormatFloat(double number
, char buffer
[], int buffersize
)
5727 switch (xmlXPathIsInf(number
)) {
5729 if (buffersize
> (int)sizeof("INF"))
5730 snprintf(buffer
, buffersize
, "INF");
5733 if (buffersize
> (int)sizeof("-INF"))
5734 snprintf(buffer
, buffersize
, "-INF");
5737 if (xmlXPathIsNaN(number
)) {
5738 if (buffersize
> (int)sizeof("NaN"))
5739 snprintf(buffer
, buffersize
, "NaN");
5740 } else if (number
== 0) {
5741 snprintf(buffer
, buffersize
, "0.0E0");
5743 /* 3 is sign, decimal point, and terminating zero */
5744 char work
[DBL_DIG
+ EXPONENT_DIGITS
+ 3];
5745 int integer_place
, fraction_place
;
5747 char *after_fraction
;
5748 double absolute_value
;
5751 absolute_value
= fabs(number
);
5754 * Result is in work, and after_fraction points
5755 * just past the fractional part.
5756 * Use scientific notation
5758 integer_place
= DBL_DIG
+ EXPONENT_DIGITS
+ 1;
5759 fraction_place
= DBL_DIG
- 1;
5760 snprintf(work
, sizeof(work
),"%*.*e",
5761 integer_place
, fraction_place
, number
);
5762 after_fraction
= strchr(work
+ DBL_DIG
, 'e');
5763 /* Remove fractional trailing zeroes */
5764 ptr
= after_fraction
;
5765 while (*(--ptr
) == '0')
5769 while ((*ptr
++ = *after_fraction
++) != 0);
5771 /* Finally copy result back to caller */
5772 size
= strlen(work
) + 1;
5773 if (size
> buffersize
) {
5774 work
[buffersize
- 1] = 0;
5777 memmove(buffer
, work
, size
);
5785 * xmlSchemaGetCanonValue:
5786 * @val: the precomputed value
5787 * @retValue: the returned value
5789 * Get the canonical lexical representation of the value.
5790 * The caller has to FREE the returned retValue.
5792 * WARNING: Some value types are not supported yet, resulting
5793 * in a @retValue of "???".
5795 * TODO: XML Schema 1.0 does not define canonical representations
5796 * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay,
5797 * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1.
5800 * Returns 0 if the value could be built, 1 if the value type is
5801 * not supported yet and -1 in case of API errors.
5804 xmlSchemaGetCanonValue(xmlSchemaValPtr val
, const xmlChar
**retValue
)
5806 if ((retValue
== NULL
) || (val
== NULL
))
5809 switch (val
->type
) {
5810 case XML_SCHEMAS_STRING
:
5811 if (val
->value
.str
== NULL
)
5812 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
5815 BAD_CAST
xmlStrdup((const xmlChar
*) val
->value
.str
);
5817 case XML_SCHEMAS_NORMSTRING
:
5818 if (val
->value
.str
== NULL
)
5819 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
5821 *retValue
= xmlSchemaWhiteSpaceReplace(
5822 (const xmlChar
*) val
->value
.str
);
5823 if ((*retValue
) == NULL
)
5824 *retValue
= BAD_CAST
xmlStrdup(
5825 (const xmlChar
*) val
->value
.str
);
5828 case XML_SCHEMAS_TOKEN
:
5829 case XML_SCHEMAS_LANGUAGE
:
5830 case XML_SCHEMAS_NMTOKEN
:
5831 case XML_SCHEMAS_NAME
:
5832 case XML_SCHEMAS_NCNAME
:
5833 case XML_SCHEMAS_ID
:
5834 case XML_SCHEMAS_IDREF
:
5835 case XML_SCHEMAS_ENTITY
:
5836 case XML_SCHEMAS_NOTATION
: /* Unclear */
5837 case XML_SCHEMAS_ANYURI
: /* Unclear */
5838 if (val
->value
.str
== NULL
)
5841 BAD_CAST
xmlSchemaCollapseString(BAD_CAST val
->value
.str
);
5842 if (*retValue
== NULL
)
5844 BAD_CAST
xmlStrdup((const xmlChar
*) val
->value
.str
);
5846 case XML_SCHEMAS_QNAME
:
5847 /* TODO: Unclear in XML Schema 1.0. */
5848 if (val
->value
.qname
.uri
== NULL
) {
5849 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST val
->value
.qname
.name
);
5852 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"{");
5853 *retValue
= BAD_CAST
xmlStrcat((xmlChar
*) (*retValue
),
5854 BAD_CAST val
->value
.qname
.uri
);
5855 *retValue
= BAD_CAST
xmlStrcat((xmlChar
*) (*retValue
),
5857 *retValue
= BAD_CAST
xmlStrcat((xmlChar
*) (*retValue
),
5858 BAD_CAST val
->value
.qname
.uri
);
5861 case XML_SCHEMAS_DECIMAL
:
5863 * TODO: Lookout for a more simple implementation.
5865 if ((val
->value
.decimal
.total
== 1) &&
5866 (val
->value
.decimal
.lo
== 0)) {
5867 *retValue
= xmlStrdup(BAD_CAST
"0.0");
5869 xmlSchemaValDecimal dec
= val
->value
.decimal
;
5871 char *buf
= NULL
, *offs
;
5873 /* Add room for the decimal point as well. */
5874 bufsize
= dec
.total
+ 2;
5877 /* Add room for leading/trailing zero. */
5878 if ((dec
.frac
== 0) || (dec
.frac
== dec
.total
))
5880 buf
= xmlMalloc(bufsize
);
5886 if (dec
.frac
== dec
.total
) {
5891 snprintf(offs
, bufsize
- (offs
- buf
),
5892 "%lu%lu%lu", dec
.hi
, dec
.mi
, dec
.lo
);
5893 else if (dec
.mi
!= 0)
5894 snprintf(offs
, bufsize
- (offs
- buf
),
5895 "%lu%lu", dec
.mi
, dec
.lo
);
5897 snprintf(offs
, bufsize
- (offs
- buf
),
5900 if (dec
.frac
!= 0) {
5901 if (dec
.frac
!= dec
.total
) {
5902 int diff
= dec
.total
- dec
.frac
;
5904 * Insert the decimal point.
5906 memmove(offs
+ diff
+ 1, offs
+ diff
, dec
.frac
+1);
5911 * Insert missing zeroes behind the decimal point.
5913 while (*(offs
+ i
) != 0)
5915 if (i
< dec
.total
) {
5916 memmove(offs
+ (dec
.total
- i
), offs
, i
+1);
5917 memset(offs
, '0', dec
.total
- i
);
5922 * Append decimal point and zero.
5924 offs
= buf
+ bufsize
- 1;
5929 *retValue
= BAD_CAST buf
;
5932 case XML_SCHEMAS_INTEGER
:
5933 case XML_SCHEMAS_PINTEGER
:
5934 case XML_SCHEMAS_NPINTEGER
:
5935 case XML_SCHEMAS_NINTEGER
:
5936 case XML_SCHEMAS_NNINTEGER
:
5937 case XML_SCHEMAS_LONG
:
5938 case XML_SCHEMAS_BYTE
:
5939 case XML_SCHEMAS_SHORT
:
5940 case XML_SCHEMAS_INT
:
5941 case XML_SCHEMAS_UINT
:
5942 case XML_SCHEMAS_ULONG
:
5943 case XML_SCHEMAS_USHORT
:
5944 case XML_SCHEMAS_UBYTE
:
5945 if ((val
->value
.decimal
.total
== 1) &&
5946 (val
->value
.decimal
.lo
== 0))
5947 *retValue
= xmlStrdup(BAD_CAST
"0");
5949 xmlSchemaValDecimal dec
= val
->value
.decimal
;
5950 int bufsize
= dec
.total
+ 1;
5952 /* Add room for the decimal point as well. */
5955 *retValue
= xmlMalloc(bufsize
);
5956 if (*retValue
== NULL
)
5960 snprintf((char *) *retValue
, bufsize
,
5961 "-%lu%lu%lu", dec
.hi
, dec
.mi
, dec
.lo
);
5963 snprintf((char *) *retValue
, bufsize
,
5964 "%lu%lu%lu", dec
.hi
, dec
.mi
, dec
.lo
);
5965 } else if (dec
.mi
!= 0) {
5967 snprintf((char *) *retValue
, bufsize
,
5968 "-%lu%lu", dec
.mi
, dec
.lo
);
5970 snprintf((char *) *retValue
, bufsize
,
5971 "%lu%lu", dec
.mi
, dec
.lo
);
5974 snprintf((char *) *retValue
, bufsize
, "-%lu", dec
.lo
);
5976 snprintf((char *) *retValue
, bufsize
, "%lu", dec
.lo
);
5980 case XML_SCHEMAS_BOOLEAN
:
5982 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"true");
5984 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"false");
5986 case XML_SCHEMAS_DURATION
: {
5989 unsigned long mon
, day
, hour
= 0, min
= 0;
5990 double sec
= 0, left
;
5992 /* TODO: Unclear in XML Schema 1.0 */
5994 * TODO: This results in a normalized output of the value
5995 * - which is NOT conformant to the spec -
5996 * since the exact values of each property are not
5997 * recoverable. Think about extending the structure to
5998 * provide a field for every property.
6000 year
= (unsigned long) FQUOTIENT(labs(val
->value
.dur
.mon
), 12);
6001 mon
= labs(val
->value
.dur
.mon
) - 12 * year
;
6003 day
= (unsigned long) FQUOTIENT(fabs(val
->value
.dur
.sec
), 86400);
6004 left
= fabs(val
->value
.dur
.sec
) - day
* 86400;
6006 hour
= (unsigned long) FQUOTIENT(left
, 3600);
6007 left
= left
- (hour
* 3600);
6009 min
= (unsigned long) FQUOTIENT(left
, 60);
6010 sec
= left
- (min
* 60);
6013 if ((val
->value
.dur
.mon
< 0) || (val
->value
.dur
.sec
< 0))
6014 snprintf(buf
, 100, "P%luY%luM%luDT%luH%luM%.14gS",
6015 year
, mon
, day
, hour
, min
, sec
);
6017 snprintf(buf
, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
6018 year
, mon
, day
, hour
, min
, sec
);
6019 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6022 case XML_SCHEMAS_GYEAR
: {
6024 /* TODO: Unclear in XML Schema 1.0 */
6025 /* TODO: What to do with the timezone? */
6026 snprintf(buf
, 30, "%04ld", val
->value
.date
.year
);
6027 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6030 case XML_SCHEMAS_GMONTH
: {
6031 /* TODO: Unclear in XML Schema 1.0 */
6032 /* TODO: What to do with the timezone? */
6033 *retValue
= xmlMalloc(6);
6034 if (*retValue
== NULL
)
6036 snprintf((char *) *retValue
, 6, "--%02u",
6037 val
->value
.date
.mon
);
6040 case XML_SCHEMAS_GDAY
: {
6041 /* TODO: Unclear in XML Schema 1.0 */
6042 /* TODO: What to do with the timezone? */
6043 *retValue
= xmlMalloc(6);
6044 if (*retValue
== NULL
)
6046 snprintf((char *) *retValue
, 6, "---%02u",
6047 val
->value
.date
.day
);
6050 case XML_SCHEMAS_GMONTHDAY
: {
6051 /* TODO: Unclear in XML Schema 1.0 */
6052 /* TODO: What to do with the timezone? */
6053 *retValue
= xmlMalloc(8);
6054 if (*retValue
== NULL
)
6056 snprintf((char *) *retValue
, 8, "--%02u-%02u",
6057 val
->value
.date
.mon
, val
->value
.date
.day
);
6060 case XML_SCHEMAS_GYEARMONTH
: {
6062 /* TODO: Unclear in XML Schema 1.0 */
6063 /* TODO: What to do with the timezone? */
6064 if (val
->value
.date
.year
< 0)
6065 snprintf(buf
, 35, "-%04ld-%02u",
6066 labs(val
->value
.date
.year
),
6067 val
->value
.date
.mon
);
6069 snprintf(buf
, 35, "%04ld-%02u",
6070 val
->value
.date
.year
, val
->value
.date
.mon
);
6071 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6074 case XML_SCHEMAS_TIME
:
6078 if (val
->value
.date
.tz_flag
) {
6079 xmlSchemaValPtr norm
;
6081 norm
= xmlSchemaDateNormalize(val
, 0);
6085 * TODO: Check if "%.14g" is portable.
6088 "%02u:%02u:%02.14gZ",
6089 norm
->value
.date
.hour
,
6090 norm
->value
.date
.min
,
6091 norm
->value
.date
.sec
);
6092 xmlSchemaFreeValue(norm
);
6095 "%02u:%02u:%02.14g",
6096 val
->value
.date
.hour
,
6097 val
->value
.date
.min
,
6098 val
->value
.date
.sec
);
6100 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6103 case XML_SCHEMAS_DATE
:
6107 if (val
->value
.date
.tz_flag
) {
6108 xmlSchemaValPtr norm
;
6110 norm
= xmlSchemaDateNormalize(val
, 0);
6114 * TODO: Append the canonical value of the
6115 * recoverable timezone and not "Z".
6119 norm
->value
.date
.year
, norm
->value
.date
.mon
,
6120 norm
->value
.date
.day
);
6121 xmlSchemaFreeValue(norm
);
6125 val
->value
.date
.year
, val
->value
.date
.mon
,
6126 val
->value
.date
.day
);
6128 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6131 case XML_SCHEMAS_DATETIME
:
6135 if (val
->value
.date
.tz_flag
) {
6136 xmlSchemaValPtr norm
;
6138 norm
= xmlSchemaDateNormalize(val
, 0);
6142 * TODO: Check if "%.14g" is portable.
6145 "%04ld-%02u-%02uT%02u:%02u:%02.14gZ",
6146 norm
->value
.date
.year
, norm
->value
.date
.mon
,
6147 norm
->value
.date
.day
, norm
->value
.date
.hour
,
6148 norm
->value
.date
.min
, norm
->value
.date
.sec
);
6149 xmlSchemaFreeValue(norm
);
6152 "%04ld-%02u-%02uT%02u:%02u:%02.14g",
6153 val
->value
.date
.year
, val
->value
.date
.mon
,
6154 val
->value
.date
.day
, val
->value
.date
.hour
,
6155 val
->value
.date
.min
, val
->value
.date
.sec
);
6157 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6160 case XML_SCHEMAS_HEXBINARY
:
6161 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST val
->value
.hex
.str
);
6163 case XML_SCHEMAS_BASE64BINARY
:
6165 * TODO: Is the following spec piece implemented?:
6166 * SPEC: "Note: For some values the canonical form defined
6167 * above does not conform to [RFC 2045], which requires breaking
6168 * with linefeeds at appropriate intervals."
6170 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST val
->value
.base64
.str
);
6172 case XML_SCHEMAS_FLOAT
: {
6175 * |m| < 16777216, -149 <= e <= 104.
6176 * TODO: Handle, NaN, INF, -INF. The format is not
6177 * yet conformant. The c type float does not cover
6180 snprintf(buf
, 30, "%01.14e", val
->value
.f
);
6181 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6184 case XML_SCHEMAS_DOUBLE
: {
6186 /* |m| < 9007199254740992, -1075 <= e <= 970 */
6188 * TODO: Handle, NaN, INF, -INF. The format is not
6189 * yet conformant. The c type float does not cover
6192 snprintf(buf
, 40, "%01.14e", val
->value
.d
);
6193 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6197 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"???");
6200 if (*retValue
== NULL
)
6206 * xmlSchemaGetCanonValueWhtsp:
6207 * @val: the precomputed value
6208 * @retValue: the returned value
6209 * @ws: the whitespace type of the value
6211 * Get the canonical representation of the value.
6212 * The caller has to free the returned @retValue.
6214 * Returns 0 if the value could be built, 1 if the value type is
6215 * not supported yet and -1 in case of API errors.
6218 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val
,
6219 const xmlChar
**retValue
,
6220 xmlSchemaWhitespaceValueType ws
)
6222 if ((retValue
== NULL
) || (val
== NULL
))
6224 if ((ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) ||
6225 (ws
> XML_SCHEMA_WHITESPACE_COLLAPSE
))
6229 switch (val
->type
) {
6230 case XML_SCHEMAS_STRING
:
6231 if (val
->value
.str
== NULL
)
6232 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
6233 else if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
6234 *retValue
= xmlSchemaCollapseString(val
->value
.str
);
6235 else if (ws
== XML_SCHEMA_WHITESPACE_REPLACE
)
6236 *retValue
= xmlSchemaWhiteSpaceReplace(val
->value
.str
);
6237 if ((*retValue
) == NULL
)
6238 *retValue
= BAD_CAST
xmlStrdup(val
->value
.str
);
6240 case XML_SCHEMAS_NORMSTRING
:
6241 if (val
->value
.str
== NULL
)
6242 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
6244 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
6245 *retValue
= xmlSchemaCollapseString(val
->value
.str
);
6247 *retValue
= xmlSchemaWhiteSpaceReplace(val
->value
.str
);
6248 if ((*retValue
) == NULL
)
6249 *retValue
= BAD_CAST
xmlStrdup(val
->value
.str
);
6253 return (xmlSchemaGetCanonValue(val
, retValue
));
6259 * xmlSchemaGetValType:
6260 * @val: a schemas value
6262 * Accessor for the type of a value
6264 * Returns the xmlSchemaValType of the value
6267 xmlSchemaGetValType(xmlSchemaValPtr val
)
6270 return(XML_SCHEMAS_UNKNOWN
);
6274 #define bottom_xmlschemastypes
6275 #include "elfgcchack.h"
6276 #endif /* LIBXML_SCHEMAS_ENABLED */