2 * schemastypes.c : implementation of the XML Schema Datatypes
3 * definition and validity checking
5 * See Copyright for the status of this software.
7 * Daniel Veillard <veillard@redhat.com>
10 /* To avoid EBCDIC trouble when parsing on zOS */
12 #pragma convert("ISO8859-1")
18 #ifdef LIBXML_SCHEMAS_ENABLED
24 #include <libxml/xmlmemory.h>
25 #include <libxml/parser.h>
26 #include <libxml/parserInternals.h>
27 #include <libxml/hash.h>
28 #include <libxml/valid.h>
29 #include <libxml/xpath.h>
30 #include <libxml/uri.h>
32 #include <libxml/xmlschemas.h>
33 #include <libxml/schemasInternals.h>
34 #include <libxml/xmlschemastypes.h>
36 #include "private/error.h"
40 #ifndef LIBXML_XPATH_ENABLED
41 extern double xmlXPathNAN
;
42 extern double xmlXPathPINF
;
43 extern double xmlXPathNINF
;
47 xmlGenericError(xmlGenericErrorContext, \
48 "Unimplemented block at %s:%d\n", \
51 #define XML_SCHEMAS_NAMESPACE_NAME \
52 (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
54 #define IS_WSP_REPLACE_CH(c) ((((c) == 0x9) || ((c) == 0xa)) || \
57 #define IS_WSP_SPACE_CH(c) ((c) == 0x20)
59 #define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c)
62 typedef struct _xmlSchemaValDate xmlSchemaValDate
;
63 typedef xmlSchemaValDate
*xmlSchemaValDatePtr
;
64 struct _xmlSchemaValDate
{
66 unsigned int mon
:4; /* 1 <= mon <= 12 */
67 unsigned int day
:5; /* 1 <= day <= 31 */
68 unsigned int hour
:5; /* 0 <= hour <= 24 */
69 unsigned int min
:6; /* 0 <= min <= 59 */
71 unsigned int tz_flag
:1; /* is tzo explicitly set? */
72 signed int tzo
:12; /* -1440 <= tzo <= 1440;
73 currently only -840 to +840 are needed */
77 typedef struct _xmlSchemaValDuration xmlSchemaValDuration
;
78 typedef xmlSchemaValDuration
*xmlSchemaValDurationPtr
;
79 struct _xmlSchemaValDuration
{
80 long mon
; /* mon stores years also */
82 double sec
; /* sec stores min and hour also */
85 typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal
;
86 typedef xmlSchemaValDecimal
*xmlSchemaValDecimalPtr
;
87 struct _xmlSchemaValDecimal
{
88 /* would use long long but not portable */
98 typedef struct _xmlSchemaValQName xmlSchemaValQName
;
99 typedef xmlSchemaValQName
*xmlSchemaValQNamePtr
;
100 struct _xmlSchemaValQName
{
105 typedef struct _xmlSchemaValHex xmlSchemaValHex
;
106 typedef xmlSchemaValHex
*xmlSchemaValHexPtr
;
107 struct _xmlSchemaValHex
{
112 typedef struct _xmlSchemaValBase64 xmlSchemaValBase64
;
113 typedef xmlSchemaValBase64
*xmlSchemaValBase64Ptr
;
114 struct _xmlSchemaValBase64
{
119 struct _xmlSchemaVal
{
120 xmlSchemaValType type
;
121 struct _xmlSchemaVal
*next
;
123 xmlSchemaValDecimal decimal
;
124 xmlSchemaValDate date
;
125 xmlSchemaValDuration dur
;
126 xmlSchemaValQName qname
;
128 xmlSchemaValBase64 base64
;
136 static int xmlSchemaTypesInitialized
= 0;
137 static xmlHashTablePtr xmlSchemaTypesBank
= NULL
;
142 static xmlSchemaTypePtr xmlSchemaTypeStringDef
= NULL
;
143 static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef
= NULL
;
144 static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef
= NULL
;
145 static xmlSchemaTypePtr xmlSchemaTypeDecimalDef
= NULL
;
146 static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef
= NULL
;
147 static xmlSchemaTypePtr xmlSchemaTypeDateDef
= NULL
;
148 static xmlSchemaTypePtr xmlSchemaTypeTimeDef
= NULL
;
149 static xmlSchemaTypePtr xmlSchemaTypeGYearDef
= NULL
;
150 static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef
= NULL
;
151 static xmlSchemaTypePtr xmlSchemaTypeGDayDef
= NULL
;
152 static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef
= NULL
;
153 static xmlSchemaTypePtr xmlSchemaTypeGMonthDef
= NULL
;
154 static xmlSchemaTypePtr xmlSchemaTypeDurationDef
= NULL
;
155 static xmlSchemaTypePtr xmlSchemaTypeFloatDef
= NULL
;
156 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef
= NULL
;
157 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef
= NULL
;
158 static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef
= NULL
;
159 static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef
= NULL
;
160 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef
= NULL
;
165 static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef
= NULL
;
166 static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef
= NULL
;
167 static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef
= NULL
;
168 static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef
= NULL
;
169 static xmlSchemaTypePtr xmlSchemaTypeIntegerDef
= NULL
;
170 static xmlSchemaTypePtr xmlSchemaTypeLongDef
= NULL
;
171 static xmlSchemaTypePtr xmlSchemaTypeIntDef
= NULL
;
172 static xmlSchemaTypePtr xmlSchemaTypeShortDef
= NULL
;
173 static xmlSchemaTypePtr xmlSchemaTypeByteDef
= NULL
;
174 static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef
= NULL
;
175 static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef
= NULL
;
176 static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef
= NULL
;
177 static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef
= NULL
;
178 static xmlSchemaTypePtr xmlSchemaTypeNormStringDef
= NULL
;
179 static xmlSchemaTypePtr xmlSchemaTypeTokenDef
= NULL
;
180 static xmlSchemaTypePtr xmlSchemaTypeLanguageDef
= NULL
;
181 static xmlSchemaTypePtr xmlSchemaTypeNameDef
= NULL
;
182 static xmlSchemaTypePtr xmlSchemaTypeQNameDef
= NULL
;
183 static xmlSchemaTypePtr xmlSchemaTypeNCNameDef
= NULL
;
184 static xmlSchemaTypePtr xmlSchemaTypeIdDef
= NULL
;
185 static xmlSchemaTypePtr xmlSchemaTypeIdrefDef
= NULL
;
186 static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef
= NULL
;
187 static xmlSchemaTypePtr xmlSchemaTypeEntityDef
= NULL
;
188 static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef
= NULL
;
189 static xmlSchemaTypePtr xmlSchemaTypeNotationDef
= NULL
;
190 static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef
= NULL
;
191 static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef
= NULL
;
193 /************************************************************************
195 * Datatype error handlers *
197 ************************************************************************/
199 * xmlSchemaTypeErrMemory:
200 * @extra: extra information
202 * Handle an out of memory condition
205 xmlSchemaTypeErrMemory(xmlNodePtr node
, const char *extra
)
207 __xmlSimpleError(XML_FROM_DATATYPE
, XML_ERR_NO_MEMORY
, node
, NULL
, extra
);
210 /************************************************************************
212 * Base types support *
214 ************************************************************************/
218 * @type: the value type
220 * Allocate a new simple type value
222 * Returns a pointer to the new value or NULL in case of error
224 static xmlSchemaValPtr
225 xmlSchemaNewValue(xmlSchemaValType type
) {
226 xmlSchemaValPtr value
;
228 value
= (xmlSchemaValPtr
) xmlMalloc(sizeof(xmlSchemaVal
));
232 memset(value
, 0, sizeof(xmlSchemaVal
));
237 static xmlSchemaFacetPtr
238 xmlSchemaNewMinLengthFacet(int value
)
240 xmlSchemaFacetPtr ret
;
242 ret
= xmlSchemaNewFacet();
246 ret
->type
= XML_SCHEMA_FACET_MINLENGTH
;
247 ret
->val
= xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER
);
248 if (ret
->val
== NULL
) {
252 ret
->val
->value
.decimal
.lo
= value
;
257 * xmlSchemaInitBasicType:
258 * @name: the type name
259 * @type: the value type associated
261 * Initialize one primitive built-in type
263 static xmlSchemaTypePtr
264 xmlSchemaInitBasicType(const char *name
, xmlSchemaValType type
,
265 xmlSchemaTypePtr baseType
) {
266 xmlSchemaTypePtr ret
;
268 ret
= (xmlSchemaTypePtr
) xmlMalloc(sizeof(xmlSchemaType
));
270 xmlSchemaTypeErrMemory(NULL
, "could not initialize basic types");
273 memset(ret
, 0, sizeof(xmlSchemaType
));
274 ret
->name
= (const xmlChar
*)name
;
275 ret
->targetNamespace
= XML_SCHEMAS_NAMESPACE_NAME
;
276 ret
->type
= XML_SCHEMA_TYPE_BASIC
;
277 ret
->baseType
= baseType
;
278 ret
->contentType
= XML_SCHEMA_CONTENT_BASIC
;
283 case XML_SCHEMAS_STRING
:
284 case XML_SCHEMAS_DECIMAL
:
285 case XML_SCHEMAS_DATE
:
286 case XML_SCHEMAS_DATETIME
:
287 case XML_SCHEMAS_TIME
:
288 case XML_SCHEMAS_GYEAR
:
289 case XML_SCHEMAS_GYEARMONTH
:
290 case XML_SCHEMAS_GMONTH
:
291 case XML_SCHEMAS_GMONTHDAY
:
292 case XML_SCHEMAS_GDAY
:
293 case XML_SCHEMAS_DURATION
:
294 case XML_SCHEMAS_FLOAT
:
295 case XML_SCHEMAS_DOUBLE
:
296 case XML_SCHEMAS_BOOLEAN
:
297 case XML_SCHEMAS_ANYURI
:
298 case XML_SCHEMAS_HEXBINARY
:
299 case XML_SCHEMAS_BASE64BINARY
:
300 case XML_SCHEMAS_QNAME
:
301 case XML_SCHEMAS_NOTATION
:
302 ret
->flags
|= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE
;
311 case XML_SCHEMAS_ANYTYPE
:
312 case XML_SCHEMAS_ANYSIMPLETYPE
:
314 case XML_SCHEMAS_IDREFS
:
315 case XML_SCHEMAS_NMTOKENS
:
316 case XML_SCHEMAS_ENTITIES
:
317 ret
->flags
|= XML_SCHEMAS_TYPE_VARIETY_LIST
;
318 ret
->facets
= xmlSchemaNewMinLengthFacet(1);
319 ret
->flags
|= XML_SCHEMAS_TYPE_HAS_FACETS
;
322 ret
->flags
|= XML_SCHEMAS_TYPE_VARIETY_ATOMIC
;
325 xmlHashAddEntry2(xmlSchemaTypesBank
, ret
->name
,
326 XML_SCHEMAS_NAMESPACE_NAME
, ret
);
327 ret
->builtInType
= type
;
332 * WARNING: Those type reside normally in xmlschemas.c but are
333 * redefined here locally in oder of being able to use them for xs:anyType-
334 * TODO: Remove those definition if we move the types to a header file.
335 * TODO: Always keep those structs up-to-date with the originals.
337 #define UNBOUNDED (1 << 30)
339 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem
;
340 typedef xmlSchemaTreeItem
*xmlSchemaTreeItemPtr
;
341 struct _xmlSchemaTreeItem
{
342 xmlSchemaTypeType type
;
343 xmlSchemaAnnotPtr annot
;
344 xmlSchemaTreeItemPtr next
;
345 xmlSchemaTreeItemPtr children
;
348 typedef struct _xmlSchemaParticle xmlSchemaParticle
;
349 typedef xmlSchemaParticle
*xmlSchemaParticlePtr
;
350 struct _xmlSchemaParticle
{
351 xmlSchemaTypeType type
;
352 xmlSchemaAnnotPtr annot
;
353 xmlSchemaTreeItemPtr next
;
354 xmlSchemaTreeItemPtr children
;
360 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup
;
361 typedef xmlSchemaModelGroup
*xmlSchemaModelGroupPtr
;
362 struct _xmlSchemaModelGroup
{
363 xmlSchemaTypeType type
;
364 xmlSchemaAnnotPtr annot
;
365 xmlSchemaTreeItemPtr next
;
366 xmlSchemaTreeItemPtr children
;
370 static xmlSchemaParticlePtr
371 xmlSchemaAddParticle(void)
373 xmlSchemaParticlePtr ret
= NULL
;
375 ret
= (xmlSchemaParticlePtr
)
376 xmlMalloc(sizeof(xmlSchemaParticle
));
378 xmlSchemaTypeErrMemory(NULL
, "allocating particle component");
381 memset(ret
, 0, sizeof(xmlSchemaParticle
));
382 ret
->type
= XML_SCHEMA_TYPE_PARTICLE
;
389 xmlSchemaFreeTypeEntry(void *type
, const xmlChar
*name ATTRIBUTE_UNUSED
) {
390 xmlSchemaFreeType((xmlSchemaTypePtr
) type
);
394 * xmlSchemaCleanupTypesInternal:
396 * Cleanup the default XML Schemas type library
399 xmlSchemaCleanupTypesInternal(void) {
400 xmlSchemaParticlePtr particle
;
405 if (xmlSchemaTypeAnyTypeDef
!= NULL
) {
406 /* Attribute wildcard. */
407 xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef
->attributeWildcard
);
409 particle
= (xmlSchemaParticlePtr
) xmlSchemaTypeAnyTypeDef
->subtypes
;
411 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr
)
412 particle
->children
->children
->children
);
413 xmlFree((xmlSchemaParticlePtr
) particle
->children
->children
);
414 /* Sequence model group. */
415 xmlFree((xmlSchemaModelGroupPtr
) particle
->children
);
416 xmlFree((xmlSchemaParticlePtr
) particle
);
417 xmlSchemaTypeAnyTypeDef
->subtypes
= NULL
;
418 xmlSchemaTypeAnyTypeDef
= NULL
;
421 xmlHashFree(xmlSchemaTypesBank
, xmlSchemaFreeTypeEntry
);
422 xmlSchemaTypesBank
= NULL
;
423 /* Note that the xmlSchemaType*Def pointers aren't set to NULL. */
427 * xmlSchemaInitTypes:
429 * Initialize the default XML Schemas type library
431 * Returns 0 on success, -1 on error.
434 xmlSchemaInitTypes(void)
436 if (xmlSchemaTypesInitialized
!= 0)
438 xmlSchemaTypesBank
= xmlHashCreate(40);
439 if (xmlSchemaTypesBank
== NULL
) {
440 xmlSchemaTypeErrMemory(NULL
, NULL
);
445 * 3.4.7 Built-in Complex Type Definition
447 xmlSchemaTypeAnyTypeDef
= xmlSchemaInitBasicType("anyType",
450 if (xmlSchemaTypeAnyTypeDef
== NULL
)
452 xmlSchemaTypeAnyTypeDef
->baseType
= xmlSchemaTypeAnyTypeDef
;
453 xmlSchemaTypeAnyTypeDef
->contentType
= XML_SCHEMA_CONTENT_MIXED
;
455 * Init the content type.
457 xmlSchemaTypeAnyTypeDef
->contentType
= XML_SCHEMA_CONTENT_MIXED
;
459 xmlSchemaParticlePtr particle
;
460 xmlSchemaModelGroupPtr sequence
;
461 xmlSchemaWildcardPtr wild
;
462 /* First particle. */
463 particle
= xmlSchemaAddParticle();
464 if (particle
== NULL
)
466 xmlSchemaTypeAnyTypeDef
->subtypes
= (xmlSchemaTypePtr
) particle
;
467 /* Sequence model group. */
468 sequence
= (xmlSchemaModelGroupPtr
)
469 xmlMalloc(sizeof(xmlSchemaModelGroup
));
470 if (sequence
== NULL
) {
471 xmlSchemaTypeErrMemory(NULL
, "allocating model group component");
474 memset(sequence
, 0, sizeof(xmlSchemaModelGroup
));
475 sequence
->type
= XML_SCHEMA_TYPE_SEQUENCE
;
476 particle
->children
= (xmlSchemaTreeItemPtr
) sequence
;
477 /* Second particle. */
478 particle
= xmlSchemaAddParticle();
479 if (particle
== NULL
)
481 particle
->minOccurs
= 0;
482 particle
->maxOccurs
= UNBOUNDED
;
483 sequence
->children
= (xmlSchemaTreeItemPtr
) particle
;
485 wild
= (xmlSchemaWildcardPtr
) xmlMalloc(sizeof(xmlSchemaWildcard
));
487 xmlSchemaTypeErrMemory(NULL
, "allocating wildcard component");
490 memset(wild
, 0, sizeof(xmlSchemaWildcard
));
491 wild
->type
= XML_SCHEMA_TYPE_ANY
;
493 wild
->processContents
= XML_SCHEMAS_ANY_LAX
;
494 particle
->children
= (xmlSchemaTreeItemPtr
) wild
;
496 * Create the attribute wildcard.
498 wild
= (xmlSchemaWildcardPtr
) xmlMalloc(sizeof(xmlSchemaWildcard
));
500 xmlSchemaTypeErrMemory(NULL
, "could not create an attribute "
501 "wildcard on anyType");
504 memset(wild
, 0, sizeof(xmlSchemaWildcard
));
506 wild
->processContents
= XML_SCHEMAS_ANY_LAX
;
507 xmlSchemaTypeAnyTypeDef
->attributeWildcard
= wild
;
509 xmlSchemaTypeAnySimpleTypeDef
= xmlSchemaInitBasicType("anySimpleType",
510 XML_SCHEMAS_ANYSIMPLETYPE
,
511 xmlSchemaTypeAnyTypeDef
);
512 if (xmlSchemaTypeAnySimpleTypeDef
== NULL
)
515 * primitive datatypes
517 xmlSchemaTypeStringDef
= xmlSchemaInitBasicType("string",
519 xmlSchemaTypeAnySimpleTypeDef
);
520 if (xmlSchemaTypeStringDef
== NULL
)
522 xmlSchemaTypeDecimalDef
= xmlSchemaInitBasicType("decimal",
524 xmlSchemaTypeAnySimpleTypeDef
);
525 if (xmlSchemaTypeDecimalDef
== NULL
)
527 xmlSchemaTypeDateDef
= xmlSchemaInitBasicType("date",
529 xmlSchemaTypeAnySimpleTypeDef
);
530 if (xmlSchemaTypeDateDef
== NULL
)
532 xmlSchemaTypeDatetimeDef
= xmlSchemaInitBasicType("dateTime",
533 XML_SCHEMAS_DATETIME
,
534 xmlSchemaTypeAnySimpleTypeDef
);
535 if (xmlSchemaTypeDatetimeDef
== NULL
)
537 xmlSchemaTypeTimeDef
= xmlSchemaInitBasicType("time",
539 xmlSchemaTypeAnySimpleTypeDef
);
540 if (xmlSchemaTypeTimeDef
== NULL
)
542 xmlSchemaTypeGYearDef
= xmlSchemaInitBasicType("gYear",
544 xmlSchemaTypeAnySimpleTypeDef
);
545 if (xmlSchemaTypeGYearDef
== NULL
)
547 xmlSchemaTypeGYearMonthDef
= xmlSchemaInitBasicType("gYearMonth",
548 XML_SCHEMAS_GYEARMONTH
,
549 xmlSchemaTypeAnySimpleTypeDef
);
550 if (xmlSchemaTypeGYearMonthDef
== NULL
)
552 xmlSchemaTypeGMonthDef
= xmlSchemaInitBasicType("gMonth",
554 xmlSchemaTypeAnySimpleTypeDef
);
555 if (xmlSchemaTypeGMonthDef
== NULL
)
557 xmlSchemaTypeGMonthDayDef
= xmlSchemaInitBasicType("gMonthDay",
558 XML_SCHEMAS_GMONTHDAY
,
559 xmlSchemaTypeAnySimpleTypeDef
);
560 if (xmlSchemaTypeGMonthDayDef
== NULL
)
562 xmlSchemaTypeGDayDef
= xmlSchemaInitBasicType("gDay",
564 xmlSchemaTypeAnySimpleTypeDef
);
565 if (xmlSchemaTypeGDayDef
== NULL
)
567 xmlSchemaTypeDurationDef
= xmlSchemaInitBasicType("duration",
568 XML_SCHEMAS_DURATION
,
569 xmlSchemaTypeAnySimpleTypeDef
);
570 if (xmlSchemaTypeDurationDef
== NULL
)
572 xmlSchemaTypeFloatDef
= xmlSchemaInitBasicType("float",
574 xmlSchemaTypeAnySimpleTypeDef
);
575 if (xmlSchemaTypeFloatDef
== NULL
)
577 xmlSchemaTypeDoubleDef
= xmlSchemaInitBasicType("double",
579 xmlSchemaTypeAnySimpleTypeDef
);
580 if (xmlSchemaTypeDoubleDef
== NULL
)
582 xmlSchemaTypeBooleanDef
= xmlSchemaInitBasicType("boolean",
584 xmlSchemaTypeAnySimpleTypeDef
);
585 if (xmlSchemaTypeBooleanDef
== NULL
)
587 xmlSchemaTypeAnyURIDef
= xmlSchemaInitBasicType("anyURI",
589 xmlSchemaTypeAnySimpleTypeDef
);
590 if (xmlSchemaTypeAnyURIDef
== NULL
)
592 xmlSchemaTypeHexBinaryDef
= xmlSchemaInitBasicType("hexBinary",
593 XML_SCHEMAS_HEXBINARY
,
594 xmlSchemaTypeAnySimpleTypeDef
);
595 if (xmlSchemaTypeHexBinaryDef
== NULL
)
597 xmlSchemaTypeBase64BinaryDef
598 = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY
,
599 xmlSchemaTypeAnySimpleTypeDef
);
600 if (xmlSchemaTypeBase64BinaryDef
== NULL
)
602 xmlSchemaTypeNotationDef
= xmlSchemaInitBasicType("NOTATION",
603 XML_SCHEMAS_NOTATION
,
604 xmlSchemaTypeAnySimpleTypeDef
);
605 if (xmlSchemaTypeNotationDef
== NULL
)
607 xmlSchemaTypeQNameDef
= xmlSchemaInitBasicType("QName",
609 xmlSchemaTypeAnySimpleTypeDef
);
610 if (xmlSchemaTypeQNameDef
== NULL
)
616 xmlSchemaTypeIntegerDef
= xmlSchemaInitBasicType("integer",
618 xmlSchemaTypeDecimalDef
);
619 if (xmlSchemaTypeIntegerDef
== NULL
)
621 xmlSchemaTypeNonPositiveIntegerDef
=
622 xmlSchemaInitBasicType("nonPositiveInteger",
623 XML_SCHEMAS_NPINTEGER
,
624 xmlSchemaTypeIntegerDef
);
625 if (xmlSchemaTypeNonPositiveIntegerDef
== NULL
)
627 xmlSchemaTypeNegativeIntegerDef
=
628 xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER
,
629 xmlSchemaTypeNonPositiveIntegerDef
);
630 if (xmlSchemaTypeNegativeIntegerDef
== NULL
)
632 xmlSchemaTypeLongDef
=
633 xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG
,
634 xmlSchemaTypeIntegerDef
);
635 if (xmlSchemaTypeLongDef
== NULL
)
637 xmlSchemaTypeIntDef
= xmlSchemaInitBasicType("int", XML_SCHEMAS_INT
,
638 xmlSchemaTypeLongDef
);
639 if (xmlSchemaTypeIntDef
== NULL
)
641 xmlSchemaTypeShortDef
= xmlSchemaInitBasicType("short",
643 xmlSchemaTypeIntDef
);
644 if (xmlSchemaTypeShortDef
== NULL
)
646 xmlSchemaTypeByteDef
= xmlSchemaInitBasicType("byte",
648 xmlSchemaTypeShortDef
);
649 if (xmlSchemaTypeByteDef
== NULL
)
651 xmlSchemaTypeNonNegativeIntegerDef
=
652 xmlSchemaInitBasicType("nonNegativeInteger",
653 XML_SCHEMAS_NNINTEGER
,
654 xmlSchemaTypeIntegerDef
);
655 if (xmlSchemaTypeNonNegativeIntegerDef
== NULL
)
657 xmlSchemaTypeUnsignedLongDef
=
658 xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG
,
659 xmlSchemaTypeNonNegativeIntegerDef
);
660 if (xmlSchemaTypeUnsignedLongDef
== NULL
)
662 xmlSchemaTypeUnsignedIntDef
=
663 xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT
,
664 xmlSchemaTypeUnsignedLongDef
);
665 if (xmlSchemaTypeUnsignedIntDef
== NULL
)
667 xmlSchemaTypeUnsignedShortDef
=
668 xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT
,
669 xmlSchemaTypeUnsignedIntDef
);
670 if (xmlSchemaTypeUnsignedShortDef
== NULL
)
672 xmlSchemaTypeUnsignedByteDef
=
673 xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE
,
674 xmlSchemaTypeUnsignedShortDef
);
675 if (xmlSchemaTypeUnsignedByteDef
== NULL
)
677 xmlSchemaTypePositiveIntegerDef
=
678 xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER
,
679 xmlSchemaTypeNonNegativeIntegerDef
);
680 if (xmlSchemaTypePositiveIntegerDef
== NULL
)
682 xmlSchemaTypeNormStringDef
= xmlSchemaInitBasicType("normalizedString",
683 XML_SCHEMAS_NORMSTRING
,
684 xmlSchemaTypeStringDef
);
685 if (xmlSchemaTypeNormStringDef
== NULL
)
687 xmlSchemaTypeTokenDef
= xmlSchemaInitBasicType("token",
689 xmlSchemaTypeNormStringDef
);
690 if (xmlSchemaTypeTokenDef
== NULL
)
692 xmlSchemaTypeLanguageDef
= xmlSchemaInitBasicType("language",
693 XML_SCHEMAS_LANGUAGE
,
694 xmlSchemaTypeTokenDef
);
695 if (xmlSchemaTypeLanguageDef
== NULL
)
697 xmlSchemaTypeNameDef
= xmlSchemaInitBasicType("Name",
699 xmlSchemaTypeTokenDef
);
700 if (xmlSchemaTypeNameDef
== NULL
)
702 xmlSchemaTypeNmtokenDef
= xmlSchemaInitBasicType("NMTOKEN",
704 xmlSchemaTypeTokenDef
);
705 if (xmlSchemaTypeNmtokenDef
== NULL
)
707 xmlSchemaTypeNCNameDef
= xmlSchemaInitBasicType("NCName",
709 xmlSchemaTypeNameDef
);
710 if (xmlSchemaTypeNCNameDef
== NULL
)
712 xmlSchemaTypeIdDef
= xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID
,
713 xmlSchemaTypeNCNameDef
);
714 if (xmlSchemaTypeIdDef
== NULL
)
716 xmlSchemaTypeIdrefDef
= xmlSchemaInitBasicType("IDREF",
718 xmlSchemaTypeNCNameDef
);
719 if (xmlSchemaTypeIdrefDef
== NULL
)
721 xmlSchemaTypeEntityDef
= xmlSchemaInitBasicType("ENTITY",
723 xmlSchemaTypeNCNameDef
);
724 if (xmlSchemaTypeEntityDef
== NULL
)
727 * Derived list types.
730 xmlSchemaTypeEntitiesDef
= xmlSchemaInitBasicType("ENTITIES",
731 XML_SCHEMAS_ENTITIES
,
732 xmlSchemaTypeAnySimpleTypeDef
);
733 if (xmlSchemaTypeEntitiesDef
== NULL
)
735 xmlSchemaTypeEntitiesDef
->subtypes
= xmlSchemaTypeEntityDef
;
737 xmlSchemaTypeIdrefsDef
= xmlSchemaInitBasicType("IDREFS",
739 xmlSchemaTypeAnySimpleTypeDef
);
740 if (xmlSchemaTypeIdrefsDef
== NULL
)
742 xmlSchemaTypeIdrefsDef
->subtypes
= xmlSchemaTypeIdrefDef
;
745 xmlSchemaTypeNmtokensDef
= xmlSchemaInitBasicType("NMTOKENS",
746 XML_SCHEMAS_NMTOKENS
,
747 xmlSchemaTypeAnySimpleTypeDef
);
748 if (xmlSchemaTypeNmtokensDef
== NULL
)
750 xmlSchemaTypeNmtokensDef
->subtypes
= xmlSchemaTypeNmtokenDef
;
752 xmlSchemaTypesInitialized
= 1;
756 xmlSchemaCleanupTypesInternal();
761 * xmlSchemaCleanupTypes:
763 * DEPRECATED: This function will be made private. Call xmlCleanupParser
764 * to free global state but see the warnings there. xmlCleanupParser
765 * should be only called once at program exit. In most cases, you don't
766 * have to call cleanup functions at all.
768 * Cleanup the default XML Schemas type library
771 xmlSchemaCleanupTypes(void) {
772 if (xmlSchemaTypesInitialized
!= 0) {
773 xmlSchemaCleanupTypesInternal();
774 xmlSchemaTypesInitialized
= 0;
779 * xmlSchemaIsBuiltInTypeFacet:
780 * @type: the built-in type
781 * @facetType: the facet type
783 * Evaluates if a specific facet can be
784 * used in conjunction with a type.
786 * Returns 1 if the facet can be used with the given built-in type,
787 * 0 otherwise and -1 in case the type is not a built-in type.
790 xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type
, int facetType
)
794 if (type
->type
!= XML_SCHEMA_TYPE_BASIC
)
796 switch (type
->builtInType
) {
797 case XML_SCHEMAS_BOOLEAN
:
798 if ((facetType
== XML_SCHEMA_FACET_PATTERN
) ||
799 (facetType
== XML_SCHEMA_FACET_WHITESPACE
))
803 case XML_SCHEMAS_STRING
:
804 case XML_SCHEMAS_NOTATION
:
805 case XML_SCHEMAS_QNAME
:
806 case XML_SCHEMAS_ANYURI
:
807 case XML_SCHEMAS_BASE64BINARY
:
808 case XML_SCHEMAS_HEXBINARY
:
809 if ((facetType
== XML_SCHEMA_FACET_LENGTH
) ||
810 (facetType
== XML_SCHEMA_FACET_MINLENGTH
) ||
811 (facetType
== XML_SCHEMA_FACET_MAXLENGTH
) ||
812 (facetType
== XML_SCHEMA_FACET_PATTERN
) ||
813 (facetType
== XML_SCHEMA_FACET_ENUMERATION
) ||
814 (facetType
== XML_SCHEMA_FACET_WHITESPACE
))
818 case XML_SCHEMAS_DECIMAL
:
819 if ((facetType
== XML_SCHEMA_FACET_TOTALDIGITS
) ||
820 (facetType
== XML_SCHEMA_FACET_FRACTIONDIGITS
) ||
821 (facetType
== XML_SCHEMA_FACET_PATTERN
) ||
822 (facetType
== XML_SCHEMA_FACET_WHITESPACE
) ||
823 (facetType
== XML_SCHEMA_FACET_ENUMERATION
) ||
824 (facetType
== XML_SCHEMA_FACET_MAXINCLUSIVE
) ||
825 (facetType
== XML_SCHEMA_FACET_MAXEXCLUSIVE
) ||
826 (facetType
== XML_SCHEMA_FACET_MININCLUSIVE
) ||
827 (facetType
== XML_SCHEMA_FACET_MINEXCLUSIVE
))
831 case XML_SCHEMAS_TIME
:
832 case XML_SCHEMAS_GDAY
:
833 case XML_SCHEMAS_GMONTH
:
834 case XML_SCHEMAS_GMONTHDAY
:
835 case XML_SCHEMAS_GYEAR
:
836 case XML_SCHEMAS_GYEARMONTH
:
837 case XML_SCHEMAS_DATE
:
838 case XML_SCHEMAS_DATETIME
:
839 case XML_SCHEMAS_DURATION
:
840 case XML_SCHEMAS_FLOAT
:
841 case XML_SCHEMAS_DOUBLE
:
842 if ((facetType
== XML_SCHEMA_FACET_PATTERN
) ||
843 (facetType
== XML_SCHEMA_FACET_ENUMERATION
) ||
844 (facetType
== XML_SCHEMA_FACET_WHITESPACE
) ||
845 (facetType
== XML_SCHEMA_FACET_MAXINCLUSIVE
) ||
846 (facetType
== XML_SCHEMA_FACET_MAXEXCLUSIVE
) ||
847 (facetType
== XML_SCHEMA_FACET_MININCLUSIVE
) ||
848 (facetType
== XML_SCHEMA_FACET_MINEXCLUSIVE
))
859 * xmlSchemaGetBuiltInType:
860 * @type: the type of the built in type
862 * Gives you the type struct for a built-in
863 * type by its type id.
865 * Returns the type if found, NULL otherwise.
868 xmlSchemaGetBuiltInType(xmlSchemaValType type
)
870 if ((xmlSchemaTypesInitialized
== 0) &&
871 (xmlSchemaInitTypes() < 0))
875 case XML_SCHEMAS_ANYSIMPLETYPE
:
876 return (xmlSchemaTypeAnySimpleTypeDef
);
877 case XML_SCHEMAS_STRING
:
878 return (xmlSchemaTypeStringDef
);
879 case XML_SCHEMAS_NORMSTRING
:
880 return (xmlSchemaTypeNormStringDef
);
881 case XML_SCHEMAS_DECIMAL
:
882 return (xmlSchemaTypeDecimalDef
);
883 case XML_SCHEMAS_TIME
:
884 return (xmlSchemaTypeTimeDef
);
885 case XML_SCHEMAS_GDAY
:
886 return (xmlSchemaTypeGDayDef
);
887 case XML_SCHEMAS_GMONTH
:
888 return (xmlSchemaTypeGMonthDef
);
889 case XML_SCHEMAS_GMONTHDAY
:
890 return (xmlSchemaTypeGMonthDayDef
);
891 case XML_SCHEMAS_GYEAR
:
892 return (xmlSchemaTypeGYearDef
);
893 case XML_SCHEMAS_GYEARMONTH
:
894 return (xmlSchemaTypeGYearMonthDef
);
895 case XML_SCHEMAS_DATE
:
896 return (xmlSchemaTypeDateDef
);
897 case XML_SCHEMAS_DATETIME
:
898 return (xmlSchemaTypeDatetimeDef
);
899 case XML_SCHEMAS_DURATION
:
900 return (xmlSchemaTypeDurationDef
);
901 case XML_SCHEMAS_FLOAT
:
902 return (xmlSchemaTypeFloatDef
);
903 case XML_SCHEMAS_DOUBLE
:
904 return (xmlSchemaTypeDoubleDef
);
905 case XML_SCHEMAS_BOOLEAN
:
906 return (xmlSchemaTypeBooleanDef
);
907 case XML_SCHEMAS_TOKEN
:
908 return (xmlSchemaTypeTokenDef
);
909 case XML_SCHEMAS_LANGUAGE
:
910 return (xmlSchemaTypeLanguageDef
);
911 case XML_SCHEMAS_NMTOKEN
:
912 return (xmlSchemaTypeNmtokenDef
);
913 case XML_SCHEMAS_NMTOKENS
:
914 return (xmlSchemaTypeNmtokensDef
);
915 case XML_SCHEMAS_NAME
:
916 return (xmlSchemaTypeNameDef
);
917 case XML_SCHEMAS_QNAME
:
918 return (xmlSchemaTypeQNameDef
);
919 case XML_SCHEMAS_NCNAME
:
920 return (xmlSchemaTypeNCNameDef
);
922 return (xmlSchemaTypeIdDef
);
923 case XML_SCHEMAS_IDREF
:
924 return (xmlSchemaTypeIdrefDef
);
925 case XML_SCHEMAS_IDREFS
:
926 return (xmlSchemaTypeIdrefsDef
);
927 case XML_SCHEMAS_ENTITY
:
928 return (xmlSchemaTypeEntityDef
);
929 case XML_SCHEMAS_ENTITIES
:
930 return (xmlSchemaTypeEntitiesDef
);
931 case XML_SCHEMAS_NOTATION
:
932 return (xmlSchemaTypeNotationDef
);
933 case XML_SCHEMAS_ANYURI
:
934 return (xmlSchemaTypeAnyURIDef
);
935 case XML_SCHEMAS_INTEGER
:
936 return (xmlSchemaTypeIntegerDef
);
937 case XML_SCHEMAS_NPINTEGER
:
938 return (xmlSchemaTypeNonPositiveIntegerDef
);
939 case XML_SCHEMAS_NINTEGER
:
940 return (xmlSchemaTypeNegativeIntegerDef
);
941 case XML_SCHEMAS_NNINTEGER
:
942 return (xmlSchemaTypeNonNegativeIntegerDef
);
943 case XML_SCHEMAS_PINTEGER
:
944 return (xmlSchemaTypePositiveIntegerDef
);
945 case XML_SCHEMAS_INT
:
946 return (xmlSchemaTypeIntDef
);
947 case XML_SCHEMAS_UINT
:
948 return (xmlSchemaTypeUnsignedIntDef
);
949 case XML_SCHEMAS_LONG
:
950 return (xmlSchemaTypeLongDef
);
951 case XML_SCHEMAS_ULONG
:
952 return (xmlSchemaTypeUnsignedLongDef
);
953 case XML_SCHEMAS_SHORT
:
954 return (xmlSchemaTypeShortDef
);
955 case XML_SCHEMAS_USHORT
:
956 return (xmlSchemaTypeUnsignedShortDef
);
957 case XML_SCHEMAS_BYTE
:
958 return (xmlSchemaTypeByteDef
);
959 case XML_SCHEMAS_UBYTE
:
960 return (xmlSchemaTypeUnsignedByteDef
);
961 case XML_SCHEMAS_HEXBINARY
:
962 return (xmlSchemaTypeHexBinaryDef
);
963 case XML_SCHEMAS_BASE64BINARY
:
964 return (xmlSchemaTypeBase64BinaryDef
);
965 case XML_SCHEMAS_ANYTYPE
:
966 return (xmlSchemaTypeAnyTypeDef
);
973 * xmlSchemaValueAppend:
975 * @cur: the value to be appended
977 * Appends a next sibling to a list of computed values.
979 * Returns 0 if succeeded and -1 on API errors.
982 xmlSchemaValueAppend(xmlSchemaValPtr prev
, xmlSchemaValPtr cur
) {
984 if ((prev
== NULL
) || (cur
== NULL
))
991 * xmlSchemaValueGetNext:
994 * Accessor for the next sibling of a list of computed values.
996 * Returns the next value or NULL if there was none, or on
1000 xmlSchemaValueGetNext(xmlSchemaValPtr cur
) {
1008 * xmlSchemaValueGetAsString:
1011 * Accessor for the string value of a computed value.
1013 * Returns the string value or NULL if there was none, or on
1017 xmlSchemaValueGetAsString(xmlSchemaValPtr val
)
1021 switch (val
->type
) {
1022 case XML_SCHEMAS_STRING
:
1023 case XML_SCHEMAS_NORMSTRING
:
1024 case XML_SCHEMAS_ANYSIMPLETYPE
:
1025 case XML_SCHEMAS_TOKEN
:
1026 case XML_SCHEMAS_LANGUAGE
:
1027 case XML_SCHEMAS_NMTOKEN
:
1028 case XML_SCHEMAS_NAME
:
1029 case XML_SCHEMAS_NCNAME
:
1030 case XML_SCHEMAS_ID
:
1031 case XML_SCHEMAS_IDREF
:
1032 case XML_SCHEMAS_ENTITY
:
1033 case XML_SCHEMAS_ANYURI
:
1034 return (BAD_CAST val
->value
.str
);
1042 * xmlSchemaValueGetAsBoolean:
1045 * Accessor for the boolean value of a computed value.
1047 * Returns 1 if true and 0 if false, or in case of an error. Hmm.
1050 xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val
)
1052 if ((val
== NULL
) || (val
->type
!= XML_SCHEMAS_BOOLEAN
))
1054 return (val
->value
.b
);
1058 * xmlSchemaNewStringValue:
1059 * @type: the value type
1062 * Allocate a new simple type value. The type can be
1063 * of XML_SCHEMAS_STRING.
1064 * WARNING: This one is intended to be expanded for other
1065 * string based types. We need this for anySimpleType as well.
1066 * The given value is consumed and freed with the struct.
1068 * Returns a pointer to the new value or NULL in case of error
1071 xmlSchemaNewStringValue(xmlSchemaValType type
,
1072 const xmlChar
*value
)
1074 xmlSchemaValPtr val
;
1076 if (type
!= XML_SCHEMAS_STRING
)
1078 val
= (xmlSchemaValPtr
) xmlMalloc(sizeof(xmlSchemaVal
));
1082 memset(val
, 0, sizeof(xmlSchemaVal
));
1084 val
->value
.str
= (xmlChar
*) value
;
1089 * xmlSchemaNewNOTATIONValue:
1090 * @name: the notation name
1091 * @ns: the notation namespace name or NULL
1093 * Allocate a new NOTATION value.
1094 * The given values are consumed and freed with the struct.
1096 * Returns a pointer to the new value or NULL in case of error
1099 xmlSchemaNewNOTATIONValue(const xmlChar
*name
,
1102 xmlSchemaValPtr val
;
1104 val
= xmlSchemaNewValue(XML_SCHEMAS_NOTATION
);
1108 val
->value
.qname
.name
= (xmlChar
*)name
;
1110 val
->value
.qname
.uri
= (xmlChar
*)ns
;
1115 * xmlSchemaNewQNameValue:
1116 * @namespaceName: the namespace name
1117 * @localName: the local name
1119 * Allocate a new QName value.
1120 * The given values are consumed and freed with the struct.
1122 * Returns a pointer to the new value or NULL in case of an error.
1125 xmlSchemaNewQNameValue(const xmlChar
*namespaceName
,
1126 const xmlChar
*localName
)
1128 xmlSchemaValPtr val
;
1130 val
= xmlSchemaNewValue(XML_SCHEMAS_QNAME
);
1134 val
->value
.qname
.name
= (xmlChar
*) localName
;
1135 val
->value
.qname
.uri
= (xmlChar
*) namespaceName
;
1140 * xmlSchemaFreeValue:
1141 * @value: the value to free
1143 * Cleanup the default XML Schemas type library
1146 xmlSchemaFreeValue(xmlSchemaValPtr value
) {
1147 xmlSchemaValPtr prev
;
1149 while (value
!= NULL
) {
1150 switch (value
->type
) {
1151 case XML_SCHEMAS_STRING
:
1152 case XML_SCHEMAS_NORMSTRING
:
1153 case XML_SCHEMAS_TOKEN
:
1154 case XML_SCHEMAS_LANGUAGE
:
1155 case XML_SCHEMAS_NMTOKEN
:
1156 case XML_SCHEMAS_NMTOKENS
:
1157 case XML_SCHEMAS_NAME
:
1158 case XML_SCHEMAS_NCNAME
:
1159 case XML_SCHEMAS_ID
:
1160 case XML_SCHEMAS_IDREF
:
1161 case XML_SCHEMAS_IDREFS
:
1162 case XML_SCHEMAS_ENTITY
:
1163 case XML_SCHEMAS_ENTITIES
:
1164 case XML_SCHEMAS_ANYURI
:
1165 case XML_SCHEMAS_ANYSIMPLETYPE
:
1166 if (value
->value
.str
!= NULL
)
1167 xmlFree(value
->value
.str
);
1169 case XML_SCHEMAS_NOTATION
:
1170 case XML_SCHEMAS_QNAME
:
1171 if (value
->value
.qname
.uri
!= NULL
)
1172 xmlFree(value
->value
.qname
.uri
);
1173 if (value
->value
.qname
.name
!= NULL
)
1174 xmlFree(value
->value
.qname
.name
);
1176 case XML_SCHEMAS_HEXBINARY
:
1177 if (value
->value
.hex
.str
!= NULL
)
1178 xmlFree(value
->value
.hex
.str
);
1180 case XML_SCHEMAS_BASE64BINARY
:
1181 if (value
->value
.base64
.str
!= NULL
)
1182 xmlFree(value
->value
.base64
.str
);
1188 value
= value
->next
;
1194 * xmlSchemaGetPredefinedType:
1195 * @name: the type name
1196 * @ns: the URI of the namespace usually "http://www.w3.org/2001/XMLSchema"
1198 * Lookup a type in the default XML Schemas type library
1200 * Returns the type if found, NULL otherwise
1203 xmlSchemaGetPredefinedType(const xmlChar
*name
, const xmlChar
*ns
) {
1204 if ((xmlSchemaTypesInitialized
== 0) &&
1205 (xmlSchemaInitTypes() < 0))
1209 return((xmlSchemaTypePtr
) xmlHashLookup2(xmlSchemaTypesBank
, name
, ns
));
1213 * xmlSchemaGetBuiltInListSimpleTypeItemType:
1214 * @type: the built-in simple type.
1218 * Returns the item type of @type as defined by the built-in datatype
1219 * hierarchy of XML Schema Part 2: Datatypes, or NULL in case of an error.
1222 xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type
)
1224 if ((type
== NULL
) || (type
->type
!= XML_SCHEMA_TYPE_BASIC
))
1226 switch (type
->builtInType
) {
1227 case XML_SCHEMAS_NMTOKENS
:
1228 return (xmlSchemaTypeNmtokenDef
);
1229 case XML_SCHEMAS_IDREFS
:
1230 return (xmlSchemaTypeIdrefDef
);
1231 case XML_SCHEMAS_ENTITIES
:
1232 return (xmlSchemaTypeEntityDef
);
1238 /****************************************************************
1240 * Convenience macros and functions *
1242 ****************************************************************/
1244 #define IS_TZO_CHAR(c) \
1245 ((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
1247 #define VALID_YEAR(yr) (yr != 0)
1248 #define VALID_MONTH(mon) ((mon >= 1) && (mon <= 12))
1249 /* VALID_DAY should only be used when month is unknown */
1250 #define VALID_DAY(day) ((day >= 1) && (day <= 31))
1251 #define VALID_HOUR(hr) ((hr >= 0) && (hr <= 23))
1252 #define VALID_MIN(min) ((min >= 0) && (min <= 59))
1253 #define VALID_SEC(sec) ((sec >= 0) && (sec < 60))
1254 #define VALID_TZO(tzo) ((tzo >= -840) && (tzo <= 840))
1255 #define IS_LEAP(y) \
1256 (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
1258 static const unsigned int daysInMonth
[12] =
1259 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1260 static const unsigned int daysInMonthLeap
[12] =
1261 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1263 #define MAX_DAYINMONTH(yr,mon) \
1264 (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
1266 #define VALID_MDAY(dt) \
1267 (IS_LEAP(dt->year) ? \
1268 (dt->day <= daysInMonthLeap[dt->mon - 1]) : \
1269 (dt->day <= daysInMonth[dt->mon - 1]))
1271 #define VALID_DATE(dt) \
1272 (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
1274 #define VALID_END_OF_DAY(dt) \
1275 ((dt)->hour == 24 && (dt)->min == 0 && (dt)->sec == 0)
1277 #define VALID_TIME(dt) \
1278 (((VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \
1279 VALID_SEC(dt->sec)) || VALID_END_OF_DAY(dt)) && \
1282 #define VALID_DATETIME(dt) \
1283 (VALID_DATE(dt) && VALID_TIME(dt))
1285 #define SECS_PER_MIN 60
1286 #define MINS_PER_HOUR 60
1287 #define HOURS_PER_DAY 24
1288 #define SECS_PER_HOUR (MINS_PER_HOUR * SECS_PER_MIN)
1289 #define SECS_PER_DAY (HOURS_PER_DAY * SECS_PER_HOUR)
1290 #define MINS_PER_DAY (HOURS_PER_DAY * MINS_PER_HOUR)
1292 static const long dayInYearByMonth
[12] =
1293 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1294 static const long dayInLeapYearByMonth
[12] =
1295 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
1297 #define DAY_IN_YEAR(day, month, year) \
1299 dayInLeapYearByMonth[month - 1] : \
1300 dayInYearByMonth[month - 1]) + day)
1303 #define DEBUG_DATE(dt) \
1304 xmlGenericError(xmlGenericErrorContext, \
1305 "type=%o %04ld-%02u-%02uT%02u:%02u:%03f", \
1306 dt->type,dt->value.date.year,dt->value.date.mon, \
1307 dt->value.date.day,dt->value.date.hour,dt->value.date.min, \
1308 dt->value.date.sec); \
1309 if (dt->value.date.tz_flag) \
1310 if (dt->value.date.tzo != 0) \
1311 xmlGenericError(xmlGenericErrorContext, \
1312 "%+05d\n",dt->value.date.tzo); \
1314 xmlGenericError(xmlGenericErrorContext, "Z\n"); \
1316 xmlGenericError(xmlGenericErrorContext,"\n")
1318 #define DEBUG_DATE(dt)
1322 * _xmlSchemaParseGYear:
1323 * @dt: pointer to a date structure
1324 * @str: pointer to the string to analyze
1326 * Parses a xs:gYear without time zone and fills in the appropriate
1327 * field of the @dt structure. @str is updated to point just after the
1328 * xs:gYear. It is supposed that @dt->year is big enough to contain
1331 * Returns 0 or the error code
1334 _xmlSchemaParseGYear (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1335 const xmlChar
*cur
= *str
, *firstChar
;
1336 int isneg
= 0, digcnt
= 0;
1338 if (((*cur
< '0') || (*cur
> '9')) &&
1339 (*cur
!= '-') && (*cur
!= '+'))
1349 while ((*cur
>= '0') && (*cur
<= '9')) {
1350 int digit
= *cur
- '0';
1352 if (dt
->year
> LONG_MAX
/ 10)
1355 if (dt
->year
> LONG_MAX
- digit
)
1362 /* year must be at least 4 digits (CCYY); over 4
1363 * digits cannot have a leading zero. */
1364 if ((digcnt
< 4) || ((digcnt
> 4) && (*firstChar
== '0')))
1368 dt
->year
= - dt
->year
;
1370 if (!VALID_YEAR(dt
->year
))
1379 * @num: the integer to fill in
1380 * @cur: an #xmlChar *
1381 * @invalid: an integer
1383 * Parses a 2-digits integer and updates @num with the value. @cur is
1384 * updated to point just after the integer.
1385 * In case of error, @invalid is set to %TRUE, values of @num and
1386 * @cur are undefined.
1388 #define PARSE_2_DIGITS(num, cur, invalid) \
1389 if ((cur[0] < '0') || (cur[0] > '9') || \
1390 (cur[1] < '0') || (cur[1] > '9')) \
1393 num = (cur[0] - '0') * 10 + (cur[1] - '0'); \
1398 * @num: the double to fill in
1399 * @cur: an #xmlChar *
1400 * @invalid: an integer
1402 * Parses a float and updates @num with the value. @cur is
1403 * updated to point just after the float. The float must have a
1404 * 2-digits integer part and may or may not have a decimal part.
1405 * In case of error, @invalid is set to %TRUE, values of @num and
1406 * @cur are undefined.
1408 #define PARSE_FLOAT(num, cur, invalid) \
1409 PARSE_2_DIGITS(num, cur, invalid); \
1410 if (!invalid && (*cur == '.')) { \
1413 if ((*cur < '0') || (*cur > '9')) \
1415 while ((*cur >= '0') && (*cur <= '9')) { \
1417 num += (*cur - '0') * mult; \
1423 * _xmlSchemaParseGMonth:
1424 * @dt: pointer to a date structure
1425 * @str: pointer to the string to analyze
1427 * Parses a xs:gMonth without time zone and fills in the appropriate
1428 * field of the @dt structure. @str is updated to point just after the
1431 * Returns 0 or the error code
1434 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1435 const xmlChar
*cur
= *str
;
1437 unsigned int value
= 0;
1439 PARSE_2_DIGITS(value
, cur
, ret
);
1443 if (!VALID_MONTH(value
))
1453 * _xmlSchemaParseGDay:
1454 * @dt: pointer to a date structure
1455 * @str: pointer to the string to analyze
1457 * Parses a xs:gDay without time zone and fills in the appropriate
1458 * field of the @dt structure. @str is updated to point just after the
1461 * Returns 0 or the error code
1464 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1465 const xmlChar
*cur
= *str
;
1467 unsigned int value
= 0;
1469 PARSE_2_DIGITS(value
, cur
, ret
);
1473 if (!VALID_DAY(value
))
1482 * _xmlSchemaParseTime:
1483 * @dt: pointer to a date structure
1484 * @str: pointer to the string to analyze
1486 * Parses a xs:time without time zone and fills in the appropriate
1487 * fields of the @dt structure. @str is updated to point just after the
1489 * In case of error, values of @dt fields are undefined.
1491 * Returns 0 or the error code
1494 _xmlSchemaParseTime (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1495 const xmlChar
*cur
= *str
;
1499 PARSE_2_DIGITS(value
, cur
, ret
);
1504 if (!VALID_HOUR(value
) && value
!= 24 /* Allow end-of-day hour */)
1508 /* the ':' insures this string is xs:time */
1511 PARSE_2_DIGITS(value
, cur
, ret
);
1514 if (!VALID_MIN(value
))
1522 PARSE_FLOAT(dt
->sec
, cur
, ret
);
1526 if (!VALID_TIME(dt
))
1534 * _xmlSchemaParseTimeZone:
1535 * @dt: pointer to a date structure
1536 * @str: pointer to the string to analyze
1538 * Parses a time zone without time zone and fills in the appropriate
1539 * field of the @dt structure. @str is updated to point just after the
1542 * Returns 0 or the error code
1545 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt
, const xmlChar
**str
) {
1567 int isneg
= 0, tmp
= 0;
1568 isneg
= (*cur
== '-');
1572 PARSE_2_DIGITS(tmp
, cur
, ret
);
1575 if (!VALID_HOUR(tmp
))
1584 PARSE_2_DIGITS(tmp
, cur
, ret
);
1587 if (!VALID_MIN(tmp
))
1592 dt
->tzo
= - dt
->tzo
;
1594 if (!VALID_TZO(dt
->tzo
))
1609 * _xmlSchemaBase64Decode:
1612 * Converts a base64 encoded character to its base 64 value.
1614 * Returns 0-63 (value), 64 (pad), or -1 (not recognized)
1617 _xmlSchemaBase64Decode (const xmlChar ch
) {
1618 if (('A' <= ch
) && (ch
<= 'Z')) return ch
- 'A';
1619 if (('a' <= ch
) && (ch
<= 'z')) return ch
- 'a' + 26;
1620 if (('0' <= ch
) && (ch
<= '9')) return ch
- '0' + 52;
1621 if ('+' == ch
) return 62;
1622 if ('/' == ch
) return 63;
1623 if ('=' == ch
) return 64;
1627 /****************************************************************
1629 * XML Schema Dates/Times Datatypes Handling *
1631 ****************************************************************/
1635 * @num: the integer to fill in
1636 * @cur: an #xmlChar *
1637 * @num_type: an integer flag
1639 * Parses a digits integer and updates @num with the value. @cur is
1640 * updated to point just after the integer.
1641 * In case of error, @num_type is set to -1, values of @num and
1642 * @cur are undefined.
1644 #define PARSE_DIGITS(num, cur, num_type) \
1645 if ((*cur < '0') || (*cur > '9')) \
1648 while ((*cur >= '0') && (*cur <= '9')) { \
1649 num = num * 10 + (*cur - '0'); \
1655 * @num: the double to fill in
1656 * @cur: an #xmlChar *
1657 * @num_type: an integer flag
1659 * Parses a float or integer and updates @num with the value. @cur is
1660 * updated to point just after the number. If the number is a float,
1661 * then it must have an integer part and a decimal part; @num_type will
1662 * be set to 1. If there is no decimal part, @num_type is set to zero.
1663 * In case of error, @num_type is set to -1, values of @num and
1664 * @cur are undefined.
1666 #define PARSE_NUM(num, cur, num_type) \
1668 PARSE_DIGITS(num, cur, num_type); \
1669 if (!num_type && (*cur == '.')) { \
1672 if ((*cur < '0') || (*cur > '9')) \
1676 while ((*cur >= '0') && (*cur <= '9')) { \
1678 num += (*cur - '0') * mult; \
1684 * xmlSchemaValidateDates:
1685 * @type: the expected type or XML_SCHEMAS_UNKNOWN
1686 * @dateTime: string to analyze
1687 * @val: the return computed value
1689 * Check that @dateTime conforms to the lexical space of one of the date types.
1690 * if true a value is computed and returned in @val.
1692 * Returns 0 if this validates, a positive error code number otherwise
1693 * and -1 in case of internal or API error.
1696 xmlSchemaValidateDates (xmlSchemaValType type
,
1697 const xmlChar
*dateTime
, xmlSchemaValPtr
*val
,
1701 const xmlChar
*cur
= dateTime
;
1703 #define RETURN_TYPE_IF_VALID(t) \
1704 if (IS_TZO_CHAR(*cur)) { \
1705 ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); \
1714 if (dateTime
== NULL
)
1718 while IS_WSP_BLANK_CH(*cur
) cur
++;
1720 if ((*cur
!= '-') && (*cur
< '0') && (*cur
> '9'))
1723 dt
= xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN
);
1727 if ((cur
[0] == '-') && (cur
[1] == '-')) {
1729 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
1734 /* is it an xs:gDay? */
1736 if (type
== XML_SCHEMAS_GMONTH
)
1739 ret
= _xmlSchemaParseGDay(&(dt
->value
.date
), &cur
);
1743 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY
);
1749 * it should be an xs:gMonthDay or xs:gMonth
1751 ret
= _xmlSchemaParseGMonth(&(dt
->value
.date
), &cur
);
1756 * a '-' char could indicate this type is xs:gMonthDay or
1757 * a negative time zone offset. Check for xs:gMonthDay first.
1758 * Also the first three char's of a negative tzo (-MM:SS) can
1759 * appear to be a valid day; so even if the day portion
1760 * of the xs:gMonthDay verifies, we must insure it was not
1764 const xmlChar
*rewnd
= cur
;
1767 ret
= _xmlSchemaParseGDay(&(dt
->value
.date
), &cur
);
1768 if ((ret
== 0) && ((*cur
== 0) || (*cur
!= ':'))) {
1771 * we can use the VALID_MDAY macro to validate the month
1772 * and day because the leap year test will flag year zero
1773 * as a leap year (even though zero is an invalid year).
1774 * FUTURE TODO: Zero will become valid in XML Schema 1.1
1777 if (VALID_MDAY((&(dt
->value
.date
)))) {
1779 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY
);
1786 * not xs:gMonthDay so rewind and check if just xs:gMonth
1787 * with an optional time zone.
1792 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH
);
1798 * It's a right-truncated date or an xs:time.
1799 * Try to parse an xs:time then fallback on right-truncated dates.
1801 if ((*cur
>= '0') && (*cur
<= '9')) {
1802 ret
= _xmlSchemaParseTime(&(dt
->value
.date
), &cur
);
1804 /* it's an xs:time */
1805 RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME
);
1809 /* fallback on date parsing */
1812 ret
= _xmlSchemaParseGYear(&(dt
->value
.date
), &cur
);
1816 /* is it an xs:gYear? */
1817 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR
);
1823 ret
= _xmlSchemaParseGMonth(&(dt
->value
.date
), &cur
);
1827 /* is it an xs:gYearMonth? */
1828 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH
);
1834 ret
= _xmlSchemaParseGDay(&(dt
->value
.date
), &cur
);
1835 if ((ret
!= 0) || !VALID_DATE((&(dt
->value
.date
))))
1838 /* is it an xs:date? */
1839 RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE
);
1845 /* it should be an xs:dateTime */
1846 ret
= _xmlSchemaParseTime(&(dt
->value
.date
), &cur
);
1850 ret
= _xmlSchemaParseTimeZone(&(dt
->value
.date
), &cur
);
1852 while IS_WSP_BLANK_CH(*cur
) cur
++;
1853 if ((ret
!= 0) || (*cur
!= 0) || (!(VALID_DATETIME((&(dt
->value
.date
))))))
1857 dt
->type
= XML_SCHEMAS_DATETIME
;
1861 if ((type
!= XML_SCHEMAS_UNKNOWN
) && (type
!= dt
->type
))
1865 * insure the parsed type is equal to or less significant (right
1866 * truncated) than the desired type.
1868 if ((type
!= XML_SCHEMAS_UNKNOWN
) && (type
!= dt
->type
)) {
1870 /* time only matches time */
1871 if ((type
== XML_SCHEMAS_TIME
) && (dt
->type
== XML_SCHEMAS_TIME
))
1874 if ((type
== XML_SCHEMAS_DATETIME
) &&
1875 ((dt
->type
!= XML_SCHEMAS_DATE
) ||
1876 (dt
->type
!= XML_SCHEMAS_GYEARMONTH
) ||
1877 (dt
->type
!= XML_SCHEMAS_GYEAR
)))
1880 if ((type
== XML_SCHEMAS_DATE
) &&
1881 ((dt
->type
!= XML_SCHEMAS_GYEAR
) ||
1882 (dt
->type
!= XML_SCHEMAS_GYEARMONTH
)))
1885 if ((type
== XML_SCHEMAS_GYEARMONTH
) && (dt
->type
!= XML_SCHEMAS_GYEAR
))
1888 if ((type
== XML_SCHEMAS_GMONTHDAY
) && (dt
->type
!= XML_SCHEMAS_GMONTH
))
1896 xmlSchemaFreeValue(dt
);
1902 xmlSchemaFreeValue(dt
);
1907 * xmlSchemaValidateDuration:
1908 * @type: the predefined type
1909 * @duration: string to analyze
1910 * @val: the return computed value
1912 * Check that @duration conforms to the lexical space of the duration type.
1913 * if true a value is computed and returned in @val.
1915 * Returns 0 if this validates, a positive error code number otherwise
1916 * and -1 in case of internal or API error.
1919 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED
,
1920 const xmlChar
*duration
, xmlSchemaValPtr
*val
,
1922 const xmlChar
*cur
= duration
;
1923 xmlSchemaValPtr dur
;
1925 unsigned int seq
= 0;
1926 long days
, secs
= 0;
1927 double sec_frac
= 0.0;
1929 if (duration
== NULL
)
1933 while IS_WSP_BLANK_CH(*cur
) cur
++;
1940 /* duration must start with 'P' (after sign) */
1947 dur
= xmlSchemaNewValue(XML_SCHEMAS_DURATION
);
1953 size_t has_digits
= 0;
1955 const xmlChar desig
[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
1957 /* input string should be empty or invalid date/time item */
1958 if (seq
>= sizeof(desig
))
1961 /* T designator must be present for time items */
1967 } else if (seq
== 3)
1970 /* Parse integral part. */
1971 while (*cur
>= '0' && *cur
<= '9') {
1972 long digit
= *cur
- '0';
1974 if (num
> LONG_MAX
/ 10)
1977 if (num
> LONG_MAX
- digit
)
1986 /* Parse fractional part. */
1990 while (*cur
>= '0' && *cur
<= '9') {
1992 sec_frac
+= (*cur
- '0') * mult
;
1998 while (*cur
!= desig
[seq
]) {
2000 /* No T designator or invalid char. */
2001 if (seq
== 3 || seq
== sizeof(desig
))
2006 if (!has_digits
|| (has_frac
&& (seq
!= 5)))
2012 if (num
> LONG_MAX
/ 12)
2014 dur
->value
.dur
.mon
= num
* 12;
2018 if (dur
->value
.dur
.mon
> LONG_MAX
- num
)
2020 dur
->value
.dur
.mon
+= num
;
2024 dur
->value
.dur
.day
= num
;
2028 days
= num
/ HOURS_PER_DAY
;
2029 if (dur
->value
.dur
.day
> LONG_MAX
- days
)
2031 dur
->value
.dur
.day
+= days
;
2032 secs
= (num
% HOURS_PER_DAY
) * SECS_PER_HOUR
;
2036 days
= num
/ MINS_PER_DAY
;
2037 if (dur
->value
.dur
.day
> LONG_MAX
- days
)
2039 dur
->value
.dur
.day
+= days
;
2040 secs
+= (num
% MINS_PER_DAY
) * SECS_PER_MIN
;
2044 days
= num
/ SECS_PER_DAY
;
2045 if (dur
->value
.dur
.day
> LONG_MAX
- days
)
2047 dur
->value
.dur
.day
+= days
;
2048 secs
+= num
% SECS_PER_DAY
;
2055 days
= secs
/ SECS_PER_DAY
;
2056 if (dur
->value
.dur
.day
> LONG_MAX
- days
)
2058 dur
->value
.dur
.day
+= days
;
2059 dur
->value
.dur
.sec
= (secs
% SECS_PER_DAY
) + sec_frac
;
2062 dur
->value
.dur
.mon
= -dur
->value
.dur
.mon
;
2063 dur
->value
.dur
.day
= -dur
->value
.dur
.day
;
2064 dur
->value
.dur
.sec
= -dur
->value
.dur
.sec
;
2070 xmlSchemaFreeValue(dur
);
2076 xmlSchemaFreeValue(dur
);
2084 * Removes the leading and ending spaces of a string
2086 * Returns the new string or NULL if no change was required.
2089 xmlSchemaStrip(const xmlChar
*value
) {
2090 const xmlChar
*start
= value
, *end
, *f
;
2092 if (value
== NULL
) return(NULL
);
2093 while ((*start
!= 0) && (IS_BLANK_CH(*start
))) start
++;
2095 while (*end
!= 0) end
++;
2098 while ((end
> start
) && (IS_BLANK_CH(*end
))) end
--;
2100 if ((start
== value
) && (f
== end
)) return(NULL
);
2101 return(xmlStrndup(start
, end
- start
));
2105 * xmlSchemaWhiteSpaceReplace:
2108 * Replaces 0xd, 0x9 and 0xa with a space.
2110 * Returns the new string or NULL if no change was required.
2113 xmlSchemaWhiteSpaceReplace(const xmlChar
*value
) {
2114 const xmlChar
*cur
= value
;
2115 xmlChar
*ret
= NULL
, *mcur
;
2120 while ((*cur
!= 0) &&
2121 (((*cur
) != 0xd) && ((*cur
) != 0x9) && ((*cur
) != 0xa))) {
2126 ret
= xmlStrdup(value
);
2127 /* TODO FIXME: I guess gcc will bark at this. */
2128 mcur
= (xmlChar
*) (ret
+ (cur
- value
));
2130 if ( ((*mcur
) == 0xd) || ((*mcur
) == 0x9) || ((*mcur
) == 0xa) )
2133 } while (*mcur
!= 0);
2138 * xmlSchemaCollapseString:
2141 * Removes and normalize white spaces in the string
2143 * Returns the new string or NULL if no change was required.
2146 xmlSchemaCollapseString(const xmlChar
*value
) {
2147 const xmlChar
*start
= value
, *end
, *f
;
2151 if (value
== NULL
) return(NULL
);
2152 while ((*start
!= 0) && (IS_BLANK_CH(*start
))) start
++;
2155 if ((*end
== ' ') && (IS_BLANK_CH(end
[1]))) {
2158 } else if ((*end
== 0xa) || (*end
== 0x9) || (*end
== 0xd)) {
2167 while ((end
> start
) && (IS_BLANK_CH(*end
))) end
--;
2169 if ((start
== value
) && (f
== end
)) return(NULL
);
2170 return(xmlStrndup(start
, end
- start
));
2172 start
= xmlStrdup(start
);
2173 if (start
== NULL
) return(NULL
);
2174 g
= (xmlChar
*) (start
+ col
);
2177 if (IS_BLANK_CH(*end
)) {
2179 while (IS_BLANK_CH(*end
)) end
++;
2186 return((xmlChar
*) start
);
2190 * xmlSchemaValAtomicListNode:
2191 * @type: the predefined atomic type for a token in the list
2192 * @value: the list value to check
2193 * @ret: the return computed value
2194 * @node: the node containing the value
2196 * Check that a value conforms to the lexical space of the predefined
2197 * list type. if true a value is computed and returned in @ret.
2199 * Returns the number of items if this validates, a negative error code
2203 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type
, const xmlChar
*value
,
2204 xmlSchemaValPtr
*ret
, xmlNodePtr node
) {
2205 xmlChar
*val
, *cur
, *endval
;
2209 if (value
== NULL
) {
2212 val
= xmlStrdup(value
);
2223 while (IS_BLANK_CH(*cur
)) *cur
++ = 0;
2225 if (IS_BLANK_CH(*cur
)) {
2228 while (IS_BLANK_CH(*cur
)) *cur
++ = 0;
2232 while ((*cur
!= 0) && (!IS_BLANK_CH(*cur
))) cur
++;
2235 if (nb_values
== 0) {
2241 while ((*cur
== 0) && (cur
!= endval
)) cur
++;
2242 while (cur
!= endval
) {
2243 tmp
= xmlSchemaValPredefTypeNode(type
, cur
, NULL
, node
);
2246 while (*cur
!= 0) cur
++;
2247 while ((*cur
== 0) && (cur
!= endval
)) cur
++;
2249 /* TODO what return value ? c.f. bug #158628
2260 * xmlSchemaParseUInt:
2261 * @str: pointer to the string R/W
2262 * @llo: pointer to the low result
2263 * @lmi: pointer to the mid result
2264 * @lhi: pointer to the high result
2266 * Parse an unsigned long into 3 fields.
2268 * Returns the number of significant digits in the number or
2269 * -1 if overflow of the capacity and -2 if it's not a number.
2272 xmlSchemaParseUInt(const xmlChar
**str
, unsigned long *llo
,
2273 unsigned long *lmi
, unsigned long *lhi
) {
2274 unsigned long lo
= 0, mi
= 0, hi
= 0;
2275 const xmlChar
*tmp
, *cur
= *str
;
2278 if (!((*cur
>= '0') && (*cur
<= '9')))
2281 while (*cur
== '0') { /* ignore leading zeroes */
2285 while ((*tmp
!= 0) && (*tmp
>= '0') && (*tmp
<= '9')) {
2293 hi
= hi
* 10 + (*cur
++ - '0');
2297 mi
= mi
* 10 + (*cur
++ - '0');
2301 lo
= lo
* 10 + (*cur
++ - '0');
2313 * xmlSchemaCheckLanguageType
2314 * @value: the value to check
2316 * Check that a value conforms to the lexical space of the language datatype.
2317 * Must conform to [a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*
2319 * Returns 1 if this validates, 0 otherwise.
2322 xmlSchemaCheckLanguageType(const xmlChar
* value
) {
2323 int first
= 1, len
= 0;
2324 const xmlChar
* cur
= value
;
2329 while (cur
[0] != 0) {
2330 if (!( ((cur
[0] >= 'a') && (cur
[0] <= 'z')) || ((cur
[0] >= 'A') && (cur
[0] <= 'Z'))
2332 || ((first
== 0) && (xmlIsDigit_ch(cur
[0]))) ))
2334 if (cur
[0] == '-') {
2335 if ((len
< 1) || (len
> 8))
2344 if ((len
< 1) || (len
> 8))
2351 * xmlSchemaValAtomicType:
2352 * @type: the predefined type
2353 * @value: the value to check
2354 * @val: the return computed value
2355 * @node: the node containing the value
2356 * flags: flags to control the validation
2358 * Check that a value conforms to the lexical space of the atomic type.
2359 * if true a value is computed and returned in @val.
2360 * This checks the value space for list types as well (IDREFS, NMTOKENS).
2362 * Returns 0 if this validates, a positive error code number otherwise
2363 * and -1 in case of internal or API error.
2366 xmlSchemaValAtomicType(xmlSchemaTypePtr type
, const xmlChar
* value
,
2367 xmlSchemaValPtr
* val
, xmlNodePtr node
, int flags
,
2368 xmlSchemaWhitespaceValueType ws
,
2369 int normOnTheFly
, int applyNorm
, int createStringValue
)
2372 xmlChar
*norm
= NULL
;
2375 if ((xmlSchemaTypesInitialized
== 0) &&
2376 (xmlSchemaInitTypes() < 0))
2382 * validating a non existent text node is similar to validating
2386 value
= BAD_CAST
"";
2390 if ((flags
== 0) && (value
!= NULL
)) {
2392 if ((type
->builtInType
!= XML_SCHEMAS_STRING
) &&
2393 (type
->builtInType
!= XML_SCHEMAS_ANYTYPE
) &&
2394 (type
->builtInType
!= XML_SCHEMAS_ANYSIMPLETYPE
)) {
2395 if (type
->builtInType
== XML_SCHEMAS_NORMSTRING
)
2396 norm
= xmlSchemaWhiteSpaceReplace(value
);
2398 norm
= xmlSchemaCollapseString(value
);
2404 switch (type
->builtInType
) {
2405 case XML_SCHEMAS_UNKNOWN
:
2407 case XML_SCHEMAS_ANYTYPE
:
2408 case XML_SCHEMAS_ANYSIMPLETYPE
:
2409 if ((createStringValue
) && (val
!= NULL
)) {
2410 v
= xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE
);
2412 v
->value
.str
= xmlStrdup(value
);
2419 case XML_SCHEMAS_STRING
:
2420 if (! normOnTheFly
) {
2421 const xmlChar
*cur
= value
;
2423 if (ws
== XML_SCHEMA_WHITESPACE_REPLACE
) {
2425 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2431 } else if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
) {
2433 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2435 } else if IS_WSP_SPACE_CH(*cur
) {
2437 if IS_WSP_SPACE_CH(*cur
)
2445 if (createStringValue
&& (val
!= NULL
)) {
2447 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
2448 norm
= xmlSchemaCollapseString(value
);
2449 else if (ws
== XML_SCHEMA_WHITESPACE_REPLACE
)
2450 norm
= xmlSchemaWhiteSpaceReplace(value
);
2454 v
= xmlSchemaNewValue(XML_SCHEMAS_STRING
);
2456 v
->value
.str
= xmlStrdup(value
);
2463 case XML_SCHEMAS_NORMSTRING
:{
2466 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
2467 norm
= xmlSchemaCollapseString(value
);
2469 norm
= xmlSchemaWhiteSpaceReplace(value
);
2474 const xmlChar
*cur
= value
;
2476 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2484 v
= xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING
);
2486 v
->value
.str
= xmlStrdup(value
);
2494 case XML_SCHEMAS_DECIMAL
:{
2495 const xmlChar
*cur
= value
;
2496 unsigned int len
, neg
, integ
, hasLeadingZeroes
;
2498 xmlChar
*cptr
= cval
;
2500 if ((cur
== NULL
) || (*cur
== 0))
2504 * xs:decimal has a whitespace-facet value of 'collapse'.
2507 while IS_WSP_BLANK_CH(*cur
) cur
++;
2510 * First we handle an optional sign.
2516 } else if (*cur
== '+')
2519 * Disallow: "", "-", "- "
2524 * Next we "pre-parse" the number, in preparation for calling
2525 * the common routine xmlSchemaParseUInt. We get rid of any
2526 * leading zeroes (because we have reserved only 25 chars),
2527 * and note the position of a decimal point.
2531 hasLeadingZeroes
= 0;
2533 * Skip leading zeroes.
2535 while (*cur
== '0') {
2537 hasLeadingZeroes
= 1;
2541 if ((*cur
>= '0') && (*cur
<= '9')) {
2544 } else if (*cur
== '.') {
2548 if ((*cur
>= '0') && (*cur
<= '9')) {
2555 * Disallow "." but allow "00."
2557 if ((len
== 0) && (!hasLeadingZeroes
))
2565 while IS_WSP_BLANK_CH(*cur
) cur
++;
2567 goto return1
; /* error if any extraneous chars */
2569 v
= xmlSchemaNewValue(XML_SCHEMAS_DECIMAL
);
2572 * Now evaluate the significant digits of the number
2578 * Get rid of trailing zeroes in the
2581 while ((len
!= integ
) && (*(cptr
-1) == '0')) {
2587 * Terminate the (preparsed) string.
2593 xmlSchemaParseUInt((const xmlChar
**)&cptr
,
2594 &v
->value
.decimal
.lo
,
2595 &v
->value
.decimal
.mi
,
2596 &v
->value
.decimal
.hi
);
2600 * Set the total digits to 1 if a zero value.
2602 v
->value
.decimal
.sign
= neg
;
2604 /* Speedup for zero values. */
2605 v
->value
.decimal
.total
= 1;
2607 v
->value
.decimal
.total
= len
;
2609 v
->value
.decimal
.frac
= 0;
2611 v
->value
.decimal
.frac
= len
- integ
;
2618 case XML_SCHEMAS_TIME
:
2619 case XML_SCHEMAS_GDAY
:
2620 case XML_SCHEMAS_GMONTH
:
2621 case XML_SCHEMAS_GMONTHDAY
:
2622 case XML_SCHEMAS_GYEAR
:
2623 case XML_SCHEMAS_GYEARMONTH
:
2624 case XML_SCHEMAS_DATE
:
2625 case XML_SCHEMAS_DATETIME
:
2626 ret
= xmlSchemaValidateDates(type
->builtInType
, value
, val
,
2629 case XML_SCHEMAS_DURATION
:
2630 ret
= xmlSchemaValidateDuration(type
, value
, val
,
2633 case XML_SCHEMAS_FLOAT
:
2634 case XML_SCHEMAS_DOUBLE
: {
2635 const xmlChar
*cur
= value
;
2637 int digits_before
= 0;
2638 int digits_after
= 0;
2641 while IS_WSP_BLANK_CH(*cur
) cur
++;
2643 if ((cur
[0] == 'N') && (cur
[1] == 'a') && (cur
[2] == 'N')) {
2648 if (type
== xmlSchemaTypeFloatDef
) {
2649 v
= xmlSchemaNewValue(XML_SCHEMAS_FLOAT
);
2651 v
->value
.f
= (float) xmlXPathNAN
;
2653 xmlSchemaFreeValue(v
);
2657 v
= xmlSchemaNewValue(XML_SCHEMAS_DOUBLE
);
2659 v
->value
.d
= xmlXPathNAN
;
2661 xmlSchemaFreeValue(v
);
2673 if ((cur
[0] == 'I') && (cur
[1] == 'N') && (cur
[2] == 'F')) {
2678 if (type
== xmlSchemaTypeFloatDef
) {
2679 v
= xmlSchemaNewValue(XML_SCHEMAS_FLOAT
);
2682 v
->value
.f
= (float) xmlXPathNINF
;
2684 v
->value
.f
= (float) xmlXPathPINF
;
2686 xmlSchemaFreeValue(v
);
2690 v
= xmlSchemaNewValue(XML_SCHEMAS_DOUBLE
);
2693 v
->value
.d
= xmlXPathNINF
;
2695 v
->value
.d
= xmlXPathPINF
;
2697 xmlSchemaFreeValue(v
);
2705 if ((neg
== 0) && (*cur
== '+'))
2707 if ((cur
[0] == 0) || (cur
[0] == '+') || (cur
[0] == '-'))
2709 while ((*cur
>= '0') && (*cur
<= '9')) {
2715 while ((*cur
>= '0') && (*cur
<= '9')) {
2720 if ((digits_before
== 0) && (digits_after
== 0))
2722 if ((*cur
== 'e') || (*cur
== 'E')) {
2724 if ((*cur
== '-') || (*cur
== '+'))
2726 while ((*cur
>= '0') && (*cur
<= '9'))
2730 while IS_WSP_BLANK_CH(*cur
) cur
++;
2735 if (type
== xmlSchemaTypeFloatDef
) {
2736 v
= xmlSchemaNewValue(XML_SCHEMAS_FLOAT
);
2739 * TODO: sscanf seems not to give the correct
2740 * value for extremely high/low values.
2741 * E.g. "1E-149" results in zero.
2743 if (sscanf((const char *) value
, "%f",
2744 &(v
->value
.f
)) == 1) {
2747 xmlSchemaFreeValue(v
);
2754 v
= xmlSchemaNewValue(XML_SCHEMAS_DOUBLE
);
2757 * TODO: sscanf seems not to give the correct
2758 * value for extremely high/low values.
2760 if (sscanf((const char *) value
, "%lf",
2761 &(v
->value
.d
)) == 1) {
2764 xmlSchemaFreeValue(v
);
2774 case XML_SCHEMAS_BOOLEAN
:{
2775 const xmlChar
*cur
= value
;
2778 while IS_WSP_BLANK_CH(*cur
) cur
++;
2782 } else if (*cur
== '1') {
2785 } else if (*cur
== 't') {
2787 if ((*cur
++ == 'r') && (*cur
++ == 'u') &&
2792 } else if (*cur
== 'f') {
2794 if ((*cur
++ == 'a') && (*cur
++ == 'l') &&
2795 (*cur
++ == 's') && (*cur
++ == 'e')) {
2802 while IS_WSP_BLANK_CH(*cur
) cur
++;
2807 if ((cur
[0] == '0') && (cur
[1] == 0))
2809 else if ((cur
[0] == '1') && (cur
[1] == 0))
2811 else if ((cur
[0] == 't') && (cur
[1] == 'r')
2812 && (cur
[2] == 'u') && (cur
[3] == 'e')
2815 else if ((cur
[0] == 'f') && (cur
[1] == 'a')
2816 && (cur
[2] == 'l') && (cur
[3] == 's')
2817 && (cur
[4] == 'e') && (cur
[5] == 0))
2823 v
= xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN
);
2833 case XML_SCHEMAS_TOKEN
:{
2834 const xmlChar
*cur
= value
;
2836 if (! normOnTheFly
) {
2838 if ((*cur
== 0xd) || (*cur
== 0xa) || (*cur
== 0x9)) {
2840 } else if (*cur
== ' ') {
2852 v
= xmlSchemaNewValue(XML_SCHEMAS_TOKEN
);
2854 v
->value
.str
= xmlStrdup(value
);
2862 case XML_SCHEMAS_LANGUAGE
:
2863 if ((norm
== NULL
) && (normOnTheFly
)) {
2864 norm
= xmlSchemaCollapseString(value
);
2869 if (xmlSchemaCheckLanguageType(value
) == 1) {
2871 v
= xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE
);
2873 v
->value
.str
= xmlStrdup(value
);
2882 case XML_SCHEMAS_NMTOKEN
:
2883 if (xmlValidateNMToken(value
, 1) == 0) {
2885 v
= xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN
);
2887 v
->value
.str
= xmlStrdup(value
);
2896 case XML_SCHEMAS_NMTOKENS
:
2897 ret
= xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef
,
2904 case XML_SCHEMAS_NAME
:
2905 ret
= xmlValidateName(value
, 1);
2906 if ((ret
== 0) && (val
!= NULL
) && (value
!= NULL
)) {
2907 v
= xmlSchemaNewValue(XML_SCHEMAS_NAME
);
2909 const xmlChar
*start
= value
, *end
;
2910 while (IS_BLANK_CH(*start
)) start
++;
2912 while ((*end
!= 0) && (!IS_BLANK_CH(*end
))) end
++;
2913 v
->value
.str
= xmlStrndup(start
, end
- start
);
2920 case XML_SCHEMAS_QNAME
:{
2921 const xmlChar
*uri
= NULL
;
2922 xmlChar
*local
= NULL
;
2924 ret
= xmlValidateQName(value
, 1);
2931 local
= xmlSplitQName2(value
, &prefix
);
2932 ns
= xmlSearchNs(node
->doc
, node
, prefix
);
2933 if ((ns
== NULL
) && (prefix
!= NULL
)) {
2945 v
= xmlSchemaNewValue(XML_SCHEMAS_QNAME
);
2952 v
->value
.qname
.name
= local
;
2954 v
->value
.qname
.name
= xmlStrdup(value
);
2956 v
->value
.qname
.uri
= xmlStrdup(uri
);
2963 case XML_SCHEMAS_NCNAME
:
2964 ret
= xmlValidateNCName(value
, 1);
2965 if ((ret
== 0) && (val
!= NULL
)) {
2966 v
= xmlSchemaNewValue(XML_SCHEMAS_NCNAME
);
2968 v
->value
.str
= xmlStrdup(value
);
2975 case XML_SCHEMAS_ID
:
2976 ret
= xmlValidateNCName(value
, 1);
2977 if ((ret
== 0) && (val
!= NULL
)) {
2978 v
= xmlSchemaNewValue(XML_SCHEMAS_ID
);
2980 v
->value
.str
= xmlStrdup(value
);
2986 if ((ret
== 0) && (node
!= NULL
) &&
2987 (node
->type
== XML_ATTRIBUTE_NODE
)) {
2988 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
2991 * NOTE: the IDness might have already be declared in the DTD
2993 if (attr
->atype
!= XML_ATTRIBUTE_ID
) {
2997 strip
= xmlSchemaStrip(value
);
2998 if (strip
!= NULL
) {
2999 res
= xmlAddID(NULL
, node
->doc
, strip
, attr
);
3002 res
= xmlAddID(NULL
, node
->doc
, value
, attr
);
3006 attr
->atype
= XML_ATTRIBUTE_ID
;
3011 case XML_SCHEMAS_IDREF
:
3012 ret
= xmlValidateNCName(value
, 1);
3013 if ((ret
== 0) && (val
!= NULL
)) {
3014 v
= xmlSchemaNewValue(XML_SCHEMAS_IDREF
);
3017 v
->value
.str
= xmlStrdup(value
);
3020 if ((ret
== 0) && (node
!= NULL
) &&
3021 (node
->type
== XML_ATTRIBUTE_NODE
)) {
3022 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
3025 strip
= xmlSchemaStrip(value
);
3026 if (strip
!= NULL
) {
3027 xmlAddRef(NULL
, node
->doc
, strip
, attr
);
3030 xmlAddRef(NULL
, node
->doc
, value
, attr
);
3031 attr
->atype
= XML_ATTRIBUTE_IDREF
;
3034 case XML_SCHEMAS_IDREFS
:
3035 ret
= xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef
,
3041 if ((ret
== 0) && (node
!= NULL
) &&
3042 (node
->type
== XML_ATTRIBUTE_NODE
)) {
3043 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
3045 attr
->atype
= XML_ATTRIBUTE_IDREFS
;
3048 case XML_SCHEMAS_ENTITY
:{
3051 ret
= xmlValidateNCName(value
, 1);
3052 if ((node
== NULL
) || (node
->doc
== NULL
))
3057 strip
= xmlSchemaStrip(value
);
3058 if (strip
!= NULL
) {
3059 ent
= xmlGetDocEntity(node
->doc
, strip
);
3062 ent
= xmlGetDocEntity(node
->doc
, value
);
3064 if ((ent
== NULL
) ||
3066 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
))
3069 if ((ret
== 0) && (val
!= NULL
)) {
3072 if ((ret
== 0) && (node
!= NULL
) &&
3073 (node
->type
== XML_ATTRIBUTE_NODE
)) {
3074 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
3076 attr
->atype
= XML_ATTRIBUTE_ENTITY
;
3080 case XML_SCHEMAS_ENTITIES
:
3081 if ((node
== NULL
) || (node
->doc
== NULL
))
3083 ret
= xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef
,
3089 if ((ret
== 0) && (node
!= NULL
) &&
3090 (node
->type
== XML_ATTRIBUTE_NODE
)) {
3091 xmlAttrPtr attr
= (xmlAttrPtr
) node
;
3093 attr
->atype
= XML_ATTRIBUTE_ENTITIES
;
3096 case XML_SCHEMAS_NOTATION
:{
3097 xmlChar
*uri
= NULL
;
3098 xmlChar
*local
= NULL
;
3100 ret
= xmlValidateQName(value
, 1);
3101 if ((ret
== 0) && (node
!= NULL
)) {
3104 local
= xmlSplitQName2(value
, &prefix
);
3105 if (prefix
!= NULL
) {
3108 ns
= xmlSearchNs(node
->doc
, node
, prefix
);
3111 else if (val
!= NULL
)
3112 uri
= xmlStrdup(ns
->href
);
3114 if ((local
!= NULL
) && ((val
== NULL
) || (ret
!= 0)))
3119 if ((node
== NULL
) || (node
->doc
== NULL
))
3122 ret
= xmlValidateNotationUse(NULL
, node
->doc
, value
);
3128 if ((ret
== 0) && (val
!= NULL
)) {
3129 v
= xmlSchemaNewValue(XML_SCHEMAS_NOTATION
);
3132 v
->value
.qname
.name
= local
;
3134 v
->value
.qname
.name
= xmlStrdup(value
);
3136 v
->value
.qname
.uri
= uri
;
3149 case XML_SCHEMAS_ANYURI
:{
3152 xmlChar
*tmpval
, *cur
;
3153 if ((norm
== NULL
) && (normOnTheFly
)) {
3154 norm
= xmlSchemaCollapseString(value
);
3158 tmpval
= xmlStrdup(value
);
3161 for (cur
= tmpval
; *cur
; ++cur
) {
3162 if (*cur
< 32 || *cur
>= 127 || *cur
== ' ' ||
3163 *cur
== '<' || *cur
== '>' || *cur
== '"' ||
3164 *cur
== '{' || *cur
== '}' || *cur
== '|' ||
3165 *cur
== '\\' || *cur
== '^' || *cur
== '`' ||
3169 uri
= xmlParseURI((const char *) tmpval
);
3177 v
= xmlSchemaNewValue(XML_SCHEMAS_ANYURI
);
3180 v
->value
.str
= xmlStrdup(value
);
3185 case XML_SCHEMAS_HEXBINARY
:{
3186 const xmlChar
*cur
= value
, *start
;
3194 while IS_WSP_BLANK_CH(*cur
) cur
++;
3197 while (((*cur
>= '0') && (*cur
<= '9')) ||
3198 ((*cur
>= 'A') && (*cur
<= 'F')) ||
3199 ((*cur
>= 'a') && (*cur
<= 'f'))) {
3204 while IS_WSP_BLANK_CH(*cur
) cur
++;
3213 v
= xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY
);
3217 * Copy only the normalized piece.
3218 * CRITICAL TODO: Check this.
3220 cur
= xmlStrndup(start
, i
);
3222 xmlSchemaTypeErrMemory(node
, "allocating hexbin data");
3227 total
= i
/ 2; /* number of octets */
3229 base
= (xmlChar
*) cur
;
3232 *base
= *base
- ('a' - 'A');
3236 v
->value
.hex
.str
= (xmlChar
*) cur
;
3237 v
->value
.hex
.total
= total
;
3242 case XML_SCHEMAS_BASE64BINARY
:{
3245 * Ignore all stray characters? (yes, currently)
3246 * Worry about long lines? (no, currently)
3250 * "The encoded output stream must be represented in lines of
3251 * no more than 76 characters each. All line breaks or other
3252 * characters not found in Table 1 must be ignored by decoding
3253 * software. In base64 data, characters other than those in
3254 * Table 1, line breaks, and other white space probably
3255 * indicate a transmission error, about which a warning
3256 * message or even a message rejection might be appropriate
3257 * under some circumstances." */
3258 const xmlChar
*cur
= value
;
3260 int total
, i
= 0, pad
= 0;
3265 for (; *cur
; ++cur
) {
3268 decc
= _xmlSchemaBase64Decode(*cur
);
3275 for (; *cur
; ++cur
) {
3278 decc
= _xmlSchemaBase64Decode(*cur
);
3286 /* rfc2045.txt: "Special processing is performed if fewer than
3287 * 24 bits are available at the end of the data being encoded.
3288 * A full encoding quantum is always completed at the end of a
3289 * body. When fewer than 24 input bits are available in an
3290 * input group, zero bits are added (on the right) to form an
3291 * integral number of 6-bit groups. Padding at the end of the
3292 * data is performed using the "=" character. Since all
3293 * base64 input is an integral number of octets, only the
3294 * following cases can arise: (1) the final quantum of
3295 * encoding input is an integral multiple of 24 bits; here,
3296 * the final unit of encoded output will be an integral
3297 * multiple of indent: Standard input:701: Warning:old style
3298 * assignment ambiguity in "=*". Assuming "= *" 4 characters
3299 * with no "=" padding, (2) the final
3300 * quantum of encoding input is exactly 8 bits; here, the
3301 * final unit of encoded output will be two characters
3302 * followed by two "=" padding characters, or (3) the final
3303 * quantum of encoding input is exactly 16 bits; here, the
3304 * final unit of encoded output will be three characters
3305 * followed by one "=" padding character." */
3307 total
= 3 * (i
/ 4);
3311 } else if (pad
== 1) {
3316 for (decc
= _xmlSchemaBase64Decode(*cur
);
3317 (decc
< 0) || (decc
> 63);
3318 decc
= _xmlSchemaBase64Decode(*cur
))
3320 /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
3321 /* 00111100 -> 0x3c */
3325 } else if (pad
== 2) {
3330 for (decc
= _xmlSchemaBase64Decode(*cur
);
3331 (decc
< 0) || (decc
> 63);
3332 decc
= _xmlSchemaBase64Decode(*cur
))
3334 /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
3335 /* 00110000 -> 0x30 */
3343 v
= xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY
);
3347 (xmlChar
*) xmlMallocAtomic(i
+ pad
+ 1);
3349 xmlSchemaTypeErrMemory(node
, "allocating base64 data");
3353 v
->value
.base64
.str
= base
;
3354 for (cur
= value
; *cur
; ++cur
)
3355 if (_xmlSchemaBase64Decode(*cur
) >= 0) {
3360 v
->value
.base64
.total
= total
;
3365 case XML_SCHEMAS_INTEGER
:
3366 case XML_SCHEMAS_PINTEGER
:
3367 case XML_SCHEMAS_NPINTEGER
:
3368 case XML_SCHEMAS_NINTEGER
:
3369 case XML_SCHEMAS_NNINTEGER
:{
3370 const xmlChar
*cur
= value
;
3371 unsigned long lo
, mi
, hi
;
3377 while IS_WSP_BLANK_CH(*cur
) cur
++;
3381 } else if (*cur
== '+')
3383 ret
= xmlSchemaParseUInt(&cur
, &lo
, &mi
, &hi
);
3387 while IS_WSP_BLANK_CH(*cur
) cur
++;
3390 if (type
->builtInType
== XML_SCHEMAS_NPINTEGER
) {
3392 ((hi
!= 0) || (mi
!= 0) || (lo
!= 0)))
3394 } else if (type
->builtInType
== XML_SCHEMAS_PINTEGER
) {
3397 if ((hi
== 0) && (mi
== 0) && (lo
== 0))
3399 } else if (type
->builtInType
== XML_SCHEMAS_NINTEGER
) {
3402 if ((hi
== 0) && (mi
== 0) && (lo
== 0))
3404 } else if (type
->builtInType
== XML_SCHEMAS_NNINTEGER
) {
3406 ((hi
!= 0) || (mi
!= 0) || (lo
!= 0)))
3410 v
= xmlSchemaNewValue(type
->builtInType
);
3414 v
->value
.decimal
.lo
= lo
;
3415 v
->value
.decimal
.mi
= mi
;
3416 v
->value
.decimal
.hi
= hi
;
3417 v
->value
.decimal
.sign
= sign
;
3418 v
->value
.decimal
.frac
= 0;
3419 v
->value
.decimal
.total
= ret
;
3425 case XML_SCHEMAS_LONG
:
3426 case XML_SCHEMAS_BYTE
:
3427 case XML_SCHEMAS_SHORT
:
3428 case XML_SCHEMAS_INT
:{
3429 const xmlChar
*cur
= value
;
3430 unsigned long lo
, mi
, hi
;
3436 while IS_WSP_BLANK_CH(*cur
) cur
++;
3440 } else if (*cur
== '+')
3442 ret
= xmlSchemaParseUInt(&cur
, &lo
, &mi
, &hi
);
3446 while IS_WSP_BLANK_CH(*cur
) cur
++;
3449 if (type
->builtInType
== XML_SCHEMAS_LONG
) {
3453 if (mi
>= 33720368) {
3456 if ((sign
== 0) && (lo
> 54775807))
3458 if ((sign
== 1) && (lo
> 54775808))
3462 } else if (type
->builtInType
== XML_SCHEMAS_INT
) {
3468 if ((sign
== 0) && (lo
> 47483647))
3470 if ((sign
== 1) && (lo
> 47483648))
3473 } else if (type
->builtInType
== XML_SCHEMAS_SHORT
) {
3474 if ((mi
!= 0) || (hi
!= 0))
3476 if ((sign
== 1) && (lo
> 32768))
3478 if ((sign
== 0) && (lo
> 32767))
3480 } else if (type
->builtInType
== XML_SCHEMAS_BYTE
) {
3481 if ((mi
!= 0) || (hi
!= 0))
3483 if ((sign
== 1) && (lo
> 128))
3485 if ((sign
== 0) && (lo
> 127))
3489 v
= xmlSchemaNewValue(type
->builtInType
);
3491 v
->value
.decimal
.lo
= lo
;
3492 v
->value
.decimal
.mi
= mi
;
3493 v
->value
.decimal
.hi
= hi
;
3494 v
->value
.decimal
.sign
= sign
;
3495 v
->value
.decimal
.frac
= 0;
3496 v
->value
.decimal
.total
= ret
;
3502 case XML_SCHEMAS_UINT
:
3503 case XML_SCHEMAS_ULONG
:
3504 case XML_SCHEMAS_USHORT
:
3505 case XML_SCHEMAS_UBYTE
:{
3506 const xmlChar
*cur
= value
;
3507 unsigned long lo
, mi
, hi
;
3512 while IS_WSP_BLANK_CH(*cur
) cur
++;
3513 ret
= xmlSchemaParseUInt(&cur
, &lo
, &mi
, &hi
);
3517 while IS_WSP_BLANK_CH(*cur
) cur
++;
3520 if (type
->builtInType
== XML_SCHEMAS_ULONG
) {
3524 if (mi
>= 67440737) {
3531 } else if (type
->builtInType
== XML_SCHEMAS_UINT
) {
3540 } else if (type
->builtInType
== XML_SCHEMAS_USHORT
) {
3541 if ((mi
!= 0) || (hi
!= 0))
3545 } else if (type
->builtInType
== XML_SCHEMAS_UBYTE
) {
3546 if ((mi
!= 0) || (hi
!= 0))
3552 v
= xmlSchemaNewValue(type
->builtInType
);
3554 v
->value
.decimal
.lo
= lo
;
3555 v
->value
.decimal
.mi
= mi
;
3556 v
->value
.decimal
.hi
= hi
;
3557 v
->value
.decimal
.sign
= 0;
3558 v
->value
.decimal
.frac
= 0;
3559 v
->value
.decimal
.total
= ret
;
3590 * xmlSchemaValPredefTypeNode:
3591 * @type: the predefined type
3592 * @value: the value to check
3593 * @val: the return computed value
3594 * @node: the node containing the value
3596 * Check that a value conforms to the lexical space of the predefined type.
3597 * if true a value is computed and returned in @val.
3599 * Returns 0 if this validates, a positive error code number otherwise
3600 * and -1 in case of internal or API error.
3603 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type
, const xmlChar
*value
,
3604 xmlSchemaValPtr
*val
, xmlNodePtr node
) {
3605 return(xmlSchemaValAtomicType(type
, value
, val
, node
, 0,
3606 XML_SCHEMA_WHITESPACE_UNKNOWN
, 1, 1, 0));
3610 * xmlSchemaValPredefTypeNodeNoNorm:
3611 * @type: the predefined type
3612 * @value: the value to check
3613 * @val: the return computed value
3614 * @node: the node containing the value
3616 * Check that a value conforms to the lexical space of the predefined type.
3617 * if true a value is computed and returned in @val.
3618 * This one does apply any normalization to the value.
3620 * Returns 0 if this validates, a positive error code number otherwise
3621 * and -1 in case of internal or API error.
3624 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type
, const xmlChar
*value
,
3625 xmlSchemaValPtr
*val
, xmlNodePtr node
) {
3626 return(xmlSchemaValAtomicType(type
, value
, val
, node
, 1,
3627 XML_SCHEMA_WHITESPACE_UNKNOWN
, 1, 0, 1));
3631 * xmlSchemaValidatePredefinedType:
3632 * @type: the predefined type
3633 * @value: the value to check
3634 * @val: the return computed value
3636 * Check that a value conforms to the lexical space of the predefined type.
3637 * if true a value is computed and returned in @val.
3639 * Returns 0 if this validates, a positive error code number otherwise
3640 * and -1 in case of internal or API error.
3643 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type
, const xmlChar
*value
,
3644 xmlSchemaValPtr
*val
) {
3645 return(xmlSchemaValPredefTypeNode(type
, value
, val
, NULL
));
3649 * xmlSchemaCompareDecimals:
3650 * @x: a first decimal value
3651 * @y: a second decimal value
3653 * Compare 2 decimals
3655 * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
3658 xmlSchemaCompareDecimals(xmlSchemaValPtr x
, xmlSchemaValPtr y
)
3660 xmlSchemaValPtr swp
;
3661 int order
= 1, integx
, integy
, dlen
;
3662 unsigned long hi
, mi
, lo
;
3665 * First test: If x is -ve and not zero
3667 if ((x
->value
.decimal
.sign
) &&
3668 ((x
->value
.decimal
.lo
!= 0) ||
3669 (x
->value
.decimal
.mi
!= 0) ||
3670 (x
->value
.decimal
.hi
!= 0))) {
3672 * Then if y is -ve and not zero reverse the compare
3674 if ((y
->value
.decimal
.sign
) &&
3675 ((y
->value
.decimal
.lo
!= 0) ||
3676 (y
->value
.decimal
.mi
!= 0) ||
3677 (y
->value
.decimal
.hi
!= 0)))
3680 * Otherwise (y >= 0) we have the answer
3685 * If x is not -ve and y is -ve we have the answer
3687 } else if ((y
->value
.decimal
.sign
) &&
3688 ((y
->value
.decimal
.lo
!= 0) ||
3689 (y
->value
.decimal
.mi
!= 0) ||
3690 (y
->value
.decimal
.hi
!= 0))) {
3694 * If it's not simply determined by a difference in sign,
3695 * then we need to compare the actual values of the two nums.
3696 * To do this, we start by looking at the integral parts.
3697 * If the number of integral digits differ, then we have our
3700 integx
= x
->value
.decimal
.total
- x
->value
.decimal
.frac
;
3701 integy
= y
->value
.decimal
.total
- y
->value
.decimal
.frac
;
3703 * NOTE: We changed the "total" for values like "0.1"
3704 * (or "-0.1" or ".1") to be 1, which was 2 previously.
3705 * Therefore the special case, when such values are
3706 * compared with 0, needs to be handled separately;
3707 * otherwise a zero would be recognized incorrectly as
3708 * greater than those values. This has the nice side effect
3709 * that we gain an overall optimized comparison with zeroes.
3710 * Note that a "0" has a "total" of 1 already.
3713 if (x
->value
.decimal
.lo
== 0) {
3716 else if (y
->value
.decimal
.lo
!= 0)
3723 if (y
->value
.decimal
.lo
== 0) {
3726 else if (x
->value
.decimal
.lo
!= 0)
3733 if (integx
> integy
)
3735 else if (integy
> integx
)
3739 * If the number of integral digits is the same for both numbers,
3740 * then things get a little more complicated. We need to "normalize"
3741 * the numbers in order to properly compare them. To do this, we
3742 * look at the total length of each number (length => number of
3743 * significant digits), and divide the "shorter" by 10 (decreasing
3744 * the length) until they are of equal length.
3746 dlen
= x
->value
.decimal
.total
- y
->value
.decimal
.total
;
3747 if (dlen
< 0) { /* y has more digits than x */
3749 hi
= y
->value
.decimal
.hi
;
3750 mi
= y
->value
.decimal
.mi
;
3751 lo
= y
->value
.decimal
.lo
;
3754 } else { /* x has more digits than y */
3756 hi
= x
->value
.decimal
.hi
;
3757 mi
= x
->value
.decimal
.mi
;
3758 lo
= x
->value
.decimal
.lo
;
3760 while (dlen
> 8) { /* in effect, right shift by 10**8 */
3767 unsigned long rem1
, rem2
;
3768 rem1
= (hi
% 10) * 100000000L;
3770 rem2
= (mi
% 10) * 100000000L;
3771 mi
= (mi
+ rem1
) / 10;
3772 lo
= (lo
+ rem2
) / 10;
3775 if (hi
> swp
->value
.decimal
.hi
) {
3777 } else if (hi
== swp
->value
.decimal
.hi
) {
3778 if (mi
> swp
->value
.decimal
.mi
) {
3780 } else if (mi
== swp
->value
.decimal
.mi
) {
3781 if (lo
> swp
->value
.decimal
.lo
) {
3783 } else if (lo
== swp
->value
.decimal
.lo
) {
3784 if (x
->value
.decimal
.total
== y
->value
.decimal
.total
) {
3796 * xmlSchemaCompareDurations:
3797 * @x: a first duration value
3798 * @y: a second duration value
3800 * Compare 2 durations
3802 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3806 xmlSchemaCompareDurations(xmlSchemaValPtr x
, xmlSchemaValPtr y
)
3808 long carry
, mon
, day
;
3811 long xmon
, xday
, myear
, minday
, maxday
;
3812 static const long dayRange
[2][12] = {
3813 { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
3814 { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
3816 if ((x
== NULL
) || (y
== NULL
))
3820 mon
= x
->value
.dur
.mon
- y
->value
.dur
.mon
;
3823 sec
= x
->value
.dur
.sec
- y
->value
.dur
.sec
;
3824 carry
= (long)(sec
/ SECS_PER_DAY
);
3825 sec
-= ((double)carry
) * SECS_PER_DAY
;
3828 day
= x
->value
.dur
.day
- y
->value
.dur
.day
+ carry
;
3846 if ((day
>= 0) && (sec
>= 0.0))
3852 } else if ((day
<= 0) && (sec
<= 0.0)) {
3865 if (myear
> LONG_MAX
/ 366)
3867 /* FIXME: This doesn't take leap year exceptions every 100/400 years
3869 maxday
= 365 * myear
+ (myear
+ 3) / 4;
3870 /* FIXME: Needs to be calculated separately */
3871 minday
= maxday
- 1;
3875 minday
+= dayRange
[0][xmon
];
3876 maxday
+= dayRange
[1][xmon
];
3878 if ((maxday
== minday
) && (maxday
== xday
))
3879 return(0); /* can this really happen ? */
3890 * macros for adding date/times and durations
3892 #define FQUOTIENT(a,b) (floor(((double)a/(double)b)))
3893 #define MODULO(a,b) (a - FQUOTIENT(a,b) * b)
3894 #define FQUOTIENT_RANGE(a,low,high) (FQUOTIENT((a-low),(high-low)))
3895 #define MODULO_RANGE(a,low,high) ((MODULO((a-low),(high-low)))+low)
3899 * @v: the #xmlSchemaValPtr value to duplicate
3901 * Makes a copy of @v. The calling program is responsible for freeing
3902 * the returned value.
3904 * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error.
3906 static xmlSchemaValPtr
3907 xmlSchemaDupVal (xmlSchemaValPtr v
)
3909 xmlSchemaValPtr ret
= xmlSchemaNewValue(v
->type
);
3913 memcpy(ret
, v
, sizeof(xmlSchemaVal
));
3919 * xmlSchemaCopyValue:
3920 * @val: the precomputed value to be copied
3922 * Copies the precomputed value. This duplicates any string within.
3924 * Returns the copy or NULL if a copy for a data-type is not implemented.
3927 xmlSchemaCopyValue(xmlSchemaValPtr val
)
3929 xmlSchemaValPtr ret
= NULL
, prev
= NULL
, cur
;
3932 * Copy the string values.
3934 while (val
!= NULL
) {
3935 switch (val
->type
) {
3936 case XML_SCHEMAS_ANYTYPE
:
3937 case XML_SCHEMAS_IDREFS
:
3938 case XML_SCHEMAS_ENTITIES
:
3939 case XML_SCHEMAS_NMTOKENS
:
3940 xmlSchemaFreeValue(ret
);
3942 case XML_SCHEMAS_ANYSIMPLETYPE
:
3943 case XML_SCHEMAS_STRING
:
3944 case XML_SCHEMAS_NORMSTRING
:
3945 case XML_SCHEMAS_TOKEN
:
3946 case XML_SCHEMAS_LANGUAGE
:
3947 case XML_SCHEMAS_NAME
:
3948 case XML_SCHEMAS_NCNAME
:
3949 case XML_SCHEMAS_ID
:
3950 case XML_SCHEMAS_IDREF
:
3951 case XML_SCHEMAS_ENTITY
:
3952 case XML_SCHEMAS_NMTOKEN
:
3953 case XML_SCHEMAS_ANYURI
:
3954 cur
= xmlSchemaDupVal(val
);
3955 if (val
->value
.str
!= NULL
)
3956 cur
->value
.str
= xmlStrdup(BAD_CAST val
->value
.str
);
3958 case XML_SCHEMAS_QNAME
:
3959 case XML_SCHEMAS_NOTATION
:
3960 cur
= xmlSchemaDupVal(val
);
3961 if (val
->value
.qname
.name
!= NULL
)
3962 cur
->value
.qname
.name
=
3963 xmlStrdup(BAD_CAST val
->value
.qname
.name
);
3964 if (val
->value
.qname
.uri
!= NULL
)
3965 cur
->value
.qname
.uri
=
3966 xmlStrdup(BAD_CAST val
->value
.qname
.uri
);
3968 case XML_SCHEMAS_HEXBINARY
:
3969 cur
= xmlSchemaDupVal(val
);
3970 if (val
->value
.hex
.str
!= NULL
)
3971 cur
->value
.hex
.str
= xmlStrdup(BAD_CAST val
->value
.hex
.str
);
3973 case XML_SCHEMAS_BASE64BINARY
:
3974 cur
= xmlSchemaDupVal(val
);
3975 if (val
->value
.base64
.str
!= NULL
)
3976 cur
->value
.base64
.str
=
3977 xmlStrdup(BAD_CAST val
->value
.base64
.str
);
3980 cur
= xmlSchemaDupVal(val
);
3994 * _xmlSchemaDateAdd:
3995 * @dt: an #xmlSchemaValPtr
3996 * @dur: an #xmlSchemaValPtr of type #XS_DURATION
3998 * Compute a new date/time from @dt and @dur. This function assumes @dt
3999 * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
4000 * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as
4001 * @dt. The calling program is responsible for freeing the returned value.
4003 * Returns a pointer to a new #xmlSchemaVal or NULL if error.
4005 static xmlSchemaValPtr
4006 _xmlSchemaDateAdd (xmlSchemaValPtr dt
, xmlSchemaValPtr dur
)
4008 xmlSchemaValPtr ret
, tmp
;
4009 long carry
, tempdays
, temp
;
4010 xmlSchemaValDatePtr r
, d
;
4011 xmlSchemaValDurationPtr u
;
4013 if ((dt
== NULL
) || (dur
== NULL
))
4016 ret
= xmlSchemaNewValue(dt
->type
);
4020 /* make a copy so we don't alter the original value */
4021 tmp
= xmlSchemaDupVal(dt
);
4023 xmlSchemaFreeValue(ret
);
4027 r
= &(ret
->value
.date
);
4028 d
= &(tmp
->value
.date
);
4029 u
= &(dur
->value
.dur
);
4035 /* normalize for time zone offset */
4036 u
->sec
-= (d
->tzo
* 60);
4044 carry
= d
->mon
+ u
->mon
;
4045 r
->mon
= (unsigned int) MODULO_RANGE(carry
, 1, 13);
4046 carry
= (long) FQUOTIENT_RANGE(carry
, 1, 13);
4048 /* year (may be modified later) */
4049 r
->year
= d
->year
+ carry
;
4059 r
->tz_flag
= d
->tz_flag
;
4062 r
->sec
= d
->sec
+ u
->sec
;
4063 carry
= (long) FQUOTIENT((long)r
->sec
, 60);
4064 if (r
->sec
!= 0.0) {
4065 r
->sec
= MODULO(r
->sec
, 60.0);
4070 r
->min
= (unsigned int) MODULO(carry
, 60);
4071 carry
= (long) FQUOTIENT(carry
, 60);
4075 r
->hour
= (unsigned int) MODULO(carry
, 24);
4076 carry
= (long)FQUOTIENT(carry
, 24);
4080 * Note we use tempdays because the temporary values may need more
4083 if ((VALID_YEAR(r
->year
)) && (VALID_MONTH(r
->mon
)) &&
4084 (d
->day
> MAX_DAYINMONTH(r
->year
, r
->mon
)))
4085 tempdays
= MAX_DAYINMONTH(r
->year
, r
->mon
);
4086 else if (d
->day
< 1)
4091 tempdays
+= u
->day
+ carry
;
4095 long tmon
= (long) MODULO_RANGE((int)r
->mon
-1, 1, 13);
4096 long tyr
= r
->year
+ (long)FQUOTIENT_RANGE((int)r
->mon
-1, 1, 13);
4100 * Coverity detected an overrun in daysInMonth
4101 * of size 12 at position 12 with index variable "((r)->mon - 1)"
4107 tempdays
+= MAX_DAYINMONTH(tyr
, tmon
);
4109 } else if (VALID_YEAR(r
->year
) && VALID_MONTH(r
->mon
) &&
4110 tempdays
> (long) MAX_DAYINMONTH(r
->year
, r
->mon
)) {
4111 tempdays
= tempdays
- MAX_DAYINMONTH(r
->year
, r
->mon
);
4116 temp
= r
->mon
+ carry
;
4117 r
->mon
= (unsigned int) MODULO_RANGE(temp
, 1, 13);
4118 r
->year
= r
->year
+ (long) FQUOTIENT_RANGE(temp
, 1, 13);
4130 * adjust the date/time type to the date values
4132 if (ret
->type
!= XML_SCHEMAS_DATETIME
) {
4133 if ((r
->hour
) || (r
->min
) || (r
->sec
))
4134 ret
->type
= XML_SCHEMAS_DATETIME
;
4135 else if (ret
->type
!= XML_SCHEMAS_DATE
) {
4136 if ((r
->mon
!= 1) && (r
->day
!= 1))
4137 ret
->type
= XML_SCHEMAS_DATE
;
4138 else if ((ret
->type
!= XML_SCHEMAS_GYEARMONTH
) && (r
->mon
!= 1))
4139 ret
->type
= XML_SCHEMAS_GYEARMONTH
;
4143 xmlSchemaFreeValue(tmp
);
4149 * xmlSchemaDateNormalize:
4150 * @dt: an #xmlSchemaValPtr of a date/time type value.
4151 * @offset: number of seconds to adjust @dt by.
4153 * Normalize @dt to GMT time. The @offset parameter is subtracted from
4154 * the return value is a time-zone offset is present on @dt.
4156 * Returns a normalized copy of @dt or NULL if error.
4158 static xmlSchemaValPtr
4159 xmlSchemaDateNormalize (xmlSchemaValPtr dt
, double offset
)
4161 xmlSchemaValPtr dur
, ret
;
4166 if (((dt
->type
!= XML_SCHEMAS_TIME
) &&
4167 (dt
->type
!= XML_SCHEMAS_DATETIME
) &&
4168 (dt
->type
!= XML_SCHEMAS_DATE
)) || (dt
->value
.date
.tzo
== 0))
4169 return xmlSchemaDupVal(dt
);
4171 dur
= xmlSchemaNewValue(XML_SCHEMAS_DURATION
);
4175 dur
->value
.date
.sec
-= offset
;
4177 ret
= _xmlSchemaDateAdd(dt
, dur
);
4181 xmlSchemaFreeValue(dur
);
4183 /* ret->value.date.tzo = 0; */
4188 * _xmlSchemaDateCastYMToDays:
4189 * @dt: an #xmlSchemaValPtr
4191 * Convert mon and year of @dt to total number of days. Take the
4192 * number of years since (or before) 1 AD and add the number of leap
4193 * years. This is a function because negative
4194 * years must be handled a little differently and there is no zero year.
4196 * Returns number of days.
4199 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt
)
4204 mon
= dt
->value
.date
.mon
;
4205 if (mon
<= 0) mon
= 1; /* normalization */
4207 if (dt
->value
.date
.year
<= 0)
4208 ret
= (dt
->value
.date
.year
* 365) +
4209 (((dt
->value
.date
.year
+1)/4)-((dt
->value
.date
.year
+1)/100)+
4210 ((dt
->value
.date
.year
+1)/400)) +
4211 DAY_IN_YEAR(0, mon
, dt
->value
.date
.year
);
4213 ret
= ((dt
->value
.date
.year
-1) * 365) +
4214 (((dt
->value
.date
.year
-1)/4)-((dt
->value
.date
.year
-1)/100)+
4215 ((dt
->value
.date
.year
-1)/400)) +
4216 DAY_IN_YEAR(0, mon
, dt
->value
.date
.year
);
4223 * @dt: an #xmlSchemaValPtr
4225 * Calculates the number of seconds in the time portion of @dt.
4229 #define TIME_TO_NUMBER(dt) \
4230 ((double)((dt->value.date.hour * SECS_PER_HOUR) + \
4231 (dt->value.date.min * SECS_PER_MIN) + \
4232 (dt->value.date.tzo * SECS_PER_MIN)) + \
4236 * xmlSchemaCompareDates:
4237 * @x: a first date/time value
4238 * @y: a second date/time value
4240 * Compare 2 date/times
4242 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4246 xmlSchemaCompareDates (xmlSchemaValPtr x
, xmlSchemaValPtr y
)
4248 unsigned char xmask
, ymask
, xor_mask
, and_mask
;
4249 xmlSchemaValPtr p1
, p2
, q1
, q2
;
4250 long p1d
, p2d
, q1d
, q2d
;
4252 if ((x
== NULL
) || (y
== NULL
))
4255 if ((x
->value
.date
.year
> LONG_MAX
/ 366) ||
4256 (x
->value
.date
.year
< LONG_MIN
/ 366) ||
4257 (y
->value
.date
.year
> LONG_MAX
/ 366) ||
4258 (y
->value
.date
.year
< LONG_MIN
/ 366)) {
4259 /* Possible overflow when converting to days. */
4263 if (x
->value
.date
.tz_flag
) {
4265 if (!y
->value
.date
.tz_flag
) {
4266 p1
= xmlSchemaDateNormalize(x
, 0);
4269 p1d
= _xmlSchemaDateCastYMToDays(p1
) + p1
->value
.date
.day
;
4270 /* normalize y + 14:00 */
4271 q1
= xmlSchemaDateNormalize(y
, (14 * SECS_PER_HOUR
));
4273 xmlSchemaFreeValue(p1
);
4277 q1d
= _xmlSchemaDateCastYMToDays(q1
) + q1
->value
.date
.day
;
4279 xmlSchemaFreeValue(p1
);
4280 xmlSchemaFreeValue(q1
);
4282 } else if (p1d
== q1d
) {
4285 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q1
);
4287 xmlSchemaFreeValue(p1
);
4288 xmlSchemaFreeValue(q1
);
4292 /* normalize y - 14:00 */
4293 q2
= xmlSchemaDateNormalize(y
, -(14 * SECS_PER_HOUR
));
4295 xmlSchemaFreeValue(p1
);
4296 xmlSchemaFreeValue(q1
);
4299 q2d
= _xmlSchemaDateCastYMToDays(q2
) + q2
->value
.date
.day
;
4302 else if (p1d
== q2d
) {
4303 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q2
);
4307 ret
= 2; /* indeterminate */
4309 xmlSchemaFreeValue(p1
);
4310 xmlSchemaFreeValue(q1
);
4311 xmlSchemaFreeValue(q2
);
4316 xmlSchemaFreeValue(p1
);
4317 xmlSchemaFreeValue(q1
);
4320 } else if (y
->value
.date
.tz_flag
) {
4321 q1
= xmlSchemaDateNormalize(y
, 0);
4324 q1d
= _xmlSchemaDateCastYMToDays(q1
) + q1
->value
.date
.day
;
4326 /* normalize x - 14:00 */
4327 p1
= xmlSchemaDateNormalize(x
, -(14 * SECS_PER_HOUR
));
4329 xmlSchemaFreeValue(q1
);
4332 p1d
= _xmlSchemaDateCastYMToDays(p1
) + p1
->value
.date
.day
;
4335 xmlSchemaFreeValue(p1
);
4336 xmlSchemaFreeValue(q1
);
4338 } else if (p1d
== q1d
) {
4341 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q1
);
4343 xmlSchemaFreeValue(p1
);
4344 xmlSchemaFreeValue(q1
);
4348 /* normalize x + 14:00 */
4349 p2
= xmlSchemaDateNormalize(x
, (14 * SECS_PER_HOUR
));
4351 xmlSchemaFreeValue(p1
);
4352 xmlSchemaFreeValue(q1
);
4355 p2d
= _xmlSchemaDateCastYMToDays(p2
) + p2
->value
.date
.day
;
4359 } else if (p2d
== q1d
) {
4360 sec
= TIME_TO_NUMBER(p2
) - TIME_TO_NUMBER(q1
);
4364 ret
= 2; /* indeterminate */
4366 xmlSchemaFreeValue(p1
);
4367 xmlSchemaFreeValue(q1
);
4368 xmlSchemaFreeValue(p2
);
4373 xmlSchemaFreeValue(p1
);
4374 xmlSchemaFreeValue(q1
);
4379 * if the same type then calculate the difference
4381 if (x
->type
== y
->type
) {
4383 q1
= xmlSchemaDateNormalize(y
, 0);
4386 q1d
= _xmlSchemaDateCastYMToDays(q1
) + q1
->value
.date
.day
;
4388 p1
= xmlSchemaDateNormalize(x
, 0);
4390 xmlSchemaFreeValue(q1
);
4393 p1d
= _xmlSchemaDateCastYMToDays(p1
) + p1
->value
.date
.day
;
4397 } else if (p1d
> q1d
) {
4402 sec
= TIME_TO_NUMBER(p1
) - TIME_TO_NUMBER(q1
);
4409 xmlSchemaFreeValue(p1
);
4410 xmlSchemaFreeValue(q1
);
4415 case XML_SCHEMAS_DATETIME
:
4418 case XML_SCHEMAS_DATE
:
4421 case XML_SCHEMAS_GYEAR
:
4424 case XML_SCHEMAS_GMONTH
:
4427 case XML_SCHEMAS_GDAY
:
4430 case XML_SCHEMAS_GYEARMONTH
:
4433 case XML_SCHEMAS_GMONTHDAY
:
4436 case XML_SCHEMAS_TIME
:
4445 case XML_SCHEMAS_DATETIME
:
4448 case XML_SCHEMAS_DATE
:
4451 case XML_SCHEMAS_GYEAR
:
4454 case XML_SCHEMAS_GMONTH
:
4457 case XML_SCHEMAS_GDAY
:
4460 case XML_SCHEMAS_GYEARMONTH
:
4463 case XML_SCHEMAS_GMONTHDAY
:
4466 case XML_SCHEMAS_TIME
:
4474 xor_mask
= xmask
^ ymask
; /* mark type differences */
4475 and_mask
= xmask
& ymask
; /* mark field specification */
4479 return 2; /* indeterminate */
4480 else if (and_mask
& 1) {
4481 if (x
->value
.date
.year
< y
->value
.date
.year
)
4483 else if (x
->value
.date
.year
> y
->value
.date
.year
)
4489 return 2; /* indeterminate */
4490 else if (and_mask
& 2) {
4491 if (x
->value
.date
.mon
< y
->value
.date
.mon
)
4493 else if (x
->value
.date
.mon
> y
->value
.date
.mon
)
4499 return 2; /* indeterminate */
4500 else if (and_mask
& 4) {
4501 if (x
->value
.date
.day
< y
->value
.date
.day
)
4503 else if (x
->value
.date
.day
> y
->value
.date
.day
)
4509 return 2; /* indeterminate */
4510 else if (and_mask
& 8) {
4511 if (x
->value
.date
.hour
< y
->value
.date
.hour
)
4513 else if (x
->value
.date
.hour
> y
->value
.date
.hour
)
4515 else if (x
->value
.date
.min
< y
->value
.date
.min
)
4517 else if (x
->value
.date
.min
> y
->value
.date
.min
)
4519 else if (x
->value
.date
.sec
< y
->value
.date
.sec
)
4521 else if (x
->value
.date
.sec
> y
->value
.date
.sec
)
4529 * xmlSchemaComparePreserveReplaceStrings:
4530 * @x: a first string value
4531 * @y: a second string value
4532 * @invert: inverts the result if x < y or x > y.
4534 * Compare 2 string for their normalized values.
4535 * @x is a string with whitespace of "preserve", @y is
4536 * a string with a whitespace of "replace". I.e. @x could
4537 * be an "xsd:string" and @y an "xsd:normalizedString".
4539 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4543 xmlSchemaComparePreserveReplaceStrings(const xmlChar
*x
,
4549 while ((*x
!= 0) && (*y
!= 0)) {
4550 if (IS_WSP_REPLACE_CH(*y
)) {
4551 if (! IS_WSP_SPACE_CH(*x
)) {
4552 if ((*x
- 0x20) < 0) {
4598 * xmlSchemaComparePreserveCollapseStrings:
4599 * @x: a first string value
4600 * @y: a second string value
4602 * Compare 2 string for their normalized values.
4603 * @x is a string with whitespace of "preserve", @y is
4604 * a string with a whitespace of "collapse". I.e. @x could
4605 * be an "xsd:string" and @y an "xsd:normalizedString".
4607 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4611 xmlSchemaComparePreserveCollapseStrings(const xmlChar
*x
,
4618 * Skip leading blank chars of the collapsed string.
4620 while IS_WSP_BLANK_CH(*y
)
4623 while ((*x
!= 0) && (*y
!= 0)) {
4624 if IS_WSP_BLANK_CH(*y
) {
4625 if (! IS_WSP_SPACE_CH(*x
)) {
4627 * The yv character would have been replaced to 0x20.
4629 if ((*x
- 0x20) < 0) {
4644 * Skip contiguous blank chars of the collapsed string.
4646 while IS_WSP_BLANK_CH(*y
)
4672 * Skip trailing blank chars of the collapsed string.
4674 while IS_WSP_BLANK_CH(*y
)
4687 * xmlSchemaComparePreserveCollapseStrings:
4688 * @x: a first string value
4689 * @y: a second string value
4691 * Compare 2 string for their normalized values.
4692 * @x is a string with whitespace of "preserve", @y is
4693 * a string with a whitespace of "collapse". I.e. @x could
4694 * be an "xsd:string" and @y an "xsd:normalizedString".
4696 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4700 xmlSchemaCompareReplaceCollapseStrings(const xmlChar
*x
,
4707 * Skip leading blank chars of the collapsed string.
4709 while IS_WSP_BLANK_CH(*y
)
4712 while ((*x
!= 0) && (*y
!= 0)) {
4713 if IS_WSP_BLANK_CH(*y
) {
4714 if (! IS_WSP_BLANK_CH(*x
)) {
4716 * The yv character would have been replaced to 0x20.
4718 if ((*x
- 0x20) < 0) {
4733 * Skip contiguous blank chars of the collapsed string.
4735 while IS_WSP_BLANK_CH(*y
)
4738 if IS_WSP_BLANK_CH(*x
) {
4740 * The xv character would have been replaced to 0x20.
4742 if ((0x20 - *y
) < 0) {
4769 * Skip trailing blank chars of the collapsed string.
4771 while IS_WSP_BLANK_CH(*y
)
4785 * xmlSchemaCompareReplacedStrings:
4786 * @x: a first string value
4787 * @y: a second string value
4789 * Compare 2 string for their normalized values.
4791 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4795 xmlSchemaCompareReplacedStrings(const xmlChar
*x
,
4800 while ((*x
!= 0) && (*y
!= 0)) {
4801 if IS_WSP_BLANK_CH(*y
) {
4802 if (! IS_WSP_BLANK_CH(*x
)) {
4803 if ((*x
- 0x20) < 0)
4809 if IS_WSP_BLANK_CH(*x
) {
4810 if ((0x20 - *y
) < 0)
4832 * xmlSchemaCompareNormStrings:
4833 * @x: a first string value
4834 * @y: a second string value
4836 * Compare 2 string for their normalized values.
4838 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4842 xmlSchemaCompareNormStrings(const xmlChar
*x
,
4846 while (IS_BLANK_CH(*x
)) x
++;
4847 while (IS_BLANK_CH(*y
)) y
++;
4848 while ((*x
!= 0) && (*y
!= 0)) {
4849 if (IS_BLANK_CH(*x
)) {
4850 if (!IS_BLANK_CH(*y
)) {
4854 while (IS_BLANK_CH(*x
)) x
++;
4855 while (IS_BLANK_CH(*y
)) y
++;
4865 while (IS_BLANK_CH(*x
)) x
++;
4870 while (IS_BLANK_CH(*y
)) y
++;
4878 * xmlSchemaCompareFloats:
4879 * @x: a first float or double value
4880 * @y: a second float or double value
4884 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4888 xmlSchemaCompareFloats(xmlSchemaValPtr x
, xmlSchemaValPtr y
) {
4891 if ((x
== NULL
) || (y
== NULL
))
4895 * Cast everything to doubles.
4897 if (x
->type
== XML_SCHEMAS_DOUBLE
)
4899 else if (x
->type
== XML_SCHEMAS_FLOAT
)
4904 if (y
->type
== XML_SCHEMAS_DOUBLE
)
4906 else if (y
->type
== XML_SCHEMAS_FLOAT
)
4912 * Check for special cases.
4914 if (xmlXPathIsNaN(d1
)) {
4915 if (xmlXPathIsNaN(d2
))
4919 if (xmlXPathIsNaN(d2
))
4921 if (d1
== xmlXPathPINF
) {
4922 if (d2
== xmlXPathPINF
)
4926 if (d2
== xmlXPathPINF
)
4928 if (d1
== xmlXPathNINF
) {
4929 if (d2
== xmlXPathNINF
)
4933 if (d2
== xmlXPathNINF
)
4937 * basic tests, the last one we should have equality, but
4938 * portability is more important than speed and handling
4939 * NaN or Inf in a portable way is always a challenge, so ...
4951 * xmlSchemaCompareValues:
4953 * @xvalue: the first value as a string (optional)
4954 * @xwtsp: the whitespace type
4955 * @y: a second value
4956 * @xvalue: the second value as a string (optional)
4957 * @ywtsp: the whitespace type
4961 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not
4962 * comparable and -2 in case of error
4965 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype
,
4967 const xmlChar
*xvalue
,
4968 xmlSchemaWhitespaceValueType xws
,
4969 xmlSchemaValType ytype
,
4971 const xmlChar
*yvalue
,
4972 xmlSchemaWhitespaceValueType yws
)
4975 case XML_SCHEMAS_UNKNOWN
:
4976 case XML_SCHEMAS_ANYTYPE
:
4978 case XML_SCHEMAS_INTEGER
:
4979 case XML_SCHEMAS_NPINTEGER
:
4980 case XML_SCHEMAS_NINTEGER
:
4981 case XML_SCHEMAS_NNINTEGER
:
4982 case XML_SCHEMAS_PINTEGER
:
4983 case XML_SCHEMAS_INT
:
4984 case XML_SCHEMAS_UINT
:
4985 case XML_SCHEMAS_LONG
:
4986 case XML_SCHEMAS_ULONG
:
4987 case XML_SCHEMAS_SHORT
:
4988 case XML_SCHEMAS_USHORT
:
4989 case XML_SCHEMAS_BYTE
:
4990 case XML_SCHEMAS_UBYTE
:
4991 case XML_SCHEMAS_DECIMAL
:
4992 if ((x
== NULL
) || (y
== NULL
))
4995 return(xmlSchemaCompareDecimals(x
, y
));
4996 if ((ytype
== XML_SCHEMAS_DECIMAL
) ||
4997 (ytype
== XML_SCHEMAS_INTEGER
) ||
4998 (ytype
== XML_SCHEMAS_NPINTEGER
) ||
4999 (ytype
== XML_SCHEMAS_NINTEGER
) ||
5000 (ytype
== XML_SCHEMAS_NNINTEGER
) ||
5001 (ytype
== XML_SCHEMAS_PINTEGER
) ||
5002 (ytype
== XML_SCHEMAS_INT
) ||
5003 (ytype
== XML_SCHEMAS_UINT
) ||
5004 (ytype
== XML_SCHEMAS_LONG
) ||
5005 (ytype
== XML_SCHEMAS_ULONG
) ||
5006 (ytype
== XML_SCHEMAS_SHORT
) ||
5007 (ytype
== XML_SCHEMAS_USHORT
) ||
5008 (ytype
== XML_SCHEMAS_BYTE
) ||
5009 (ytype
== XML_SCHEMAS_UBYTE
))
5010 return(xmlSchemaCompareDecimals(x
, y
));
5012 case XML_SCHEMAS_DURATION
:
5013 if ((x
== NULL
) || (y
== NULL
))
5015 if (ytype
== XML_SCHEMAS_DURATION
)
5016 return(xmlSchemaCompareDurations(x
, y
));
5018 case XML_SCHEMAS_TIME
:
5019 case XML_SCHEMAS_GDAY
:
5020 case XML_SCHEMAS_GMONTH
:
5021 case XML_SCHEMAS_GMONTHDAY
:
5022 case XML_SCHEMAS_GYEAR
:
5023 case XML_SCHEMAS_GYEARMONTH
:
5024 case XML_SCHEMAS_DATE
:
5025 case XML_SCHEMAS_DATETIME
:
5026 if ((x
== NULL
) || (y
== NULL
))
5028 if ((ytype
== XML_SCHEMAS_DATETIME
) ||
5029 (ytype
== XML_SCHEMAS_TIME
) ||
5030 (ytype
== XML_SCHEMAS_GDAY
) ||
5031 (ytype
== XML_SCHEMAS_GMONTH
) ||
5032 (ytype
== XML_SCHEMAS_GMONTHDAY
) ||
5033 (ytype
== XML_SCHEMAS_GYEAR
) ||
5034 (ytype
== XML_SCHEMAS_DATE
) ||
5035 (ytype
== XML_SCHEMAS_GYEARMONTH
))
5036 return (xmlSchemaCompareDates(x
, y
));
5039 * Note that we will support comparison of string types against
5040 * anySimpleType as well.
5042 case XML_SCHEMAS_ANYSIMPLETYPE
:
5043 case XML_SCHEMAS_STRING
:
5044 case XML_SCHEMAS_NORMSTRING
:
5045 case XML_SCHEMAS_TOKEN
:
5046 case XML_SCHEMAS_LANGUAGE
:
5047 case XML_SCHEMAS_NMTOKEN
:
5048 case XML_SCHEMAS_NAME
:
5049 case XML_SCHEMAS_NCNAME
:
5050 case XML_SCHEMAS_ID
:
5051 case XML_SCHEMAS_IDREF
:
5052 case XML_SCHEMAS_ENTITY
:
5053 case XML_SCHEMAS_ANYURI
:
5055 const xmlChar
*xv
, *yv
;
5066 * TODO: Compare those against QName.
5068 if (ytype
== XML_SCHEMAS_QNAME
) {
5074 if ((ytype
== XML_SCHEMAS_ANYSIMPLETYPE
) ||
5075 (ytype
== XML_SCHEMAS_STRING
) ||
5076 (ytype
== XML_SCHEMAS_NORMSTRING
) ||
5077 (ytype
== XML_SCHEMAS_TOKEN
) ||
5078 (ytype
== XML_SCHEMAS_LANGUAGE
) ||
5079 (ytype
== XML_SCHEMAS_NMTOKEN
) ||
5080 (ytype
== XML_SCHEMAS_NAME
) ||
5081 (ytype
== XML_SCHEMAS_NCNAME
) ||
5082 (ytype
== XML_SCHEMAS_ID
) ||
5083 (ytype
== XML_SCHEMAS_IDREF
) ||
5084 (ytype
== XML_SCHEMAS_ENTITY
) ||
5085 (ytype
== XML_SCHEMAS_ANYURI
)) {
5087 if (xws
== XML_SCHEMA_WHITESPACE_PRESERVE
) {
5089 if (yws
== XML_SCHEMA_WHITESPACE_PRESERVE
) {
5090 /* TODO: What about x < y or x > y. */
5091 if (xmlStrEqual(xv
, yv
))
5095 } else if (yws
== XML_SCHEMA_WHITESPACE_REPLACE
)
5096 return (xmlSchemaComparePreserveReplaceStrings(xv
, yv
, 0));
5097 else if (yws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
5098 return (xmlSchemaComparePreserveCollapseStrings(xv
, yv
, 0));
5100 } else if (xws
== XML_SCHEMA_WHITESPACE_REPLACE
) {
5102 if (yws
== XML_SCHEMA_WHITESPACE_PRESERVE
)
5103 return (xmlSchemaComparePreserveReplaceStrings(yv
, xv
, 1));
5104 if (yws
== XML_SCHEMA_WHITESPACE_REPLACE
)
5105 return (xmlSchemaCompareReplacedStrings(xv
, yv
));
5106 if (yws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
5107 return (xmlSchemaCompareReplaceCollapseStrings(xv
, yv
, 0));
5109 } else if (xws
== XML_SCHEMA_WHITESPACE_COLLAPSE
) {
5111 if (yws
== XML_SCHEMA_WHITESPACE_PRESERVE
)
5112 return (xmlSchemaComparePreserveCollapseStrings(yv
, xv
, 1));
5113 if (yws
== XML_SCHEMA_WHITESPACE_REPLACE
)
5114 return (xmlSchemaCompareReplaceCollapseStrings(yv
, xv
, 1));
5115 if (yws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
5116 return (xmlSchemaCompareNormStrings(xv
, yv
));
5123 case XML_SCHEMAS_QNAME
:
5124 case XML_SCHEMAS_NOTATION
:
5125 if ((x
== NULL
) || (y
== NULL
))
5127 if ((ytype
== XML_SCHEMAS_QNAME
) ||
5128 (ytype
== XML_SCHEMAS_NOTATION
)) {
5129 if ((xmlStrEqual(x
->value
.qname
.name
, y
->value
.qname
.name
)) &&
5130 (xmlStrEqual(x
->value
.qname
.uri
, y
->value
.qname
.uri
)))
5135 case XML_SCHEMAS_FLOAT
:
5136 case XML_SCHEMAS_DOUBLE
:
5137 if ((x
== NULL
) || (y
== NULL
))
5139 if ((ytype
== XML_SCHEMAS_FLOAT
) ||
5140 (ytype
== XML_SCHEMAS_DOUBLE
))
5141 return (xmlSchemaCompareFloats(x
, y
));
5143 case XML_SCHEMAS_BOOLEAN
:
5144 if ((x
== NULL
) || (y
== NULL
))
5146 if (ytype
== XML_SCHEMAS_BOOLEAN
) {
5147 if (x
->value
.b
== y
->value
.b
)
5149 if (x
->value
.b
== 0)
5154 case XML_SCHEMAS_HEXBINARY
:
5155 if ((x
== NULL
) || (y
== NULL
))
5157 if (ytype
== XML_SCHEMAS_HEXBINARY
) {
5158 if (x
->value
.hex
.total
== y
->value
.hex
.total
) {
5159 int ret
= xmlStrcmp(x
->value
.hex
.str
, y
->value
.hex
.str
);
5165 else if (x
->value
.hex
.total
> y
->value
.hex
.total
)
5171 case XML_SCHEMAS_BASE64BINARY
:
5172 if ((x
== NULL
) || (y
== NULL
))
5174 if (ytype
== XML_SCHEMAS_BASE64BINARY
) {
5175 if (x
->value
.base64
.total
== y
->value
.base64
.total
) {
5176 int ret
= xmlStrcmp(x
->value
.base64
.str
,
5177 y
->value
.base64
.str
);
5185 else if (x
->value
.base64
.total
> y
->value
.base64
.total
)
5191 case XML_SCHEMAS_IDREFS
:
5192 case XML_SCHEMAS_ENTITIES
:
5193 case XML_SCHEMAS_NMTOKENS
:
5201 * xmlSchemaCompareValues:
5203 * @y: a second value
5207 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5211 xmlSchemaCompareValues(xmlSchemaValPtr x
, xmlSchemaValPtr y
) {
5212 xmlSchemaWhitespaceValueType xws
, yws
;
5214 if ((x
== NULL
) || (y
== NULL
))
5216 if (x
->type
== XML_SCHEMAS_STRING
)
5217 xws
= XML_SCHEMA_WHITESPACE_PRESERVE
;
5218 else if (x
->type
== XML_SCHEMAS_NORMSTRING
)
5219 xws
= XML_SCHEMA_WHITESPACE_REPLACE
;
5221 xws
= XML_SCHEMA_WHITESPACE_COLLAPSE
;
5223 if (y
->type
== XML_SCHEMAS_STRING
)
5224 yws
= XML_SCHEMA_WHITESPACE_PRESERVE
;
5225 else if (y
->type
== XML_SCHEMAS_NORMSTRING
)
5226 yws
= XML_SCHEMA_WHITESPACE_REPLACE
;
5228 yws
= XML_SCHEMA_WHITESPACE_COLLAPSE
;
5230 return(xmlSchemaCompareValuesInternal(x
->type
, x
, NULL
, xws
, y
->type
,
5235 * xmlSchemaCompareValuesWhtsp:
5237 * @xws: the whitespace value of x
5238 * @y: a second value
5239 * @yws: the whitespace value of y
5243 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5247 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x
,
5248 xmlSchemaWhitespaceValueType xws
,
5250 xmlSchemaWhitespaceValueType yws
)
5252 if ((x
== NULL
) || (y
== NULL
))
5254 return(xmlSchemaCompareValuesInternal(x
->type
, x
, NULL
, xws
, y
->type
,
5259 * xmlSchemaCompareValuesWhtspExt:
5261 * @xws: the whitespace value of x
5262 * @y: a second value
5263 * @yws: the whitespace value of y
5267 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5271 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype
,
5273 const xmlChar
*xvalue
,
5274 xmlSchemaWhitespaceValueType xws
,
5275 xmlSchemaValType ytype
,
5277 const xmlChar
*yvalue
,
5278 xmlSchemaWhitespaceValueType yws
)
5280 return(xmlSchemaCompareValuesInternal(xtype
, x
, xvalue
, xws
, ytype
, y
,
5288 * Computes the UTF8 length of the normalized value of the string
5290 * Returns the length or -1 in case of error.
5293 xmlSchemaNormLen(const xmlChar
*value
) {
5300 while (IS_BLANK_CH(*utf
)) utf
++;
5302 if (utf
[0] & 0x80) {
5303 if ((utf
[1] & 0xc0) != 0x80)
5305 if ((utf
[0] & 0xe0) == 0xe0) {
5306 if ((utf
[2] & 0xc0) != 0x80)
5308 if ((utf
[0] & 0xf0) == 0xf0) {
5309 if ((utf
[0] & 0xf8) != 0xf0 || (utf
[3] & 0xc0) != 0x80)
5318 } else if (IS_BLANK_CH(*utf
)) {
5319 while (IS_BLANK_CH(*utf
)) utf
++;
5331 * xmlSchemaGetFacetValueAsULong:
5332 * @facet: an schemas type facet
5334 * Extract the value of a facet
5336 * Returns the value as a long
5339 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet
)
5342 * TODO: Check if this is a decimal.
5344 if (facet
== NULL
|| facet
->val
== NULL
)
5346 return ((unsigned long) facet
->val
->value
.decimal
.lo
);
5350 * xmlSchemaValidateListSimpleTypeFacet:
5351 * @facet: the facet to check
5352 * @value: the lexical repr of the value to validate
5353 * @actualLen: the number of list items
5354 * @expectedLen: the resulting expected number of list items
5356 * Checks the value of a list simple type against a facet.
5358 * Returns 0 if the value is valid, a positive error code
5359 * number otherwise and -1 in case of an internal error.
5362 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet
,
5363 const xmlChar
*value
,
5364 unsigned long actualLen
,
5365 unsigned long *expectedLen
)
5370 * TODO: Check if this will work with large numbers.
5371 * (compare value.decimal.mi and value.decimal.hi as well?).
5373 if (facet
->type
== XML_SCHEMA_FACET_LENGTH
) {
5374 if (actualLen
!= facet
->val
->value
.decimal
.lo
) {
5375 if (expectedLen
!= NULL
)
5376 *expectedLen
= facet
->val
->value
.decimal
.lo
;
5377 return (XML_SCHEMAV_CVC_LENGTH_VALID
);
5379 } else if (facet
->type
== XML_SCHEMA_FACET_MINLENGTH
) {
5380 if (actualLen
< facet
->val
->value
.decimal
.lo
) {
5381 if (expectedLen
!= NULL
)
5382 *expectedLen
= facet
->val
->value
.decimal
.lo
;
5383 return (XML_SCHEMAV_CVC_MINLENGTH_VALID
);
5385 } else if (facet
->type
== XML_SCHEMA_FACET_MAXLENGTH
) {
5386 if (actualLen
> facet
->val
->value
.decimal
.lo
) {
5387 if (expectedLen
!= NULL
)
5388 *expectedLen
= facet
->val
->value
.decimal
.lo
;
5389 return (XML_SCHEMAV_CVC_MAXLENGTH_VALID
);
5393 * NOTE: That we can pass NULL as xmlSchemaValPtr to
5394 * xmlSchemaValidateFacet, since the remaining facet types
5395 * are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
5397 return(xmlSchemaValidateFacet(NULL
, facet
, value
, NULL
));
5402 * xmlSchemaValidateLengthFacet:
5403 * @type: the built-in type
5404 * @facet: the facet to check
5405 * @value: the lexical repr. of the value to be validated
5406 * @val: the precomputed value
5407 * @ws: the whitespace type of the value
5408 * @length: the actual length of the value
5410 * Checka a value against a "length", "minLength" and "maxLength"
5411 * facet; sets @length to the computed length of @value.
5413 * Returns 0 if the value is valid, a positive error code
5414 * otherwise and -1 in case of an internal or API error.
5417 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet
,
5418 xmlSchemaValType valType
,
5419 const xmlChar
*value
,
5420 xmlSchemaValPtr val
,
5421 unsigned long *length
,
5422 xmlSchemaWhitespaceValueType ws
)
5424 unsigned int len
= 0;
5426 if ((length
== NULL
) || (facet
== NULL
))
5429 if ((facet
->type
!= XML_SCHEMA_FACET_LENGTH
) &&
5430 (facet
->type
!= XML_SCHEMA_FACET_MAXLENGTH
) &&
5431 (facet
->type
!= XML_SCHEMA_FACET_MINLENGTH
))
5435 * TODO: length, maxLength and minLength must be of type
5436 * nonNegativeInteger only. Check if decimal is used somehow.
5438 if ((facet
->val
== NULL
) ||
5439 ((facet
->val
->type
!= XML_SCHEMAS_DECIMAL
) &&
5440 (facet
->val
->type
!= XML_SCHEMAS_NNINTEGER
)) ||
5441 (facet
->val
->value
.decimal
.frac
!= 0)) {
5444 if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_HEXBINARY
))
5445 len
= val
->value
.hex
.total
;
5446 else if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_BASE64BINARY
))
5447 len
= val
->value
.base64
.total
;
5450 case XML_SCHEMAS_STRING
:
5451 case XML_SCHEMAS_NORMSTRING
:
5452 if (ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) {
5454 * This is to ensure API compatibility with the old
5455 * xmlSchemaValidateLengthFacet(). Anyway, this was and
5456 * is not the correct handling.
5457 * TODO: Get rid of this case somehow.
5459 if (valType
== XML_SCHEMAS_STRING
)
5460 len
= xmlUTF8Strlen(value
);
5462 len
= xmlSchemaNormLen(value
);
5463 } else if (value
!= NULL
) {
5464 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
5465 len
= xmlSchemaNormLen(value
);
5468 * Should be OK for "preserve" as well.
5470 len
= xmlUTF8Strlen(value
);
5473 case XML_SCHEMAS_IDREF
:
5474 case XML_SCHEMAS_TOKEN
:
5475 case XML_SCHEMAS_LANGUAGE
:
5476 case XML_SCHEMAS_NMTOKEN
:
5477 case XML_SCHEMAS_NAME
:
5478 case XML_SCHEMAS_NCNAME
:
5479 case XML_SCHEMAS_ID
:
5481 * FIXME: What exactly to do with anyURI?
5483 case XML_SCHEMAS_ANYURI
:
5485 len
= xmlSchemaNormLen(value
);
5487 case XML_SCHEMAS_QNAME
:
5488 case XML_SCHEMAS_NOTATION
:
5490 * For QName and NOTATION, those facets are
5491 * deprecated and should be ignored.
5498 *length
= (unsigned long) len
;
5500 * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
5502 if (facet
->type
== XML_SCHEMA_FACET_LENGTH
) {
5503 if (len
!= facet
->val
->value
.decimal
.lo
)
5504 return(XML_SCHEMAV_CVC_LENGTH_VALID
);
5505 } else if (facet
->type
== XML_SCHEMA_FACET_MINLENGTH
) {
5506 if (len
< facet
->val
->value
.decimal
.lo
)
5507 return(XML_SCHEMAV_CVC_MINLENGTH_VALID
);
5509 if (len
> facet
->val
->value
.decimal
.lo
)
5510 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID
);
5517 * xmlSchemaValidateLengthFacet:
5518 * @type: the built-in type
5519 * @facet: the facet to check
5520 * @value: the lexical repr. of the value to be validated
5521 * @val: the precomputed value
5522 * @length: the actual length of the value
5524 * Checka a value against a "length", "minLength" and "maxLength"
5525 * facet; sets @length to the computed length of @value.
5527 * Returns 0 if the value is valid, a positive error code
5528 * otherwise and -1 in case of an internal or API error.
5531 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type
,
5532 xmlSchemaFacetPtr facet
,
5533 const xmlChar
*value
,
5534 xmlSchemaValPtr val
,
5535 unsigned long *length
)
5539 return (xmlSchemaValidateLengthFacetInternal(facet
,
5540 type
->builtInType
, value
, val
, length
,
5541 XML_SCHEMA_WHITESPACE_UNKNOWN
));
5545 * xmlSchemaValidateLengthFacetWhtsp:
5546 * @facet: the facet to check
5547 * @valType: the built-in type
5548 * @value: the lexical repr. of the value to be validated
5549 * @val: the precomputed value
5550 * @ws: the whitespace type of the value
5551 * @length: the actual length of the value
5553 * Checka a value against a "length", "minLength" and "maxLength"
5554 * facet; sets @length to the computed length of @value.
5556 * Returns 0 if the value is valid, a positive error code
5557 * otherwise and -1 in case of an internal or API error.
5560 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet
,
5561 xmlSchemaValType valType
,
5562 const xmlChar
*value
,
5563 xmlSchemaValPtr val
,
5564 unsigned long *length
,
5565 xmlSchemaWhitespaceValueType ws
)
5567 return (xmlSchemaValidateLengthFacetInternal(facet
, valType
, value
, val
,
5572 * xmlSchemaValidateFacetInternal:
5573 * @facet: the facet to check
5574 * @fws: the whitespace type of the facet's value
5575 * @valType: the built-in type of the value
5576 * @value: the lexical repr of the value to validate
5577 * @val: the precomputed value
5578 * @ws: the whitespace type of the value
5580 * Check a value against a facet condition
5582 * Returns 0 if the element is schemas valid, a positive error code
5583 * number otherwise and -1 in case of internal or API error.
5586 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet
,
5587 xmlSchemaWhitespaceValueType fws
,
5588 xmlSchemaValType valType
,
5589 const xmlChar
*value
,
5590 xmlSchemaValPtr val
,
5591 xmlSchemaWhitespaceValueType ws
)
5598 switch (facet
->type
) {
5599 case XML_SCHEMA_FACET_PATTERN
:
5601 * NOTE that for patterns, the @value needs to be the normalized
5602 * value, *not* the lexical initial value or the canonical value.
5607 * If string-derived type, regexp must be tested on the value space of
5609 * See https://www.w3.org/TR/xmlschema-2/#rf-pattern
5613 ((val
->type
>= XML_SCHEMAS_STRING
&&
5614 val
->type
<= XML_SCHEMAS_NORMSTRING
) ||
5615 (val
->type
>= XML_SCHEMAS_TOKEN
&&
5616 val
->type
<= XML_SCHEMAS_ENTITIES
&&
5617 val
->type
!= XML_SCHEMAS_QNAME
))) {
5618 value
= val
->value
.str
;
5620 ret
= xmlRegexpExec(facet
->regexp
, value
);
5624 return(XML_SCHEMAV_CVC_PATTERN_VALID
);
5626 case XML_SCHEMA_FACET_MAXEXCLUSIVE
:
5627 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5632 return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID
);
5633 case XML_SCHEMA_FACET_MAXINCLUSIVE
:
5634 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5637 if ((ret
== -1) || (ret
== 0))
5639 return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID
);
5640 case XML_SCHEMA_FACET_MINEXCLUSIVE
:
5641 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5646 return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID
);
5647 case XML_SCHEMA_FACET_MININCLUSIVE
:
5648 ret
= xmlSchemaCompareValues(val
, facet
->val
);
5651 if ((ret
== 1) || (ret
== 0))
5653 return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID
);
5654 case XML_SCHEMA_FACET_WHITESPACE
:
5655 /* TODO whitespaces */
5657 * NOTE: Whitespace should be handled to normalize
5658 * the value to be validated against a the facets;
5659 * not to normalize the value in-between.
5662 case XML_SCHEMA_FACET_ENUMERATION
:
5663 if (ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) {
5665 * This is to ensure API compatibility with the old
5666 * xmlSchemaValidateFacet().
5667 * TODO: Get rid of this case.
5669 if ((facet
->value
!= NULL
) &&
5670 (xmlStrEqual(facet
->value
, value
)))
5673 ret
= xmlSchemaCompareValuesWhtspExt(facet
->val
->type
,
5674 facet
->val
, facet
->value
, fws
, valType
, val
,
5681 return(XML_SCHEMAV_CVC_ENUMERATION_VALID
);
5682 case XML_SCHEMA_FACET_LENGTH
:
5684 * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
5685 * then any {value} is facet-valid."
5687 if ((valType
== XML_SCHEMAS_QNAME
) ||
5688 (valType
== XML_SCHEMAS_NOTATION
))
5690 /* Falls through. */
5691 case XML_SCHEMA_FACET_MAXLENGTH
:
5692 case XML_SCHEMA_FACET_MINLENGTH
: {
5693 unsigned int len
= 0;
5695 if ((valType
== XML_SCHEMAS_QNAME
) ||
5696 (valType
== XML_SCHEMAS_NOTATION
))
5699 * TODO: length, maxLength and minLength must be of type
5700 * nonNegativeInteger only. Check if decimal is used somehow.
5702 if ((facet
->val
== NULL
) ||
5703 ((facet
->val
->type
!= XML_SCHEMAS_DECIMAL
) &&
5704 (facet
->val
->type
!= XML_SCHEMAS_NNINTEGER
)) ||
5705 (facet
->val
->value
.decimal
.frac
!= 0)) {
5708 if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_HEXBINARY
))
5709 len
= val
->value
.hex
.total
;
5710 else if ((val
!= NULL
) && (val
->type
== XML_SCHEMAS_BASE64BINARY
))
5711 len
= val
->value
.base64
.total
;
5714 case XML_SCHEMAS_STRING
:
5715 case XML_SCHEMAS_NORMSTRING
:
5716 if (ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) {
5718 * This is to ensure API compatibility with the old
5719 * xmlSchemaValidateFacet(). Anyway, this was and
5720 * is not the correct handling.
5721 * TODO: Get rid of this case somehow.
5723 if (valType
== XML_SCHEMAS_STRING
)
5724 len
= xmlUTF8Strlen(value
);
5726 len
= xmlSchemaNormLen(value
);
5727 } else if (value
!= NULL
) {
5728 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
5729 len
= xmlSchemaNormLen(value
);
5732 * Should be OK for "preserve" as well.
5734 len
= xmlUTF8Strlen(value
);
5737 case XML_SCHEMAS_IDREF
:
5738 case XML_SCHEMAS_TOKEN
:
5739 case XML_SCHEMAS_LANGUAGE
:
5740 case XML_SCHEMAS_NMTOKEN
:
5741 case XML_SCHEMAS_NAME
:
5742 case XML_SCHEMAS_NCNAME
:
5743 case XML_SCHEMAS_ID
:
5744 case XML_SCHEMAS_ANYURI
:
5746 len
= xmlSchemaNormLen(value
);
5752 if (facet
->type
== XML_SCHEMA_FACET_LENGTH
) {
5753 if (len
!= facet
->val
->value
.decimal
.lo
)
5754 return(XML_SCHEMAV_CVC_LENGTH_VALID
);
5755 } else if (facet
->type
== XML_SCHEMA_FACET_MINLENGTH
) {
5756 if (len
< facet
->val
->value
.decimal
.lo
)
5757 return(XML_SCHEMAV_CVC_MINLENGTH_VALID
);
5759 if (len
> facet
->val
->value
.decimal
.lo
)
5760 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID
);
5764 case XML_SCHEMA_FACET_TOTALDIGITS
:
5765 case XML_SCHEMA_FACET_FRACTIONDIGITS
:
5767 if ((facet
->val
== NULL
) ||
5768 ((facet
->val
->type
!= XML_SCHEMAS_PINTEGER
) &&
5769 (facet
->val
->type
!= XML_SCHEMAS_NNINTEGER
)) ||
5770 (facet
->val
->value
.decimal
.frac
!= 0)) {
5773 if ((val
== NULL
) ||
5774 ((val
->type
!= XML_SCHEMAS_DECIMAL
) &&
5775 (val
->type
!= XML_SCHEMAS_INTEGER
) &&
5776 (val
->type
!= XML_SCHEMAS_NPINTEGER
) &&
5777 (val
->type
!= XML_SCHEMAS_NINTEGER
) &&
5778 (val
->type
!= XML_SCHEMAS_NNINTEGER
) &&
5779 (val
->type
!= XML_SCHEMAS_PINTEGER
) &&
5780 (val
->type
!= XML_SCHEMAS_INT
) &&
5781 (val
->type
!= XML_SCHEMAS_UINT
) &&
5782 (val
->type
!= XML_SCHEMAS_LONG
) &&
5783 (val
->type
!= XML_SCHEMAS_ULONG
) &&
5784 (val
->type
!= XML_SCHEMAS_SHORT
) &&
5785 (val
->type
!= XML_SCHEMAS_USHORT
) &&
5786 (val
->type
!= XML_SCHEMAS_BYTE
) &&
5787 (val
->type
!= XML_SCHEMAS_UBYTE
))) {
5790 if (facet
->type
== XML_SCHEMA_FACET_TOTALDIGITS
) {
5791 if (val
->value
.decimal
.total
> facet
->val
->value
.decimal
.lo
)
5792 return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID
);
5794 } else if (facet
->type
== XML_SCHEMA_FACET_FRACTIONDIGITS
) {
5795 if (val
->value
.decimal
.frac
> facet
->val
->value
.decimal
.lo
)
5796 return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID
);
5807 * xmlSchemaValidateFacet:
5808 * @base: the base type
5809 * @facet: the facet to check
5810 * @value: the lexical repr of the value to validate
5811 * @val: the precomputed value
5813 * Check a value against a facet condition
5815 * Returns 0 if the element is schemas valid, a positive error code
5816 * number otherwise and -1 in case of internal or API error.
5819 xmlSchemaValidateFacet(xmlSchemaTypePtr base
,
5820 xmlSchemaFacetPtr facet
,
5821 const xmlChar
*value
,
5822 xmlSchemaValPtr val
)
5825 * This tries to ensure API compatibility regarding the old
5826 * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
5827 * xmlSchemaValidateFacetWhtsp().
5830 return(xmlSchemaValidateFacetInternal(facet
,
5831 XML_SCHEMA_WHITESPACE_UNKNOWN
, val
->type
, value
, val
,
5832 XML_SCHEMA_WHITESPACE_UNKNOWN
));
5833 else if (base
!= NULL
)
5834 return(xmlSchemaValidateFacetInternal(facet
,
5835 XML_SCHEMA_WHITESPACE_UNKNOWN
, base
->builtInType
, value
, val
,
5836 XML_SCHEMA_WHITESPACE_UNKNOWN
));
5841 * xmlSchemaValidateFacetWhtsp:
5842 * @facet: the facet to check
5843 * @fws: the whitespace type of the facet's value
5844 * @valType: the built-in type of the value
5845 * @value: the lexical (or normalized for pattern) repr of the value to validate
5846 * @val: the precomputed value
5847 * @ws: the whitespace type of the value
5849 * Check a value against a facet condition. This takes value normalization
5850 * according to the specified whitespace types into account.
5851 * Note that @value needs to be the *normalized* value if the facet
5852 * is of type "pattern".
5854 * Returns 0 if the element is schemas valid, a positive error code
5855 * number otherwise and -1 in case of internal or API error.
5858 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet
,
5859 xmlSchemaWhitespaceValueType fws
,
5860 xmlSchemaValType valType
,
5861 const xmlChar
*value
,
5862 xmlSchemaValPtr val
,
5863 xmlSchemaWhitespaceValueType ws
)
5865 return(xmlSchemaValidateFacetInternal(facet
, fws
, valType
,
5874 #define DBL_EPSILON 1E-9
5877 #define INTEGER_DIGITS DBL_DIG
5878 #define FRACTION_DIGITS (DBL_DIG + 1)
5879 #define EXPONENT_DIGITS (3 + 2)
5882 * xmlXPathFormatNumber:
5883 * @number: number to format
5884 * @buffer: output buffer
5885 * @buffersize: size of output buffer
5887 * Convert the number into a string representation.
5890 xmlSchemaFormatFloat(double number
, char buffer
[], int buffersize
)
5892 switch (xmlXPathIsInf(number
)) {
5894 if (buffersize
> (int)sizeof("INF"))
5895 snprintf(buffer
, buffersize
, "INF");
5898 if (buffersize
> (int)sizeof("-INF"))
5899 snprintf(buffer
, buffersize
, "-INF");
5902 if (xmlXPathIsNaN(number
)) {
5903 if (buffersize
> (int)sizeof("NaN"))
5904 snprintf(buffer
, buffersize
, "NaN");
5905 } else if (number
== 0) {
5906 snprintf(buffer
, buffersize
, "0.0E0");
5908 /* 3 is sign, decimal point, and terminating zero */
5909 char work
[DBL_DIG
+ EXPONENT_DIGITS
+ 3];
5910 int integer_place
, fraction_place
;
5912 char *after_fraction
;
5913 double absolute_value
;
5916 absolute_value
= fabs(number
);
5919 * Result is in work, and after_fraction points
5920 * just past the fractional part.
5921 * Use scientific notation
5923 integer_place
= DBL_DIG
+ EXPONENT_DIGITS
+ 1;
5924 fraction_place
= DBL_DIG
- 1;
5925 snprintf(work
, sizeof(work
),"%*.*e",
5926 integer_place
, fraction_place
, number
);
5927 after_fraction
= strchr(work
+ DBL_DIG
, 'e');
5928 /* Remove fractional trailing zeroes */
5929 ptr
= after_fraction
;
5930 while (*(--ptr
) == '0')
5934 while ((*ptr
++ = *after_fraction
++) != 0);
5936 /* Finally copy result back to caller */
5937 size
= strlen(work
) + 1;
5938 if (size
> buffersize
) {
5939 work
[buffersize
- 1] = 0;
5942 memmove(buffer
, work
, size
);
5950 * xmlSchemaGetCanonValue:
5951 * @val: the precomputed value
5952 * @retValue: the returned value
5954 * Get the canonical lexical representation of the value.
5955 * The caller has to FREE the returned retValue.
5957 * WARNING: Some value types are not supported yet, resulting
5958 * in a @retValue of "???".
5960 * TODO: XML Schema 1.0 does not define canonical representations
5961 * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay,
5962 * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1.
5965 * Returns 0 if the value could be built, 1 if the value type is
5966 * not supported yet and -1 in case of API errors.
5969 xmlSchemaGetCanonValue(xmlSchemaValPtr val
, const xmlChar
**retValue
)
5971 if ((retValue
== NULL
) || (val
== NULL
))
5974 switch (val
->type
) {
5975 case XML_SCHEMAS_STRING
:
5976 if (val
->value
.str
== NULL
)
5977 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
5980 BAD_CAST
xmlStrdup((const xmlChar
*) val
->value
.str
);
5982 case XML_SCHEMAS_NORMSTRING
:
5983 if (val
->value
.str
== NULL
)
5984 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
5986 *retValue
= xmlSchemaWhiteSpaceReplace(
5987 (const xmlChar
*) val
->value
.str
);
5988 if ((*retValue
) == NULL
)
5989 *retValue
= BAD_CAST
xmlStrdup(
5990 (const xmlChar
*) val
->value
.str
);
5993 case XML_SCHEMAS_TOKEN
:
5994 case XML_SCHEMAS_LANGUAGE
:
5995 case XML_SCHEMAS_NMTOKEN
:
5996 case XML_SCHEMAS_NAME
:
5997 case XML_SCHEMAS_NCNAME
:
5998 case XML_SCHEMAS_ID
:
5999 case XML_SCHEMAS_IDREF
:
6000 case XML_SCHEMAS_ENTITY
:
6001 case XML_SCHEMAS_NOTATION
: /* Unclear */
6002 case XML_SCHEMAS_ANYURI
: /* Unclear */
6003 if (val
->value
.str
== NULL
)
6006 BAD_CAST
xmlSchemaCollapseString(BAD_CAST val
->value
.str
);
6007 if (*retValue
== NULL
)
6009 BAD_CAST
xmlStrdup((const xmlChar
*) val
->value
.str
);
6011 case XML_SCHEMAS_QNAME
:
6012 /* TODO: Unclear in XML Schema 1.0. */
6013 if (val
->value
.qname
.uri
== NULL
) {
6014 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST val
->value
.qname
.name
);
6017 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"{");
6018 *retValue
= BAD_CAST
xmlStrcat((xmlChar
*) (*retValue
),
6019 BAD_CAST val
->value
.qname
.uri
);
6020 *retValue
= BAD_CAST
xmlStrcat((xmlChar
*) (*retValue
),
6022 *retValue
= BAD_CAST
xmlStrcat((xmlChar
*) (*retValue
),
6023 BAD_CAST val
->value
.qname
.uri
);
6026 case XML_SCHEMAS_DECIMAL
:
6028 * TODO: Lookout for a more simple implementation.
6030 if ((val
->value
.decimal
.total
== 1) &&
6031 (val
->value
.decimal
.lo
== 0)) {
6032 *retValue
= xmlStrdup(BAD_CAST
"0.0");
6034 xmlSchemaValDecimal dec
= val
->value
.decimal
;
6036 char *buf
= NULL
, *offs
;
6038 /* Add room for the decimal point as well. */
6039 bufsize
= dec
.total
+ 2;
6042 /* Add room for leading/trailing zero. */
6043 if ((dec
.frac
== 0) || (dec
.frac
== dec
.total
))
6045 buf
= xmlMalloc(bufsize
);
6051 if (dec
.frac
== dec
.total
) {
6056 snprintf(offs
, bufsize
- (offs
- buf
),
6057 "%lu%lu%lu", dec
.hi
, dec
.mi
, dec
.lo
);
6058 else if (dec
.mi
!= 0)
6059 snprintf(offs
, bufsize
- (offs
- buf
),
6060 "%lu%lu", dec
.mi
, dec
.lo
);
6062 snprintf(offs
, bufsize
- (offs
- buf
),
6065 if (dec
.frac
!= 0) {
6066 if (dec
.frac
!= dec
.total
) {
6067 int diff
= dec
.total
- dec
.frac
;
6069 * Insert the decimal point.
6071 memmove(offs
+ diff
+ 1, offs
+ diff
, dec
.frac
+1);
6076 * Insert missing zeroes behind the decimal point.
6078 while (*(offs
+ i
) != 0)
6080 if (i
< dec
.total
) {
6081 memmove(offs
+ (dec
.total
- i
), offs
, i
+1);
6082 memset(offs
, '0', dec
.total
- i
);
6087 * Append decimal point and zero.
6089 offs
= buf
+ bufsize
- 1;
6094 *retValue
= BAD_CAST buf
;
6097 case XML_SCHEMAS_INTEGER
:
6098 case XML_SCHEMAS_PINTEGER
:
6099 case XML_SCHEMAS_NPINTEGER
:
6100 case XML_SCHEMAS_NINTEGER
:
6101 case XML_SCHEMAS_NNINTEGER
:
6102 case XML_SCHEMAS_LONG
:
6103 case XML_SCHEMAS_BYTE
:
6104 case XML_SCHEMAS_SHORT
:
6105 case XML_SCHEMAS_INT
:
6106 case XML_SCHEMAS_UINT
:
6107 case XML_SCHEMAS_ULONG
:
6108 case XML_SCHEMAS_USHORT
:
6109 case XML_SCHEMAS_UBYTE
:
6110 if ((val
->value
.decimal
.total
== 1) &&
6111 (val
->value
.decimal
.lo
== 0))
6112 *retValue
= xmlStrdup(BAD_CAST
"0");
6114 xmlSchemaValDecimal dec
= val
->value
.decimal
;
6115 int bufsize
= dec
.total
+ 1;
6117 /* Add room for the decimal point as well. */
6120 *retValue
= xmlMalloc(bufsize
);
6121 if (*retValue
== NULL
)
6125 snprintf((char *) *retValue
, bufsize
,
6126 "-%lu%lu%lu", dec
.hi
, dec
.mi
, dec
.lo
);
6128 snprintf((char *) *retValue
, bufsize
,
6129 "%lu%lu%lu", dec
.hi
, dec
.mi
, dec
.lo
);
6130 } else if (dec
.mi
!= 0) {
6132 snprintf((char *) *retValue
, bufsize
,
6133 "-%lu%lu", dec
.mi
, dec
.lo
);
6135 snprintf((char *) *retValue
, bufsize
,
6136 "%lu%lu", dec
.mi
, dec
.lo
);
6139 snprintf((char *) *retValue
, bufsize
, "-%lu", dec
.lo
);
6141 snprintf((char *) *retValue
, bufsize
, "%lu", dec
.lo
);
6145 case XML_SCHEMAS_BOOLEAN
:
6147 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"true");
6149 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"false");
6151 case XML_SCHEMAS_DURATION
: {
6154 unsigned long mon
, day
, hour
= 0, min
= 0;
6155 double sec
= 0, left
;
6157 /* TODO: Unclear in XML Schema 1.0 */
6159 * TODO: This results in a normalized output of the value
6160 * - which is NOT conformant to the spec -
6161 * since the exact values of each property are not
6162 * recoverable. Think about extending the structure to
6163 * provide a field for every property.
6165 year
= (unsigned long) FQUOTIENT(labs(val
->value
.dur
.mon
), 12);
6166 mon
= labs(val
->value
.dur
.mon
) - 12 * year
;
6168 day
= (unsigned long) FQUOTIENT(fabs(val
->value
.dur
.sec
), 86400);
6169 left
= fabs(val
->value
.dur
.sec
) - day
* 86400;
6171 hour
= (unsigned long) FQUOTIENT(left
, 3600);
6172 left
= left
- (hour
* 3600);
6174 min
= (unsigned long) FQUOTIENT(left
, 60);
6175 sec
= left
- (min
* 60);
6178 if ((val
->value
.dur
.mon
< 0) || (val
->value
.dur
.sec
< 0))
6179 snprintf(buf
, 100, "P%luY%luM%luDT%luH%luM%.14gS",
6180 year
, mon
, day
, hour
, min
, sec
);
6182 snprintf(buf
, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
6183 year
, mon
, day
, hour
, min
, sec
);
6184 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6187 case XML_SCHEMAS_GYEAR
: {
6189 /* TODO: Unclear in XML Schema 1.0 */
6190 /* TODO: What to do with the timezone? */
6191 snprintf(buf
, 30, "%04ld", val
->value
.date
.year
);
6192 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6195 case XML_SCHEMAS_GMONTH
: {
6196 /* TODO: Unclear in XML Schema 1.0 */
6197 /* TODO: What to do with the timezone? */
6198 *retValue
= xmlMalloc(6);
6199 if (*retValue
== NULL
)
6201 snprintf((char *) *retValue
, 6, "--%02u",
6202 val
->value
.date
.mon
);
6205 case XML_SCHEMAS_GDAY
: {
6206 /* TODO: Unclear in XML Schema 1.0 */
6207 /* TODO: What to do with the timezone? */
6208 *retValue
= xmlMalloc(6);
6209 if (*retValue
== NULL
)
6211 snprintf((char *) *retValue
, 6, "---%02u",
6212 val
->value
.date
.day
);
6215 case XML_SCHEMAS_GMONTHDAY
: {
6216 /* TODO: Unclear in XML Schema 1.0 */
6217 /* TODO: What to do with the timezone? */
6218 *retValue
= xmlMalloc(8);
6219 if (*retValue
== NULL
)
6221 snprintf((char *) *retValue
, 8, "--%02u-%02u",
6222 val
->value
.date
.mon
, val
->value
.date
.day
);
6225 case XML_SCHEMAS_GYEARMONTH
: {
6227 /* TODO: Unclear in XML Schema 1.0 */
6228 /* TODO: What to do with the timezone? */
6229 if (val
->value
.date
.year
< 0)
6230 snprintf(buf
, 35, "-%04ld-%02u",
6231 labs(val
->value
.date
.year
),
6232 val
->value
.date
.mon
);
6234 snprintf(buf
, 35, "%04ld-%02u",
6235 val
->value
.date
.year
, val
->value
.date
.mon
);
6236 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6239 case XML_SCHEMAS_TIME
:
6243 if (val
->value
.date
.tz_flag
) {
6244 xmlSchemaValPtr norm
;
6246 norm
= xmlSchemaDateNormalize(val
, 0);
6250 * TODO: Check if "%.14g" is portable.
6253 "%02u:%02u:%02.14gZ",
6254 norm
->value
.date
.hour
,
6255 norm
->value
.date
.min
,
6256 norm
->value
.date
.sec
);
6257 xmlSchemaFreeValue(norm
);
6260 "%02u:%02u:%02.14g",
6261 val
->value
.date
.hour
,
6262 val
->value
.date
.min
,
6263 val
->value
.date
.sec
);
6265 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6268 case XML_SCHEMAS_DATE
:
6272 if (val
->value
.date
.tz_flag
) {
6273 xmlSchemaValPtr norm
;
6275 norm
= xmlSchemaDateNormalize(val
, 0);
6279 * TODO: Append the canonical value of the
6280 * recoverable timezone and not "Z".
6284 norm
->value
.date
.year
, norm
->value
.date
.mon
,
6285 norm
->value
.date
.day
);
6286 xmlSchemaFreeValue(norm
);
6290 val
->value
.date
.year
, val
->value
.date
.mon
,
6291 val
->value
.date
.day
);
6293 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6296 case XML_SCHEMAS_DATETIME
:
6300 if (val
->value
.date
.tz_flag
) {
6301 xmlSchemaValPtr norm
;
6303 norm
= xmlSchemaDateNormalize(val
, 0);
6307 * TODO: Check if "%.14g" is portable.
6310 "%04ld-%02u-%02uT%02u:%02u:%02.14gZ",
6311 norm
->value
.date
.year
, norm
->value
.date
.mon
,
6312 norm
->value
.date
.day
, norm
->value
.date
.hour
,
6313 norm
->value
.date
.min
, norm
->value
.date
.sec
);
6314 xmlSchemaFreeValue(norm
);
6317 "%04ld-%02u-%02uT%02u:%02u:%02.14g",
6318 val
->value
.date
.year
, val
->value
.date
.mon
,
6319 val
->value
.date
.day
, val
->value
.date
.hour
,
6320 val
->value
.date
.min
, val
->value
.date
.sec
);
6322 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6325 case XML_SCHEMAS_HEXBINARY
:
6326 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST val
->value
.hex
.str
);
6328 case XML_SCHEMAS_BASE64BINARY
:
6330 * TODO: Is the following spec piece implemented?:
6331 * SPEC: "Note: For some values the canonical form defined
6332 * above does not conform to [RFC 2045], which requires breaking
6333 * with linefeeds at appropriate intervals."
6335 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST val
->value
.base64
.str
);
6337 case XML_SCHEMAS_FLOAT
: {
6340 * |m| < 16777216, -149 <= e <= 104.
6341 * TODO: Handle, NaN, INF, -INF. The format is not
6342 * yet conformant. The c type float does not cover
6345 snprintf(buf
, 30, "%01.14e", val
->value
.f
);
6346 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6349 case XML_SCHEMAS_DOUBLE
: {
6351 /* |m| < 9007199254740992, -1075 <= e <= 970 */
6353 * TODO: Handle, NaN, INF, -INF. The format is not
6354 * yet conformant. The c type float does not cover
6357 snprintf(buf
, 40, "%01.14e", val
->value
.d
);
6358 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST buf
);
6362 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"???");
6365 if (*retValue
== NULL
)
6371 * xmlSchemaGetCanonValueWhtsp:
6372 * @val: the precomputed value
6373 * @retValue: the returned value
6374 * @ws: the whitespace type of the value
6376 * Get the canonical representation of the value.
6377 * The caller has to free the returned @retValue.
6379 * Returns 0 if the value could be built, 1 if the value type is
6380 * not supported yet and -1 in case of API errors.
6383 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val
,
6384 const xmlChar
**retValue
,
6385 xmlSchemaWhitespaceValueType ws
)
6387 if ((retValue
== NULL
) || (val
== NULL
))
6389 if ((ws
== XML_SCHEMA_WHITESPACE_UNKNOWN
) ||
6390 (ws
> XML_SCHEMA_WHITESPACE_COLLAPSE
))
6394 switch (val
->type
) {
6395 case XML_SCHEMAS_STRING
:
6396 if (val
->value
.str
== NULL
)
6397 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
6398 else if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
6399 *retValue
= xmlSchemaCollapseString(val
->value
.str
);
6400 else if (ws
== XML_SCHEMA_WHITESPACE_REPLACE
)
6401 *retValue
= xmlSchemaWhiteSpaceReplace(val
->value
.str
);
6402 if ((*retValue
) == NULL
)
6403 *retValue
= BAD_CAST
xmlStrdup(val
->value
.str
);
6405 case XML_SCHEMAS_NORMSTRING
:
6406 if (val
->value
.str
== NULL
)
6407 *retValue
= BAD_CAST
xmlStrdup(BAD_CAST
"");
6409 if (ws
== XML_SCHEMA_WHITESPACE_COLLAPSE
)
6410 *retValue
= xmlSchemaCollapseString(val
->value
.str
);
6412 *retValue
= xmlSchemaWhiteSpaceReplace(val
->value
.str
);
6413 if ((*retValue
) == NULL
)
6414 *retValue
= BAD_CAST
xmlStrdup(val
->value
.str
);
6418 return (xmlSchemaGetCanonValue(val
, retValue
));
6424 * xmlSchemaGetValType:
6425 * @val: a schemas value
6427 * Accessor for the type of a value
6429 * Returns the xmlSchemaValType of the value
6432 xmlSchemaGetValType(xmlSchemaValPtr val
)
6435 return(XML_SCHEMAS_UNKNOWN
);
6439 #endif /* LIBXML_SCHEMAS_ENABLED */