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