2 * schemastypes.c : implementation of the XML Schema Datatypes
3 * definition and validity checking
5 * See Copyright for the status of this software.
7 * Daniel Veillard <veillard@redhat.com>
13 #ifdef LIBXML_SCHEMAS_ENABLED
16 #include <libxml/xmlmemory.h>
17 #include <libxml/parser.h>
18 #include <libxml/parserInternals.h>
19 #include <libxml/hash.h>
20 #include <libxml/valid.h>
21 #include <libxml/xpath.h>
22 #include <libxml/uri.h>
24 #include <libxml/xmlschemas.h>
25 #include <libxml/schemasInternals.h>
26 #include <libxml/xmlschemastypes.h>
37 #ifndef LIBXML_XPATH_ENABLED
38 extern double xmlXPathNAN
;
39 extern double xmlXPathPINF
;
40 extern double xmlXPathNINF
;
44 xmlGenericError(xmlGenericErrorContext, \
45 "Unimplemented block at %s:%d\n", \
48 #define XML_SCHEMAS_NAMESPACE_NAME \
49 (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
51 #define IS_WSP_REPLACE_CH(c) ((((c) == 0x9) || ((c) == 0xa)) || \
54 #define IS_WSP_SPACE_CH(c) ((c) == 0x20)
56 #define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c)
59 typedef struct _xmlSchemaValDate xmlSchemaValDate
;
60 typedef xmlSchemaValDate
*xmlSchemaValDatePtr
;
61 struct _xmlSchemaValDate
{
63 unsigned int mon
:4; /* 1 <= mon <= 12 */
64 unsigned int day
:5; /* 1 <= day <= 31 */
65 unsigned int hour
:5; /* 0 <= hour <= 23 */
66 unsigned int min
:6; /* 0 <= min <= 59 */
68 unsigned int tz_flag
:1; /* is tzo explicitely set? */
69 signed int tzo
:12; /* -1440 <= tzo <= 1440;
70 currently only -840 to +840 are needed */
74 typedef struct _xmlSchemaValDuration xmlSchemaValDuration
;
75 typedef xmlSchemaValDuration
*xmlSchemaValDurationPtr
;
76 struct _xmlSchemaValDuration
{
77 long mon
; /* mon stores years also */
79 double sec
; /* sec stores min and hour also */
82 typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal
;
83 typedef xmlSchemaValDecimal
*xmlSchemaValDecimalPtr
;
84 struct _xmlSchemaValDecimal
{
85 /* would use long long but not portable */
95 typedef struct _xmlSchemaValQName xmlSchemaValQName
;
96 typedef xmlSchemaValQName
*xmlSchemaValQNamePtr
;
97 struct _xmlSchemaValQName
{
102 typedef struct _xmlSchemaValHex xmlSchemaValHex
;
103 typedef xmlSchemaValHex
*xmlSchemaValHexPtr
;
104 struct _xmlSchemaValHex
{
109 typedef struct _xmlSchemaValBase64 xmlSchemaValBase64
;
110 typedef xmlSchemaValBase64
*xmlSchemaValBase64Ptr
;
111 struct _xmlSchemaValBase64
{
116 struct _xmlSchemaVal
{
117 xmlSchemaValType type
;
118 struct _xmlSchemaVal
*next
;
120 xmlSchemaValDecimal decimal
;
121 xmlSchemaValDate date
;
122 xmlSchemaValDuration dur
;
123 xmlSchemaValQName qname
;
125 xmlSchemaValBase64 base64
;
133 static int xmlSchemaTypesInitialized
= 0;
134 static xmlHashTablePtr xmlSchemaTypesBank
= NULL
;
139 static xmlSchemaTypePtr xmlSchemaTypeStringDef
= NULL
;
140 static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef
= NULL
;
141 static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef
= NULL
;
142 static xmlSchemaTypePtr xmlSchemaTypeDecimalDef
= NULL
;
143 static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef
= NULL
;
144 static xmlSchemaTypePtr xmlSchemaTypeDateDef
= NULL
;
145 static xmlSchemaTypePtr xmlSchemaTypeTimeDef
= NULL
;
146 static xmlSchemaTypePtr xmlSchemaTypeGYearDef
= NULL
;
147 static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef
= NULL
;
148 static xmlSchemaTypePtr xmlSchemaTypeGDayDef
= NULL
;
149 static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef
= NULL
;
150 static xmlSchemaTypePtr xmlSchemaTypeGMonthDef
= NULL
;
151 static xmlSchemaTypePtr xmlSchemaTypeDurationDef
= NULL
;
152 static xmlSchemaTypePtr xmlSchemaTypeFloatDef
= NULL
;
153 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef
= NULL
;
154 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef
= NULL
;
155 static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef
= NULL
;
156 static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef
= NULL
;
157 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef
= NULL
;
162 static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef
= NULL
;
163 static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef
= NULL
;
164 static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef
= NULL
;
165 static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef
= NULL
;
166 static xmlSchemaTypePtr xmlSchemaTypeIntegerDef
= NULL
;
167 static xmlSchemaTypePtr xmlSchemaTypeLongDef
= NULL
;
168 static xmlSchemaTypePtr xmlSchemaTypeIntDef
= NULL
;
169 static xmlSchemaTypePtr xmlSchemaTypeShortDef
= NULL
;
170 static xmlSchemaTypePtr xmlSchemaTypeByteDef
= NULL
;
171 static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef
= NULL
;
172 static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef
= NULL
;
173 static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef
= NULL
;
174 static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef
= NULL
;
175 static xmlSchemaTypePtr xmlSchemaTypeNormStringDef
= NULL
;
176 static xmlSchemaTypePtr xmlSchemaTypeTokenDef
= NULL
;
177 static xmlSchemaTypePtr xmlSchemaTypeLanguageDef
= NULL
;
178 static xmlSchemaTypePtr xmlSchemaTypeNameDef
= NULL
;
179 static xmlSchemaTypePtr xmlSchemaTypeQNameDef
= NULL
;
180 static xmlSchemaTypePtr xmlSchemaTypeNCNameDef
= NULL
;
181 static xmlSchemaTypePtr xmlSchemaTypeIdDef
= NULL
;
182 static xmlSchemaTypePtr xmlSchemaTypeIdrefDef
= NULL
;
183 static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef
= NULL
;
184 static xmlSchemaTypePtr xmlSchemaTypeEntityDef
= NULL
;
185 static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef
= NULL
;
186 static xmlSchemaTypePtr xmlSchemaTypeNotationDef
= NULL
;
187 static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef
= NULL
;
188 static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef
= NULL
;
190 /************************************************************************
192 * Datatype error handlers *
194 ************************************************************************/
196 * xmlSchemaTypeErrMemory:
197 * @extra: extra informations
199 * Handle an out of memory condition
202 xmlSchemaTypeErrMemory(xmlNodePtr node
, const char *extra
)
204 __xmlSimpleError(XML_FROM_DATATYPE
, XML_ERR_NO_MEMORY
, node
, NULL
, extra
);
207 /************************************************************************
209 * Base types support *
211 ************************************************************************/
215 * @type: the value type
217 * Allocate a new simple type value
219 * Returns a pointer to the new value or NULL in case of error
221 static xmlSchemaValPtr
222 xmlSchemaNewValue(xmlSchemaValType type
) {
223 xmlSchemaValPtr value
;
225 value
= (xmlSchemaValPtr
) xmlMalloc(sizeof(xmlSchemaVal
));
229 memset(value
, 0, sizeof(xmlSchemaVal
));
234 static xmlSchemaFacetPtr
235 xmlSchemaNewMinLengthFacet(int value
)
237 xmlSchemaFacetPtr ret
;
239 ret
= xmlSchemaNewFacet();
243 ret
->type
= XML_SCHEMA_FACET_MINLENGTH
;
244 ret
->val
= xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER
);
245 if (ret
->val
== NULL
) {
249 ret
->val
->value
.decimal
.lo
= value
;
254 * xmlSchemaInitBasicType:
255 * @name: the type name
256 * @type: the value type associated
258 * Initialize one primitive built-in type
260 static xmlSchemaTypePtr
261 xmlSchemaInitBasicType(const char *name
, xmlSchemaValType type
,
262 xmlSchemaTypePtr baseType
) {
263 xmlSchemaTypePtr ret
;
265 ret
= (xmlSchemaTypePtr
) xmlMalloc(sizeof(xmlSchemaType
));
267 xmlSchemaTypeErrMemory(NULL
, "could not initialize basic types");
270 memset(ret
, 0, sizeof(xmlSchemaType
));
271 ret
->name
= (const xmlChar
*)name
;
272 ret
->targetNamespace
= XML_SCHEMAS_NAMESPACE_NAME
;
273 ret
->type
= XML_SCHEMA_TYPE_BASIC
;
274 ret
->baseType
= baseType
;
275 ret
->contentType
= XML_SCHEMA_CONTENT_BASIC
;
280 case XML_SCHEMAS_STRING
:
281 case XML_SCHEMAS_DECIMAL
:
282 case XML_SCHEMAS_DATE
:
283 case XML_SCHEMAS_DATETIME
:
284 case XML_SCHEMAS_TIME
:
285 case XML_SCHEMAS_GYEAR
:
286 case XML_SCHEMAS_GYEARMONTH
:
287 case XML_SCHEMAS_GMONTH
:
288 case XML_SCHEMAS_GMONTHDAY
:
289 case XML_SCHEMAS_GDAY
:
290 case XML_SCHEMAS_DURATION
:
291 case XML_SCHEMAS_FLOAT
:
292 case XML_SCHEMAS_DOUBLE
:
293 case XML_SCHEMAS_BOOLEAN
:
294 case XML_SCHEMAS_ANYURI
:
295 case XML_SCHEMAS_HEXBINARY
:
296 case XML_SCHEMAS_BASE64BINARY
:
297 case XML_SCHEMAS_QNAME
:
298 case XML_SCHEMAS_NOTATION
:
299 ret
->flags
|= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE
;
308 case XML_SCHEMAS_ANYTYPE
:
309 case XML_SCHEMAS_ANYSIMPLETYPE
:
311 case XML_SCHEMAS_IDREFS
:
312 case XML_SCHEMAS_NMTOKENS
:
313 case XML_SCHEMAS_ENTITIES
:
314 ret
->flags
|= XML_SCHEMAS_TYPE_VARIETY_LIST
;
315 ret
->facets
= xmlSchemaNewMinLengthFacet(1);
316 ret
->flags
|= XML_SCHEMAS_TYPE_HAS_FACETS
;
319 ret
->flags
|= XML_SCHEMAS_TYPE_VARIETY_ATOMIC
;
322 xmlHashAddEntry2(xmlSchemaTypesBank
, ret
->name
,
323 XML_SCHEMAS_NAMESPACE_NAME
, ret
);
324 ret
->builtInType
= type
;
329 * WARNING: Those type reside normally in xmlschemas.c but are
330 * redefined here locally in oder of being able to use them for xs:anyType-
331 * TODO: Remove those definition if we move the types to a header file.
332 * TODO: Always keep those structs up-to-date with the originals.
334 #define UNBOUNDED (1 << 30)
336 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem
;
337 typedef xmlSchemaTreeItem
*xmlSchemaTreeItemPtr
;
338 struct _xmlSchemaTreeItem
{
339 xmlSchemaTypeType type
;
340 xmlSchemaAnnotPtr annot
;
341 xmlSchemaTreeItemPtr next
;
342 xmlSchemaTreeItemPtr children
;
345 typedef struct _xmlSchemaParticle xmlSchemaParticle
;
346 typedef xmlSchemaParticle
*xmlSchemaParticlePtr
;
347 struct _xmlSchemaParticle
{
348 xmlSchemaTypeType type
;
349 xmlSchemaAnnotPtr annot
;
350 xmlSchemaTreeItemPtr next
;
351 xmlSchemaTreeItemPtr children
;
357 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup
;
358 typedef xmlSchemaModelGroup
*xmlSchemaModelGroupPtr
;
359 struct _xmlSchemaModelGroup
{
360 xmlSchemaTypeType type
;
361 xmlSchemaAnnotPtr annot
;
362 xmlSchemaTreeItemPtr next
;
363 xmlSchemaTreeItemPtr children
;
367 static xmlSchemaParticlePtr
368 xmlSchemaAddParticle(void)
370 xmlSchemaParticlePtr ret
= NULL
;
372 ret
= (xmlSchemaParticlePtr
)
373 xmlMalloc(sizeof(xmlSchemaParticle
));
375 xmlSchemaTypeErrMemory(NULL
, "allocating particle component");
378 memset(ret
, 0, sizeof(xmlSchemaParticle
));
379 ret
->type
= XML_SCHEMA_TYPE_PARTICLE
;
386 * xmlSchemaInitTypes:
388 * Initialize the default XML Schemas type library
391 xmlSchemaInitTypes(void)
393 if (xmlSchemaTypesInitialized
!= 0)
395 xmlSchemaTypesBank
= xmlHashCreate(40);
399 * 3.4.7 Built-in Complex Type Definition
401 xmlSchemaTypeAnyTypeDef
= xmlSchemaInitBasicType("anyType",
404 xmlSchemaTypeAnyTypeDef
->baseType
= xmlSchemaTypeAnyTypeDef
;
405 xmlSchemaTypeAnyTypeDef
->contentType
= XML_SCHEMA_CONTENT_MIXED
;
407 * Init the content type.
409 xmlSchemaTypeAnyTypeDef
->contentType
= XML_SCHEMA_CONTENT_MIXED
;
411 xmlSchemaParticlePtr particle
;
412 xmlSchemaModelGroupPtr sequence
;
413 xmlSchemaWildcardPtr wild
;
414 /* First particle. */
415 particle
= xmlSchemaAddParticle();
416 if (particle
== NULL
)
418 xmlSchemaTypeAnyTypeDef
->subtypes
= (xmlSchemaTypePtr
) particle
;
419 /* Sequence model group. */
420 sequence
= (xmlSchemaModelGroupPtr
)
421 xmlMalloc(sizeof(xmlSchemaModelGroup
));
422 if (sequence
== NULL
) {
423 xmlSchemaTypeErrMemory(NULL
, "allocating model group component");
426 memset(sequence
, 0, sizeof(xmlSchemaModelGroup
));
427 sequence
->type
= XML_SCHEMA_TYPE_SEQUENCE
;
428 particle
->children
= (xmlSchemaTreeItemPtr
) sequence
;
429 /* Second particle. */
430 particle
= xmlSchemaAddParticle();
431 if (particle
== NULL
)
433 particle
->minOccurs
= 0;
434 particle
->maxOccurs
= UNBOUNDED
;
435 sequence
->children
= (xmlSchemaTreeItemPtr
) particle
;
437 wild
= (xmlSchemaWildcardPtr
) xmlMalloc(sizeof(xmlSchemaWildcard
));
439 xmlSchemaTypeErrMemory(NULL
, "allocating wildcard component");
442 memset(wild
, 0, sizeof(xmlSchemaWildcard
));
443 wild
->type
= XML_SCHEMA_TYPE_ANY
;
445 wild
->processContents
= XML_SCHEMAS_ANY_LAX
;
446 particle
->children
= (xmlSchemaTreeItemPtr
) wild
;
448 * Create the attribute wildcard.
450 wild
= (xmlSchemaWildcardPtr
) xmlMalloc(sizeof(xmlSchemaWildcard
));
452 xmlSchemaTypeErrMemory(NULL
, "could not create an attribute "
453 "wildcard on anyType");
456 memset(wild
, 0, sizeof(xmlSchemaWildcard
));
458 wild
->processContents
= XML_SCHEMAS_ANY_LAX
;
459 xmlSchemaTypeAnyTypeDef
->attributeWildcard
= wild
;
461 xmlSchemaTypeAnySimpleTypeDef
= xmlSchemaInitBasicType("anySimpleType",
462 XML_SCHEMAS_ANYSIMPLETYPE
,
463 xmlSchemaTypeAnyTypeDef
);
465 * primitive datatypes
467 xmlSchemaTypeStringDef
= xmlSchemaInitBasicType("string",
469 xmlSchemaTypeAnySimpleTypeDef
);
470 xmlSchemaTypeDecimalDef
= xmlSchemaInitBasicType("decimal",
472 xmlSchemaTypeAnySimpleTypeDef
);
473 xmlSchemaTypeDateDef
= xmlSchemaInitBasicType("date",
475 xmlSchemaTypeAnySimpleTypeDef
);
476 xmlSchemaTypeDatetimeDef
= xmlSchemaInitBasicType("dateTime",
477 XML_SCHEMAS_DATETIME
,
478 xmlSchemaTypeAnySimpleTypeDef
);
479 xmlSchemaTypeTimeDef
= xmlSchemaInitBasicType("time",
481 xmlSchemaTypeAnySimpleTypeDef
);
482 xmlSchemaTypeGYearDef
= xmlSchemaInitBasicType("gYear",
484 xmlSchemaTypeAnySimpleTypeDef
);
485 xmlSchemaTypeGYearMonthDef
= xmlSchemaInitBasicType("gYearMonth",
486 XML_SCHEMAS_GYEARMONTH
,
487 xmlSchemaTypeAnySimpleTypeDef
);
488 xmlSchemaTypeGMonthDef
= xmlSchemaInitBasicType("gMonth",
490 xmlSchemaTypeAnySimpleTypeDef
);
491 xmlSchemaTypeGMonthDayDef
= xmlSchemaInitBasicType("gMonthDay",
492 XML_SCHEMAS_GMONTHDAY
,
493 xmlSchemaTypeAnySimpleTypeDef
);
494 xmlSchemaTypeGDayDef
= xmlSchemaInitBasicType("gDay",
496 xmlSchemaTypeAnySimpleTypeDef
);
497 xmlSchemaTypeDurationDef
= xmlSchemaInitBasicType("duration",
498 XML_SCHEMAS_DURATION
,
499 xmlSchemaTypeAnySimpleTypeDef
);
500 xmlSchemaTypeFloatDef
= xmlSchemaInitBasicType("float",
502 xmlSchemaTypeAnySimpleTypeDef
);
503 xmlSchemaTypeDoubleDef
= xmlSchemaInitBasicType("double",
505 xmlSchemaTypeAnySimpleTypeDef
);
506 xmlSchemaTypeBooleanDef
= xmlSchemaInitBasicType("boolean",
508 xmlSchemaTypeAnySimpleTypeDef
);
509 xmlSchemaTypeAnyURIDef
= xmlSchemaInitBasicType("anyURI",
511 xmlSchemaTypeAnySimpleTypeDef
);
512 xmlSchemaTypeHexBinaryDef
= xmlSchemaInitBasicType("hexBinary",
513 XML_SCHEMAS_HEXBINARY
,
514 xmlSchemaTypeAnySimpleTypeDef
);
515 xmlSchemaTypeBase64BinaryDef
516 = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY
,
517 xmlSchemaTypeAnySimpleTypeDef
);
518 xmlSchemaTypeNotationDef
= xmlSchemaInitBasicType("NOTATION",
519 XML_SCHEMAS_NOTATION
,
520 xmlSchemaTypeAnySimpleTypeDef
);
521 xmlSchemaTypeQNameDef
= xmlSchemaInitBasicType("QName",
523 xmlSchemaTypeAnySimpleTypeDef
);
528 xmlSchemaTypeIntegerDef
= xmlSchemaInitBasicType("integer",
530 xmlSchemaTypeDecimalDef
);
531 xmlSchemaTypeNonPositiveIntegerDef
=
532 xmlSchemaInitBasicType("nonPositiveInteger",
533 XML_SCHEMAS_NPINTEGER
,
534 xmlSchemaTypeIntegerDef
);
535 xmlSchemaTypeNegativeIntegerDef
=
536 xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER
,
537 xmlSchemaTypeNonPositiveIntegerDef
);
538 xmlSchemaTypeLongDef
=
539 xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG
,
540 xmlSchemaTypeIntegerDef
);
541 xmlSchemaTypeIntDef
= xmlSchemaInitBasicType("int", XML_SCHEMAS_INT
,
542 xmlSchemaTypeLongDef
);
543 xmlSchemaTypeShortDef
= xmlSchemaInitBasicType("short",
545 xmlSchemaTypeIntDef
);
546 xmlSchemaTypeByteDef
= xmlSchemaInitBasicType("byte",
548 xmlSchemaTypeShortDef
);
549 xmlSchemaTypeNonNegativeIntegerDef
=
550 xmlSchemaInitBasicType("nonNegativeInteger",
551 XML_SCHEMAS_NNINTEGER
,
552 xmlSchemaTypeIntegerDef
);
553 xmlSchemaTypeUnsignedLongDef
=
554 xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG
,
555 xmlSchemaTypeNonNegativeIntegerDef
);
556 xmlSchemaTypeUnsignedIntDef
=
557 xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT
,
558 xmlSchemaTypeUnsignedLongDef
);
559 xmlSchemaTypeUnsignedShortDef
=
560 xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT
,
561 xmlSchemaTypeUnsignedIntDef
);
562 xmlSchemaTypeUnsignedByteDef
=
563 xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE
,
564 xmlSchemaTypeUnsignedShortDef
);
565 xmlSchemaTypePositiveIntegerDef
=
566 xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER
,
567 xmlSchemaTypeNonNegativeIntegerDef
);
568 xmlSchemaTypeNormStringDef
= xmlSchemaInitBasicType("normalizedString",
569 XML_SCHEMAS_NORMSTRING
,
570 xmlSchemaTypeStringDef
);
571 xmlSchemaTypeTokenDef
= xmlSchemaInitBasicType("token",
573 xmlSchemaTypeNormStringDef
);
574 xmlSchemaTypeLanguageDef
= xmlSchemaInitBasicType("language",
575 XML_SCHEMAS_LANGUAGE
,
576 xmlSchemaTypeTokenDef
);
577 xmlSchemaTypeNameDef
= xmlSchemaInitBasicType("Name",
579 xmlSchemaTypeTokenDef
);
580 xmlSchemaTypeNmtokenDef
= xmlSchemaInitBasicType("NMTOKEN",
582 xmlSchemaTypeTokenDef
);
583 xmlSchemaTypeNCNameDef
= xmlSchemaInitBasicType("NCName",
585 xmlSchemaTypeNameDef
);
586 xmlSchemaTypeIdDef
= xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID
,
587 xmlSchemaTypeNCNameDef
);
588 xmlSchemaTypeIdrefDef
= xmlSchemaInitBasicType("IDREF",
590 xmlSchemaTypeNCNameDef
);
591 xmlSchemaTypeEntityDef
= xmlSchemaInitBasicType("ENTITY",
593 xmlSchemaTypeNCNameDef
);
595 * Derived list types.
598 xmlSchemaTypeEntitiesDef
= xmlSchemaInitBasicType("ENTITIES",
599 XML_SCHEMAS_ENTITIES
,
600 xmlSchemaTypeAnySimpleTypeDef
);
601 xmlSchemaTypeEntitiesDef
->subtypes
= xmlSchemaTypeEntityDef
;
603 xmlSchemaTypeIdrefsDef
= xmlSchemaInitBasicType("IDREFS",
605 xmlSchemaTypeAnySimpleTypeDef
);
606 xmlSchemaTypeIdrefsDef
->subtypes
= xmlSchemaTypeIdrefDef
;
609 xmlSchemaTypeNmtokensDef
= xmlSchemaInitBasicType("NMTOKENS",
610 XML_SCHEMAS_NMTOKENS
,
611 xmlSchemaTypeAnySimpleTypeDef
);
612 xmlSchemaTypeNmtokensDef
->subtypes
= xmlSchemaTypeNmtokenDef
;
614 xmlSchemaTypesInitialized
= 1;
618 * xmlSchemaCleanupTypes:
620 * Cleanup the default XML Schemas type library
623 xmlSchemaCleanupTypes(void) {
624 if (xmlSchemaTypesInitialized
== 0)
630 xmlSchemaParticlePtr particle
;
631 /* Attribute wildcard. */
632 xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef
->attributeWildcard
);
634 particle
= (xmlSchemaParticlePtr
) xmlSchemaTypeAnyTypeDef
->subtypes
;
636 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr
)
637 particle
->children
->children
->children
);
638 xmlFree((xmlSchemaParticlePtr
) particle
->children
->children
);
639 /* Sequence model group. */
640 xmlFree((xmlSchemaModelGroupPtr
) particle
->children
);
641 xmlFree((xmlSchemaParticlePtr
) particle
);
642 xmlSchemaTypeAnyTypeDef
->subtypes
= NULL
;
644 xmlHashFree(xmlSchemaTypesBank
, (xmlHashDeallocator
) xmlSchemaFreeType
);
645 xmlSchemaTypesInitialized
= 0;
649 * xmlSchemaIsBuiltInTypeFacet:
650 * @type: the built-in type
651 * @facetType: the facet type
653 * Evaluates if a specific facet can be
654 * used in conjunction with a type.
656 * Returns 1 if the facet can be used with the given built-in type,
657 * 0 otherwise and -1 in case the type is not a built-in type.
660 xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type
, int facetType
)
664 if (type
->type
!= XML_SCHEMA_TYPE_BASIC
)
666 switch (type
->builtInType
) {
667 case XML_SCHEMAS_BOOLEAN
:
668 if ((facetType
== XML_SCHEMA_FACET_PATTERN
) ||
669 (facetType
== XML_SCHEMA_FACET_WHITESPACE
))
673 case XML_SCHEMAS_STRING
:
674 case XML_SCHEMAS_NOTATION
:
675 case XML_SCHEMAS_QNAME
:
676 case XML_SCHEMAS_ANYURI
:
677 case XML_SCHEMAS_BASE64BINARY
:
678 case XML_SCHEMAS_HEXBINARY
:
679 if ((facetType
== XML_SCHEMA_FACET_LENGTH
) ||
680 (facetType
== XML_SCHEMA_FACET_MINLENGTH
) ||
681 (facetType
== XML_SCHEMA_FACET_MAXLENGTH
) ||
682 (facetType
== XML_SCHEMA_FACET_PATTERN
) ||
683 (facetType
== XML_SCHEMA_FACET_ENUMERATION
) ||
684 (facetType
== XML_SCHEMA_FACET_WHITESPACE
))
688 case XML_SCHEMAS_DECIMAL
:
689 if ((facetType
== XML_SCHEMA_FACET_TOTALDIGITS
) ||
690 (facetType
== XML_SCHEMA_FACET_FRACTIONDIGITS
) ||
691 (facetType
== XML_SCHEMA_FACET_PATTERN
) ||
692 (facetType
== XML_SCHEMA_FACET_WHITESPACE
) ||
693 (facetType
== XML_SCHEMA_FACET_ENUMERATION
) ||
694 (facetType
== XML_SCHEMA_FACET_MAXINCLUSIVE
) ||
695 (facetType
== XML_SCHEMA_FACET_MAXEXCLUSIVE
) ||
696 (facetType
== XML_SCHEMA_FACET_MININCLUSIVE
) ||
697 (facetType
== XML_SCHEMA_FACET_MINEXCLUSIVE
))
701 case XML_SCHEMAS_TIME
:
702 case XML_SCHEMAS_GDAY
:
703 case XML_SCHEMAS_GMONTH
:
704 case XML_SCHEMAS_GMONTHDAY
:
705 case XML_SCHEMAS_GYEAR
:
706 case XML_SCHEMAS_GYEARMONTH
:
707 case XML_SCHEMAS_DATE
:
708 case XML_SCHEMAS_DATETIME
:
709 case XML_SCHEMAS_DURATION
:
710 case XML_SCHEMAS_FLOAT
:
711 case XML_SCHEMAS_DOUBLE
:
712 if ((facetType
== XML_SCHEMA_FACET_PATTERN
) ||
713 (facetType
== XML_SCHEMA_FACET_ENUMERATION
) ||
714 (facetType
== XML_SCHEMA_FACET_WHITESPACE
) ||
715 (facetType
== XML_SCHEMA_FACET_MAXINCLUSIVE
) ||
716 (facetType
== XML_SCHEMA_FACET_MAXEXCLUSIVE
) ||
717 (facetType
== XML_SCHEMA_FACET_MININCLUSIVE
) ||
718 (facetType
== XML_SCHEMA_FACET_MINEXCLUSIVE
))
729 * xmlSchemaGetBuiltInType:
730 * @type: the type of the built in type
732 * Gives you the type struct for a built-in
733 * type by its type id.
735 * Returns the type if found, NULL otherwise.
738 xmlSchemaGetBuiltInType(xmlSchemaValType type
)
740 if (xmlSchemaTypesInitialized
== 0)
741 xmlSchemaInitTypes();
744 case XML_SCHEMAS_ANYSIMPLETYPE
:
745 return (xmlSchemaTypeAnySimpleTypeDef
);
746 case XML_SCHEMAS_STRING
:
747 return (xmlSchemaTypeStringDef
);
748 case XML_SCHEMAS_NORMSTRING
:
749 return (xmlSchemaTypeNormStringDef
);
750 case XML_SCHEMAS_DECIMAL
:
751 return (xmlSchemaTypeDecimalDef
);
752 case XML_SCHEMAS_TIME
:
753 return (xmlSchemaTypeTimeDef
);
754 case XML_SCHEMAS_GDAY
:
755 return (xmlSchemaTypeGDayDef
);
756 case XML_SCHEMAS_GMONTH
:
757 return (xmlSchemaTypeGMonthDef
);
758 case XML_SCHEMAS_GMONTHDAY
:
759 return (xmlSchemaTypeGMonthDayDef
);
760 case XML_SCHEMAS_GYEAR
:
761 return (xmlSchemaTypeGYearDef
);
762 case XML_SCHEMAS_GYEARMONTH
:
763 return (xmlSchemaTypeGYearMonthDef
);
764 case XML_SCHEMAS_DATE
:
765 return (xmlSchemaTypeDateDef
);
766 case XML_SCHEMAS_DATETIME
:
767 return (xmlSchemaTypeDatetimeDef
);
768 case XML_SCHEMAS_DURATION
:
769 return (xmlSchemaTypeDurationDef
);
770 case XML_SCHEMAS_FLOAT
:
771 return (xmlSchemaTypeFloatDef
);
772 case XML_SCHEMAS_DOUBLE
:
773 return (xmlSchemaTypeDoubleDef
);
774 case XML_SCHEMAS_BOOLEAN
:
775 return (xmlSchemaTypeBooleanDef
);
776 case XML_SCHEMAS_TOKEN
:
777 return (xmlSchemaTypeTokenDef
);
778 case XML_SCHEMAS_LANGUAGE
:
779 return (xmlSchemaTypeLanguageDef
);
780 case XML_SCHEMAS_NMTOKEN
:
781 return (xmlSchemaTypeNmtokenDef
);
782 case XML_SCHEMAS_NMTOKENS
:
783 return (xmlSchemaTypeNmtokensDef
);
784 case XML_SCHEMAS_NAME
:
785 return (xmlSchemaTypeNameDef
);
786 case XML_SCHEMAS_QNAME
:
787 return (xmlSchemaTypeQNameDef
);
788 case XML_SCHEMAS_NCNAME
:
789 return (xmlSchemaTypeNCNameDef
);
791 return (xmlSchemaTypeIdDef
);
792 case XML_SCHEMAS_IDREF
:
793 return (xmlSchemaTypeIdrefDef
);
794 case XML_SCHEMAS_IDREFS
:
795 return (xmlSchemaTypeIdrefsDef
);
796 case XML_SCHEMAS_ENTITY
:
797 return (xmlSchemaTypeEntityDef
);
798 case XML_SCHEMAS_ENTITIES
:
799 return (xmlSchemaTypeEntitiesDef
);
800 case XML_SCHEMAS_NOTATION
:
801 return (xmlSchemaTypeNotationDef
);
802 case XML_SCHEMAS_ANYURI
:
803 return (xmlSchemaTypeAnyURIDef
);
804 case XML_SCHEMAS_INTEGER
:
805 return (xmlSchemaTypeIntegerDef
);
806 case XML_SCHEMAS_NPINTEGER
:
807 return (xmlSchemaTypeNonPositiveIntegerDef
);
808 case XML_SCHEMAS_NINTEGER
:
809 return (xmlSchemaTypeNegativeIntegerDef
);
810 case XML_SCHEMAS_NNINTEGER
:
811 return (xmlSchemaTypeNonNegativeIntegerDef
);
812 case XML_SCHEMAS_PINTEGER
:
813 return (xmlSchemaTypePositiveIntegerDef
);
814 case XML_SCHEMAS_INT
:
815 return (xmlSchemaTypeIntDef
);
816 case XML_SCHEMAS_UINT
:
817 return (xmlSchemaTypeUnsignedIntDef
);
818 case XML_SCHEMAS_LONG
:
819 return (xmlSchemaTypeLongDef
);
820 case XML_SCHEMAS_ULONG
:
821 return (xmlSchemaTypeUnsignedLongDef
);
822 case XML_SCHEMAS_SHORT
:
823 return (xmlSchemaTypeShortDef
);
824 case XML_SCHEMAS_USHORT
:
825 return (xmlSchemaTypeUnsignedShortDef
);
826 case XML_SCHEMAS_BYTE
:
827 return (xmlSchemaTypeByteDef
);
828 case XML_SCHEMAS_UBYTE
:
829 return (xmlSchemaTypeUnsignedByteDef
);
830 case XML_SCHEMAS_HEXBINARY
:
831 return (xmlSchemaTypeHexBinaryDef
);
832 case XML_SCHEMAS_BASE64BINARY
:
833 return (xmlSchemaTypeBase64BinaryDef
);
834 case XML_SCHEMAS_ANYTYPE
:
835 return (xmlSchemaTypeAnyTypeDef
);
842 * xmlSchemaValueAppend:
844 * @cur: the value to be appended
846 * Appends a next sibling to a list of computed values.
848 * Returns 0 if succeeded and -1 on API errors.
851 xmlSchemaValueAppend(xmlSchemaValPtr prev
, xmlSchemaValPtr cur
) {
853 if ((prev
== NULL
) || (cur
== NULL
))
860 * xmlSchemaValueGetNext:
863 * Accessor for the next sibling of a list of computed values.
865 * Returns the next value or NULL if there was none, or on
869 xmlSchemaValueGetNext(xmlSchemaValPtr cur
) {
877 * xmlSchemaValueGetAsString:
880 * Accessor for the string value of a computed value.
882 * Returns the string value or NULL if there was none, or on
886 xmlSchemaValueGetAsString(xmlSchemaValPtr val
)
891 case XML_SCHEMAS_STRING
:
892 case XML_SCHEMAS_NORMSTRING
:
893 case XML_SCHEMAS_ANYSIMPLETYPE
:
894 case XML_SCHEMAS_TOKEN
:
895 case XML_SCHEMAS_LANGUAGE
:
896 case XML_SCHEMAS_NMTOKEN
:
897 case XML_SCHEMAS_NAME
:
898 case XML_SCHEMAS_NCNAME
:
900 case XML_SCHEMAS_IDREF
:
901 case XML_SCHEMAS_ENTITY
:
902 case XML_SCHEMAS_ANYURI
:
903 return (BAD_CAST val
->value
.str
);
911 * xmlSchemaValueGetAsBoolean:
914 * Accessor for the boolean value of a computed value.
916 * Returns 1 if true and 0 if false, or in case of an error. Hmm.
919 xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val
)
921 if ((val
== NULL
) || (val
->type
!= XML_SCHEMAS_BOOLEAN
))
923 return (val
->value
.b
);
927 * xmlSchemaNewStringValue:
928 * @type: the value type
931 * Allocate a new simple type value. The type can be
932 * of XML_SCHEMAS_STRING.
933 * WARNING: This one is intended to be expanded for other
934 * string based types. We need this for anySimpleType as well.
935 * The given value is consumed and freed with the struct.
937 * Returns a pointer to the new value or NULL in case of error
940 xmlSchemaNewStringValue(xmlSchemaValType type
,
941 const xmlChar
*value
)
945 if (type
!= XML_SCHEMAS_STRING
)
947 val
= (xmlSchemaValPtr
) xmlMalloc(sizeof(xmlSchemaVal
));
951 memset(val
, 0, sizeof(xmlSchemaVal
));
953 val
->value
.str
= (xmlChar
*) value
;
958 * xmlSchemaNewNOTATIONValue:
959 * @name: the notation name
960 * @ns: the notation namespace name or NULL
962 * Allocate a new NOTATION value.
963 * The given values are consumed and freed with the struct.
965 * Returns a pointer to the new value or NULL in case of error
968 xmlSchemaNewNOTATIONValue(const xmlChar
*name
,
973 val
= xmlSchemaNewValue(XML_SCHEMAS_NOTATION
);
977 val
->value
.qname
.name
= (xmlChar
*)name
;
979 val
->value
.qname
.uri
= (xmlChar
*)ns
;
984 * xmlSchemaNewQNameValue:
985 * @namespaceName: the namespace name
986 * @localName: the local name
988 * Allocate a new QName value.
989 * The given values are consumed and freed with the struct.
991 * Returns a pointer to the new value or NULL in case of an error.
994 xmlSchemaNewQNameValue(const xmlChar
*namespaceName
,
995 const xmlChar
*localName
)
999 val
= xmlSchemaNewValue(XML_SCHEMAS_QNAME
);
1003 val
->value
.qname
.name
= (xmlChar
*) localName
;
1004 val
->value
.qname
.uri
= (xmlChar
*) namespaceName
;
1009 * xmlSchemaFreeValue:
1010 * @value: the value to free
1012 * Cleanup the default XML Schemas type library
1015 xmlSchemaFreeValue(xmlSchemaValPtr value
) {
1016 xmlSchemaValPtr prev
;
1018 while (value
!= NULL
) {
1019 switch (value
->type
) {
1020 case XML_SCHEMAS_STRING
:
1021 case XML_SCHEMAS_NORMSTRING
:
1022 case XML_SCHEMAS_TOKEN
:
1023 case XML_SCHEMAS_LANGUAGE
:
1024 case XML_SCHEMAS_NMTOKEN
:
1025 case XML_SCHEMAS_NMTOKENS
:
1026 case XML_SCHEMAS_NAME
:
1027 case XML_SCHEMAS_NCNAME
:
1028 case XML_SCHEMAS_ID
:
1029 case XML_SCHEMAS_IDREF
:
1030 case XML_SCHEMAS_IDREFS
:
1031 case XML_SCHEMAS_ENTITY
:
1032 case XML_SCHEMAS_ENTITIES
:
1033 case XML_SCHEMAS_ANYURI
:
1034 case XML_SCHEMAS_ANYSIMPLETYPE
:
1035 if (value
->value
.str
!= NULL
)
1036 xmlFree(value
->value
.str
);
1038 case XML_SCHEMAS_NOTATION
:
1039 case XML_SCHEMAS_QNAME
:
1040 if (value
->value
.qname
.uri
!= NULL
)
1041 xmlFree(value
->value
.qname
.uri
);
1042 if (value
->value
.qname
.name
!= NULL
)
1043 xmlFree(value
->value
.qname
.name
);
1045 case XML_SCHEMAS_HEXBINARY
:
1046 if (value
->value
.hex
.str
!= NULL
)
1047 xmlFree(value
->value
.hex
.str
);
1049 case XML_SCHEMAS_BASE64BINARY
:
1050 if (value
->value
.base64
.str
!= NULL
)
1051 xmlFree(value
->value
.base64
.str
);
1057 value
= value
->next
;
1063 * xmlSchemaGetPredefinedType:
1064 * @name: the type name
1065 * @ns: the URI of the namespace usually "http://www.w3.org/2001/XMLSchema"
1067 * Lookup a type in the default XML Schemas type library
1069 * Returns the type if found, NULL otherwise
1072 xmlSchemaGetPredefinedType(const xmlChar
*name
, const xmlChar
*ns
) {
1073 if (xmlSchemaTypesInitialized
== 0)
1074 xmlSchemaInitTypes();
1077 return((xmlSchemaTypePtr
) xmlHashLookup2(xmlSchemaTypesBank
, name
, ns
));
1081 * xmlSchemaGetBuiltInListSimpleTypeItemType:
1082 * @type: the built-in simple type.
1086 * Returns the item type of @type as defined by the built-in datatype
1087 * hierarchy of XML Schema Part 2: Datatypes, or NULL in case of an error.
1090 xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type
)
1092 if ((type
== NULL
) || (type
->type
!= XML_SCHEMA_TYPE_BASIC
))
1094 switch (type
->builtInType
) {
1095 case XML_SCHEMAS_NMTOKENS
:
1096 return (xmlSchemaTypeNmtokenDef
);
1097 case XML_SCHEMAS_IDREFS
:
1098 return (xmlSchemaTypeIdrefDef
);
1099 case XML_SCHEMAS_ENTITIES
:
1100 return (xmlSchemaTypeEntityDef
);
1106 /****************************************************************
1108 * Convenience macros and functions *
1110 ****************************************************************/
1112 #define IS_TZO_CHAR(c) \
1113 ((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
1115 #define VALID_YEAR(yr) (yr != 0)
1116 #define VALID_MONTH(mon) ((mon >= 1) && (mon <= 12))
1117 /* VALID_DAY should only be used when month is unknown */
1118 #define VALID_DAY(day) ((day >= 1) && (day <= 31))
1119 #define VALID_HOUR(hr) ((hr >= 0) && (hr <= 23))
1120 #define VALID_MIN(min) ((min >= 0) && (min <= 59))
1121 #define VALID_SEC(sec) ((sec >= 0) && (sec < 60))
1122 #define VALID_TZO(tzo) ((tzo > -840) && (tzo < 840))
1123 #define IS_LEAP(y) \
1124 (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
1126 static const unsigned int daysInMonth
[12] =
1127 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1128 static const unsigned int daysInMonthLeap
[12] =
1129 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1131 #define MAX_DAYINMONTH(yr,mon) \
1132 (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
1134 #define VALID_MDAY(dt) \
1135 (IS_LEAP(dt->year) ? \
1136 (dt->day <= daysInMonthLeap[dt->mon - 1]) : \
1137 (dt->day <= daysInMonth[dt->mon - 1]))
1139 #define VALID_DATE(dt) \
1140 (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
1142 #define VALID_TIME(dt) \
1143 (VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \
1144 VALID_SEC(dt->sec) && VALID_TZO(dt->tzo))
1146 #define VALID_DATETIME(dt) \
1147 (VALID_DATE(dt) && VALID_TIME(dt))
1149 #define SECS_PER_MIN (60)
1150 #define SECS_PER_HOUR (60 * SECS_PER_MIN)
1151 #define SECS_PER_DAY (24 * SECS_PER_HOUR)
1153 static const long dayInYearByMonth
[12] =
1154 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1155 static const long dayInLeapYearByMonth
[12] =
1156 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
1158 #define DAY_IN_YEAR(day, month, year) \
1160 dayInLeapYearByMonth[month - 1] : \
1161 dayInYearByMonth[month - 1]) + day)
1164 #define DEBUG_DATE(dt) \
1165 xmlGenericError(xmlGenericErrorContext, \
1166 "type=%o %04ld-%02u-%02uT%02u:%02u:%03f", \
1167 dt->type,dt->value.date.year,dt->value.date.mon, \
1168 dt->value.date.day,dt->value.date.hour,dt->value.date.min, \
1169 dt->value.date.sec); \
1170 if (dt->value.date.tz_flag) \
1171 if (dt->value.date.tzo != 0) \
1172 xmlGenericError(xmlGenericErrorContext, \
1173 "%+05d\n",dt->value.date.tzo); \
1175 xmlGenericError(xmlGenericErrorContext, "Z\n"); \
1177 xmlGenericError(xmlGenericErrorContext,"\n")
1179 #define DEBUG_DATE(dt)
1183 * _xmlSchemaParseGYear:
1184 * @dt: pointer to a date structure
1185 * @str: pointer to the string to analyze
1187 * Parses a xs:gYear without time zone and fills in the appropriate
1188 * field of the @dt structure. @str is updated to point just after the
1189 * xs:gYear. It is supposed that @dt->year is big enough to contain
1192 * Returns 0 or the error code
1195 _xmlSchemaParseGYear (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1196 const xmlChar
*cur
= *str
, *firstChar
;
1197 int isneg
= 0, digcnt
= 0;
1199 if (((*cur
< '0') || (*cur
> '9')) &&
1200 (*cur
!= '-') && (*cur
!= '+'))
1210 while ((*cur
>= '0') && (*cur
<= '9')) {
1211 dt
->year
= dt
->year
* 10 + (*cur
- '0');
1216 /* year must be at least 4 digits (CCYY); over 4
1217 * digits cannot have a leading zero. */
1218 if ((digcnt
< 4) || ((digcnt
> 4) && (*firstChar
== '0')))
1222 dt
->year
= - dt
->year
;
1224 if (!VALID_YEAR(dt
->year
))
1233 * @num: the integer to fill in
1234 * @cur: an #xmlChar *
1235 * @invalid: an integer
1237 * Parses a 2-digits integer and updates @num with the value. @cur is
1238 * updated to point just after the integer.
1239 * In case of error, @invalid is set to %TRUE, values of @num and
1240 * @cur are undefined.
1242 #define PARSE_2_DIGITS(num, cur, invalid) \
1243 if ((cur[0] < '0') || (cur[0] > '9') || \
1244 (cur[1] < '0') || (cur[1] > '9')) \
1247 num = (cur[0] - '0') * 10 + (cur[1] - '0'); \
1252 * @num: the double to fill in
1253 * @cur: an #xmlChar *
1254 * @invalid: an integer
1256 * Parses a float and updates @num with the value. @cur is
1257 * updated to point just after the float. The float must have a
1258 * 2-digits integer part and may or may not have a decimal part.
1259 * In case of error, @invalid is set to %TRUE, values of @num and
1260 * @cur are undefined.
1262 #define PARSE_FLOAT(num, cur, invalid) \
1263 PARSE_2_DIGITS(num, cur, invalid); \
1264 if (!invalid && (*cur == '.')) { \
1267 if ((*cur < '0') || (*cur > '9')) \
1269 while ((*cur >= '0') && (*cur <= '9')) { \
1271 num += (*cur - '0') * mult; \
1277 * _xmlSchemaParseGMonth:
1278 * @dt: pointer to a date structure
1279 * @str: pointer to the string to analyze
1281 * Parses a xs:gMonth without time zone and fills in the appropriate
1282 * field of the @dt structure. @str is updated to point just after the
1285 * Returns 0 or the error code
1288 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1289 const xmlChar
*cur
= *str
;
1291 unsigned int value
= 0;
1293 PARSE_2_DIGITS(value
, cur
, ret
);
1297 if (!VALID_MONTH(value
))
1307 * _xmlSchemaParseGDay:
1308 * @dt: pointer to a date structure
1309 * @str: pointer to the string to analyze
1311 * Parses a xs:gDay without time zone and fills in the appropriate
1312 * field of the @dt structure. @str is updated to point just after the
1315 * Returns 0 or the error code
1318 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1319 const xmlChar
*cur
= *str
;
1321 unsigned int value
= 0;
1323 PARSE_2_DIGITS(value
, cur
, ret
);
1327 if (!VALID_DAY(value
))
1336 * _xmlSchemaParseTime:
1337 * @dt: pointer to a date structure
1338 * @str: pointer to the string to analyze
1340 * Parses a xs:time without time zone and fills in the appropriate
1341 * fields of the @dt structure. @str is updated to point just after the
1343 * In case of error, values of @dt fields are undefined.
1345 * Returns 0 or the error code
1348 _xmlSchemaParseTime (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1349 const xmlChar
*cur
= *str
;
1353 PARSE_2_DIGITS(value
, cur
, ret
);
1358 if (!VALID_HOUR(value
))
1362 /* the ':' insures this string is xs:time */
1365 PARSE_2_DIGITS(value
, cur
, ret
);
1368 if (!VALID_MIN(value
))
1376 PARSE_FLOAT(dt
->sec
, cur
, ret
);
1380 if ((!VALID_SEC(dt
->sec
)) || (!VALID_TZO(dt
->tzo
)))
1388 * _xmlSchemaParseTimeZone:
1389 * @dt: pointer to a date structure
1390 * @str: pointer to the string to analyze
1392 * Parses a time zone without time zone and fills in the appropriate
1393 * field of the @dt structure. @str is updated to point just after the
1396 * Returns 0 or the error code
1399 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1421 int isneg
= 0, tmp
= 0;
1422 isneg
= (*cur
== '-');
1426 PARSE_2_DIGITS(tmp
, cur
, ret
);
1429 if (!VALID_HOUR(tmp
))
1438 PARSE_2_DIGITS(tmp
, cur
, ret
);
1441 if (!VALID_MIN(tmp
))
1446 dt
->tzo
= - dt
->tzo
;
1448 if (!VALID_TZO(dt
->tzo
))
1463 * _xmlSchemaBase64Decode:
1466 * Converts a base64 encoded character to its base 64 value.
1468 * Returns 0-63 (value), 64 (pad), or -1 (not recognized)
1471 _xmlSchemaBase64Decode (const xmlChar ch
) {
1472 if (('A' <= ch
) && (ch
<= 'Z')) return ch
- 'A';
1473 if (('a' <= ch
) && (ch
<= 'z')) return ch
- 'a' + 26;
1474 if (('0' <= ch
) && (ch
<= '9')) return ch
- '0' + 52;
1475 if ('+' == ch
) return 62;
1476 if ('/' == ch
) return 63;
1477 if ('=' == ch
) return 64;
1481 /****************************************************************
1483 * XML Schema Dates/Times Datatypes Handling *
1485 ****************************************************************/
1489 * @num: the integer to fill in
1490 * @cur: an #xmlChar *
1491 * @num_type: an integer flag
1493 * Parses a digits integer and updates @num with the value. @cur is
1494 * updated to point just after the integer.
1495 * In case of error, @num_type is set to -1, values of @num and
1496 * @cur are undefined.
1498 #define PARSE_DIGITS(num, cur, num_type) \
1499 if ((*cur < '0') || (*cur > '9')) \
1502 while ((*cur >= '0') && (*cur <= '9')) { \
1503 num = num * 10 + (*cur - '0'); \
1509 * @num: the double to fill in
1510 * @cur: an #xmlChar *
1511 * @num_type: an integer flag
1513 * Parses a float or integer and updates @num with the value. @cur is
1514 * updated to point just after the number. If the number is a float,
1515 * then it must have an integer part and a decimal part; @num_type will
1516 * be set to 1. If there is no decimal part, @num_type is set to zero.
1517 * In case of error, @num_type is set to -1, values of @num and
1518 * @cur are undefined.
1520 #define PARSE_NUM(num, cur, num_type) \
1522 PARSE_DIGITS(num, cur, num_type); \
1523 if (!num_type && (*cur == '.')) { \
1526 if ((*cur < '0') || (*cur > '9')) \
1530 while ((*cur >= '0') && (*cur <= '9')) { \
1532 num += (*cur - '0') * mult; \
1538 * xmlSchemaValidateDates:
1539 * @type: the expected type or XML_SCHEMAS_UNKNOWN
1540 * @dateTime: string to analyze
1541 * @val: the return computed value
1543 * Check that @dateTime conforms to the lexical space of one of the date types.
1544 * if true a value is computed and returned in @val.
1546 * Returns 0 if this validates, a positive error code number otherwise
1547 * and -1 in case of internal or API error.
1550 xmlSchemaValidateDates (xmlSchemaValType type
,
1551 const xmlChar
*dateTime
, xmlSchemaValPtr
*val
,
1555 const xmlChar
*cur
= dateTime
;
1557 #define RETURN_TYPE_IF_VALID(t) \
1558 if (IS_TZO_CHAR(*cur)) { \
1559 ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); \
1568 if (dateTime
== NULL
)
1572 while IS_WSP_BLANK_CH(*cur
) cur
++;
1574 if ((*cur
!= '-') && (*cur
< '0') && (*cur
> '9'))
1577 dt
= xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN
);
1581 if ((cur
[0] == '-') && (cur
[1] == '-')) {
1583 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
1588 /* is it an xs:gDay? */
1590 if (type
== XML_SCHEMAS_GMONTH
)
1593 ret
= _xmlSchemaParseGDay(&(dt
->value
.date
), &cur
);
1597 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY
);
1603 * it should be an xs:gMonthDay or xs:gMonth
1605 ret
= _xmlSchemaParseGMonth(&(dt
->value
.date
), &cur
);
1610 * a '-' char could indicate this type is xs:gMonthDay or
1611 * a negative time zone offset. Check for xs:gMonthDay first.
1612 * Also the first three char's of a negative tzo (-MM:SS) can
1613 * appear to be a valid day; so even if the day portion
1614 * of the xs:gMonthDay verifies, we must insure it was not
1618 const xmlChar
*rewnd
= cur
;
1621 ret
= _xmlSchemaParseGDay(&(dt
->value
.date
), &cur
);
1622 if ((ret
== 0) && ((*cur
== 0) || (*cur
!= ':'))) {
1625 * we can use the VALID_MDAY macro to validate the month
1626 * and day because the leap year test will flag year zero
1627 * as a leap year (even though zero is an invalid year).
1628 * FUTURE TODO: Zero will become valid in XML Schema 1.1
1631 if (VALID_MDAY((&(dt
->value
.date
)))) {
1633 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY
);
1640 * not xs:gMonthDay so rewind and check if just xs:gMonth
1641 * with an optional time zone.
1646 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH
);
1652 * It's a right-truncated date or an xs:time.
1653 * Try to parse an xs:time then fallback on right-truncated dates.
1655 if ((*cur
>= '0') && (*cur
<= '9')) {
1656 ret
= _xmlSchemaParseTime(&(dt
->value
.date
), &cur
);
1658 /* it's an xs:time */
1659 RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME
);
1663 /* fallback on date parsing */
1666 ret
= _xmlSchemaParseGYear(&(dt
->value
.date
), &cur
);
1670 /* is it an xs:gYear? */
1671 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR
);
1677 ret
= _xmlSchemaParseGMonth(&(dt
->value
.date
), &cur
);
1681 /* is it an xs:gYearMonth? */
1682 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH
);
1688 ret
= _xmlSchemaParseGDay(&(dt
->value
.date
), &cur
);
1689 if ((ret
!= 0) || !VALID_DATE((&(dt
->value
.date
))))
1692 /* is it an xs:date? */
1693 RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE
);
1699 /* it should be an xs:dateTime */
1700 ret
= _xmlSchemaParseTime(&(dt
->value
.date
), &cur
);
1704 ret
= _xmlSchemaParseTimeZone(&(dt
->value
.date
), &cur
);
1706 while IS_WSP_BLANK_CH(*cur
) cur
++;
1707 if ((ret
!= 0) || (*cur
!= 0) || (!(VALID_DATETIME((&(dt
->value
.date
))))))
1711 dt
->type
= XML_SCHEMAS_DATETIME
;
1715 if ((type
!= XML_SCHEMAS_UNKNOWN
) && (type
!= dt
->type
))
1719 * insure the parsed type is equal to or less significant (right
1720 * truncated) than the desired type.
1722 if ((type
!= XML_SCHEMAS_UNKNOWN
) && (type
!= dt
->type
)) {
1724 /* time only matches time */
1725 if ((type
== XML_SCHEMAS_TIME
) && (dt
->type
== XML_SCHEMAS_TIME
))
1728 if ((type
== XML_SCHEMAS_DATETIME
) &&
1729 ((dt
->type
!= XML_SCHEMAS_DATE
) ||
1730 (dt
->type
!= XML_SCHEMAS_GYEARMONTH
) ||
1731 (dt
->type
!= XML_SCHEMAS_GYEAR
)))
1734 if ((type
== XML_SCHEMAS_DATE
) &&
1735 ((dt
->type
!= XML_SCHEMAS_GYEAR
) ||
1736 (dt
->type
!= XML_SCHEMAS_GYEARMONTH
)))
1739 if ((type
== XML_SCHEMAS_GYEARMONTH
) && (dt
->type
!= XML_SCHEMAS_GYEAR
))
1742 if ((type
== XML_SCHEMAS_GMONTHDAY
) && (dt
->type
!= XML_SCHEMAS_GMONTH
))
1750 xmlSchemaFreeValue(dt
);
1756 xmlSchemaFreeValue(dt
);
1761 * xmlSchemaValidateDuration:
1762 * @type: the predefined type
1763 * @duration: string to analyze
1764 * @val: the return computed value
1766 * Check that @duration conforms to the lexical space of the duration type.
1767 * if true a value is computed and returned in @val.
1769 * Returns 0 if this validates, a positive error code number otherwise
1770 * and -1 in case of internal or API error.
1773 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED
,
1774 const xmlChar
*duration
, xmlSchemaValPtr
*val
,
1776 const xmlChar
*cur
= duration
;
1777 xmlSchemaValPtr dur
;
1779 unsigned int seq
= 0;
1781 int num_type
= 0; /* -1 = invalid, 0 = int, 1 = floating */
1782 const xmlChar desig
[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
1783 const double multi
[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
1785 if (duration
== NULL
)
1789 while IS_WSP_BLANK_CH(*cur
) cur
++;
1796 /* duration must start with 'P' (after sign) */
1803 dur
= xmlSchemaNewValue(XML_SCHEMAS_DURATION
);
1809 /* input string should be empty or invalid date/time item */
1810 if (seq
>= sizeof(desig
))
1813 /* T designator must be present for time items */
1820 } else if (seq
== 3)
1823 /* parse the number portion of the item */
1824 PARSE_NUM(num
, cur
, num_type
);
1826 if ((num_type
== -1) || (*cur
== 0))
1829 /* update duration based on item type */
1830 while (seq
< sizeof(desig
)) {
1831 if (*cur
== desig
[seq
]) {
1833 /* verify numeric type; only seconds can be float */
1834 if ((num_type
!= 0) && (seq
< (sizeof(desig
)-1)))
1839 dur
->value
.dur
.mon
= (long)num
* 12;
1842 dur
->value
.dur
.mon
+= (long)num
;
1845 /* convert to seconds using multiplier */
1846 dur
->value
.dur
.sec
+= num
* multi
[seq
];
1851 break; /* exit loop */
1853 /* no date designators found? */
1854 if ((++seq
== 3) || (seq
== 6))
1859 while IS_WSP_BLANK_CH(*cur
) cur
++;
1863 dur
->value
.dur
.mon
= -dur
->value
.dur
.mon
;
1864 dur
->value
.dur
.day
= -dur
->value
.dur
.day
;
1865 dur
->value
.dur
.sec
= -dur
->value
.dur
.sec
;
1871 xmlSchemaFreeValue(dur
);
1877 xmlSchemaFreeValue(dur
);
1885 * Removes the leading and ending spaces of a string
1887 * Returns the new string or NULL if no change was required.
1890 xmlSchemaStrip(const xmlChar
*value
) {
1891 const xmlChar
*start
= value
, *end
, *f
;
1893 if (value
== NULL
) return(NULL
);
1894 while ((*start
!= 0) && (IS_BLANK_CH(*start
))) start
++;
1896 while (*end
!= 0) end
++;
1899 while ((end
> start
) && (IS_BLANK_CH(*end
))) end
--;
1901 if ((start
== value
) && (f
== end
)) return(NULL
);
1902 return(xmlStrndup(start
, end
- start
));
1906 * xmlSchemaWhiteSpaceReplace:
1909 * Replaces 0xd, 0x9 and 0xa with a space.
1911 * Returns the new string or NULL if no change was required.
1914 xmlSchemaWhiteSpaceReplace(const xmlChar
*value
) {
1915 const xmlChar
*cur
= value
;
1916 xmlChar
*ret
= NULL
, *mcur
;
1921 while ((*cur
!= 0) &&
1922 (((*cur
) != 0xd) && ((*cur
) != 0x9) && ((*cur
) != 0xa))) {
1927 ret
= xmlStrdup(value
);
1928 /* TODO FIXME: I guess gcc will bark at this. */
1929 mcur
= (xmlChar
*) (ret
+ (cur
- value
));
1931 if ( ((*mcur
) == 0xd) || ((*mcur
) == 0x9) || ((*mcur
) == 0xa) )
1934 } while (*mcur
!= 0);
1939 * xmlSchemaCollapseString:
1942 * Removes and normalize white spaces in the string
1944 * Returns the new string or NULL if no change was required.
1947 xmlSchemaCollapseString(const xmlChar
*value
) {
1948 const xmlChar
*start
= value
, *end
, *f
;
1952 if (value
== NULL
) return(NULL
);
1953 while ((*start
!= 0) && (IS_BLANK_CH(*start
))) start
++;
1956 if ((*end
== ' ') && (IS_BLANK_CH(end
[1]))) {
1959 } else if ((*end
== 0xa) || (*end
== 0x9) || (*end
== 0xd)) {
1968 while ((end
> start
) && (IS_BLANK_CH(*end
))) end
--;
1970 if ((start
== value
) && (f
== end
)) return(NULL
);
1971 return(xmlStrndup(start
, end
- start
));
1973 start
= xmlStrdup(start
);
1974 if (start
== NULL
) return(NULL
);
1975 g
= (xmlChar
*) (start
+ col
);
1978 if (IS_BLANK_CH(*end
)) {
1980 while (IS_BLANK_CH(*end
)) end
++;
1987 return((xmlChar
*) start
);
1991 * xmlSchemaValAtomicListNode:
1992 * @type: the predefined atomic type for a token in the list
1993 * @value: the list value to check
1994 * @ret: the return computed value
1995 * @node: the node containing the value
1997 * Check that a value conforms to the lexical space of the predefined
1998 * list type. if true a value is computed and returned in @ret.
2000 * Returns the number of items if this validates, a negative error code
2004 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type
, const xmlChar
*value
,
2005 xmlSchemaValPtr
*ret
, xmlNodePtr node
) {
2006 xmlChar
*val
, *cur
, *endval
;
2010 if (value
== NULL
) {
2013 val
= xmlStrdup(value
);
2024 while (IS_BLANK_CH(*cur
)) *cur
++ = 0;
2026 if (IS_BLANK_CH(*cur
)) {
2029 while (IS_BLANK_CH(*cur
)) *cur
++ = 0;
2033 while ((*cur
!= 0) && (!IS_BLANK_CH(*cur
))) cur
++;
2036 if (nb_values
== 0) {
2042 while ((*cur
== 0) && (cur
!= endval
)) cur
++;
2043 while (cur
!= endval
) {
2044 tmp
= xmlSchemaValPredefTypeNode(type
, cur
, NULL
, node
);
2047 while (*cur
!= 0) cur
++;
2048 while ((*cur
== 0) && (cur
!= endval
)) cur
++;
2050 /* TODO what return value ? c.f. bug #158628
2061 * xmlSchemaParseUInt:
2062 * @str: pointer to the string R/W
2063 * @llo: pointer to the low result
2064 * @lmi: pointer to the mid result
2065 * @lhi: pointer to the high result
2067 * Parse an unsigned long into 3 fields.
2069 * Returns the number of significant digits in the number or
2070 * -1 if overflow of the capacity and -2 if it's not a number.
2073 xmlSchemaParseUInt(const xmlChar
**str
, unsigned long *llo
,
2074 unsigned long *lmi
, unsigned long *lhi
) {
2075 unsigned long lo
= 0, mi
= 0, hi
= 0;
2076 const xmlChar
*tmp
, *cur
= *str
;
2079 if (!((*cur
>= '0') && (*cur
<= '9')))
2082 while (*cur
== '0') { /* ignore leading zeroes */
2086 while ((*tmp
!= 0) && (*tmp
>= '0') && (*tmp
<= '9')) {
2094 hi
= hi
* 10 + (*cur
++ - '0');
2098 mi
= mi
* 10 + (*cur
++ - '0');
2102 lo
= lo
* 10 + (*cur
++ - '0');
2114 * xmlSchemaValAtomicType:
2115 * @type: the predefined type
2116 * @value: the value to check
2117 * @val: the return computed value
2118 * @node: the node containing the value
2119 * flags: flags to control the vlidation
2121 * Check that a value conforms to the lexical space of the atomic type.
2122 * if true a value is computed and returned in @val.
2123 * This checks the value space for list types as well (IDREFS, NMTOKENS).
2125 * Returns 0 if this validates, a positive error code number otherwise
2126 * and -1 in case of internal or API error.
2129 xmlSchemaValAtomicType(xmlSchemaTypePtr type
, const xmlChar
* value
,
2130 xmlSchemaValPtr
* val
, xmlNodePtr node
, int flags
,
2131 xmlSchemaWhitespaceValueType ws
,
2132 int normOnTheFly
, int applyNorm
, int createStringValue
)
2135 xmlChar
*norm
= NULL
;
2138 if (xmlSchemaTypesInitialized
== 0)
2139 xmlSchemaInitTypes();
2144 * validating a non existant text node is similar to validating
2148 value
= BAD_CAST
"";
2152 if ((flags
== 0) && (value
!= NULL
)) {
2154 if ((type
->builtInType
!= XML_SCHEMAS_STRING
) &&
2155 (type
->builtInType
!= XML_SCHEMAS_ANYTYPE
) &&
2156 (type
->builtInType
!= XML_SCHEMAS_ANYSIMPLETYPE
)) {
2157 if (type
->builtInType
== XML_SCHEMAS_NORMSTRING
)
2158 norm
= xmlSchemaWhiteSpaceReplace(value
);
2160 norm
= xmlSchemaCollapseString(value
);
2166 switch (type
->builtInType
) {
2167 case XML_SCHEMAS_UNKNOWN
:
2169 case XML_SCHEMAS_ANYTYPE
:
2170 case XML_SCHEMAS_ANYSIMPLETYPE
:
2171 if ((createStringValue
) && (val
!= NULL
)) {
2172 v
= xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE
);
2174 v
->value
.str
= xmlStrdup(value
);
2181 case XML_SCHEMAS_STRING
:
2182 if (! normOnTheFly
) {
2183 const xmlChar
*cur
= value
;
2185 if (ws
== XML_SCHEMA_WHITESPACE_REPLACE
) {
2187 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2193 } else if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
) {
2195 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2197 } else if IS_WSP_SPACE_CH(*cur
) {
2199 if IS_WSP_SPACE_CH(*cur
)
2207 if (createStringValue
&& (val
!= NULL
)) {
2209 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
2210 norm
= xmlSchemaCollapseString(value
);
2211 else if (ws
== XML_SCHEMA_WHITESPACE_REPLACE
)
2212 norm
= xmlSchemaWhiteSpaceReplace(value
);
2216 v
= xmlSchemaNewValue(XML_SCHEMAS_STRING
);
2218 v
->value
.str
= xmlStrdup(value
);
2225 case XML_SCHEMAS_NORMSTRING
:{
2228 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
2229 norm
= xmlSchemaCollapseString(value
);
2231 norm
= xmlSchemaWhiteSpaceReplace(value
);
2236 const xmlChar
*cur
= value
;
2238 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2246 v
= xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING
);
2248 v
->value
.str
= xmlStrdup(value
);
2256 case XML_SCHEMAS_DECIMAL
:{
2257 const xmlChar
*cur
= value
;
2258 unsigned int len
, neg
, integ
, hasLeadingZeroes
;
2260 xmlChar
*cptr
= cval
;
2262 if ((cur
== NULL
) || (*cur
== 0))
2266 * xs:decimal has a whitespace-facet value of 'collapse'.
2269 while IS_WSP_BLANK_CH(*cur
) cur
++;
2272 * First we handle an optional sign.
2278 } else if (*cur
== '+')
2281 * Disallow: "", "-", "- "
2286 * Next we "pre-parse" the number, in preparation for calling
2287 * the common routine xmlSchemaParseUInt. We get rid of any
2288 * leading zeroes (because we have reserved only 25 chars),
2289 * and note the position of a decimal point.
2293 hasLeadingZeroes
= 0;
2295 * Skip leading zeroes.
2297 while (*cur
== '0') {
2299 hasLeadingZeroes
= 1;
2303 if ((*cur
>= '0') && (*cur
<= '9')) {
2306 } else if (*cur
== '.') {
2310 if ((*cur
>= '0') && (*cur
<= '9')) {
2317 * Disallow "." but allow "00."
2319 if ((len
== 0) && (!hasLeadingZeroes
))
2327 while IS_WSP_BLANK_CH(*cur
) cur
++;
2329 goto return1
; /* error if any extraneous chars */
2331 v
= xmlSchemaNewValue(XML_SCHEMAS_DECIMAL
);
2334 * Now evaluate the significant digits of the number
2340 * Get rid of trailing zeroes in the
2343 while ((len
!= integ
) && (*(cptr
-1) == '0')) {
2349 * Terminate the (preparsed) string.
2355 xmlSchemaParseUInt((const xmlChar
**)&cptr
,
2356 &v
->value
.decimal
.lo
,
2357 &v
->value
.decimal
.mi
,
2358 &v
->value
.decimal
.hi
);
2362 * Set the total digits to 1 if a zero value.
2364 v
->value
.decimal
.sign
= neg
;
2366 /* Speedup for zero values. */
2367 v
->value
.decimal
.total
= 1;
2369 v
->value
.decimal
.total
= len
;
2371 v
->value
.decimal
.frac
= 0;
2373 v
->value
.decimal
.frac
= len
- integ
;
2380 case XML_SCHEMAS_TIME
:
2381 case XML_SCHEMAS_GDAY
:
2382 case XML_SCHEMAS_GMONTH
:
2383 case XML_SCHEMAS_GMONTHDAY
:
2384 case XML_SCHEMAS_GYEAR
:
2385 case XML_SCHEMAS_GYEARMONTH
:
2386 case XML_SCHEMAS_DATE
:
2387 case XML_SCHEMAS_DATETIME
:
2388 ret
= xmlSchemaValidateDates(type
->builtInType
, value
, val
,
2391 case XML_SCHEMAS_DURATION
:
2392 ret
= xmlSchemaValidateDuration(type
, value
, val
,
2395 case XML_SCHEMAS_FLOAT
:
2396 case XML_SCHEMAS_DOUBLE
: {
2397 const xmlChar
*cur
= value
;
2399 int digits_before
= 0;
2400 int digits_after
= 0;
2403 while IS_WSP_BLANK_CH(*cur
) cur
++;
2405 if ((cur
[0] == 'N') && (cur
[1] == 'a') && (cur
[2] == 'N')) {
2410 if (type
== xmlSchemaTypeFloatDef
) {
2411 v
= xmlSchemaNewValue(XML_SCHEMAS_FLOAT
);
2413 v
->value
.f
= (float) xmlXPathNAN
;
2415 xmlSchemaFreeValue(v
);
2419 v
= xmlSchemaNewValue(XML_SCHEMAS_DOUBLE
);
2421 v
->value
.d
= xmlXPathNAN
;
2423 xmlSchemaFreeValue(v
);
2435 if ((cur
[0] == 'I') && (cur
[1] == 'N') && (cur
[2] == 'F')) {
2440 if (type
== xmlSchemaTypeFloatDef
) {
2441 v
= xmlSchemaNewValue(XML_SCHEMAS_FLOAT
);
2444 v
->value
.f
= (float) xmlXPathNINF
;
2446 v
->value
.f
= (float) xmlXPathPINF
;
2448 xmlSchemaFreeValue(v
);
2452 v
= xmlSchemaNewValue(XML_SCHEMAS_DOUBLE
);
2455 v
->value
.d
= xmlXPathNINF
;
2457 v
->value
.d
= xmlXPathPINF
;
2459 xmlSchemaFreeValue(v
);
2467 if ((neg
== 0) && (*cur
== '+'))
2469 if ((cur
[0] == 0) || (cur
[0] == '+') || (cur
[0] == '-'))
2471 while ((*cur
>= '0') && (*cur
<= '9')) {
2477 while ((*cur
>= '0') && (*cur
<= '9')) {
2482 if ((digits_before
== 0) && (digits_after
== 0))
2484 if ((*cur
== 'e') || (*cur
== 'E')) {
2486 if ((*cur
== '-') || (*cur
== '+'))
2488 while ((*cur
>= '0') && (*cur
<= '9'))
2492 while IS_WSP_BLANK_CH(*cur
) cur
++;
2497 if (type
== xmlSchemaTypeFloatDef
) {
2498 v
= xmlSchemaNewValue(XML_SCHEMAS_FLOAT
);
2501 * TODO: sscanf seems not to give the correct
2502 * value for extremely high/low values.
2503 * E.g. "1E-149" results in zero.
2505 if (sscanf((const char *) value
, "%f",
2506 &(v
->value
.f
)) == 1) {
2509 xmlSchemaFreeValue(v
);
2516 v
= xmlSchemaNewValue(XML_SCHEMAS_DOUBLE
);
2519 * TODO: sscanf seems not to give the correct
2520 * value for extremely high/low values.
2522 if (sscanf((const char *) value
, "%lf",
2523 &(v
->value
.d
)) == 1) {
2526 xmlSchemaFreeValue(v
);
2536 case XML_SCHEMAS_BOOLEAN
:{
2537 const xmlChar
*cur
= value
;
2540 while IS_WSP_BLANK_CH(*cur
) cur
++;
2544 } else if (*cur
== '1') {
2547 } else if (*cur
== 't') {
2549 if ((*cur
++ == 'r') && (*cur
++ == 'u') &&
2554 } else if (*cur
== 'f') {
2556 if ((*cur
++ == 'a') && (*cur
++ == 'l') &&
2557 (*cur
++ == 's') && (*cur
++ == 'e')) {
2564 while IS_WSP_BLANK_CH(*cur
) cur
++;
2569 if ((cur
[0] == '0') && (cur
[1] == 0))
2571 else if ((cur
[0] == '1') && (cur
[1] == 0))
2573 else if ((cur
[0] == 't') && (cur
[1] == 'r')
2574 && (cur
[2] == 'u') && (cur
[3] == 'e')
2577 else if ((cur
[0] == 'f') && (cur
[1] == 'a')
2578 && (cur
[2] == 'l') && (cur
[3] == 's')
2579 && (cur
[4] == 'e') && (cur
[5] == 0))
2585 v
= xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN
);
2595 case XML_SCHEMAS_TOKEN
:{
2596 const xmlChar
*cur
= value
;
2598 if (! normOnTheFly
) {
2600 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2602 } else if (*cur
== ' ') {
2614 v
= xmlSchemaNewValue(XML_SCHEMAS_TOKEN
);
2616 v
->value
.str
= xmlStrdup(value
);
2624 case XML_SCHEMAS_LANGUAGE
:
2626 norm
= xmlSchemaCollapseString(value
);
2630 if (xmlCheckLanguageID(value
) == 1) {
2632 v
= xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE
);
2634 v
->value
.str
= xmlStrdup(value
);
2643 case XML_SCHEMAS_NMTOKEN
:
2644 if (xmlValidateNMToken(value
, 1) == 0) {
2646 v
= xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN
);
2648 v
->value
.str
= xmlStrdup(value
);
2657 case XML_SCHEMAS_NMTOKENS
:
2658 ret
= xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef
,
2665 case XML_SCHEMAS_NAME
:
2666 ret
= xmlValidateName(value
, 1);
2667 if ((ret
== 0) && (val
!= NULL
) && (value
!= NULL
)) {
2668 v
= xmlSchemaNewValue(XML_SCHEMAS_NAME
);
2670 const xmlChar
*start
= value
, *end
;
2671 while (IS_BLANK_CH(*start
)) start
++;
2673 while ((*end
!= 0) && (!IS_BLANK_CH(*end
))) end
++;
2674 v
->value
.str
= xmlStrndup(start
, end
- start
);
2681 case XML_SCHEMAS_QNAME
:{
2682 const xmlChar
*uri
= NULL
;
2683 xmlChar
*local
= NULL
;
2685 ret
= xmlValidateQName(value
, 1);
2692 local
= xmlSplitQName2(value
, &prefix
);
2693 ns
= xmlSearchNs(node
->doc
, node
, prefix
);
2694 if ((ns
== NULL
) && (prefix
!= NULL
)) {
2706 v
= xmlSchemaNewValue(XML_SCHEMAS_QNAME
);
2713 v
->value
.qname
.name
= local
;
2715 v
->value
.qname
.name
= xmlStrdup(value
);
2717 v
->value
.qname
.uri
= xmlStrdup(uri
);
2724 case XML_SCHEMAS_NCNAME
:
2725 ret
= xmlValidateNCName(value
, 1);
2726 if ((ret
== 0) && (val
!= NULL
)) {
2727 v
= xmlSchemaNewValue(XML_SCHEMAS_NCNAME
);
2729 v
->value
.str
= xmlStrdup(value
);
2736 case XML_SCHEMAS_ID
:
2737 ret
= xmlValidateNCName(value
, 1);
2738 if ((ret
== 0) && (val
!= NULL
)) {
2739 v
= xmlSchemaNewValue(XML_SCHEMAS_ID
);
2741 v
->value
.str
= xmlStrdup(value
);
2747 if ((ret
== 0) && (node
!= NULL
) &&
2748 (node
->type
== XML_ATTRIBUTE_NODE
)) {
2749 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
2752 * NOTE: the IDness might have already be declared in the DTD
2754 if (attr
->atype
!= XML_ATTRIBUTE_ID
) {
2758 strip
= xmlSchemaStrip(value
);
2759 if (strip
!= NULL
) {
2760 res
= xmlAddID(NULL
, node
->doc
, strip
, attr
);
2763 res
= xmlAddID(NULL
, node
->doc
, value
, attr
);
2767 attr
->atype
= XML_ATTRIBUTE_ID
;
2772 case XML_SCHEMAS_IDREF
:
2773 ret
= xmlValidateNCName(value
, 1);
2774 if ((ret
== 0) && (val
!= NULL
)) {
2775 v
= xmlSchemaNewValue(XML_SCHEMAS_IDREF
);
2778 v
->value
.str
= xmlStrdup(value
);
2781 if ((ret
== 0) && (node
!= NULL
) &&
2782 (node
->type
== XML_ATTRIBUTE_NODE
)) {
2783 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
2786 strip
= xmlSchemaStrip(value
);
2787 if (strip
!= NULL
) {
2788 xmlAddRef(NULL
, node
->doc
, strip
, attr
);
2791 xmlAddRef(NULL
, node
->doc
, value
, attr
);
2792 attr
->atype
= XML_ATTRIBUTE_IDREF
;
2795 case XML_SCHEMAS_IDREFS
:
2796 ret
= xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef
,
2802 if ((ret
== 0) && (node
!= NULL
) &&
2803 (node
->type
== XML_ATTRIBUTE_NODE
)) {
2804 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
2806 attr
->atype
= XML_ATTRIBUTE_IDREFS
;
2809 case XML_SCHEMAS_ENTITY
:{
2812 ret
= xmlValidateNCName(value
, 1);
2813 if ((node
== NULL
) || (node
->doc
== NULL
))
2818 strip
= xmlSchemaStrip(value
);
2819 if (strip
!= NULL
) {
2820 ent
= xmlGetDocEntity(node
->doc
, strip
);
2823 ent
= xmlGetDocEntity(node
->doc
, value
);
2825 if ((ent
== NULL
) ||
2827 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
))
2830 if ((ret
== 0) && (val
!= NULL
)) {
2833 if ((ret
== 0) && (node
!= NULL
) &&
2834 (node
->type
== XML_ATTRIBUTE_NODE
)) {
2835 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
2837 attr
->atype
= XML_ATTRIBUTE_ENTITY
;
2841 case XML_SCHEMAS_ENTITIES
:
2842 if ((node
== NULL
) || (node
->doc
== NULL
))
2844 ret
= xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef
,
2850 if ((ret
== 0) && (node
!= NULL
) &&
2851 (node
->type
== XML_ATTRIBUTE_NODE
)) {
2852 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
2854 attr
->atype
= XML_ATTRIBUTE_ENTITIES
;
2857 case XML_SCHEMAS_NOTATION
:{
2858 xmlChar
*uri
= NULL
;
2859 xmlChar
*local
= NULL
;
2861 ret
= xmlValidateQName(value
, 1);
2862 if ((ret
== 0) && (node
!= NULL
)) {
2865 local
= xmlSplitQName2(value
, &prefix
);
2866 if (prefix
!= NULL
) {
2869 ns
= xmlSearchNs(node
->doc
, node
, prefix
);
2872 else if (val
!= NULL
)
2873 uri
= xmlStrdup(ns
->href
);
2875 if ((local
!= NULL
) && ((val
== NULL
) || (ret
!= 0)))
2880 if ((node
== NULL
) || (node
->doc
== NULL
))
2883 ret
= xmlValidateNotationUse(NULL
, node
->doc
, value
);
2889 if ((ret
== 0) && (val
!= NULL
)) {
2890 v
= xmlSchemaNewValue(XML_SCHEMAS_NOTATION
);
2893 v
->value
.qname
.name
= local
;
2895 v
->value
.qname
.name
= xmlStrdup(value
);
2897 v
->value
.qname
.uri
= uri
;
2910 case XML_SCHEMAS_ANYURI
:{
2913 xmlChar
*tmpval
, *cur
;
2915 norm
= xmlSchemaCollapseString(value
);
2919 tmpval
= xmlStrdup(value
);
2920 for (cur
= tmpval
; *cur
; ++cur
) {
2921 if (*cur
< 32 || *cur
>= 127 || *cur
== ' ' ||
2922 *cur
== '<' || *cur
== '>' || *cur
== '"' ||
2923 *cur
== '{' || *cur
== '}' || *cur
== '|' ||
2924 *cur
== '\\' || *cur
== '^' || *cur
== '`' ||
2928 uri
= xmlParseURI((const char *) tmpval
);
2936 v
= xmlSchemaNewValue(XML_SCHEMAS_ANYURI
);
2939 v
->value
.str
= xmlStrdup(value
);
2944 case XML_SCHEMAS_HEXBINARY
:{
2945 const xmlChar
*cur
= value
, *start
;
2953 while IS_WSP_BLANK_CH(*cur
) cur
++;
2956 while (((*cur
>= '0') && (*cur
<= '9')) ||
2957 ((*cur
>= 'A') && (*cur
<= 'F')) ||
2958 ((*cur
>= 'a') && (*cur
<= 'f'))) {
2963 while IS_WSP_BLANK_CH(*cur
) cur
++;
2972 v
= xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY
);
2976 * Copy only the normalized piece.
2977 * CRITICAL TODO: Check this.
2979 cur
= xmlStrndup(start
, i
);
2981 xmlSchemaTypeErrMemory(node
, "allocating hexbin data");
2986 total
= i
/ 2; /* number of octets */
2988 base
= (xmlChar
*) cur
;
2991 *base
= *base
- ('a' - 'A');
2995 v
->value
.hex
.str
= (xmlChar
*) cur
;
2996 v
->value
.hex
.total
= total
;
3001 case XML_SCHEMAS_BASE64BINARY
:{
3004 * Ignore all stray characters? (yes, currently)
3005 * Worry about long lines? (no, currently)
3009 * "The encoded output stream must be represented in lines of
3010 * no more than 76 characters each. All line breaks or other
3011 * characters not found in Table 1 must be ignored by decoding
3012 * software. In base64 data, characters other than those in
3013 * Table 1, line breaks, and other white space probably
3014 * indicate a transmission error, about which a warning
3015 * message or even a message rejection might be appropriate
3016 * under some circumstances." */
3017 const xmlChar
*cur
= value
;
3019 int total
, i
= 0, pad
= 0;
3024 for (; *cur
; ++cur
) {
3027 decc
= _xmlSchemaBase64Decode(*cur
);
3034 for (; *cur
; ++cur
) {
3037 decc
= _xmlSchemaBase64Decode(*cur
);
3045 /* rfc2045.txt: "Special processing is performed if fewer than
3046 * 24 bits are available at the end of the data being encoded.
3047 * A full encoding quantum is always completed at the end of a
3048 * body. When fewer than 24 input bits are available in an
3049 * input group, zero bits are added (on the right) to form an
3050 * integral number of 6-bit groups. Padding at the end of the
3051 * data is performed using the "=" character. Since all
3052 * base64 input is an integral number of octets, only the
3053 * following cases can arise: (1) the final quantum of
3054 * encoding input is an integral multiple of 24 bits; here,
3055 * the final unit of encoded output will be an integral
3056 * multiple ofindent: Standard input:701: Warning:old style
3057 * assignment ambiguity in "=*". Assuming "= *" 4 characters
3058 * with no "=" padding, (2) the final
3059 * quantum of encoding input is exactly 8 bits; here, the
3060 * final unit of encoded output will be two characters
3061 * followed by two "=" padding characters, or (3) the final
3062 * quantum of encoding input is exactly 16 bits; here, the
3063 * final unit of encoded output will be three characters
3064 * followed by one "=" padding character." */
3066 total
= 3 * (i
/ 4);
3070 } else if (pad
== 1) {
3075 for (decc
= _xmlSchemaBase64Decode(*cur
);
3076 (decc
< 0) || (decc
> 63);
3077 decc
= _xmlSchemaBase64Decode(*cur
))
3079 /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
3080 /* 00111100 -> 0x3c */
3084 } else if (pad
== 2) {
3089 for (decc
= _xmlSchemaBase64Decode(*cur
);
3090 (decc
< 0) || (decc
> 63);
3091 decc
= _xmlSchemaBase64Decode(*cur
))
3093 /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
3094 /* 00110000 -> 0x30 */
3102 v
= xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY
);
3106 (xmlChar
*) xmlMallocAtomic((i
+ pad
+ 1) *
3109 xmlSchemaTypeErrMemory(node
, "allocating base64 data");
3113 v
->value
.base64
.str
= base
;
3114 for (cur
= value
; *cur
; ++cur
)
3115 if (_xmlSchemaBase64Decode(*cur
) >= 0) {
3120 v
->value
.base64
.total
= total
;
3125 case XML_SCHEMAS_INTEGER
:
3126 case XML_SCHEMAS_PINTEGER
:
3127 case XML_SCHEMAS_NPINTEGER
:
3128 case XML_SCHEMAS_NINTEGER
:
3129 case XML_SCHEMAS_NNINTEGER
:{
3130 const xmlChar
*cur
= value
;
3131 unsigned long lo
, mi
, hi
;
3137 while IS_WSP_BLANK_CH(*cur
) cur
++;
3141 } else if (*cur
== '+')
3143 ret
= xmlSchemaParseUInt(&cur
, &lo
, &mi
, &hi
);
3147 while IS_WSP_BLANK_CH(*cur
) cur
++;
3150 if (type
->builtInType
== XML_SCHEMAS_NPINTEGER
) {
3152 ((hi
!= 0) || (mi
!= 0) || (lo
!= 0)))
3154 } else if (type
->builtInType
== XML_SCHEMAS_PINTEGER
) {
3157 if ((hi
== 0) && (mi
== 0) && (lo
== 0))
3159 } else if (type
->builtInType
== XML_SCHEMAS_NINTEGER
) {
3162 if ((hi
== 0) && (mi
== 0) && (lo
== 0))
3164 } else if (type
->builtInType
== XML_SCHEMAS_NNINTEGER
) {
3166 ((hi
!= 0) || (mi
!= 0) || (lo
!= 0)))
3170 v
= xmlSchemaNewValue(type
->builtInType
);
3174 v
->value
.decimal
.lo
= lo
;
3175 v
->value
.decimal
.mi
= mi
;
3176 v
->value
.decimal
.hi
= hi
;
3177 v
->value
.decimal
.sign
= sign
;
3178 v
->value
.decimal
.frac
= 0;
3179 v
->value
.decimal
.total
= ret
;
3185 case XML_SCHEMAS_LONG
:
3186 case XML_SCHEMAS_BYTE
:
3187 case XML_SCHEMAS_SHORT
:
3188 case XML_SCHEMAS_INT
:{
3189 const xmlChar
*cur
= value
;
3190 unsigned long lo
, mi
, hi
;
3198 } else if (*cur
== '+')
3200 ret
= xmlSchemaParseUInt(&cur
, &lo
, &mi
, &hi
);
3205 if (type
->builtInType
== XML_SCHEMAS_LONG
) {
3209 if (mi
>= 33720368) {
3212 if ((sign
== 0) && (lo
> 54775807))
3214 if ((sign
== 1) && (lo
> 54775808))
3218 } else if (type
->builtInType
== XML_SCHEMAS_INT
) {
3224 if ((sign
== 0) && (lo
> 47483647))
3226 if ((sign
== 1) && (lo
> 47483648))
3229 } else if (type
->builtInType
== XML_SCHEMAS_SHORT
) {
3230 if ((mi
!= 0) || (hi
!= 0))
3232 if ((sign
== 1) && (lo
> 32768))
3234 if ((sign
== 0) && (lo
> 32767))
3236 } else if (type
->builtInType
== XML_SCHEMAS_BYTE
) {
3237 if ((mi
!= 0) || (hi
!= 0))
3239 if ((sign
== 1) && (lo
> 128))
3241 if ((sign
== 0) && (lo
> 127))
3245 v
= xmlSchemaNewValue(type
->builtInType
);
3247 v
->value
.decimal
.lo
= lo
;
3248 v
->value
.decimal
.mi
= mi
;
3249 v
->value
.decimal
.hi
= hi
;
3250 v
->value
.decimal
.sign
= sign
;
3251 v
->value
.decimal
.frac
= 0;
3252 v
->value
.decimal
.total
= ret
;
3258 case XML_SCHEMAS_UINT
:
3259 case XML_SCHEMAS_ULONG
:
3260 case XML_SCHEMAS_USHORT
:
3261 case XML_SCHEMAS_UBYTE
:{
3262 const xmlChar
*cur
= value
;
3263 unsigned long lo
, mi
, hi
;
3267 ret
= xmlSchemaParseUInt(&cur
, &lo
, &mi
, &hi
);
3272 if (type
->builtInType
== XML_SCHEMAS_ULONG
) {
3276 if (mi
>= 67440737) {
3283 } else if (type
->builtInType
== XML_SCHEMAS_UINT
) {
3292 } else if (type
->builtInType
== XML_SCHEMAS_USHORT
) {
3293 if ((mi
!= 0) || (hi
!= 0))
3297 } else if (type
->builtInType
== XML_SCHEMAS_UBYTE
) {
3298 if ((mi
!= 0) || (hi
!= 0))
3304 v
= xmlSchemaNewValue(type
->builtInType
);
3306 v
->value
.decimal
.lo
= lo
;
3307 v
->value
.decimal
.mi
= mi
;
3308 v
->value
.decimal
.hi
= hi
;
3309 v
->value
.decimal
.sign
= 0;
3310 v
->value
.decimal
.frac
= 0;
3311 v
->value
.decimal
.total
= ret
;
3342 * xmlSchemaValPredefTypeNode:
3343 * @type: the predefined type
3344 * @value: the value to check
3345 * @val: the return computed value
3346 * @node: the node containing the value
3348 * Check that a value conforms to the lexical space of the predefined type.
3349 * if true a value is computed and returned in @val.
3351 * Returns 0 if this validates, a positive error code number otherwise
3352 * and -1 in case of internal or API error.
3355 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type
, const xmlChar
*value
,
3356 xmlSchemaValPtr
*val
, xmlNodePtr node
) {
3357 return(xmlSchemaValAtomicType(type
, value
, val
, node
, 0,
3358 XML_SCHEMA_WHITESPACE_UNKNOWN
, 1, 1, 0));
3362 * xmlSchemaValPredefTypeNodeNoNorm:
3363 * @type: the predefined type
3364 * @value: the value to check
3365 * @val: the return computed value
3366 * @node: the node containing the value
3368 * Check that a value conforms to the lexical space of the predefined type.
3369 * if true a value is computed and returned in @val.
3370 * This one does apply any normalization to the value.
3372 * Returns 0 if this validates, a positive error code number otherwise
3373 * and -1 in case of internal or API error.
3376 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type
, const xmlChar
*value
,
3377 xmlSchemaValPtr
*val
, xmlNodePtr node
) {
3378 return(xmlSchemaValAtomicType(type
, value
, val
, node
, 1,
3379 XML_SCHEMA_WHITESPACE_UNKNOWN
, 1, 0, 1));
3383 * xmlSchemaValidatePredefinedType:
3384 * @type: the predefined type
3385 * @value: the value to check
3386 * @val: the return computed value
3388 * Check that a value conforms to the lexical space of the predefined type.
3389 * if true a value is computed and returned in @val.
3391 * Returns 0 if this validates, a positive error code number otherwise
3392 * and -1 in case of internal or API error.
3395 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type
, const xmlChar
*value
,
3396 xmlSchemaValPtr
*val
) {
3397 return(xmlSchemaValPredefTypeNode(type
, value
, val
, NULL
));
3401 * xmlSchemaCompareDecimals:
3402 * @x: a first decimal value
3403 * @y: a second decimal value
3405 * Compare 2 decimals
3407 * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
3410 xmlSchemaCompareDecimals(xmlSchemaValPtr x
, xmlSchemaValPtr y
)
3412 xmlSchemaValPtr swp
;
3413 int order
= 1, integx
, integy
, dlen
;
3414 unsigned long hi
, mi
, lo
;
3417 * First test: If x is -ve and not zero
3419 if ((x
->value
.decimal
.sign
) &&
3420 ((x
->value
.decimal
.lo
!= 0) ||
3421 (x
->value
.decimal
.mi
!= 0) ||
3422 (x
->value
.decimal
.hi
!= 0))) {
3424 * Then if y is -ve and not zero reverse the compare
3426 if ((y
->value
.decimal
.sign
) &&
3427 ((y
->value
.decimal
.lo
!= 0) ||
3428 (y
->value
.decimal
.mi
!= 0) ||
3429 (y
->value
.decimal
.hi
!= 0)))
3432 * Otherwise (y >= 0) we have the answer
3437 * If x is not -ve and y is -ve we have the answer
3439 } else if ((y
->value
.decimal
.sign
) &&
3440 ((y
->value
.decimal
.lo
!= 0) ||
3441 (y
->value
.decimal
.mi
!= 0) ||
3442 (y
->value
.decimal
.hi
!= 0))) {
3446 * If it's not simply determined by a difference in sign,
3447 * then we need to compare the actual values of the two nums.
3448 * To do this, we start by looking at the integral parts.
3449 * If the number of integral digits differ, then we have our
3452 integx
= x
->value
.decimal
.total
- x
->value
.decimal
.frac
;
3453 integy
= y
->value
.decimal
.total
- y
->value
.decimal
.frac
;
3455 * NOTE: We changed the "total" for values like "0.1"
3456 * (or "-0.1" or ".1") to be 1, which was 2 previously.
3457 * Therefore the special case, when such values are
3458 * compared with 0, needs to be handled separately;
3459 * otherwise a zero would be recognized incorrectly as
3460 * greater than those values. This has the nice side effect
3461 * that we gain an overall optimized comparison with zeroes.
3462 * Note that a "0" has a "total" of 1 already.
3465 if (x
->value
.decimal
.lo
== 0) {
3468 else if (y
->value
.decimal
.lo
!= 0)
3475 if (y
->value
.decimal
.lo
== 0) {
3478 else if (x
->value
.decimal
.lo
!= 0)
3485 if (integx
> integy
)
3487 else if (integy
> integx
)
3491 * If the number of integral digits is the same for both numbers,
3492 * then things get a little more complicated. We need to "normalize"
3493 * the numbers in order to properly compare them. To do this, we
3494 * look at the total length of each number (length => number of
3495 * significant digits), and divide the "shorter" by 10 (decreasing
3496 * the length) until they are of equal length.
3498 dlen
= x
->value
.decimal
.total
- y
->value
.decimal
.total
;
3499 if (dlen
< 0) { /* y has more digits than x */
3501 hi
= y
->value
.decimal
.hi
;
3502 mi
= y
->value
.decimal
.mi
;
3503 lo
= y
->value
.decimal
.lo
;
3506 } else { /* x has more digits than y */
3508 hi
= x
->value
.decimal
.hi
;
3509 mi
= x
->value
.decimal
.mi
;
3510 lo
= x
->value
.decimal
.lo
;
3512 while (dlen
> 8) { /* in effect, right shift by 10**8 */
3519 unsigned long rem1
, rem2
;
3520 rem1
= (hi
% 10) * 100000000L;
3522 rem2
= (mi
% 10) * 100000000L;
3523 mi
= (mi
+ rem1
) / 10;
3524 lo
= (lo
+ rem2
) / 10;
3527 if (hi
> swp
->value
.decimal
.hi
) {
3529 } else if (hi
== swp
->value
.decimal
.hi
) {
3530 if (mi
> swp
->value
.decimal
.mi
) {
3532 } else if (mi
== swp
->value
.decimal
.mi
) {
3533 if (lo
> swp
->value
.decimal
.lo
) {
3535 } else if (lo
== swp
->value
.decimal
.lo
) {
3536 if (x
->value
.decimal
.total
== y
->value
.decimal
.total
) {
3548 * xmlSchemaCompareDurations:
3549 * @x: a first duration value
3550 * @y: a second duration value
3552 * Compare 2 durations
3554 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3558 xmlSchemaCompareDurations(xmlSchemaValPtr x
, xmlSchemaValPtr y
)
3560 long carry
, mon
, day
;
3563 long xmon
, xday
, myear
, minday
, maxday
;
3564 static const long dayRange
[2][12] = {
3565 { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
3566 { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
3568 if ((x
== NULL
) || (y
== NULL
))
3572 mon
= x
->value
.dur
.mon
- y
->value
.dur
.mon
;
3575 sec
= x
->value
.dur
.sec
- y
->value
.dur
.sec
;
3576 carry
= (long)(sec
/ SECS_PER_DAY
);
3577 sec
-= ((double)carry
) * SECS_PER_DAY
;
3580 day
= x
->value
.dur
.day
- y
->value
.dur
.day
+ carry
;
3598 if ((day
>= 0) && (sec
>= 0.0))
3604 } else if ((day
<= 0) && (sec
<= 0.0)) {
3617 maxday
= 366 * ((myear
+ 3) / 4) +
3618 365 * ((myear
- 1) % 4);
3619 minday
= maxday
- 1;
3623 minday
+= dayRange
[0][xmon
];
3624 maxday
+= dayRange
[1][xmon
];
3626 if ((maxday
== minday
) && (maxday
== xday
))
3627 return(0); /* can this really happen ? */
3638 * macros for adding date/times and durations
3640 #define FQUOTIENT(a,b) (floor(((double)a/(double)b)))
3641 #define MODULO(a,b) (a - FQUOTIENT(a,b) * b)
3642 #define FQUOTIENT_RANGE(a,low,high) (FQUOTIENT((a-low),(high-low)))
3643 #define MODULO_RANGE(a,low,high) ((MODULO((a-low),(high-low)))+low)
3647 * @v: the #xmlSchemaValPtr value to duplicate
3649 * Makes a copy of @v. The calling program is responsible for freeing
3650 * the returned value.
3652 * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error.
3654 static xmlSchemaValPtr
3655 xmlSchemaDupVal (xmlSchemaValPtr v
)
3657 xmlSchemaValPtr ret
= xmlSchemaNewValue(v
->type
);
3661 memcpy(ret
, v
, sizeof(xmlSchemaVal
));
3667 * xmlSchemaCopyValue:
3668 * @val: the precomputed value to be copied
3670 * Copies the precomputed value. This duplicates any string within.
3672 * Returns the copy or NULL if a copy for a data-type is not implemented.
3675 xmlSchemaCopyValue(xmlSchemaValPtr val
)
3677 xmlSchemaValPtr ret
= NULL
, prev
= NULL
, cur
;
3680 * Copy the string values.
3682 while (val
!= NULL
) {
3683 switch (val
->type
) {
3684 case XML_SCHEMAS_ANYTYPE
:
3685 case XML_SCHEMAS_IDREFS
:
3686 case XML_SCHEMAS_ENTITIES
:
3687 case XML_SCHEMAS_NMTOKENS
:
3688 xmlSchemaFreeValue(ret
);
3690 case XML_SCHEMAS_ANYSIMPLETYPE
:
3691 case XML_SCHEMAS_STRING
:
3692 case XML_SCHEMAS_NORMSTRING
:
3693 case XML_SCHEMAS_TOKEN
:
3694 case XML_SCHEMAS_LANGUAGE
:
3695 case XML_SCHEMAS_NAME
:
3696 case XML_SCHEMAS_NCNAME
:
3697 case XML_SCHEMAS_ID
:
3698 case XML_SCHEMAS_IDREF
:
3699 case XML_SCHEMAS_ENTITY
:
3700 case XML_SCHEMAS_NMTOKEN
:
3701 case XML_SCHEMAS_ANYURI
:
3702 cur
= xmlSchemaDupVal(val
);
3703 if (val
->value
.str
!= NULL
)
3704 cur
->value
.str
= xmlStrdup(BAD_CAST val
->value
.str
);
3706 case XML_SCHEMAS_QNAME
:
3707 case XML_SCHEMAS_NOTATION
:
3708 cur
= xmlSchemaDupVal(val
);
3709 if (val
->value
.qname
.name
!= NULL
)
3710 cur
->value
.qname
.name
=
3711 xmlStrdup(BAD_CAST val
->value
.qname
.name
);
3712 if (val
->value
.qname
.uri
!= NULL
)
3713 cur
->value
.qname
.uri
=
3714 xmlStrdup(BAD_CAST val
->value
.qname
.uri
);
3716 case XML_SCHEMAS_HEXBINARY
:
3717 cur
= xmlSchemaDupVal(val
);
3718 if (val
->value
.hex
.str
!= NULL
)
3719 cur
->value
.hex
.str
= xmlStrdup(BAD_CAST val
->value
.hex
.str
);
3721 case XML_SCHEMAS_BASE64BINARY
:
3722 cur
= xmlSchemaDupVal(val
);
3723 if (val
->value
.base64
.str
!= NULL
)
3724 cur
->value
.base64
.str
=
3725 xmlStrdup(BAD_CAST val
->value
.base64
.str
);
3728 cur
= xmlSchemaDupVal(val
);
3742 * _xmlSchemaDateAdd:
3743 * @dt: an #xmlSchemaValPtr
3744 * @dur: an #xmlSchemaValPtr of type #XS_DURATION
3746 * Compute a new date/time from @dt and @dur. This function assumes @dt
3747 * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
3748 * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as
3749 * @dt. The calling program is responsible for freeing the returned value.
3751 * Returns a pointer to a new #xmlSchemaVal or NULL if error.
3753 static xmlSchemaValPtr
3754 _xmlSchemaDateAdd (xmlSchemaValPtr dt
, xmlSchemaValPtr dur
)
3756 xmlSchemaValPtr ret
, tmp
;
3757 long carry
, tempdays
, temp
;
3758 xmlSchemaValDatePtr r
, d
;
3759 xmlSchemaValDurationPtr u
;
3761 if ((dt
== NULL
) || (dur
== NULL
))
3764 ret
= xmlSchemaNewValue(dt
->type
);
3768 /* make a copy so we don't alter the original value */
3769 tmp
= xmlSchemaDupVal(dt
);
3771 xmlSchemaFreeValue(ret
);
3775 r
= &(ret
->value
.date
);
3776 d
= &(tmp
->value
.date
);
3777 u
= &(dur
->value
.dur
);
3783 /* normalize for time zone offset */
3784 u
->sec
-= (d
->tzo
* 60);
3792 carry
= d
->mon
+ u
->mon
;
3793 r
->mon
= (unsigned int) MODULO_RANGE(carry
, 1, 13);
3794 carry
= (long) FQUOTIENT_RANGE(carry
, 1, 13);
3796 /* year (may be modified later) */
3797 r
->year
= d
->year
+ carry
;
3807 r
->tz_flag
= d
->tz_flag
;
3810 r
->sec
= d
->sec
+ u
->sec
;
3811 carry
= (long) FQUOTIENT((long)r
->sec
, 60);
3812 if (r
->sec
!= 0.0) {
3813 r
->sec
= MODULO(r
->sec
, 60.0);
3818 r
->min
= (unsigned int) MODULO(carry
, 60);
3819 carry
= (long) FQUOTIENT(carry
, 60);
3823 r
->hour
= (unsigned int) MODULO(carry
, 24);
3824 carry
= (long)FQUOTIENT(carry
, 24);
3828 * Note we use tempdays because the temporary values may need more
3831 if ((VALID_YEAR(r
->year
)) && (VALID_MONTH(r
->mon
)) &&
3832 (d
->day
> MAX_DAYINMONTH(r
->year
, r
->mon
)))
3833 tempdays
= MAX_DAYINMONTH(r
->year
, r
->mon
);
3834 else if (d
->day
< 1)
3839 tempdays
+= u
->day
+ carry
;
3843 long tmon
= (long) MODULO_RANGE((int)r
->mon
-1, 1, 13);
3844 long tyr
= r
->year
+ (long)FQUOTIENT_RANGE((int)r
->mon
-1, 1, 13);
3848 * Coverity detected an overrun in daysInMonth
3849 * of size 12 at position 12 with index variable "((r)->mon - 1)"
3855 tempdays
+= MAX_DAYINMONTH(tyr
, tmon
);
3857 } else if (VALID_YEAR(r
->year
) && VALID_MONTH(r
->mon
) &&
3858 tempdays
> (long) MAX_DAYINMONTH(r
->year
, r
->mon
)) {
3859 tempdays
= tempdays
- MAX_DAYINMONTH(r
->year
, r
->mon
);
3864 temp
= r
->mon
+ carry
;
3865 r
->mon
= (unsigned int) MODULO_RANGE(temp
, 1, 13);
3866 r
->year
= r
->year
+ (unsigned int) FQUOTIENT_RANGE(temp
, 1, 13);
3878 * adjust the date/time type to the date values
3880 if (ret
->type
!= XML_SCHEMAS_DATETIME
) {
3881 if ((r
->hour
) || (r
->min
) || (r
->sec
))
3882 ret
->type
= XML_SCHEMAS_DATETIME
;
3883 else if (ret
->type
!= XML_SCHEMAS_DATE
) {
3884 if ((r
->mon
!= 1) && (r
->day
!= 1))
3885 ret
->type
= XML_SCHEMAS_DATE
;
3886 else if ((ret
->type
!= XML_SCHEMAS_GYEARMONTH
) && (r
->mon
!= 1))
3887 ret
->type
= XML_SCHEMAS_GYEARMONTH
;
3891 xmlSchemaFreeValue(tmp
);
3897 * xmlSchemaDateNormalize:
3898 * @dt: an #xmlSchemaValPtr of a date/time type value.
3899 * @offset: number of seconds to adjust @dt by.
3901 * Normalize @dt to GMT time. The @offset parameter is subtracted from
3902 * the return value is a time-zone offset is present on @dt.
3904 * Returns a normalized copy of @dt or NULL if error.
3906 static xmlSchemaValPtr
3907 xmlSchemaDateNormalize (xmlSchemaValPtr dt
, double offset
)
3909 xmlSchemaValPtr dur
, ret
;
3914 if (((dt
->type
!= XML_SCHEMAS_TIME
) &&
3915 (dt
->type
!= XML_SCHEMAS_DATETIME
) &&
3916 (dt
->type
!= XML_SCHEMAS_DATE
)) || (dt
->value
.date
.tzo
== 0))
3917 return xmlSchemaDupVal(dt
);
3919 dur
= xmlSchemaNewValue(XML_SCHEMAS_DURATION
);
3923 dur
->value
.date
.sec
-= offset
;
3925 ret
= _xmlSchemaDateAdd(dt
, dur
);
3929 xmlSchemaFreeValue(dur
);
3931 /* ret->value.date.tzo = 0; */
3936 * _xmlSchemaDateCastYMToDays:
3937 * @dt: an #xmlSchemaValPtr
3939 * Convert mon and year of @dt to total number of days. Take the
3940 * number of years since (or before) 1 AD and add the number of leap
3941 * years. This is a function because negative
3942 * years must be handled a little differently and there is no zero year.
3944 * Returns number of days.
3947 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt
)
3952 mon
= dt
->value
.date
.mon
;
3953 if (mon
<= 0) mon
= 1; /* normalization */
3955 if (dt
->value
.date
.year
<= 0)
3956 ret
= (dt
->value
.date
.year
* 365) +
3957 (((dt
->value
.date
.year
+1)/4)-((dt
->value
.date
.year
+1)/100)+
3958 ((dt
->value
.date
.year
+1)/400)) +
3959 DAY_IN_YEAR(0, mon
, dt
->value
.date
.year
);
3961 ret
= ((dt
->value
.date
.year
-1) * 365) +
3962 (((dt
->value
.date
.year
-1)/4)-((dt
->value
.date
.year
-1)/100)+
3963 ((dt
->value
.date
.year
-1)/400)) +
3964 DAY_IN_YEAR(0, mon
, dt
->value
.date
.year
);
3971 * @dt: an #xmlSchemaValPtr
3973 * Calculates the number of seconds in the time portion of @dt.
3977 #define TIME_TO_NUMBER(dt) \
3978 ((double)((dt->value.date.hour * SECS_PER_HOUR) + \
3979 (dt->value.date.min * SECS_PER_MIN) + \
3980 (dt->value.date.tzo * SECS_PER_MIN)) + \
3984 * xmlSchemaCompareDates:
3985 * @x: a first date/time value
3986 * @y: a second date/time value
3988 * Compare 2 date/times
3990 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3994 xmlSchemaCompareDates (xmlSchemaValPtr x
, xmlSchemaValPtr y
)
3996 unsigned char xmask
, ymask
, xor_mask
, and_mask
;
3997 xmlSchemaValPtr p1
, p2
, q1
, q2
;
3998 long p1d
, p2d
, q1d
, q2d
;
4000 if ((x
== NULL
) || (y
== NULL
))
4003 if (x
->value
.date
.tz_flag
) {
4005 if (!y
->value
.date
.tz_flag
) {
4006 p1
= xmlSchemaDateNormalize(x
, 0);
4007 p1d
= _xmlSchemaDateCastYMToDays(p1
) + p1
->value
.date
.day
;
4008 /* normalize y + 14:00 */
4009 q1
= xmlSchemaDateNormalize(y
, (14 * SECS_PER_HOUR
));
4011 q1d
= _xmlSchemaDateCastYMToDays(q1
) + q1
->value
.date
.day
;
4013 xmlSchemaFreeValue(p1
);
4014 xmlSchemaFreeValue(q1
);
4016 } else if (p1d
== q1d
) {
4019 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q1
);
4021 xmlSchemaFreeValue(p1
);
4022 xmlSchemaFreeValue(q1
);
4026 /* normalize y - 14:00 */
4027 q2
= xmlSchemaDateNormalize(y
, -(14 * SECS_PER_HOUR
));
4028 q2d
= _xmlSchemaDateCastYMToDays(q2
) + q2
->value
.date
.day
;
4031 else if (p1d
== q2d
) {
4032 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q2
);
4036 ret
= 2; /* indeterminate */
4038 xmlSchemaFreeValue(p1
);
4039 xmlSchemaFreeValue(q1
);
4040 xmlSchemaFreeValue(q2
);
4045 xmlSchemaFreeValue(p1
);
4046 xmlSchemaFreeValue(q1
);
4049 } else if (y
->value
.date
.tz_flag
) {
4050 q1
= xmlSchemaDateNormalize(y
, 0);
4051 q1d
= _xmlSchemaDateCastYMToDays(q1
) + q1
->value
.date
.day
;
4053 /* normalize x - 14:00 */
4054 p1
= xmlSchemaDateNormalize(x
, -(14 * SECS_PER_HOUR
));
4055 p1d
= _xmlSchemaDateCastYMToDays(p1
) + p1
->value
.date
.day
;
4058 xmlSchemaFreeValue(p1
);
4059 xmlSchemaFreeValue(q1
);
4061 } else if (p1d
== q1d
) {
4064 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q1
);
4066 xmlSchemaFreeValue(p1
);
4067 xmlSchemaFreeValue(q1
);
4071 /* normalize x + 14:00 */
4072 p2
= xmlSchemaDateNormalize(x
, (14 * SECS_PER_HOUR
));
4073 p2d
= _xmlSchemaDateCastYMToDays(p2
) + p2
->value
.date
.day
;
4077 } else if (p2d
== q1d
) {
4078 sec
= TIME_TO_NUMBER(p2
) - TIME_TO_NUMBER(q1
);
4082 ret
= 2; /* indeterminate */
4084 xmlSchemaFreeValue(p1
);
4085 xmlSchemaFreeValue(q1
);
4086 xmlSchemaFreeValue(p2
);
4091 xmlSchemaFreeValue(p1
);
4092 xmlSchemaFreeValue(q1
);
4097 * if the same type then calculate the difference
4099 if (x
->type
== y
->type
) {
4101 q1
= xmlSchemaDateNormalize(y
, 0);
4102 q1d
= _xmlSchemaDateCastYMToDays(q1
) + q1
->value
.date
.day
;
4104 p1
= xmlSchemaDateNormalize(x
, 0);
4105 p1d
= _xmlSchemaDateCastYMToDays(p1
) + p1
->value
.date
.day
;
4109 } else if (p1d
> q1d
) {
4114 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q1
);
4121 xmlSchemaFreeValue(p1
);
4122 xmlSchemaFreeValue(q1
);
4127 case XML_SCHEMAS_DATETIME
:
4130 case XML_SCHEMAS_DATE
:
4133 case XML_SCHEMAS_GYEAR
:
4136 case XML_SCHEMAS_GMONTH
:
4139 case XML_SCHEMAS_GDAY
:
4142 case XML_SCHEMAS_GYEARMONTH
:
4145 case XML_SCHEMAS_GMONTHDAY
:
4148 case XML_SCHEMAS_TIME
:
4157 case XML_SCHEMAS_DATETIME
:
4160 case XML_SCHEMAS_DATE
:
4163 case XML_SCHEMAS_GYEAR
:
4166 case XML_SCHEMAS_GMONTH
:
4169 case XML_SCHEMAS_GDAY
:
4172 case XML_SCHEMAS_GYEARMONTH
:
4175 case XML_SCHEMAS_GMONTHDAY
:
4178 case XML_SCHEMAS_TIME
:
4186 xor_mask
= xmask
^ ymask
; /* mark type differences */
4187 and_mask
= xmask
& ymask
; /* mark field specification */
4191 return 2; /* indeterminate */
4192 else if (and_mask
& 1) {
4193 if (x
->value
.date
.year
< y
->value
.date
.year
)
4195 else if (x
->value
.date
.year
> y
->value
.date
.year
)
4201 return 2; /* indeterminate */
4202 else if (and_mask
& 2) {
4203 if (x
->value
.date
.mon
< y
->value
.date
.mon
)
4205 else if (x
->value
.date
.mon
> y
->value
.date
.mon
)
4211 return 2; /* indeterminate */
4212 else if (and_mask
& 4) {
4213 if (x
->value
.date
.day
< y
->value
.date
.day
)
4215 else if (x
->value
.date
.day
> y
->value
.date
.day
)
4221 return 2; /* indeterminate */
4222 else if (and_mask
& 8) {
4223 if (x
->value
.date
.hour
< y
->value
.date
.hour
)
4225 else if (x
->value
.date
.hour
> y
->value
.date
.hour
)
4227 else if (x
->value
.date
.min
< y
->value
.date
.min
)
4229 else if (x
->value
.date
.min
> y
->value
.date
.min
)
4231 else if (x
->value
.date
.sec
< y
->value
.date
.sec
)
4233 else if (x
->value
.date
.sec
> y
->value
.date
.sec
)
4241 * xmlSchemaComparePreserveReplaceStrings:
4242 * @x: a first string value
4243 * @y: a second string value
4244 * @invert: inverts the result if x < y or x > y.
4246 * Compare 2 string for their normalized values.
4247 * @x is a string with whitespace of "preserve", @y is
4248 * a string with a whitespace of "replace". I.e. @x could
4249 * be an "xsd:string" and @y an "xsd:normalizedString".
4251 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4255 xmlSchemaComparePreserveReplaceStrings(const xmlChar
*x
,
4261 while ((*x
!= 0) && (*y
!= 0)) {
4262 if (IS_WSP_REPLACE_CH(*y
)) {
4263 if (! IS_WSP_SPACE_CH(*x
)) {
4264 if ((*x
- 0x20) < 0) {
4310 * xmlSchemaComparePreserveCollapseStrings:
4311 * @x: a first string value
4312 * @y: a second string value
4314 * Compare 2 string for their normalized values.
4315 * @x is a string with whitespace of "preserve", @y is
4316 * a string with a whitespace of "collapse". I.e. @x could
4317 * be an "xsd:string" and @y an "xsd:normalizedString".
4319 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4323 xmlSchemaComparePreserveCollapseStrings(const xmlChar
*x
,
4330 * Skip leading blank chars of the collapsed string.
4332 while IS_WSP_BLANK_CH(*y
)
4335 while ((*x
!= 0) && (*y
!= 0)) {
4336 if IS_WSP_BLANK_CH(*y
) {
4337 if (! IS_WSP_SPACE_CH(*x
)) {
4339 * The yv character would have been replaced to 0x20.
4341 if ((*x
- 0x20) < 0) {
4356 * Skip contiguous blank chars of the collapsed string.
4358 while IS_WSP_BLANK_CH(*y
)
4384 * Skip trailing blank chars of the collapsed string.
4386 while IS_WSP_BLANK_CH(*y
)
4399 * xmlSchemaComparePreserveCollapseStrings:
4400 * @x: a first string value
4401 * @y: a second string value
4403 * Compare 2 string for their normalized values.
4404 * @x is a string with whitespace of "preserve", @y is
4405 * a string with a whitespace of "collapse". I.e. @x could
4406 * be an "xsd:string" and @y an "xsd:normalizedString".
4408 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4412 xmlSchemaCompareReplaceCollapseStrings(const xmlChar
*x
,
4419 * Skip leading blank chars of the collapsed string.
4421 while IS_WSP_BLANK_CH(*y
)
4424 while ((*x
!= 0) && (*y
!= 0)) {
4425 if IS_WSP_BLANK_CH(*y
) {
4426 if (! IS_WSP_BLANK_CH(*x
)) {
4428 * The yv character would have been replaced to 0x20.
4430 if ((*x
- 0x20) < 0) {
4445 * Skip contiguous blank chars of the collapsed string.
4447 while IS_WSP_BLANK_CH(*y
)
4450 if IS_WSP_BLANK_CH(*x
) {
4452 * The xv character would have been replaced to 0x20.
4454 if ((0x20 - *y
) < 0) {
4481 * Skip trailing blank chars of the collapsed string.
4483 while IS_WSP_BLANK_CH(*y
)
4497 * xmlSchemaCompareReplacedStrings:
4498 * @x: a first string value
4499 * @y: a second string value
4501 * Compare 2 string for their normalized values.
4503 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4507 xmlSchemaCompareReplacedStrings(const xmlChar
*x
,
4512 while ((*x
!= 0) && (*y
!= 0)) {
4513 if IS_WSP_BLANK_CH(*y
) {
4514 if (! IS_WSP_BLANK_CH(*x
)) {
4515 if ((*x
- 0x20) < 0)
4521 if IS_WSP_BLANK_CH(*x
) {
4522 if ((0x20 - *y
) < 0)
4544 * xmlSchemaCompareNormStrings:
4545 * @x: a first string value
4546 * @y: a second string value
4548 * Compare 2 string for their normalized values.
4550 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4554 xmlSchemaCompareNormStrings(const xmlChar
*x
,
4558 while (IS_BLANK_CH(*x
)) x
++;
4559 while (IS_BLANK_CH(*y
)) y
++;
4560 while ((*x
!= 0) && (*y
!= 0)) {
4561 if (IS_BLANK_CH(*x
)) {
4562 if (!IS_BLANK_CH(*y
)) {
4566 while (IS_BLANK_CH(*x
)) x
++;
4567 while (IS_BLANK_CH(*y
)) y
++;
4577 while (IS_BLANK_CH(*x
)) x
++;
4582 while (IS_BLANK_CH(*y
)) y
++;
4590 * xmlSchemaCompareFloats:
4591 * @x: a first float or double value
4592 * @y: a second float or double value
4596 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4600 xmlSchemaCompareFloats(xmlSchemaValPtr x
, xmlSchemaValPtr y
) {
4603 if ((x
== NULL
) || (y
== NULL
))
4607 * Cast everything to doubles.
4609 if (x
->type
== XML_SCHEMAS_DOUBLE
)
4611 else if (x
->type
== XML_SCHEMAS_FLOAT
)
4616 if (y
->type
== XML_SCHEMAS_DOUBLE
)
4618 else if (y
->type
== XML_SCHEMAS_FLOAT
)
4624 * Check for special cases.
4626 if (xmlXPathIsNaN(d1
)) {
4627 if (xmlXPathIsNaN(d2
))
4631 if (xmlXPathIsNaN(d2
))
4633 if (d1
== xmlXPathPINF
) {
4634 if (d2
== xmlXPathPINF
)
4638 if (d2
== xmlXPathPINF
)
4640 if (d1
== xmlXPathNINF
) {
4641 if (d2
== xmlXPathNINF
)
4645 if (d2
== xmlXPathNINF
)
4649 * basic tests, the last one we should have equality, but
4650 * portability is more important than speed and handling
4651 * NaN or Inf in a portable way is always a challenge, so ...
4663 * xmlSchemaCompareValues:
4665 * @xvalue: the first value as a string (optional)
4666 * @xwtsp: the whitespace type
4667 * @y: a second value
4668 * @xvalue: the second value as a string (optional)
4669 * @ywtsp: the whitespace type
4673 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not
4674 * comparable and -2 in case of error
4677 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype
,
4679 const xmlChar
*xvalue
,
4680 xmlSchemaWhitespaceValueType xws
,
4681 xmlSchemaValType ytype
,
4683 const xmlChar
*yvalue
,
4684 xmlSchemaWhitespaceValueType yws
)
4687 case XML_SCHEMAS_UNKNOWN
:
4688 case XML_SCHEMAS_ANYTYPE
:
4690 case XML_SCHEMAS_INTEGER
:
4691 case XML_SCHEMAS_NPINTEGER
:
4692 case XML_SCHEMAS_NINTEGER
:
4693 case XML_SCHEMAS_NNINTEGER
:
4694 case XML_SCHEMAS_PINTEGER
:
4695 case XML_SCHEMAS_INT
:
4696 case XML_SCHEMAS_UINT
:
4697 case XML_SCHEMAS_LONG
:
4698 case XML_SCHEMAS_ULONG
:
4699 case XML_SCHEMAS_SHORT
:
4700 case XML_SCHEMAS_USHORT
:
4701 case XML_SCHEMAS_BYTE
:
4702 case XML_SCHEMAS_UBYTE
:
4703 case XML_SCHEMAS_DECIMAL
:
4704 if ((x
== NULL
) || (y
== NULL
))
4707 return(xmlSchemaCompareDecimals(x
, y
));
4708 if ((ytype
== XML_SCHEMAS_DECIMAL
) ||
4709 (ytype
== XML_SCHEMAS_INTEGER
) ||
4710 (ytype
== XML_SCHEMAS_NPINTEGER
) ||
4711 (ytype
== XML_SCHEMAS_NINTEGER
) ||
4712 (ytype
== XML_SCHEMAS_NNINTEGER
) ||
4713 (ytype
== XML_SCHEMAS_PINTEGER
) ||
4714 (ytype
== XML_SCHEMAS_INT
) ||
4715 (ytype
== XML_SCHEMAS_UINT
) ||
4716 (ytype
== XML_SCHEMAS_LONG
) ||
4717 (ytype
== XML_SCHEMAS_ULONG
) ||
4718 (ytype
== XML_SCHEMAS_SHORT
) ||
4719 (ytype
== XML_SCHEMAS_USHORT
) ||
4720 (ytype
== XML_SCHEMAS_BYTE
) ||
4721 (ytype
== XML_SCHEMAS_UBYTE
))
4722 return(xmlSchemaCompareDecimals(x
, y
));
4724 case XML_SCHEMAS_DURATION
:
4725 if ((x
== NULL
) || (y
== NULL
))
4727 if (ytype
== XML_SCHEMAS_DURATION
)
4728 return(xmlSchemaCompareDurations(x
, y
));
4730 case XML_SCHEMAS_TIME
:
4731 case XML_SCHEMAS_GDAY
:
4732 case XML_SCHEMAS_GMONTH
:
4733 case XML_SCHEMAS_GMONTHDAY
:
4734 case XML_SCHEMAS_GYEAR
:
4735 case XML_SCHEMAS_GYEARMONTH
:
4736 case XML_SCHEMAS_DATE
:
4737 case XML_SCHEMAS_DATETIME
:
4738 if ((x
== NULL
) || (y
== NULL
))
4740 if ((ytype
== XML_SCHEMAS_DATETIME
) ||
4741 (ytype
== XML_SCHEMAS_TIME
) ||
4742 (ytype
== XML_SCHEMAS_GDAY
) ||
4743 (ytype
== XML_SCHEMAS_GMONTH
) ||
4744 (ytype
== XML_SCHEMAS_GMONTHDAY
) ||
4745 (ytype
== XML_SCHEMAS_GYEAR
) ||
4746 (ytype
== XML_SCHEMAS_DATE
) ||
4747 (ytype
== XML_SCHEMAS_GYEARMONTH
))
4748 return (xmlSchemaCompareDates(x
, y
));
4751 * Note that we will support comparison of string types against
4752 * anySimpleType as well.
4754 case XML_SCHEMAS_ANYSIMPLETYPE
:
4755 case XML_SCHEMAS_STRING
:
4756 case XML_SCHEMAS_NORMSTRING
:
4757 case XML_SCHEMAS_TOKEN
:
4758 case XML_SCHEMAS_LANGUAGE
:
4759 case XML_SCHEMAS_NMTOKEN
:
4760 case XML_SCHEMAS_NAME
:
4761 case XML_SCHEMAS_NCNAME
:
4762 case XML_SCHEMAS_ID
:
4763 case XML_SCHEMAS_IDREF
:
4764 case XML_SCHEMAS_ENTITY
:
4765 case XML_SCHEMAS_ANYURI
:
4767 const xmlChar
*xv
, *yv
;
4778 * TODO: Compare those against QName.
4780 if (ytype
== XML_SCHEMAS_QNAME
) {
4786 if ((ytype
== XML_SCHEMAS_ANYSIMPLETYPE
) ||
4787 (ytype
== XML_SCHEMAS_STRING
) ||
4788 (ytype
== XML_SCHEMAS_NORMSTRING
) ||
4789 (ytype
== XML_SCHEMAS_TOKEN
) ||
4790 (ytype
== XML_SCHEMAS_LANGUAGE
) ||
4791 (ytype
== XML_SCHEMAS_NMTOKEN
) ||
4792 (ytype
== XML_SCHEMAS_NAME
) ||
4793 (ytype
== XML_SCHEMAS_NCNAME
) ||
4794 (ytype
== XML_SCHEMAS_ID
) ||
4795 (ytype
== XML_SCHEMAS_IDREF
) ||
4796 (ytype
== XML_SCHEMAS_ENTITY
) ||
4797 (ytype
== XML_SCHEMAS_ANYURI
)) {
4799 if (xws
== XML_SCHEMA_WHITESPACE_PRESERVE
) {
4801 if (yws
== XML_SCHEMA_WHITESPACE_PRESERVE
) {
4802 /* TODO: What about x < y or x > y. */
4803 if (xmlStrEqual(xv
, yv
))
4807 } else if (yws
== XML_SCHEMA_WHITESPACE_REPLACE
)
4808 return (xmlSchemaComparePreserveReplaceStrings(xv
, yv
, 0));
4809 else if (yws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
4810 return (xmlSchemaComparePreserveCollapseStrings(xv
, yv
, 0));
4812 } else if (xws
== XML_SCHEMA_WHITESPACE_REPLACE
) {
4814 if (yws
== XML_SCHEMA_WHITESPACE_PRESERVE
)
4815 return (xmlSchemaComparePreserveReplaceStrings(yv
, xv
, 1));
4816 if (yws
== XML_SCHEMA_WHITESPACE_REPLACE
)
4817 return (xmlSchemaCompareReplacedStrings(xv
, yv
));
4818 if (yws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
4819 return (xmlSchemaCompareReplaceCollapseStrings(xv
, yv
, 0));
4821 } else if (xws
== XML_SCHEMA_WHITESPACE_COLLAPSE
) {
4823 if (yws
== XML_SCHEMA_WHITESPACE_PRESERVE
)
4824 return (xmlSchemaComparePreserveCollapseStrings(yv
, xv
, 1));
4825 if (yws
== XML_SCHEMA_WHITESPACE_REPLACE
)
4826 return (xmlSchemaCompareReplaceCollapseStrings(yv
, xv
, 1));
4827 if (yws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
4828 return (xmlSchemaCompareNormStrings(xv
, yv
));
4835 case XML_SCHEMAS_QNAME
:
4836 case XML_SCHEMAS_NOTATION
:
4837 if ((x
== NULL
) || (y
== NULL
))
4839 if ((ytype
== XML_SCHEMAS_QNAME
) ||
4840 (ytype
== XML_SCHEMAS_NOTATION
)) {
4841 if ((xmlStrEqual(x
->value
.qname
.name
, y
->value
.qname
.name
)) &&
4842 (xmlStrEqual(x
->value
.qname
.uri
, y
->value
.qname
.uri
)))
4847 case XML_SCHEMAS_FLOAT
:
4848 case XML_SCHEMAS_DOUBLE
:
4849 if ((x
== NULL
) || (y
== NULL
))
4851 if ((ytype
== XML_SCHEMAS_FLOAT
) ||
4852 (ytype
== XML_SCHEMAS_DOUBLE
))
4853 return (xmlSchemaCompareFloats(x
, y
));
4855 case XML_SCHEMAS_BOOLEAN
:
4856 if ((x
== NULL
) || (y
== NULL
))
4858 if (ytype
== XML_SCHEMAS_BOOLEAN
) {
4859 if (x
->value
.b
== y
->value
.b
)
4861 if (x
->value
.b
== 0)
4866 case XML_SCHEMAS_HEXBINARY
:
4867 if ((x
== NULL
) || (y
== NULL
))
4869 if (ytype
== XML_SCHEMAS_HEXBINARY
) {
4870 if (x
->value
.hex
.total
== y
->value
.hex
.total
) {
4871 int ret
= xmlStrcmp(x
->value
.hex
.str
, y
->value
.hex
.str
);
4877 else if (x
->value
.hex
.total
> y
->value
.hex
.total
)
4883 case XML_SCHEMAS_BASE64BINARY
:
4884 if ((x
== NULL
) || (y
== NULL
))
4886 if (ytype
== XML_SCHEMAS_BASE64BINARY
) {
4887 if (x
->value
.base64
.total
== y
->value
.base64
.total
) {
4888 int ret
= xmlStrcmp(x
->value
.base64
.str
,
4889 y
->value
.base64
.str
);
4897 else if (x
->value
.base64
.total
> y
->value
.base64
.total
)
4903 case XML_SCHEMAS_IDREFS
:
4904 case XML_SCHEMAS_ENTITIES
:
4905 case XML_SCHEMAS_NMTOKENS
:
4913 * xmlSchemaCompareValues:
4915 * @y: a second value
4919 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4923 xmlSchemaCompareValues(xmlSchemaValPtr x
, xmlSchemaValPtr y
) {
4924 xmlSchemaWhitespaceValueType xws
, yws
;
4926 if ((x
== NULL
) || (y
== NULL
))
4928 if (x
->type
== XML_SCHEMAS_STRING
)
4929 xws
= XML_SCHEMA_WHITESPACE_PRESERVE
;
4930 else if (x
->type
== XML_SCHEMAS_NORMSTRING
)
4931 xws
= XML_SCHEMA_WHITESPACE_REPLACE
;
4933 xws
= XML_SCHEMA_WHITESPACE_COLLAPSE
;
4935 if (y
->type
== XML_SCHEMAS_STRING
)
4936 yws
= XML_SCHEMA_WHITESPACE_PRESERVE
;
4937 else if (y
->type
== XML_SCHEMAS_NORMSTRING
)
4938 yws
= XML_SCHEMA_WHITESPACE_REPLACE
;
4940 yws
= XML_SCHEMA_WHITESPACE_COLLAPSE
;
4942 return(xmlSchemaCompareValuesInternal(x
->type
, x
, NULL
, xws
, y
->type
,
4947 * xmlSchemaCompareValuesWhtsp:
4949 * @xws: the whitespace value of x
4950 * @y: a second value
4951 * @yws: the whitespace value of y
4955 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4959 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x
,
4960 xmlSchemaWhitespaceValueType xws
,
4962 xmlSchemaWhitespaceValueType yws
)
4964 if ((x
== NULL
) || (y
== NULL
))
4966 return(xmlSchemaCompareValuesInternal(x
->type
, x
, NULL
, xws
, y
->type
,
4971 * xmlSchemaCompareValuesWhtspExt:
4973 * @xws: the whitespace value of x
4974 * @y: a second value
4975 * @yws: the whitespace value of y
4979 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4983 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype
,
4985 const xmlChar
*xvalue
,
4986 xmlSchemaWhitespaceValueType xws
,
4987 xmlSchemaValType ytype
,
4989 const xmlChar
*yvalue
,
4990 xmlSchemaWhitespaceValueType yws
)
4992 return(xmlSchemaCompareValuesInternal(xtype
, x
, xvalue
, xws
, ytype
, y
,
5000 * Computes the UTF8 length of the normalized value of the string
5002 * Returns the length or -1 in case of error.
5005 xmlSchemaNormLen(const xmlChar
*value
) {
5012 while (IS_BLANK_CH(*utf
)) utf
++;
5014 if (utf
[0] & 0x80) {
5015 if ((utf
[1] & 0xc0) != 0x80)
5017 if ((utf
[0] & 0xe0) == 0xe0) {
5018 if ((utf
[2] & 0xc0) != 0x80)
5020 if ((utf
[0] & 0xf0) == 0xf0) {
5021 if ((utf
[0] & 0xf8) != 0xf0 || (utf
[3] & 0xc0) != 0x80)
5030 } else if (IS_BLANK_CH(*utf
)) {
5031 while (IS_BLANK_CH(*utf
)) utf
++;
5043 * xmlSchemaGetFacetValueAsULong:
5044 * @facet: an schemas type facet
5046 * Extract the value of a facet
5048 * Returns the value as a long
5051 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet
)
5054 * TODO: Check if this is a decimal.
5058 return ((unsigned long) facet
->val
->value
.decimal
.lo
);
5062 * xmlSchemaValidateListSimpleTypeFacet:
5063 * @facet: the facet to check
5064 * @value: the lexical repr of the value to validate
5065 * @actualLen: the number of list items
5066 * @expectedLen: the resulting expected number of list items
5068 * Checks the value of a list simple type against a facet.
5070 * Returns 0 if the value is valid, a positive error code
5071 * number otherwise and -1 in case of an internal error.
5074 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet
,
5075 const xmlChar
*value
,
5076 unsigned long actualLen
,
5077 unsigned long *expectedLen
)
5082 * TODO: Check if this will work with large numbers.
5083 * (compare value.decimal.mi and value.decimal.hi as well?).
5085 if (facet
->type
== XML_SCHEMA_FACET_LENGTH
) {
5086 if (actualLen
!= facet
->val
->value
.decimal
.lo
) {
5087 if (expectedLen
!= NULL
)
5088 *expectedLen
= facet
->val
->value
.decimal
.lo
;
5089 return (XML_SCHEMAV_CVC_LENGTH_VALID
);
5091 } else if (facet
->type
== XML_SCHEMA_FACET_MINLENGTH
) {
5092 if (actualLen
< facet
->val
->value
.decimal
.lo
) {
5093 if (expectedLen
!= NULL
)
5094 *expectedLen
= facet
->val
->value
.decimal
.lo
;
5095 return (XML_SCHEMAV_CVC_MINLENGTH_VALID
);
5097 } else if (facet
->type
== XML_SCHEMA_FACET_MAXLENGTH
) {
5098 if (actualLen
> facet
->val
->value
.decimal
.lo
) {
5099 if (expectedLen
!= NULL
)
5100 *expectedLen
= facet
->val
->value
.decimal
.lo
;
5101 return (XML_SCHEMAV_CVC_MAXLENGTH_VALID
);
5105 * NOTE: That we can pass NULL as xmlSchemaValPtr to
5106 * xmlSchemaValidateFacet, since the remaining facet types
5107 * are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
5109 return(xmlSchemaValidateFacet(NULL
, facet
, value
, NULL
));
5114 * xmlSchemaValidateLengthFacet:
5115 * @type: the built-in type
5116 * @facet: the facet to check
5117 * @value: the lexical repr. of the value to be validated
5118 * @val: the precomputed value
5119 * @ws: the whitespace type of the value
5120 * @length: the actual length of the value
5122 * Checka a value against a "length", "minLength" and "maxLength"
5123 * facet; sets @length to the computed length of @value.
5125 * Returns 0 if the value is valid, a positive error code
5126 * otherwise and -1 in case of an internal or API error.
5129 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet
,
5130 xmlSchemaValType valType
,
5131 const xmlChar
*value
,
5132 xmlSchemaValPtr val
,
5133 unsigned long *length
,
5134 xmlSchemaWhitespaceValueType ws
)
5136 unsigned int len
= 0;
5138 if ((length
== NULL
) || (facet
== NULL
))
5141 if ((facet
->type
!= XML_SCHEMA_FACET_LENGTH
) &&
5142 (facet
->type
!= XML_SCHEMA_FACET_MAXLENGTH
) &&
5143 (facet
->type
!= XML_SCHEMA_FACET_MINLENGTH
))
5147 * TODO: length, maxLength and minLength must be of type
5148 * nonNegativeInteger only. Check if decimal is used somehow.
5150 if ((facet
->val
== NULL
) ||
5151 ((facet
->val
->type
!= XML_SCHEMAS_DECIMAL
) &&
5152 (facet
->val
->type
!= XML_SCHEMAS_NNINTEGER
)) ||
5153 (facet
->val
->value
.decimal
.frac
!= 0)) {
5156 if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_HEXBINARY
))
5157 len
= val
->value
.hex
.total
;
5158 else if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_BASE64BINARY
))
5159 len
= val
->value
.base64
.total
;
5162 case XML_SCHEMAS_STRING
:
5163 case XML_SCHEMAS_NORMSTRING
:
5164 if (ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) {
5166 * This is to ensure API compatibility with the old
5167 * xmlSchemaValidateLengthFacet(). Anyway, this was and
5168 * is not the correct handling.
5169 * TODO: Get rid of this case somehow.
5171 if (valType
== XML_SCHEMAS_STRING
)
5172 len
= xmlUTF8Strlen(value
);
5174 len
= xmlSchemaNormLen(value
);
5175 } else if (value
!= NULL
) {
5176 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
5177 len
= xmlSchemaNormLen(value
);
5180 * Should be OK for "preserve" as well.
5182 len
= xmlUTF8Strlen(value
);
5185 case XML_SCHEMAS_IDREF
:
5186 case XML_SCHEMAS_TOKEN
:
5187 case XML_SCHEMAS_LANGUAGE
:
5188 case XML_SCHEMAS_NMTOKEN
:
5189 case XML_SCHEMAS_NAME
:
5190 case XML_SCHEMAS_NCNAME
:
5191 case XML_SCHEMAS_ID
:
5193 * FIXME: What exactly to do with anyURI?
5195 case XML_SCHEMAS_ANYURI
:
5197 len
= xmlSchemaNormLen(value
);
5199 case XML_SCHEMAS_QNAME
:
5200 case XML_SCHEMAS_NOTATION
:
5202 * For QName and NOTATION, those facets are
5203 * deprecated and should be ignored.
5210 *length
= (unsigned long) len
;
5212 * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
5214 if (facet
->type
== XML_SCHEMA_FACET_LENGTH
) {
5215 if (len
!= facet
->val
->value
.decimal
.lo
)
5216 return(XML_SCHEMAV_CVC_LENGTH_VALID
);
5217 } else if (facet
->type
== XML_SCHEMA_FACET_MINLENGTH
) {
5218 if (len
< facet
->val
->value
.decimal
.lo
)
5219 return(XML_SCHEMAV_CVC_MINLENGTH_VALID
);
5221 if (len
> facet
->val
->value
.decimal
.lo
)
5222 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID
);
5229 * xmlSchemaValidateLengthFacet:
5230 * @type: the built-in type
5231 * @facet: the facet to check
5232 * @value: the lexical repr. of the value to be validated
5233 * @val: the precomputed value
5234 * @length: the actual length of the value
5236 * Checka a value against a "length", "minLength" and "maxLength"
5237 * facet; sets @length to the computed length of @value.
5239 * Returns 0 if the value is valid, a positive error code
5240 * otherwise and -1 in case of an internal or API error.
5243 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type
,
5244 xmlSchemaFacetPtr facet
,
5245 const xmlChar
*value
,
5246 xmlSchemaValPtr val
,
5247 unsigned long *length
)
5251 return (xmlSchemaValidateLengthFacetInternal(facet
,
5252 type
->builtInType
, value
, val
, length
,
5253 XML_SCHEMA_WHITESPACE_UNKNOWN
));
5257 * xmlSchemaValidateLengthFacetWhtsp:
5258 * @facet: the facet to check
5259 * @valType: the built-in type
5260 * @value: the lexical repr. of the value to be validated
5261 * @val: the precomputed value
5262 * @ws: the whitespace type of the value
5263 * @length: the actual length of the value
5265 * Checka a value against a "length", "minLength" and "maxLength"
5266 * facet; sets @length to the computed length of @value.
5268 * Returns 0 if the value is valid, a positive error code
5269 * otherwise and -1 in case of an internal or API error.
5272 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet
,
5273 xmlSchemaValType valType
,
5274 const xmlChar
*value
,
5275 xmlSchemaValPtr val
,
5276 unsigned long *length
,
5277 xmlSchemaWhitespaceValueType ws
)
5279 return (xmlSchemaValidateLengthFacetInternal(facet
, valType
, value
, val
,
5284 * xmlSchemaValidateFacetInternal:
5285 * @facet: the facet to check
5286 * @fws: the whitespace type of the facet's value
5287 * @valType: the built-in type of the value
5288 * @value: the lexical repr of the value to validate
5289 * @val: the precomputed value
5290 * @ws: the whitespace type of the value
5292 * Check a value against a facet condition
5294 * Returns 0 if the element is schemas valid, a positive error code
5295 * number otherwise and -1 in case of internal or API error.
5298 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet
,
5299 xmlSchemaWhitespaceValueType fws
,
5300 xmlSchemaValType valType
,
5301 const xmlChar
*value
,
5302 xmlSchemaValPtr val
,
5303 xmlSchemaWhitespaceValueType ws
)
5310 switch (facet
->type
) {
5311 case XML_SCHEMA_FACET_PATTERN
:
5313 * NOTE that for patterns, the @value needs to be the normalized
5314 * value, *not* the lexical initial value or the canonical value.
5318 ret
= xmlRegexpExec(facet
->regexp
, value
);
5322 return(XML_SCHEMAV_CVC_PATTERN_VALID
);
5324 case XML_SCHEMA_FACET_MAXEXCLUSIVE
:
5325 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5330 return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID
);
5331 case XML_SCHEMA_FACET_MAXINCLUSIVE
:
5332 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5335 if ((ret
== -1) || (ret
== 0))
5337 return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID
);
5338 case XML_SCHEMA_FACET_MINEXCLUSIVE
:
5339 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5344 return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID
);
5345 case XML_SCHEMA_FACET_MININCLUSIVE
:
5346 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5349 if ((ret
== 1) || (ret
== 0))
5351 return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID
);
5352 case XML_SCHEMA_FACET_WHITESPACE
:
5353 /* TODO whitespaces */
5355 * NOTE: Whitespace should be handled to normalize
5356 * the value to be validated against a the facets;
5357 * not to normalize the value in-between.
5360 case XML_SCHEMA_FACET_ENUMERATION
:
5361 if (ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) {
5363 * This is to ensure API compatibility with the old
5364 * xmlSchemaValidateFacet().
5365 * TODO: Get rid of this case.
5367 if ((facet
->value
!= NULL
) &&
5368 (xmlStrEqual(facet
->value
, value
)))
5371 ret
= xmlSchemaCompareValuesWhtspExt(facet
->val
->type
,
5372 facet
->val
, facet
->value
, fws
, valType
, val
,
5379 return(XML_SCHEMAV_CVC_ENUMERATION_VALID
);
5380 case XML_SCHEMA_FACET_LENGTH
:
5382 * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
5383 * then any {value} is facet-valid."
5385 if ((valType
== XML_SCHEMAS_QNAME
) ||
5386 (valType
== XML_SCHEMAS_NOTATION
))
5388 /* No break on purpose. */
5389 case XML_SCHEMA_FACET_MAXLENGTH
:
5390 case XML_SCHEMA_FACET_MINLENGTH
: {
5391 unsigned int len
= 0;
5393 if ((valType
== XML_SCHEMAS_QNAME
) ||
5394 (valType
== XML_SCHEMAS_NOTATION
))
5397 * TODO: length, maxLength and minLength must be of type
5398 * nonNegativeInteger only. Check if decimal is used somehow.
5400 if ((facet
->val
== NULL
) ||
5401 ((facet
->val
->type
!= XML_SCHEMAS_DECIMAL
) &&
5402 (facet
->val
->type
!= XML_SCHEMAS_NNINTEGER
)) ||
5403 (facet
->val
->value
.decimal
.frac
!= 0)) {
5406 if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_HEXBINARY
))
5407 len
= val
->value
.hex
.total
;
5408 else if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_BASE64BINARY
))
5409 len
= val
->value
.base64
.total
;
5412 case XML_SCHEMAS_STRING
:
5413 case XML_SCHEMAS_NORMSTRING
:
5414 if (ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) {
5416 * This is to ensure API compatibility with the old
5417 * xmlSchemaValidateFacet(). Anyway, this was and
5418 * is not the correct handling.
5419 * TODO: Get rid of this case somehow.
5421 if (valType
== XML_SCHEMAS_STRING
)
5422 len
= xmlUTF8Strlen(value
);
5424 len
= xmlSchemaNormLen(value
);
5425 } else if (value
!= NULL
) {
5426 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
5427 len
= xmlSchemaNormLen(value
);
5430 * Should be OK for "preserve" as well.
5432 len
= xmlUTF8Strlen(value
);
5435 case XML_SCHEMAS_IDREF
:
5436 case XML_SCHEMAS_TOKEN
:
5437 case XML_SCHEMAS_LANGUAGE
:
5438 case XML_SCHEMAS_NMTOKEN
:
5439 case XML_SCHEMAS_NAME
:
5440 case XML_SCHEMAS_NCNAME
:
5441 case XML_SCHEMAS_ID
:
5442 case XML_SCHEMAS_ANYURI
:
5444 len
= xmlSchemaNormLen(value
);
5450 if (facet
->type
== XML_SCHEMA_FACET_LENGTH
) {
5451 if (len
!= facet
->val
->value
.decimal
.lo
)
5452 return(XML_SCHEMAV_CVC_LENGTH_VALID
);
5453 } else if (facet
->type
== XML_SCHEMA_FACET_MINLENGTH
) {
5454 if (len
< facet
->val
->value
.decimal
.lo
)
5455 return(XML_SCHEMAV_CVC_MINLENGTH_VALID
);
5457 if (len
> facet
->val
->value
.decimal
.lo
)
5458 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID
);
5462 case XML_SCHEMA_FACET_TOTALDIGITS
:
5463 case XML_SCHEMA_FACET_FRACTIONDIGITS
:
5465 if ((facet
->val
== NULL
) ||
5466 ((facet
->val
->type
!= XML_SCHEMAS_PINTEGER
) &&
5467 (facet
->val
->type
!= XML_SCHEMAS_NNINTEGER
)) ||
5468 (facet
->val
->value
.decimal
.frac
!= 0)) {
5471 if ((val
== NULL
) ||
5472 ((val
->type
!= XML_SCHEMAS_DECIMAL
) &&
5473 (val
->type
!= XML_SCHEMAS_INTEGER
) &&
5474 (val
->type
!= XML_SCHEMAS_NPINTEGER
) &&
5475 (val
->type
!= XML_SCHEMAS_NINTEGER
) &&
5476 (val
->type
!= XML_SCHEMAS_NNINTEGER
) &&
5477 (val
->type
!= XML_SCHEMAS_PINTEGER
) &&
5478 (val
->type
!= XML_SCHEMAS_INT
) &&
5479 (val
->type
!= XML_SCHEMAS_UINT
) &&
5480 (val
->type
!= XML_SCHEMAS_LONG
) &&
5481 (val
->type
!= XML_SCHEMAS_ULONG
) &&
5482 (val
->type
!= XML_SCHEMAS_SHORT
) &&
5483 (val
->type
!= XML_SCHEMAS_USHORT
) &&
5484 (val
->type
!= XML_SCHEMAS_BYTE
) &&
5485 (val
->type
!= XML_SCHEMAS_UBYTE
))) {
5488 if (facet
->type
== XML_SCHEMA_FACET_TOTALDIGITS
) {
5489 if (val
->value
.decimal
.total
> facet
->val
->value
.decimal
.lo
)
5490 return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID
);
5492 } else if (facet
->type
== XML_SCHEMA_FACET_FRACTIONDIGITS
) {
5493 if (val
->value
.decimal
.frac
> facet
->val
->value
.decimal
.lo
)
5494 return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID
);
5505 * xmlSchemaValidateFacet:
5506 * @base: the base type
5507 * @facet: the facet to check
5508 * @value: the lexical repr of the value to validate
5509 * @val: the precomputed value
5511 * Check a value against a facet condition
5513 * Returns 0 if the element is schemas valid, a positive error code
5514 * number otherwise and -1 in case of internal or API error.
5517 xmlSchemaValidateFacet(xmlSchemaTypePtr base
,
5518 xmlSchemaFacetPtr facet
,
5519 const xmlChar
*value
,
5520 xmlSchemaValPtr val
)
5523 * This tries to ensure API compatibility regarding the old
5524 * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
5525 * xmlSchemaValidateFacetWhtsp().
5528 return(xmlSchemaValidateFacetInternal(facet
,
5529 XML_SCHEMA_WHITESPACE_UNKNOWN
, val
->type
, value
, val
,
5530 XML_SCHEMA_WHITESPACE_UNKNOWN
));
5531 else if (base
!= NULL
)
5532 return(xmlSchemaValidateFacetInternal(facet
,
5533 XML_SCHEMA_WHITESPACE_UNKNOWN
, base
->builtInType
, value
, val
,
5534 XML_SCHEMA_WHITESPACE_UNKNOWN
));
5539 * xmlSchemaValidateFacetWhtsp:
5540 * @facet: the facet to check
5541 * @fws: the whitespace type of the facet's value
5542 * @valType: the built-in type of the value
5543 * @value: the lexical (or normalized for pattern) repr of the value to validate
5544 * @val: the precomputed value
5545 * @ws: the whitespace type of the value
5547 * Check a value against a facet condition. This takes value normalization
5548 * according to the specified whitespace types into account.
5549 * Note that @value needs to be the *normalized* value if the facet
5550 * is of type "pattern".
5552 * Returns 0 if the element is schemas valid, a positive error code
5553 * number otherwise and -1 in case of internal or API error.
5556 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet
,
5557 xmlSchemaWhitespaceValueType fws
,
5558 xmlSchemaValType valType
,
5559 const xmlChar
*value
,
5560 xmlSchemaValPtr val
,
5561 xmlSchemaWhitespaceValueType ws
)
5563 return(xmlSchemaValidateFacetInternal(facet
, fws
, valType
,
5572 #define DBL_EPSILON 1E-9
5575 #define INTEGER_DIGITS DBL_DIG
5576 #define FRACTION_DIGITS (DBL_DIG + 1)
5577 #define EXPONENT_DIGITS (3 + 2)
5580 * xmlXPathFormatNumber:
5581 * @number: number to format
5582 * @buffer: output buffer
5583 * @buffersize: size of output buffer
5585 * Convert the number into a string representation.
5588 xmlSchemaFormatFloat(double number
, char buffer
[], int buffersize
)
5590 switch (xmlXPathIsInf(number
)) {
5592 if (buffersize
> (int)sizeof("INF"))
5593 snprintf(buffer
, buffersize
, "INF");
5596 if (buffersize
> (int)sizeof("-INF"))
5597 snprintf(buffer
, buffersize
, "-INF");
5600 if (xmlXPathIsNaN(number
)) {
5601 if (buffersize
> (int)sizeof("NaN"))
5602 snprintf(buffer
, buffersize
, "NaN");
5603 } else if (number
== 0) {
5604 snprintf(buffer
, buffersize
, "0.0E0");
5606 /* 3 is sign, decimal point, and terminating zero */
5607 char work
[DBL_DIG
+ EXPONENT_DIGITS
+ 3];
5608 int integer_place
, fraction_place
;
5610 char *after_fraction
;
5611 double absolute_value
;
5614 absolute_value
= fabs(number
);
5617 * Result is in work, and after_fraction points
5618 * just past the fractional part.
5619 * Use scientific notation
5621 integer_place
= DBL_DIG
+ EXPONENT_DIGITS
+ 1;
5622 fraction_place
= DBL_DIG
- 1;
5623 snprintf(work
, sizeof(work
),"%*.*e",
5624 integer_place
, fraction_place
, number
);
5625 after_fraction
= strchr(work
+ DBL_DIG
, 'e');
5626 /* Remove fractional trailing zeroes */
5627 ptr
= after_fraction
;
5628 while (*(--ptr
) == '0')
5632 while ((*ptr
++ = *after_fraction
++) != 0);
5634 /* Finally copy result back to caller */
5635 size
= strlen(work
) + 1;
5636 if (size
> buffersize
) {
5637 work
[buffersize
- 1] = 0;
5640 memmove(buffer
, work
, size
);
5648 * xmlSchemaGetCanonValue:
5649 * @val: the precomputed value
5650 * @retValue: the returned value
5652 * Get the canonical lexical representation of the value.
5653 * The caller has to FREE the returned retValue.
5655 * WARNING: Some value types are not supported yet, resulting
5656 * in a @retValue of "???".
5658 * TODO: XML Schema 1.0 does not define canonical representations
5659 * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay,
5660 * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1.
5663 * Returns 0 if the value could be built, 1 if the value type is
5664 * not supported yet and -1 in case of API errors.
5667 xmlSchemaGetCanonValue(xmlSchemaValPtr val
, const xmlChar
**retValue
)
5669 if ((retValue
== NULL
) || (val
== NULL
))
5672 switch (val
->type
) {
5673 case XML_SCHEMAS_STRING
:
5674 if (val
->value
.str
== NULL
)
5675 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
5678 BAD_CAST
xmlStrdup((const xmlChar
*) val
->value
.str
);
5680 case XML_SCHEMAS_NORMSTRING
:
5681 if (val
->value
.str
== NULL
)
5682 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
5684 *retValue
= xmlSchemaWhiteSpaceReplace(
5685 (const xmlChar
*) val
->value
.str
);
5686 if ((*retValue
) == NULL
)
5687 *retValue
= BAD_CAST
xmlStrdup(
5688 (const xmlChar
*) val
->value
.str
);
5691 case XML_SCHEMAS_TOKEN
:
5692 case XML_SCHEMAS_LANGUAGE
:
5693 case XML_SCHEMAS_NMTOKEN
:
5694 case XML_SCHEMAS_NAME
:
5695 case XML_SCHEMAS_NCNAME
:
5696 case XML_SCHEMAS_ID
:
5697 case XML_SCHEMAS_IDREF
:
5698 case XML_SCHEMAS_ENTITY
:
5699 case XML_SCHEMAS_NOTATION
: /* Unclear */
5700 case XML_SCHEMAS_ANYURI
: /* Unclear */
5701 if (val
->value
.str
== NULL
)
5704 BAD_CAST
xmlSchemaCollapseString(BAD_CAST val
->value
.str
);
5705 if (*retValue
== NULL
)
5707 BAD_CAST
xmlStrdup((const xmlChar
*) val
->value
.str
);
5709 case XML_SCHEMAS_QNAME
:
5710 /* TODO: Unclear in XML Schema 1.0. */
5711 if (val
->value
.qname
.uri
== NULL
) {
5712 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST val
->value
.qname
.name
);
5715 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"{");
5716 *retValue
= BAD_CAST
xmlStrcat((xmlChar
*) (*retValue
),
5717 BAD_CAST val
->value
.qname
.uri
);
5718 *retValue
= BAD_CAST
xmlStrcat((xmlChar
*) (*retValue
),
5720 *retValue
= BAD_CAST
xmlStrcat((xmlChar
*) (*retValue
),
5721 BAD_CAST val
->value
.qname
.uri
);
5724 case XML_SCHEMAS_DECIMAL
:
5726 * TODO: Lookout for a more simple implementation.
5728 if ((val
->value
.decimal
.total
== 1) &&
5729 (val
->value
.decimal
.lo
== 0)) {
5730 *retValue
= xmlStrdup(BAD_CAST
"0.0");
5732 xmlSchemaValDecimal dec
= val
->value
.decimal
;
5734 char *buf
= NULL
, *offs
;
5736 /* Add room for the decimal point as well. */
5737 bufsize
= dec
.total
+ 2;
5740 /* Add room for leading/trailing zero. */
5741 if ((dec
.frac
== 0) || (dec
.frac
== dec
.total
))
5743 buf
= xmlMalloc(bufsize
);
5749 if (dec
.frac
== dec
.total
) {
5754 snprintf(offs
, bufsize
- (offs
- buf
),
5755 "%lu%lu%lu", dec
.hi
, dec
.mi
, dec
.lo
);
5756 else if (dec
.mi
!= 0)
5757 snprintf(offs
, bufsize
- (offs
- buf
),
5758 "%lu%lu", dec
.mi
, dec
.lo
);
5760 snprintf(offs
, bufsize
- (offs
- buf
),
5763 if (dec
.frac
!= 0) {
5764 if (dec
.frac
!= dec
.total
) {
5765 int diff
= dec
.total
- dec
.frac
;
5767 * Insert the decimal point.
5769 memmove(offs
+ diff
+ 1, offs
+ diff
, dec
.frac
+1);
5774 * Insert missing zeroes behind the decimal point.
5776 while (*(offs
+ i
) != 0)
5778 if (i
< dec
.total
) {
5779 memmove(offs
+ (dec
.total
- i
), offs
, i
+1);
5780 memset(offs
, '0', dec
.total
- i
);
5785 * Append decimal point and zero.
5787 offs
= buf
+ bufsize
- 1;
5792 *retValue
= BAD_CAST buf
;
5795 case XML_SCHEMAS_INTEGER
:
5796 case XML_SCHEMAS_PINTEGER
:
5797 case XML_SCHEMAS_NPINTEGER
:
5798 case XML_SCHEMAS_NINTEGER
:
5799 case XML_SCHEMAS_NNINTEGER
:
5800 case XML_SCHEMAS_LONG
:
5801 case XML_SCHEMAS_BYTE
:
5802 case XML_SCHEMAS_SHORT
:
5803 case XML_SCHEMAS_INT
:
5804 case XML_SCHEMAS_UINT
:
5805 case XML_SCHEMAS_ULONG
:
5806 case XML_SCHEMAS_USHORT
:
5807 case XML_SCHEMAS_UBYTE
:
5808 if ((val
->value
.decimal
.total
== 1) &&
5809 (val
->value
.decimal
.lo
== 0))
5810 *retValue
= xmlStrdup(BAD_CAST
"0");
5812 xmlSchemaValDecimal dec
= val
->value
.decimal
;
5813 int bufsize
= dec
.total
+ 1;
5815 /* Add room for the decimal point as well. */
5818 *retValue
= xmlMalloc(bufsize
);
5819 if (*retValue
== NULL
)
5823 snprintf((char *) *retValue
, bufsize
,
5824 "-%lu%lu%lu", dec
.hi
, dec
.mi
, dec
.lo
);
5826 snprintf((char *) *retValue
, bufsize
,
5827 "%lu%lu%lu", dec
.hi
, dec
.mi
, dec
.lo
);
5828 } else if (dec
.mi
!= 0) {
5830 snprintf((char *) *retValue
, bufsize
,
5831 "-%lu%lu", dec
.mi
, dec
.lo
);
5833 snprintf((char *) *retValue
, bufsize
,
5834 "%lu%lu", dec
.mi
, dec
.lo
);
5837 snprintf((char *) *retValue
, bufsize
, "-%lu", dec
.lo
);
5839 snprintf((char *) *retValue
, bufsize
, "%lu", dec
.lo
);
5843 case XML_SCHEMAS_BOOLEAN
:
5845 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"true");
5847 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"false");
5849 case XML_SCHEMAS_DURATION
: {
5852 unsigned long mon
, day
, hour
= 0, min
= 0;
5853 double sec
= 0, left
;
5855 /* TODO: Unclear in XML Schema 1.0 */
5857 * TODO: This results in a normalized output of the value
5858 * - which is NOT conformant to the spec -
5859 * since the exact values of each property are not
5860 * recoverable. Think about extending the structure to
5861 * provide a field for every property.
5863 year
= (unsigned long) FQUOTIENT(labs(val
->value
.dur
.mon
), 12);
5864 mon
= labs(val
->value
.dur
.mon
) - 12 * year
;
5866 day
= (unsigned long) FQUOTIENT(fabs(val
->value
.dur
.sec
), 86400);
5867 left
= fabs(val
->value
.dur
.sec
) - day
* 86400;
5869 hour
= (unsigned long) FQUOTIENT(left
, 3600);
5870 left
= left
- (hour
* 3600);
5872 min
= (unsigned long) FQUOTIENT(left
, 60);
5873 sec
= left
- (min
* 60);
5876 if ((val
->value
.dur
.mon
< 0) || (val
->value
.dur
.sec
< 0))
5877 snprintf(buf
, 100, "P%luY%luM%luDT%luH%luM%.14gS",
5878 year
, mon
, day
, hour
, min
, sec
);
5880 snprintf(buf
, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
5881 year
, mon
, day
, hour
, min
, sec
);
5882 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
5885 case XML_SCHEMAS_GYEAR
: {
5887 /* TODO: Unclear in XML Schema 1.0 */
5888 /* TODO: What to do with the timezone? */
5889 snprintf(buf
, 30, "%04ld", val
->value
.date
.year
);
5890 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
5893 case XML_SCHEMAS_GMONTH
: {
5894 /* TODO: Unclear in XML Schema 1.0 */
5895 /* TODO: What to do with the timezone? */
5896 *retValue
= xmlMalloc(6);
5897 if (*retValue
== NULL
)
5899 snprintf((char *) *retValue
, 6, "--%02u",
5900 val
->value
.date
.mon
);
5903 case XML_SCHEMAS_GDAY
: {
5904 /* TODO: Unclear in XML Schema 1.0 */
5905 /* TODO: What to do with the timezone? */
5906 *retValue
= xmlMalloc(6);
5907 if (*retValue
== NULL
)
5909 snprintf((char *) *retValue
, 6, "---%02u",
5910 val
->value
.date
.day
);
5913 case XML_SCHEMAS_GMONTHDAY
: {
5914 /* TODO: Unclear in XML Schema 1.0 */
5915 /* TODO: What to do with the timezone? */
5916 *retValue
= xmlMalloc(8);
5917 if (*retValue
== NULL
)
5919 snprintf((char *) *retValue
, 8, "--%02u-%02u",
5920 val
->value
.date
.mon
, val
->value
.date
.day
);
5923 case XML_SCHEMAS_GYEARMONTH
: {
5925 /* TODO: Unclear in XML Schema 1.0 */
5926 /* TODO: What to do with the timezone? */
5927 if (val
->value
.date
.year
< 0)
5928 snprintf(buf
, 35, "-%04ld-%02u",
5929 labs(val
->value
.date
.year
),
5930 val
->value
.date
.mon
);
5932 snprintf(buf
, 35, "%04ld-%02u",
5933 val
->value
.date
.year
, val
->value
.date
.mon
);
5934 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
5937 case XML_SCHEMAS_TIME
:
5941 if (val
->value
.date
.tz_flag
) {
5942 xmlSchemaValPtr norm
;
5944 norm
= xmlSchemaDateNormalize(val
, 0);
5948 * TODO: Check if "%.14g" is portable.
5951 "%02u:%02u:%02.14gZ",
5952 norm
->value
.date
.hour
,
5953 norm
->value
.date
.min
,
5954 norm
->value
.date
.sec
);
5955 xmlSchemaFreeValue(norm
);
5958 "%02u:%02u:%02.14g",
5959 val
->value
.date
.hour
,
5960 val
->value
.date
.min
,
5961 val
->value
.date
.sec
);
5963 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
5966 case XML_SCHEMAS_DATE
:
5970 if (val
->value
.date
.tz_flag
) {
5971 xmlSchemaValPtr norm
;
5973 norm
= xmlSchemaDateNormalize(val
, 0);
5977 * TODO: Append the canonical value of the
5978 * recoverable timezone and not "Z".
5982 norm
->value
.date
.year
, norm
->value
.date
.mon
,
5983 norm
->value
.date
.day
);
5984 xmlSchemaFreeValue(norm
);
5988 val
->value
.date
.year
, val
->value
.date
.mon
,
5989 val
->value
.date
.day
);
5991 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
5994 case XML_SCHEMAS_DATETIME
:
5998 if (val
->value
.date
.tz_flag
) {
5999 xmlSchemaValPtr norm
;
6001 norm
= xmlSchemaDateNormalize(val
, 0);
6005 * TODO: Check if "%.14g" is portable.
6008 "%04ld:%02u:%02uT%02u:%02u:%02.14gZ",
6009 norm
->value
.date
.year
, norm
->value
.date
.mon
,
6010 norm
->value
.date
.day
, norm
->value
.date
.hour
,
6011 norm
->value
.date
.min
, norm
->value
.date
.sec
);
6012 xmlSchemaFreeValue(norm
);
6015 "%04ld:%02u:%02uT%02u:%02u:%02.14g",
6016 val
->value
.date
.year
, val
->value
.date
.mon
,
6017 val
->value
.date
.day
, val
->value
.date
.hour
,
6018 val
->value
.date
.min
, val
->value
.date
.sec
);
6020 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6023 case XML_SCHEMAS_HEXBINARY
:
6024 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST val
->value
.hex
.str
);
6026 case XML_SCHEMAS_BASE64BINARY
:
6028 * TODO: Is the following spec piece implemented?:
6029 * SPEC: "Note: For some values the canonical form defined
6030 * above does not conform to [RFC 2045], which requires breaking
6031 * with linefeeds at appropriate intervals."
6033 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST val
->value
.base64
.str
);
6035 case XML_SCHEMAS_FLOAT
: {
6038 * |m| < 16777216, -149 <= e <= 104.
6039 * TODO: Handle, NaN, INF, -INF. The format is not
6040 * yet conformant. The c type float does not cover
6043 snprintf(buf
, 30, "%01.14e", val
->value
.f
);
6044 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6047 case XML_SCHEMAS_DOUBLE
: {
6049 /* |m| < 9007199254740992, -1075 <= e <= 970 */
6051 * TODO: Handle, NaN, INF, -INF. The format is not
6052 * yet conformant. The c type float does not cover
6055 snprintf(buf
, 40, "%01.14e", val
->value
.d
);
6056 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6060 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"???");
6063 if (*retValue
== NULL
)
6069 * xmlSchemaGetCanonValueWhtsp:
6070 * @val: the precomputed value
6071 * @retValue: the returned value
6072 * @ws: the whitespace type of the value
6074 * Get the canonical representation of the value.
6075 * The caller has to free the returned @retValue.
6077 * Returns 0 if the value could be built, 1 if the value type is
6078 * not supported yet and -1 in case of API errors.
6081 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val
,
6082 const xmlChar
**retValue
,
6083 xmlSchemaWhitespaceValueType ws
)
6085 if ((retValue
== NULL
) || (val
== NULL
))
6087 if ((ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) ||
6088 (ws
> XML_SCHEMA_WHITESPACE_COLLAPSE
))
6092 switch (val
->type
) {
6093 case XML_SCHEMAS_STRING
:
6094 if (val
->value
.str
== NULL
)
6095 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
6096 else if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
6097 *retValue
= xmlSchemaCollapseString(val
->value
.str
);
6098 else if (ws
== XML_SCHEMA_WHITESPACE_REPLACE
)
6099 *retValue
= xmlSchemaWhiteSpaceReplace(val
->value
.str
);
6100 if ((*retValue
) == NULL
)
6101 *retValue
= BAD_CAST
xmlStrdup(val
->value
.str
);
6103 case XML_SCHEMAS_NORMSTRING
:
6104 if (val
->value
.str
== NULL
)
6105 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
6107 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
6108 *retValue
= xmlSchemaCollapseString(val
->value
.str
);
6110 *retValue
= xmlSchemaWhiteSpaceReplace(val
->value
.str
);
6111 if ((*retValue
) == NULL
)
6112 *retValue
= BAD_CAST
xmlStrdup(val
->value
.str
);
6116 return (xmlSchemaGetCanonValue(val
, retValue
));
6122 * xmlSchemaGetValType:
6123 * @val: a schemas value
6125 * Accessor for the type of a value
6127 * Returns the xmlSchemaValType of the value
6130 xmlSchemaGetValType(xmlSchemaValPtr val
)
6133 return(XML_SCHEMAS_UNKNOWN
);
6137 #define bottom_xmlschemastypes
6138 #include "elfgcchack.h"
6139 #endif /* LIBXML_SCHEMAS_ENABLED */