• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * schemastypes.c : implementation of the XML Schema Datatypes
3  *             definition and validity checking
4  *
5  * See Copyright for the status of this software.
6  *
7  * Daniel Veillard <veillard@redhat.com>
8  */
9 
10 /* To avoid EBCDIC trouble when parsing on zOS */
11 #if defined(__MVS__)
12 #pragma convert("ISO8859-1")
13 #endif
14 
15 #define IN_LIBXML
16 #include "libxml.h"
17 
18 #ifdef LIBXML_SCHEMAS_ENABLED
19 
20 #include <string.h>
21 #include <libxml/xmlmemory.h>
22 #include <libxml/parser.h>
23 #include <libxml/parserInternals.h>
24 #include <libxml/hash.h>
25 #include <libxml/valid.h>
26 #include <libxml/xpath.h>
27 #include <libxml/uri.h>
28 
29 #include <libxml/xmlschemas.h>
30 #include <libxml/schemasInternals.h>
31 #include <libxml/xmlschemastypes.h>
32 
33 #ifdef HAVE_MATH_H
34 #include <math.h>
35 #endif
36 #ifdef HAVE_FLOAT_H
37 #include <float.h>
38 #endif
39 
40 #define DEBUG
41 
42 #ifndef LIBXML_XPATH_ENABLED
43 extern double xmlXPathNAN;
44 extern double xmlXPathPINF;
45 extern double xmlXPathNINF;
46 #endif
47 
48 #define TODO								\
49     xmlGenericError(xmlGenericErrorContext,				\
50 	    "Unimplemented block at %s:%d\n",				\
51             __FILE__, __LINE__);
52 
53 #define XML_SCHEMAS_NAMESPACE_NAME \
54     (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
55 
56 #define IS_WSP_REPLACE_CH(c)	((((c) == 0x9) || ((c) == 0xa)) || \
57 				 ((c) == 0xd))
58 
59 #define IS_WSP_SPACE_CH(c)	((c) == 0x20)
60 
61 #define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c)
62 
63 /* Date value */
64 typedef struct _xmlSchemaValDate xmlSchemaValDate;
65 typedef xmlSchemaValDate *xmlSchemaValDatePtr;
66 struct _xmlSchemaValDate {
67     long		year;
68     unsigned int	mon	:4;	/* 1 <=  mon    <= 12   */
69     unsigned int	day	:5;	/* 1 <=  day    <= 31   */
70     unsigned int	hour	:5;	/* 0 <=  hour   <= 24   */
71     unsigned int	min	:6;	/* 0 <=  min    <= 59	*/
72     double		sec;
73     unsigned int	tz_flag	:1;	/* is tzo explicitly set? */
74     signed int		tzo	:12;	/* -1440 <= tzo <= 1440;
75 					   currently only -840 to +840 are needed */
76 };
77 
78 /* Duration value */
79 typedef struct _xmlSchemaValDuration xmlSchemaValDuration;
80 typedef xmlSchemaValDuration *xmlSchemaValDurationPtr;
81 struct _xmlSchemaValDuration {
82     long	        mon;		/* mon stores years also */
83     long	day;
84     double		sec;            /* sec stores min and hour also */
85 };
86 
87 typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
88 typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
89 struct _xmlSchemaValDecimal {
90     /* would use long long but not portable */
91     unsigned long lo;
92     unsigned long mi;
93     unsigned long hi;
94     unsigned int extra;
95     unsigned int sign:1;
96     unsigned int frac:7;
97     unsigned int total:8;
98 };
99 
100 typedef struct _xmlSchemaValQName xmlSchemaValQName;
101 typedef xmlSchemaValQName *xmlSchemaValQNamePtr;
102 struct _xmlSchemaValQName {
103     xmlChar *name;
104     xmlChar *uri;
105 };
106 
107 typedef struct _xmlSchemaValHex xmlSchemaValHex;
108 typedef xmlSchemaValHex *xmlSchemaValHexPtr;
109 struct _xmlSchemaValHex {
110     xmlChar     *str;
111     unsigned int total;
112 };
113 
114 typedef struct _xmlSchemaValBase64 xmlSchemaValBase64;
115 typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr;
116 struct _xmlSchemaValBase64 {
117     xmlChar     *str;
118     unsigned int total;
119 };
120 
121 struct _xmlSchemaVal {
122     xmlSchemaValType type;
123     struct _xmlSchemaVal *next;
124     union {
125 	xmlSchemaValDecimal     decimal;
126         xmlSchemaValDate        date;
127         xmlSchemaValDuration    dur;
128 	xmlSchemaValQName	qname;
129 	xmlSchemaValHex		hex;
130 	xmlSchemaValBase64	base64;
131 	float			f;
132 	double			d;
133 	int			b;
134 	xmlChar                *str;
135     } value;
136 };
137 
138 static int xmlSchemaTypesInitialized = 0;
139 static xmlHashTablePtr xmlSchemaTypesBank = NULL;
140 
141 /*
142  * Basic types
143  */
144 static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL;
145 static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL;
146 static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL;
147 static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL;
148 static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL;
149 static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL;
150 static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL;
151 static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL;
152 static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL;
153 static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL;
154 static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL;
155 static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL;
156 static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL;
157 static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
158 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
159 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
160 static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
161 static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL;
162 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
163 
164 /*
165  * Derived types
166  */
167 static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL;
168 static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL;
169 static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL;
170 static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL;
171 static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL;
172 static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL;
173 static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL;
174 static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL;
175 static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL;
176 static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL;
177 static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL;
178 static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL;
179 static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL;
180 static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL;
181 static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL;
182 static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL;
183 static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
184 static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
185 static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL;
186 static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL;
187 static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL;
188 static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL;
189 static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL;
190 static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL;
191 static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL;
192 static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL;
193 static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
194 
195 /************************************************************************
196  *									*
197  *			Datatype error handlers				*
198  *									*
199  ************************************************************************/
200 /**
201  * xmlSchemaTypeErrMemory:
202  * @extra:  extra information
203  *
204  * Handle an out of memory condition
205  */
206 static void
xmlSchemaTypeErrMemory(xmlNodePtr node,const char * extra)207 xmlSchemaTypeErrMemory(xmlNodePtr node, const char *extra)
208 {
209     __xmlSimpleError(XML_FROM_DATATYPE, XML_ERR_NO_MEMORY, node, NULL, extra);
210 }
211 
212 /************************************************************************
213  *									*
214  *			Base types support				*
215  *									*
216  ************************************************************************/
217 
218 /**
219  * xmlSchemaNewValue:
220  * @type:  the value type
221  *
222  * Allocate a new simple type value
223  *
224  * Returns a pointer to the new value or NULL in case of error
225  */
226 static xmlSchemaValPtr
xmlSchemaNewValue(xmlSchemaValType type)227 xmlSchemaNewValue(xmlSchemaValType type) {
228     xmlSchemaValPtr value;
229 
230     value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
231     if (value == NULL) {
232 	return(NULL);
233     }
234     memset(value, 0, sizeof(xmlSchemaVal));
235     value->type = type;
236     return(value);
237 }
238 
239 static xmlSchemaFacetPtr
xmlSchemaNewMinLengthFacet(int value)240 xmlSchemaNewMinLengthFacet(int value)
241 {
242     xmlSchemaFacetPtr ret;
243 
244     ret = xmlSchemaNewFacet();
245     if (ret == NULL) {
246         return(NULL);
247     }
248     ret->type = XML_SCHEMA_FACET_MINLENGTH;
249     ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER);
250     if (ret->val == NULL) {
251         xmlFree(ret);
252 	return(NULL);
253     }
254     ret->val->value.decimal.lo = value;
255     return (ret);
256 }
257 
258 /*
259  * xmlSchemaInitBasicType:
260  * @name:  the type name
261  * @type:  the value type associated
262  *
263  * Initialize one primitive built-in type
264  */
265 static xmlSchemaTypePtr
xmlSchemaInitBasicType(const char * name,xmlSchemaValType type,xmlSchemaTypePtr baseType)266 xmlSchemaInitBasicType(const char *name, xmlSchemaValType type,
267 		       xmlSchemaTypePtr baseType) {
268     xmlSchemaTypePtr ret;
269 
270     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
271     if (ret == NULL) {
272         xmlSchemaTypeErrMemory(NULL, "could not initialize basic types");
273 	return(NULL);
274     }
275     memset(ret, 0, sizeof(xmlSchemaType));
276     ret->name = (const xmlChar *)name;
277     ret->targetNamespace = XML_SCHEMAS_NAMESPACE_NAME;
278     ret->type = XML_SCHEMA_TYPE_BASIC;
279     ret->baseType = baseType;
280     ret->contentType = XML_SCHEMA_CONTENT_BASIC;
281     /*
282     * Primitive types.
283     */
284     switch (type) {
285 	case XML_SCHEMAS_STRING:
286 	case XML_SCHEMAS_DECIMAL:
287 	case XML_SCHEMAS_DATE:
288 	case XML_SCHEMAS_DATETIME:
289 	case XML_SCHEMAS_TIME:
290 	case XML_SCHEMAS_GYEAR:
291 	case XML_SCHEMAS_GYEARMONTH:
292 	case XML_SCHEMAS_GMONTH:
293 	case XML_SCHEMAS_GMONTHDAY:
294 	case XML_SCHEMAS_GDAY:
295 	case XML_SCHEMAS_DURATION:
296 	case XML_SCHEMAS_FLOAT:
297 	case XML_SCHEMAS_DOUBLE:
298 	case XML_SCHEMAS_BOOLEAN:
299 	case XML_SCHEMAS_ANYURI:
300 	case XML_SCHEMAS_HEXBINARY:
301 	case XML_SCHEMAS_BASE64BINARY:
302 	case XML_SCHEMAS_QNAME:
303 	case XML_SCHEMAS_NOTATION:
304 	    ret->flags |= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE;
305 	    break;
306 	default:
307 	    break;
308     }
309     /*
310     * Set variety.
311     */
312     switch (type) {
313 	case XML_SCHEMAS_ANYTYPE:
314 	case XML_SCHEMAS_ANYSIMPLETYPE:
315 	    break;
316 	case XML_SCHEMAS_IDREFS:
317 	case XML_SCHEMAS_NMTOKENS:
318 	case XML_SCHEMAS_ENTITIES:
319 	    ret->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
320 	    ret->facets = xmlSchemaNewMinLengthFacet(1);
321 	    ret->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
322 	    break;
323 	default:
324 	    ret->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
325 	    break;
326     }
327     xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
328 	             XML_SCHEMAS_NAMESPACE_NAME, ret);
329     ret->builtInType = type;
330     return(ret);
331 }
332 
333 /*
334 * WARNING: Those type reside normally in xmlschemas.c but are
335 * redefined here locally in oder of being able to use them for xs:anyType-
336 * TODO: Remove those definition if we move the types to a header file.
337 * TODO: Always keep those structs up-to-date with the originals.
338 */
339 #define UNBOUNDED (1 << 30)
340 
341 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
342 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
343 struct _xmlSchemaTreeItem {
344     xmlSchemaTypeType type;
345     xmlSchemaAnnotPtr annot;
346     xmlSchemaTreeItemPtr next;
347     xmlSchemaTreeItemPtr children;
348 };
349 
350 typedef struct _xmlSchemaParticle xmlSchemaParticle;
351 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
352 struct _xmlSchemaParticle {
353     xmlSchemaTypeType type;
354     xmlSchemaAnnotPtr annot;
355     xmlSchemaTreeItemPtr next;
356     xmlSchemaTreeItemPtr children;
357     int minOccurs;
358     int maxOccurs;
359     xmlNodePtr node;
360 };
361 
362 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
363 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
364 struct _xmlSchemaModelGroup {
365     xmlSchemaTypeType type;
366     xmlSchemaAnnotPtr annot;
367     xmlSchemaTreeItemPtr next;
368     xmlSchemaTreeItemPtr children;
369     xmlNodePtr node;
370 };
371 
372 static xmlSchemaParticlePtr
xmlSchemaAddParticle(void)373 xmlSchemaAddParticle(void)
374 {
375     xmlSchemaParticlePtr ret = NULL;
376 
377     ret = (xmlSchemaParticlePtr)
378 	xmlMalloc(sizeof(xmlSchemaParticle));
379     if (ret == NULL) {
380 	xmlSchemaTypeErrMemory(NULL, "allocating particle component");
381 	return (NULL);
382     }
383     memset(ret, 0, sizeof(xmlSchemaParticle));
384     ret->type = XML_SCHEMA_TYPE_PARTICLE;
385     ret->minOccurs = 1;
386     ret->maxOccurs = 1;
387     return (ret);
388 }
389 
390 /*
391  * xmlSchemaInitTypes:
392  *
393  * Initialize the default XML Schemas type library
394  */
395 void
xmlSchemaInitTypes(void)396 xmlSchemaInitTypes(void)
397 {
398     if (xmlSchemaTypesInitialized != 0)
399         return;
400     xmlSchemaTypesBank = xmlHashCreate(40);
401 
402 
403     /*
404     * 3.4.7 Built-in Complex Type Definition
405     */
406     xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
407                                                      XML_SCHEMAS_ANYTYPE,
408 						     NULL);
409     xmlSchemaTypeAnyTypeDef->baseType = xmlSchemaTypeAnyTypeDef;
410     xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
411     /*
412     * Init the content type.
413     */
414     xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
415     {
416 	xmlSchemaParticlePtr particle;
417 	xmlSchemaModelGroupPtr sequence;
418 	xmlSchemaWildcardPtr wild;
419 	/* First particle. */
420 	particle = xmlSchemaAddParticle();
421 	if (particle == NULL)
422 	    return;
423 	xmlSchemaTypeAnyTypeDef->subtypes = (xmlSchemaTypePtr) particle;
424 	/* Sequence model group. */
425 	sequence = (xmlSchemaModelGroupPtr)
426 	    xmlMalloc(sizeof(xmlSchemaModelGroup));
427 	if (sequence == NULL) {
428 	    xmlSchemaTypeErrMemory(NULL, "allocating model group component");
429 	    return;
430 	}
431 	memset(sequence, 0, sizeof(xmlSchemaModelGroup));
432 	sequence->type = XML_SCHEMA_TYPE_SEQUENCE;
433 	particle->children = (xmlSchemaTreeItemPtr) sequence;
434 	/* Second particle. */
435 	particle = xmlSchemaAddParticle();
436 	if (particle == NULL)
437 	    return;
438 	particle->minOccurs = 0;
439 	particle->maxOccurs = UNBOUNDED;
440 	sequence->children = (xmlSchemaTreeItemPtr) particle;
441 	/* The wildcard */
442 	wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
443 	if (wild == NULL) {
444 	    xmlSchemaTypeErrMemory(NULL, "allocating wildcard component");
445 	    return;
446 	}
447 	memset(wild, 0, sizeof(xmlSchemaWildcard));
448 	wild->type = XML_SCHEMA_TYPE_ANY;
449 	wild->any = 1;
450 	wild->processContents = XML_SCHEMAS_ANY_LAX;
451 	particle->children = (xmlSchemaTreeItemPtr) wild;
452 	/*
453 	* Create the attribute wildcard.
454 	*/
455 	wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
456 	if (wild == NULL) {
457 	    xmlSchemaTypeErrMemory(NULL, "could not create an attribute "
458 		"wildcard on anyType");
459 	    return;
460 	}
461 	memset(wild, 0, sizeof(xmlSchemaWildcard));
462 	wild->any = 1;
463 	wild->processContents = XML_SCHEMAS_ANY_LAX;
464 	xmlSchemaTypeAnyTypeDef->attributeWildcard = wild;
465     }
466     xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType",
467                                                            XML_SCHEMAS_ANYSIMPLETYPE,
468 							   xmlSchemaTypeAnyTypeDef);
469     /*
470     * primitive datatypes
471     */
472     xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
473                                                     XML_SCHEMAS_STRING,
474 						    xmlSchemaTypeAnySimpleTypeDef);
475     xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
476                                                      XML_SCHEMAS_DECIMAL,
477 						     xmlSchemaTypeAnySimpleTypeDef);
478     xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
479                                                   XML_SCHEMAS_DATE,
480 						  xmlSchemaTypeAnySimpleTypeDef);
481     xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
482                                                       XML_SCHEMAS_DATETIME,
483 						      xmlSchemaTypeAnySimpleTypeDef);
484     xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
485                                                   XML_SCHEMAS_TIME,
486 						  xmlSchemaTypeAnySimpleTypeDef);
487     xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
488                                                    XML_SCHEMAS_GYEAR,
489 						   xmlSchemaTypeAnySimpleTypeDef);
490     xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
491                                                         XML_SCHEMAS_GYEARMONTH,
492 							xmlSchemaTypeAnySimpleTypeDef);
493     xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
494                                                     XML_SCHEMAS_GMONTH,
495 						    xmlSchemaTypeAnySimpleTypeDef);
496     xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
497                                                        XML_SCHEMAS_GMONTHDAY,
498 						       xmlSchemaTypeAnySimpleTypeDef);
499     xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
500                                                   XML_SCHEMAS_GDAY,
501 						  xmlSchemaTypeAnySimpleTypeDef);
502     xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
503                                                       XML_SCHEMAS_DURATION,
504 						      xmlSchemaTypeAnySimpleTypeDef);
505     xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
506                                                    XML_SCHEMAS_FLOAT,
507 						   xmlSchemaTypeAnySimpleTypeDef);
508     xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
509                                                     XML_SCHEMAS_DOUBLE,
510 						    xmlSchemaTypeAnySimpleTypeDef);
511     xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
512                                                      XML_SCHEMAS_BOOLEAN,
513 						     xmlSchemaTypeAnySimpleTypeDef);
514     xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
515                                                     XML_SCHEMAS_ANYURI,
516 						    xmlSchemaTypeAnySimpleTypeDef);
517     xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
518                                                      XML_SCHEMAS_HEXBINARY,
519 						     xmlSchemaTypeAnySimpleTypeDef);
520     xmlSchemaTypeBase64BinaryDef
521         = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY,
522 	xmlSchemaTypeAnySimpleTypeDef);
523     xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
524                                                     XML_SCHEMAS_NOTATION,
525 						    xmlSchemaTypeAnySimpleTypeDef);
526     xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
527                                                    XML_SCHEMAS_QNAME,
528 						   xmlSchemaTypeAnySimpleTypeDef);
529 
530     /*
531      * derived datatypes
532      */
533     xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
534                                                      XML_SCHEMAS_INTEGER,
535 						     xmlSchemaTypeDecimalDef);
536     xmlSchemaTypeNonPositiveIntegerDef =
537         xmlSchemaInitBasicType("nonPositiveInteger",
538                                XML_SCHEMAS_NPINTEGER,
539 			       xmlSchemaTypeIntegerDef);
540     xmlSchemaTypeNegativeIntegerDef =
541         xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER,
542 	xmlSchemaTypeNonPositiveIntegerDef);
543     xmlSchemaTypeLongDef =
544         xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG,
545 	xmlSchemaTypeIntegerDef);
546     xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT,
547 	xmlSchemaTypeLongDef);
548     xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
549                                                    XML_SCHEMAS_SHORT,
550 						   xmlSchemaTypeIntDef);
551     xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
552                                                   XML_SCHEMAS_BYTE,
553 						  xmlSchemaTypeShortDef);
554     xmlSchemaTypeNonNegativeIntegerDef =
555         xmlSchemaInitBasicType("nonNegativeInteger",
556                                XML_SCHEMAS_NNINTEGER,
557 			       xmlSchemaTypeIntegerDef);
558     xmlSchemaTypeUnsignedLongDef =
559         xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG,
560 	xmlSchemaTypeNonNegativeIntegerDef);
561     xmlSchemaTypeUnsignedIntDef =
562         xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT,
563 	xmlSchemaTypeUnsignedLongDef);
564     xmlSchemaTypeUnsignedShortDef =
565         xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT,
566 	xmlSchemaTypeUnsignedIntDef);
567     xmlSchemaTypeUnsignedByteDef =
568         xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE,
569 	xmlSchemaTypeUnsignedShortDef);
570     xmlSchemaTypePositiveIntegerDef =
571         xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER,
572 	xmlSchemaTypeNonNegativeIntegerDef);
573     xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
574                                                         XML_SCHEMAS_NORMSTRING,
575 							xmlSchemaTypeStringDef);
576     xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
577                                                    XML_SCHEMAS_TOKEN,
578 						   xmlSchemaTypeNormStringDef);
579     xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
580                                                       XML_SCHEMAS_LANGUAGE,
581 						      xmlSchemaTypeTokenDef);
582     xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
583                                                   XML_SCHEMAS_NAME,
584 						  xmlSchemaTypeTokenDef);
585     xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
586                                                      XML_SCHEMAS_NMTOKEN,
587 						     xmlSchemaTypeTokenDef);
588     xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
589                                                     XML_SCHEMAS_NCNAME,
590 						    xmlSchemaTypeNameDef);
591     xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID,
592 						    xmlSchemaTypeNCNameDef);
593     xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
594                                                    XML_SCHEMAS_IDREF,
595 						   xmlSchemaTypeNCNameDef);
596     xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
597                                                     XML_SCHEMAS_ENTITY,
598 						    xmlSchemaTypeNCNameDef);
599     /*
600     * Derived list types.
601     */
602     /* ENTITIES */
603     xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
604                                                       XML_SCHEMAS_ENTITIES,
605 						      xmlSchemaTypeAnySimpleTypeDef);
606     xmlSchemaTypeEntitiesDef->subtypes = xmlSchemaTypeEntityDef;
607     /* IDREFS */
608     xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
609                                                     XML_SCHEMAS_IDREFS,
610 						    xmlSchemaTypeAnySimpleTypeDef);
611     xmlSchemaTypeIdrefsDef->subtypes = xmlSchemaTypeIdrefDef;
612 
613     /* NMTOKENS */
614     xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
615                                                       XML_SCHEMAS_NMTOKENS,
616 						      xmlSchemaTypeAnySimpleTypeDef);
617     xmlSchemaTypeNmtokensDef->subtypes = xmlSchemaTypeNmtokenDef;
618 
619     xmlSchemaTypesInitialized = 1;
620 }
621 
622 static void
xmlSchemaFreeTypeEntry(void * type,const xmlChar * name ATTRIBUTE_UNUSED)623 xmlSchemaFreeTypeEntry(void *type, const xmlChar *name ATTRIBUTE_UNUSED) {
624     xmlSchemaFreeType((xmlSchemaTypePtr) type);
625 }
626 
627 /**
628  * xmlSchemaCleanupTypes:
629  *
630  * Cleanup the default XML Schemas type library
631  */
632 void
xmlSchemaCleanupTypes(void)633 xmlSchemaCleanupTypes(void) {
634     if (xmlSchemaTypesInitialized == 0)
635 	return;
636     /*
637     * Free xs:anyType.
638     */
639     {
640 	xmlSchemaParticlePtr particle;
641 	/* Attribute wildcard. */
642 	xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard);
643 	/* Content type. */
644 	particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes;
645 	/* Wildcard. */
646 	xmlSchemaFreeWildcard((xmlSchemaWildcardPtr)
647 	    particle->children->children->children);
648 	xmlFree((xmlSchemaParticlePtr) particle->children->children);
649 	/* Sequence model group. */
650 	xmlFree((xmlSchemaModelGroupPtr) particle->children);
651 	xmlFree((xmlSchemaParticlePtr) particle);
652 	xmlSchemaTypeAnyTypeDef->subtypes = NULL;
653     }
654     xmlHashFree(xmlSchemaTypesBank, xmlSchemaFreeTypeEntry);
655     xmlSchemaTypesInitialized = 0;
656 }
657 
658 /**
659  * xmlSchemaIsBuiltInTypeFacet:
660  * @type: the built-in type
661  * @facetType:  the facet type
662  *
663  * Evaluates if a specific facet can be
664  * used in conjunction with a type.
665  *
666  * Returns 1 if the facet can be used with the given built-in type,
667  * 0 otherwise and -1 in case the type is not a built-in type.
668  */
669 int
xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type,int facetType)670 xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type, int facetType)
671 {
672     if (type == NULL)
673 	return (-1);
674     if (type->type != XML_SCHEMA_TYPE_BASIC)
675 	return (-1);
676     switch (type->builtInType) {
677 	case XML_SCHEMAS_BOOLEAN:
678 	    if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
679 		(facetType == XML_SCHEMA_FACET_WHITESPACE))
680 		return (1);
681 	    else
682 		return (0);
683 	case XML_SCHEMAS_STRING:
684 	case XML_SCHEMAS_NOTATION:
685 	case XML_SCHEMAS_QNAME:
686 	case XML_SCHEMAS_ANYURI:
687 	case XML_SCHEMAS_BASE64BINARY:
688 	case XML_SCHEMAS_HEXBINARY:
689 	    if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
690 		(facetType == XML_SCHEMA_FACET_MINLENGTH) ||
691 		(facetType == XML_SCHEMA_FACET_MAXLENGTH) ||
692 		(facetType == XML_SCHEMA_FACET_PATTERN) ||
693 		(facetType == XML_SCHEMA_FACET_ENUMERATION) ||
694 		(facetType == XML_SCHEMA_FACET_WHITESPACE))
695 		return (1);
696 	    else
697 		return (0);
698 	case XML_SCHEMAS_DECIMAL:
699 	    if ((facetType == XML_SCHEMA_FACET_TOTALDIGITS) ||
700 		(facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) ||
701 		(facetType == XML_SCHEMA_FACET_PATTERN) ||
702 		(facetType == XML_SCHEMA_FACET_WHITESPACE) ||
703 		(facetType == XML_SCHEMA_FACET_ENUMERATION) ||
704 		(facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
705 		(facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
706 		(facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
707 		(facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
708 		return (1);
709 	    else
710 		return (0);
711 	case XML_SCHEMAS_TIME:
712 	case XML_SCHEMAS_GDAY:
713 	case XML_SCHEMAS_GMONTH:
714 	case XML_SCHEMAS_GMONTHDAY:
715 	case XML_SCHEMAS_GYEAR:
716 	case XML_SCHEMAS_GYEARMONTH:
717 	case XML_SCHEMAS_DATE:
718 	case XML_SCHEMAS_DATETIME:
719 	case XML_SCHEMAS_DURATION:
720 	case XML_SCHEMAS_FLOAT:
721 	case XML_SCHEMAS_DOUBLE:
722 	    if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
723 		(facetType == XML_SCHEMA_FACET_ENUMERATION) ||
724 		(facetType == XML_SCHEMA_FACET_WHITESPACE) ||
725 		(facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
726 		(facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
727 		(facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
728 		(facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
729 		return (1);
730 	    else
731 		return (0);
732 	default:
733 	    break;
734     }
735     return (0);
736 }
737 
738 /**
739  * xmlSchemaGetBuiltInType:
740  * @type:  the type of the built in type
741  *
742  * Gives you the type struct for a built-in
743  * type by its type id.
744  *
745  * Returns the type if found, NULL otherwise.
746  */
747 xmlSchemaTypePtr
xmlSchemaGetBuiltInType(xmlSchemaValType type)748 xmlSchemaGetBuiltInType(xmlSchemaValType type)
749 {
750     if (xmlSchemaTypesInitialized == 0)
751 	xmlSchemaInitTypes();
752     switch (type) {
753 
754 	case XML_SCHEMAS_ANYSIMPLETYPE:
755 	    return (xmlSchemaTypeAnySimpleTypeDef);
756 	case XML_SCHEMAS_STRING:
757 	    return (xmlSchemaTypeStringDef);
758 	case XML_SCHEMAS_NORMSTRING:
759 	    return (xmlSchemaTypeNormStringDef);
760 	case XML_SCHEMAS_DECIMAL:
761 	    return (xmlSchemaTypeDecimalDef);
762 	case XML_SCHEMAS_TIME:
763 	    return (xmlSchemaTypeTimeDef);
764 	case XML_SCHEMAS_GDAY:
765 	    return (xmlSchemaTypeGDayDef);
766 	case XML_SCHEMAS_GMONTH:
767 	    return (xmlSchemaTypeGMonthDef);
768 	case XML_SCHEMAS_GMONTHDAY:
769 	    return (xmlSchemaTypeGMonthDayDef);
770 	case XML_SCHEMAS_GYEAR:
771 	    return (xmlSchemaTypeGYearDef);
772 	case XML_SCHEMAS_GYEARMONTH:
773 	    return (xmlSchemaTypeGYearMonthDef);
774 	case XML_SCHEMAS_DATE:
775 	    return (xmlSchemaTypeDateDef);
776 	case XML_SCHEMAS_DATETIME:
777 	    return (xmlSchemaTypeDatetimeDef);
778 	case XML_SCHEMAS_DURATION:
779 	    return (xmlSchemaTypeDurationDef);
780 	case XML_SCHEMAS_FLOAT:
781 	    return (xmlSchemaTypeFloatDef);
782 	case XML_SCHEMAS_DOUBLE:
783 	    return (xmlSchemaTypeDoubleDef);
784 	case XML_SCHEMAS_BOOLEAN:
785 	    return (xmlSchemaTypeBooleanDef);
786 	case XML_SCHEMAS_TOKEN:
787 	    return (xmlSchemaTypeTokenDef);
788 	case XML_SCHEMAS_LANGUAGE:
789 	    return (xmlSchemaTypeLanguageDef);
790 	case XML_SCHEMAS_NMTOKEN:
791 	    return (xmlSchemaTypeNmtokenDef);
792 	case XML_SCHEMAS_NMTOKENS:
793 	    return (xmlSchemaTypeNmtokensDef);
794 	case XML_SCHEMAS_NAME:
795 	    return (xmlSchemaTypeNameDef);
796 	case XML_SCHEMAS_QNAME:
797 	    return (xmlSchemaTypeQNameDef);
798 	case XML_SCHEMAS_NCNAME:
799 	    return (xmlSchemaTypeNCNameDef);
800 	case XML_SCHEMAS_ID:
801 	    return (xmlSchemaTypeIdDef);
802 	case XML_SCHEMAS_IDREF:
803 	    return (xmlSchemaTypeIdrefDef);
804 	case XML_SCHEMAS_IDREFS:
805 	    return (xmlSchemaTypeIdrefsDef);
806 	case XML_SCHEMAS_ENTITY:
807 	    return (xmlSchemaTypeEntityDef);
808 	case XML_SCHEMAS_ENTITIES:
809 	    return (xmlSchemaTypeEntitiesDef);
810 	case XML_SCHEMAS_NOTATION:
811 	    return (xmlSchemaTypeNotationDef);
812 	case XML_SCHEMAS_ANYURI:
813 	    return (xmlSchemaTypeAnyURIDef);
814 	case XML_SCHEMAS_INTEGER:
815 	    return (xmlSchemaTypeIntegerDef);
816 	case XML_SCHEMAS_NPINTEGER:
817 	    return (xmlSchemaTypeNonPositiveIntegerDef);
818 	case XML_SCHEMAS_NINTEGER:
819 	    return (xmlSchemaTypeNegativeIntegerDef);
820 	case XML_SCHEMAS_NNINTEGER:
821 	    return (xmlSchemaTypeNonNegativeIntegerDef);
822 	case XML_SCHEMAS_PINTEGER:
823 	    return (xmlSchemaTypePositiveIntegerDef);
824 	case XML_SCHEMAS_INT:
825 	    return (xmlSchemaTypeIntDef);
826 	case XML_SCHEMAS_UINT:
827 	    return (xmlSchemaTypeUnsignedIntDef);
828 	case XML_SCHEMAS_LONG:
829 	    return (xmlSchemaTypeLongDef);
830 	case XML_SCHEMAS_ULONG:
831 	    return (xmlSchemaTypeUnsignedLongDef);
832 	case XML_SCHEMAS_SHORT:
833 	    return (xmlSchemaTypeShortDef);
834 	case XML_SCHEMAS_USHORT:
835 	    return (xmlSchemaTypeUnsignedShortDef);
836 	case XML_SCHEMAS_BYTE:
837 	    return (xmlSchemaTypeByteDef);
838 	case XML_SCHEMAS_UBYTE:
839 	    return (xmlSchemaTypeUnsignedByteDef);
840 	case XML_SCHEMAS_HEXBINARY:
841 	    return (xmlSchemaTypeHexBinaryDef);
842 	case XML_SCHEMAS_BASE64BINARY:
843 	    return (xmlSchemaTypeBase64BinaryDef);
844 	case XML_SCHEMAS_ANYTYPE:
845 	    return (xmlSchemaTypeAnyTypeDef);
846 	default:
847 	    return (NULL);
848     }
849 }
850 
851 /**
852  * xmlSchemaValueAppend:
853  * @prev: the value
854  * @cur: the value to be appended
855  *
856  * Appends a next sibling to a list of computed values.
857  *
858  * Returns 0 if succeeded and -1 on API errors.
859  */
860 int
xmlSchemaValueAppend(xmlSchemaValPtr prev,xmlSchemaValPtr cur)861 xmlSchemaValueAppend(xmlSchemaValPtr prev, xmlSchemaValPtr cur) {
862 
863     if ((prev == NULL) || (cur == NULL))
864 	return (-1);
865     prev->next = cur;
866     return (0);
867 }
868 
869 /**
870  * xmlSchemaValueGetNext:
871  * @cur: the value
872  *
873  * Accessor for the next sibling of a list of computed values.
874  *
875  * Returns the next value or NULL if there was none, or on
876  *         API errors.
877  */
878 xmlSchemaValPtr
xmlSchemaValueGetNext(xmlSchemaValPtr cur)879 xmlSchemaValueGetNext(xmlSchemaValPtr cur) {
880 
881     if (cur == NULL)
882 	return (NULL);
883     return (cur->next);
884 }
885 
886 /**
887  * xmlSchemaValueGetAsString:
888  * @val: the value
889  *
890  * Accessor for the string value of a computed value.
891  *
892  * Returns the string value or NULL if there was none, or on
893  *         API errors.
894  */
895 const xmlChar *
xmlSchemaValueGetAsString(xmlSchemaValPtr val)896 xmlSchemaValueGetAsString(xmlSchemaValPtr val)
897 {
898     if (val == NULL)
899 	return (NULL);
900     switch (val->type) {
901 	case XML_SCHEMAS_STRING:
902 	case XML_SCHEMAS_NORMSTRING:
903 	case XML_SCHEMAS_ANYSIMPLETYPE:
904 	case XML_SCHEMAS_TOKEN:
905         case XML_SCHEMAS_LANGUAGE:
906         case XML_SCHEMAS_NMTOKEN:
907         case XML_SCHEMAS_NAME:
908         case XML_SCHEMAS_NCNAME:
909         case XML_SCHEMAS_ID:
910         case XML_SCHEMAS_IDREF:
911         case XML_SCHEMAS_ENTITY:
912         case XML_SCHEMAS_ANYURI:
913 	    return (BAD_CAST val->value.str);
914 	default:
915 	    break;
916     }
917     return (NULL);
918 }
919 
920 /**
921  * xmlSchemaValueGetAsBoolean:
922  * @val: the value
923  *
924  * Accessor for the boolean value of a computed value.
925  *
926  * Returns 1 if true and 0 if false, or in case of an error. Hmm.
927  */
928 int
xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val)929 xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val)
930 {
931     if ((val == NULL) || (val->type != XML_SCHEMAS_BOOLEAN))
932 	return (0);
933     return (val->value.b);
934 }
935 
936 /**
937  * xmlSchemaNewStringValue:
938  * @type:  the value type
939  * @value:  the value
940  *
941  * Allocate a new simple type value. The type can be
942  * of XML_SCHEMAS_STRING.
943  * WARNING: This one is intended to be expanded for other
944  * string based types. We need this for anySimpleType as well.
945  * The given value is consumed and freed with the struct.
946  *
947  * Returns a pointer to the new value or NULL in case of error
948  */
949 xmlSchemaValPtr
xmlSchemaNewStringValue(xmlSchemaValType type,const xmlChar * value)950 xmlSchemaNewStringValue(xmlSchemaValType type,
951 			const xmlChar *value)
952 {
953     xmlSchemaValPtr val;
954 
955     if (type != XML_SCHEMAS_STRING)
956 	return(NULL);
957     val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
958     if (val == NULL) {
959 	return(NULL);
960     }
961     memset(val, 0, sizeof(xmlSchemaVal));
962     val->type = type;
963     val->value.str = (xmlChar *) value;
964     return(val);
965 }
966 
967 /**
968  * xmlSchemaNewNOTATIONValue:
969  * @name:  the notation name
970  * @ns: the notation namespace name or NULL
971  *
972  * Allocate a new NOTATION value.
973  * The given values are consumed and freed with the struct.
974  *
975  * Returns a pointer to the new value or NULL in case of error
976  */
977 xmlSchemaValPtr
xmlSchemaNewNOTATIONValue(const xmlChar * name,const xmlChar * ns)978 xmlSchemaNewNOTATIONValue(const xmlChar *name,
979 			  const xmlChar *ns)
980 {
981     xmlSchemaValPtr val;
982 
983     val = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
984     if (val == NULL)
985 	return (NULL);
986 
987     val->value.qname.name = (xmlChar *)name;
988     if (ns != NULL)
989 	val->value.qname.uri = (xmlChar *)ns;
990     return(val);
991 }
992 
993 /**
994  * xmlSchemaNewQNameValue:
995  * @namespaceName: the namespace name
996  * @localName: the local name
997  *
998  * Allocate a new QName value.
999  * The given values are consumed and freed with the struct.
1000  *
1001  * Returns a pointer to the new value or NULL in case of an error.
1002  */
1003 xmlSchemaValPtr
xmlSchemaNewQNameValue(const xmlChar * namespaceName,const xmlChar * localName)1004 xmlSchemaNewQNameValue(const xmlChar *namespaceName,
1005 		       const xmlChar *localName)
1006 {
1007     xmlSchemaValPtr val;
1008 
1009     val = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
1010     if (val == NULL)
1011 	return (NULL);
1012 
1013     val->value.qname.name = (xmlChar *) localName;
1014     val->value.qname.uri = (xmlChar *) namespaceName;
1015     return(val);
1016 }
1017 
1018 /**
1019  * xmlSchemaFreeValue:
1020  * @value:  the value to free
1021  *
1022  * Cleanup the default XML Schemas type library
1023  */
1024 void
xmlSchemaFreeValue(xmlSchemaValPtr value)1025 xmlSchemaFreeValue(xmlSchemaValPtr value) {
1026     xmlSchemaValPtr prev;
1027 
1028     while (value != NULL) {
1029 	switch (value->type) {
1030 	    case XML_SCHEMAS_STRING:
1031 	    case XML_SCHEMAS_NORMSTRING:
1032 	    case XML_SCHEMAS_TOKEN:
1033 	    case XML_SCHEMAS_LANGUAGE:
1034 	    case XML_SCHEMAS_NMTOKEN:
1035 	    case XML_SCHEMAS_NMTOKENS:
1036 	    case XML_SCHEMAS_NAME:
1037 	    case XML_SCHEMAS_NCNAME:
1038 	    case XML_SCHEMAS_ID:
1039 	    case XML_SCHEMAS_IDREF:
1040 	    case XML_SCHEMAS_IDREFS:
1041 	    case XML_SCHEMAS_ENTITY:
1042 	    case XML_SCHEMAS_ENTITIES:
1043 	    case XML_SCHEMAS_ANYURI:
1044 	    case XML_SCHEMAS_ANYSIMPLETYPE:
1045 		if (value->value.str != NULL)
1046 		    xmlFree(value->value.str);
1047 		break;
1048 	    case XML_SCHEMAS_NOTATION:
1049 	    case XML_SCHEMAS_QNAME:
1050 		if (value->value.qname.uri != NULL)
1051 		    xmlFree(value->value.qname.uri);
1052 		if (value->value.qname.name != NULL)
1053 		    xmlFree(value->value.qname.name);
1054 		break;
1055 	    case XML_SCHEMAS_HEXBINARY:
1056 		if (value->value.hex.str != NULL)
1057 		    xmlFree(value->value.hex.str);
1058 		break;
1059 	    case XML_SCHEMAS_BASE64BINARY:
1060 		if (value->value.base64.str != NULL)
1061 		    xmlFree(value->value.base64.str);
1062 		break;
1063 	    default:
1064 		break;
1065 	}
1066 	prev = value;
1067 	value = value->next;
1068 	xmlFree(prev);
1069     }
1070 }
1071 
1072 /**
1073  * xmlSchemaGetPredefinedType:
1074  * @name: the type name
1075  * @ns:  the URI of the namespace usually "http://www.w3.org/2001/XMLSchema"
1076  *
1077  * Lookup a type in the default XML Schemas type library
1078  *
1079  * Returns the type if found, NULL otherwise
1080  */
1081 xmlSchemaTypePtr
xmlSchemaGetPredefinedType(const xmlChar * name,const xmlChar * ns)1082 xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
1083     if (xmlSchemaTypesInitialized == 0)
1084 	xmlSchemaInitTypes();
1085     if (name == NULL)
1086 	return(NULL);
1087     return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
1088 }
1089 
1090 /**
1091  * xmlSchemaGetBuiltInListSimpleTypeItemType:
1092  * @type: the built-in simple type.
1093  *
1094  * Lookup function
1095  *
1096  * Returns the item type of @type as defined by the built-in datatype
1097  * hierarchy of XML Schema Part 2: Datatypes, or NULL in case of an error.
1098  */
1099 xmlSchemaTypePtr
xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type)1100 xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type)
1101 {
1102     if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_BASIC))
1103 	return (NULL);
1104     switch (type->builtInType) {
1105 	case XML_SCHEMAS_NMTOKENS:
1106 	    return (xmlSchemaTypeNmtokenDef );
1107 	case XML_SCHEMAS_IDREFS:
1108 	    return (xmlSchemaTypeIdrefDef);
1109 	case XML_SCHEMAS_ENTITIES:
1110 	    return (xmlSchemaTypeEntityDef);
1111 	default:
1112 	    return (NULL);
1113     }
1114 }
1115 
1116 /****************************************************************
1117  *								*
1118  *		Convenience macros and functions		*
1119  *								*
1120  ****************************************************************/
1121 
1122 #define IS_TZO_CHAR(c)						\
1123 	((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
1124 
1125 #define VALID_YEAR(yr)          (yr != 0)
1126 #define VALID_MONTH(mon)        ((mon >= 1) && (mon <= 12))
1127 /* VALID_DAY should only be used when month is unknown */
1128 #define VALID_DAY(day)          ((day >= 1) && (day <= 31))
1129 #define VALID_HOUR(hr)          ((hr >= 0) && (hr <= 23))
1130 #define VALID_MIN(min)          ((min >= 0) && (min <= 59))
1131 #define VALID_SEC(sec)          ((sec >= 0) && (sec < 60))
1132 #define VALID_TZO(tzo)          ((tzo >= -840) && (tzo <= 840))
1133 #define IS_LEAP(y)						\
1134 	(((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
1135 
1136 static const unsigned int daysInMonth[12] =
1137 	{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1138 static const unsigned int daysInMonthLeap[12] =
1139 	{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1140 
1141 #define MAX_DAYINMONTH(yr,mon)                                  \
1142         (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
1143 
1144 #define VALID_MDAY(dt)						\
1145 	(IS_LEAP(dt->year) ?				        \
1146 	    (dt->day <= daysInMonthLeap[dt->mon - 1]) :	        \
1147 	    (dt->day <= daysInMonth[dt->mon - 1]))
1148 
1149 #define VALID_DATE(dt)						\
1150 	(VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
1151 
1152 #define VALID_END_OF_DAY(dt)					\
1153 	((dt)->hour == 24 && (dt)->min == 0 && (dt)->sec == 0)
1154 
1155 #define VALID_TIME(dt)						\
1156 	(((VALID_HOUR(dt->hour) && VALID_MIN(dt->min) &&	\
1157 	  VALID_SEC(dt->sec)) || VALID_END_OF_DAY(dt)) &&	\
1158 	 VALID_TZO(dt->tzo))
1159 
1160 #define VALID_DATETIME(dt)					\
1161 	(VALID_DATE(dt) && VALID_TIME(dt))
1162 
1163 #define SECS_PER_MIN            60
1164 #define MINS_PER_HOUR           60
1165 #define HOURS_PER_DAY           24
1166 #define SECS_PER_HOUR           (MINS_PER_HOUR * SECS_PER_MIN)
1167 #define SECS_PER_DAY            (HOURS_PER_DAY * SECS_PER_HOUR)
1168 #define MINS_PER_DAY            (HOURS_PER_DAY * MINS_PER_HOUR)
1169 
1170 static const long dayInYearByMonth[12] =
1171 	{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
1172 static const long dayInLeapYearByMonth[12] =
1173 	{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
1174 
1175 #define DAY_IN_YEAR(day, month, year)				\
1176         ((IS_LEAP(year) ?					\
1177                 dayInLeapYearByMonth[month - 1] :		\
1178                 dayInYearByMonth[month - 1]) + day)
1179 
1180 #ifdef DEBUG
1181 #define DEBUG_DATE(dt)                                                  \
1182     xmlGenericError(xmlGenericErrorContext,                             \
1183         "type=%o %04ld-%02u-%02uT%02u:%02u:%03f",                       \
1184         dt->type,dt->value.date.year,dt->value.date.mon,                \
1185         dt->value.date.day,dt->value.date.hour,dt->value.date.min,      \
1186         dt->value.date.sec);                                            \
1187     if (dt->value.date.tz_flag)                                         \
1188         if (dt->value.date.tzo != 0)                                    \
1189             xmlGenericError(xmlGenericErrorContext,                     \
1190                 "%+05d\n",dt->value.date.tzo);                          \
1191         else                                                            \
1192             xmlGenericError(xmlGenericErrorContext, "Z\n");             \
1193     else                                                                \
1194         xmlGenericError(xmlGenericErrorContext,"\n")
1195 #else
1196 #define DEBUG_DATE(dt)
1197 #endif
1198 
1199 /**
1200  * _xmlSchemaParseGYear:
1201  * @dt:  pointer to a date structure
1202  * @str: pointer to the string to analyze
1203  *
1204  * Parses a xs:gYear without time zone and fills in the appropriate
1205  * field of the @dt structure. @str is updated to point just after the
1206  * xs:gYear. It is supposed that @dt->year is big enough to contain
1207  * the year.
1208  *
1209  * Returns 0 or the error code
1210  */
1211 static int
_xmlSchemaParseGYear(xmlSchemaValDatePtr dt,const xmlChar ** str)1212 _xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
1213     const xmlChar *cur = *str, *firstChar;
1214     int isneg = 0, digcnt = 0;
1215 
1216     if (((*cur < '0') || (*cur > '9')) &&
1217 	(*cur != '-') && (*cur != '+'))
1218 	return -1;
1219 
1220     if (*cur == '-') {
1221 	isneg = 1;
1222 	cur++;
1223     }
1224 
1225     firstChar = cur;
1226 
1227     while ((*cur >= '0') && (*cur <= '9')) {
1228         int digit = *cur - '0';
1229 
1230         if (dt->year > LONG_MAX / 10)
1231             return 2;
1232 	dt->year *= 10;
1233         if (dt->year > LONG_MAX - digit)
1234             return 2;
1235         dt->year += digit;
1236 	cur++;
1237 	digcnt++;
1238     }
1239 
1240     /* year must be at least 4 digits (CCYY); over 4
1241      * digits cannot have a leading zero. */
1242     if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0')))
1243 	return 1;
1244 
1245     if (isneg)
1246 	dt->year = - dt->year;
1247 
1248     if (!VALID_YEAR(dt->year))
1249 	return 2;
1250 
1251     *str = cur;
1252     return 0;
1253 }
1254 
1255 /**
1256  * PARSE_2_DIGITS:
1257  * @num:  the integer to fill in
1258  * @cur:  an #xmlChar *
1259  * @invalid: an integer
1260  *
1261  * Parses a 2-digits integer and updates @num with the value. @cur is
1262  * updated to point just after the integer.
1263  * In case of error, @invalid is set to %TRUE, values of @num and
1264  * @cur are undefined.
1265  */
1266 #define PARSE_2_DIGITS(num, cur, invalid)			\
1267 	if ((cur[0] < '0') || (cur[0] > '9') ||			\
1268 	    (cur[1] < '0') || (cur[1] > '9'))			\
1269 	    invalid = 1;					\
1270 	else							\
1271 	    num = (cur[0] - '0') * 10 + (cur[1] - '0');		\
1272 	cur += 2;
1273 
1274 /**
1275  * PARSE_FLOAT:
1276  * @num:  the double to fill in
1277  * @cur:  an #xmlChar *
1278  * @invalid: an integer
1279  *
1280  * Parses a float and updates @num with the value. @cur is
1281  * updated to point just after the float. The float must have a
1282  * 2-digits integer part and may or may not have a decimal part.
1283  * In case of error, @invalid is set to %TRUE, values of @num and
1284  * @cur are undefined.
1285  */
1286 #define PARSE_FLOAT(num, cur, invalid)				\
1287 	PARSE_2_DIGITS(num, cur, invalid);			\
1288 	if (!invalid && (*cur == '.')) {			\
1289 	    double mult = 1;				        \
1290 	    cur++;						\
1291 	    if ((*cur < '0') || (*cur > '9'))			\
1292 		invalid = 1;					\
1293 	    while ((*cur >= '0') && (*cur <= '9')) {		\
1294 		mult /= 10;					\
1295 		num += (*cur - '0') * mult;			\
1296 		cur++;						\
1297 	    }							\
1298 	}
1299 
1300 /**
1301  * _xmlSchemaParseGMonth:
1302  * @dt:  pointer to a date structure
1303  * @str: pointer to the string to analyze
1304  *
1305  * Parses a xs:gMonth without time zone and fills in the appropriate
1306  * field of the @dt structure. @str is updated to point just after the
1307  * xs:gMonth.
1308  *
1309  * Returns 0 or the error code
1310  */
1311 static int
_xmlSchemaParseGMonth(xmlSchemaValDatePtr dt,const xmlChar ** str)1312 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) {
1313     const xmlChar *cur = *str;
1314     int ret = 0;
1315     unsigned int value = 0;
1316 
1317     PARSE_2_DIGITS(value, cur, ret);
1318     if (ret != 0)
1319 	return ret;
1320 
1321     if (!VALID_MONTH(value))
1322 	return 2;
1323 
1324     dt->mon = value;
1325 
1326     *str = cur;
1327     return 0;
1328 }
1329 
1330 /**
1331  * _xmlSchemaParseGDay:
1332  * @dt:  pointer to a date structure
1333  * @str: pointer to the string to analyze
1334  *
1335  * Parses a xs:gDay without time zone and fills in the appropriate
1336  * field of the @dt structure. @str is updated to point just after the
1337  * xs:gDay.
1338  *
1339  * Returns 0 or the error code
1340  */
1341 static int
_xmlSchemaParseGDay(xmlSchemaValDatePtr dt,const xmlChar ** str)1342 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) {
1343     const xmlChar *cur = *str;
1344     int ret = 0;
1345     unsigned int value = 0;
1346 
1347     PARSE_2_DIGITS(value, cur, ret);
1348     if (ret != 0)
1349 	return ret;
1350 
1351     if (!VALID_DAY(value))
1352 	return 2;
1353 
1354     dt->day = value;
1355     *str = cur;
1356     return 0;
1357 }
1358 
1359 /**
1360  * _xmlSchemaParseTime:
1361  * @dt:  pointer to a date structure
1362  * @str: pointer to the string to analyze
1363  *
1364  * Parses a xs:time without time zone and fills in the appropriate
1365  * fields of the @dt structure. @str is updated to point just after the
1366  * xs:time.
1367  * In case of error, values of @dt fields are undefined.
1368  *
1369  * Returns 0 or the error code
1370  */
1371 static int
_xmlSchemaParseTime(xmlSchemaValDatePtr dt,const xmlChar ** str)1372 _xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) {
1373     const xmlChar *cur = *str;
1374     int ret = 0;
1375     int value = 0;
1376 
1377     PARSE_2_DIGITS(value, cur, ret);
1378     if (ret != 0)
1379 	return ret;
1380     if (*cur != ':')
1381 	return 1;
1382     if (!VALID_HOUR(value) && value != 24 /* Allow end-of-day hour */)
1383 	return 2;
1384     cur++;
1385 
1386     /* the ':' insures this string is xs:time */
1387     dt->hour = value;
1388 
1389     PARSE_2_DIGITS(value, cur, ret);
1390     if (ret != 0)
1391 	return ret;
1392     if (!VALID_MIN(value))
1393 	return 2;
1394     dt->min = value;
1395 
1396     if (*cur != ':')
1397 	return 1;
1398     cur++;
1399 
1400     PARSE_FLOAT(dt->sec, cur, ret);
1401     if (ret != 0)
1402 	return ret;
1403 
1404     if (!VALID_TIME(dt))
1405 	return 2;
1406 
1407     *str = cur;
1408     return 0;
1409 }
1410 
1411 /**
1412  * _xmlSchemaParseTimeZone:
1413  * @dt:  pointer to a date structure
1414  * @str: pointer to the string to analyze
1415  *
1416  * Parses a time zone without time zone and fills in the appropriate
1417  * field of the @dt structure. @str is updated to point just after the
1418  * time zone.
1419  *
1420  * Returns 0 or the error code
1421  */
1422 static int
_xmlSchemaParseTimeZone(xmlSchemaValDatePtr dt,const xmlChar ** str)1423 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
1424     const xmlChar *cur;
1425     int ret = 0;
1426 
1427     if (str == NULL)
1428 	return -1;
1429     cur = *str;
1430 
1431     switch (*cur) {
1432     case 0:
1433 	dt->tz_flag = 0;
1434 	dt->tzo = 0;
1435 	break;
1436 
1437     case 'Z':
1438 	dt->tz_flag = 1;
1439 	dt->tzo = 0;
1440 	cur++;
1441 	break;
1442 
1443     case '+':
1444     case '-': {
1445 	int isneg = 0, tmp = 0;
1446 	isneg = (*cur == '-');
1447 
1448 	cur++;
1449 
1450 	PARSE_2_DIGITS(tmp, cur, ret);
1451 	if (ret != 0)
1452 	    return ret;
1453 	if (!VALID_HOUR(tmp))
1454 	    return 2;
1455 
1456 	if (*cur != ':')
1457 	    return 1;
1458 	cur++;
1459 
1460 	dt->tzo = tmp * 60;
1461 
1462 	PARSE_2_DIGITS(tmp, cur, ret);
1463 	if (ret != 0)
1464 	    return ret;
1465 	if (!VALID_MIN(tmp))
1466 	    return 2;
1467 
1468 	dt->tzo += tmp;
1469 	if (isneg)
1470 	    dt->tzo = - dt->tzo;
1471 
1472 	if (!VALID_TZO(dt->tzo))
1473 	    return 2;
1474 
1475 	dt->tz_flag = 1;
1476 	break;
1477       }
1478     default:
1479 	return 1;
1480     }
1481 
1482     *str = cur;
1483     return 0;
1484 }
1485 
1486 /**
1487  * _xmlSchemaBase64Decode:
1488  * @ch: a character
1489  *
1490  * Converts a base64 encoded character to its base 64 value.
1491  *
1492  * Returns 0-63 (value), 64 (pad), or -1 (not recognized)
1493  */
1494 static int
_xmlSchemaBase64Decode(const xmlChar ch)1495 _xmlSchemaBase64Decode (const xmlChar ch) {
1496     if (('A' <= ch) && (ch <= 'Z')) return ch - 'A';
1497     if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26;
1498     if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52;
1499     if ('+' == ch) return 62;
1500     if ('/' == ch) return 63;
1501     if ('=' == ch) return 64;
1502     return -1;
1503 }
1504 
1505 /****************************************************************
1506  *								*
1507  *	XML Schema Dates/Times Datatypes Handling		*
1508  *								*
1509  ****************************************************************/
1510 
1511 /**
1512  * PARSE_DIGITS:
1513  * @num:  the integer to fill in
1514  * @cur:  an #xmlChar *
1515  * @num_type: an integer flag
1516  *
1517  * Parses a digits integer and updates @num with the value. @cur is
1518  * updated to point just after the integer.
1519  * In case of error, @num_type is set to -1, values of @num and
1520  * @cur are undefined.
1521  */
1522 #define PARSE_DIGITS(num, cur, num_type)	                \
1523 	if ((*cur < '0') || (*cur > '9'))			\
1524 	    num_type = -1;					\
1525         else                                                    \
1526 	    while ((*cur >= '0') && (*cur <= '9')) {		\
1527 	        num = num * 10 + (*cur - '0');		        \
1528 	        cur++;                                          \
1529             }
1530 
1531 /**
1532  * PARSE_NUM:
1533  * @num:  the double to fill in
1534  * @cur:  an #xmlChar *
1535  * @num_type: an integer flag
1536  *
1537  * Parses a float or integer and updates @num with the value. @cur is
1538  * updated to point just after the number. If the number is a float,
1539  * then it must have an integer part and a decimal part; @num_type will
1540  * be set to 1. If there is no decimal part, @num_type is set to zero.
1541  * In case of error, @num_type is set to -1, values of @num and
1542  * @cur are undefined.
1543  */
1544 #define PARSE_NUM(num, cur, num_type)				\
1545         num = 0;                                                \
1546 	PARSE_DIGITS(num, cur, num_type);	                \
1547 	if (!num_type && (*cur == '.')) {			\
1548 	    double mult = 1;				        \
1549 	    cur++;						\
1550 	    if ((*cur < '0') || (*cur > '9'))			\
1551 		num_type = -1;					\
1552             else                                                \
1553                 num_type = 1;                                   \
1554 	    while ((*cur >= '0') && (*cur <= '9')) {		\
1555 		mult /= 10;					\
1556 		num += (*cur - '0') * mult;			\
1557 		cur++;						\
1558 	    }							\
1559 	}
1560 
1561 /**
1562  * xmlSchemaValidateDates:
1563  * @type: the expected type or XML_SCHEMAS_UNKNOWN
1564  * @dateTime:  string to analyze
1565  * @val:  the return computed value
1566  *
1567  * Check that @dateTime conforms to the lexical space of one of the date types.
1568  * if true a value is computed and returned in @val.
1569  *
1570  * Returns 0 if this validates, a positive error code number otherwise
1571  *         and -1 in case of internal or API error.
1572  */
1573 static int
xmlSchemaValidateDates(xmlSchemaValType type,const xmlChar * dateTime,xmlSchemaValPtr * val,int collapse)1574 xmlSchemaValidateDates (xmlSchemaValType type,
1575 	                const xmlChar *dateTime, xmlSchemaValPtr *val,
1576 			int collapse) {
1577     xmlSchemaValPtr dt;
1578     int ret;
1579     const xmlChar *cur = dateTime;
1580 
1581 #define RETURN_TYPE_IF_VALID(t)					\
1582     if (IS_TZO_CHAR(*cur)) {					\
1583 	ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);	\
1584 	if (ret == 0) {						\
1585 	    if (*cur != 0)					\
1586 		goto error;					\
1587 	    dt->type = t;					\
1588 	    goto done;						\
1589 	}							\
1590     }
1591 
1592     if (dateTime == NULL)
1593 	return -1;
1594 
1595     if (collapse)
1596 	while IS_WSP_BLANK_CH(*cur) cur++;
1597 
1598     if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
1599 	return 1;
1600 
1601     dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN);
1602     if (dt == NULL)
1603 	return -1;
1604 
1605     if ((cur[0] == '-') && (cur[1] == '-')) {
1606 	/*
1607 	 * It's an incomplete date (xs:gMonthDay, xs:gMonth or
1608 	 * xs:gDay)
1609 	 */
1610 	cur += 2;
1611 
1612 	/* is it an xs:gDay? */
1613 	if (*cur == '-') {
1614 	    if (type == XML_SCHEMAS_GMONTH)
1615 		goto error;
1616 	  ++cur;
1617 	    ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1618 	    if (ret != 0)
1619 		goto error;
1620 
1621 	    RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY);
1622 
1623 	    goto error;
1624 	}
1625 
1626 	/*
1627 	 * it should be an xs:gMonthDay or xs:gMonth
1628 	 */
1629 	ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1630 	if (ret != 0)
1631 	    goto error;
1632 
1633         /*
1634          * a '-' char could indicate this type is xs:gMonthDay or
1635          * a negative time zone offset. Check for xs:gMonthDay first.
1636          * Also the first three char's of a negative tzo (-MM:SS) can
1637          * appear to be a valid day; so even if the day portion
1638          * of the xs:gMonthDay verifies, we must insure it was not
1639          * a tzo.
1640          */
1641         if (*cur == '-') {
1642             const xmlChar *rewnd = cur;
1643             cur++;
1644 
1645 	    ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1646             if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) {
1647 
1648                 /*
1649                  * we can use the VALID_MDAY macro to validate the month
1650                  * and day because the leap year test will flag year zero
1651                  * as a leap year (even though zero is an invalid year).
1652 		 * FUTURE TODO: Zero will become valid in XML Schema 1.1
1653 		 * probably.
1654                  */
1655                 if (VALID_MDAY((&(dt->value.date)))) {
1656 
1657 	            RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
1658 
1659                     goto error;
1660                 }
1661             }
1662 
1663             /*
1664              * not xs:gMonthDay so rewind and check if just xs:gMonth
1665              * with an optional time zone.
1666              */
1667             cur = rewnd;
1668         }
1669 
1670 	RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
1671 
1672 	goto error;
1673     }
1674 
1675     /*
1676      * It's a right-truncated date or an xs:time.
1677      * Try to parse an xs:time then fallback on right-truncated dates.
1678      */
1679     if ((*cur >= '0') && (*cur <= '9')) {
1680 	ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1681 	if (ret == 0) {
1682 	    /* it's an xs:time */
1683 	    RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME);
1684 	}
1685     }
1686 
1687     /* fallback on date parsing */
1688     cur = dateTime;
1689 
1690     ret = _xmlSchemaParseGYear(&(dt->value.date), &cur);
1691     if (ret != 0)
1692 	goto error;
1693 
1694     /* is it an xs:gYear? */
1695     RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR);
1696 
1697     if (*cur != '-')
1698 	goto error;
1699     cur++;
1700 
1701     ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1702     if (ret != 0)
1703 	goto error;
1704 
1705     /* is it an xs:gYearMonth? */
1706     RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH);
1707 
1708     if (*cur != '-')
1709 	goto error;
1710     cur++;
1711 
1712     ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1713     if ((ret != 0) || !VALID_DATE((&(dt->value.date))))
1714 	goto error;
1715 
1716     /* is it an xs:date? */
1717     RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE);
1718 
1719     if (*cur != 'T')
1720 	goto error;
1721     cur++;
1722 
1723     /* it should be an xs:dateTime */
1724     ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1725     if (ret != 0)
1726 	goto error;
1727 
1728     ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);
1729     if (collapse)
1730 	while IS_WSP_BLANK_CH(*cur) cur++;
1731     if ((ret != 0) || (*cur != 0) || (!(VALID_DATETIME((&(dt->value.date))))))
1732 	goto error;
1733 
1734 
1735     dt->type = XML_SCHEMAS_DATETIME;
1736 
1737 done:
1738 #if 1
1739     if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
1740         goto error;
1741 #else
1742     /*
1743      * insure the parsed type is equal to or less significant (right
1744      * truncated) than the desired type.
1745      */
1746     if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) {
1747 
1748         /* time only matches time */
1749         if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME))
1750             goto error;
1751 
1752         if ((type == XML_SCHEMAS_DATETIME) &&
1753             ((dt->type != XML_SCHEMAS_DATE) ||
1754              (dt->type != XML_SCHEMAS_GYEARMONTH) ||
1755              (dt->type != XML_SCHEMAS_GYEAR)))
1756             goto error;
1757 
1758         if ((type == XML_SCHEMAS_DATE) &&
1759             ((dt->type != XML_SCHEMAS_GYEAR) ||
1760              (dt->type != XML_SCHEMAS_GYEARMONTH)))
1761             goto error;
1762 
1763         if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
1764             goto error;
1765 
1766         if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
1767             goto error;
1768     }
1769 #endif
1770 
1771     if (val != NULL)
1772         *val = dt;
1773     else
1774 	xmlSchemaFreeValue(dt);
1775 
1776     return 0;
1777 
1778 error:
1779     if (dt != NULL)
1780 	xmlSchemaFreeValue(dt);
1781     return 1;
1782 }
1783 
1784 /**
1785  * xmlSchemaValidateDuration:
1786  * @type: the predefined type
1787  * @duration:  string to analyze
1788  * @val:  the return computed value
1789  *
1790  * Check that @duration conforms to the lexical space of the duration type.
1791  * if true a value is computed and returned in @val.
1792  *
1793  * Returns 0 if this validates, a positive error code number otherwise
1794  *         and -1 in case of internal or API error.
1795  */
1796 static int
xmlSchemaValidateDuration(xmlSchemaTypePtr type ATTRIBUTE_UNUSED,const xmlChar * duration,xmlSchemaValPtr * val,int collapse)1797 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1798 	                   const xmlChar *duration, xmlSchemaValPtr *val,
1799 			   int collapse) {
1800     const xmlChar  *cur = duration;
1801     xmlSchemaValPtr dur;
1802     int isneg = 0;
1803     unsigned int seq = 0;
1804     long days, secs = 0;
1805     double sec_frac = 0.0;
1806 
1807     if (duration == NULL)
1808 	return -1;
1809 
1810     if (collapse)
1811 	while IS_WSP_BLANK_CH(*cur) cur++;
1812 
1813     if (*cur == '-') {
1814         isneg = 1;
1815         cur++;
1816     }
1817 
1818     /* duration must start with 'P' (after sign) */
1819     if (*cur++ != 'P')
1820 	return 1;
1821 
1822     if (*cur == 0)
1823 	return 1;
1824 
1825     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
1826     if (dur == NULL)
1827 	return -1;
1828 
1829     while (*cur != 0) {
1830         long           num = 0;
1831         size_t         has_digits = 0;
1832         int            has_frac = 0;
1833         const xmlChar  desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
1834 
1835         /* input string should be empty or invalid date/time item */
1836         if (seq >= sizeof(desig))
1837             goto error;
1838 
1839         /* T designator must be present for time items */
1840         if (*cur == 'T') {
1841             if (seq > 3)
1842                 goto error;
1843             cur++;
1844             seq = 3;
1845         } else if (seq == 3)
1846             goto error;
1847 
1848         /* Parse integral part. */
1849         while (*cur >= '0' && *cur <= '9') {
1850             long digit = *cur - '0';
1851 
1852             if (num > LONG_MAX / 10)
1853                 goto error;
1854             num *= 10;
1855             if (num > LONG_MAX - digit)
1856                 goto error;
1857             num += digit;
1858 
1859             has_digits = 1;
1860             cur++;
1861         }
1862 
1863         if (*cur == '.') {
1864             /* Parse fractional part. */
1865             double mult = 1.0;
1866             cur++;
1867             has_frac = 1;
1868             while (*cur >= '0' && *cur <= '9') {
1869                 mult /= 10.0;
1870                 sec_frac += (*cur - '0') * mult;
1871                 has_digits = 1;
1872                 cur++;
1873             }
1874         }
1875 
1876         while (*cur != desig[seq]) {
1877             seq++;
1878             /* No T designator or invalid char. */
1879             if (seq == 3 || seq == sizeof(desig))
1880                 goto error;
1881         }
1882 	cur++;
1883 
1884         if (!has_digits || (has_frac && (seq != 5)))
1885             goto error;
1886 
1887         switch (seq) {
1888             case 0:
1889                 /* Year */
1890                 if (num > LONG_MAX / 12)
1891                     goto error;
1892                 dur->value.dur.mon = num * 12;
1893                 break;
1894             case 1:
1895                 /* Month */
1896                 if (dur->value.dur.mon > LONG_MAX - num)
1897                     goto error;
1898                 dur->value.dur.mon += num;
1899                 break;
1900             case 2:
1901                 /* Day */
1902                 dur->value.dur.day = num;
1903                 break;
1904             case 3:
1905                 /* Hour */
1906                 days = num / HOURS_PER_DAY;
1907                 if (dur->value.dur.day > LONG_MAX - days)
1908                     goto error;
1909                 dur->value.dur.day += days;
1910                 secs = (num % HOURS_PER_DAY) * SECS_PER_HOUR;
1911                 break;
1912             case 4:
1913                 /* Minute */
1914                 days = num / MINS_PER_DAY;
1915                 if (dur->value.dur.day > LONG_MAX - days)
1916                     goto error;
1917                 dur->value.dur.day += days;
1918                 secs += (num % MINS_PER_DAY) * SECS_PER_MIN;
1919                 break;
1920             case 5:
1921                 /* Second */
1922                 days = num / SECS_PER_DAY;
1923                 if (dur->value.dur.day > LONG_MAX - days)
1924                     goto error;
1925                 dur->value.dur.day += days;
1926                 secs += num % SECS_PER_DAY;
1927                 break;
1928         }
1929 
1930         seq++;
1931     }
1932 
1933     days = secs / SECS_PER_DAY;
1934     if (dur->value.dur.day > LONG_MAX - days)
1935         goto error;
1936     dur->value.dur.day += days;
1937     dur->value.dur.sec = (secs % SECS_PER_DAY) + sec_frac;
1938 
1939     if (isneg) {
1940         dur->value.dur.mon = -dur->value.dur.mon;
1941         dur->value.dur.day = -dur->value.dur.day;
1942         dur->value.dur.sec = -dur->value.dur.sec;
1943     }
1944 
1945     if (val != NULL)
1946         *val = dur;
1947     else
1948 	xmlSchemaFreeValue(dur);
1949 
1950     return 0;
1951 
1952 error:
1953     if (dur != NULL)
1954 	xmlSchemaFreeValue(dur);
1955     return 1;
1956 }
1957 
1958 /**
1959  * xmlSchemaStrip:
1960  * @value: a value
1961  *
1962  * Removes the leading and ending spaces of a string
1963  *
1964  * Returns the new string or NULL if no change was required.
1965  */
1966 static xmlChar *
xmlSchemaStrip(const xmlChar * value)1967 xmlSchemaStrip(const xmlChar *value) {
1968     const xmlChar *start = value, *end, *f;
1969 
1970     if (value == NULL) return(NULL);
1971     while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
1972     end = start;
1973     while (*end != 0) end++;
1974     f = end;
1975     end--;
1976     while ((end > start) && (IS_BLANK_CH(*end))) end--;
1977     end++;
1978     if ((start == value) && (f == end)) return(NULL);
1979     return(xmlStrndup(start, end - start));
1980 }
1981 
1982 /**
1983  * xmlSchemaWhiteSpaceReplace:
1984  * @value: a value
1985  *
1986  * Replaces 0xd, 0x9 and 0xa with a space.
1987  *
1988  * Returns the new string or NULL if no change was required.
1989  */
1990 xmlChar *
xmlSchemaWhiteSpaceReplace(const xmlChar * value)1991 xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
1992     const xmlChar *cur = value;
1993     xmlChar *ret = NULL, *mcur;
1994 
1995     if (value == NULL)
1996 	return(NULL);
1997 
1998     while ((*cur != 0) &&
1999 	(((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
2000 	cur++;
2001     }
2002     if (*cur == 0)
2003 	return (NULL);
2004     ret = xmlStrdup(value);
2005     /* TODO FIXME: I guess gcc will bark at this. */
2006     mcur = (xmlChar *)  (ret + (cur - value));
2007     do {
2008 	if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
2009 	    *mcur = ' ';
2010 	mcur++;
2011     } while (*mcur != 0);
2012     return(ret);
2013 }
2014 
2015 /**
2016  * xmlSchemaCollapseString:
2017  * @value: a value
2018  *
2019  * Removes and normalize white spaces in the string
2020  *
2021  * Returns the new string or NULL if no change was required.
2022  */
2023 xmlChar *
xmlSchemaCollapseString(const xmlChar * value)2024 xmlSchemaCollapseString(const xmlChar *value) {
2025     const xmlChar *start = value, *end, *f;
2026     xmlChar *g;
2027     int col = 0;
2028 
2029     if (value == NULL) return(NULL);
2030     while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
2031     end = start;
2032     while (*end != 0) {
2033 	if ((*end == ' ') && (IS_BLANK_CH(end[1]))) {
2034 	    col = end - start;
2035 	    break;
2036 	} else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) {
2037 	    col = end - start;
2038 	    break;
2039 	}
2040 	end++;
2041     }
2042     if (col == 0) {
2043 	f = end;
2044 	end--;
2045 	while ((end > start) && (IS_BLANK_CH(*end))) end--;
2046 	end++;
2047 	if ((start == value) && (f == end)) return(NULL);
2048 	return(xmlStrndup(start, end - start));
2049     }
2050     start = xmlStrdup(start);
2051     if (start == NULL) return(NULL);
2052     g = (xmlChar *) (start + col);
2053     end = g;
2054     while (*end != 0) {
2055 	if (IS_BLANK_CH(*end)) {
2056 	    end++;
2057 	    while (IS_BLANK_CH(*end)) end++;
2058 	    if (*end != 0)
2059 		*g++ = ' ';
2060 	} else
2061 	    *g++ = *end++;
2062     }
2063     *g = 0;
2064     return((xmlChar *) start);
2065 }
2066 
2067 /**
2068  * xmlSchemaValAtomicListNode:
2069  * @type: the predefined atomic type for a token in the list
2070  * @value: the list value to check
2071  * @ret:  the return computed value
2072  * @node:  the node containing the value
2073  *
2074  * Check that a value conforms to the lexical space of the predefined
2075  * list type. if true a value is computed and returned in @ret.
2076  *
2077  * Returns the number of items if this validates, a negative error code
2078  *         number otherwise
2079  */
2080 static int
xmlSchemaValAtomicListNode(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * ret,xmlNodePtr node)2081 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
2082 	                   xmlSchemaValPtr *ret, xmlNodePtr node) {
2083     xmlChar *val, *cur, *endval;
2084     int nb_values = 0;
2085     int tmp = 0;
2086 
2087     if (value == NULL) {
2088 	return(-1);
2089     }
2090     val = xmlStrdup(value);
2091     if (val == NULL) {
2092 	return(-1);
2093     }
2094     if (ret != NULL) {
2095         *ret = NULL;
2096     }
2097     cur = val;
2098     /*
2099      * Split the list
2100      */
2101     while (IS_BLANK_CH(*cur)) *cur++ = 0;
2102     while (*cur != 0) {
2103 	if (IS_BLANK_CH(*cur)) {
2104 	    *cur = 0;
2105 	    cur++;
2106 	    while (IS_BLANK_CH(*cur)) *cur++ = 0;
2107 	} else {
2108 	    nb_values++;
2109 	    cur++;
2110 	    while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
2111 	}
2112     }
2113     if (nb_values == 0) {
2114 	xmlFree(val);
2115 	return(nb_values);
2116     }
2117     endval = cur;
2118     cur = val;
2119     while ((*cur == 0) && (cur != endval)) cur++;
2120     while (cur != endval) {
2121 	tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node);
2122 	if (tmp != 0)
2123 	    break;
2124 	while (*cur != 0) cur++;
2125 	while ((*cur == 0) && (cur != endval)) cur++;
2126     }
2127     /* TODO what return value ? c.f. bug #158628
2128     if (ret != NULL) {
2129 	TODO
2130     } */
2131     xmlFree(val);
2132     if (tmp == 0)
2133 	return(nb_values);
2134     return(-1);
2135 }
2136 
2137 /**
2138  * xmlSchemaParseUInt:
2139  * @str: pointer to the string R/W
2140  * @llo: pointer to the low result
2141  * @lmi: pointer to the mid result
2142  * @lhi: pointer to the high result
2143  *
2144  * Parse an unsigned long into 3 fields.
2145  *
2146  * Returns the number of significant digits in the number or
2147  * -1 if overflow of the capacity and -2 if it's not a number.
2148  */
2149 static int
xmlSchemaParseUInt(const xmlChar ** str,unsigned long * llo,unsigned long * lmi,unsigned long * lhi)2150 xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
2151                    unsigned long *lmi, unsigned long *lhi) {
2152     unsigned long lo = 0, mi = 0, hi = 0;
2153     const xmlChar *tmp, *cur = *str;
2154     int ret = 0, i = 0;
2155 
2156     if (!((*cur >= '0') && (*cur <= '9')))
2157         return(-2);
2158 
2159     while (*cur == '0') {        /* ignore leading zeroes */
2160         cur++;
2161     }
2162     tmp = cur;
2163     while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
2164         i++;tmp++;ret++;
2165     }
2166     if (i > 24) {
2167         *str = tmp;
2168         return(-1);
2169     }
2170     while (i > 16) {
2171         hi = hi * 10 + (*cur++ - '0');
2172         i--;
2173     }
2174     while (i > 8) {
2175         mi = mi * 10 + (*cur++ - '0');
2176         i--;
2177     }
2178     while (i > 0) {
2179         lo = lo * 10 + (*cur++ - '0');
2180         i--;
2181     }
2182 
2183     *str = cur;
2184     *llo = lo;
2185     *lmi = mi;
2186     *lhi = hi;
2187     return(ret);
2188 }
2189 
2190 /*
2191  * xmlSchemaCheckLanguageType
2192  * @value: the value to check
2193  *
2194  * Check that a value conforms to the lexical space of the language datatype.
2195  * Must conform to [a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*
2196  *
2197  * Returns 1 if this validates, 0 otherwise.
2198  */
2199 static int
xmlSchemaCheckLanguageType(const xmlChar * value)2200 xmlSchemaCheckLanguageType(const xmlChar* value) {
2201     int first = 1, len = 0;
2202     const xmlChar* cur = value;
2203 
2204     if (value == NULL)
2205         return (0);
2206 
2207     while (cur[0] != 0) {
2208         if (!( ((cur[0] >= 'a') && (cur[0] <= 'z')) || ((cur[0] >= 'A') && (cur[0] <= 'Z'))
2209             || (cur[0] == '-')
2210             || ((first == 0) && (xmlIsDigit_ch(cur[0]))) ))
2211             return (0);
2212         if (cur[0] == '-') {
2213             if ((len < 1) || (len > 8))
2214                 return (0);
2215             len = 0;
2216             first = 0;
2217         }
2218         else
2219             len++;
2220         cur++;
2221     }
2222     if ((len < 1) || (len > 8))
2223         return (0);
2224 
2225     return (1);
2226 }
2227 
2228 /**
2229  * xmlSchemaValAtomicType:
2230  * @type: the predefined type
2231  * @value: the value to check
2232  * @val:  the return computed value
2233  * @node:  the node containing the value
2234  * flags:  flags to control the validation
2235  *
2236  * Check that a value conforms to the lexical space of the atomic type.
2237  * if true a value is computed and returned in @val.
2238  * This checks the value space for list types as well (IDREFS, NMTOKENS).
2239  *
2240  * Returns 0 if this validates, a positive error code number otherwise
2241  *         and -1 in case of internal or API error.
2242  */
2243 static int
xmlSchemaValAtomicType(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val,xmlNodePtr node,int flags,xmlSchemaWhitespaceValueType ws,int normOnTheFly,int applyNorm,int createStringValue)2244 xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
2245                        xmlSchemaValPtr * val, xmlNodePtr node, int flags,
2246 		       xmlSchemaWhitespaceValueType ws,
2247 		       int normOnTheFly, int applyNorm, int createStringValue)
2248 {
2249     xmlSchemaValPtr v;
2250     xmlChar *norm = NULL;
2251     int ret = 0;
2252 
2253     if (xmlSchemaTypesInitialized == 0)
2254         xmlSchemaInitTypes();
2255     if (type == NULL)
2256         return (-1);
2257 
2258     /*
2259      * validating a non existent text node is similar to validating
2260      * an empty one.
2261      */
2262     if (value == NULL)
2263         value = BAD_CAST "";
2264 
2265     if (val != NULL)
2266         *val = NULL;
2267     if ((flags == 0) && (value != NULL)) {
2268 
2269         if ((type->builtInType != XML_SCHEMAS_STRING) &&
2270 	  (type->builtInType != XML_SCHEMAS_ANYTYPE) &&
2271 	  (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
2272 	    if (type->builtInType == XML_SCHEMAS_NORMSTRING)
2273 		norm = xmlSchemaWhiteSpaceReplace(value);
2274             else
2275 		norm = xmlSchemaCollapseString(value);
2276             if (norm != NULL)
2277                 value = norm;
2278         }
2279     }
2280 
2281     switch (type->builtInType) {
2282         case XML_SCHEMAS_UNKNOWN:
2283             goto error;
2284 	case XML_SCHEMAS_ANYTYPE:
2285 	case XML_SCHEMAS_ANYSIMPLETYPE:
2286 	    if ((createStringValue) && (val != NULL)) {
2287 		v = xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE);
2288 		if (v != NULL) {
2289 		    v->value.str = xmlStrdup(value);
2290 		    *val = v;
2291 		} else {
2292 		    goto error;
2293 		}
2294 	    }
2295 	    goto return0;
2296         case XML_SCHEMAS_STRING:
2297 	    if (! normOnTheFly) {
2298 		const xmlChar *cur = value;
2299 
2300 		if (ws == XML_SCHEMA_WHITESPACE_REPLACE) {
2301 		    while (*cur != 0) {
2302 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2303 			    goto return1;
2304 			} else {
2305 			    cur++;
2306 			}
2307 		    }
2308 		} else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
2309 		    while (*cur != 0) {
2310 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2311 			    goto return1;
2312 			} else if IS_WSP_SPACE_CH(*cur) {
2313 			    cur++;
2314 			    if IS_WSP_SPACE_CH(*cur)
2315 				goto return1;
2316 			} else {
2317 			    cur++;
2318 			}
2319 		    }
2320 		}
2321 	    }
2322 	    if (createStringValue && (val != NULL)) {
2323 		if (applyNorm) {
2324 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
2325 			norm = xmlSchemaCollapseString(value);
2326 		    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
2327 			norm = xmlSchemaWhiteSpaceReplace(value);
2328 		    if (norm != NULL)
2329 			value = norm;
2330 		}
2331 		v = xmlSchemaNewValue(XML_SCHEMAS_STRING);
2332 		if (v != NULL) {
2333 		    v->value.str = xmlStrdup(value);
2334 		    *val = v;
2335 		} else {
2336 		    goto error;
2337 		}
2338 	    }
2339             goto return0;
2340         case XML_SCHEMAS_NORMSTRING:{
2341 		if (normOnTheFly) {
2342 		    if (applyNorm) {
2343 			if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
2344 			    norm = xmlSchemaCollapseString(value);
2345 			else
2346 			    norm = xmlSchemaWhiteSpaceReplace(value);
2347 			if (norm != NULL)
2348 			    value = norm;
2349 		    }
2350 		} else {
2351 		    const xmlChar *cur = value;
2352 		    while (*cur != 0) {
2353 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2354 			    goto return1;
2355 			} else {
2356 			    cur++;
2357 			}
2358 		    }
2359 		}
2360                 if (val != NULL) {
2361                     v = xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING);
2362                     if (v != NULL) {
2363                         v->value.str = xmlStrdup(value);
2364                         *val = v;
2365                     } else {
2366                         goto error;
2367                     }
2368                 }
2369                 goto return0;
2370             }
2371         case XML_SCHEMAS_DECIMAL:{
2372                 const xmlChar *cur = value;
2373                 unsigned int len, neg, integ, hasLeadingZeroes;
2374 		xmlChar cval[25];
2375 		xmlChar *cptr = cval;
2376 
2377                 if ((cur == NULL) || (*cur == 0))
2378                     goto return1;
2379 
2380 		/*
2381 		* xs:decimal has a whitespace-facet value of 'collapse'.
2382 		*/
2383 		if (normOnTheFly)
2384 		    while IS_WSP_BLANK_CH(*cur) cur++;
2385 
2386 		/*
2387 		* First we handle an optional sign.
2388 		*/
2389 		neg = 0;
2390                 if (*cur == '-') {
2391 		    neg = 1;
2392                     cur++;
2393 		} else if (*cur == '+')
2394                     cur++;
2395 		/*
2396 		* Disallow: "", "-", "- "
2397 		*/
2398 		if (*cur == 0)
2399 		    goto return1;
2400 		/*
2401 		 * Next we "pre-parse" the number, in preparation for calling
2402 		 * the common routine xmlSchemaParseUInt.  We get rid of any
2403 		 * leading zeroes (because we have reserved only 25 chars),
2404 		 * and note the position of a decimal point.
2405 		 */
2406 		len = 0;
2407 		integ = ~0u;
2408 		hasLeadingZeroes = 0;
2409 		/*
2410 		* Skip leading zeroes.
2411 		*/
2412 		while (*cur == '0') {
2413 		    cur++;
2414 		    hasLeadingZeroes = 1;
2415 		}
2416 		if (*cur != 0) {
2417 		    do {
2418 			if ((*cur >= '0') && (*cur <= '9')) {
2419 			    *cptr++ = *cur++;
2420 			    len++;
2421 			} else if (*cur == '.') {
2422 			    cur++;
2423 			    integ = len;
2424 			    do {
2425 				if ((*cur >= '0') && (*cur <= '9')) {
2426 				    *cptr++ = *cur++;
2427 				    len++;
2428 				} else
2429 				    break;
2430 			    } while (len < 24);
2431 			    /*
2432 			    * Disallow "." but allow "00."
2433 			    */
2434 			    if ((len == 0) && (!hasLeadingZeroes))
2435 				goto return1;
2436 			    break;
2437 			} else
2438 			    break;
2439 		    } while (len < 24);
2440 		}
2441 		if (normOnTheFly)
2442 		    while IS_WSP_BLANK_CH(*cur) cur++;
2443 		if (*cur != 0)
2444 		    goto return1; /* error if any extraneous chars */
2445                 if (val != NULL) {
2446                     v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
2447                     if (v != NULL) {
2448 			/*
2449 			* Now evaluate the significant digits of the number
2450 			*/
2451 			if (len != 0) {
2452 
2453 			    if (integ != ~0u) {
2454 				/*
2455 				* Get rid of trailing zeroes in the
2456 				* fractional part.
2457 				*/
2458 				while ((len != integ) && (*(cptr-1) == '0')) {
2459 				    cptr--;
2460 				    len--;
2461 				}
2462 			    }
2463 			    /*
2464 			    * Terminate the (preparsed) string.
2465 			    */
2466 			    if (len != 0) {
2467 				*cptr = 0;
2468 				cptr = cval;
2469 
2470 				xmlSchemaParseUInt((const xmlChar **)&cptr,
2471 				    &v->value.decimal.lo,
2472 				    &v->value.decimal.mi,
2473 				    &v->value.decimal.hi);
2474 			    }
2475 			}
2476 			/*
2477 			* Set the total digits to 1 if a zero value.
2478 			*/
2479                         v->value.decimal.sign = neg;
2480 			if (len == 0) {
2481 			    /* Speedup for zero values. */
2482 			    v->value.decimal.total = 1;
2483 			} else {
2484 			    v->value.decimal.total = len;
2485 			    if (integ == ~0u)
2486 				v->value.decimal.frac = 0;
2487 			    else
2488 				v->value.decimal.frac = len - integ;
2489 			}
2490                         *val = v;
2491                     }
2492                 }
2493                 goto return0;
2494             }
2495         case XML_SCHEMAS_TIME:
2496         case XML_SCHEMAS_GDAY:
2497         case XML_SCHEMAS_GMONTH:
2498         case XML_SCHEMAS_GMONTHDAY:
2499         case XML_SCHEMAS_GYEAR:
2500         case XML_SCHEMAS_GYEARMONTH:
2501         case XML_SCHEMAS_DATE:
2502         case XML_SCHEMAS_DATETIME:
2503             ret = xmlSchemaValidateDates(type->builtInType, value, val,
2504 		normOnTheFly);
2505             break;
2506         case XML_SCHEMAS_DURATION:
2507             ret = xmlSchemaValidateDuration(type, value, val,
2508 		normOnTheFly);
2509             break;
2510         case XML_SCHEMAS_FLOAT:
2511         case XML_SCHEMAS_DOUBLE: {
2512                 const xmlChar *cur = value;
2513                 int neg = 0;
2514                 int digits_before = 0;
2515                 int digits_after = 0;
2516 
2517 		if (normOnTheFly)
2518 		    while IS_WSP_BLANK_CH(*cur) cur++;
2519 
2520                 if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
2521                     cur += 3;
2522                     if (*cur != 0)
2523                         goto return1;
2524                     if (val != NULL) {
2525                         if (type == xmlSchemaTypeFloatDef) {
2526                             v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2527                             if (v != NULL) {
2528                                 v->value.f = (float) xmlXPathNAN;
2529                             } else {
2530                                 xmlSchemaFreeValue(v);
2531                                 goto error;
2532                             }
2533                         } else {
2534                             v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2535                             if (v != NULL) {
2536                                 v->value.d = xmlXPathNAN;
2537                             } else {
2538                                 xmlSchemaFreeValue(v);
2539                                 goto error;
2540                             }
2541                         }
2542                         *val = v;
2543                     }
2544                     goto return0;
2545                 }
2546                 if (*cur == '-') {
2547                     neg = 1;
2548                     cur++;
2549                 }
2550                 if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
2551                     cur += 3;
2552                     if (*cur != 0)
2553                         goto return1;
2554                     if (val != NULL) {
2555                         if (type == xmlSchemaTypeFloatDef) {
2556                             v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2557                             if (v != NULL) {
2558                                 if (neg)
2559                                     v->value.f = (float) xmlXPathNINF;
2560                                 else
2561                                     v->value.f = (float) xmlXPathPINF;
2562                             } else {
2563                                 xmlSchemaFreeValue(v);
2564                                 goto error;
2565                             }
2566                         } else {
2567                             v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2568                             if (v != NULL) {
2569                                 if (neg)
2570                                     v->value.d = xmlXPathNINF;
2571                                 else
2572                                     v->value.d = xmlXPathPINF;
2573                             } else {
2574                                 xmlSchemaFreeValue(v);
2575                                 goto error;
2576                             }
2577                         }
2578                         *val = v;
2579                     }
2580                     goto return0;
2581                 }
2582                 if ((neg == 0) && (*cur == '+'))
2583                     cur++;
2584                 if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
2585                     goto return1;
2586                 while ((*cur >= '0') && (*cur <= '9')) {
2587                     cur++;
2588                     digits_before++;
2589                 }
2590                 if (*cur == '.') {
2591                     cur++;
2592                     while ((*cur >= '0') && (*cur <= '9')) {
2593                         cur++;
2594                         digits_after++;
2595                     }
2596                 }
2597                 if ((digits_before == 0) && (digits_after == 0))
2598                     goto return1;
2599                 if ((*cur == 'e') || (*cur == 'E')) {
2600                     cur++;
2601                     if ((*cur == '-') || (*cur == '+'))
2602                         cur++;
2603                     while ((*cur >= '0') && (*cur <= '9'))
2604                         cur++;
2605                 }
2606 		if (normOnTheFly)
2607 		    while IS_WSP_BLANK_CH(*cur) cur++;
2608 
2609                 if (*cur != 0)
2610                     goto return1;
2611                 if (val != NULL) {
2612                     if (type == xmlSchemaTypeFloatDef) {
2613                         v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
2614                         if (v != NULL) {
2615 			    /*
2616 			    * TODO: sscanf seems not to give the correct
2617 			    * value for extremely high/low values.
2618 			    * E.g. "1E-149" results in zero.
2619 			    */
2620                             if (sscanf((const char *) value, "%f",
2621                                  &(v->value.f)) == 1) {
2622                                 *val = v;
2623                             } else {
2624                                 xmlSchemaFreeValue(v);
2625                                 goto return1;
2626                             }
2627                         } else {
2628                             goto error;
2629                         }
2630                     } else {
2631                         v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
2632                         if (v != NULL) {
2633 			    /*
2634 			    * TODO: sscanf seems not to give the correct
2635 			    * value for extremely high/low values.
2636 			    */
2637                             if (sscanf((const char *) value, "%lf",
2638                                  &(v->value.d)) == 1) {
2639                                 *val = v;
2640                             } else {
2641                                 xmlSchemaFreeValue(v);
2642                                 goto return1;
2643                             }
2644                         } else {
2645                             goto error;
2646                         }
2647                     }
2648                 }
2649                 goto return0;
2650             }
2651         case XML_SCHEMAS_BOOLEAN:{
2652                 const xmlChar *cur = value;
2653 
2654 		if (normOnTheFly) {
2655 		    while IS_WSP_BLANK_CH(*cur) cur++;
2656 		    if (*cur == '0') {
2657 			ret = 0;
2658 			cur++;
2659 		    } else if (*cur == '1') {
2660 			ret = 1;
2661 			cur++;
2662 		    } else if (*cur == 't') {
2663 			cur++;
2664 			if ((*cur++ == 'r') && (*cur++ == 'u') &&
2665 			    (*cur++ == 'e')) {
2666 			    ret = 1;
2667 			} else
2668 			    goto return1;
2669 		    } else if (*cur == 'f') {
2670 			cur++;
2671 			if ((*cur++ == 'a') && (*cur++ == 'l') &&
2672 			    (*cur++ == 's') && (*cur++ == 'e')) {
2673 			    ret = 0;
2674 			} else
2675 			    goto return1;
2676 		    } else
2677 			goto return1;
2678 		    if (*cur != 0) {
2679 			while IS_WSP_BLANK_CH(*cur) cur++;
2680 			if (*cur != 0)
2681 			    goto return1;
2682 		    }
2683 		} else {
2684 		    if ((cur[0] == '0') && (cur[1] == 0))
2685 			ret = 0;
2686 		    else if ((cur[0] == '1') && (cur[1] == 0))
2687 			ret = 1;
2688 		    else if ((cur[0] == 't') && (cur[1] == 'r')
2689 			&& (cur[2] == 'u') && (cur[3] == 'e')
2690 			&& (cur[4] == 0))
2691 			ret = 1;
2692 		    else if ((cur[0] == 'f') && (cur[1] == 'a')
2693 			&& (cur[2] == 'l') && (cur[3] == 's')
2694 			&& (cur[4] == 'e') && (cur[5] == 0))
2695 			ret = 0;
2696 		    else
2697 			goto return1;
2698 		}
2699                 if (val != NULL) {
2700                     v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
2701                     if (v != NULL) {
2702                         v->value.b = ret;
2703                         *val = v;
2704                     } else {
2705                         goto error;
2706                     }
2707                 }
2708                 goto return0;
2709             }
2710         case XML_SCHEMAS_TOKEN:{
2711                 const xmlChar *cur = value;
2712 
2713 		if (! normOnTheFly) {
2714 		    while (*cur != 0) {
2715 			if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2716 			    goto return1;
2717 			} else if (*cur == ' ') {
2718 			    cur++;
2719 			    if (*cur == 0)
2720 				goto return1;
2721 			    if (*cur == ' ')
2722 				goto return1;
2723 			} else {
2724 			    cur++;
2725 			}
2726 		    }
2727 		}
2728                 if (val != NULL) {
2729                     v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
2730                     if (v != NULL) {
2731                         v->value.str = xmlStrdup(value);
2732                         *val = v;
2733                     } else {
2734                         goto error;
2735                     }
2736                 }
2737                 goto return0;
2738             }
2739         case XML_SCHEMAS_LANGUAGE:
2740 	    if ((norm == NULL) && (normOnTheFly)) {
2741 		norm = xmlSchemaCollapseString(value);
2742 		if (norm != NULL)
2743 		    value = norm;
2744 	    }
2745 
2746             if (xmlSchemaCheckLanguageType(value) == 1) {
2747                 if (val != NULL) {
2748                     v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
2749                     if (v != NULL) {
2750                         v->value.str = xmlStrdup(value);
2751                         *val = v;
2752                     } else {
2753                         goto error;
2754                     }
2755                 }
2756                 goto return0;
2757             }
2758             goto return1;
2759         case XML_SCHEMAS_NMTOKEN:
2760             if (xmlValidateNMToken(value, 1) == 0) {
2761                 if (val != NULL) {
2762                     v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
2763                     if (v != NULL) {
2764                         v->value.str = xmlStrdup(value);
2765                         *val = v;
2766                     } else {
2767                         goto error;
2768                     }
2769                 }
2770                 goto return0;
2771             }
2772             goto return1;
2773         case XML_SCHEMAS_NMTOKENS:
2774             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
2775                                              value, val, node);
2776             if (ret > 0)
2777                 ret = 0;
2778             else
2779                 ret = 1;
2780             goto done;
2781         case XML_SCHEMAS_NAME:
2782             ret = xmlValidateName(value, 1);
2783             if ((ret == 0) && (val != NULL) && (value != NULL)) {
2784 		v = xmlSchemaNewValue(XML_SCHEMAS_NAME);
2785 		if (v != NULL) {
2786 		     const xmlChar *start = value, *end;
2787 		     while (IS_BLANK_CH(*start)) start++;
2788 		     end = start;
2789 		     while ((*end != 0) && (!IS_BLANK_CH(*end))) end++;
2790 		     v->value.str = xmlStrndup(start, end - start);
2791 		    *val = v;
2792 		} else {
2793 		    goto error;
2794 		}
2795             }
2796             goto done;
2797         case XML_SCHEMAS_QNAME:{
2798                 const xmlChar *uri = NULL;
2799                 xmlChar *local = NULL;
2800 
2801                 ret = xmlValidateQName(value, 1);
2802 		if (ret != 0)
2803 		    goto done;
2804                 if (node != NULL) {
2805                     xmlChar *prefix;
2806 		    xmlNsPtr ns;
2807 
2808                     local = xmlSplitQName2(value, &prefix);
2809 		    ns = xmlSearchNs(node->doc, node, prefix);
2810 		    if ((ns == NULL) && (prefix != NULL)) {
2811 			xmlFree(prefix);
2812 			if (local != NULL)
2813 			    xmlFree(local);
2814 			goto return1;
2815 		    }
2816 		    if (ns != NULL)
2817 			uri = ns->href;
2818                     if (prefix != NULL)
2819                         xmlFree(prefix);
2820                 }
2821                 if (val != NULL) {
2822                     v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
2823                     if (v == NULL) {
2824 			if (local != NULL)
2825 			    xmlFree(local);
2826 			goto error;
2827 		    }
2828 		    if (local != NULL)
2829 			v->value.qname.name = local;
2830 		    else
2831 			v->value.qname.name = xmlStrdup(value);
2832 		    if (uri != NULL)
2833 			v->value.qname.uri = xmlStrdup(uri);
2834 		    *val = v;
2835                 } else
2836 		    if (local != NULL)
2837 			xmlFree(local);
2838                 goto done;
2839             }
2840         case XML_SCHEMAS_NCNAME:
2841             ret = xmlValidateNCName(value, 1);
2842             if ((ret == 0) && (val != NULL)) {
2843                 v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
2844                 if (v != NULL) {
2845                     v->value.str = xmlStrdup(value);
2846                     *val = v;
2847                 } else {
2848                     goto error;
2849                 }
2850             }
2851             goto done;
2852         case XML_SCHEMAS_ID:
2853             ret = xmlValidateNCName(value, 1);
2854             if ((ret == 0) && (val != NULL)) {
2855                 v = xmlSchemaNewValue(XML_SCHEMAS_ID);
2856                 if (v != NULL) {
2857                     v->value.str = xmlStrdup(value);
2858                     *val = v;
2859                 } else {
2860                     goto error;
2861                 }
2862             }
2863             if ((ret == 0) && (node != NULL) &&
2864                 (node->type == XML_ATTRIBUTE_NODE)) {
2865                 xmlAttrPtr attr = (xmlAttrPtr) node;
2866 
2867                 /*
2868                  * NOTE: the IDness might have already be declared in the DTD
2869                  */
2870                 if (attr->atype != XML_ATTRIBUTE_ID) {
2871                     xmlIDPtr res;
2872                     xmlChar *strip;
2873 
2874                     strip = xmlSchemaStrip(value);
2875                     if (strip != NULL) {
2876                         res = xmlAddID(NULL, node->doc, strip, attr);
2877                         xmlFree(strip);
2878                     } else
2879                         res = xmlAddID(NULL, node->doc, value, attr);
2880                     if (res == NULL) {
2881                         ret = 2;
2882                     } else {
2883                         attr->atype = XML_ATTRIBUTE_ID;
2884                     }
2885                 }
2886             }
2887             goto done;
2888         case XML_SCHEMAS_IDREF:
2889             ret = xmlValidateNCName(value, 1);
2890             if ((ret == 0) && (val != NULL)) {
2891 		v = xmlSchemaNewValue(XML_SCHEMAS_IDREF);
2892 		if (v == NULL)
2893 		    goto error;
2894 		v->value.str = xmlStrdup(value);
2895 		*val = v;
2896             }
2897             if ((ret == 0) && (node != NULL) &&
2898                 (node->type == XML_ATTRIBUTE_NODE)) {
2899                 xmlAttrPtr attr = (xmlAttrPtr) node;
2900                 xmlChar *strip;
2901 
2902                 strip = xmlSchemaStrip(value);
2903                 if (strip != NULL) {
2904                     xmlAddRef(NULL, node->doc, strip, attr);
2905                     xmlFree(strip);
2906                 } else
2907                     xmlAddRef(NULL, node->doc, value, attr);
2908                 attr->atype = XML_ATTRIBUTE_IDREF;
2909             }
2910             goto done;
2911         case XML_SCHEMAS_IDREFS:
2912             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
2913                                              value, val, node);
2914             if (ret < 0)
2915                 ret = 2;
2916             else
2917                 ret = 0;
2918             if ((ret == 0) && (node != NULL) &&
2919                 (node->type == XML_ATTRIBUTE_NODE)) {
2920                 xmlAttrPtr attr = (xmlAttrPtr) node;
2921 
2922                 attr->atype = XML_ATTRIBUTE_IDREFS;
2923             }
2924             goto done;
2925         case XML_SCHEMAS_ENTITY:{
2926                 xmlChar *strip;
2927 
2928                 ret = xmlValidateNCName(value, 1);
2929                 if ((node == NULL) || (node->doc == NULL))
2930                     ret = 3;
2931                 if (ret == 0) {
2932                     xmlEntityPtr ent;
2933 
2934                     strip = xmlSchemaStrip(value);
2935                     if (strip != NULL) {
2936                         ent = xmlGetDocEntity(node->doc, strip);
2937                         xmlFree(strip);
2938                     } else {
2939                         ent = xmlGetDocEntity(node->doc, value);
2940                     }
2941                     if ((ent == NULL) ||
2942                         (ent->etype !=
2943                          XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
2944                         ret = 4;
2945                 }
2946                 if ((ret == 0) && (val != NULL)) {
2947                     TODO;
2948                 }
2949                 if ((ret == 0) && (node != NULL) &&
2950                     (node->type == XML_ATTRIBUTE_NODE)) {
2951                     xmlAttrPtr attr = (xmlAttrPtr) node;
2952 
2953                     attr->atype = XML_ATTRIBUTE_ENTITY;
2954                 }
2955                 goto done;
2956             }
2957         case XML_SCHEMAS_ENTITIES:
2958             if ((node == NULL) || (node->doc == NULL))
2959                 goto return3;
2960             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
2961                                              value, val, node);
2962             if (ret <= 0)
2963                 ret = 1;
2964             else
2965                 ret = 0;
2966             if ((ret == 0) && (node != NULL) &&
2967                 (node->type == XML_ATTRIBUTE_NODE)) {
2968                 xmlAttrPtr attr = (xmlAttrPtr) node;
2969 
2970                 attr->atype = XML_ATTRIBUTE_ENTITIES;
2971             }
2972             goto done;
2973         case XML_SCHEMAS_NOTATION:{
2974                 xmlChar *uri = NULL;
2975                 xmlChar *local = NULL;
2976 
2977                 ret = xmlValidateQName(value, 1);
2978                 if ((ret == 0) && (node != NULL)) {
2979                     xmlChar *prefix;
2980 
2981                     local = xmlSplitQName2(value, &prefix);
2982                     if (prefix != NULL) {
2983                         xmlNsPtr ns;
2984 
2985                         ns = xmlSearchNs(node->doc, node, prefix);
2986                         if (ns == NULL)
2987                             ret = 1;
2988                         else if (val != NULL)
2989                             uri = xmlStrdup(ns->href);
2990                     }
2991                     if ((local != NULL) && ((val == NULL) || (ret != 0)))
2992                         xmlFree(local);
2993                     if (prefix != NULL)
2994                         xmlFree(prefix);
2995                 }
2996                 if ((node == NULL) || (node->doc == NULL))
2997                     ret = 3;
2998                 if (ret == 0) {
2999                     ret = xmlValidateNotationUse(NULL, node->doc, value);
3000                     if (ret == 1)
3001                         ret = 0;
3002                     else
3003                         ret = 1;
3004                 }
3005                 if ((ret == 0) && (val != NULL)) {
3006                     v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
3007                     if (v != NULL) {
3008                         if (local != NULL)
3009                             v->value.qname.name = local;
3010                         else
3011                             v->value.qname.name = xmlStrdup(value);
3012                         if (uri != NULL)
3013                             v->value.qname.uri = uri;
3014 
3015                         *val = v;
3016                     } else {
3017                         if (local != NULL)
3018                             xmlFree(local);
3019                         if (uri != NULL)
3020                             xmlFree(uri);
3021                         goto error;
3022                     }
3023                 }
3024                 goto done;
3025             }
3026         case XML_SCHEMAS_ANYURI:{
3027                 if (*value != 0) {
3028 		    xmlURIPtr uri;
3029 		    xmlChar *tmpval, *cur;
3030 		    if ((norm == NULL) && (normOnTheFly)) {
3031 			norm = xmlSchemaCollapseString(value);
3032 			if (norm != NULL)
3033 			    value = norm;
3034 		    }
3035 		    tmpval = xmlStrdup(value);
3036 		    for (cur = tmpval; *cur; ++cur) {
3037 			if (*cur < 32 || *cur >= 127 || *cur == ' ' ||
3038 			    *cur == '<' || *cur == '>' || *cur == '"' ||
3039 			    *cur == '{' || *cur == '}' || *cur == '|' ||
3040 			    *cur == '\\' || *cur == '^' || *cur == '`' ||
3041 			    *cur == '\'')
3042 			    *cur = '_';
3043 		    }
3044                     uri = xmlParseURI((const char *) tmpval);
3045 		    xmlFree(tmpval);
3046                     if (uri == NULL)
3047                         goto return1;
3048                     xmlFreeURI(uri);
3049                 }
3050 
3051                 if (val != NULL) {
3052                     v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI);
3053                     if (v == NULL)
3054                         goto error;
3055                     v->value.str = xmlStrdup(value);
3056                     *val = v;
3057                 }
3058                 goto return0;
3059             }
3060         case XML_SCHEMAS_HEXBINARY:{
3061                 const xmlChar *cur = value, *start;
3062                 xmlChar *base;
3063                 int total, i = 0;
3064 
3065                 if (cur == NULL)
3066                     goto return1;
3067 
3068 		if (normOnTheFly)
3069 		    while IS_WSP_BLANK_CH(*cur) cur++;
3070 
3071 		start = cur;
3072                 while (((*cur >= '0') && (*cur <= '9')) ||
3073                        ((*cur >= 'A') && (*cur <= 'F')) ||
3074                        ((*cur >= 'a') && (*cur <= 'f'))) {
3075                     i++;
3076                     cur++;
3077                 }
3078 		if (normOnTheFly)
3079 		    while IS_WSP_BLANK_CH(*cur) cur++;
3080 
3081                 if (*cur != 0)
3082                     goto return1;
3083                 if ((i % 2) != 0)
3084                     goto return1;
3085 
3086                 if (val != NULL) {
3087 
3088                     v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
3089                     if (v == NULL)
3090                         goto error;
3091 		    /*
3092 		    * Copy only the normalized piece.
3093 		    * CRITICAL TODO: Check this.
3094 		    */
3095                     cur = xmlStrndup(start, i);
3096                     if (cur == NULL) {
3097 		        xmlSchemaTypeErrMemory(node, "allocating hexbin data");
3098                         xmlFree(v);
3099                         goto return1;
3100                     }
3101 
3102                     total = i / 2;      /* number of octets */
3103 
3104                     base = (xmlChar *) cur;
3105                     while (i-- > 0) {
3106                         if (*base >= 'a')
3107                             *base = *base - ('a' - 'A');
3108                         base++;
3109                     }
3110 
3111                     v->value.hex.str = (xmlChar *) cur;
3112                     v->value.hex.total = total;
3113                     *val = v;
3114                 }
3115                 goto return0;
3116             }
3117         case XML_SCHEMAS_BASE64BINARY:{
3118                 /* ISSUE:
3119                  *
3120                  * Ignore all stray characters? (yes, currently)
3121                  * Worry about long lines? (no, currently)
3122                  *
3123                  * rfc2045.txt:
3124                  *
3125                  * "The encoded output stream must be represented in lines of
3126                  * no more than 76 characters each.  All line breaks or other
3127                  * characters not found in Table 1 must be ignored by decoding
3128                  * software.  In base64 data, characters other than those in
3129                  * Table 1, line breaks, and other white space probably
3130                  * indicate a transmission error, about which a warning
3131                  * message or even a message rejection might be appropriate
3132                  * under some circumstances." */
3133                 const xmlChar *cur = value;
3134                 xmlChar *base;
3135                 int total, i = 0, pad = 0;
3136 
3137                 if (cur == NULL)
3138                     goto return1;
3139 
3140                 for (; *cur; ++cur) {
3141                     int decc;
3142 
3143                     decc = _xmlSchemaBase64Decode(*cur);
3144                     if (decc < 0) ;
3145                     else if (decc < 64)
3146                         i++;
3147                     else
3148                         break;
3149                 }
3150                 for (; *cur; ++cur) {
3151                     int decc;
3152 
3153                     decc = _xmlSchemaBase64Decode(*cur);
3154                     if (decc < 0) ;
3155                     else if (decc < 64)
3156                         goto return1;
3157                     if (decc == 64)
3158                         pad++;
3159                 }
3160 
3161                 /* rfc2045.txt: "Special processing is performed if fewer than
3162                  * 24 bits are available at the end of the data being encoded.
3163                  * A full encoding quantum is always completed at the end of a
3164                  * body.  When fewer than 24 input bits are available in an
3165                  * input group, zero bits are added (on the right) to form an
3166                  * integral number of 6-bit groups.  Padding at the end of the
3167                  * data is performed using the "=" character.  Since all
3168                  * base64 input is an integral number of octets, only the
3169                  * following cases can arise: (1) the final quantum of
3170                  * encoding input is an integral multiple of 24 bits; here,
3171                  * the final unit of encoded output will be an integral
3172                  * multiple of indent: Standard input:701: Warning:old style
3173 		 * assignment ambiguity in "=*".  Assuming "= *" 4 characters
3174 		 * with no "=" padding, (2) the final
3175                  * quantum of encoding input is exactly 8 bits; here, the
3176                  * final unit of encoded output will be two characters
3177                  * followed by two "=" padding characters, or (3) the final
3178                  * quantum of encoding input is exactly 16 bits; here, the
3179                  * final unit of encoded output will be three characters
3180                  * followed by one "=" padding character." */
3181 
3182                 total = 3 * (i / 4);
3183                 if (pad == 0) {
3184                     if (i % 4 != 0)
3185                         goto return1;
3186                 } else if (pad == 1) {
3187                     int decc;
3188 
3189                     if (i % 4 != 3)
3190                         goto return1;
3191                     for (decc = _xmlSchemaBase64Decode(*cur);
3192                          (decc < 0) || (decc > 63);
3193                          decc = _xmlSchemaBase64Decode(*cur))
3194                         --cur;
3195                     /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
3196                     /* 00111100 -> 0x3c */
3197                     if (decc & ~0x3c)
3198                         goto return1;
3199                     total += 2;
3200                 } else if (pad == 2) {
3201                     int decc;
3202 
3203                     if (i % 4 != 2)
3204                         goto return1;
3205                     for (decc = _xmlSchemaBase64Decode(*cur);
3206                          (decc < 0) || (decc > 63);
3207                          decc = _xmlSchemaBase64Decode(*cur))
3208                         --cur;
3209                     /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
3210                     /* 00110000 -> 0x30 */
3211                     if (decc & ~0x30)
3212                         goto return1;
3213                     total += 1;
3214                 } else
3215                     goto return1;
3216 
3217                 if (val != NULL) {
3218                     v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
3219                     if (v == NULL)
3220                         goto error;
3221                     base =
3222                         (xmlChar *) xmlMallocAtomic((i + pad + 1) *
3223                                                     sizeof(xmlChar));
3224                     if (base == NULL) {
3225 		        xmlSchemaTypeErrMemory(node, "allocating base64 data");
3226                         xmlFree(v);
3227                         goto return1;
3228                     }
3229                     v->value.base64.str = base;
3230                     for (cur = value; *cur; ++cur)
3231                         if (_xmlSchemaBase64Decode(*cur) >= 0) {
3232                             *base = *cur;
3233                             ++base;
3234                         }
3235                     *base = 0;
3236                     v->value.base64.total = total;
3237                     *val = v;
3238                 }
3239                 goto return0;
3240             }
3241         case XML_SCHEMAS_INTEGER:
3242         case XML_SCHEMAS_PINTEGER:
3243         case XML_SCHEMAS_NPINTEGER:
3244         case XML_SCHEMAS_NINTEGER:
3245         case XML_SCHEMAS_NNINTEGER:{
3246                 const xmlChar *cur = value;
3247                 unsigned long lo, mi, hi;
3248                 int sign = 0;
3249 
3250                 if (cur == NULL)
3251                     goto return1;
3252 		if (normOnTheFly)
3253 		    while IS_WSP_BLANK_CH(*cur) cur++;
3254                 if (*cur == '-') {
3255                     sign = 1;
3256                     cur++;
3257                 } else if (*cur == '+')
3258                     cur++;
3259                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3260                 if (ret < 0)
3261                     goto return1;
3262 		if (normOnTheFly)
3263 		    while IS_WSP_BLANK_CH(*cur) cur++;
3264                 if (*cur != 0)
3265                     goto return1;
3266                 if (type->builtInType == XML_SCHEMAS_NPINTEGER) {
3267                     if ((sign == 0) &&
3268                         ((hi != 0) || (mi != 0) || (lo != 0)))
3269                         goto return1;
3270                 } else if (type->builtInType == XML_SCHEMAS_PINTEGER) {
3271                     if (sign == 1)
3272                         goto return1;
3273                     if ((hi == 0) && (mi == 0) && (lo == 0))
3274                         goto return1;
3275                 } else if (type->builtInType == XML_SCHEMAS_NINTEGER) {
3276                     if (sign == 0)
3277                         goto return1;
3278                     if ((hi == 0) && (mi == 0) && (lo == 0))
3279                         goto return1;
3280                 } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) {
3281                     if ((sign == 1) &&
3282                         ((hi != 0) || (mi != 0) || (lo != 0)))
3283                         goto return1;
3284                 }
3285                 if (val != NULL) {
3286                     v = xmlSchemaNewValue(type->builtInType);
3287                     if (v != NULL) {
3288 			if (ret == 0)
3289 			    ret++;
3290                         v->value.decimal.lo = lo;
3291                         v->value.decimal.mi = mi;
3292                         v->value.decimal.hi = hi;
3293                         v->value.decimal.sign = sign;
3294                         v->value.decimal.frac = 0;
3295                         v->value.decimal.total = ret;
3296                         *val = v;
3297                     }
3298                 }
3299                 goto return0;
3300             }
3301         case XML_SCHEMAS_LONG:
3302         case XML_SCHEMAS_BYTE:
3303         case XML_SCHEMAS_SHORT:
3304         case XML_SCHEMAS_INT:{
3305                 const xmlChar *cur = value;
3306                 unsigned long lo, mi, hi;
3307                 int sign = 0;
3308 
3309                 if (cur == NULL)
3310                     goto return1;
3311                 if (*cur == '-') {
3312                     sign = 1;
3313                     cur++;
3314                 } else if (*cur == '+')
3315                     cur++;
3316                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3317                 if (ret < 0)
3318                     goto return1;
3319                 if (*cur != 0)
3320                     goto return1;
3321                 if (type->builtInType == XML_SCHEMAS_LONG) {
3322                     if (hi >= 922) {
3323                         if (hi > 922)
3324                             goto return1;
3325                         if (mi >= 33720368) {
3326                             if (mi > 33720368)
3327                                 goto return1;
3328                             if ((sign == 0) && (lo > 54775807))
3329                                 goto return1;
3330                             if ((sign == 1) && (lo > 54775808))
3331                                 goto return1;
3332                         }
3333                     }
3334                 } else if (type->builtInType == XML_SCHEMAS_INT) {
3335                     if (hi != 0)
3336                         goto return1;
3337                     if (mi >= 21) {
3338                         if (mi > 21)
3339                             goto return1;
3340                         if ((sign == 0) && (lo > 47483647))
3341                             goto return1;
3342                         if ((sign == 1) && (lo > 47483648))
3343                             goto return1;
3344                     }
3345                 } else if (type->builtInType == XML_SCHEMAS_SHORT) {
3346                     if ((mi != 0) || (hi != 0))
3347                         goto return1;
3348                     if ((sign == 1) && (lo > 32768))
3349                         goto return1;
3350                     if ((sign == 0) && (lo > 32767))
3351                         goto return1;
3352                 } else if (type->builtInType == XML_SCHEMAS_BYTE) {
3353                     if ((mi != 0) || (hi != 0))
3354                         goto return1;
3355                     if ((sign == 1) && (lo > 128))
3356                         goto return1;
3357                     if ((sign == 0) && (lo > 127))
3358                         goto return1;
3359                 }
3360                 if (val != NULL) {
3361                     v = xmlSchemaNewValue(type->builtInType);
3362                     if (v != NULL) {
3363                         v->value.decimal.lo = lo;
3364                         v->value.decimal.mi = mi;
3365                         v->value.decimal.hi = hi;
3366                         v->value.decimal.sign = sign;
3367                         v->value.decimal.frac = 0;
3368                         v->value.decimal.total = ret;
3369                         *val = v;
3370                     }
3371                 }
3372                 goto return0;
3373             }
3374         case XML_SCHEMAS_UINT:
3375         case XML_SCHEMAS_ULONG:
3376         case XML_SCHEMAS_USHORT:
3377         case XML_SCHEMAS_UBYTE:{
3378                 const xmlChar *cur = value;
3379                 unsigned long lo, mi, hi;
3380 
3381                 if (cur == NULL)
3382                     goto return1;
3383                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3384                 if (ret < 0)
3385                     goto return1;
3386                 if (*cur != 0)
3387                     goto return1;
3388                 if (type->builtInType == XML_SCHEMAS_ULONG) {
3389                     if (hi >= 1844) {
3390                         if (hi > 1844)
3391                             goto return1;
3392                         if (mi >= 67440737) {
3393                             if (mi > 67440737)
3394                                 goto return1;
3395                             if (lo > 9551615)
3396                                 goto return1;
3397                         }
3398                     }
3399                 } else if (type->builtInType == XML_SCHEMAS_UINT) {
3400                     if (hi != 0)
3401                         goto return1;
3402                     if (mi >= 42) {
3403                         if (mi > 42)
3404                             goto return1;
3405                         if (lo > 94967295)
3406                             goto return1;
3407                     }
3408                 } else if (type->builtInType == XML_SCHEMAS_USHORT) {
3409                     if ((mi != 0) || (hi != 0))
3410                         goto return1;
3411                     if (lo > 65535)
3412                         goto return1;
3413                 } else if (type->builtInType == XML_SCHEMAS_UBYTE) {
3414                     if ((mi != 0) || (hi != 0))
3415                         goto return1;
3416                     if (lo > 255)
3417                         goto return1;
3418                 }
3419                 if (val != NULL) {
3420                     v = xmlSchemaNewValue(type->builtInType);
3421                     if (v != NULL) {
3422                         v->value.decimal.lo = lo;
3423                         v->value.decimal.mi = mi;
3424                         v->value.decimal.hi = hi;
3425                         v->value.decimal.sign = 0;
3426                         v->value.decimal.frac = 0;
3427                         v->value.decimal.total = ret;
3428                         *val = v;
3429                     }
3430                 }
3431                 goto return0;
3432             }
3433     }
3434 
3435   done:
3436     if (norm != NULL)
3437         xmlFree(norm);
3438     return (ret);
3439   return3:
3440     if (norm != NULL)
3441         xmlFree(norm);
3442     return (3);
3443   return1:
3444     if (norm != NULL)
3445         xmlFree(norm);
3446     return (1);
3447   return0:
3448     if (norm != NULL)
3449         xmlFree(norm);
3450     return (0);
3451   error:
3452     if (norm != NULL)
3453         xmlFree(norm);
3454     return (-1);
3455 }
3456 
3457 /**
3458  * xmlSchemaValPredefTypeNode:
3459  * @type: the predefined type
3460  * @value: the value to check
3461  * @val:  the return computed value
3462  * @node:  the node containing the value
3463  *
3464  * Check that a value conforms to the lexical space of the predefined type.
3465  * if true a value is computed and returned in @val.
3466  *
3467  * Returns 0 if this validates, a positive error code number otherwise
3468  *         and -1 in case of internal or API error.
3469  */
3470 int
xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val,xmlNodePtr node)3471 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
3472 	                   xmlSchemaValPtr *val, xmlNodePtr node) {
3473     return(xmlSchemaValAtomicType(type, value, val, node, 0,
3474 	XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 1, 0));
3475 }
3476 
3477 /**
3478  * xmlSchemaValPredefTypeNodeNoNorm:
3479  * @type: the predefined type
3480  * @value: the value to check
3481  * @val:  the return computed value
3482  * @node:  the node containing the value
3483  *
3484  * Check that a value conforms to the lexical space of the predefined type.
3485  * if true a value is computed and returned in @val.
3486  * This one does apply any normalization to the value.
3487  *
3488  * Returns 0 if this validates, a positive error code number otherwise
3489  *         and -1 in case of internal or API error.
3490  */
3491 int
xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val,xmlNodePtr node)3492 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value,
3493 				 xmlSchemaValPtr *val, xmlNodePtr node) {
3494     return(xmlSchemaValAtomicType(type, value, val, node, 1,
3495 	XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 0, 1));
3496 }
3497 
3498 /**
3499  * xmlSchemaValidatePredefinedType:
3500  * @type: the predefined type
3501  * @value: the value to check
3502  * @val:  the return computed value
3503  *
3504  * Check that a value conforms to the lexical space of the predefined type.
3505  * if true a value is computed and returned in @val.
3506  *
3507  * Returns 0 if this validates, a positive error code number otherwise
3508  *         and -1 in case of internal or API error.
3509  */
3510 int
xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)3511 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
3512 	                        xmlSchemaValPtr *val) {
3513     return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
3514 }
3515 
3516 /**
3517  * xmlSchemaCompareDecimals:
3518  * @x:  a first decimal value
3519  * @y:  a second decimal value
3520  *
3521  * Compare 2 decimals
3522  *
3523  * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
3524  */
3525 static int
xmlSchemaCompareDecimals(xmlSchemaValPtr x,xmlSchemaValPtr y)3526 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
3527 {
3528     xmlSchemaValPtr swp;
3529     int order = 1, integx, integy, dlen;
3530     unsigned long hi, mi, lo;
3531 
3532     /*
3533      * First test: If x is -ve and not zero
3534      */
3535     if ((x->value.decimal.sign) &&
3536 	((x->value.decimal.lo != 0) ||
3537 	 (x->value.decimal.mi != 0) ||
3538 	 (x->value.decimal.hi != 0))) {
3539 	/*
3540 	 * Then if y is -ve and not zero reverse the compare
3541 	 */
3542 	if ((y->value.decimal.sign) &&
3543 	    ((y->value.decimal.lo != 0) ||
3544 	     (y->value.decimal.mi != 0) ||
3545 	     (y->value.decimal.hi != 0)))
3546 	    order = -1;
3547 	/*
3548 	 * Otherwise (y >= 0) we have the answer
3549 	 */
3550 	else
3551 	    return (-1);
3552     /*
3553      * If x is not -ve and y is -ve we have the answer
3554      */
3555     } else if ((y->value.decimal.sign) &&
3556 	       ((y->value.decimal.lo != 0) ||
3557 		(y->value.decimal.mi != 0) ||
3558 		(y->value.decimal.hi != 0))) {
3559         return (1);
3560     }
3561     /*
3562      * If it's not simply determined by a difference in sign,
3563      * then we need to compare the actual values of the two nums.
3564      * To do this, we start by looking at the integral parts.
3565      * If the number of integral digits differ, then we have our
3566      * answer.
3567      */
3568     integx = x->value.decimal.total - x->value.decimal.frac;
3569     integy = y->value.decimal.total - y->value.decimal.frac;
3570     /*
3571     * NOTE: We changed the "total" for values like "0.1"
3572     *   (or "-0.1" or ".1") to be 1, which was 2 previously.
3573     *   Therefore the special case, when such values are
3574     *   compared with 0, needs to be handled separately;
3575     *   otherwise a zero would be recognized incorrectly as
3576     *   greater than those values. This has the nice side effect
3577     *   that we gain an overall optimized comparison with zeroes.
3578     * Note that a "0" has a "total" of 1 already.
3579     */
3580     if (integx == 1) {
3581 	if (x->value.decimal.lo == 0) {
3582 	    if (integy != 1)
3583 		return -order;
3584 	    else if (y->value.decimal.lo != 0)
3585 		return -order;
3586 	    else
3587 		return(0);
3588 	}
3589     }
3590     if (integy == 1) {
3591 	if (y->value.decimal.lo == 0) {
3592 	    if (integx != 1)
3593 		return order;
3594 	    else if (x->value.decimal.lo != 0)
3595 		return order;
3596 	    else
3597 		return(0);
3598 	}
3599     }
3600 
3601     if (integx > integy)
3602 	return order;
3603     else if (integy > integx)
3604 	return -order;
3605 
3606     /*
3607      * If the number of integral digits is the same for both numbers,
3608      * then things get a little more complicated.  We need to "normalize"
3609      * the numbers in order to properly compare them.  To do this, we
3610      * look at the total length of each number (length => number of
3611      * significant digits), and divide the "shorter" by 10 (decreasing
3612      * the length) until they are of equal length.
3613      */
3614     dlen = x->value.decimal.total - y->value.decimal.total;
3615     if (dlen < 0) {	/* y has more digits than x */
3616 	swp = x;
3617 	hi = y->value.decimal.hi;
3618 	mi = y->value.decimal.mi;
3619 	lo = y->value.decimal.lo;
3620 	dlen = -dlen;
3621 	order = -order;
3622     } else {		/* x has more digits than y */
3623 	swp = y;
3624 	hi = x->value.decimal.hi;
3625 	mi = x->value.decimal.mi;
3626 	lo = x->value.decimal.lo;
3627     }
3628     while (dlen > 8) {	/* in effect, right shift by 10**8 */
3629 	lo = mi;
3630 	mi = hi;
3631 	hi = 0;
3632 	dlen -= 8;
3633     }
3634     while (dlen > 0) {
3635 	unsigned long rem1, rem2;
3636 	rem1 = (hi % 10) * 100000000L;
3637 	hi = hi / 10;
3638 	rem2 = (mi % 10) * 100000000L;
3639 	mi = (mi + rem1) / 10;
3640 	lo = (lo + rem2) / 10;
3641 	dlen--;
3642     }
3643     if (hi > swp->value.decimal.hi) {
3644 	return order;
3645     } else if (hi == swp->value.decimal.hi) {
3646 	if (mi > swp->value.decimal.mi) {
3647 	    return order;
3648 	} else if (mi == swp->value.decimal.mi) {
3649 	    if (lo > swp->value.decimal.lo) {
3650 		return order;
3651 	    } else if (lo == swp->value.decimal.lo) {
3652 		if (x->value.decimal.total == y->value.decimal.total) {
3653 		    return 0;
3654 		} else {
3655 		    return order;
3656 		}
3657 	    }
3658 	}
3659     }
3660     return -order;
3661 }
3662 
3663 /**
3664  * xmlSchemaCompareDurations:
3665  * @x:  a first duration value
3666  * @y:  a second duration value
3667  *
3668  * Compare 2 durations
3669  *
3670  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3671  * case of error
3672  */
3673 static int
xmlSchemaCompareDurations(xmlSchemaValPtr x,xmlSchemaValPtr y)3674 xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
3675 {
3676     long carry, mon, day;
3677     double sec;
3678     int invert = 1;
3679     long xmon, xday, myear, minday, maxday;
3680     static const long dayRange [2][12] = {
3681         { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
3682         { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
3683 
3684     if ((x == NULL) || (y == NULL))
3685         return -2;
3686 
3687     /* months */
3688     mon = x->value.dur.mon - y->value.dur.mon;
3689 
3690     /* seconds */
3691     sec = x->value.dur.sec - y->value.dur.sec;
3692     carry = (long)(sec / SECS_PER_DAY);
3693     sec -= ((double)carry) * SECS_PER_DAY;
3694 
3695     /* days */
3696     day = x->value.dur.day - y->value.dur.day + carry;
3697 
3698     /* easy test */
3699     if (mon == 0) {
3700         if (day == 0)
3701             if (sec == 0.0)
3702                 return 0;
3703             else if (sec < 0.0)
3704                 return -1;
3705             else
3706                 return 1;
3707         else if (day < 0)
3708             return -1;
3709         else
3710             return 1;
3711     }
3712 
3713     if (mon > 0) {
3714         if ((day >= 0) && (sec >= 0.0))
3715             return 1;
3716         else {
3717             xmon = mon;
3718             xday = -day;
3719         }
3720     } else if ((day <= 0) && (sec <= 0.0)) {
3721         return -1;
3722     } else {
3723 	invert = -1;
3724         xmon = -mon;
3725         xday = day;
3726     }
3727 
3728     myear = xmon / 12;
3729     if (myear == 0) {
3730 	minday = 0;
3731 	maxday = 0;
3732     } else {
3733         if (myear > LONG_MAX / 366)
3734             return -2;
3735         /* FIXME: This doesn't take leap year exceptions every 100/400 years
3736            into account. */
3737 	maxday = 365 * myear + (myear + 3) / 4;
3738         /* FIXME: Needs to be calculated separately */
3739 	minday = maxday - 1;
3740     }
3741 
3742     xmon = xmon % 12;
3743     minday += dayRange[0][xmon];
3744     maxday += dayRange[1][xmon];
3745 
3746     if ((maxday == minday) && (maxday == xday))
3747 	return(0); /* can this really happen ? */
3748     if (maxday < xday)
3749         return(-invert);
3750     if (minday > xday)
3751         return(invert);
3752 
3753     /* indeterminate */
3754     return 2;
3755 }
3756 
3757 /*
3758  * macros for adding date/times and durations
3759  */
3760 #define FQUOTIENT(a,b)                  (floor(((double)a/(double)b)))
3761 #define MODULO(a,b)                     (a - FQUOTIENT(a,b) * b)
3762 #define FQUOTIENT_RANGE(a,low,high)     (FQUOTIENT((a-low),(high-low)))
3763 #define MODULO_RANGE(a,low,high)        ((MODULO((a-low),(high-low)))+low)
3764 
3765 /**
3766  * xmlSchemaDupVal:
3767  * @v: the #xmlSchemaValPtr value to duplicate
3768  *
3769  * Makes a copy of @v. The calling program is responsible for freeing
3770  * the returned value.
3771  *
3772  * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error.
3773  */
3774 static xmlSchemaValPtr
xmlSchemaDupVal(xmlSchemaValPtr v)3775 xmlSchemaDupVal (xmlSchemaValPtr v)
3776 {
3777     xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
3778     if (ret == NULL)
3779         return NULL;
3780 
3781     memcpy(ret, v, sizeof(xmlSchemaVal));
3782     ret->next = NULL;
3783     return ret;
3784 }
3785 
3786 /**
3787  * xmlSchemaCopyValue:
3788  * @val:  the precomputed value to be copied
3789  *
3790  * Copies the precomputed value. This duplicates any string within.
3791  *
3792  * Returns the copy or NULL if a copy for a data-type is not implemented.
3793  */
3794 xmlSchemaValPtr
xmlSchemaCopyValue(xmlSchemaValPtr val)3795 xmlSchemaCopyValue(xmlSchemaValPtr val)
3796 {
3797     xmlSchemaValPtr ret = NULL, prev = NULL, cur;
3798 
3799     /*
3800     * Copy the string values.
3801     */
3802     while (val != NULL) {
3803 	switch (val->type) {
3804 	    case XML_SCHEMAS_ANYTYPE:
3805 	    case XML_SCHEMAS_IDREFS:
3806 	    case XML_SCHEMAS_ENTITIES:
3807 	    case XML_SCHEMAS_NMTOKENS:
3808 		xmlSchemaFreeValue(ret);
3809 		return (NULL);
3810 	    case XML_SCHEMAS_ANYSIMPLETYPE:
3811 	    case XML_SCHEMAS_STRING:
3812 	    case XML_SCHEMAS_NORMSTRING:
3813 	    case XML_SCHEMAS_TOKEN:
3814 	    case XML_SCHEMAS_LANGUAGE:
3815 	    case XML_SCHEMAS_NAME:
3816 	    case XML_SCHEMAS_NCNAME:
3817 	    case XML_SCHEMAS_ID:
3818 	    case XML_SCHEMAS_IDREF:
3819 	    case XML_SCHEMAS_ENTITY:
3820 	    case XML_SCHEMAS_NMTOKEN:
3821 	    case XML_SCHEMAS_ANYURI:
3822 		cur = xmlSchemaDupVal(val);
3823 		if (val->value.str != NULL)
3824 		    cur->value.str = xmlStrdup(BAD_CAST val->value.str);
3825 		break;
3826 	    case XML_SCHEMAS_QNAME:
3827 	    case XML_SCHEMAS_NOTATION:
3828 		cur = xmlSchemaDupVal(val);
3829 		if (val->value.qname.name != NULL)
3830 		    cur->value.qname.name =
3831                     xmlStrdup(BAD_CAST val->value.qname.name);
3832 		if (val->value.qname.uri != NULL)
3833 		    cur->value.qname.uri =
3834                     xmlStrdup(BAD_CAST val->value.qname.uri);
3835 		break;
3836 	    case XML_SCHEMAS_HEXBINARY:
3837 		cur = xmlSchemaDupVal(val);
3838 		if (val->value.hex.str != NULL)
3839 		    cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str);
3840 		break;
3841 	    case XML_SCHEMAS_BASE64BINARY:
3842 		cur = xmlSchemaDupVal(val);
3843 		if (val->value.base64.str != NULL)
3844 		    cur->value.base64.str =
3845                     xmlStrdup(BAD_CAST val->value.base64.str);
3846 		break;
3847 	    default:
3848 		cur = xmlSchemaDupVal(val);
3849 		break;
3850 	}
3851 	if (ret == NULL)
3852 	    ret = cur;
3853 	else
3854 	    prev->next = cur;
3855 	prev = cur;
3856 	val = val->next;
3857     }
3858     return (ret);
3859 }
3860 
3861 /**
3862  * _xmlSchemaDateAdd:
3863  * @dt: an #xmlSchemaValPtr
3864  * @dur: an #xmlSchemaValPtr of type #XS_DURATION
3865  *
3866  * Compute a new date/time from @dt and @dur. This function assumes @dt
3867  * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
3868  * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as
3869  * @dt. The calling program is responsible for freeing the returned value.
3870  *
3871  * Returns a pointer to a new #xmlSchemaVal or NULL if error.
3872  */
3873 static xmlSchemaValPtr
_xmlSchemaDateAdd(xmlSchemaValPtr dt,xmlSchemaValPtr dur)3874 _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
3875 {
3876     xmlSchemaValPtr ret, tmp;
3877     long carry, tempdays, temp;
3878     xmlSchemaValDatePtr r, d;
3879     xmlSchemaValDurationPtr u;
3880 
3881     if ((dt == NULL) || (dur == NULL))
3882         return NULL;
3883 
3884     ret = xmlSchemaNewValue(dt->type);
3885     if (ret == NULL)
3886         return NULL;
3887 
3888     /* make a copy so we don't alter the original value */
3889     tmp = xmlSchemaDupVal(dt);
3890     if (tmp == NULL) {
3891         xmlSchemaFreeValue(ret);
3892         return NULL;
3893     }
3894 
3895     r = &(ret->value.date);
3896     d = &(tmp->value.date);
3897     u = &(dur->value.dur);
3898 
3899     /* normalization */
3900     if (d->mon == 0)
3901         d->mon = 1;
3902 
3903     /* normalize for time zone offset */
3904     u->sec -= (d->tzo * 60);
3905     d->tzo = 0;
3906 
3907     /* normalization */
3908     if (d->day == 0)
3909         d->day = 1;
3910 
3911     /* month */
3912     carry  = d->mon + u->mon;
3913     r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13);
3914     carry  = (long) FQUOTIENT_RANGE(carry, 1, 13);
3915 
3916     /* year (may be modified later) */
3917     r->year = d->year + carry;
3918     if (r->year == 0) {
3919         if (d->year > 0)
3920             r->year--;
3921         else
3922             r->year++;
3923     }
3924 
3925     /* time zone */
3926     r->tzo     = d->tzo;
3927     r->tz_flag = d->tz_flag;
3928 
3929     /* seconds */
3930     r->sec = d->sec + u->sec;
3931     carry  = (long) FQUOTIENT((long)r->sec, 60);
3932     if (r->sec != 0.0) {
3933         r->sec = MODULO(r->sec, 60.0);
3934     }
3935 
3936     /* minute */
3937     carry += d->min;
3938     r->min = (unsigned int) MODULO(carry, 60);
3939     carry  = (long) FQUOTIENT(carry, 60);
3940 
3941     /* hours */
3942     carry  += d->hour;
3943     r->hour = (unsigned int) MODULO(carry, 24);
3944     carry   = (long)FQUOTIENT(carry, 24);
3945 
3946     /*
3947      * days
3948      * Note we use tempdays because the temporary values may need more
3949      * than 5 bits
3950      */
3951     if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
3952                   (d->day > MAX_DAYINMONTH(r->year, r->mon)))
3953         tempdays = MAX_DAYINMONTH(r->year, r->mon);
3954     else if (d->day < 1)
3955         tempdays = 1;
3956     else
3957         tempdays = d->day;
3958 
3959     tempdays += u->day + carry;
3960 
3961     while (1) {
3962         if (tempdays < 1) {
3963             long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13);
3964             long tyr  = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13);
3965             if (tyr == 0)
3966                 tyr--;
3967 	    /*
3968 	     * Coverity detected an overrun in daysInMonth
3969 	     * of size 12 at position 12 with index variable "((r)->mon - 1)"
3970 	     */
3971 	    if (tmon < 1)
3972 	        tmon = 1;
3973 	    if (tmon > 12)
3974 	        tmon = 12;
3975             tempdays += MAX_DAYINMONTH(tyr, tmon);
3976             carry = -1;
3977         } else if (VALID_YEAR(r->year) && VALID_MONTH(r->mon) &&
3978                    tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) {
3979             tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
3980             carry = 1;
3981         } else
3982             break;
3983 
3984         temp = r->mon + carry;
3985         r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13);
3986         r->year = r->year + (long) FQUOTIENT_RANGE(temp, 1, 13);
3987         if (r->year == 0) {
3988             if (temp < 1)
3989                 r->year--;
3990             else
3991                 r->year++;
3992 	}
3993     }
3994 
3995     r->day = tempdays;
3996 
3997     /*
3998      * adjust the date/time type to the date values
3999      */
4000     if (ret->type != XML_SCHEMAS_DATETIME) {
4001         if ((r->hour) || (r->min) || (r->sec))
4002             ret->type = XML_SCHEMAS_DATETIME;
4003         else if (ret->type != XML_SCHEMAS_DATE) {
4004             if ((r->mon != 1) && (r->day != 1))
4005                 ret->type = XML_SCHEMAS_DATE;
4006             else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
4007                 ret->type = XML_SCHEMAS_GYEARMONTH;
4008         }
4009     }
4010 
4011     xmlSchemaFreeValue(tmp);
4012 
4013     return ret;
4014 }
4015 
4016 /**
4017  * xmlSchemaDateNormalize:
4018  * @dt: an #xmlSchemaValPtr of a date/time type value.
4019  * @offset: number of seconds to adjust @dt by.
4020  *
4021  * Normalize @dt to GMT time. The @offset parameter is subtracted from
4022  * the return value is a time-zone offset is present on @dt.
4023  *
4024  * Returns a normalized copy of @dt or NULL if error.
4025  */
4026 static xmlSchemaValPtr
xmlSchemaDateNormalize(xmlSchemaValPtr dt,double offset)4027 xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
4028 {
4029     xmlSchemaValPtr dur, ret;
4030 
4031     if (dt == NULL)
4032         return NULL;
4033 
4034     if (((dt->type != XML_SCHEMAS_TIME) &&
4035          (dt->type != XML_SCHEMAS_DATETIME) &&
4036 	 (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0))
4037         return xmlSchemaDupVal(dt);
4038 
4039     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
4040     if (dur == NULL)
4041         return NULL;
4042 
4043     dur->value.date.sec -= offset;
4044 
4045     ret = _xmlSchemaDateAdd(dt, dur);
4046     if (ret == NULL)
4047         return NULL;
4048 
4049     xmlSchemaFreeValue(dur);
4050 
4051     /* ret->value.date.tzo = 0; */
4052     return ret;
4053 }
4054 
4055 /**
4056  * _xmlSchemaDateCastYMToDays:
4057  * @dt: an #xmlSchemaValPtr
4058  *
4059  * Convert mon and year of @dt to total number of days. Take the
4060  * number of years since (or before) 1 AD and add the number of leap
4061  * years. This is a function  because negative
4062  * years must be handled a little differently and there is no zero year.
4063  *
4064  * Returns number of days.
4065  */
4066 static long
_xmlSchemaDateCastYMToDays(const xmlSchemaValPtr dt)4067 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
4068 {
4069     long ret;
4070     int mon;
4071 
4072     mon = dt->value.date.mon;
4073     if (mon <= 0) mon = 1; /* normalization */
4074 
4075     if (dt->value.date.year <= 0)
4076         ret = (dt->value.date.year * 365) +
4077               (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
4078                ((dt->value.date.year+1)/400)) +
4079               DAY_IN_YEAR(0, mon, dt->value.date.year);
4080     else
4081         ret = ((dt->value.date.year-1) * 365) +
4082               (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
4083                ((dt->value.date.year-1)/400)) +
4084               DAY_IN_YEAR(0, mon, dt->value.date.year);
4085 
4086     return ret;
4087 }
4088 
4089 /**
4090  * TIME_TO_NUMBER:
4091  * @dt:  an #xmlSchemaValPtr
4092  *
4093  * Calculates the number of seconds in the time portion of @dt.
4094  *
4095  * Returns seconds.
4096  */
4097 #define TIME_TO_NUMBER(dt)                              \
4098     ((double)((dt->value.date.hour * SECS_PER_HOUR) +   \
4099               (dt->value.date.min * SECS_PER_MIN) +	\
4100               (dt->value.date.tzo * SECS_PER_MIN)) +	\
4101                dt->value.date.sec)
4102 
4103 /**
4104  * xmlSchemaCompareDates:
4105  * @x:  a first date/time value
4106  * @y:  a second date/time value
4107  *
4108  * Compare 2 date/times
4109  *
4110  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4111  * case of error
4112  */
4113 static int
xmlSchemaCompareDates(xmlSchemaValPtr x,xmlSchemaValPtr y)4114 xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
4115 {
4116     unsigned char xmask, ymask, xor_mask, and_mask;
4117     xmlSchemaValPtr p1, p2, q1, q2;
4118     long p1d, p2d, q1d, q2d;
4119 
4120     if ((x == NULL) || (y == NULL))
4121         return -2;
4122 
4123     if ((x->value.date.year > LONG_MAX / 366) ||
4124         (x->value.date.year < LONG_MIN / 366) ||
4125         (y->value.date.year > LONG_MAX / 366) ||
4126         (y->value.date.year < LONG_MIN / 366)) {
4127         /* Possible overflow when converting to days. */
4128         return -2;
4129     }
4130 
4131     if (x->value.date.tz_flag) {
4132 
4133         if (!y->value.date.tz_flag) {
4134             p1 = xmlSchemaDateNormalize(x, 0);
4135             p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4136             /* normalize y + 14:00 */
4137             q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
4138 
4139             q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4140             if (p1d < q1d) {
4141 		xmlSchemaFreeValue(p1);
4142 		xmlSchemaFreeValue(q1);
4143                 return -1;
4144 	    } else if (p1d == q1d) {
4145                 double sec;
4146 
4147                 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4148                 if (sec < 0.0) {
4149 		    xmlSchemaFreeValue(p1);
4150 		    xmlSchemaFreeValue(q1);
4151                     return -1;
4152 		} else {
4153 		    int ret = 0;
4154                     /* normalize y - 14:00 */
4155                     q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
4156                     q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
4157                     if (p1d > q2d)
4158                         ret = 1;
4159                     else if (p1d == q2d) {
4160                         sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
4161                         if (sec > 0.0)
4162                             ret = 1;
4163                         else
4164                             ret = 2; /* indeterminate */
4165                     }
4166 		    xmlSchemaFreeValue(p1);
4167 		    xmlSchemaFreeValue(q1);
4168 		    xmlSchemaFreeValue(q2);
4169 		    if (ret != 0)
4170 		        return(ret);
4171                 }
4172             } else {
4173 		xmlSchemaFreeValue(p1);
4174 		xmlSchemaFreeValue(q1);
4175 	    }
4176         }
4177     } else if (y->value.date.tz_flag) {
4178         q1 = xmlSchemaDateNormalize(y, 0);
4179         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4180 
4181         /* normalize x - 14:00 */
4182         p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
4183         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4184 
4185         if (p1d < q1d) {
4186 	    xmlSchemaFreeValue(p1);
4187 	    xmlSchemaFreeValue(q1);
4188             return -1;
4189 	} else if (p1d == q1d) {
4190             double sec;
4191 
4192             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4193             if (sec < 0.0) {
4194 		xmlSchemaFreeValue(p1);
4195 		xmlSchemaFreeValue(q1);
4196                 return -1;
4197 	    } else {
4198 	        int ret = 0;
4199                 /* normalize x + 14:00 */
4200                 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
4201                 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
4202 
4203                 if (p2d > q1d) {
4204                     ret = 1;
4205 		} else if (p2d == q1d) {
4206                     sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
4207                     if (sec > 0.0)
4208                         ret = 1;
4209                     else
4210                         ret = 2; /* indeterminate */
4211                 }
4212 		xmlSchemaFreeValue(p1);
4213 		xmlSchemaFreeValue(q1);
4214 		xmlSchemaFreeValue(p2);
4215 		if (ret != 0)
4216 		    return(ret);
4217             }
4218 	} else {
4219 	    xmlSchemaFreeValue(p1);
4220 	    xmlSchemaFreeValue(q1);
4221         }
4222     }
4223 
4224     /*
4225      * if the same type then calculate the difference
4226      */
4227     if (x->type == y->type) {
4228         int ret = 0;
4229         q1 = xmlSchemaDateNormalize(y, 0);
4230         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4231 
4232         p1 = xmlSchemaDateNormalize(x, 0);
4233         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4234 
4235         if (p1d < q1d) {
4236             ret = -1;
4237 	} else if (p1d > q1d) {
4238             ret = 1;
4239 	} else {
4240             double sec;
4241 
4242             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4243             if (sec < 0.0)
4244                 ret = -1;
4245             else if (sec > 0.0)
4246                 ret = 1;
4247 
4248         }
4249 	xmlSchemaFreeValue(p1);
4250 	xmlSchemaFreeValue(q1);
4251         return(ret);
4252     }
4253 
4254     switch (x->type) {
4255         case XML_SCHEMAS_DATETIME:
4256             xmask = 0xf;
4257             break;
4258         case XML_SCHEMAS_DATE:
4259             xmask = 0x7;
4260             break;
4261         case XML_SCHEMAS_GYEAR:
4262             xmask = 0x1;
4263             break;
4264         case XML_SCHEMAS_GMONTH:
4265             xmask = 0x2;
4266             break;
4267         case XML_SCHEMAS_GDAY:
4268             xmask = 0x3;
4269             break;
4270         case XML_SCHEMAS_GYEARMONTH:
4271             xmask = 0x3;
4272             break;
4273         case XML_SCHEMAS_GMONTHDAY:
4274             xmask = 0x6;
4275             break;
4276         case XML_SCHEMAS_TIME:
4277             xmask = 0x8;
4278             break;
4279         default:
4280             xmask = 0;
4281             break;
4282     }
4283 
4284     switch (y->type) {
4285         case XML_SCHEMAS_DATETIME:
4286             ymask = 0xf;
4287             break;
4288         case XML_SCHEMAS_DATE:
4289             ymask = 0x7;
4290             break;
4291         case XML_SCHEMAS_GYEAR:
4292             ymask = 0x1;
4293             break;
4294         case XML_SCHEMAS_GMONTH:
4295             ymask = 0x2;
4296             break;
4297         case XML_SCHEMAS_GDAY:
4298             ymask = 0x3;
4299             break;
4300         case XML_SCHEMAS_GYEARMONTH:
4301             ymask = 0x3;
4302             break;
4303         case XML_SCHEMAS_GMONTHDAY:
4304             ymask = 0x6;
4305             break;
4306         case XML_SCHEMAS_TIME:
4307             ymask = 0x8;
4308             break;
4309         default:
4310             ymask = 0;
4311             break;
4312     }
4313 
4314     xor_mask = xmask ^ ymask;           /* mark type differences */
4315     and_mask = xmask & ymask;           /* mark field specification */
4316 
4317     /* year */
4318     if (xor_mask & 1)
4319         return 2; /* indeterminate */
4320     else if (and_mask & 1) {
4321         if (x->value.date.year < y->value.date.year)
4322             return -1;
4323         else if (x->value.date.year > y->value.date.year)
4324             return 1;
4325     }
4326 
4327     /* month */
4328     if (xor_mask & 2)
4329         return 2; /* indeterminate */
4330     else if (and_mask & 2) {
4331         if (x->value.date.mon < y->value.date.mon)
4332             return -1;
4333         else if (x->value.date.mon > y->value.date.mon)
4334             return 1;
4335     }
4336 
4337     /* day */
4338     if (xor_mask & 4)
4339         return 2; /* indeterminate */
4340     else if (and_mask & 4) {
4341         if (x->value.date.day < y->value.date.day)
4342             return -1;
4343         else if (x->value.date.day > y->value.date.day)
4344             return 1;
4345     }
4346 
4347     /* time */
4348     if (xor_mask & 8)
4349         return 2; /* indeterminate */
4350     else if (and_mask & 8) {
4351         if (x->value.date.hour < y->value.date.hour)
4352             return -1;
4353         else if (x->value.date.hour > y->value.date.hour)
4354             return 1;
4355         else if (x->value.date.min < y->value.date.min)
4356             return -1;
4357         else if (x->value.date.min > y->value.date.min)
4358             return 1;
4359         else if (x->value.date.sec < y->value.date.sec)
4360             return -1;
4361         else if (x->value.date.sec > y->value.date.sec)
4362             return 1;
4363     }
4364 
4365     return 0;
4366 }
4367 
4368 /**
4369  * xmlSchemaComparePreserveReplaceStrings:
4370  * @x:  a first string value
4371  * @y:  a second string value
4372  * @invert: inverts the result if x < y or x > y.
4373  *
4374  * Compare 2 string for their normalized values.
4375  * @x is a string with whitespace of "preserve", @y is
4376  * a string with a whitespace of "replace". I.e. @x could
4377  * be an "xsd:string" and @y an "xsd:normalizedString".
4378  *
4379  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4380  * case of error
4381  */
4382 static int
xmlSchemaComparePreserveReplaceStrings(const xmlChar * x,const xmlChar * y,int invert)4383 xmlSchemaComparePreserveReplaceStrings(const xmlChar *x,
4384 				       const xmlChar *y,
4385 				       int invert)
4386 {
4387     int tmp;
4388 
4389     while ((*x != 0) && (*y != 0)) {
4390 	if (IS_WSP_REPLACE_CH(*y)) {
4391 	    if (! IS_WSP_SPACE_CH(*x)) {
4392 		if ((*x - 0x20) < 0) {
4393 		    if (invert)
4394 			return(1);
4395 		    else
4396 			return(-1);
4397 		} else {
4398 		    if (invert)
4399 			return(-1);
4400 		    else
4401 			return(1);
4402 		}
4403 	    }
4404 	} else {
4405 	    tmp = *x - *y;
4406 	    if (tmp < 0) {
4407 		if (invert)
4408 		    return(1);
4409 		else
4410 		    return(-1);
4411 	    }
4412 	    if (tmp > 0) {
4413 		if (invert)
4414 		    return(-1);
4415 		else
4416 		    return(1);
4417 	    }
4418 	}
4419 	x++;
4420 	y++;
4421     }
4422     if (*x != 0) {
4423 	if (invert)
4424 	    return(-1);
4425 	else
4426 	    return(1);
4427     }
4428     if (*y != 0) {
4429 	if (invert)
4430 	    return(1);
4431 	else
4432 	    return(-1);
4433     }
4434     return(0);
4435 }
4436 
4437 /**
4438  * xmlSchemaComparePreserveCollapseStrings:
4439  * @x:  a first string value
4440  * @y:  a second string value
4441  *
4442  * Compare 2 string for their normalized values.
4443  * @x is a string with whitespace of "preserve", @y is
4444  * a string with a whitespace of "collapse". I.e. @x could
4445  * be an "xsd:string" and @y an "xsd:normalizedString".
4446  *
4447  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4448  * case of error
4449  */
4450 static int
xmlSchemaComparePreserveCollapseStrings(const xmlChar * x,const xmlChar * y,int invert)4451 xmlSchemaComparePreserveCollapseStrings(const xmlChar *x,
4452 				        const xmlChar *y,
4453 					int invert)
4454 {
4455     int tmp;
4456 
4457     /*
4458     * Skip leading blank chars of the collapsed string.
4459     */
4460     while IS_WSP_BLANK_CH(*y)
4461 	y++;
4462 
4463     while ((*x != 0) && (*y != 0)) {
4464 	if IS_WSP_BLANK_CH(*y) {
4465 	    if (! IS_WSP_SPACE_CH(*x)) {
4466 		/*
4467 		* The yv character would have been replaced to 0x20.
4468 		*/
4469 		if ((*x - 0x20) < 0) {
4470 		    if (invert)
4471 			return(1);
4472 		    else
4473 			return(-1);
4474 		} else {
4475 		    if (invert)
4476 			return(-1);
4477 		    else
4478 			return(1);
4479 		}
4480 	    }
4481 	    x++;
4482 	    y++;
4483 	    /*
4484 	    * Skip contiguous blank chars of the collapsed string.
4485 	    */
4486 	    while IS_WSP_BLANK_CH(*y)
4487 		y++;
4488 	} else {
4489 	    tmp = *x++ - *y++;
4490 	    if (tmp < 0) {
4491 		if (invert)
4492 		    return(1);
4493 		else
4494 		    return(-1);
4495 	    }
4496 	    if (tmp > 0) {
4497 		if (invert)
4498 		    return(-1);
4499 		else
4500 		    return(1);
4501 	    }
4502 	}
4503     }
4504     if (*x != 0) {
4505 	 if (invert)
4506 	     return(-1);
4507 	 else
4508 	     return(1);
4509     }
4510     if (*y != 0) {
4511 	/*
4512 	* Skip trailing blank chars of the collapsed string.
4513 	*/
4514 	while IS_WSP_BLANK_CH(*y)
4515 	    y++;
4516 	if (*y != 0) {
4517 	    if (invert)
4518 		return(1);
4519 	    else
4520 		return(-1);
4521 	}
4522     }
4523     return(0);
4524 }
4525 
4526 /**
4527  * xmlSchemaComparePreserveCollapseStrings:
4528  * @x:  a first string value
4529  * @y:  a second string value
4530  *
4531  * Compare 2 string for their normalized values.
4532  * @x is a string with whitespace of "preserve", @y is
4533  * a string with a whitespace of "collapse". I.e. @x could
4534  * be an "xsd:string" and @y an "xsd:normalizedString".
4535  *
4536  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4537  * case of error
4538  */
4539 static int
xmlSchemaCompareReplaceCollapseStrings(const xmlChar * x,const xmlChar * y,int invert)4540 xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x,
4541 				       const xmlChar *y,
4542 				       int invert)
4543 {
4544     int tmp;
4545 
4546     /*
4547     * Skip leading blank chars of the collapsed string.
4548     */
4549     while IS_WSP_BLANK_CH(*y)
4550 	y++;
4551 
4552     while ((*x != 0) && (*y != 0)) {
4553 	if IS_WSP_BLANK_CH(*y) {
4554 	    if (! IS_WSP_BLANK_CH(*x)) {
4555 		/*
4556 		* The yv character would have been replaced to 0x20.
4557 		*/
4558 		if ((*x - 0x20) < 0) {
4559 		    if (invert)
4560 			return(1);
4561 		    else
4562 			return(-1);
4563 		} else {
4564 		    if (invert)
4565 			return(-1);
4566 		    else
4567 			return(1);
4568 		}
4569 	    }
4570 	    x++;
4571 	    y++;
4572 	    /*
4573 	    * Skip contiguous blank chars of the collapsed string.
4574 	    */
4575 	    while IS_WSP_BLANK_CH(*y)
4576 		y++;
4577 	} else {
4578 	    if IS_WSP_BLANK_CH(*x) {
4579 		/*
4580 		* The xv character would have been replaced to 0x20.
4581 		*/
4582 		if ((0x20 - *y) < 0) {
4583 		    if (invert)
4584 			return(1);
4585 		    else
4586 			return(-1);
4587 		} else {
4588 		    if (invert)
4589 			return(-1);
4590 		    else
4591 			return(1);
4592 		}
4593 	    }
4594 	    tmp = *x++ - *y++;
4595 	    if (tmp < 0)
4596 		return(-1);
4597 	    if (tmp > 0)
4598 		return(1);
4599 	}
4600     }
4601     if (*x != 0) {
4602 	 if (invert)
4603 	     return(-1);
4604 	 else
4605 	     return(1);
4606     }
4607     if (*y != 0) {
4608 	/*
4609 	* Skip trailing blank chars of the collapsed string.
4610 	*/
4611 	while IS_WSP_BLANK_CH(*y)
4612 	    y++;
4613 	if (*y != 0) {
4614 	    if (invert)
4615 		return(1);
4616 	    else
4617 		return(-1);
4618 	}
4619     }
4620     return(0);
4621 }
4622 
4623 
4624 /**
4625  * xmlSchemaCompareReplacedStrings:
4626  * @x:  a first string value
4627  * @y:  a second string value
4628  *
4629  * Compare 2 string for their normalized values.
4630  *
4631  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4632  * case of error
4633  */
4634 static int
xmlSchemaCompareReplacedStrings(const xmlChar * x,const xmlChar * y)4635 xmlSchemaCompareReplacedStrings(const xmlChar *x,
4636 				const xmlChar *y)
4637 {
4638     int tmp;
4639 
4640     while ((*x != 0) && (*y != 0)) {
4641 	if IS_WSP_BLANK_CH(*y) {
4642 	    if (! IS_WSP_BLANK_CH(*x)) {
4643 		if ((*x - 0x20) < 0)
4644 		    return(-1);
4645 		else
4646 		    return(1);
4647 	    }
4648 	} else {
4649 	    if IS_WSP_BLANK_CH(*x) {
4650 		if ((0x20 - *y) < 0)
4651 		    return(-1);
4652 		else
4653 		    return(1);
4654 	    }
4655 	    tmp = *x - *y;
4656 	    if (tmp < 0)
4657 		return(-1);
4658 	    if (tmp > 0)
4659 		return(1);
4660 	}
4661 	x++;
4662 	y++;
4663     }
4664     if (*x != 0)
4665         return(1);
4666     if (*y != 0)
4667         return(-1);
4668     return(0);
4669 }
4670 
4671 /**
4672  * xmlSchemaCompareNormStrings:
4673  * @x:  a first string value
4674  * @y:  a second string value
4675  *
4676  * Compare 2 string for their normalized values.
4677  *
4678  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4679  * case of error
4680  */
4681 static int
xmlSchemaCompareNormStrings(const xmlChar * x,const xmlChar * y)4682 xmlSchemaCompareNormStrings(const xmlChar *x,
4683 			    const xmlChar *y) {
4684     int tmp;
4685 
4686     while (IS_BLANK_CH(*x)) x++;
4687     while (IS_BLANK_CH(*y)) y++;
4688     while ((*x != 0) && (*y != 0)) {
4689 	if (IS_BLANK_CH(*x)) {
4690 	    if (!IS_BLANK_CH(*y)) {
4691 		tmp = *x - *y;
4692 		return(tmp);
4693 	    }
4694 	    while (IS_BLANK_CH(*x)) x++;
4695 	    while (IS_BLANK_CH(*y)) y++;
4696 	} else {
4697 	    tmp = *x++ - *y++;
4698 	    if (tmp < 0)
4699 		return(-1);
4700 	    if (tmp > 0)
4701 		return(1);
4702 	}
4703     }
4704     if (*x != 0) {
4705 	while (IS_BLANK_CH(*x)) x++;
4706 	if (*x != 0)
4707 	    return(1);
4708     }
4709     if (*y != 0) {
4710 	while (IS_BLANK_CH(*y)) y++;
4711 	if (*y != 0)
4712 	    return(-1);
4713     }
4714     return(0);
4715 }
4716 
4717 /**
4718  * xmlSchemaCompareFloats:
4719  * @x:  a first float or double value
4720  * @y:  a second float or double value
4721  *
4722  * Compare 2 values
4723  *
4724  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4725  * case of error
4726  */
4727 static int
xmlSchemaCompareFloats(xmlSchemaValPtr x,xmlSchemaValPtr y)4728 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
4729     double d1, d2;
4730 
4731     if ((x == NULL) || (y == NULL))
4732 	return(-2);
4733 
4734     /*
4735      * Cast everything to doubles.
4736      */
4737     if (x->type == XML_SCHEMAS_DOUBLE)
4738 	d1 = x->value.d;
4739     else if (x->type == XML_SCHEMAS_FLOAT)
4740 	d1 = x->value.f;
4741     else
4742 	return(-2);
4743 
4744     if (y->type == XML_SCHEMAS_DOUBLE)
4745 	d2 = y->value.d;
4746     else if (y->type == XML_SCHEMAS_FLOAT)
4747 	d2 = y->value.f;
4748     else
4749 	return(-2);
4750 
4751     /*
4752      * Check for special cases.
4753      */
4754     if (xmlXPathIsNaN(d1)) {
4755 	if (xmlXPathIsNaN(d2))
4756 	    return(0);
4757 	return(1);
4758     }
4759     if (xmlXPathIsNaN(d2))
4760 	return(-1);
4761     if (d1 == xmlXPathPINF) {
4762 	if (d2 == xmlXPathPINF)
4763 	    return(0);
4764         return(1);
4765     }
4766     if (d2 == xmlXPathPINF)
4767         return(-1);
4768     if (d1 == xmlXPathNINF) {
4769 	if (d2 == xmlXPathNINF)
4770 	    return(0);
4771         return(-1);
4772     }
4773     if (d2 == xmlXPathNINF)
4774         return(1);
4775 
4776     /*
4777      * basic tests, the last one we should have equality, but
4778      * portability is more important than speed and handling
4779      * NaN or Inf in a portable way is always a challenge, so ...
4780      */
4781     if (d1 < d2)
4782 	return(-1);
4783     if (d1 > d2)
4784 	return(1);
4785     if (d1 == d2)
4786 	return(0);
4787     return(2);
4788 }
4789 
4790 /**
4791  * xmlSchemaCompareValues:
4792  * @x:  a first value
4793  * @xvalue: the first value as a string (optional)
4794  * @xwtsp: the whitespace type
4795  * @y:  a second value
4796  * @xvalue: the second value as a string (optional)
4797  * @ywtsp: the whitespace type
4798  *
4799  * Compare 2 values
4800  *
4801  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not
4802  * comparable and -2 in case of error
4803  */
4804 static int
xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,xmlSchemaValPtr x,const xmlChar * xvalue,xmlSchemaWhitespaceValueType xws,xmlSchemaValType ytype,xmlSchemaValPtr y,const xmlChar * yvalue,xmlSchemaWhitespaceValueType yws)4805 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
4806 			       xmlSchemaValPtr x,
4807 			       const xmlChar *xvalue,
4808 			       xmlSchemaWhitespaceValueType xws,
4809 			       xmlSchemaValType ytype,
4810 			       xmlSchemaValPtr y,
4811 			       const xmlChar *yvalue,
4812 			       xmlSchemaWhitespaceValueType yws)
4813 {
4814     switch (xtype) {
4815 	case XML_SCHEMAS_UNKNOWN:
4816 	case XML_SCHEMAS_ANYTYPE:
4817 	    return(-2);
4818         case XML_SCHEMAS_INTEGER:
4819         case XML_SCHEMAS_NPINTEGER:
4820         case XML_SCHEMAS_NINTEGER:
4821         case XML_SCHEMAS_NNINTEGER:
4822         case XML_SCHEMAS_PINTEGER:
4823         case XML_SCHEMAS_INT:
4824         case XML_SCHEMAS_UINT:
4825         case XML_SCHEMAS_LONG:
4826         case XML_SCHEMAS_ULONG:
4827         case XML_SCHEMAS_SHORT:
4828         case XML_SCHEMAS_USHORT:
4829         case XML_SCHEMAS_BYTE:
4830         case XML_SCHEMAS_UBYTE:
4831 	case XML_SCHEMAS_DECIMAL:
4832 	    if ((x == NULL) || (y == NULL))
4833 		return(-2);
4834 	    if (ytype == xtype)
4835 		return(xmlSchemaCompareDecimals(x, y));
4836 	    if ((ytype == XML_SCHEMAS_DECIMAL) ||
4837 		(ytype == XML_SCHEMAS_INTEGER) ||
4838 		(ytype == XML_SCHEMAS_NPINTEGER) ||
4839 		(ytype == XML_SCHEMAS_NINTEGER) ||
4840 		(ytype == XML_SCHEMAS_NNINTEGER) ||
4841 		(ytype == XML_SCHEMAS_PINTEGER) ||
4842 		(ytype == XML_SCHEMAS_INT) ||
4843 		(ytype == XML_SCHEMAS_UINT) ||
4844 		(ytype == XML_SCHEMAS_LONG) ||
4845 		(ytype == XML_SCHEMAS_ULONG) ||
4846 		(ytype == XML_SCHEMAS_SHORT) ||
4847 		(ytype == XML_SCHEMAS_USHORT) ||
4848 		(ytype == XML_SCHEMAS_BYTE) ||
4849 		(ytype == XML_SCHEMAS_UBYTE))
4850 		return(xmlSchemaCompareDecimals(x, y));
4851 	    return(-2);
4852         case XML_SCHEMAS_DURATION:
4853 	    if ((x == NULL) || (y == NULL))
4854 		return(-2);
4855 	    if (ytype == XML_SCHEMAS_DURATION)
4856                 return(xmlSchemaCompareDurations(x, y));
4857             return(-2);
4858         case XML_SCHEMAS_TIME:
4859         case XML_SCHEMAS_GDAY:
4860         case XML_SCHEMAS_GMONTH:
4861         case XML_SCHEMAS_GMONTHDAY:
4862         case XML_SCHEMAS_GYEAR:
4863         case XML_SCHEMAS_GYEARMONTH:
4864         case XML_SCHEMAS_DATE:
4865         case XML_SCHEMAS_DATETIME:
4866 	    if ((x == NULL) || (y == NULL))
4867 		return(-2);
4868             if ((ytype == XML_SCHEMAS_DATETIME)  ||
4869                 (ytype == XML_SCHEMAS_TIME)      ||
4870                 (ytype == XML_SCHEMAS_GDAY)      ||
4871                 (ytype == XML_SCHEMAS_GMONTH)    ||
4872                 (ytype == XML_SCHEMAS_GMONTHDAY) ||
4873                 (ytype == XML_SCHEMAS_GYEAR)     ||
4874                 (ytype == XML_SCHEMAS_DATE)      ||
4875                 (ytype == XML_SCHEMAS_GYEARMONTH))
4876                 return (xmlSchemaCompareDates(x, y));
4877             return (-2);
4878 	/*
4879 	* Note that we will support comparison of string types against
4880 	* anySimpleType as well.
4881 	*/
4882 	case XML_SCHEMAS_ANYSIMPLETYPE:
4883 	case XML_SCHEMAS_STRING:
4884         case XML_SCHEMAS_NORMSTRING:
4885         case XML_SCHEMAS_TOKEN:
4886         case XML_SCHEMAS_LANGUAGE:
4887         case XML_SCHEMAS_NMTOKEN:
4888         case XML_SCHEMAS_NAME:
4889         case XML_SCHEMAS_NCNAME:
4890         case XML_SCHEMAS_ID:
4891         case XML_SCHEMAS_IDREF:
4892         case XML_SCHEMAS_ENTITY:
4893         case XML_SCHEMAS_ANYURI:
4894 	{
4895 	    const xmlChar *xv, *yv;
4896 
4897 	    if (x == NULL)
4898 		xv = xvalue;
4899 	    else
4900 		xv = x->value.str;
4901 	    if (y == NULL)
4902 		yv = yvalue;
4903 	    else
4904 		yv = y->value.str;
4905 	    /*
4906 	    * TODO: Compare those against QName.
4907 	    */
4908 	    if (ytype == XML_SCHEMAS_QNAME) {
4909 		TODO
4910 		if (y == NULL)
4911 		    return(-2);
4912 		return (-2);
4913 	    }
4914             if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) ||
4915 		(ytype == XML_SCHEMAS_STRING) ||
4916 		(ytype == XML_SCHEMAS_NORMSTRING) ||
4917                 (ytype == XML_SCHEMAS_TOKEN) ||
4918                 (ytype == XML_SCHEMAS_LANGUAGE) ||
4919                 (ytype == XML_SCHEMAS_NMTOKEN) ||
4920                 (ytype == XML_SCHEMAS_NAME) ||
4921                 (ytype == XML_SCHEMAS_NCNAME) ||
4922                 (ytype == XML_SCHEMAS_ID) ||
4923                 (ytype == XML_SCHEMAS_IDREF) ||
4924                 (ytype == XML_SCHEMAS_ENTITY) ||
4925                 (ytype == XML_SCHEMAS_ANYURI)) {
4926 
4927 		if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) {
4928 
4929 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) {
4930 			/* TODO: What about x < y or x > y. */
4931 			if (xmlStrEqual(xv, yv))
4932 			    return (0);
4933 			else
4934 			    return (2);
4935 		    } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4936 			return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0));
4937 		    else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4938 			return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0));
4939 
4940 		} else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) {
4941 
4942 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
4943 			return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1));
4944 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4945 			return (xmlSchemaCompareReplacedStrings(xv, yv));
4946 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4947 			return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0));
4948 
4949 		} else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
4950 
4951 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
4952 			return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1));
4953 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4954 			return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1));
4955 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4956 			return (xmlSchemaCompareNormStrings(xv, yv));
4957 		} else
4958 		    return (-2);
4959 
4960 	    }
4961             return (-2);
4962 	}
4963         case XML_SCHEMAS_QNAME:
4964 	case XML_SCHEMAS_NOTATION:
4965 	    if ((x == NULL) || (y == NULL))
4966 		return(-2);
4967             if ((ytype == XML_SCHEMAS_QNAME) ||
4968 		(ytype == XML_SCHEMAS_NOTATION)) {
4969 		if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
4970 		    (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
4971 		    return(0);
4972 		return(2);
4973 	    }
4974 	    return (-2);
4975         case XML_SCHEMAS_FLOAT:
4976         case XML_SCHEMAS_DOUBLE:
4977 	    if ((x == NULL) || (y == NULL))
4978 		return(-2);
4979             if ((ytype == XML_SCHEMAS_FLOAT) ||
4980                 (ytype == XML_SCHEMAS_DOUBLE))
4981                 return (xmlSchemaCompareFloats(x, y));
4982             return (-2);
4983         case XML_SCHEMAS_BOOLEAN:
4984 	    if ((x == NULL) || (y == NULL))
4985 		return(-2);
4986             if (ytype == XML_SCHEMAS_BOOLEAN) {
4987 		if (x->value.b == y->value.b)
4988 		    return(0);
4989 		if (x->value.b == 0)
4990 		    return(-1);
4991 		return(1);
4992 	    }
4993 	    return (-2);
4994         case XML_SCHEMAS_HEXBINARY:
4995 	    if ((x == NULL) || (y == NULL))
4996 		return(-2);
4997             if (ytype == XML_SCHEMAS_HEXBINARY) {
4998 	        if (x->value.hex.total == y->value.hex.total) {
4999 		    int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
5000 		    if (ret > 0)
5001 			return(1);
5002 		    else if (ret == 0)
5003 			return(0);
5004 		}
5005 		else if (x->value.hex.total > y->value.hex.total)
5006 		    return(1);
5007 
5008 		return(-1);
5009             }
5010             return (-2);
5011         case XML_SCHEMAS_BASE64BINARY:
5012 	    if ((x == NULL) || (y == NULL))
5013 		return(-2);
5014             if (ytype == XML_SCHEMAS_BASE64BINARY) {
5015                 if (x->value.base64.total == y->value.base64.total) {
5016                     int ret = xmlStrcmp(x->value.base64.str,
5017 		                        y->value.base64.str);
5018                     if (ret > 0)
5019                         return(1);
5020                     else if (ret == 0)
5021                         return(0);
5022 		    else
5023 		        return(-1);
5024                 }
5025                 else if (x->value.base64.total > y->value.base64.total)
5026                     return(1);
5027                 else
5028                     return(-1);
5029             }
5030             return (-2);
5031         case XML_SCHEMAS_IDREFS:
5032         case XML_SCHEMAS_ENTITIES:
5033         case XML_SCHEMAS_NMTOKENS:
5034 	    TODO
5035 	    break;
5036     }
5037     return -2;
5038 }
5039 
5040 /**
5041  * xmlSchemaCompareValues:
5042  * @x:  a first value
5043  * @y:  a second value
5044  *
5045  * Compare 2 values
5046  *
5047  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5048  * case of error
5049  */
5050 int
xmlSchemaCompareValues(xmlSchemaValPtr x,xmlSchemaValPtr y)5051 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
5052     xmlSchemaWhitespaceValueType xws, yws;
5053 
5054     if ((x == NULL) || (y == NULL))
5055         return(-2);
5056     if (x->type == XML_SCHEMAS_STRING)
5057 	xws = XML_SCHEMA_WHITESPACE_PRESERVE;
5058     else if (x->type == XML_SCHEMAS_NORMSTRING)
5059         xws = XML_SCHEMA_WHITESPACE_REPLACE;
5060     else
5061         xws = XML_SCHEMA_WHITESPACE_COLLAPSE;
5062 
5063     if (y->type == XML_SCHEMAS_STRING)
5064 	yws = XML_SCHEMA_WHITESPACE_PRESERVE;
5065     else if (y->type == XML_SCHEMAS_NORMSTRING)
5066         yws = XML_SCHEMA_WHITESPACE_REPLACE;
5067     else
5068         yws = XML_SCHEMA_WHITESPACE_COLLAPSE;
5069 
5070     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
5071 	y, NULL, yws));
5072 }
5073 
5074 /**
5075  * xmlSchemaCompareValuesWhtsp:
5076  * @x:  a first value
5077  * @xws: the whitespace value of x
5078  * @y:  a second value
5079  * @yws: the whitespace value of y
5080  *
5081  * Compare 2 values
5082  *
5083  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5084  * case of error
5085  */
5086 int
xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,xmlSchemaWhitespaceValueType xws,xmlSchemaValPtr y,xmlSchemaWhitespaceValueType yws)5087 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,
5088 			    xmlSchemaWhitespaceValueType xws,
5089 			    xmlSchemaValPtr y,
5090 			    xmlSchemaWhitespaceValueType yws)
5091 {
5092     if ((x == NULL) || (y == NULL))
5093 	return(-2);
5094     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
5095 	y, NULL, yws));
5096 }
5097 
5098 /**
5099  * xmlSchemaCompareValuesWhtspExt:
5100  * @x:  a first value
5101  * @xws: the whitespace value of x
5102  * @y:  a second value
5103  * @yws: the whitespace value of y
5104  *
5105  * Compare 2 values
5106  *
5107  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
5108  * case of error
5109  */
5110 static int
xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,xmlSchemaValPtr x,const xmlChar * xvalue,xmlSchemaWhitespaceValueType xws,xmlSchemaValType ytype,xmlSchemaValPtr y,const xmlChar * yvalue,xmlSchemaWhitespaceValueType yws)5111 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,
5112 			       xmlSchemaValPtr x,
5113 			       const xmlChar *xvalue,
5114 			       xmlSchemaWhitespaceValueType xws,
5115 			       xmlSchemaValType ytype,
5116 			       xmlSchemaValPtr y,
5117 			       const xmlChar *yvalue,
5118 			       xmlSchemaWhitespaceValueType yws)
5119 {
5120     return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y,
5121 	yvalue, yws));
5122 }
5123 
5124 /**
5125  * xmlSchemaNormLen:
5126  * @value:  a string
5127  *
5128  * Computes the UTF8 length of the normalized value of the string
5129  *
5130  * Returns the length or -1 in case of error.
5131  */
5132 static int
xmlSchemaNormLen(const xmlChar * value)5133 xmlSchemaNormLen(const xmlChar *value) {
5134     const xmlChar *utf;
5135     int ret = 0;
5136 
5137     if (value == NULL)
5138 	return(-1);
5139     utf = value;
5140     while (IS_BLANK_CH(*utf)) utf++;
5141     while (*utf != 0) {
5142 	if (utf[0] & 0x80) {
5143 	    if ((utf[1] & 0xc0) != 0x80)
5144 		return(-1);
5145 	    if ((utf[0] & 0xe0) == 0xe0) {
5146 		if ((utf[2] & 0xc0) != 0x80)
5147 		    return(-1);
5148 		if ((utf[0] & 0xf0) == 0xf0) {
5149 		    if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
5150 			return(-1);
5151 		    utf += 4;
5152 		} else {
5153 		    utf += 3;
5154 		}
5155 	    } else {
5156 		utf += 2;
5157 	    }
5158 	} else if (IS_BLANK_CH(*utf)) {
5159 	    while (IS_BLANK_CH(*utf)) utf++;
5160 	    if (*utf == 0)
5161 		break;
5162 	} else {
5163 	    utf++;
5164 	}
5165 	ret++;
5166     }
5167     return(ret);
5168 }
5169 
5170 /**
5171  * xmlSchemaGetFacetValueAsULong:
5172  * @facet: an schemas type facet
5173  *
5174  * Extract the value of a facet
5175  *
5176  * Returns the value as a long
5177  */
5178 unsigned long
xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)5179 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
5180 {
5181     /*
5182     * TODO: Check if this is a decimal.
5183     */
5184     if (facet == NULL || facet->val == NULL)
5185         return 0;
5186     return ((unsigned long) facet->val->value.decimal.lo);
5187 }
5188 
5189 /**
5190  * xmlSchemaValidateListSimpleTypeFacet:
5191  * @facet:  the facet to check
5192  * @value:  the lexical repr of the value to validate
5193  * @actualLen:  the number of list items
5194  * @expectedLen: the resulting expected number of list items
5195  *
5196  * Checks the value of a list simple type against a facet.
5197  *
5198  * Returns 0 if the value is valid, a positive error code
5199  * number otherwise and -1 in case of an internal error.
5200  */
5201 int
xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,const xmlChar * value,unsigned long actualLen,unsigned long * expectedLen)5202 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,
5203 				     const xmlChar *value,
5204 				     unsigned long actualLen,
5205 				     unsigned long *expectedLen)
5206 {
5207     if (facet == NULL)
5208         return(-1);
5209     /*
5210     * TODO: Check if this will work with large numbers.
5211     * (compare value.decimal.mi and value.decimal.hi as well?).
5212     */
5213     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5214 	if (actualLen != facet->val->value.decimal.lo) {
5215 	    if (expectedLen != NULL)
5216 		*expectedLen = facet->val->value.decimal.lo;
5217 	    return (XML_SCHEMAV_CVC_LENGTH_VALID);
5218 	}
5219     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5220 	if (actualLen < facet->val->value.decimal.lo) {
5221 	    if (expectedLen != NULL)
5222 		*expectedLen = facet->val->value.decimal.lo;
5223 	    return (XML_SCHEMAV_CVC_MINLENGTH_VALID);
5224 	}
5225     } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
5226 	if (actualLen > facet->val->value.decimal.lo) {
5227 	    if (expectedLen != NULL)
5228 		*expectedLen = facet->val->value.decimal.lo;
5229 	    return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5230 	}
5231     } else
5232 	/*
5233 	* NOTE: That we can pass NULL as xmlSchemaValPtr to
5234 	* xmlSchemaValidateFacet, since the remaining facet types
5235 	* are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
5236 	*/
5237 	return(xmlSchemaValidateFacet(NULL, facet, value, NULL));
5238     return (0);
5239 }
5240 
5241 /**
5242  * xmlSchemaValidateLengthFacet:
5243  * @type:  the built-in type
5244  * @facet:  the facet to check
5245  * @value:  the lexical repr. of the value to be validated
5246  * @val:  the precomputed value
5247  * @ws: the whitespace type of the value
5248  * @length: the actual length of the value
5249  *
5250  * Checka a value against a "length", "minLength" and "maxLength"
5251  * facet; sets @length to the computed length of @value.
5252  *
5253  * Returns 0 if the value is valid, a positive error code
5254  * otherwise and -1 in case of an internal or API error.
5255  */
5256 static int
xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length,xmlSchemaWhitespaceValueType ws)5257 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
5258 				     xmlSchemaValType valType,
5259 				     const xmlChar *value,
5260 				     xmlSchemaValPtr val,
5261 				     unsigned long *length,
5262 				     xmlSchemaWhitespaceValueType ws)
5263 {
5264     unsigned int len = 0;
5265 
5266     if ((length == NULL) || (facet == NULL))
5267         return (-1);
5268     *length = 0;
5269     if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
5270 	(facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
5271 	(facet->type != XML_SCHEMA_FACET_MINLENGTH))
5272 	return (-1);
5273 
5274     /*
5275     * TODO: length, maxLength and minLength must be of type
5276     * nonNegativeInteger only. Check if decimal is used somehow.
5277     */
5278     if ((facet->val == NULL) ||
5279 	((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5280 	 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5281 	(facet->val->value.decimal.frac != 0)) {
5282 	return(-1);
5283     }
5284     if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5285 	len = val->value.hex.total;
5286     else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5287 	len = val->value.base64.total;
5288     else {
5289 	switch (valType) {
5290 	    case XML_SCHEMAS_STRING:
5291 	    case XML_SCHEMAS_NORMSTRING:
5292 		if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5293 		    /*
5294 		    * This is to ensure API compatibility with the old
5295 		    * xmlSchemaValidateLengthFacet(). Anyway, this was and
5296 		    * is not the correct handling.
5297 		    * TODO: Get rid of this case somehow.
5298 		    */
5299 		    if (valType == XML_SCHEMAS_STRING)
5300 			len = xmlUTF8Strlen(value);
5301 		    else
5302 			len = xmlSchemaNormLen(value);
5303 		} else if (value != NULL) {
5304 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5305 			len = xmlSchemaNormLen(value);
5306 		    else
5307 		    /*
5308 		    * Should be OK for "preserve" as well.
5309 		    */
5310 		    len = xmlUTF8Strlen(value);
5311 		}
5312 		break;
5313 	    case XML_SCHEMAS_IDREF:
5314 	    case XML_SCHEMAS_TOKEN:
5315 	    case XML_SCHEMAS_LANGUAGE:
5316 	    case XML_SCHEMAS_NMTOKEN:
5317 	    case XML_SCHEMAS_NAME:
5318 	    case XML_SCHEMAS_NCNAME:
5319 	    case XML_SCHEMAS_ID:
5320 		/*
5321 		* FIXME: What exactly to do with anyURI?
5322 		*/
5323 	    case XML_SCHEMAS_ANYURI:
5324 		if (value != NULL)
5325 		    len = xmlSchemaNormLen(value);
5326 		break;
5327 	    case XML_SCHEMAS_QNAME:
5328 	    case XML_SCHEMAS_NOTATION:
5329 		/*
5330 		* For QName and NOTATION, those facets are
5331 		* deprecated and should be ignored.
5332 		*/
5333 		return (0);
5334 	    default:
5335 		TODO
5336 	}
5337     }
5338     *length = (unsigned long) len;
5339     /*
5340     * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
5341     */
5342     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5343 	if (len != facet->val->value.decimal.lo)
5344 	    return(XML_SCHEMAV_CVC_LENGTH_VALID);
5345     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5346 	if (len < facet->val->value.decimal.lo)
5347 	    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
5348     } else {
5349 	if (len > facet->val->value.decimal.lo)
5350 	    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5351     }
5352 
5353     return (0);
5354 }
5355 
5356 /**
5357  * xmlSchemaValidateLengthFacet:
5358  * @type:  the built-in type
5359  * @facet:  the facet to check
5360  * @value:  the lexical repr. of the value to be validated
5361  * @val:  the precomputed value
5362  * @length: the actual length of the value
5363  *
5364  * Checka a value against a "length", "minLength" and "maxLength"
5365  * facet; sets @length to the computed length of @value.
5366  *
5367  * Returns 0 if the value is valid, a positive error code
5368  * otherwise and -1 in case of an internal or API error.
5369  */
5370 int
xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,xmlSchemaFacetPtr facet,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length)5371 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,
5372 			     xmlSchemaFacetPtr facet,
5373 			     const xmlChar *value,
5374 			     xmlSchemaValPtr val,
5375 			     unsigned long *length)
5376 {
5377     if (type == NULL)
5378         return(-1);
5379     return (xmlSchemaValidateLengthFacetInternal(facet,
5380 	type->builtInType, value, val, length,
5381 	XML_SCHEMA_WHITESPACE_UNKNOWN));
5382 }
5383 
5384 /**
5385  * xmlSchemaValidateLengthFacetWhtsp:
5386  * @facet:  the facet to check
5387  * @valType:  the built-in type
5388  * @value:  the lexical repr. of the value to be validated
5389  * @val:  the precomputed value
5390  * @ws: the whitespace type of the value
5391  * @length: the actual length of the value
5392  *
5393  * Checka a value against a "length", "minLength" and "maxLength"
5394  * facet; sets @length to the computed length of @value.
5395  *
5396  * Returns 0 if the value is valid, a positive error code
5397  * otherwise and -1 in case of an internal or API error.
5398  */
5399 int
xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length,xmlSchemaWhitespaceValueType ws)5400 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
5401 				  xmlSchemaValType valType,
5402 				  const xmlChar *value,
5403 				  xmlSchemaValPtr val,
5404 				  unsigned long *length,
5405 				  xmlSchemaWhitespaceValueType ws)
5406 {
5407     return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val,
5408 	length, ws));
5409 }
5410 
5411 /**
5412  * xmlSchemaValidateFacetInternal:
5413  * @facet:  the facet to check
5414  * @fws: the whitespace type of the facet's value
5415  * @valType: the built-in type of the value
5416  * @value:  the lexical repr of the value to validate
5417  * @val:  the precomputed value
5418  * @ws: the whitespace type of the value
5419  *
5420  * Check a value against a facet condition
5421  *
5422  * Returns 0 if the element is schemas valid, a positive error code
5423  *     number otherwise and -1 in case of internal or API error.
5424  */
5425 static int
xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,xmlSchemaWhitespaceValueType fws,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws)5426 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
5427 			       xmlSchemaWhitespaceValueType fws,
5428 			       xmlSchemaValType valType,
5429 			       const xmlChar *value,
5430 			       xmlSchemaValPtr val,
5431 			       xmlSchemaWhitespaceValueType ws)
5432 {
5433     int ret;
5434 
5435     if (facet == NULL)
5436 	return(-1);
5437 
5438     switch (facet->type) {
5439 	case XML_SCHEMA_FACET_PATTERN:
5440 	    /*
5441 	    * NOTE that for patterns, the @value needs to be the normalized
5442 	    * value, *not* the lexical initial value or the canonical value.
5443 	    */
5444 	    if (value == NULL)
5445 		return(-1);
5446 	    /*
5447 	    * If string-derived type, regexp must be tested on the value space of
5448 	    * the datatype.
5449 	    * See https://www.w3.org/TR/xmlschema-2/#rf-pattern
5450 	    */
5451 	    if (val &&
5452                 val->value.str &&
5453                 ((val->type >= XML_SCHEMAS_STRING &&
5454                   val->type <= XML_SCHEMAS_NORMSTRING) ||
5455                  (val->type >= XML_SCHEMAS_TOKEN &&
5456                   val->type <= XML_SCHEMAS_ENTITIES &&
5457                   val->type != XML_SCHEMAS_QNAME))) {
5458                 value = val->value.str;
5459             }
5460 	    ret = xmlRegexpExec(facet->regexp, value);
5461 	    if (ret == 1)
5462 		return(0);
5463 	    if (ret == 0)
5464 		return(XML_SCHEMAV_CVC_PATTERN_VALID);
5465 	    return(ret);
5466 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5467 	    ret = xmlSchemaCompareValues(val, facet->val);
5468 	    if (ret == -2)
5469 		return(-1);
5470 	    if (ret == -1)
5471 		return(0);
5472 	    return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID);
5473 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
5474 	    ret = xmlSchemaCompareValues(val, facet->val);
5475 	    if (ret == -2)
5476 		return(-1);
5477 	    if ((ret == -1) || (ret == 0))
5478 		return(0);
5479 	    return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID);
5480 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
5481 	    ret = xmlSchemaCompareValues(val, facet->val);
5482 	    if (ret == -2)
5483 		return(-1);
5484 	    if (ret == 1)
5485 		return(0);
5486 	    return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID);
5487 	case XML_SCHEMA_FACET_MININCLUSIVE:
5488 	    ret = xmlSchemaCompareValues(val, facet->val);
5489 	    if (ret == -2)
5490 		return(-1);
5491 	    if ((ret == 1) || (ret == 0))
5492 		return(0);
5493 	    return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID);
5494 	case XML_SCHEMA_FACET_WHITESPACE:
5495 	    /* TODO whitespaces */
5496 	    /*
5497 	    * NOTE: Whitespace should be handled to normalize
5498 	    * the value to be validated against a the facets;
5499 	    * not to normalize the value in-between.
5500 	    */
5501 	    return(0);
5502 	case  XML_SCHEMA_FACET_ENUMERATION:
5503 	    if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5504 		/*
5505 		* This is to ensure API compatibility with the old
5506 		* xmlSchemaValidateFacet().
5507 		* TODO: Get rid of this case.
5508 		*/
5509 		if ((facet->value != NULL) &&
5510 		    (xmlStrEqual(facet->value, value)))
5511 		    return(0);
5512 	    } else {
5513 		ret = xmlSchemaCompareValuesWhtspExt(facet->val->type,
5514 		    facet->val, facet->value, fws, valType, val,
5515 		    value, ws);
5516 		if (ret == -2)
5517 		    return(-1);
5518 		if (ret == 0)
5519 		    return(0);
5520 	    }
5521 	    return(XML_SCHEMAV_CVC_ENUMERATION_VALID);
5522 	case XML_SCHEMA_FACET_LENGTH:
5523 	    /*
5524 	    * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
5525 	    * then any {value} is facet-valid."
5526 	    */
5527 	    if ((valType == XML_SCHEMAS_QNAME) ||
5528 		(valType == XML_SCHEMAS_NOTATION))
5529 		return (0);
5530             /* Falls through. */
5531 	case XML_SCHEMA_FACET_MAXLENGTH:
5532 	case XML_SCHEMA_FACET_MINLENGTH: {
5533 	    unsigned int len = 0;
5534 
5535 	    if ((valType == XML_SCHEMAS_QNAME) ||
5536 		(valType == XML_SCHEMAS_NOTATION))
5537 		return (0);
5538 	    /*
5539 	    * TODO: length, maxLength and minLength must be of type
5540 	    * nonNegativeInteger only. Check if decimal is used somehow.
5541 	    */
5542 	    if ((facet->val == NULL) ||
5543 		((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5544 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5545 		(facet->val->value.decimal.frac != 0)) {
5546 		return(-1);
5547 	    }
5548 	    if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5549 		len = val->value.hex.total;
5550 	    else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5551 		len = val->value.base64.total;
5552 	    else {
5553 		switch (valType) {
5554 		    case XML_SCHEMAS_STRING:
5555 		    case XML_SCHEMAS_NORMSTRING:
5556 			if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5557 			    /*
5558 			    * This is to ensure API compatibility with the old
5559 			    * xmlSchemaValidateFacet(). Anyway, this was and
5560 			    * is not the correct handling.
5561 			    * TODO: Get rid of this case somehow.
5562 			    */
5563 			    if (valType == XML_SCHEMAS_STRING)
5564 				len = xmlUTF8Strlen(value);
5565 			    else
5566 				len = xmlSchemaNormLen(value);
5567 			} else if (value != NULL) {
5568 			    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5569 				len = xmlSchemaNormLen(value);
5570 			    else
5571 				/*
5572 				* Should be OK for "preserve" as well.
5573 				*/
5574 				len = xmlUTF8Strlen(value);
5575 			}
5576 			break;
5577 		    case XML_SCHEMAS_IDREF:
5578 		    case XML_SCHEMAS_TOKEN:
5579 		    case XML_SCHEMAS_LANGUAGE:
5580 		    case XML_SCHEMAS_NMTOKEN:
5581 		    case XML_SCHEMAS_NAME:
5582 		    case XML_SCHEMAS_NCNAME:
5583 		    case XML_SCHEMAS_ID:
5584 		    case XML_SCHEMAS_ANYURI:
5585 			if (value != NULL)
5586 			    len = xmlSchemaNormLen(value);
5587 			break;
5588 		    default:
5589 		        TODO
5590 		}
5591 	    }
5592 	    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5593 		if (len != facet->val->value.decimal.lo)
5594 		    return(XML_SCHEMAV_CVC_LENGTH_VALID);
5595 	    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5596 		if (len < facet->val->value.decimal.lo)
5597 		    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
5598 	    } else {
5599 		if (len > facet->val->value.decimal.lo)
5600 		    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5601 	    }
5602 	    break;
5603 	}
5604 	case XML_SCHEMA_FACET_TOTALDIGITS:
5605 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
5606 
5607 	    if ((facet->val == NULL) ||
5608 		((facet->val->type != XML_SCHEMAS_PINTEGER) &&
5609 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5610 		(facet->val->value.decimal.frac != 0)) {
5611 		return(-1);
5612 	    }
5613 	    if ((val == NULL) ||
5614 		((val->type != XML_SCHEMAS_DECIMAL) &&
5615 		 (val->type != XML_SCHEMAS_INTEGER) &&
5616 		 (val->type != XML_SCHEMAS_NPINTEGER) &&
5617 		 (val->type != XML_SCHEMAS_NINTEGER) &&
5618 		 (val->type != XML_SCHEMAS_NNINTEGER) &&
5619 		 (val->type != XML_SCHEMAS_PINTEGER) &&
5620 		 (val->type != XML_SCHEMAS_INT) &&
5621 		 (val->type != XML_SCHEMAS_UINT) &&
5622 		 (val->type != XML_SCHEMAS_LONG) &&
5623 		 (val->type != XML_SCHEMAS_ULONG) &&
5624 		 (val->type != XML_SCHEMAS_SHORT) &&
5625 		 (val->type != XML_SCHEMAS_USHORT) &&
5626 		 (val->type != XML_SCHEMAS_BYTE) &&
5627 		 (val->type != XML_SCHEMAS_UBYTE))) {
5628 		return(-1);
5629 	    }
5630 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
5631 	        if (val->value.decimal.total > facet->val->value.decimal.lo)
5632 	            return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID);
5633 
5634 	    } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
5635 	        if (val->value.decimal.frac > facet->val->value.decimal.lo)
5636 		    return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID);
5637 	    }
5638 	    break;
5639 	default:
5640 	    TODO
5641     }
5642     return(0);
5643 
5644 }
5645 
5646 /**
5647  * xmlSchemaValidateFacet:
5648  * @base:  the base type
5649  * @facet:  the facet to check
5650  * @value:  the lexical repr of the value to validate
5651  * @val:  the precomputed value
5652  *
5653  * Check a value against a facet condition
5654  *
5655  * Returns 0 if the element is schemas valid, a positive error code
5656  *     number otherwise and -1 in case of internal or API error.
5657  */
5658 int
xmlSchemaValidateFacet(xmlSchemaTypePtr base,xmlSchemaFacetPtr facet,const xmlChar * value,xmlSchemaValPtr val)5659 xmlSchemaValidateFacet(xmlSchemaTypePtr base,
5660 	               xmlSchemaFacetPtr facet,
5661 	               const xmlChar *value,
5662 		       xmlSchemaValPtr val)
5663 {
5664     /*
5665     * This tries to ensure API compatibility regarding the old
5666     * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
5667     * xmlSchemaValidateFacetWhtsp().
5668     */
5669     if (val != NULL)
5670 	return(xmlSchemaValidateFacetInternal(facet,
5671 	    XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val,
5672 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
5673     else if (base != NULL)
5674 	return(xmlSchemaValidateFacetInternal(facet,
5675 	    XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val,
5676 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
5677     return(-1);
5678 }
5679 
5680 /**
5681  * xmlSchemaValidateFacetWhtsp:
5682  * @facet:  the facet to check
5683  * @fws: the whitespace type of the facet's value
5684  * @valType: the built-in type of the value
5685  * @value:  the lexical (or normalized for pattern) repr of the value to validate
5686  * @val:  the precomputed value
5687  * @ws: the whitespace type of the value
5688  *
5689  * Check a value against a facet condition. This takes value normalization
5690  * according to the specified whitespace types into account.
5691  * Note that @value needs to be the *normalized* value if the facet
5692  * is of type "pattern".
5693  *
5694  * Returns 0 if the element is schemas valid, a positive error code
5695  *     number otherwise and -1 in case of internal or API error.
5696  */
5697 int
xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,xmlSchemaWhitespaceValueType fws,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws)5698 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,
5699 			    xmlSchemaWhitespaceValueType fws,
5700 			    xmlSchemaValType valType,
5701 			    const xmlChar *value,
5702 			    xmlSchemaValPtr val,
5703 			    xmlSchemaWhitespaceValueType ws)
5704 {
5705      return(xmlSchemaValidateFacetInternal(facet, fws, valType,
5706 	 value, val, ws));
5707 }
5708 
5709 #if 0
5710 #ifndef DBL_DIG
5711 #define DBL_DIG 16
5712 #endif
5713 #ifndef DBL_EPSILON
5714 #define DBL_EPSILON 1E-9
5715 #endif
5716 
5717 #define INTEGER_DIGITS DBL_DIG
5718 #define FRACTION_DIGITS (DBL_DIG + 1)
5719 #define EXPONENT_DIGITS (3 + 2)
5720 
5721 /**
5722  * xmlXPathFormatNumber:
5723  * @number:     number to format
5724  * @buffer:     output buffer
5725  * @buffersize: size of output buffer
5726  *
5727  * Convert the number into a string representation.
5728  */
5729 static void
5730 xmlSchemaFormatFloat(double number, char buffer[], int buffersize)
5731 {
5732     switch (xmlXPathIsInf(number)) {
5733     case 1:
5734 	if (buffersize > (int)sizeof("INF"))
5735 	    snprintf(buffer, buffersize, "INF");
5736 	break;
5737     case -1:
5738 	if (buffersize > (int)sizeof("-INF"))
5739 	    snprintf(buffer, buffersize, "-INF");
5740 	break;
5741     default:
5742 	if (xmlXPathIsNaN(number)) {
5743 	    if (buffersize > (int)sizeof("NaN"))
5744 		snprintf(buffer, buffersize, "NaN");
5745 	} else if (number == 0) {
5746 	    snprintf(buffer, buffersize, "0.0E0");
5747 	} else {
5748 	    /* 3 is sign, decimal point, and terminating zero */
5749 	    char work[DBL_DIG + EXPONENT_DIGITS + 3];
5750 	    int integer_place, fraction_place;
5751 	    char *ptr;
5752 	    char *after_fraction;
5753 	    double absolute_value;
5754 	    int size;
5755 
5756 	    absolute_value = fabs(number);
5757 
5758 	    /*
5759 	     * Result is in work, and after_fraction points
5760 	     * just past the fractional part.
5761 	     * Use scientific notation
5762 	    */
5763 	    integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
5764 	    fraction_place = DBL_DIG - 1;
5765 	    snprintf(work, sizeof(work),"%*.*e",
5766 		integer_place, fraction_place, number);
5767 	    after_fraction = strchr(work + DBL_DIG, 'e');
5768 	    /* Remove fractional trailing zeroes */
5769 	    ptr = after_fraction;
5770 	    while (*(--ptr) == '0')
5771 		;
5772 	    if (*ptr != '.')
5773 	        ptr++;
5774 	    while ((*ptr++ = *after_fraction++) != 0);
5775 
5776 	    /* Finally copy result back to caller */
5777 	    size = strlen(work) + 1;
5778 	    if (size > buffersize) {
5779 		work[buffersize - 1] = 0;
5780 		size = buffersize;
5781 	    }
5782 	    memmove(buffer, work, size);
5783 	}
5784 	break;
5785     }
5786 }
5787 #endif
5788 
5789 /**
5790  * xmlSchemaGetCanonValue:
5791  * @val: the precomputed value
5792  * @retValue: the returned value
5793  *
5794  * Get the canonical lexical representation of the value.
5795  * The caller has to FREE the returned retValue.
5796  *
5797  * WARNING: Some value types are not supported yet, resulting
5798  * in a @retValue of "???".
5799  *
5800  * TODO: XML Schema 1.0 does not define canonical representations
5801  * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay,
5802  * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1.
5803  *
5804  *
5805  * Returns 0 if the value could be built, 1 if the value type is
5806  * not supported yet and -1 in case of API errors.
5807  */
5808 int
xmlSchemaGetCanonValue(xmlSchemaValPtr val,const xmlChar ** retValue)5809 xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
5810 {
5811     if ((retValue == NULL) || (val == NULL))
5812 	return (-1);
5813     *retValue = NULL;
5814     switch (val->type) {
5815 	case XML_SCHEMAS_STRING:
5816 	    if (val->value.str == NULL)
5817 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5818 	    else
5819 		*retValue =
5820 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5821 	    break;
5822 	case XML_SCHEMAS_NORMSTRING:
5823 	    if (val->value.str == NULL)
5824 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5825 	    else {
5826 		*retValue = xmlSchemaWhiteSpaceReplace(
5827 		    (const xmlChar *) val->value.str);
5828 		if ((*retValue) == NULL)
5829 		    *retValue = BAD_CAST xmlStrdup(
5830 			(const xmlChar *) val->value.str);
5831 	    }
5832 	    break;
5833 	case XML_SCHEMAS_TOKEN:
5834 	case XML_SCHEMAS_LANGUAGE:
5835 	case XML_SCHEMAS_NMTOKEN:
5836 	case XML_SCHEMAS_NAME:
5837 	case XML_SCHEMAS_NCNAME:
5838 	case XML_SCHEMAS_ID:
5839 	case XML_SCHEMAS_IDREF:
5840 	case XML_SCHEMAS_ENTITY:
5841 	case XML_SCHEMAS_NOTATION: /* Unclear */
5842 	case XML_SCHEMAS_ANYURI:   /* Unclear */
5843 	    if (val->value.str == NULL)
5844 		return (-1);
5845 	    *retValue =
5846 		BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str);
5847 	    if (*retValue == NULL)
5848 		*retValue =
5849 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5850 	    break;
5851 	case XML_SCHEMAS_QNAME:
5852 	    /* TODO: Unclear in XML Schema 1.0. */
5853 	    if (val->value.qname.uri == NULL) {
5854 		*retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name);
5855 		return (0);
5856 	    } else {
5857 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "{");
5858 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5859 		    BAD_CAST val->value.qname.uri);
5860 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5861 		    BAD_CAST "}");
5862 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5863 		    BAD_CAST val->value.qname.uri);
5864 	    }
5865 	    break;
5866 	case XML_SCHEMAS_DECIMAL:
5867 	    /*
5868 	    * TODO: Lookout for a more simple implementation.
5869 	    */
5870 	    if ((val->value.decimal.total == 1) &&
5871 		(val->value.decimal.lo == 0)) {
5872 		*retValue = xmlStrdup(BAD_CAST "0.0");
5873 	    } else {
5874 		xmlSchemaValDecimal dec = val->value.decimal;
5875 		int bufsize;
5876 		char *buf = NULL, *offs;
5877 
5878 		/* Add room for the decimal point as well. */
5879 		bufsize = dec.total + 2;
5880 		if (dec.sign)
5881 		    bufsize++;
5882 		/* Add room for leading/trailing zero. */
5883 		if ((dec.frac == 0) || (dec.frac == dec.total))
5884 		    bufsize++;
5885 		buf = xmlMalloc(bufsize);
5886 		if (buf == NULL)
5887 		    return(-1);
5888 		offs = buf;
5889 		if (dec.sign)
5890 		    *offs++ = '-';
5891 		if (dec.frac == dec.total) {
5892 		    *offs++ = '0';
5893 		    *offs++ = '.';
5894 		}
5895 		if (dec.hi != 0)
5896 		    snprintf(offs, bufsize - (offs - buf),
5897 			"%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5898 		else if (dec.mi != 0)
5899 		    snprintf(offs, bufsize - (offs - buf),
5900 			"%lu%lu", dec.mi, dec.lo);
5901 		else
5902 		    snprintf(offs, bufsize - (offs - buf),
5903 			"%lu", dec.lo);
5904 
5905 		if (dec.frac != 0) {
5906 		    if (dec.frac != dec.total) {
5907 			int diff = dec.total - dec.frac;
5908 			/*
5909 			* Insert the decimal point.
5910 			*/
5911 			memmove(offs + diff + 1, offs + diff, dec.frac +1);
5912 			offs[diff] = '.';
5913 		    } else {
5914 			unsigned int i = 0;
5915 			/*
5916 			* Insert missing zeroes behind the decimal point.
5917 			*/
5918 			while (*(offs + i) != 0)
5919 			    i++;
5920 			if (i < dec.total) {
5921 			    memmove(offs + (dec.total - i), offs, i +1);
5922 			    memset(offs, '0', dec.total - i);
5923 			}
5924 		    }
5925 		} else {
5926 		    /*
5927 		    * Append decimal point and zero.
5928 		    */
5929 		    offs = buf + bufsize - 1;
5930 		    *offs-- = 0;
5931 		    *offs-- = '0';
5932 		    *offs-- = '.';
5933 		}
5934 		*retValue = BAD_CAST buf;
5935 	    }
5936 	    break;
5937 	case XML_SCHEMAS_INTEGER:
5938         case XML_SCHEMAS_PINTEGER:
5939         case XML_SCHEMAS_NPINTEGER:
5940         case XML_SCHEMAS_NINTEGER:
5941         case XML_SCHEMAS_NNINTEGER:
5942 	case XML_SCHEMAS_LONG:
5943         case XML_SCHEMAS_BYTE:
5944         case XML_SCHEMAS_SHORT:
5945         case XML_SCHEMAS_INT:
5946 	case XML_SCHEMAS_UINT:
5947         case XML_SCHEMAS_ULONG:
5948         case XML_SCHEMAS_USHORT:
5949         case XML_SCHEMAS_UBYTE:
5950 	    if ((val->value.decimal.total == 1) &&
5951 		(val->value.decimal.lo == 0))
5952 		*retValue = xmlStrdup(BAD_CAST "0");
5953 	    else {
5954 		xmlSchemaValDecimal dec = val->value.decimal;
5955 		int bufsize = dec.total + 1;
5956 
5957 		/* Add room for the decimal point as well. */
5958 		if (dec.sign)
5959 		    bufsize++;
5960 		*retValue = xmlMalloc(bufsize);
5961 		if (*retValue == NULL)
5962 		    return(-1);
5963 		if (dec.hi != 0) {
5964 		    if (dec.sign)
5965 			snprintf((char *) *retValue, bufsize,
5966 			    "-%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5967 		    else
5968 			snprintf((char *) *retValue, bufsize,
5969 			    "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5970 		} else if (dec.mi != 0) {
5971 		    if (dec.sign)
5972 			snprintf((char *) *retValue, bufsize,
5973 			    "-%lu%lu", dec.mi, dec.lo);
5974 		    else
5975 			snprintf((char *) *retValue, bufsize,
5976 			    "%lu%lu", dec.mi, dec.lo);
5977 		} else {
5978 		    if (dec.sign)
5979 			snprintf((char *) *retValue, bufsize, "-%lu", dec.lo);
5980 		    else
5981 			snprintf((char *) *retValue, bufsize, "%lu", dec.lo);
5982 		}
5983 	    }
5984 	    break;
5985 	case XML_SCHEMAS_BOOLEAN:
5986 	    if (val->value.b)
5987 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "true");
5988 	    else
5989 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "false");
5990 	    break;
5991 	case XML_SCHEMAS_DURATION: {
5992 		char buf[100];
5993 		unsigned long year;
5994 		unsigned long mon, day, hour = 0, min = 0;
5995 		double sec = 0, left;
5996 
5997 		/* TODO: Unclear in XML Schema 1.0 */
5998 		/*
5999 		* TODO: This results in a normalized output of the value
6000 		* - which is NOT conformant to the spec -
6001 		* since the exact values of each property are not
6002 		* recoverable. Think about extending the structure to
6003 		* provide a field for every property.
6004 		*/
6005 		year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12);
6006 		mon = labs(val->value.dur.mon) - 12 * year;
6007 
6008 		day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400);
6009 		left = fabs(val->value.dur.sec) - day * 86400;
6010 		if (left > 0) {
6011 		    hour = (unsigned long) FQUOTIENT(left, 3600);
6012 		    left = left - (hour * 3600);
6013 		    if (left > 0) {
6014 			min = (unsigned long) FQUOTIENT(left, 60);
6015 			sec = left - (min * 60);
6016 		    }
6017 		}
6018 		if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0))
6019 		    snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS",
6020 			year, mon, day, hour, min, sec);
6021 		else
6022 		    snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
6023 			year, mon, day, hour, min, sec);
6024 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6025 	    }
6026 	    break;
6027 	case XML_SCHEMAS_GYEAR: {
6028 		char buf[30];
6029 		/* TODO: Unclear in XML Schema 1.0 */
6030 		/* TODO: What to do with the timezone? */
6031 		snprintf(buf, 30, "%04ld", val->value.date.year);
6032 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6033 	    }
6034 	    break;
6035 	case XML_SCHEMAS_GMONTH: {
6036 		/* TODO: Unclear in XML Schema 1.0 */
6037 		/* TODO: What to do with the timezone? */
6038 		*retValue = xmlMalloc(6);
6039 		if (*retValue == NULL)
6040 		    return(-1);
6041 		snprintf((char *) *retValue, 6, "--%02u",
6042 		    val->value.date.mon);
6043 	    }
6044 	    break;
6045         case XML_SCHEMAS_GDAY: {
6046 		/* TODO: Unclear in XML Schema 1.0 */
6047 		/* TODO: What to do with the timezone? */
6048 		*retValue = xmlMalloc(6);
6049 		if (*retValue == NULL)
6050 		    return(-1);
6051 		snprintf((char *) *retValue, 6, "---%02u",
6052 		    val->value.date.day);
6053 	    }
6054 	    break;
6055         case XML_SCHEMAS_GMONTHDAY: {
6056 		/* TODO: Unclear in XML Schema 1.0 */
6057 		/* TODO: What to do with the timezone? */
6058 		*retValue = xmlMalloc(8);
6059 		if (*retValue == NULL)
6060 		    return(-1);
6061 		snprintf((char *) *retValue, 8, "--%02u-%02u",
6062 		    val->value.date.mon, val->value.date.day);
6063 	    }
6064 	    break;
6065         case XML_SCHEMAS_GYEARMONTH: {
6066 		char buf[35];
6067 		/* TODO: Unclear in XML Schema 1.0 */
6068 		/* TODO: What to do with the timezone? */
6069 		if (val->value.date.year < 0)
6070 		    snprintf(buf, 35, "-%04ld-%02u",
6071 			labs(val->value.date.year),
6072 			val->value.date.mon);
6073 		else
6074 		    snprintf(buf, 35, "%04ld-%02u",
6075 			val->value.date.year, val->value.date.mon);
6076 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6077 	    }
6078 	    break;
6079 	case XML_SCHEMAS_TIME:
6080 	    {
6081 		char buf[30];
6082 
6083 		if (val->value.date.tz_flag) {
6084 		    xmlSchemaValPtr norm;
6085 
6086 		    norm = xmlSchemaDateNormalize(val, 0);
6087 		    if (norm == NULL)
6088 			return (-1);
6089 		    /*
6090 		    * TODO: Check if "%.14g" is portable.
6091 		    */
6092 		    snprintf(buf, 30,
6093 			"%02u:%02u:%02.14gZ",
6094 			norm->value.date.hour,
6095 			norm->value.date.min,
6096 			norm->value.date.sec);
6097 		    xmlSchemaFreeValue(norm);
6098 		} else {
6099 		    snprintf(buf, 30,
6100 			"%02u:%02u:%02.14g",
6101 			val->value.date.hour,
6102 			val->value.date.min,
6103 			val->value.date.sec);
6104 		}
6105 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6106 	    }
6107 	    break;
6108         case XML_SCHEMAS_DATE:
6109 	    {
6110 		char buf[30];
6111 
6112 		if (val->value.date.tz_flag) {
6113 		    xmlSchemaValPtr norm;
6114 
6115 		    norm = xmlSchemaDateNormalize(val, 0);
6116 		    if (norm == NULL)
6117 			return (-1);
6118 		    /*
6119 		    * TODO: Append the canonical value of the
6120 		    * recoverable timezone and not "Z".
6121 		    */
6122 		    snprintf(buf, 30,
6123 			"%04ld-%02u-%02uZ",
6124 			norm->value.date.year, norm->value.date.mon,
6125 			norm->value.date.day);
6126 		    xmlSchemaFreeValue(norm);
6127 		} else {
6128 		    snprintf(buf, 30,
6129 			"%04ld-%02u-%02u",
6130 			val->value.date.year, val->value.date.mon,
6131 			val->value.date.day);
6132 		}
6133 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6134 	    }
6135 	    break;
6136         case XML_SCHEMAS_DATETIME:
6137 	    {
6138 		char buf[50];
6139 
6140 		if (val->value.date.tz_flag) {
6141 		    xmlSchemaValPtr norm;
6142 
6143 		    norm = xmlSchemaDateNormalize(val, 0);
6144 		    if (norm == NULL)
6145 			return (-1);
6146 		    /*
6147 		    * TODO: Check if "%.14g" is portable.
6148 		    */
6149 		    snprintf(buf, 50,
6150 			"%04ld-%02u-%02uT%02u:%02u:%02.14gZ",
6151 			norm->value.date.year, norm->value.date.mon,
6152 			norm->value.date.day, norm->value.date.hour,
6153 			norm->value.date.min, norm->value.date.sec);
6154 		    xmlSchemaFreeValue(norm);
6155 		} else {
6156 		    snprintf(buf, 50,
6157 			"%04ld-%02u-%02uT%02u:%02u:%02.14g",
6158 			val->value.date.year, val->value.date.mon,
6159 			val->value.date.day, val->value.date.hour,
6160 			val->value.date.min, val->value.date.sec);
6161 		}
6162 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6163 	    }
6164 	    break;
6165 	case XML_SCHEMAS_HEXBINARY:
6166 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str);
6167 	    break;
6168 	case XML_SCHEMAS_BASE64BINARY:
6169 	    /*
6170 	    * TODO: Is the following spec piece implemented?:
6171 	    * SPEC: "Note: For some values the canonical form defined
6172 	    * above does not conform to [RFC 2045], which requires breaking
6173 	    * with linefeeds at appropriate intervals."
6174 	    */
6175 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str);
6176 	    break;
6177 	case XML_SCHEMAS_FLOAT: {
6178 		char buf[30];
6179 		/*
6180 		* |m| < 16777216, -149 <= e <= 104.
6181 		* TODO: Handle, NaN, INF, -INF. The format is not
6182 		* yet conformant. The c type float does not cover
6183 		* the whole range.
6184 		*/
6185 		snprintf(buf, 30, "%01.14e", val->value.f);
6186 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6187 	    }
6188 	    break;
6189 	case XML_SCHEMAS_DOUBLE: {
6190 		char buf[40];
6191 		/* |m| < 9007199254740992, -1075 <= e <= 970 */
6192 		/*
6193 		* TODO: Handle, NaN, INF, -INF. The format is not
6194 		* yet conformant. The c type float does not cover
6195 		* the whole range.
6196 		*/
6197 		snprintf(buf, 40, "%01.14e", val->value.d);
6198 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6199 	    }
6200 	    break;
6201 	default:
6202 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST "???");
6203 	    return (1);
6204     }
6205     if (*retValue == NULL)
6206 	return(-1);
6207     return (0);
6208 }
6209 
6210 /**
6211  * xmlSchemaGetCanonValueWhtsp:
6212  * @val: the precomputed value
6213  * @retValue: the returned value
6214  * @ws: the whitespace type of the value
6215  *
6216  * Get the canonical representation of the value.
6217  * The caller has to free the returned @retValue.
6218  *
6219  * Returns 0 if the value could be built, 1 if the value type is
6220  * not supported yet and -1 in case of API errors.
6221  */
6222 int
xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,const xmlChar ** retValue,xmlSchemaWhitespaceValueType ws)6223 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,
6224 			    const xmlChar **retValue,
6225 			    xmlSchemaWhitespaceValueType ws)
6226 {
6227     if ((retValue == NULL) || (val == NULL))
6228 	return (-1);
6229     if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) ||
6230 	(ws > XML_SCHEMA_WHITESPACE_COLLAPSE))
6231 	return (-1);
6232 
6233     *retValue = NULL;
6234     switch (val->type) {
6235 	case XML_SCHEMAS_STRING:
6236 	    if (val->value.str == NULL)
6237 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6238 	    else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6239 		*retValue = xmlSchemaCollapseString(val->value.str);
6240 	    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
6241 		*retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6242 	    if ((*retValue) == NULL)
6243 		*retValue = BAD_CAST xmlStrdup(val->value.str);
6244 	    break;
6245 	case XML_SCHEMAS_NORMSTRING:
6246 	    if (val->value.str == NULL)
6247 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6248 	    else {
6249 		if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6250 		    *retValue = xmlSchemaCollapseString(val->value.str);
6251 		else
6252 		    *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6253 		if ((*retValue) == NULL)
6254 		    *retValue = BAD_CAST xmlStrdup(val->value.str);
6255 	    }
6256 	    break;
6257 	default:
6258 	    return (xmlSchemaGetCanonValue(val, retValue));
6259     }
6260     return (0);
6261 }
6262 
6263 /**
6264  * xmlSchemaGetValType:
6265  * @val: a schemas value
6266  *
6267  * Accessor for the type of a value
6268  *
6269  * Returns the xmlSchemaValType of the value
6270  */
6271 xmlSchemaValType
xmlSchemaGetValType(xmlSchemaValPtr val)6272 xmlSchemaGetValType(xmlSchemaValPtr val)
6273 {
6274     if (val == NULL)
6275         return(XML_SCHEMAS_UNKNOWN);
6276     return (val->type);
6277 }
6278 
6279 #define bottom_xmlschemastypes
6280 #include "elfgcchack.h"
6281 #endif /* LIBXML_SCHEMAS_ENABLED */
6282