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