mscms: Fix double free on error path in EnumColorProfilesA (scan-build).
[wine.git] / libs / xml2 / xmlschemastypes.c
blob60268e2d8eb9892c711935a7d57681b76793e315
1 /*
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>
8 */
10 /* To avoid EBCDIC trouble when parsing on zOS */
11 #if defined(__MVS__)
12 #pragma convert("ISO8859-1")
13 #endif
15 #define IN_LIBXML
16 #include "libxml.h"
18 #ifdef LIBXML_SCHEMAS_ENABLED
20 #include <string.h>
21 #include <math.h>
22 #include <float.h>
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"
38 #define DEBUG
40 #ifndef LIBXML_XPATH_ENABLED
41 extern double xmlXPathNAN;
42 extern double xmlXPathPINF;
43 extern double xmlXPathNINF;
44 #endif
46 #define TODO \
47 xmlGenericError(xmlGenericErrorContext, \
48 "Unimplemented block at %s:%d\n", \
49 __FILE__, __LINE__);
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)) || \
55 ((c) == 0xd))
57 #define IS_WSP_SPACE_CH(c) ((c) == 0x20)
59 #define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c)
61 /* Date value */
62 typedef struct _xmlSchemaValDate xmlSchemaValDate;
63 typedef xmlSchemaValDate *xmlSchemaValDatePtr;
64 struct _xmlSchemaValDate {
65 long year;
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 */
70 double sec;
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 */
76 /* Duration value */
77 typedef struct _xmlSchemaValDuration xmlSchemaValDuration;
78 typedef xmlSchemaValDuration *xmlSchemaValDurationPtr;
79 struct _xmlSchemaValDuration {
80 long mon; /* mon stores years also */
81 long day;
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 */
89 unsigned long lo;
90 unsigned long mi;
91 unsigned long hi;
92 unsigned int extra;
93 unsigned int sign:1;
94 unsigned int frac:7;
95 unsigned int total:8;
98 typedef struct _xmlSchemaValQName xmlSchemaValQName;
99 typedef xmlSchemaValQName *xmlSchemaValQNamePtr;
100 struct _xmlSchemaValQName {
101 xmlChar *name;
102 xmlChar *uri;
105 typedef struct _xmlSchemaValHex xmlSchemaValHex;
106 typedef xmlSchemaValHex *xmlSchemaValHexPtr;
107 struct _xmlSchemaValHex {
108 xmlChar *str;
109 unsigned int total;
112 typedef struct _xmlSchemaValBase64 xmlSchemaValBase64;
113 typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr;
114 struct _xmlSchemaValBase64 {
115 xmlChar *str;
116 unsigned int total;
119 struct _xmlSchemaVal {
120 xmlSchemaValType type;
121 struct _xmlSchemaVal *next;
122 union {
123 xmlSchemaValDecimal decimal;
124 xmlSchemaValDate date;
125 xmlSchemaValDuration dur;
126 xmlSchemaValQName qname;
127 xmlSchemaValHex hex;
128 xmlSchemaValBase64 base64;
129 float f;
130 double d;
131 int b;
132 xmlChar *str;
133 } value;
136 static int xmlSchemaTypesInitialized = 0;
137 static xmlHashTablePtr xmlSchemaTypesBank = NULL;
140 * Basic types
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;
163 * Derived types
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
204 static void
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 ************************************************************************/
217 * xmlSchemaNewValue:
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));
229 if (value == NULL) {
230 return(NULL);
232 memset(value, 0, sizeof(xmlSchemaVal));
233 value->type = type;
234 return(value);
237 static xmlSchemaFacetPtr
238 xmlSchemaNewMinLengthFacet(int value)
240 xmlSchemaFacetPtr ret;
242 ret = xmlSchemaNewFacet();
243 if (ret == NULL) {
244 return(NULL);
246 ret->type = XML_SCHEMA_FACET_MINLENGTH;
247 ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER);
248 if (ret->val == NULL) {
249 xmlFree(ret);
250 return(NULL);
252 ret->val->value.decimal.lo = value;
253 return (ret);
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));
269 if (ret == NULL) {
270 xmlSchemaTypeErrMemory(NULL, "could not initialize basic types");
271 return(NULL);
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;
280 * Primitive types.
282 switch (type) {
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;
303 break;
304 default:
305 break;
308 * Set variety.
310 switch (type) {
311 case XML_SCHEMAS_ANYTYPE:
312 case XML_SCHEMAS_ANYSIMPLETYPE:
313 break;
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;
320 break;
321 default:
322 ret->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
323 break;
325 xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
326 XML_SCHEMAS_NAMESPACE_NAME, ret);
327 ret->builtInType = type;
328 return(ret);
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;
355 int minOccurs;
356 int maxOccurs;
357 xmlNodePtr node;
360 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
361 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
362 struct _xmlSchemaModelGroup {
363 xmlSchemaTypeType type;
364 xmlSchemaAnnotPtr annot;
365 xmlSchemaTreeItemPtr next;
366 xmlSchemaTreeItemPtr children;
367 xmlNodePtr node;
370 static xmlSchemaParticlePtr
371 xmlSchemaAddParticle(void)
373 xmlSchemaParticlePtr ret = NULL;
375 ret = (xmlSchemaParticlePtr)
376 xmlMalloc(sizeof(xmlSchemaParticle));
377 if (ret == NULL) {
378 xmlSchemaTypeErrMemory(NULL, "allocating particle component");
379 return (NULL);
381 memset(ret, 0, sizeof(xmlSchemaParticle));
382 ret->type = XML_SCHEMA_TYPE_PARTICLE;
383 ret->minOccurs = 1;
384 ret->maxOccurs = 1;
385 return (ret);
388 static void
389 xmlSchemaFreeTypeEntry(void *type, const xmlChar *name ATTRIBUTE_UNUSED) {
390 xmlSchemaFreeType((xmlSchemaTypePtr) type);
394 * xmlSchemaCleanupTypesInternal:
396 * Cleanup the default XML Schemas type library
398 static void
399 xmlSchemaCleanupTypesInternal(void) {
400 xmlSchemaParticlePtr particle;
403 * Free xs:anyType.
405 if (xmlSchemaTypeAnyTypeDef != NULL) {
406 /* Attribute wildcard. */
407 xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard);
408 /* Content type. */
409 particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes;
410 /* Wildcard. */
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)
437 return (0);
438 xmlSchemaTypesBank = xmlHashCreate(40);
439 if (xmlSchemaTypesBank == NULL) {
440 xmlSchemaTypeErrMemory(NULL, NULL);
441 goto error;
445 * 3.4.7 Built-in Complex Type Definition
447 xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
448 XML_SCHEMAS_ANYTYPE,
449 NULL);
450 if (xmlSchemaTypeAnyTypeDef == NULL)
451 goto error;
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)
465 goto error;
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");
472 goto error;
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)
480 goto error;
481 particle->minOccurs = 0;
482 particle->maxOccurs = UNBOUNDED;
483 sequence->children = (xmlSchemaTreeItemPtr) particle;
484 /* The wildcard */
485 wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
486 if (wild == NULL) {
487 xmlSchemaTypeErrMemory(NULL, "allocating wildcard component");
488 goto error;
490 memset(wild, 0, sizeof(xmlSchemaWildcard));
491 wild->type = XML_SCHEMA_TYPE_ANY;
492 wild->any = 1;
493 wild->processContents = XML_SCHEMAS_ANY_LAX;
494 particle->children = (xmlSchemaTreeItemPtr) wild;
496 * Create the attribute wildcard.
498 wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
499 if (wild == NULL) {
500 xmlSchemaTypeErrMemory(NULL, "could not create an attribute "
501 "wildcard on anyType");
502 goto error;
504 memset(wild, 0, sizeof(xmlSchemaWildcard));
505 wild->any = 1;
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)
513 goto error;
515 * primitive datatypes
517 xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
518 XML_SCHEMAS_STRING,
519 xmlSchemaTypeAnySimpleTypeDef);
520 if (xmlSchemaTypeStringDef == NULL)
521 goto error;
522 xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
523 XML_SCHEMAS_DECIMAL,
524 xmlSchemaTypeAnySimpleTypeDef);
525 if (xmlSchemaTypeDecimalDef == NULL)
526 goto error;
527 xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
528 XML_SCHEMAS_DATE,
529 xmlSchemaTypeAnySimpleTypeDef);
530 if (xmlSchemaTypeDateDef == NULL)
531 goto error;
532 xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
533 XML_SCHEMAS_DATETIME,
534 xmlSchemaTypeAnySimpleTypeDef);
535 if (xmlSchemaTypeDatetimeDef == NULL)
536 goto error;
537 xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
538 XML_SCHEMAS_TIME,
539 xmlSchemaTypeAnySimpleTypeDef);
540 if (xmlSchemaTypeTimeDef == NULL)
541 goto error;
542 xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
543 XML_SCHEMAS_GYEAR,
544 xmlSchemaTypeAnySimpleTypeDef);
545 if (xmlSchemaTypeGYearDef == NULL)
546 goto error;
547 xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
548 XML_SCHEMAS_GYEARMONTH,
549 xmlSchemaTypeAnySimpleTypeDef);
550 if (xmlSchemaTypeGYearMonthDef == NULL)
551 goto error;
552 xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
553 XML_SCHEMAS_GMONTH,
554 xmlSchemaTypeAnySimpleTypeDef);
555 if (xmlSchemaTypeGMonthDef == NULL)
556 goto error;
557 xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
558 XML_SCHEMAS_GMONTHDAY,
559 xmlSchemaTypeAnySimpleTypeDef);
560 if (xmlSchemaTypeGMonthDayDef == NULL)
561 goto error;
562 xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
563 XML_SCHEMAS_GDAY,
564 xmlSchemaTypeAnySimpleTypeDef);
565 if (xmlSchemaTypeGDayDef == NULL)
566 goto error;
567 xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
568 XML_SCHEMAS_DURATION,
569 xmlSchemaTypeAnySimpleTypeDef);
570 if (xmlSchemaTypeDurationDef == NULL)
571 goto error;
572 xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
573 XML_SCHEMAS_FLOAT,
574 xmlSchemaTypeAnySimpleTypeDef);
575 if (xmlSchemaTypeFloatDef == NULL)
576 goto error;
577 xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
578 XML_SCHEMAS_DOUBLE,
579 xmlSchemaTypeAnySimpleTypeDef);
580 if (xmlSchemaTypeDoubleDef == NULL)
581 goto error;
582 xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
583 XML_SCHEMAS_BOOLEAN,
584 xmlSchemaTypeAnySimpleTypeDef);
585 if (xmlSchemaTypeBooleanDef == NULL)
586 goto error;
587 xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
588 XML_SCHEMAS_ANYURI,
589 xmlSchemaTypeAnySimpleTypeDef);
590 if (xmlSchemaTypeAnyURIDef == NULL)
591 goto error;
592 xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
593 XML_SCHEMAS_HEXBINARY,
594 xmlSchemaTypeAnySimpleTypeDef);
595 if (xmlSchemaTypeHexBinaryDef == NULL)
596 goto error;
597 xmlSchemaTypeBase64BinaryDef
598 = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY,
599 xmlSchemaTypeAnySimpleTypeDef);
600 if (xmlSchemaTypeBase64BinaryDef == NULL)
601 goto error;
602 xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
603 XML_SCHEMAS_NOTATION,
604 xmlSchemaTypeAnySimpleTypeDef);
605 if (xmlSchemaTypeNotationDef == NULL)
606 goto error;
607 xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
608 XML_SCHEMAS_QNAME,
609 xmlSchemaTypeAnySimpleTypeDef);
610 if (xmlSchemaTypeQNameDef == NULL)
611 goto error;
614 * derived datatypes
616 xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
617 XML_SCHEMAS_INTEGER,
618 xmlSchemaTypeDecimalDef);
619 if (xmlSchemaTypeIntegerDef == NULL)
620 goto error;
621 xmlSchemaTypeNonPositiveIntegerDef =
622 xmlSchemaInitBasicType("nonPositiveInteger",
623 XML_SCHEMAS_NPINTEGER,
624 xmlSchemaTypeIntegerDef);
625 if (xmlSchemaTypeNonPositiveIntegerDef == NULL)
626 goto error;
627 xmlSchemaTypeNegativeIntegerDef =
628 xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER,
629 xmlSchemaTypeNonPositiveIntegerDef);
630 if (xmlSchemaTypeNegativeIntegerDef == NULL)
631 goto error;
632 xmlSchemaTypeLongDef =
633 xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG,
634 xmlSchemaTypeIntegerDef);
635 if (xmlSchemaTypeLongDef == NULL)
636 goto error;
637 xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT,
638 xmlSchemaTypeLongDef);
639 if (xmlSchemaTypeIntDef == NULL)
640 goto error;
641 xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
642 XML_SCHEMAS_SHORT,
643 xmlSchemaTypeIntDef);
644 if (xmlSchemaTypeShortDef == NULL)
645 goto error;
646 xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
647 XML_SCHEMAS_BYTE,
648 xmlSchemaTypeShortDef);
649 if (xmlSchemaTypeByteDef == NULL)
650 goto error;
651 xmlSchemaTypeNonNegativeIntegerDef =
652 xmlSchemaInitBasicType("nonNegativeInteger",
653 XML_SCHEMAS_NNINTEGER,
654 xmlSchemaTypeIntegerDef);
655 if (xmlSchemaTypeNonNegativeIntegerDef == NULL)
656 goto error;
657 xmlSchemaTypeUnsignedLongDef =
658 xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG,
659 xmlSchemaTypeNonNegativeIntegerDef);
660 if (xmlSchemaTypeUnsignedLongDef == NULL)
661 goto error;
662 xmlSchemaTypeUnsignedIntDef =
663 xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT,
664 xmlSchemaTypeUnsignedLongDef);
665 if (xmlSchemaTypeUnsignedIntDef == NULL)
666 goto error;
667 xmlSchemaTypeUnsignedShortDef =
668 xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT,
669 xmlSchemaTypeUnsignedIntDef);
670 if (xmlSchemaTypeUnsignedShortDef == NULL)
671 goto error;
672 xmlSchemaTypeUnsignedByteDef =
673 xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE,
674 xmlSchemaTypeUnsignedShortDef);
675 if (xmlSchemaTypeUnsignedByteDef == NULL)
676 goto error;
677 xmlSchemaTypePositiveIntegerDef =
678 xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER,
679 xmlSchemaTypeNonNegativeIntegerDef);
680 if (xmlSchemaTypePositiveIntegerDef == NULL)
681 goto error;
682 xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
683 XML_SCHEMAS_NORMSTRING,
684 xmlSchemaTypeStringDef);
685 if (xmlSchemaTypeNormStringDef == NULL)
686 goto error;
687 xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
688 XML_SCHEMAS_TOKEN,
689 xmlSchemaTypeNormStringDef);
690 if (xmlSchemaTypeTokenDef == NULL)
691 goto error;
692 xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
693 XML_SCHEMAS_LANGUAGE,
694 xmlSchemaTypeTokenDef);
695 if (xmlSchemaTypeLanguageDef == NULL)
696 goto error;
697 xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
698 XML_SCHEMAS_NAME,
699 xmlSchemaTypeTokenDef);
700 if (xmlSchemaTypeNameDef == NULL)
701 goto error;
702 xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
703 XML_SCHEMAS_NMTOKEN,
704 xmlSchemaTypeTokenDef);
705 if (xmlSchemaTypeNmtokenDef == NULL)
706 goto error;
707 xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
708 XML_SCHEMAS_NCNAME,
709 xmlSchemaTypeNameDef);
710 if (xmlSchemaTypeNCNameDef == NULL)
711 goto error;
712 xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID,
713 xmlSchemaTypeNCNameDef);
714 if (xmlSchemaTypeIdDef == NULL)
715 goto error;
716 xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
717 XML_SCHEMAS_IDREF,
718 xmlSchemaTypeNCNameDef);
719 if (xmlSchemaTypeIdrefDef == NULL)
720 goto error;
721 xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
722 XML_SCHEMAS_ENTITY,
723 xmlSchemaTypeNCNameDef);
724 if (xmlSchemaTypeEntityDef == NULL)
725 goto error;
727 * Derived list types.
729 /* ENTITIES */
730 xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
731 XML_SCHEMAS_ENTITIES,
732 xmlSchemaTypeAnySimpleTypeDef);
733 if (xmlSchemaTypeEntitiesDef == NULL)
734 goto error;
735 xmlSchemaTypeEntitiesDef->subtypes = xmlSchemaTypeEntityDef;
736 /* IDREFS */
737 xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
738 XML_SCHEMAS_IDREFS,
739 xmlSchemaTypeAnySimpleTypeDef);
740 if (xmlSchemaTypeIdrefsDef == NULL)
741 goto error;
742 xmlSchemaTypeIdrefsDef->subtypes = xmlSchemaTypeIdrefDef;
744 /* NMTOKENS */
745 xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
746 XML_SCHEMAS_NMTOKENS,
747 xmlSchemaTypeAnySimpleTypeDef);
748 if (xmlSchemaTypeNmtokensDef == NULL)
749 goto error;
750 xmlSchemaTypeNmtokensDef->subtypes = xmlSchemaTypeNmtokenDef;
752 xmlSchemaTypesInitialized = 1;
753 return (0);
755 error:
756 xmlSchemaCleanupTypesInternal();
757 return (-1);
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
770 void
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)
792 if (type == NULL)
793 return (-1);
794 if (type->type != XML_SCHEMA_TYPE_BASIC)
795 return (-1);
796 switch (type->builtInType) {
797 case XML_SCHEMAS_BOOLEAN:
798 if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
799 (facetType == XML_SCHEMA_FACET_WHITESPACE))
800 return (1);
801 else
802 return (0);
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))
815 return (1);
816 else
817 return (0);
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))
828 return (1);
829 else
830 return (0);
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))
849 return (1);
850 else
851 return (0);
852 default:
853 break;
855 return (0);
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.
867 xmlSchemaTypePtr
868 xmlSchemaGetBuiltInType(xmlSchemaValType type)
870 if ((xmlSchemaTypesInitialized == 0) &&
871 (xmlSchemaInitTypes() < 0))
872 return (NULL);
873 switch (type) {
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);
921 case XML_SCHEMAS_ID:
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);
967 default:
968 return (NULL);
973 * xmlSchemaValueAppend:
974 * @prev: the value
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))
985 return (-1);
986 prev->next = cur;
987 return (0);
991 * xmlSchemaValueGetNext:
992 * @cur: the value
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
997 * API errors.
999 xmlSchemaValPtr
1000 xmlSchemaValueGetNext(xmlSchemaValPtr cur) {
1002 if (cur == NULL)
1003 return (NULL);
1004 return (cur->next);
1008 * xmlSchemaValueGetAsString:
1009 * @val: the value
1011 * Accessor for the string value of a computed value.
1013 * Returns the string value or NULL if there was none, or on
1014 * API errors.
1016 const xmlChar *
1017 xmlSchemaValueGetAsString(xmlSchemaValPtr val)
1019 if (val == NULL)
1020 return (NULL);
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);
1035 default:
1036 break;
1038 return (NULL);
1042 * xmlSchemaValueGetAsBoolean:
1043 * @val: the value
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))
1053 return (0);
1054 return (val->value.b);
1058 * xmlSchemaNewStringValue:
1059 * @type: the value type
1060 * @value: the value
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
1070 xmlSchemaValPtr
1071 xmlSchemaNewStringValue(xmlSchemaValType type,
1072 const xmlChar *value)
1074 xmlSchemaValPtr val;
1076 if (type != XML_SCHEMAS_STRING)
1077 return(NULL);
1078 val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
1079 if (val == NULL) {
1080 return(NULL);
1082 memset(val, 0, sizeof(xmlSchemaVal));
1083 val->type = type;
1084 val->value.str = (xmlChar *) value;
1085 return(val);
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
1098 xmlSchemaValPtr
1099 xmlSchemaNewNOTATIONValue(const xmlChar *name,
1100 const xmlChar *ns)
1102 xmlSchemaValPtr val;
1104 val = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
1105 if (val == NULL)
1106 return (NULL);
1108 val->value.qname.name = (xmlChar *)name;
1109 if (ns != NULL)
1110 val->value.qname.uri = (xmlChar *)ns;
1111 return(val);
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.
1124 xmlSchemaValPtr
1125 xmlSchemaNewQNameValue(const xmlChar *namespaceName,
1126 const xmlChar *localName)
1128 xmlSchemaValPtr val;
1130 val = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
1131 if (val == NULL)
1132 return (NULL);
1134 val->value.qname.name = (xmlChar *) localName;
1135 val->value.qname.uri = (xmlChar *) namespaceName;
1136 return(val);
1140 * xmlSchemaFreeValue:
1141 * @value: the value to free
1143 * Cleanup the default XML Schemas type library
1145 void
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);
1168 break;
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);
1175 break;
1176 case XML_SCHEMAS_HEXBINARY:
1177 if (value->value.hex.str != NULL)
1178 xmlFree(value->value.hex.str);
1179 break;
1180 case XML_SCHEMAS_BASE64BINARY:
1181 if (value->value.base64.str != NULL)
1182 xmlFree(value->value.base64.str);
1183 break;
1184 default:
1185 break;
1187 prev = value;
1188 value = value->next;
1189 xmlFree(prev);
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
1202 xmlSchemaTypePtr
1203 xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
1204 if ((xmlSchemaTypesInitialized == 0) &&
1205 (xmlSchemaInitTypes() < 0))
1206 return (NULL);
1207 if (name == NULL)
1208 return(NULL);
1209 return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
1213 * xmlSchemaGetBuiltInListSimpleTypeItemType:
1214 * @type: the built-in simple type.
1216 * Lookup function
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.
1221 xmlSchemaTypePtr
1222 xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type)
1224 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_BASIC))
1225 return (NULL);
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);
1233 default:
1234 return (NULL);
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)) && \
1280 VALID_TZO(dt->tzo))
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) \
1298 ((IS_LEAP(year) ? \
1299 dayInLeapYearByMonth[month - 1] : \
1300 dayInYearByMonth[month - 1]) + day)
1302 #ifdef DEBUG
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); \
1313 else \
1314 xmlGenericError(xmlGenericErrorContext, "Z\n"); \
1315 else \
1316 xmlGenericError(xmlGenericErrorContext,"\n")
1317 #else
1318 #define DEBUG_DATE(dt)
1319 #endif
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
1329 * the year.
1331 * Returns 0 or the error code
1333 static int
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 != '+'))
1340 return -1;
1342 if (*cur == '-') {
1343 isneg = 1;
1344 cur++;
1347 firstChar = cur;
1349 while ((*cur >= '0') && (*cur <= '9')) {
1350 int digit = *cur - '0';
1352 if (dt->year > LONG_MAX / 10)
1353 return 2;
1354 dt->year *= 10;
1355 if (dt->year > LONG_MAX - digit)
1356 return 2;
1357 dt->year += digit;
1358 cur++;
1359 digcnt++;
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')))
1365 return 1;
1367 if (isneg)
1368 dt->year = - dt->year;
1370 if (!VALID_YEAR(dt->year))
1371 return 2;
1373 *str = cur;
1374 return 0;
1378 * PARSE_2_DIGITS:
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')) \
1391 invalid = 1; \
1392 else \
1393 num = (cur[0] - '0') * 10 + (cur[1] - '0'); \
1394 cur += 2;
1397 * PARSE_FLOAT:
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 == '.')) { \
1411 double mult = 1; \
1412 cur++; \
1413 if ((*cur < '0') || (*cur > '9')) \
1414 invalid = 1; \
1415 while ((*cur >= '0') && (*cur <= '9')) { \
1416 mult /= 10; \
1417 num += (*cur - '0') * mult; \
1418 cur++; \
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
1429 * xs:gMonth.
1431 * Returns 0 or the error code
1433 static int
1434 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) {
1435 const xmlChar *cur = *str;
1436 int ret = 0;
1437 unsigned int value = 0;
1439 PARSE_2_DIGITS(value, cur, ret);
1440 if (ret != 0)
1441 return ret;
1443 if (!VALID_MONTH(value))
1444 return 2;
1446 dt->mon = value;
1448 *str = cur;
1449 return 0;
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
1459 * xs:gDay.
1461 * Returns 0 or the error code
1463 static int
1464 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) {
1465 const xmlChar *cur = *str;
1466 int ret = 0;
1467 unsigned int value = 0;
1469 PARSE_2_DIGITS(value, cur, ret);
1470 if (ret != 0)
1471 return ret;
1473 if (!VALID_DAY(value))
1474 return 2;
1476 dt->day = value;
1477 *str = cur;
1478 return 0;
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
1488 * xs:time.
1489 * In case of error, values of @dt fields are undefined.
1491 * Returns 0 or the error code
1493 static int
1494 _xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) {
1495 const xmlChar *cur = *str;
1496 int ret = 0;
1497 int value = 0;
1499 PARSE_2_DIGITS(value, cur, ret);
1500 if (ret != 0)
1501 return ret;
1502 if (*cur != ':')
1503 return 1;
1504 if (!VALID_HOUR(value) && value != 24 /* Allow end-of-day hour */)
1505 return 2;
1506 cur++;
1508 /* the ':' insures this string is xs:time */
1509 dt->hour = value;
1511 PARSE_2_DIGITS(value, cur, ret);
1512 if (ret != 0)
1513 return ret;
1514 if (!VALID_MIN(value))
1515 return 2;
1516 dt->min = value;
1518 if (*cur != ':')
1519 return 1;
1520 cur++;
1522 PARSE_FLOAT(dt->sec, cur, ret);
1523 if (ret != 0)
1524 return ret;
1526 if (!VALID_TIME(dt))
1527 return 2;
1529 *str = cur;
1530 return 0;
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
1540 * time zone.
1542 * Returns 0 or the error code
1544 static int
1545 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
1546 const xmlChar *cur;
1547 int ret = 0;
1549 if (str == NULL)
1550 return -1;
1551 cur = *str;
1553 switch (*cur) {
1554 case 0:
1555 dt->tz_flag = 0;
1556 dt->tzo = 0;
1557 break;
1559 case 'Z':
1560 dt->tz_flag = 1;
1561 dt->tzo = 0;
1562 cur++;
1563 break;
1565 case '+':
1566 case '-': {
1567 int isneg = 0, tmp = 0;
1568 isneg = (*cur == '-');
1570 cur++;
1572 PARSE_2_DIGITS(tmp, cur, ret);
1573 if (ret != 0)
1574 return ret;
1575 if (!VALID_HOUR(tmp))
1576 return 2;
1578 if (*cur != ':')
1579 return 1;
1580 cur++;
1582 dt->tzo = tmp * 60;
1584 PARSE_2_DIGITS(tmp, cur, ret);
1585 if (ret != 0)
1586 return ret;
1587 if (!VALID_MIN(tmp))
1588 return 2;
1590 dt->tzo += tmp;
1591 if (isneg)
1592 dt->tzo = - dt->tzo;
1594 if (!VALID_TZO(dt->tzo))
1595 return 2;
1597 dt->tz_flag = 1;
1598 break;
1600 default:
1601 return 1;
1604 *str = cur;
1605 return 0;
1609 * _xmlSchemaBase64Decode:
1610 * @ch: a character
1612 * Converts a base64 encoded character to its base 64 value.
1614 * Returns 0-63 (value), 64 (pad), or -1 (not recognized)
1616 static int
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;
1624 return -1;
1627 /****************************************************************
1629 * XML Schema Dates/Times Datatypes Handling *
1631 ****************************************************************/
1634 * PARSE_DIGITS:
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')) \
1646 num_type = -1; \
1647 else \
1648 while ((*cur >= '0') && (*cur <= '9')) { \
1649 num = num * 10 + (*cur - '0'); \
1650 cur++; \
1654 * PARSE_NUM:
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) \
1667 num = 0; \
1668 PARSE_DIGITS(num, cur, num_type); \
1669 if (!num_type && (*cur == '.')) { \
1670 double mult = 1; \
1671 cur++; \
1672 if ((*cur < '0') || (*cur > '9')) \
1673 num_type = -1; \
1674 else \
1675 num_type = 1; \
1676 while ((*cur >= '0') && (*cur <= '9')) { \
1677 mult /= 10; \
1678 num += (*cur - '0') * mult; \
1679 cur++; \
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.
1695 static int
1696 xmlSchemaValidateDates (xmlSchemaValType type,
1697 const xmlChar *dateTime, xmlSchemaValPtr *val,
1698 int collapse) {
1699 xmlSchemaValPtr dt;
1700 int ret;
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); \
1706 if (ret == 0) { \
1707 if (*cur != 0) \
1708 goto error; \
1709 dt->type = t; \
1710 goto done; \
1714 if (dateTime == NULL)
1715 return -1;
1717 if (collapse)
1718 while IS_WSP_BLANK_CH(*cur) cur++;
1720 if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
1721 return 1;
1723 dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN);
1724 if (dt == NULL)
1725 return -1;
1727 if ((cur[0] == '-') && (cur[1] == '-')) {
1729 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
1730 * xs:gDay)
1732 cur += 2;
1734 /* is it an xs:gDay? */
1735 if (*cur == '-') {
1736 if (type == XML_SCHEMAS_GMONTH)
1737 goto error;
1738 ++cur;
1739 ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1740 if (ret != 0)
1741 goto error;
1743 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY);
1745 goto error;
1749 * it should be an xs:gMonthDay or xs:gMonth
1751 ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1752 if (ret != 0)
1753 goto error;
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
1761 * a tzo.
1763 if (*cur == '-') {
1764 const xmlChar *rewnd = cur;
1765 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
1775 * probably.
1777 if (VALID_MDAY((&(dt->value.date)))) {
1779 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
1781 goto error;
1786 * not xs:gMonthDay so rewind and check if just xs:gMonth
1787 * with an optional time zone.
1789 cur = rewnd;
1792 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
1794 goto error;
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);
1803 if (ret == 0) {
1804 /* it's an xs:time */
1805 RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME);
1809 /* fallback on date parsing */
1810 cur = dateTime;
1812 ret = _xmlSchemaParseGYear(&(dt->value.date), &cur);
1813 if (ret != 0)
1814 goto error;
1816 /* is it an xs:gYear? */
1817 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR);
1819 if (*cur != '-')
1820 goto error;
1821 cur++;
1823 ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1824 if (ret != 0)
1825 goto error;
1827 /* is it an xs:gYearMonth? */
1828 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH);
1830 if (*cur != '-')
1831 goto error;
1832 cur++;
1834 ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1835 if ((ret != 0) || !VALID_DATE((&(dt->value.date))))
1836 goto error;
1838 /* is it an xs:date? */
1839 RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE);
1841 if (*cur != 'T')
1842 goto error;
1843 cur++;
1845 /* it should be an xs:dateTime */
1846 ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1847 if (ret != 0)
1848 goto error;
1850 ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);
1851 if (collapse)
1852 while IS_WSP_BLANK_CH(*cur) cur++;
1853 if ((ret != 0) || (*cur != 0) || (!(VALID_DATETIME((&(dt->value.date))))))
1854 goto error;
1857 dt->type = XML_SCHEMAS_DATETIME;
1859 done:
1860 #if 1
1861 if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
1862 goto error;
1863 #else
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))
1872 goto error;
1874 if ((type == XML_SCHEMAS_DATETIME) &&
1875 ((dt->type != XML_SCHEMAS_DATE) ||
1876 (dt->type != XML_SCHEMAS_GYEARMONTH) ||
1877 (dt->type != XML_SCHEMAS_GYEAR)))
1878 goto error;
1880 if ((type == XML_SCHEMAS_DATE) &&
1881 ((dt->type != XML_SCHEMAS_GYEAR) ||
1882 (dt->type != XML_SCHEMAS_GYEARMONTH)))
1883 goto error;
1885 if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
1886 goto error;
1888 if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
1889 goto error;
1891 #endif
1893 if (val != NULL)
1894 *val = dt;
1895 else
1896 xmlSchemaFreeValue(dt);
1898 return 0;
1900 error:
1901 if (dt != NULL)
1902 xmlSchemaFreeValue(dt);
1903 return 1;
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.
1918 static int
1919 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1920 const xmlChar *duration, xmlSchemaValPtr *val,
1921 int collapse) {
1922 const xmlChar *cur = duration;
1923 xmlSchemaValPtr dur;
1924 int isneg = 0;
1925 unsigned int seq = 0;
1926 long days, secs = 0;
1927 double sec_frac = 0.0;
1929 if (duration == NULL)
1930 return -1;
1932 if (collapse)
1933 while IS_WSP_BLANK_CH(*cur) cur++;
1935 if (*cur == '-') {
1936 isneg = 1;
1937 cur++;
1940 /* duration must start with 'P' (after sign) */
1941 if (*cur++ != 'P')
1942 return 1;
1944 if (*cur == 0)
1945 return 1;
1947 dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
1948 if (dur == NULL)
1949 return -1;
1951 while (*cur != 0) {
1952 long num = 0;
1953 size_t has_digits = 0;
1954 int has_frac = 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))
1959 goto error;
1961 /* T designator must be present for time items */
1962 if (*cur == 'T') {
1963 if (seq > 3)
1964 goto error;
1965 cur++;
1966 seq = 3;
1967 } else if (seq == 3)
1968 goto error;
1970 /* Parse integral part. */
1971 while (*cur >= '0' && *cur <= '9') {
1972 long digit = *cur - '0';
1974 if (num > LONG_MAX / 10)
1975 goto error;
1976 num *= 10;
1977 if (num > LONG_MAX - digit)
1978 goto error;
1979 num += digit;
1981 has_digits = 1;
1982 cur++;
1985 if (*cur == '.') {
1986 /* Parse fractional part. */
1987 double mult = 1.0;
1988 cur++;
1989 has_frac = 1;
1990 while (*cur >= '0' && *cur <= '9') {
1991 mult /= 10.0;
1992 sec_frac += (*cur - '0') * mult;
1993 has_digits = 1;
1994 cur++;
1998 while (*cur != desig[seq]) {
1999 seq++;
2000 /* No T designator or invalid char. */
2001 if (seq == 3 || seq == sizeof(desig))
2002 goto error;
2004 cur++;
2006 if (!has_digits || (has_frac && (seq != 5)))
2007 goto error;
2009 switch (seq) {
2010 case 0:
2011 /* Year */
2012 if (num > LONG_MAX / 12)
2013 goto error;
2014 dur->value.dur.mon = num * 12;
2015 break;
2016 case 1:
2017 /* Month */
2018 if (dur->value.dur.mon > LONG_MAX - num)
2019 goto error;
2020 dur->value.dur.mon += num;
2021 break;
2022 case 2:
2023 /* Day */
2024 dur->value.dur.day = num;
2025 break;
2026 case 3:
2027 /* Hour */
2028 days = num / HOURS_PER_DAY;
2029 if (dur->value.dur.day > LONG_MAX - days)
2030 goto error;
2031 dur->value.dur.day += days;
2032 secs = (num % HOURS_PER_DAY) * SECS_PER_HOUR;
2033 break;
2034 case 4:
2035 /* Minute */
2036 days = num / MINS_PER_DAY;
2037 if (dur->value.dur.day > LONG_MAX - days)
2038 goto error;
2039 dur->value.dur.day += days;
2040 secs += (num % MINS_PER_DAY) * SECS_PER_MIN;
2041 break;
2042 case 5:
2043 /* Second */
2044 days = num / SECS_PER_DAY;
2045 if (dur->value.dur.day > LONG_MAX - days)
2046 goto error;
2047 dur->value.dur.day += days;
2048 secs += num % SECS_PER_DAY;
2049 break;
2052 seq++;
2055 days = secs / SECS_PER_DAY;
2056 if (dur->value.dur.day > LONG_MAX - days)
2057 goto error;
2058 dur->value.dur.day += days;
2059 dur->value.dur.sec = (secs % SECS_PER_DAY) + sec_frac;
2061 if (isneg) {
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;
2067 if (val != NULL)
2068 *val = dur;
2069 else
2070 xmlSchemaFreeValue(dur);
2072 return 0;
2074 error:
2075 if (dur != NULL)
2076 xmlSchemaFreeValue(dur);
2077 return 1;
2081 * xmlSchemaStrip:
2082 * @value: a value
2084 * Removes the leading and ending spaces of a string
2086 * Returns the new string or NULL if no change was required.
2088 static xmlChar *
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++;
2094 end = start;
2095 while (*end != 0) end++;
2096 f = end;
2097 end--;
2098 while ((end > start) && (IS_BLANK_CH(*end))) end--;
2099 end++;
2100 if ((start == value) && (f == end)) return(NULL);
2101 return(xmlStrndup(start, end - start));
2105 * xmlSchemaWhiteSpaceReplace:
2106 * @value: a value
2108 * Replaces 0xd, 0x9 and 0xa with a space.
2110 * Returns the new string or NULL if no change was required.
2112 xmlChar *
2113 xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
2114 const xmlChar *cur = value;
2115 xmlChar *ret = NULL, *mcur;
2117 if (value == NULL)
2118 return(NULL);
2120 while ((*cur != 0) &&
2121 (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
2122 cur++;
2124 if (*cur == 0)
2125 return (NULL);
2126 ret = xmlStrdup(value);
2127 /* TODO FIXME: I guess gcc will bark at this. */
2128 mcur = (xmlChar *) (ret + (cur - value));
2129 do {
2130 if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
2131 *mcur = ' ';
2132 mcur++;
2133 } while (*mcur != 0);
2134 return(ret);
2138 * xmlSchemaCollapseString:
2139 * @value: a value
2141 * Removes and normalize white spaces in the string
2143 * Returns the new string or NULL if no change was required.
2145 xmlChar *
2146 xmlSchemaCollapseString(const xmlChar *value) {
2147 const xmlChar *start = value, *end, *f;
2148 xmlChar *g;
2149 int col = 0;
2151 if (value == NULL) return(NULL);
2152 while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
2153 end = start;
2154 while (*end != 0) {
2155 if ((*end == ' ') && (IS_BLANK_CH(end[1]))) {
2156 col = end - start;
2157 break;
2158 } else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) {
2159 col = end - start;
2160 break;
2162 end++;
2164 if (col == 0) {
2165 f = end;
2166 end--;
2167 while ((end > start) && (IS_BLANK_CH(*end))) end--;
2168 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);
2175 end = g;
2176 while (*end != 0) {
2177 if (IS_BLANK_CH(*end)) {
2178 end++;
2179 while (IS_BLANK_CH(*end)) end++;
2180 if (*end != 0)
2181 *g++ = ' ';
2182 } else
2183 *g++ = *end++;
2185 *g = 0;
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
2200 * number otherwise
2202 static int
2203 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
2204 xmlSchemaValPtr *ret, xmlNodePtr node) {
2205 xmlChar *val, *cur, *endval;
2206 int nb_values = 0;
2207 int tmp = 0;
2209 if (value == NULL) {
2210 return(-1);
2212 val = xmlStrdup(value);
2213 if (val == NULL) {
2214 return(-1);
2216 if (ret != NULL) {
2217 *ret = NULL;
2219 cur = val;
2221 * Split the list
2223 while (IS_BLANK_CH(*cur)) *cur++ = 0;
2224 while (*cur != 0) {
2225 if (IS_BLANK_CH(*cur)) {
2226 *cur = 0;
2227 cur++;
2228 while (IS_BLANK_CH(*cur)) *cur++ = 0;
2229 } else {
2230 nb_values++;
2231 cur++;
2232 while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
2235 if (nb_values == 0) {
2236 xmlFree(val);
2237 return(nb_values);
2239 endval = cur;
2240 cur = val;
2241 while ((*cur == 0) && (cur != endval)) cur++;
2242 while (cur != endval) {
2243 tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node);
2244 if (tmp != 0)
2245 break;
2246 while (*cur != 0) cur++;
2247 while ((*cur == 0) && (cur != endval)) cur++;
2249 /* TODO what return value ? c.f. bug #158628
2250 if (ret != NULL) {
2251 TODO
2252 } */
2253 xmlFree(val);
2254 if (tmp == 0)
2255 return(nb_values);
2256 return(-1);
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.
2271 static int
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;
2276 int ret = 0, i = 0;
2278 if (!((*cur >= '0') && (*cur <= '9')))
2279 return(-2);
2281 while (*cur == '0') { /* ignore leading zeroes */
2282 cur++;
2284 tmp = cur;
2285 while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
2286 i++;tmp++;ret++;
2288 if (i > 24) {
2289 *str = tmp;
2290 return(-1);
2292 while (i > 16) {
2293 hi = hi * 10 + (*cur++ - '0');
2294 i--;
2296 while (i > 8) {
2297 mi = mi * 10 + (*cur++ - '0');
2298 i--;
2300 while (i > 0) {
2301 lo = lo * 10 + (*cur++ - '0');
2302 i--;
2305 *str = cur;
2306 *llo = lo;
2307 *lmi = mi;
2308 *lhi = hi;
2309 return(ret);
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.
2321 static int
2322 xmlSchemaCheckLanguageType(const xmlChar* value) {
2323 int first = 1, len = 0;
2324 const xmlChar* cur = value;
2326 if (value == NULL)
2327 return (0);
2329 while (cur[0] != 0) {
2330 if (!( ((cur[0] >= 'a') && (cur[0] <= 'z')) || ((cur[0] >= 'A') && (cur[0] <= 'Z'))
2331 || (cur[0] == '-')
2332 || ((first == 0) && (xmlIsDigit_ch(cur[0]))) ))
2333 return (0);
2334 if (cur[0] == '-') {
2335 if ((len < 1) || (len > 8))
2336 return (0);
2337 len = 0;
2338 first = 0;
2340 else
2341 len++;
2342 cur++;
2344 if ((len < 1) || (len > 8))
2345 return (0);
2347 return (1);
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.
2365 static int
2366 xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
2367 xmlSchemaValPtr * val, xmlNodePtr node, int flags,
2368 xmlSchemaWhitespaceValueType ws,
2369 int normOnTheFly, int applyNorm, int createStringValue)
2371 xmlSchemaValPtr v;
2372 xmlChar *norm = NULL;
2373 int ret = 0;
2375 if ((xmlSchemaTypesInitialized == 0) &&
2376 (xmlSchemaInitTypes() < 0))
2377 return (-1);
2378 if (type == NULL)
2379 return (-1);
2382 * validating a non existent text node is similar to validating
2383 * an empty one.
2385 if (value == NULL)
2386 value = BAD_CAST "";
2388 if (val != NULL)
2389 *val = NULL;
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);
2397 else
2398 norm = xmlSchemaCollapseString(value);
2399 if (norm != NULL)
2400 value = norm;
2404 switch (type->builtInType) {
2405 case XML_SCHEMAS_UNKNOWN:
2406 goto error;
2407 case XML_SCHEMAS_ANYTYPE:
2408 case XML_SCHEMAS_ANYSIMPLETYPE:
2409 if ((createStringValue) && (val != NULL)) {
2410 v = xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE);
2411 if (v != NULL) {
2412 v->value.str = xmlStrdup(value);
2413 *val = v;
2414 } else {
2415 goto error;
2418 goto return0;
2419 case XML_SCHEMAS_STRING:
2420 if (! normOnTheFly) {
2421 const xmlChar *cur = value;
2423 if (ws == XML_SCHEMA_WHITESPACE_REPLACE) {
2424 while (*cur != 0) {
2425 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2426 goto return1;
2427 } else {
2428 cur++;
2431 } else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
2432 while (*cur != 0) {
2433 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2434 goto return1;
2435 } else if IS_WSP_SPACE_CH(*cur) {
2436 cur++;
2437 if IS_WSP_SPACE_CH(*cur)
2438 goto return1;
2439 } else {
2440 cur++;
2445 if (createStringValue && (val != NULL)) {
2446 if (applyNorm) {
2447 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
2448 norm = xmlSchemaCollapseString(value);
2449 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
2450 norm = xmlSchemaWhiteSpaceReplace(value);
2451 if (norm != NULL)
2452 value = norm;
2454 v = xmlSchemaNewValue(XML_SCHEMAS_STRING);
2455 if (v != NULL) {
2456 v->value.str = xmlStrdup(value);
2457 *val = v;
2458 } else {
2459 goto error;
2462 goto return0;
2463 case XML_SCHEMAS_NORMSTRING:{
2464 if (normOnTheFly) {
2465 if (applyNorm) {
2466 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
2467 norm = xmlSchemaCollapseString(value);
2468 else
2469 norm = xmlSchemaWhiteSpaceReplace(value);
2470 if (norm != NULL)
2471 value = norm;
2473 } else {
2474 const xmlChar *cur = value;
2475 while (*cur != 0) {
2476 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2477 goto return1;
2478 } else {
2479 cur++;
2483 if (val != NULL) {
2484 v = xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING);
2485 if (v != NULL) {
2486 v->value.str = xmlStrdup(value);
2487 *val = v;
2488 } else {
2489 goto error;
2492 goto return0;
2494 case XML_SCHEMAS_DECIMAL:{
2495 const xmlChar *cur = value;
2496 unsigned int len, neg, integ, hasLeadingZeroes;
2497 xmlChar cval[25];
2498 xmlChar *cptr = cval;
2500 if ((cur == NULL) || (*cur == 0))
2501 goto return1;
2504 * xs:decimal has a whitespace-facet value of 'collapse'.
2506 if (normOnTheFly)
2507 while IS_WSP_BLANK_CH(*cur) cur++;
2510 * First we handle an optional sign.
2512 neg = 0;
2513 if (*cur == '-') {
2514 neg = 1;
2515 cur++;
2516 } else if (*cur == '+')
2517 cur++;
2519 * Disallow: "", "-", "- "
2521 if (*cur == 0)
2522 goto return1;
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.
2529 len = 0;
2530 integ = ~0u;
2531 hasLeadingZeroes = 0;
2533 * Skip leading zeroes.
2535 while (*cur == '0') {
2536 cur++;
2537 hasLeadingZeroes = 1;
2539 if (*cur != 0) {
2540 do {
2541 if ((*cur >= '0') && (*cur <= '9')) {
2542 *cptr++ = *cur++;
2543 len++;
2544 } else if (*cur == '.') {
2545 cur++;
2546 integ = len;
2547 do {
2548 if ((*cur >= '0') && (*cur <= '9')) {
2549 *cptr++ = *cur++;
2550 len++;
2551 } else
2552 break;
2553 } while (len < 24);
2555 * Disallow "." but allow "00."
2557 if ((len == 0) && (!hasLeadingZeroes))
2558 goto return1;
2559 break;
2560 } else
2561 break;
2562 } while (len < 24);
2564 if (normOnTheFly)
2565 while IS_WSP_BLANK_CH(*cur) cur++;
2566 if (*cur != 0)
2567 goto return1; /* error if any extraneous chars */
2568 if (val != NULL) {
2569 v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
2570 if (v != NULL) {
2572 * Now evaluate the significant digits of the number
2574 if (len != 0) {
2576 if (integ != ~0u) {
2578 * Get rid of trailing zeroes in the
2579 * fractional part.
2581 while ((len != integ) && (*(cptr-1) == '0')) {
2582 cptr--;
2583 len--;
2587 * Terminate the (preparsed) string.
2589 if (len != 0) {
2590 *cptr = 0;
2591 cptr = cval;
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;
2603 if (len == 0) {
2604 /* Speedup for zero values. */
2605 v->value.decimal.total = 1;
2606 } else {
2607 v->value.decimal.total = len;
2608 if (integ == ~0u)
2609 v->value.decimal.frac = 0;
2610 else
2611 v->value.decimal.frac = len - integ;
2613 *val = v;
2616 goto return0;
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,
2627 normOnTheFly);
2628 break;
2629 case XML_SCHEMAS_DURATION:
2630 ret = xmlSchemaValidateDuration(type, value, val,
2631 normOnTheFly);
2632 break;
2633 case XML_SCHEMAS_FLOAT:
2634 case XML_SCHEMAS_DOUBLE: {
2635 const xmlChar *cur = value;
2636 int neg = 0;
2637 int digits_before = 0;
2638 int digits_after = 0;
2640 if (normOnTheFly)
2641 while IS_WSP_BLANK_CH(*cur) cur++;
2643 if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
2644 cur += 3;
2645 if (*cur != 0)
2646 goto return1;
2647 if (val != NULL) {
2648 if (type == xmlSchemaTypeFloatDef) {
2649 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2650 if (v != NULL) {
2651 v->value.f = (float) xmlXPathNAN;
2652 } else {
2653 xmlSchemaFreeValue(v);
2654 goto error;
2656 } else {
2657 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2658 if (v != NULL) {
2659 v->value.d = xmlXPathNAN;
2660 } else {
2661 xmlSchemaFreeValue(v);
2662 goto error;
2665 *val = v;
2667 goto return0;
2669 if (*cur == '-') {
2670 neg = 1;
2671 cur++;
2673 if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
2674 cur += 3;
2675 if (*cur != 0)
2676 goto return1;
2677 if (val != NULL) {
2678 if (type == xmlSchemaTypeFloatDef) {
2679 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2680 if (v != NULL) {
2681 if (neg)
2682 v->value.f = (float) xmlXPathNINF;
2683 else
2684 v->value.f = (float) xmlXPathPINF;
2685 } else {
2686 xmlSchemaFreeValue(v);
2687 goto error;
2689 } else {
2690 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2691 if (v != NULL) {
2692 if (neg)
2693 v->value.d = xmlXPathNINF;
2694 else
2695 v->value.d = xmlXPathPINF;
2696 } else {
2697 xmlSchemaFreeValue(v);
2698 goto error;
2701 *val = v;
2703 goto return0;
2705 if ((neg == 0) && (*cur == '+'))
2706 cur++;
2707 if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
2708 goto return1;
2709 while ((*cur >= '0') && (*cur <= '9')) {
2710 cur++;
2711 digits_before++;
2713 if (*cur == '.') {
2714 cur++;
2715 while ((*cur >= '0') && (*cur <= '9')) {
2716 cur++;
2717 digits_after++;
2720 if ((digits_before == 0) && (digits_after == 0))
2721 goto return1;
2722 if ((*cur == 'e') || (*cur == 'E')) {
2723 cur++;
2724 if ((*cur == '-') || (*cur == '+'))
2725 cur++;
2726 while ((*cur >= '0') && (*cur <= '9'))
2727 cur++;
2729 if (normOnTheFly)
2730 while IS_WSP_BLANK_CH(*cur) cur++;
2732 if (*cur != 0)
2733 goto return1;
2734 if (val != NULL) {
2735 if (type == xmlSchemaTypeFloatDef) {
2736 v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2737 if (v != NULL) {
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) {
2745 *val = v;
2746 } else {
2747 xmlSchemaFreeValue(v);
2748 goto return1;
2750 } else {
2751 goto error;
2753 } else {
2754 v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2755 if (v != NULL) {
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) {
2762 *val = v;
2763 } else {
2764 xmlSchemaFreeValue(v);
2765 goto return1;
2767 } else {
2768 goto error;
2772 goto return0;
2774 case XML_SCHEMAS_BOOLEAN:{
2775 const xmlChar *cur = value;
2777 if (normOnTheFly) {
2778 while IS_WSP_BLANK_CH(*cur) cur++;
2779 if (*cur == '0') {
2780 ret = 0;
2781 cur++;
2782 } else if (*cur == '1') {
2783 ret = 1;
2784 cur++;
2785 } else if (*cur == 't') {
2786 cur++;
2787 if ((*cur++ == 'r') && (*cur++ == 'u') &&
2788 (*cur++ == 'e')) {
2789 ret = 1;
2790 } else
2791 goto return1;
2792 } else if (*cur == 'f') {
2793 cur++;
2794 if ((*cur++ == 'a') && (*cur++ == 'l') &&
2795 (*cur++ == 's') && (*cur++ == 'e')) {
2796 ret = 0;
2797 } else
2798 goto return1;
2799 } else
2800 goto return1;
2801 if (*cur != 0) {
2802 while IS_WSP_BLANK_CH(*cur) cur++;
2803 if (*cur != 0)
2804 goto return1;
2806 } else {
2807 if ((cur[0] == '0') && (cur[1] == 0))
2808 ret = 0;
2809 else if ((cur[0] == '1') && (cur[1] == 0))
2810 ret = 1;
2811 else if ((cur[0] == 't') && (cur[1] == 'r')
2812 && (cur[2] == 'u') && (cur[3] == 'e')
2813 && (cur[4] == 0))
2814 ret = 1;
2815 else if ((cur[0] == 'f') && (cur[1] == 'a')
2816 && (cur[2] == 'l') && (cur[3] == 's')
2817 && (cur[4] == 'e') && (cur[5] == 0))
2818 ret = 0;
2819 else
2820 goto return1;
2822 if (val != NULL) {
2823 v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
2824 if (v != NULL) {
2825 v->value.b = ret;
2826 *val = v;
2827 } else {
2828 goto error;
2831 goto return0;
2833 case XML_SCHEMAS_TOKEN:{
2834 const xmlChar *cur = value;
2836 if (! normOnTheFly) {
2837 while (*cur != 0) {
2838 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2839 goto return1;
2840 } else if (*cur == ' ') {
2841 cur++;
2842 if (*cur == 0)
2843 goto return1;
2844 if (*cur == ' ')
2845 goto return1;
2846 } else {
2847 cur++;
2851 if (val != NULL) {
2852 v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
2853 if (v != NULL) {
2854 v->value.str = xmlStrdup(value);
2855 *val = v;
2856 } else {
2857 goto error;
2860 goto return0;
2862 case XML_SCHEMAS_LANGUAGE:
2863 if ((norm == NULL) && (normOnTheFly)) {
2864 norm = xmlSchemaCollapseString(value);
2865 if (norm != NULL)
2866 value = norm;
2869 if (xmlSchemaCheckLanguageType(value) == 1) {
2870 if (val != NULL) {
2871 v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
2872 if (v != NULL) {
2873 v->value.str = xmlStrdup(value);
2874 *val = v;
2875 } else {
2876 goto error;
2879 goto return0;
2881 goto return1;
2882 case XML_SCHEMAS_NMTOKEN:
2883 if (xmlValidateNMToken(value, 1) == 0) {
2884 if (val != NULL) {
2885 v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
2886 if (v != NULL) {
2887 v->value.str = xmlStrdup(value);
2888 *val = v;
2889 } else {
2890 goto error;
2893 goto return0;
2895 goto return1;
2896 case XML_SCHEMAS_NMTOKENS:
2897 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
2898 value, val, node);
2899 if (ret > 0)
2900 ret = 0;
2901 else
2902 ret = 1;
2903 goto done;
2904 case XML_SCHEMAS_NAME:
2905 ret = xmlValidateName(value, 1);
2906 if ((ret == 0) && (val != NULL) && (value != NULL)) {
2907 v = xmlSchemaNewValue(XML_SCHEMAS_NAME);
2908 if (v != NULL) {
2909 const xmlChar *start = value, *end;
2910 while (IS_BLANK_CH(*start)) start++;
2911 end = start;
2912 while ((*end != 0) && (!IS_BLANK_CH(*end))) end++;
2913 v->value.str = xmlStrndup(start, end - start);
2914 *val = v;
2915 } else {
2916 goto error;
2919 goto done;
2920 case XML_SCHEMAS_QNAME:{
2921 const xmlChar *uri = NULL;
2922 xmlChar *local = NULL;
2924 ret = xmlValidateQName(value, 1);
2925 if (ret != 0)
2926 goto done;
2927 if (node != NULL) {
2928 xmlChar *prefix;
2929 xmlNsPtr ns;
2931 local = xmlSplitQName2(value, &prefix);
2932 ns = xmlSearchNs(node->doc, node, prefix);
2933 if ((ns == NULL) && (prefix != NULL)) {
2934 xmlFree(prefix);
2935 if (local != NULL)
2936 xmlFree(local);
2937 goto return1;
2939 if (ns != NULL)
2940 uri = ns->href;
2941 if (prefix != NULL)
2942 xmlFree(prefix);
2944 if (val != NULL) {
2945 v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
2946 if (v == NULL) {
2947 if (local != NULL)
2948 xmlFree(local);
2949 goto error;
2951 if (local != NULL)
2952 v->value.qname.name = local;
2953 else
2954 v->value.qname.name = xmlStrdup(value);
2955 if (uri != NULL)
2956 v->value.qname.uri = xmlStrdup(uri);
2957 *val = v;
2958 } else
2959 if (local != NULL)
2960 xmlFree(local);
2961 goto done;
2963 case XML_SCHEMAS_NCNAME:
2964 ret = xmlValidateNCName(value, 1);
2965 if ((ret == 0) && (val != NULL)) {
2966 v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
2967 if (v != NULL) {
2968 v->value.str = xmlStrdup(value);
2969 *val = v;
2970 } else {
2971 goto error;
2974 goto done;
2975 case XML_SCHEMAS_ID:
2976 ret = xmlValidateNCName(value, 1);
2977 if ((ret == 0) && (val != NULL)) {
2978 v = xmlSchemaNewValue(XML_SCHEMAS_ID);
2979 if (v != NULL) {
2980 v->value.str = xmlStrdup(value);
2981 *val = v;
2982 } else {
2983 goto error;
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) {
2994 xmlIDPtr res;
2995 xmlChar *strip;
2997 strip = xmlSchemaStrip(value);
2998 if (strip != NULL) {
2999 res = xmlAddID(NULL, node->doc, strip, attr);
3000 xmlFree(strip);
3001 } else
3002 res = xmlAddID(NULL, node->doc, value, attr);
3003 if (res == NULL) {
3004 ret = 2;
3005 } else {
3006 attr->atype = XML_ATTRIBUTE_ID;
3010 goto done;
3011 case XML_SCHEMAS_IDREF:
3012 ret = xmlValidateNCName(value, 1);
3013 if ((ret == 0) && (val != NULL)) {
3014 v = xmlSchemaNewValue(XML_SCHEMAS_IDREF);
3015 if (v == NULL)
3016 goto error;
3017 v->value.str = xmlStrdup(value);
3018 *val = v;
3020 if ((ret == 0) && (node != NULL) &&
3021 (node->type == XML_ATTRIBUTE_NODE)) {
3022 xmlAttrPtr attr = (xmlAttrPtr) node;
3023 xmlChar *strip;
3025 strip = xmlSchemaStrip(value);
3026 if (strip != NULL) {
3027 xmlAddRef(NULL, node->doc, strip, attr);
3028 xmlFree(strip);
3029 } else
3030 xmlAddRef(NULL, node->doc, value, attr);
3031 attr->atype = XML_ATTRIBUTE_IDREF;
3033 goto done;
3034 case XML_SCHEMAS_IDREFS:
3035 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
3036 value, val, node);
3037 if (ret < 0)
3038 ret = 2;
3039 else
3040 ret = 0;
3041 if ((ret == 0) && (node != NULL) &&
3042 (node->type == XML_ATTRIBUTE_NODE)) {
3043 xmlAttrPtr attr = (xmlAttrPtr) node;
3045 attr->atype = XML_ATTRIBUTE_IDREFS;
3047 goto done;
3048 case XML_SCHEMAS_ENTITY:{
3049 xmlChar *strip;
3051 ret = xmlValidateNCName(value, 1);
3052 if ((node == NULL) || (node->doc == NULL))
3053 ret = 3;
3054 if (ret == 0) {
3055 xmlEntityPtr ent;
3057 strip = xmlSchemaStrip(value);
3058 if (strip != NULL) {
3059 ent = xmlGetDocEntity(node->doc, strip);
3060 xmlFree(strip);
3061 } else {
3062 ent = xmlGetDocEntity(node->doc, value);
3064 if ((ent == NULL) ||
3065 (ent->etype !=
3066 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
3067 ret = 4;
3069 if ((ret == 0) && (val != NULL)) {
3070 TODO;
3072 if ((ret == 0) && (node != NULL) &&
3073 (node->type == XML_ATTRIBUTE_NODE)) {
3074 xmlAttrPtr attr = (xmlAttrPtr) node;
3076 attr->atype = XML_ATTRIBUTE_ENTITY;
3078 goto done;
3080 case XML_SCHEMAS_ENTITIES:
3081 if ((node == NULL) || (node->doc == NULL))
3082 goto return3;
3083 ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
3084 value, val, node);
3085 if (ret <= 0)
3086 ret = 1;
3087 else
3088 ret = 0;
3089 if ((ret == 0) && (node != NULL) &&
3090 (node->type == XML_ATTRIBUTE_NODE)) {
3091 xmlAttrPtr attr = (xmlAttrPtr) node;
3093 attr->atype = XML_ATTRIBUTE_ENTITIES;
3095 goto done;
3096 case XML_SCHEMAS_NOTATION:{
3097 xmlChar *uri = NULL;
3098 xmlChar *local = NULL;
3100 ret = xmlValidateQName(value, 1);
3101 if ((ret == 0) && (node != NULL)) {
3102 xmlChar *prefix;
3104 local = xmlSplitQName2(value, &prefix);
3105 if (prefix != NULL) {
3106 xmlNsPtr ns;
3108 ns = xmlSearchNs(node->doc, node, prefix);
3109 if (ns == NULL)
3110 ret = 1;
3111 else if (val != NULL)
3112 uri = xmlStrdup(ns->href);
3114 if ((local != NULL) && ((val == NULL) || (ret != 0)))
3115 xmlFree(local);
3116 if (prefix != NULL)
3117 xmlFree(prefix);
3119 if ((node == NULL) || (node->doc == NULL))
3120 ret = 3;
3121 if (ret == 0) {
3122 ret = xmlValidateNotationUse(NULL, node->doc, value);
3123 if (ret == 1)
3124 ret = 0;
3125 else
3126 ret = 1;
3128 if ((ret == 0) && (val != NULL)) {
3129 v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
3130 if (v != NULL) {
3131 if (local != NULL)
3132 v->value.qname.name = local;
3133 else
3134 v->value.qname.name = xmlStrdup(value);
3135 if (uri != NULL)
3136 v->value.qname.uri = uri;
3138 *val = v;
3139 } else {
3140 if (local != NULL)
3141 xmlFree(local);
3142 if (uri != NULL)
3143 xmlFree(uri);
3144 goto error;
3147 goto done;
3149 case XML_SCHEMAS_ANYURI:{
3150 if (*value != 0) {
3151 xmlURIPtr uri;
3152 xmlChar *tmpval, *cur;
3153 if ((norm == NULL) && (normOnTheFly)) {
3154 norm = xmlSchemaCollapseString(value);
3155 if (norm != NULL)
3156 value = norm;
3158 tmpval = xmlStrdup(value);
3159 if (tmpval == NULL)
3160 goto error;
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 == '`' ||
3166 *cur == '\'')
3167 *cur = '_';
3169 uri = xmlParseURI((const char *) tmpval);
3170 xmlFree(tmpval);
3171 if (uri == NULL)
3172 goto return1;
3173 xmlFreeURI(uri);
3176 if (val != NULL) {
3177 v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI);
3178 if (v == NULL)
3179 goto error;
3180 v->value.str = xmlStrdup(value);
3181 *val = v;
3183 goto return0;
3185 case XML_SCHEMAS_HEXBINARY:{
3186 const xmlChar *cur = value, *start;
3187 xmlChar *base;
3188 int total, i = 0;
3190 if (cur == NULL)
3191 goto return1;
3193 if (normOnTheFly)
3194 while IS_WSP_BLANK_CH(*cur) cur++;
3196 start = cur;
3197 while (((*cur >= '0') && (*cur <= '9')) ||
3198 ((*cur >= 'A') && (*cur <= 'F')) ||
3199 ((*cur >= 'a') && (*cur <= 'f'))) {
3200 i++;
3201 cur++;
3203 if (normOnTheFly)
3204 while IS_WSP_BLANK_CH(*cur) cur++;
3206 if (*cur != 0)
3207 goto return1;
3208 if ((i % 2) != 0)
3209 goto return1;
3211 if (val != NULL) {
3213 v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
3214 if (v == NULL)
3215 goto error;
3217 * Copy only the normalized piece.
3218 * CRITICAL TODO: Check this.
3220 cur = xmlStrndup(start, i);
3221 if (cur == NULL) {
3222 xmlSchemaTypeErrMemory(node, "allocating hexbin data");
3223 xmlFree(v);
3224 goto return1;
3227 total = i / 2; /* number of octets */
3229 base = (xmlChar *) cur;
3230 while (i-- > 0) {
3231 if (*base >= 'a')
3232 *base = *base - ('a' - 'A');
3233 base++;
3236 v->value.hex.str = (xmlChar *) cur;
3237 v->value.hex.total = total;
3238 *val = v;
3240 goto return0;
3242 case XML_SCHEMAS_BASE64BINARY:{
3243 /* ISSUE:
3245 * Ignore all stray characters? (yes, currently)
3246 * Worry about long lines? (no, currently)
3248 * rfc2045.txt:
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;
3259 xmlChar *base;
3260 int total, i = 0, pad = 0;
3262 if (cur == NULL)
3263 goto return1;
3265 for (; *cur; ++cur) {
3266 int decc;
3268 decc = _xmlSchemaBase64Decode(*cur);
3269 if (decc < 0) ;
3270 else if (decc < 64)
3271 i++;
3272 else
3273 break;
3275 for (; *cur; ++cur) {
3276 int decc;
3278 decc = _xmlSchemaBase64Decode(*cur);
3279 if (decc < 0) ;
3280 else if (decc < 64)
3281 goto return1;
3282 if (decc == 64)
3283 pad++;
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);
3308 if (pad == 0) {
3309 if (i % 4 != 0)
3310 goto return1;
3311 } else if (pad == 1) {
3312 int decc;
3314 if (i % 4 != 3)
3315 goto return1;
3316 for (decc = _xmlSchemaBase64Decode(*cur);
3317 (decc < 0) || (decc > 63);
3318 decc = _xmlSchemaBase64Decode(*cur))
3319 --cur;
3320 /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
3321 /* 00111100 -> 0x3c */
3322 if (decc & ~0x3c)
3323 goto return1;
3324 total += 2;
3325 } else if (pad == 2) {
3326 int decc;
3328 if (i % 4 != 2)
3329 goto return1;
3330 for (decc = _xmlSchemaBase64Decode(*cur);
3331 (decc < 0) || (decc > 63);
3332 decc = _xmlSchemaBase64Decode(*cur))
3333 --cur;
3334 /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
3335 /* 00110000 -> 0x30 */
3336 if (decc & ~0x30)
3337 goto return1;
3338 total += 1;
3339 } else
3340 goto return1;
3342 if (val != NULL) {
3343 v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
3344 if (v == NULL)
3345 goto error;
3346 base =
3347 (xmlChar *) xmlMallocAtomic(i + pad + 1);
3348 if (base == NULL) {
3349 xmlSchemaTypeErrMemory(node, "allocating base64 data");
3350 xmlFree(v);
3351 goto return1;
3353 v->value.base64.str = base;
3354 for (cur = value; *cur; ++cur)
3355 if (_xmlSchemaBase64Decode(*cur) >= 0) {
3356 *base = *cur;
3357 ++base;
3359 *base = 0;
3360 v->value.base64.total = total;
3361 *val = v;
3363 goto return0;
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;
3372 int sign = 0;
3374 if (cur == NULL)
3375 goto return1;
3376 if (normOnTheFly)
3377 while IS_WSP_BLANK_CH(*cur) cur++;
3378 if (*cur == '-') {
3379 sign = 1;
3380 cur++;
3381 } else if (*cur == '+')
3382 cur++;
3383 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3384 if (ret < 0)
3385 goto return1;
3386 if (normOnTheFly)
3387 while IS_WSP_BLANK_CH(*cur) cur++;
3388 if (*cur != 0)
3389 goto return1;
3390 if (type->builtInType == XML_SCHEMAS_NPINTEGER) {
3391 if ((sign == 0) &&
3392 ((hi != 0) || (mi != 0) || (lo != 0)))
3393 goto return1;
3394 } else if (type->builtInType == XML_SCHEMAS_PINTEGER) {
3395 if (sign == 1)
3396 goto return1;
3397 if ((hi == 0) && (mi == 0) && (lo == 0))
3398 goto return1;
3399 } else if (type->builtInType == XML_SCHEMAS_NINTEGER) {
3400 if (sign == 0)
3401 goto return1;
3402 if ((hi == 0) && (mi == 0) && (lo == 0))
3403 goto return1;
3404 } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) {
3405 if ((sign == 1) &&
3406 ((hi != 0) || (mi != 0) || (lo != 0)))
3407 goto return1;
3409 if (val != NULL) {
3410 v = xmlSchemaNewValue(type->builtInType);
3411 if (v != NULL) {
3412 if (ret == 0)
3413 ret++;
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;
3420 *val = v;
3423 goto return0;
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;
3431 int sign = 0;
3433 if (cur == NULL)
3434 goto return1;
3435 if (normOnTheFly)
3436 while IS_WSP_BLANK_CH(*cur) cur++;
3437 if (*cur == '-') {
3438 sign = 1;
3439 cur++;
3440 } else if (*cur == '+')
3441 cur++;
3442 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3443 if (ret < 0)
3444 goto return1;
3445 if (normOnTheFly)
3446 while IS_WSP_BLANK_CH(*cur) cur++;
3447 if (*cur != 0)
3448 goto return1;
3449 if (type->builtInType == XML_SCHEMAS_LONG) {
3450 if (hi >= 922) {
3451 if (hi > 922)
3452 goto return1;
3453 if (mi >= 33720368) {
3454 if (mi > 33720368)
3455 goto return1;
3456 if ((sign == 0) && (lo > 54775807))
3457 goto return1;
3458 if ((sign == 1) && (lo > 54775808))
3459 goto return1;
3462 } else if (type->builtInType == XML_SCHEMAS_INT) {
3463 if (hi != 0)
3464 goto return1;
3465 if (mi >= 21) {
3466 if (mi > 21)
3467 goto return1;
3468 if ((sign == 0) && (lo > 47483647))
3469 goto return1;
3470 if ((sign == 1) && (lo > 47483648))
3471 goto return1;
3473 } else if (type->builtInType == XML_SCHEMAS_SHORT) {
3474 if ((mi != 0) || (hi != 0))
3475 goto return1;
3476 if ((sign == 1) && (lo > 32768))
3477 goto return1;
3478 if ((sign == 0) && (lo > 32767))
3479 goto return1;
3480 } else if (type->builtInType == XML_SCHEMAS_BYTE) {
3481 if ((mi != 0) || (hi != 0))
3482 goto return1;
3483 if ((sign == 1) && (lo > 128))
3484 goto return1;
3485 if ((sign == 0) && (lo > 127))
3486 goto return1;
3488 if (val != NULL) {
3489 v = xmlSchemaNewValue(type->builtInType);
3490 if (v != NULL) {
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;
3497 *val = v;
3500 goto return0;
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;
3509 if (cur == NULL)
3510 goto return1;
3511 if (normOnTheFly)
3512 while IS_WSP_BLANK_CH(*cur) cur++;
3513 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3514 if (ret < 0)
3515 goto return1;
3516 if (normOnTheFly)
3517 while IS_WSP_BLANK_CH(*cur) cur++;
3518 if (*cur != 0)
3519 goto return1;
3520 if (type->builtInType == XML_SCHEMAS_ULONG) {
3521 if (hi >= 1844) {
3522 if (hi > 1844)
3523 goto return1;
3524 if (mi >= 67440737) {
3525 if (mi > 67440737)
3526 goto return1;
3527 if (lo > 9551615)
3528 goto return1;
3531 } else if (type->builtInType == XML_SCHEMAS_UINT) {
3532 if (hi != 0)
3533 goto return1;
3534 if (mi >= 42) {
3535 if (mi > 42)
3536 goto return1;
3537 if (lo > 94967295)
3538 goto return1;
3540 } else if (type->builtInType == XML_SCHEMAS_USHORT) {
3541 if ((mi != 0) || (hi != 0))
3542 goto return1;
3543 if (lo > 65535)
3544 goto return1;
3545 } else if (type->builtInType == XML_SCHEMAS_UBYTE) {
3546 if ((mi != 0) || (hi != 0))
3547 goto return1;
3548 if (lo > 255)
3549 goto return1;
3551 if (val != NULL) {
3552 v = xmlSchemaNewValue(type->builtInType);
3553 if (v != NULL) {
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;
3560 *val = v;
3563 goto return0;
3567 done:
3568 if (norm != NULL)
3569 xmlFree(norm);
3570 return (ret);
3571 return3:
3572 if (norm != NULL)
3573 xmlFree(norm);
3574 return (3);
3575 return1:
3576 if (norm != NULL)
3577 xmlFree(norm);
3578 return (1);
3579 return0:
3580 if (norm != NULL)
3581 xmlFree(norm);
3582 return (0);
3583 error:
3584 if (norm != NULL)
3585 xmlFree(norm);
3586 return (-1);
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
3657 static int
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)))
3678 order = -1;
3680 * Otherwise (y >= 0) we have the answer
3682 else
3683 return (-1);
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))) {
3691 return (1);
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
3698 * answer.
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.
3712 if (integx == 1) {
3713 if (x->value.decimal.lo == 0) {
3714 if (integy != 1)
3715 return -order;
3716 else if (y->value.decimal.lo != 0)
3717 return -order;
3718 else
3719 return(0);
3722 if (integy == 1) {
3723 if (y->value.decimal.lo == 0) {
3724 if (integx != 1)
3725 return order;
3726 else if (x->value.decimal.lo != 0)
3727 return order;
3728 else
3729 return(0);
3733 if (integx > integy)
3734 return order;
3735 else if (integy > integx)
3736 return -order;
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 */
3748 swp = x;
3749 hi = y->value.decimal.hi;
3750 mi = y->value.decimal.mi;
3751 lo = y->value.decimal.lo;
3752 dlen = -dlen;
3753 order = -order;
3754 } else { /* x has more digits than y */
3755 swp = 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 */
3761 lo = mi;
3762 mi = hi;
3763 hi = 0;
3764 dlen -= 8;
3766 while (dlen > 0) {
3767 unsigned long rem1, rem2;
3768 rem1 = (hi % 10) * 100000000L;
3769 hi = hi / 10;
3770 rem2 = (mi % 10) * 100000000L;
3771 mi = (mi + rem1) / 10;
3772 lo = (lo + rem2) / 10;
3773 dlen--;
3775 if (hi > swp->value.decimal.hi) {
3776 return order;
3777 } else if (hi == swp->value.decimal.hi) {
3778 if (mi > swp->value.decimal.mi) {
3779 return order;
3780 } else if (mi == swp->value.decimal.mi) {
3781 if (lo > swp->value.decimal.lo) {
3782 return order;
3783 } else if (lo == swp->value.decimal.lo) {
3784 if (x->value.decimal.total == y->value.decimal.total) {
3785 return 0;
3786 } else {
3787 return order;
3792 return -order;
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
3803 * case of error
3805 static int
3806 xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
3808 long carry, mon, day;
3809 double sec;
3810 int invert = 1;
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))
3817 return -2;
3819 /* months */
3820 mon = x->value.dur.mon - y->value.dur.mon;
3822 /* seconds */
3823 sec = x->value.dur.sec - y->value.dur.sec;
3824 carry = (long)(sec / SECS_PER_DAY);
3825 sec -= ((double)carry) * SECS_PER_DAY;
3827 /* days */
3828 day = x->value.dur.day - y->value.dur.day + carry;
3830 /* easy test */
3831 if (mon == 0) {
3832 if (day == 0)
3833 if (sec == 0.0)
3834 return 0;
3835 else if (sec < 0.0)
3836 return -1;
3837 else
3838 return 1;
3839 else if (day < 0)
3840 return -1;
3841 else
3842 return 1;
3845 if (mon > 0) {
3846 if ((day >= 0) && (sec >= 0.0))
3847 return 1;
3848 else {
3849 xmon = mon;
3850 xday = -day;
3852 } else if ((day <= 0) && (sec <= 0.0)) {
3853 return -1;
3854 } else {
3855 invert = -1;
3856 xmon = -mon;
3857 xday = day;
3860 myear = xmon / 12;
3861 if (myear == 0) {
3862 minday = 0;
3863 maxday = 0;
3864 } else {
3865 if (myear > LONG_MAX / 366)
3866 return -2;
3867 /* FIXME: This doesn't take leap year exceptions every 100/400 years
3868 into account. */
3869 maxday = 365 * myear + (myear + 3) / 4;
3870 /* FIXME: Needs to be calculated separately */
3871 minday = maxday - 1;
3874 xmon = xmon % 12;
3875 minday += dayRange[0][xmon];
3876 maxday += dayRange[1][xmon];
3878 if ((maxday == minday) && (maxday == xday))
3879 return(0); /* can this really happen ? */
3880 if (maxday < xday)
3881 return(-invert);
3882 if (minday > xday)
3883 return(invert);
3885 /* indeterminate */
3886 return 2;
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)
3898 * xmlSchemaDupVal:
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);
3910 if (ret == NULL)
3911 return NULL;
3913 memcpy(ret, v, sizeof(xmlSchemaVal));
3914 ret->next = NULL;
3915 return ret;
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.
3926 xmlSchemaValPtr
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);
3941 return (NULL);
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);
3957 break;
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);
3967 break;
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);
3972 break;
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);
3978 break;
3979 default:
3980 cur = xmlSchemaDupVal(val);
3981 break;
3983 if (ret == NULL)
3984 ret = cur;
3985 else
3986 prev->next = cur;
3987 prev = cur;
3988 val = val->next;
3990 return (ret);
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))
4014 return NULL;
4016 ret = xmlSchemaNewValue(dt->type);
4017 if (ret == NULL)
4018 return NULL;
4020 /* make a copy so we don't alter the original value */
4021 tmp = xmlSchemaDupVal(dt);
4022 if (tmp == NULL) {
4023 xmlSchemaFreeValue(ret);
4024 return NULL;
4027 r = &(ret->value.date);
4028 d = &(tmp->value.date);
4029 u = &(dur->value.dur);
4031 /* normalization */
4032 if (d->mon == 0)
4033 d->mon = 1;
4035 /* normalize for time zone offset */
4036 u->sec -= (d->tzo * 60);
4037 d->tzo = 0;
4039 /* normalization */
4040 if (d->day == 0)
4041 d->day = 1;
4043 /* month */
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;
4050 if (r->year == 0) {
4051 if (d->year > 0)
4052 r->year--;
4053 else
4054 r->year++;
4057 /* time zone */
4058 r->tzo = d->tzo;
4059 r->tz_flag = d->tz_flag;
4061 /* seconds */
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);
4068 /* minute */
4069 carry += d->min;
4070 r->min = (unsigned int) MODULO(carry, 60);
4071 carry = (long) FQUOTIENT(carry, 60);
4073 /* hours */
4074 carry += d->hour;
4075 r->hour = (unsigned int) MODULO(carry, 24);
4076 carry = (long)FQUOTIENT(carry, 24);
4079 * days
4080 * Note we use tempdays because the temporary values may need more
4081 * than 5 bits
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)
4087 tempdays = 1;
4088 else
4089 tempdays = d->day;
4091 tempdays += u->day + carry;
4093 while (1) {
4094 if (tempdays < 1) {
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);
4097 if (tyr == 0)
4098 tyr--;
4100 * Coverity detected an overrun in daysInMonth
4101 * of size 12 at position 12 with index variable "((r)->mon - 1)"
4103 if (tmon < 1)
4104 tmon = 1;
4105 if (tmon > 12)
4106 tmon = 12;
4107 tempdays += MAX_DAYINMONTH(tyr, tmon);
4108 carry = -1;
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);
4112 carry = 1;
4113 } else
4114 break;
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);
4119 if (r->year == 0) {
4120 if (temp < 1)
4121 r->year--;
4122 else
4123 r->year++;
4127 r->day = tempdays;
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);
4145 return ret;
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;
4163 if (dt == NULL)
4164 return NULL;
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);
4172 if (dur == NULL)
4173 return NULL;
4175 dur->value.date.sec -= offset;
4177 ret = _xmlSchemaDateAdd(dt, dur);
4178 if (ret == NULL)
4179 return NULL;
4181 xmlSchemaFreeValue(dur);
4183 /* ret->value.date.tzo = 0; */
4184 return ret;
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.
4198 static long
4199 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
4201 long ret;
4202 int mon;
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);
4212 else
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);
4218 return ret;
4222 * TIME_TO_NUMBER:
4223 * @dt: an #xmlSchemaValPtr
4225 * Calculates the number of seconds in the time portion of @dt.
4227 * Returns seconds.
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)) + \
4233 dt->value.date.sec)
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
4243 * case of error
4245 static int
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))
4253 return -2;
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. */
4260 return -2;
4263 if (x->value.date.tz_flag) {
4265 if (!y->value.date.tz_flag) {
4266 p1 = xmlSchemaDateNormalize(x, 0);
4267 if (p1 == NULL)
4268 return -2;
4269 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4270 /* normalize y + 14:00 */
4271 q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
4272 if (q1 == NULL) {
4273 xmlSchemaFreeValue(p1);
4274 return -2;
4277 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4278 if (p1d < q1d) {
4279 xmlSchemaFreeValue(p1);
4280 xmlSchemaFreeValue(q1);
4281 return -1;
4282 } else if (p1d == q1d) {
4283 double sec;
4285 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4286 if (sec < 0.0) {
4287 xmlSchemaFreeValue(p1);
4288 xmlSchemaFreeValue(q1);
4289 return -1;
4290 } else {
4291 int ret = 0;
4292 /* normalize y - 14:00 */
4293 q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
4294 if (q2 == NULL) {
4295 xmlSchemaFreeValue(p1);
4296 xmlSchemaFreeValue(q1);
4297 return -2;
4299 q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
4300 if (p1d > q2d)
4301 ret = 1;
4302 else if (p1d == q2d) {
4303 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
4304 if (sec > 0.0)
4305 ret = 1;
4306 else
4307 ret = 2; /* indeterminate */
4309 xmlSchemaFreeValue(p1);
4310 xmlSchemaFreeValue(q1);
4311 xmlSchemaFreeValue(q2);
4312 if (ret != 0)
4313 return(ret);
4315 } else {
4316 xmlSchemaFreeValue(p1);
4317 xmlSchemaFreeValue(q1);
4320 } else if (y->value.date.tz_flag) {
4321 q1 = xmlSchemaDateNormalize(y, 0);
4322 if (q1 == NULL)
4323 return -2;
4324 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4326 /* normalize x - 14:00 */
4327 p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
4328 if (p1 == NULL) {
4329 xmlSchemaFreeValue(q1);
4330 return -2;
4332 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4334 if (p1d < q1d) {
4335 xmlSchemaFreeValue(p1);
4336 xmlSchemaFreeValue(q1);
4337 return -1;
4338 } else if (p1d == q1d) {
4339 double sec;
4341 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4342 if (sec < 0.0) {
4343 xmlSchemaFreeValue(p1);
4344 xmlSchemaFreeValue(q1);
4345 return -1;
4346 } else {
4347 int ret = 0;
4348 /* normalize x + 14:00 */
4349 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
4350 if (p2 == NULL) {
4351 xmlSchemaFreeValue(p1);
4352 xmlSchemaFreeValue(q1);
4353 return -2;
4355 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
4357 if (p2d > q1d) {
4358 ret = 1;
4359 } else if (p2d == q1d) {
4360 sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
4361 if (sec > 0.0)
4362 ret = 1;
4363 else
4364 ret = 2; /* indeterminate */
4366 xmlSchemaFreeValue(p1);
4367 xmlSchemaFreeValue(q1);
4368 xmlSchemaFreeValue(p2);
4369 if (ret != 0)
4370 return(ret);
4372 } else {
4373 xmlSchemaFreeValue(p1);
4374 xmlSchemaFreeValue(q1);
4379 * if the same type then calculate the difference
4381 if (x->type == y->type) {
4382 int ret = 0;
4383 q1 = xmlSchemaDateNormalize(y, 0);
4384 if (q1 == NULL)
4385 return -2;
4386 q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4388 p1 = xmlSchemaDateNormalize(x, 0);
4389 if (p1 == NULL) {
4390 xmlSchemaFreeValue(q1);
4391 return -2;
4393 p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4395 if (p1d < q1d) {
4396 ret = -1;
4397 } else if (p1d > q1d) {
4398 ret = 1;
4399 } else {
4400 double sec;
4402 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4403 if (sec < 0.0)
4404 ret = -1;
4405 else if (sec > 0.0)
4406 ret = 1;
4409 xmlSchemaFreeValue(p1);
4410 xmlSchemaFreeValue(q1);
4411 return(ret);
4414 switch (x->type) {
4415 case XML_SCHEMAS_DATETIME:
4416 xmask = 0xf;
4417 break;
4418 case XML_SCHEMAS_DATE:
4419 xmask = 0x7;
4420 break;
4421 case XML_SCHEMAS_GYEAR:
4422 xmask = 0x1;
4423 break;
4424 case XML_SCHEMAS_GMONTH:
4425 xmask = 0x2;
4426 break;
4427 case XML_SCHEMAS_GDAY:
4428 xmask = 0x3;
4429 break;
4430 case XML_SCHEMAS_GYEARMONTH:
4431 xmask = 0x3;
4432 break;
4433 case XML_SCHEMAS_GMONTHDAY:
4434 xmask = 0x6;
4435 break;
4436 case XML_SCHEMAS_TIME:
4437 xmask = 0x8;
4438 break;
4439 default:
4440 xmask = 0;
4441 break;
4444 switch (y->type) {
4445 case XML_SCHEMAS_DATETIME:
4446 ymask = 0xf;
4447 break;
4448 case XML_SCHEMAS_DATE:
4449 ymask = 0x7;
4450 break;
4451 case XML_SCHEMAS_GYEAR:
4452 ymask = 0x1;
4453 break;
4454 case XML_SCHEMAS_GMONTH:
4455 ymask = 0x2;
4456 break;
4457 case XML_SCHEMAS_GDAY:
4458 ymask = 0x3;
4459 break;
4460 case XML_SCHEMAS_GYEARMONTH:
4461 ymask = 0x3;
4462 break;
4463 case XML_SCHEMAS_GMONTHDAY:
4464 ymask = 0x6;
4465 break;
4466 case XML_SCHEMAS_TIME:
4467 ymask = 0x8;
4468 break;
4469 default:
4470 ymask = 0;
4471 break;
4474 xor_mask = xmask ^ ymask; /* mark type differences */
4475 and_mask = xmask & ymask; /* mark field specification */
4477 /* year */
4478 if (xor_mask & 1)
4479 return 2; /* indeterminate */
4480 else if (and_mask & 1) {
4481 if (x->value.date.year < y->value.date.year)
4482 return -1;
4483 else if (x->value.date.year > y->value.date.year)
4484 return 1;
4487 /* month */
4488 if (xor_mask & 2)
4489 return 2; /* indeterminate */
4490 else if (and_mask & 2) {
4491 if (x->value.date.mon < y->value.date.mon)
4492 return -1;
4493 else if (x->value.date.mon > y->value.date.mon)
4494 return 1;
4497 /* day */
4498 if (xor_mask & 4)
4499 return 2; /* indeterminate */
4500 else if (and_mask & 4) {
4501 if (x->value.date.day < y->value.date.day)
4502 return -1;
4503 else if (x->value.date.day > y->value.date.day)
4504 return 1;
4507 /* time */
4508 if (xor_mask & 8)
4509 return 2; /* indeterminate */
4510 else if (and_mask & 8) {
4511 if (x->value.date.hour < y->value.date.hour)
4512 return -1;
4513 else if (x->value.date.hour > y->value.date.hour)
4514 return 1;
4515 else if (x->value.date.min < y->value.date.min)
4516 return -1;
4517 else if (x->value.date.min > y->value.date.min)
4518 return 1;
4519 else if (x->value.date.sec < y->value.date.sec)
4520 return -1;
4521 else if (x->value.date.sec > y->value.date.sec)
4522 return 1;
4525 return 0;
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
4540 * case of error
4542 static int
4543 xmlSchemaComparePreserveReplaceStrings(const xmlChar *x,
4544 const xmlChar *y,
4545 int invert)
4547 int tmp;
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) {
4553 if (invert)
4554 return(1);
4555 else
4556 return(-1);
4557 } else {
4558 if (invert)
4559 return(-1);
4560 else
4561 return(1);
4564 } else {
4565 tmp = *x - *y;
4566 if (tmp < 0) {
4567 if (invert)
4568 return(1);
4569 else
4570 return(-1);
4572 if (tmp > 0) {
4573 if (invert)
4574 return(-1);
4575 else
4576 return(1);
4579 x++;
4580 y++;
4582 if (*x != 0) {
4583 if (invert)
4584 return(-1);
4585 else
4586 return(1);
4588 if (*y != 0) {
4589 if (invert)
4590 return(1);
4591 else
4592 return(-1);
4594 return(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
4608 * case of error
4610 static int
4611 xmlSchemaComparePreserveCollapseStrings(const xmlChar *x,
4612 const xmlChar *y,
4613 int invert)
4615 int tmp;
4618 * Skip leading blank chars of the collapsed string.
4620 while IS_WSP_BLANK_CH(*y)
4621 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) {
4630 if (invert)
4631 return(1);
4632 else
4633 return(-1);
4634 } else {
4635 if (invert)
4636 return(-1);
4637 else
4638 return(1);
4641 x++;
4642 y++;
4644 * Skip contiguous blank chars of the collapsed string.
4646 while IS_WSP_BLANK_CH(*y)
4647 y++;
4648 } else {
4649 tmp = *x++ - *y++;
4650 if (tmp < 0) {
4651 if (invert)
4652 return(1);
4653 else
4654 return(-1);
4656 if (tmp > 0) {
4657 if (invert)
4658 return(-1);
4659 else
4660 return(1);
4664 if (*x != 0) {
4665 if (invert)
4666 return(-1);
4667 else
4668 return(1);
4670 if (*y != 0) {
4672 * Skip trailing blank chars of the collapsed string.
4674 while IS_WSP_BLANK_CH(*y)
4675 y++;
4676 if (*y != 0) {
4677 if (invert)
4678 return(1);
4679 else
4680 return(-1);
4683 return(0);
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
4697 * case of error
4699 static int
4700 xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x,
4701 const xmlChar *y,
4702 int invert)
4704 int tmp;
4707 * Skip leading blank chars of the collapsed string.
4709 while IS_WSP_BLANK_CH(*y)
4710 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) {
4719 if (invert)
4720 return(1);
4721 else
4722 return(-1);
4723 } else {
4724 if (invert)
4725 return(-1);
4726 else
4727 return(1);
4730 x++;
4731 y++;
4733 * Skip contiguous blank chars of the collapsed string.
4735 while IS_WSP_BLANK_CH(*y)
4736 y++;
4737 } else {
4738 if IS_WSP_BLANK_CH(*x) {
4740 * The xv character would have been replaced to 0x20.
4742 if ((0x20 - *y) < 0) {
4743 if (invert)
4744 return(1);
4745 else
4746 return(-1);
4747 } else {
4748 if (invert)
4749 return(-1);
4750 else
4751 return(1);
4754 tmp = *x++ - *y++;
4755 if (tmp < 0)
4756 return(-1);
4757 if (tmp > 0)
4758 return(1);
4761 if (*x != 0) {
4762 if (invert)
4763 return(-1);
4764 else
4765 return(1);
4767 if (*y != 0) {
4769 * Skip trailing blank chars of the collapsed string.
4771 while IS_WSP_BLANK_CH(*y)
4772 y++;
4773 if (*y != 0) {
4774 if (invert)
4775 return(1);
4776 else
4777 return(-1);
4780 return(0);
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
4792 * case of error
4794 static int
4795 xmlSchemaCompareReplacedStrings(const xmlChar *x,
4796 const xmlChar *y)
4798 int tmp;
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)
4804 return(-1);
4805 else
4806 return(1);
4808 } else {
4809 if IS_WSP_BLANK_CH(*x) {
4810 if ((0x20 - *y) < 0)
4811 return(-1);
4812 else
4813 return(1);
4815 tmp = *x - *y;
4816 if (tmp < 0)
4817 return(-1);
4818 if (tmp > 0)
4819 return(1);
4821 x++;
4822 y++;
4824 if (*x != 0)
4825 return(1);
4826 if (*y != 0)
4827 return(-1);
4828 return(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
4839 * case of error
4841 static int
4842 xmlSchemaCompareNormStrings(const xmlChar *x,
4843 const xmlChar *y) {
4844 int tmp;
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)) {
4851 tmp = *x - *y;
4852 return(tmp);
4854 while (IS_BLANK_CH(*x)) x++;
4855 while (IS_BLANK_CH(*y)) y++;
4856 } else {
4857 tmp = *x++ - *y++;
4858 if (tmp < 0)
4859 return(-1);
4860 if (tmp > 0)
4861 return(1);
4864 if (*x != 0) {
4865 while (IS_BLANK_CH(*x)) x++;
4866 if (*x != 0)
4867 return(1);
4869 if (*y != 0) {
4870 while (IS_BLANK_CH(*y)) y++;
4871 if (*y != 0)
4872 return(-1);
4874 return(0);
4878 * xmlSchemaCompareFloats:
4879 * @x: a first float or double value
4880 * @y: a second float or double value
4882 * Compare 2 values
4884 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4885 * case of error
4887 static int
4888 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
4889 double d1, d2;
4891 if ((x == NULL) || (y == NULL))
4892 return(-2);
4895 * Cast everything to doubles.
4897 if (x->type == XML_SCHEMAS_DOUBLE)
4898 d1 = x->value.d;
4899 else if (x->type == XML_SCHEMAS_FLOAT)
4900 d1 = x->value.f;
4901 else
4902 return(-2);
4904 if (y->type == XML_SCHEMAS_DOUBLE)
4905 d2 = y->value.d;
4906 else if (y->type == XML_SCHEMAS_FLOAT)
4907 d2 = y->value.f;
4908 else
4909 return(-2);
4912 * Check for special cases.
4914 if (xmlXPathIsNaN(d1)) {
4915 if (xmlXPathIsNaN(d2))
4916 return(0);
4917 return(1);
4919 if (xmlXPathIsNaN(d2))
4920 return(-1);
4921 if (d1 == xmlXPathPINF) {
4922 if (d2 == xmlXPathPINF)
4923 return(0);
4924 return(1);
4926 if (d2 == xmlXPathPINF)
4927 return(-1);
4928 if (d1 == xmlXPathNINF) {
4929 if (d2 == xmlXPathNINF)
4930 return(0);
4931 return(-1);
4933 if (d2 == xmlXPathNINF)
4934 return(1);
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 ...
4941 if (d1 < d2)
4942 return(-1);
4943 if (d1 > d2)
4944 return(1);
4945 if (d1 == d2)
4946 return(0);
4947 return(2);
4951 * xmlSchemaCompareValues:
4952 * @x: a first value
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
4959 * Compare 2 values
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
4964 static int
4965 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
4966 xmlSchemaValPtr x,
4967 const xmlChar *xvalue,
4968 xmlSchemaWhitespaceValueType xws,
4969 xmlSchemaValType ytype,
4970 xmlSchemaValPtr y,
4971 const xmlChar *yvalue,
4972 xmlSchemaWhitespaceValueType yws)
4974 switch (xtype) {
4975 case XML_SCHEMAS_UNKNOWN:
4976 case XML_SCHEMAS_ANYTYPE:
4977 return(-2);
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))
4993 return(-2);
4994 if (ytype == xtype)
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));
5011 return(-2);
5012 case XML_SCHEMAS_DURATION:
5013 if ((x == NULL) || (y == NULL))
5014 return(-2);
5015 if (ytype == XML_SCHEMAS_DURATION)
5016 return(xmlSchemaCompareDurations(x, y));
5017 return(-2);
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))
5027 return(-2);
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));
5037 return (-2);
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;
5057 if (x == NULL)
5058 xv = xvalue;
5059 else
5060 xv = x->value.str;
5061 if (y == NULL)
5062 yv = yvalue;
5063 else
5064 yv = y->value.str;
5066 * TODO: Compare those against QName.
5068 if (ytype == XML_SCHEMAS_QNAME) {
5069 TODO
5070 if (y == NULL)
5071 return(-2);
5072 return (-2);
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))
5092 return (0);
5093 else
5094 return (2);
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));
5117 } else
5118 return (-2);
5121 return (-2);
5123 case XML_SCHEMAS_QNAME:
5124 case XML_SCHEMAS_NOTATION:
5125 if ((x == NULL) || (y == NULL))
5126 return(-2);
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)))
5131 return(0);
5132 return(2);
5134 return (-2);
5135 case XML_SCHEMAS_FLOAT:
5136 case XML_SCHEMAS_DOUBLE:
5137 if ((x == NULL) || (y == NULL))
5138 return(-2);
5139 if ((ytype == XML_SCHEMAS_FLOAT) ||
5140 (ytype == XML_SCHEMAS_DOUBLE))
5141 return (xmlSchemaCompareFloats(x, y));
5142 return (-2);
5143 case XML_SCHEMAS_BOOLEAN:
5144 if ((x == NULL) || (y == NULL))
5145 return(-2);
5146 if (ytype == XML_SCHEMAS_BOOLEAN) {
5147 if (x->value.b == y->value.b)
5148 return(0);
5149 if (x->value.b == 0)
5150 return(-1);
5151 return(1);
5153 return (-2);
5154 case XML_SCHEMAS_HEXBINARY:
5155 if ((x == NULL) || (y == NULL))
5156 return(-2);
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);
5160 if (ret > 0)
5161 return(1);
5162 else if (ret == 0)
5163 return(0);
5165 else if (x->value.hex.total > y->value.hex.total)
5166 return(1);
5168 return(-1);
5170 return (-2);
5171 case XML_SCHEMAS_BASE64BINARY:
5172 if ((x == NULL) || (y == NULL))
5173 return(-2);
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);
5178 if (ret > 0)
5179 return(1);
5180 else if (ret == 0)
5181 return(0);
5182 else
5183 return(-1);
5185 else if (x->value.base64.total > y->value.base64.total)
5186 return(1);
5187 else
5188 return(-1);
5190 return (-2);
5191 case XML_SCHEMAS_IDREFS:
5192 case XML_SCHEMAS_ENTITIES:
5193 case XML_SCHEMAS_NMTOKENS:
5194 TODO
5195 break;
5197 return -2;
5201 * xmlSchemaCompareValues:
5202 * @x: a first value
5203 * @y: a second value
5205 * Compare 2 values
5207 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5208 * case of error
5211 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
5212 xmlSchemaWhitespaceValueType xws, yws;
5214 if ((x == NULL) || (y == NULL))
5215 return(-2);
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;
5220 else
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;
5227 else
5228 yws = XML_SCHEMA_WHITESPACE_COLLAPSE;
5230 return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
5231 y, NULL, yws));
5235 * xmlSchemaCompareValuesWhtsp:
5236 * @x: a first value
5237 * @xws: the whitespace value of x
5238 * @y: a second value
5239 * @yws: the whitespace value of y
5241 * Compare 2 values
5243 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5244 * case of error
5247 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,
5248 xmlSchemaWhitespaceValueType xws,
5249 xmlSchemaValPtr y,
5250 xmlSchemaWhitespaceValueType yws)
5252 if ((x == NULL) || (y == NULL))
5253 return(-2);
5254 return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
5255 y, NULL, yws));
5259 * xmlSchemaCompareValuesWhtspExt:
5260 * @x: a first value
5261 * @xws: the whitespace value of x
5262 * @y: a second value
5263 * @yws: the whitespace value of y
5265 * Compare 2 values
5267 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5268 * case of error
5270 static int
5271 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,
5272 xmlSchemaValPtr x,
5273 const xmlChar *xvalue,
5274 xmlSchemaWhitespaceValueType xws,
5275 xmlSchemaValType ytype,
5276 xmlSchemaValPtr y,
5277 const xmlChar *yvalue,
5278 xmlSchemaWhitespaceValueType yws)
5280 return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y,
5281 yvalue, yws));
5285 * xmlSchemaNormLen:
5286 * @value: a string
5288 * Computes the UTF8 length of the normalized value of the string
5290 * Returns the length or -1 in case of error.
5292 static int
5293 xmlSchemaNormLen(const xmlChar *value) {
5294 const xmlChar *utf;
5295 int ret = 0;
5297 if (value == NULL)
5298 return(-1);
5299 utf = value;
5300 while (IS_BLANK_CH(*utf)) utf++;
5301 while (*utf != 0) {
5302 if (utf[0] & 0x80) {
5303 if ((utf[1] & 0xc0) != 0x80)
5304 return(-1);
5305 if ((utf[0] & 0xe0) == 0xe0) {
5306 if ((utf[2] & 0xc0) != 0x80)
5307 return(-1);
5308 if ((utf[0] & 0xf0) == 0xf0) {
5309 if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
5310 return(-1);
5311 utf += 4;
5312 } else {
5313 utf += 3;
5315 } else {
5316 utf += 2;
5318 } else if (IS_BLANK_CH(*utf)) {
5319 while (IS_BLANK_CH(*utf)) utf++;
5320 if (*utf == 0)
5321 break;
5322 } else {
5323 utf++;
5325 ret++;
5327 return(ret);
5331 * xmlSchemaGetFacetValueAsULong:
5332 * @facet: an schemas type facet
5334 * Extract the value of a facet
5336 * Returns the value as a long
5338 unsigned long
5339 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
5342 * TODO: Check if this is a decimal.
5344 if (facet == NULL || facet->val == NULL)
5345 return 0;
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)
5367 if (facet == NULL)
5368 return(-1);
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);
5391 } else
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));
5398 return (0);
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.
5416 static int
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))
5427 return (-1);
5428 *length = 0;
5429 if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
5430 (facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
5431 (facet->type != XML_SCHEMA_FACET_MINLENGTH))
5432 return (-1);
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)) {
5442 return(-1);
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;
5448 else {
5449 switch (valType) {
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);
5461 else
5462 len = xmlSchemaNormLen(value);
5463 } else if (value != NULL) {
5464 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5465 len = xmlSchemaNormLen(value);
5466 else
5468 * Should be OK for "preserve" as well.
5470 len = xmlUTF8Strlen(value);
5472 break;
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:
5484 if (value != NULL)
5485 len = xmlSchemaNormLen(value);
5486 break;
5487 case XML_SCHEMAS_QNAME:
5488 case XML_SCHEMAS_NOTATION:
5490 * For QName and NOTATION, those facets are
5491 * deprecated and should be ignored.
5493 return (0);
5494 default:
5495 TODO
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);
5508 } else {
5509 if (len > facet->val->value.decimal.lo)
5510 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5513 return (0);
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)
5537 if (type == NULL)
5538 return(-1);
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,
5568 length, ws));
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.
5585 static int
5586 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
5587 xmlSchemaWhitespaceValueType fws,
5588 xmlSchemaValType valType,
5589 const xmlChar *value,
5590 xmlSchemaValPtr val,
5591 xmlSchemaWhitespaceValueType ws)
5593 int ret;
5595 if (facet == NULL)
5596 return(-1);
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.
5604 if (value == NULL)
5605 return(-1);
5607 * If string-derived type, regexp must be tested on the value space of
5608 * the datatype.
5609 * See https://www.w3.org/TR/xmlschema-2/#rf-pattern
5611 if (val &&
5612 val->value.str &&
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);
5621 if (ret == 1)
5622 return(0);
5623 if (ret == 0)
5624 return(XML_SCHEMAV_CVC_PATTERN_VALID);
5625 return(ret);
5626 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5627 ret = xmlSchemaCompareValues(val, facet->val);
5628 if (ret == -2)
5629 return(-1);
5630 if (ret == -1)
5631 return(0);
5632 return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID);
5633 case XML_SCHEMA_FACET_MAXINCLUSIVE:
5634 ret = xmlSchemaCompareValues(val, facet->val);
5635 if (ret == -2)
5636 return(-1);
5637 if ((ret == -1) || (ret == 0))
5638 return(0);
5639 return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID);
5640 case XML_SCHEMA_FACET_MINEXCLUSIVE:
5641 ret = xmlSchemaCompareValues(val, facet->val);
5642 if (ret == -2)
5643 return(-1);
5644 if (ret == 1)
5645 return(0);
5646 return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID);
5647 case XML_SCHEMA_FACET_MININCLUSIVE:
5648 ret = xmlSchemaCompareValues(val, facet->val);
5649 if (ret == -2)
5650 return(-1);
5651 if ((ret == 1) || (ret == 0))
5652 return(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.
5661 return(0);
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)))
5671 return(0);
5672 } else {
5673 ret = xmlSchemaCompareValuesWhtspExt(facet->val->type,
5674 facet->val, facet->value, fws, valType, val,
5675 value, ws);
5676 if (ret == -2)
5677 return(-1);
5678 if (ret == 0)
5679 return(0);
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))
5689 return (0);
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))
5697 return (0);
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)) {
5706 return(-1);
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;
5712 else {
5713 switch (valType) {
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);
5725 else
5726 len = xmlSchemaNormLen(value);
5727 } else if (value != NULL) {
5728 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5729 len = xmlSchemaNormLen(value);
5730 else
5732 * Should be OK for "preserve" as well.
5734 len = xmlUTF8Strlen(value);
5736 break;
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:
5745 if (value != NULL)
5746 len = xmlSchemaNormLen(value);
5747 break;
5748 default:
5749 TODO
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);
5758 } else {
5759 if (len > facet->val->value.decimal.lo)
5760 return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5762 break;
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)) {
5771 return(-1);
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))) {
5788 return(-1);
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);
5798 break;
5799 default:
5800 TODO
5802 return(0);
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().
5829 if (val != NULL)
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));
5837 return(-1);
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,
5866 value, val, ws));
5869 #if 0
5870 #ifndef DBL_DIG
5871 #define DBL_DIG 16
5872 #endif
5873 #ifndef DBL_EPSILON
5874 #define DBL_EPSILON 1E-9
5875 #endif
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.
5889 static void
5890 xmlSchemaFormatFloat(double number, char buffer[], int buffersize)
5892 switch (xmlXPathIsInf(number)) {
5893 case 1:
5894 if (buffersize > (int)sizeof("INF"))
5895 snprintf(buffer, buffersize, "INF");
5896 break;
5897 case -1:
5898 if (buffersize > (int)sizeof("-INF"))
5899 snprintf(buffer, buffersize, "-INF");
5900 break;
5901 default:
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");
5907 } else {
5908 /* 3 is sign, decimal point, and terminating zero */
5909 char work[DBL_DIG + EXPONENT_DIGITS + 3];
5910 int integer_place, fraction_place;
5911 char *ptr;
5912 char *after_fraction;
5913 double absolute_value;
5914 int size;
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')
5932 if (*ptr != '.')
5933 ptr++;
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;
5940 size = buffersize;
5942 memmove(buffer, work, size);
5944 break;
5947 #endif
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))
5972 return (-1);
5973 *retValue = NULL;
5974 switch (val->type) {
5975 case XML_SCHEMAS_STRING:
5976 if (val->value.str == NULL)
5977 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5978 else
5979 *retValue =
5980 BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5981 break;
5982 case XML_SCHEMAS_NORMSTRING:
5983 if (val->value.str == NULL)
5984 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5985 else {
5986 *retValue = xmlSchemaWhiteSpaceReplace(
5987 (const xmlChar *) val->value.str);
5988 if ((*retValue) == NULL)
5989 *retValue = BAD_CAST xmlStrdup(
5990 (const xmlChar *) val->value.str);
5992 break;
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)
6004 return (-1);
6005 *retValue =
6006 BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str);
6007 if (*retValue == NULL)
6008 *retValue =
6009 BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
6010 break;
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);
6015 return (0);
6016 } else {
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),
6021 BAD_CAST "}");
6022 *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
6023 BAD_CAST val->value.qname.uri);
6025 break;
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");
6033 } else {
6034 xmlSchemaValDecimal dec = val->value.decimal;
6035 int bufsize;
6036 char *buf = NULL, *offs;
6038 /* Add room for the decimal point as well. */
6039 bufsize = dec.total + 2;
6040 if (dec.sign)
6041 bufsize++;
6042 /* Add room for leading/trailing zero. */
6043 if ((dec.frac == 0) || (dec.frac == dec.total))
6044 bufsize++;
6045 buf = xmlMalloc(bufsize);
6046 if (buf == NULL)
6047 return(-1);
6048 offs = buf;
6049 if (dec.sign)
6050 *offs++ = '-';
6051 if (dec.frac == dec.total) {
6052 *offs++ = '0';
6053 *offs++ = '.';
6055 if (dec.hi != 0)
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);
6061 else
6062 snprintf(offs, bufsize - (offs - buf),
6063 "%lu", dec.lo);
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);
6072 offs[diff] = '.';
6073 } else {
6074 unsigned int i = 0;
6076 * Insert missing zeroes behind the decimal point.
6078 while (*(offs + i) != 0)
6079 i++;
6080 if (i < dec.total) {
6081 memmove(offs + (dec.total - i), offs, i +1);
6082 memset(offs, '0', dec.total - i);
6085 } else {
6087 * Append decimal point and zero.
6089 offs = buf + bufsize - 1;
6090 *offs-- = 0;
6091 *offs-- = '0';
6092 *offs-- = '.';
6094 *retValue = BAD_CAST buf;
6096 break;
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");
6113 else {
6114 xmlSchemaValDecimal dec = val->value.decimal;
6115 int bufsize = dec.total + 1;
6117 /* Add room for the decimal point as well. */
6118 if (dec.sign)
6119 bufsize++;
6120 *retValue = xmlMalloc(bufsize);
6121 if (*retValue == NULL)
6122 return(-1);
6123 if (dec.hi != 0) {
6124 if (dec.sign)
6125 snprintf((char *) *retValue, bufsize,
6126 "-%lu%lu%lu", dec.hi, dec.mi, dec.lo);
6127 else
6128 snprintf((char *) *retValue, bufsize,
6129 "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
6130 } else if (dec.mi != 0) {
6131 if (dec.sign)
6132 snprintf((char *) *retValue, bufsize,
6133 "-%lu%lu", dec.mi, dec.lo);
6134 else
6135 snprintf((char *) *retValue, bufsize,
6136 "%lu%lu", dec.mi, dec.lo);
6137 } else {
6138 if (dec.sign)
6139 snprintf((char *) *retValue, bufsize, "-%lu", dec.lo);
6140 else
6141 snprintf((char *) *retValue, bufsize, "%lu", dec.lo);
6144 break;
6145 case XML_SCHEMAS_BOOLEAN:
6146 if (val->value.b)
6147 *retValue = BAD_CAST xmlStrdup(BAD_CAST "true");
6148 else
6149 *retValue = BAD_CAST xmlStrdup(BAD_CAST "false");
6150 break;
6151 case XML_SCHEMAS_DURATION: {
6152 char buf[100];
6153 unsigned long year;
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;
6170 if (left > 0) {
6171 hour = (unsigned long) FQUOTIENT(left, 3600);
6172 left = left - (hour * 3600);
6173 if (left > 0) {
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);
6181 else
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);
6186 break;
6187 case XML_SCHEMAS_GYEAR: {
6188 char buf[30];
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);
6194 break;
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)
6200 return(-1);
6201 snprintf((char *) *retValue, 6, "--%02u",
6202 val->value.date.mon);
6204 break;
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)
6210 return(-1);
6211 snprintf((char *) *retValue, 6, "---%02u",
6212 val->value.date.day);
6214 break;
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)
6220 return(-1);
6221 snprintf((char *) *retValue, 8, "--%02u-%02u",
6222 val->value.date.mon, val->value.date.day);
6224 break;
6225 case XML_SCHEMAS_GYEARMONTH: {
6226 char buf[35];
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);
6233 else
6234 snprintf(buf, 35, "%04ld-%02u",
6235 val->value.date.year, val->value.date.mon);
6236 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6238 break;
6239 case XML_SCHEMAS_TIME:
6241 char buf[30];
6243 if (val->value.date.tz_flag) {
6244 xmlSchemaValPtr norm;
6246 norm = xmlSchemaDateNormalize(val, 0);
6247 if (norm == NULL)
6248 return (-1);
6250 * TODO: Check if "%.14g" is portable.
6252 snprintf(buf, 30,
6253 "%02u:%02u:%02.14gZ",
6254 norm->value.date.hour,
6255 norm->value.date.min,
6256 norm->value.date.sec);
6257 xmlSchemaFreeValue(norm);
6258 } else {
6259 snprintf(buf, 30,
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);
6267 break;
6268 case XML_SCHEMAS_DATE:
6270 char buf[30];
6272 if (val->value.date.tz_flag) {
6273 xmlSchemaValPtr norm;
6275 norm = xmlSchemaDateNormalize(val, 0);
6276 if (norm == NULL)
6277 return (-1);
6279 * TODO: Append the canonical value of the
6280 * recoverable timezone and not "Z".
6282 snprintf(buf, 30,
6283 "%04ld-%02u-%02uZ",
6284 norm->value.date.year, norm->value.date.mon,
6285 norm->value.date.day);
6286 xmlSchemaFreeValue(norm);
6287 } else {
6288 snprintf(buf, 30,
6289 "%04ld-%02u-%02u",
6290 val->value.date.year, val->value.date.mon,
6291 val->value.date.day);
6293 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6295 break;
6296 case XML_SCHEMAS_DATETIME:
6298 char buf[50];
6300 if (val->value.date.tz_flag) {
6301 xmlSchemaValPtr norm;
6303 norm = xmlSchemaDateNormalize(val, 0);
6304 if (norm == NULL)
6305 return (-1);
6307 * TODO: Check if "%.14g" is portable.
6309 snprintf(buf, 50,
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);
6315 } else {
6316 snprintf(buf, 50,
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);
6324 break;
6325 case XML_SCHEMAS_HEXBINARY:
6326 *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str);
6327 break;
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);
6336 break;
6337 case XML_SCHEMAS_FLOAT: {
6338 char buf[30];
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
6343 * the whole range.
6345 snprintf(buf, 30, "%01.14e", val->value.f);
6346 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6348 break;
6349 case XML_SCHEMAS_DOUBLE: {
6350 char buf[40];
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
6355 * the whole range.
6357 snprintf(buf, 40, "%01.14e", val->value.d);
6358 *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6360 break;
6361 default:
6362 *retValue = BAD_CAST xmlStrdup(BAD_CAST "???");
6363 return (1);
6365 if (*retValue == NULL)
6366 return(-1);
6367 return (0);
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))
6388 return (-1);
6389 if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) ||
6390 (ws > XML_SCHEMA_WHITESPACE_COLLAPSE))
6391 return (-1);
6393 *retValue = NULL;
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);
6404 break;
6405 case XML_SCHEMAS_NORMSTRING:
6406 if (val->value.str == NULL)
6407 *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6408 else {
6409 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6410 *retValue = xmlSchemaCollapseString(val->value.str);
6411 else
6412 *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6413 if ((*retValue) == NULL)
6414 *retValue = BAD_CAST xmlStrdup(val->value.str);
6416 break;
6417 default:
6418 return (xmlSchemaGetCanonValue(val, retValue));
6420 return (0);
6424 * xmlSchemaGetValType:
6425 * @val: a schemas value
6427 * Accessor for the type of a value
6429 * Returns the xmlSchemaValType of the value
6431 xmlSchemaValType
6432 xmlSchemaGetValType(xmlSchemaValPtr val)
6434 if (val == NULL)
6435 return(XML_SCHEMAS_UNKNOWN);
6436 return (val->type);
6439 #endif /* LIBXML_SCHEMAS_ENABLED */