• 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 		    xmlChar *tmpval, *cur;
2903 		    if (normOnTheFly) {
2904 			norm = xmlSchemaCollapseString(value);
2905 			if (norm != NULL)
2906 			    value = norm;
2907 		    }
2908 		    tmpval = xmlStrdup(value);
2909 		    for (cur = tmpval; *cur; ++cur) {
2910 			if (*cur < 32 || *cur >= 127 || *cur == ' ' ||
2911 			    *cur == '<' || *cur == '>' || *cur == '"' ||
2912 			    *cur == '{' || *cur == '}' || *cur == '|' ||
2913 			    *cur == '\\' || *cur == '^' || *cur == '`' ||
2914 			    *cur == '\'')
2915 			    *cur = '_';
2916 		    }
2917                     uri = xmlParseURI((const char *) tmpval);
2918 		    xmlFree(tmpval);
2919                     if (uri == NULL)
2920                         goto return1;
2921                     xmlFreeURI(uri);
2922                 }
2923 
2924                 if (val != NULL) {
2925                     v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI);
2926                     if (v == NULL)
2927                         goto error;
2928                     v->value.str = xmlStrdup(value);
2929                     *val = v;
2930                 }
2931                 goto return0;
2932             }
2933         case XML_SCHEMAS_HEXBINARY:{
2934                 const xmlChar *cur = value, *start;
2935                 xmlChar *base;
2936                 int total, i = 0;
2937 
2938                 if (cur == NULL)
2939                     goto return1;
2940 
2941 		if (normOnTheFly)
2942 		    while IS_WSP_BLANK_CH(*cur) cur++;
2943 
2944 		start = cur;
2945                 while (((*cur >= '0') && (*cur <= '9')) ||
2946                        ((*cur >= 'A') && (*cur <= 'F')) ||
2947                        ((*cur >= 'a') && (*cur <= 'f'))) {
2948                     i++;
2949                     cur++;
2950                 }
2951 		if (normOnTheFly)
2952 		    while IS_WSP_BLANK_CH(*cur) cur++;
2953 
2954                 if (*cur != 0)
2955                     goto return1;
2956                 if ((i % 2) != 0)
2957                     goto return1;
2958 
2959                 if (val != NULL) {
2960 
2961                     v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
2962                     if (v == NULL)
2963                         goto error;
2964 		    /*
2965 		    * Copy only the normalized piece.
2966 		    * CRITICAL TODO: Check this.
2967 		    */
2968                     cur = xmlStrndup(start, i);
2969                     if (cur == NULL) {
2970 		        xmlSchemaTypeErrMemory(node, "allocating hexbin data");
2971                         xmlFree(v);
2972                         goto return1;
2973                     }
2974 
2975                     total = i / 2;      /* number of octets */
2976 
2977                     base = (xmlChar *) cur;
2978                     while (i-- > 0) {
2979                         if (*base >= 'a')
2980                             *base = *base - ('a' - 'A');
2981                         base++;
2982                     }
2983 
2984                     v->value.hex.str = (xmlChar *) cur;
2985                     v->value.hex.total = total;
2986                     *val = v;
2987                 }
2988                 goto return0;
2989             }
2990         case XML_SCHEMAS_BASE64BINARY:{
2991                 /* ISSUE:
2992                  *
2993                  * Ignore all stray characters? (yes, currently)
2994                  * Worry about long lines? (no, currently)
2995                  *
2996                  * rfc2045.txt:
2997                  *
2998                  * "The encoded output stream must be represented in lines of
2999                  * no more than 76 characters each.  All line breaks or other
3000                  * characters not found in Table 1 must be ignored by decoding
3001                  * software.  In base64 data, characters other than those in
3002                  * Table 1, line breaks, and other white space probably
3003                  * indicate a transmission error, about which a warning
3004                  * message or even a message rejection might be appropriate
3005                  * under some circumstances." */
3006                 const xmlChar *cur = value;
3007                 xmlChar *base;
3008                 int total, i = 0, pad = 0;
3009 
3010                 if (cur == NULL)
3011                     goto return1;
3012 
3013                 for (; *cur; ++cur) {
3014                     int decc;
3015 
3016                     decc = _xmlSchemaBase64Decode(*cur);
3017                     if (decc < 0) ;
3018                     else if (decc < 64)
3019                         i++;
3020                     else
3021                         break;
3022                 }
3023                 for (; *cur; ++cur) {
3024                     int decc;
3025 
3026                     decc = _xmlSchemaBase64Decode(*cur);
3027                     if (decc < 0) ;
3028                     else if (decc < 64)
3029                         goto return1;
3030                     if (decc == 64)
3031                         pad++;
3032                 }
3033 
3034                 /* rfc2045.txt: "Special processing is performed if fewer than
3035                  * 24 bits are available at the end of the data being encoded.
3036                  * A full encoding quantum is always completed at the end of a
3037                  * body.  When fewer than 24 input bits are available in an
3038                  * input group, zero bits are added (on the right) to form an
3039                  * integral number of 6-bit groups.  Padding at the end of the
3040                  * data is performed using the "=" character.  Since all
3041                  * base64 input is an integral number of octets, only the
3042                  * following cases can arise: (1) the final quantum of
3043                  * encoding input is an integral multiple of 24 bits; here,
3044                  * the final unit of encoded output will be an integral
3045                  * multiple ofindent: Standard input:701: Warning:old style
3046 		 * assignment ambiguity in "=*".  Assuming "= *" 4 characters
3047 		 * with no "=" padding, (2) the final
3048                  * quantum of encoding input is exactly 8 bits; here, the
3049                  * final unit of encoded output will be two characters
3050                  * followed by two "=" padding characters, or (3) the final
3051                  * quantum of encoding input is exactly 16 bits; here, the
3052                  * final unit of encoded output will be three characters
3053                  * followed by one "=" padding character." */
3054 
3055                 total = 3 * (i / 4);
3056                 if (pad == 0) {
3057                     if (i % 4 != 0)
3058                         goto return1;
3059                 } else if (pad == 1) {
3060                     int decc;
3061 
3062                     if (i % 4 != 3)
3063                         goto return1;
3064                     for (decc = _xmlSchemaBase64Decode(*cur);
3065                          (decc < 0) || (decc > 63);
3066                          decc = _xmlSchemaBase64Decode(*cur))
3067                         --cur;
3068                     /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
3069                     /* 00111100 -> 0x3c */
3070                     if (decc & ~0x3c)
3071                         goto return1;
3072                     total += 2;
3073                 } else if (pad == 2) {
3074                     int decc;
3075 
3076                     if (i % 4 != 2)
3077                         goto return1;
3078                     for (decc = _xmlSchemaBase64Decode(*cur);
3079                          (decc < 0) || (decc > 63);
3080                          decc = _xmlSchemaBase64Decode(*cur))
3081                         --cur;
3082                     /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
3083                     /* 00110000 -> 0x30 */
3084                     if (decc & ~0x30)
3085                         goto return1;
3086                     total += 1;
3087                 } else
3088                     goto return1;
3089 
3090                 if (val != NULL) {
3091                     v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
3092                     if (v == NULL)
3093                         goto error;
3094                     base =
3095                         (xmlChar *) xmlMallocAtomic((i + pad + 1) *
3096                                                     sizeof(xmlChar));
3097                     if (base == NULL) {
3098 		        xmlSchemaTypeErrMemory(node, "allocating base64 data");
3099                         xmlFree(v);
3100                         goto return1;
3101                     }
3102                     v->value.base64.str = base;
3103                     for (cur = value; *cur; ++cur)
3104                         if (_xmlSchemaBase64Decode(*cur) >= 0) {
3105                             *base = *cur;
3106                             ++base;
3107                         }
3108                     *base = 0;
3109                     v->value.base64.total = total;
3110                     *val = v;
3111                 }
3112                 goto return0;
3113             }
3114         case XML_SCHEMAS_INTEGER:
3115         case XML_SCHEMAS_PINTEGER:
3116         case XML_SCHEMAS_NPINTEGER:
3117         case XML_SCHEMAS_NINTEGER:
3118         case XML_SCHEMAS_NNINTEGER:{
3119                 const xmlChar *cur = value;
3120                 unsigned long lo, mi, hi;
3121                 int sign = 0;
3122 
3123                 if (cur == NULL)
3124                     goto return1;
3125 		if (normOnTheFly)
3126 		    while IS_WSP_BLANK_CH(*cur) cur++;
3127                 if (*cur == '-') {
3128                     sign = 1;
3129                     cur++;
3130                 } else if (*cur == '+')
3131                     cur++;
3132                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3133                 if (ret < 0)
3134                     goto return1;
3135 		if (normOnTheFly)
3136 		    while IS_WSP_BLANK_CH(*cur) cur++;
3137                 if (*cur != 0)
3138                     goto return1;
3139                 if (type->builtInType == XML_SCHEMAS_NPINTEGER) {
3140                     if ((sign == 0) &&
3141                         ((hi != 0) || (mi != 0) || (lo != 0)))
3142                         goto return1;
3143                 } else if (type->builtInType == XML_SCHEMAS_PINTEGER) {
3144                     if (sign == 1)
3145                         goto return1;
3146                     if ((hi == 0) && (mi == 0) && (lo == 0))
3147                         goto return1;
3148                 } else if (type->builtInType == XML_SCHEMAS_NINTEGER) {
3149                     if (sign == 0)
3150                         goto return1;
3151                     if ((hi == 0) && (mi == 0) && (lo == 0))
3152                         goto return1;
3153                 } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) {
3154                     if ((sign == 1) &&
3155                         ((hi != 0) || (mi != 0) || (lo != 0)))
3156                         goto return1;
3157                 }
3158                 if (val != NULL) {
3159                     v = xmlSchemaNewValue(type->builtInType);
3160                     if (v != NULL) {
3161 			if (ret == 0)
3162 			    ret++;
3163                         v->value.decimal.lo = lo;
3164                         v->value.decimal.mi = mi;
3165                         v->value.decimal.hi = hi;
3166                         v->value.decimal.sign = sign;
3167                         v->value.decimal.frac = 0;
3168                         v->value.decimal.total = ret;
3169                         *val = v;
3170                     }
3171                 }
3172                 goto return0;
3173             }
3174         case XML_SCHEMAS_LONG:
3175         case XML_SCHEMAS_BYTE:
3176         case XML_SCHEMAS_SHORT:
3177         case XML_SCHEMAS_INT:{
3178                 const xmlChar *cur = value;
3179                 unsigned long lo, mi, hi;
3180                 int sign = 0;
3181 
3182                 if (cur == NULL)
3183                     goto return1;
3184                 if (*cur == '-') {
3185                     sign = 1;
3186                     cur++;
3187                 } else if (*cur == '+')
3188                     cur++;
3189                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3190                 if (ret < 0)
3191                     goto return1;
3192                 if (*cur != 0)
3193                     goto return1;
3194                 if (type->builtInType == XML_SCHEMAS_LONG) {
3195                     if (hi >= 922) {
3196                         if (hi > 922)
3197                             goto return1;
3198                         if (mi >= 33720368) {
3199                             if (mi > 33720368)
3200                                 goto return1;
3201                             if ((sign == 0) && (lo > 54775807))
3202                                 goto return1;
3203                             if ((sign == 1) && (lo > 54775808))
3204                                 goto return1;
3205                         }
3206                     }
3207                 } else if (type->builtInType == XML_SCHEMAS_INT) {
3208                     if (hi != 0)
3209                         goto return1;
3210                     if (mi >= 21) {
3211                         if (mi > 21)
3212                             goto return1;
3213                         if ((sign == 0) && (lo > 47483647))
3214                             goto return1;
3215                         if ((sign == 1) && (lo > 47483648))
3216                             goto return1;
3217                     }
3218                 } else if (type->builtInType == XML_SCHEMAS_SHORT) {
3219                     if ((mi != 0) || (hi != 0))
3220                         goto return1;
3221                     if ((sign == 1) && (lo > 32768))
3222                         goto return1;
3223                     if ((sign == 0) && (lo > 32767))
3224                         goto return1;
3225                 } else if (type->builtInType == XML_SCHEMAS_BYTE) {
3226                     if ((mi != 0) || (hi != 0))
3227                         goto return1;
3228                     if ((sign == 1) && (lo > 128))
3229                         goto return1;
3230                     if ((sign == 0) && (lo > 127))
3231                         goto return1;
3232                 }
3233                 if (val != NULL) {
3234                     v = xmlSchemaNewValue(type->builtInType);
3235                     if (v != NULL) {
3236                         v->value.decimal.lo = lo;
3237                         v->value.decimal.mi = mi;
3238                         v->value.decimal.hi = hi;
3239                         v->value.decimal.sign = sign;
3240                         v->value.decimal.frac = 0;
3241                         v->value.decimal.total = ret;
3242                         *val = v;
3243                     }
3244                 }
3245                 goto return0;
3246             }
3247         case XML_SCHEMAS_UINT:
3248         case XML_SCHEMAS_ULONG:
3249         case XML_SCHEMAS_USHORT:
3250         case XML_SCHEMAS_UBYTE:{
3251                 const xmlChar *cur = value;
3252                 unsigned long lo, mi, hi;
3253 
3254                 if (cur == NULL)
3255                     goto return1;
3256                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
3257                 if (ret < 0)
3258                     goto return1;
3259                 if (*cur != 0)
3260                     goto return1;
3261                 if (type->builtInType == XML_SCHEMAS_ULONG) {
3262                     if (hi >= 1844) {
3263                         if (hi > 1844)
3264                             goto return1;
3265                         if (mi >= 67440737) {
3266                             if (mi > 67440737)
3267                                 goto return1;
3268                             if (lo > 9551615)
3269                                 goto return1;
3270                         }
3271                     }
3272                 } else if (type->builtInType == XML_SCHEMAS_UINT) {
3273                     if (hi != 0)
3274                         goto return1;
3275                     if (mi >= 42) {
3276                         if (mi > 42)
3277                             goto return1;
3278                         if (lo > 94967295)
3279                             goto return1;
3280                     }
3281                 } else if (type->builtInType == XML_SCHEMAS_USHORT) {
3282                     if ((mi != 0) || (hi != 0))
3283                         goto return1;
3284                     if (lo > 65535)
3285                         goto return1;
3286                 } else if (type->builtInType == XML_SCHEMAS_UBYTE) {
3287                     if ((mi != 0) || (hi != 0))
3288                         goto return1;
3289                     if (lo > 255)
3290                         goto return1;
3291                 }
3292                 if (val != NULL) {
3293                     v = xmlSchemaNewValue(type->builtInType);
3294                     if (v != NULL) {
3295                         v->value.decimal.lo = lo;
3296                         v->value.decimal.mi = mi;
3297                         v->value.decimal.hi = hi;
3298                         v->value.decimal.sign = 0;
3299                         v->value.decimal.frac = 0;
3300                         v->value.decimal.total = ret;
3301                         *val = v;
3302                     }
3303                 }
3304                 goto return0;
3305             }
3306     }
3307 
3308   done:
3309     if (norm != NULL)
3310         xmlFree(norm);
3311     return (ret);
3312   return3:
3313     if (norm != NULL)
3314         xmlFree(norm);
3315     return (3);
3316   return1:
3317     if (norm != NULL)
3318         xmlFree(norm);
3319     return (1);
3320   return0:
3321     if (norm != NULL)
3322         xmlFree(norm);
3323     return (0);
3324   error:
3325     if (norm != NULL)
3326         xmlFree(norm);
3327     return (-1);
3328 }
3329 
3330 /**
3331  * xmlSchemaValPredefTypeNode:
3332  * @type: the predefined type
3333  * @value: the value to check
3334  * @val:  the return computed value
3335  * @node:  the node containing the value
3336  *
3337  * Check that a value conforms to the lexical space of the predefined type.
3338  * if true a value is computed and returned in @val.
3339  *
3340  * Returns 0 if this validates, a positive error code number otherwise
3341  *         and -1 in case of internal or API error.
3342  */
3343 int
xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val,xmlNodePtr node)3344 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
3345 	                   xmlSchemaValPtr *val, xmlNodePtr node) {
3346     return(xmlSchemaValAtomicType(type, value, val, node, 0,
3347 	XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 1, 0));
3348 }
3349 
3350 /**
3351  * xmlSchemaValPredefTypeNodeNoNorm:
3352  * @type: the predefined type
3353  * @value: the value to check
3354  * @val:  the return computed value
3355  * @node:  the node containing the value
3356  *
3357  * Check that a value conforms to the lexical space of the predefined type.
3358  * if true a value is computed and returned in @val.
3359  * This one does apply any normalization to the value.
3360  *
3361  * Returns 0 if this validates, a positive error code number otherwise
3362  *         and -1 in case of internal or API error.
3363  */
3364 int
xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val,xmlNodePtr node)3365 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value,
3366 				 xmlSchemaValPtr *val, xmlNodePtr node) {
3367     return(xmlSchemaValAtomicType(type, value, val, node, 1,
3368 	XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 0, 1));
3369 }
3370 
3371 /**
3372  * xmlSchemaValidatePredefinedType:
3373  * @type: the predefined type
3374  * @value: the value to check
3375  * @val:  the return computed value
3376  *
3377  * Check that a value conforms to the lexical space of the predefined type.
3378  * if true a value is computed and returned in @val.
3379  *
3380  * Returns 0 if this validates, a positive error code number otherwise
3381  *         and -1 in case of internal or API error.
3382  */
3383 int
xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type,const xmlChar * value,xmlSchemaValPtr * val)3384 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
3385 	                        xmlSchemaValPtr *val) {
3386     return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
3387 }
3388 
3389 /**
3390  * xmlSchemaCompareDecimals:
3391  * @x:  a first decimal value
3392  * @y:  a second decimal value
3393  *
3394  * Compare 2 decimals
3395  *
3396  * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
3397  */
3398 static int
xmlSchemaCompareDecimals(xmlSchemaValPtr x,xmlSchemaValPtr y)3399 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
3400 {
3401     xmlSchemaValPtr swp;
3402     int order = 1, integx, integy, dlen;
3403     unsigned long hi, mi, lo;
3404 
3405     /*
3406      * First test: If x is -ve and not zero
3407      */
3408     if ((x->value.decimal.sign) &&
3409 	((x->value.decimal.lo != 0) ||
3410 	 (x->value.decimal.mi != 0) ||
3411 	 (x->value.decimal.hi != 0))) {
3412 	/*
3413 	 * Then if y is -ve and not zero reverse the compare
3414 	 */
3415 	if ((y->value.decimal.sign) &&
3416 	    ((y->value.decimal.lo != 0) ||
3417 	     (y->value.decimal.mi != 0) ||
3418 	     (y->value.decimal.hi != 0)))
3419 	    order = -1;
3420 	/*
3421 	 * Otherwise (y >= 0) we have the answer
3422 	 */
3423 	else
3424 	    return (-1);
3425     /*
3426      * If x is not -ve and y is -ve we have the answer
3427      */
3428     } else if ((y->value.decimal.sign) &&
3429 	       ((y->value.decimal.lo != 0) ||
3430 		(y->value.decimal.mi != 0) ||
3431 		(y->value.decimal.hi != 0))) {
3432         return (1);
3433     }
3434     /*
3435      * If it's not simply determined by a difference in sign,
3436      * then we need to compare the actual values of the two nums.
3437      * To do this, we start by looking at the integral parts.
3438      * If the number of integral digits differ, then we have our
3439      * answer.
3440      */
3441     integx = x->value.decimal.total - x->value.decimal.frac;
3442     integy = y->value.decimal.total - y->value.decimal.frac;
3443     /*
3444     * NOTE: We changed the "total" for values like "0.1"
3445     *   (or "-0.1" or ".1") to be 1, which was 2 previously.
3446     *   Therefore the special case, when such values are
3447     *   compared with 0, needs to be handled separately;
3448     *   otherwise a zero would be recognized incorrectly as
3449     *   greater than those values. This has the nice side effect
3450     *   that we gain an overall optimized comparison with zeroes.
3451     * Note that a "0" has a "total" of 1 already.
3452     */
3453     if (integx == 1) {
3454 	if (x->value.decimal.lo == 0) {
3455 	    if (integy != 1)
3456 		return -order;
3457 	    else if (y->value.decimal.lo != 0)
3458 		return -order;
3459 	    else
3460 		return(0);
3461 	}
3462     }
3463     if (integy == 1) {
3464 	if (y->value.decimal.lo == 0) {
3465 	    if (integx != 1)
3466 		return order;
3467 	    else if (x->value.decimal.lo != 0)
3468 		return order;
3469 	    else
3470 		return(0);
3471 	}
3472     }
3473 
3474     if (integx > integy)
3475 	return order;
3476     else if (integy > integx)
3477 	return -order;
3478 
3479     /*
3480      * If the number of integral digits is the same for both numbers,
3481      * then things get a little more complicated.  We need to "normalize"
3482      * the numbers in order to properly compare them.  To do this, we
3483      * look at the total length of each number (length => number of
3484      * significant digits), and divide the "shorter" by 10 (decreasing
3485      * the length) until they are of equal length.
3486      */
3487     dlen = x->value.decimal.total - y->value.decimal.total;
3488     if (dlen < 0) {	/* y has more digits than x */
3489 	swp = x;
3490 	hi = y->value.decimal.hi;
3491 	mi = y->value.decimal.mi;
3492 	lo = y->value.decimal.lo;
3493 	dlen = -dlen;
3494 	order = -order;
3495     } else {		/* x has more digits than y */
3496 	swp = y;
3497 	hi = x->value.decimal.hi;
3498 	mi = x->value.decimal.mi;
3499 	lo = x->value.decimal.lo;
3500     }
3501     while (dlen > 8) {	/* in effect, right shift by 10**8 */
3502 	lo = mi;
3503 	mi = hi;
3504 	hi = 0;
3505 	dlen -= 8;
3506     }
3507     while (dlen > 0) {
3508 	unsigned long rem1, rem2;
3509 	rem1 = (hi % 10) * 100000000L;
3510 	hi = hi / 10;
3511 	rem2 = (mi % 10) * 100000000L;
3512 	mi = (mi + rem1) / 10;
3513 	lo = (lo + rem2) / 10;
3514 	dlen--;
3515     }
3516     if (hi > swp->value.decimal.hi) {
3517 	return order;
3518     } else if (hi == swp->value.decimal.hi) {
3519 	if (mi > swp->value.decimal.mi) {
3520 	    return order;
3521 	} else if (mi == swp->value.decimal.mi) {
3522 	    if (lo > swp->value.decimal.lo) {
3523 		return order;
3524 	    } else if (lo == swp->value.decimal.lo) {
3525 		if (x->value.decimal.total == y->value.decimal.total) {
3526 		    return 0;
3527 		} else {
3528 		    return order;
3529 		}
3530 	    }
3531 	}
3532     }
3533     return -order;
3534 }
3535 
3536 /**
3537  * xmlSchemaCompareDurations:
3538  * @x:  a first duration value
3539  * @y:  a second duration value
3540  *
3541  * Compare 2 durations
3542  *
3543  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3544  * case of error
3545  */
3546 static int
xmlSchemaCompareDurations(xmlSchemaValPtr x,xmlSchemaValPtr y)3547 xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
3548 {
3549     long carry, mon, day;
3550     double sec;
3551     int invert = 1;
3552     long xmon, xday, myear, minday, maxday;
3553     static const long dayRange [2][12] = {
3554         { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
3555         { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
3556 
3557     if ((x == NULL) || (y == NULL))
3558         return -2;
3559 
3560     /* months */
3561     mon = x->value.dur.mon - y->value.dur.mon;
3562 
3563     /* seconds */
3564     sec = x->value.dur.sec - y->value.dur.sec;
3565     carry = (long)sec / SECS_PER_DAY;
3566     sec -= (double)(carry * SECS_PER_DAY);
3567 
3568     /* days */
3569     day = x->value.dur.day - y->value.dur.day + carry;
3570 
3571     /* easy test */
3572     if (mon == 0) {
3573         if (day == 0)
3574             if (sec == 0.0)
3575                 return 0;
3576             else if (sec < 0.0)
3577                 return -1;
3578             else
3579                 return 1;
3580         else if (day < 0)
3581             return -1;
3582         else
3583             return 1;
3584     }
3585 
3586     if (mon > 0) {
3587         if ((day >= 0) && (sec >= 0.0))
3588             return 1;
3589         else {
3590             xmon = mon;
3591             xday = -day;
3592         }
3593     } else if ((day <= 0) && (sec <= 0.0)) {
3594         return -1;
3595     } else {
3596 	invert = -1;
3597         xmon = -mon;
3598         xday = day;
3599     }
3600 
3601     myear = xmon / 12;
3602     if (myear == 0) {
3603 	minday = 0;
3604 	maxday = 0;
3605     } else {
3606 	maxday = 366 * ((myear + 3) / 4) +
3607 	         365 * ((myear - 1) % 4);
3608 	minday = maxday - 1;
3609     }
3610 
3611     xmon = xmon % 12;
3612     minday += dayRange[0][xmon];
3613     maxday += dayRange[1][xmon];
3614 
3615     if ((maxday == minday) && (maxday == xday))
3616 	return(0); /* can this really happen ? */
3617     if (maxday < xday)
3618         return(-invert);
3619     if (minday > xday)
3620         return(invert);
3621 
3622     /* indeterminate */
3623     return 2;
3624 }
3625 
3626 /*
3627  * macros for adding date/times and durations
3628  */
3629 #define FQUOTIENT(a,b)                  (floor(((double)a/(double)b)))
3630 #define MODULO(a,b)                     (a - FQUOTIENT(a,b) * b)
3631 #define FQUOTIENT_RANGE(a,low,high)     (FQUOTIENT((a-low),(high-low)))
3632 #define MODULO_RANGE(a,low,high)        ((MODULO((a-low),(high-low)))+low)
3633 
3634 /**
3635  * xmlSchemaDupVal:
3636  * @v: the #xmlSchemaValPtr value to duplicate
3637  *
3638  * Makes a copy of @v. The calling program is responsible for freeing
3639  * the returned value.
3640  *
3641  * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error.
3642  */
3643 static xmlSchemaValPtr
xmlSchemaDupVal(xmlSchemaValPtr v)3644 xmlSchemaDupVal (xmlSchemaValPtr v)
3645 {
3646     xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
3647     if (ret == NULL)
3648         return NULL;
3649 
3650     memcpy(ret, v, sizeof(xmlSchemaVal));
3651     ret->next = NULL;
3652     return ret;
3653 }
3654 
3655 /**
3656  * xmlSchemaCopyValue:
3657  * @val:  the precomputed value to be copied
3658  *
3659  * Copies the precomputed value. This duplicates any string within.
3660  *
3661  * Returns the copy or NULL if a copy for a data-type is not implemented.
3662  */
3663 xmlSchemaValPtr
xmlSchemaCopyValue(xmlSchemaValPtr val)3664 xmlSchemaCopyValue(xmlSchemaValPtr val)
3665 {
3666     xmlSchemaValPtr ret = NULL, prev = NULL, cur;
3667 
3668     /*
3669     * Copy the string values.
3670     */
3671     while (val != NULL) {
3672 	switch (val->type) {
3673 	    case XML_SCHEMAS_ANYTYPE:
3674 	    case XML_SCHEMAS_IDREFS:
3675 	    case XML_SCHEMAS_ENTITIES:
3676 	    case XML_SCHEMAS_NMTOKENS:
3677 		xmlSchemaFreeValue(ret);
3678 		return (NULL);
3679 	    case XML_SCHEMAS_ANYSIMPLETYPE:
3680 	    case XML_SCHEMAS_STRING:
3681 	    case XML_SCHEMAS_NORMSTRING:
3682 	    case XML_SCHEMAS_TOKEN:
3683 	    case XML_SCHEMAS_LANGUAGE:
3684 	    case XML_SCHEMAS_NAME:
3685 	    case XML_SCHEMAS_NCNAME:
3686 	    case XML_SCHEMAS_ID:
3687 	    case XML_SCHEMAS_IDREF:
3688 	    case XML_SCHEMAS_ENTITY:
3689 	    case XML_SCHEMAS_NMTOKEN:
3690 	    case XML_SCHEMAS_ANYURI:
3691 		cur = xmlSchemaDupVal(val);
3692 		if (val->value.str != NULL)
3693 		    cur->value.str = xmlStrdup(BAD_CAST val->value.str);
3694 		break;
3695 	    case XML_SCHEMAS_QNAME:
3696 	    case XML_SCHEMAS_NOTATION:
3697 		cur = xmlSchemaDupVal(val);
3698 		if (val->value.qname.name != NULL)
3699 		    cur->value.qname.name =
3700                     xmlStrdup(BAD_CAST val->value.qname.name);
3701 		if (val->value.qname.uri != NULL)
3702 		    cur->value.qname.uri =
3703                     xmlStrdup(BAD_CAST val->value.qname.uri);
3704 		break;
3705 	    case XML_SCHEMAS_HEXBINARY:
3706 		cur = xmlSchemaDupVal(val);
3707 		if (val->value.hex.str != NULL)
3708 		    cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str);
3709 		break;
3710 	    case XML_SCHEMAS_BASE64BINARY:
3711 		cur = xmlSchemaDupVal(val);
3712 		if (val->value.base64.str != NULL)
3713 		    cur->value.base64.str =
3714                     xmlStrdup(BAD_CAST val->value.base64.str);
3715 		break;
3716 	    default:
3717 		cur = xmlSchemaDupVal(val);
3718 		break;
3719 	}
3720 	if (ret == NULL)
3721 	    ret = cur;
3722 	else
3723 	    prev->next = cur;
3724 	prev = cur;
3725 	val = val->next;
3726     }
3727     return (ret);
3728 }
3729 
3730 /**
3731  * _xmlSchemaDateAdd:
3732  * @dt: an #xmlSchemaValPtr
3733  * @dur: an #xmlSchemaValPtr of type #XS_DURATION
3734  *
3735  * Compute a new date/time from @dt and @dur. This function assumes @dt
3736  * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
3737  * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as
3738  * @dt. The calling program is responsible for freeing the returned value.
3739  *
3740  * Returns a pointer to a new #xmlSchemaVal or NULL if error.
3741  */
3742 static xmlSchemaValPtr
_xmlSchemaDateAdd(xmlSchemaValPtr dt,xmlSchemaValPtr dur)3743 _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
3744 {
3745     xmlSchemaValPtr ret, tmp;
3746     long carry, tempdays, temp;
3747     xmlSchemaValDatePtr r, d;
3748     xmlSchemaValDurationPtr u;
3749 
3750     if ((dt == NULL) || (dur == NULL))
3751         return NULL;
3752 
3753     ret = xmlSchemaNewValue(dt->type);
3754     if (ret == NULL)
3755         return NULL;
3756 
3757     /* make a copy so we don't alter the original value */
3758     tmp = xmlSchemaDupVal(dt);
3759     if (tmp == NULL) {
3760         xmlSchemaFreeValue(ret);
3761         return NULL;
3762     }
3763 
3764     r = &(ret->value.date);
3765     d = &(tmp->value.date);
3766     u = &(dur->value.dur);
3767 
3768     /* normalization */
3769     if (d->mon == 0)
3770         d->mon = 1;
3771 
3772     /* normalize for time zone offset */
3773     u->sec -= (d->tzo * 60);
3774     d->tzo = 0;
3775 
3776     /* normalization */
3777     if (d->day == 0)
3778         d->day = 1;
3779 
3780     /* month */
3781     carry  = d->mon + u->mon;
3782     r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13);
3783     carry  = (long) FQUOTIENT_RANGE(carry, 1, 13);
3784 
3785     /* year (may be modified later) */
3786     r->year = d->year + carry;
3787     if (r->year == 0) {
3788         if (d->year > 0)
3789             r->year--;
3790         else
3791             r->year++;
3792     }
3793 
3794     /* time zone */
3795     r->tzo     = d->tzo;
3796     r->tz_flag = d->tz_flag;
3797 
3798     /* seconds */
3799     r->sec = d->sec + u->sec;
3800     carry  = (long) FQUOTIENT((long)r->sec, 60);
3801     if (r->sec != 0.0) {
3802         r->sec = MODULO(r->sec, 60.0);
3803     }
3804 
3805     /* minute */
3806     carry += d->min;
3807     r->min = (unsigned int) MODULO(carry, 60);
3808     carry  = (long) FQUOTIENT(carry, 60);
3809 
3810     /* hours */
3811     carry  += d->hour;
3812     r->hour = (unsigned int) MODULO(carry, 24);
3813     carry   = (long)FQUOTIENT(carry, 24);
3814 
3815     /*
3816      * days
3817      * Note we use tempdays because the temporary values may need more
3818      * than 5 bits
3819      */
3820     if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
3821                   (d->day > MAX_DAYINMONTH(r->year, r->mon)))
3822         tempdays = MAX_DAYINMONTH(r->year, r->mon);
3823     else if (d->day < 1)
3824         tempdays = 1;
3825     else
3826         tempdays = d->day;
3827 
3828     tempdays += u->day + carry;
3829 
3830     while (1) {
3831         if (tempdays < 1) {
3832             long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13);
3833             long tyr  = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13);
3834             if (tyr == 0)
3835                 tyr--;
3836 	    /*
3837 	     * Coverity detected an overrun in daysInMonth
3838 	     * of size 12 at position 12 with index variable "((r)->mon - 1)"
3839 	     */
3840 	    if (tmon < 0)
3841 	        tmon = 0;
3842 	    if (tmon > 12)
3843 	        tmon = 12;
3844             tempdays += MAX_DAYINMONTH(tyr, tmon);
3845             carry = -1;
3846         } else if (tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) {
3847             tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
3848             carry = 1;
3849         } else
3850             break;
3851 
3852         temp = r->mon + carry;
3853         r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13);
3854         r->year = r->year + (unsigned int) FQUOTIENT_RANGE(temp, 1, 13);
3855         if (r->year == 0) {
3856             if (temp < 1)
3857                 r->year--;
3858             else
3859                 r->year++;
3860 	}
3861     }
3862 
3863     r->day = tempdays;
3864 
3865     /*
3866      * adjust the date/time type to the date values
3867      */
3868     if (ret->type != XML_SCHEMAS_DATETIME) {
3869         if ((r->hour) || (r->min) || (r->sec))
3870             ret->type = XML_SCHEMAS_DATETIME;
3871         else if (ret->type != XML_SCHEMAS_DATE) {
3872             if ((r->mon != 1) && (r->day != 1))
3873                 ret->type = XML_SCHEMAS_DATE;
3874             else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
3875                 ret->type = XML_SCHEMAS_GYEARMONTH;
3876         }
3877     }
3878 
3879     xmlSchemaFreeValue(tmp);
3880 
3881     return ret;
3882 }
3883 
3884 /**
3885  * xmlSchemaDateNormalize:
3886  * @dt: an #xmlSchemaValPtr of a date/time type value.
3887  * @offset: number of seconds to adjust @dt by.
3888  *
3889  * Normalize @dt to GMT time. The @offset parameter is subtracted from
3890  * the return value is a time-zone offset is present on @dt.
3891  *
3892  * Returns a normalized copy of @dt or NULL if error.
3893  */
3894 static xmlSchemaValPtr
xmlSchemaDateNormalize(xmlSchemaValPtr dt,double offset)3895 xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
3896 {
3897     xmlSchemaValPtr dur, ret;
3898 
3899     if (dt == NULL)
3900         return NULL;
3901 
3902     if (((dt->type != XML_SCHEMAS_TIME) &&
3903          (dt->type != XML_SCHEMAS_DATETIME) &&
3904 	 (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0))
3905         return xmlSchemaDupVal(dt);
3906 
3907     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
3908     if (dur == NULL)
3909         return NULL;
3910 
3911     dur->value.date.sec -= offset;
3912 
3913     ret = _xmlSchemaDateAdd(dt, dur);
3914     if (ret == NULL)
3915         return NULL;
3916 
3917     xmlSchemaFreeValue(dur);
3918 
3919     /* ret->value.date.tzo = 0; */
3920     return ret;
3921 }
3922 
3923 /**
3924  * _xmlSchemaDateCastYMToDays:
3925  * @dt: an #xmlSchemaValPtr
3926  *
3927  * Convert mon and year of @dt to total number of days. Take the
3928  * number of years since (or before) 1 AD and add the number of leap
3929  * years. This is a function  because negative
3930  * years must be handled a little differently and there is no zero year.
3931  *
3932  * Returns number of days.
3933  */
3934 static long
_xmlSchemaDateCastYMToDays(const xmlSchemaValPtr dt)3935 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
3936 {
3937     long ret;
3938     int mon;
3939 
3940     mon = dt->value.date.mon;
3941     if (mon <= 0) mon = 1; /* normalization */
3942 
3943     if (dt->value.date.year <= 0)
3944         ret = (dt->value.date.year * 365) +
3945               (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
3946                ((dt->value.date.year+1)/400)) +
3947               DAY_IN_YEAR(0, mon, dt->value.date.year);
3948     else
3949         ret = ((dt->value.date.year-1) * 365) +
3950               (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
3951                ((dt->value.date.year-1)/400)) +
3952               DAY_IN_YEAR(0, mon, dt->value.date.year);
3953 
3954     return ret;
3955 }
3956 
3957 /**
3958  * TIME_TO_NUMBER:
3959  * @dt:  an #xmlSchemaValPtr
3960  *
3961  * Calculates the number of seconds in the time portion of @dt.
3962  *
3963  * Returns seconds.
3964  */
3965 #define TIME_TO_NUMBER(dt)                              \
3966     ((double)((dt->value.date.hour * SECS_PER_HOUR) +   \
3967               (dt->value.date.min * SECS_PER_MIN) +	\
3968               (dt->value.date.tzo * SECS_PER_MIN)) +	\
3969                dt->value.date.sec)
3970 
3971 /**
3972  * xmlSchemaCompareDates:
3973  * @x:  a first date/time value
3974  * @y:  a second date/time value
3975  *
3976  * Compare 2 date/times
3977  *
3978  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3979  * case of error
3980  */
3981 static int
xmlSchemaCompareDates(xmlSchemaValPtr x,xmlSchemaValPtr y)3982 xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
3983 {
3984     unsigned char xmask, ymask, xor_mask, and_mask;
3985     xmlSchemaValPtr p1, p2, q1, q2;
3986     long p1d, p2d, q1d, q2d;
3987 
3988     if ((x == NULL) || (y == NULL))
3989         return -2;
3990 
3991     if (x->value.date.tz_flag) {
3992 
3993         if (!y->value.date.tz_flag) {
3994             p1 = xmlSchemaDateNormalize(x, 0);
3995             p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
3996             /* normalize y + 14:00 */
3997             q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
3998 
3999             q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4000             if (p1d < q1d) {
4001 		xmlSchemaFreeValue(p1);
4002 		xmlSchemaFreeValue(q1);
4003                 return -1;
4004 	    } else if (p1d == q1d) {
4005                 double sec;
4006 
4007                 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4008                 if (sec < 0.0) {
4009 		    xmlSchemaFreeValue(p1);
4010 		    xmlSchemaFreeValue(q1);
4011                     return -1;
4012 		} else {
4013 		    int ret = 0;
4014                     /* normalize y - 14:00 */
4015                     q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
4016                     q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
4017                     if (p1d > q2d)
4018                         ret = 1;
4019                     else if (p1d == q2d) {
4020                         sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
4021                         if (sec > 0.0)
4022                             ret = 1;
4023                         else
4024                             ret = 2; /* indeterminate */
4025                     }
4026 		    xmlSchemaFreeValue(p1);
4027 		    xmlSchemaFreeValue(q1);
4028 		    xmlSchemaFreeValue(q2);
4029 		    if (ret != 0)
4030 		        return(ret);
4031                 }
4032             } else {
4033 		xmlSchemaFreeValue(p1);
4034 		xmlSchemaFreeValue(q1);
4035 	    }
4036         }
4037     } else if (y->value.date.tz_flag) {
4038         q1 = xmlSchemaDateNormalize(y, 0);
4039         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4040 
4041         /* normalize x - 14:00 */
4042         p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
4043         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4044 
4045         if (p1d < q1d) {
4046 	    xmlSchemaFreeValue(p1);
4047 	    xmlSchemaFreeValue(q1);
4048             return -1;
4049 	} else if (p1d == q1d) {
4050             double sec;
4051 
4052             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4053             if (sec < 0.0) {
4054 		xmlSchemaFreeValue(p1);
4055 		xmlSchemaFreeValue(q1);
4056                 return -1;
4057 	    } else {
4058 	        int ret = 0;
4059                 /* normalize x + 14:00 */
4060                 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
4061                 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
4062 
4063                 if (p2d > q1d) {
4064                     ret = 1;
4065 		} else if (p2d == q1d) {
4066                     sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
4067                     if (sec > 0.0)
4068                         ret = 1;
4069                     else
4070                         ret = 2; /* indeterminate */
4071                 }
4072 		xmlSchemaFreeValue(p1);
4073 		xmlSchemaFreeValue(q1);
4074 		xmlSchemaFreeValue(p2);
4075 		if (ret != 0)
4076 		    return(ret);
4077             }
4078 	} else {
4079 	    xmlSchemaFreeValue(p1);
4080 	    xmlSchemaFreeValue(q1);
4081         }
4082     }
4083 
4084     /*
4085      * if the same type then calculate the difference
4086      */
4087     if (x->type == y->type) {
4088         int ret = 0;
4089         q1 = xmlSchemaDateNormalize(y, 0);
4090         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4091 
4092         p1 = xmlSchemaDateNormalize(x, 0);
4093         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4094 
4095         if (p1d < q1d) {
4096             ret = -1;
4097 	} else if (p1d > q1d) {
4098             ret = 1;
4099 	} else {
4100             double sec;
4101 
4102             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4103             if (sec < 0.0)
4104                 ret = -1;
4105             else if (sec > 0.0)
4106                 ret = 1;
4107 
4108         }
4109 	xmlSchemaFreeValue(p1);
4110 	xmlSchemaFreeValue(q1);
4111         return(ret);
4112     }
4113 
4114     switch (x->type) {
4115         case XML_SCHEMAS_DATETIME:
4116             xmask = 0xf;
4117             break;
4118         case XML_SCHEMAS_DATE:
4119             xmask = 0x7;
4120             break;
4121         case XML_SCHEMAS_GYEAR:
4122             xmask = 0x1;
4123             break;
4124         case XML_SCHEMAS_GMONTH:
4125             xmask = 0x2;
4126             break;
4127         case XML_SCHEMAS_GDAY:
4128             xmask = 0x3;
4129             break;
4130         case XML_SCHEMAS_GYEARMONTH:
4131             xmask = 0x3;
4132             break;
4133         case XML_SCHEMAS_GMONTHDAY:
4134             xmask = 0x6;
4135             break;
4136         case XML_SCHEMAS_TIME:
4137             xmask = 0x8;
4138             break;
4139         default:
4140             xmask = 0;
4141             break;
4142     }
4143 
4144     switch (y->type) {
4145         case XML_SCHEMAS_DATETIME:
4146             ymask = 0xf;
4147             break;
4148         case XML_SCHEMAS_DATE:
4149             ymask = 0x7;
4150             break;
4151         case XML_SCHEMAS_GYEAR:
4152             ymask = 0x1;
4153             break;
4154         case XML_SCHEMAS_GMONTH:
4155             ymask = 0x2;
4156             break;
4157         case XML_SCHEMAS_GDAY:
4158             ymask = 0x3;
4159             break;
4160         case XML_SCHEMAS_GYEARMONTH:
4161             ymask = 0x3;
4162             break;
4163         case XML_SCHEMAS_GMONTHDAY:
4164             ymask = 0x6;
4165             break;
4166         case XML_SCHEMAS_TIME:
4167             ymask = 0x8;
4168             break;
4169         default:
4170             ymask = 0;
4171             break;
4172     }
4173 
4174     xor_mask = xmask ^ ymask;           /* mark type differences */
4175     and_mask = xmask & ymask;           /* mark field specification */
4176 
4177     /* year */
4178     if (xor_mask & 1)
4179         return 2; /* indeterminate */
4180     else if (and_mask & 1) {
4181         if (x->value.date.year < y->value.date.year)
4182             return -1;
4183         else if (x->value.date.year > y->value.date.year)
4184             return 1;
4185     }
4186 
4187     /* month */
4188     if (xor_mask & 2)
4189         return 2; /* indeterminate */
4190     else if (and_mask & 2) {
4191         if (x->value.date.mon < y->value.date.mon)
4192             return -1;
4193         else if (x->value.date.mon > y->value.date.mon)
4194             return 1;
4195     }
4196 
4197     /* day */
4198     if (xor_mask & 4)
4199         return 2; /* indeterminate */
4200     else if (and_mask & 4) {
4201         if (x->value.date.day < y->value.date.day)
4202             return -1;
4203         else if (x->value.date.day > y->value.date.day)
4204             return 1;
4205     }
4206 
4207     /* time */
4208     if (xor_mask & 8)
4209         return 2; /* indeterminate */
4210     else if (and_mask & 8) {
4211         if (x->value.date.hour < y->value.date.hour)
4212             return -1;
4213         else if (x->value.date.hour > y->value.date.hour)
4214             return 1;
4215         else if (x->value.date.min < y->value.date.min)
4216             return -1;
4217         else if (x->value.date.min > y->value.date.min)
4218             return 1;
4219         else if (x->value.date.sec < y->value.date.sec)
4220             return -1;
4221         else if (x->value.date.sec > y->value.date.sec)
4222             return 1;
4223     }
4224 
4225     return 0;
4226 }
4227 
4228 /**
4229  * xmlSchemaComparePreserveReplaceStrings:
4230  * @x:  a first string value
4231  * @y:  a second string value
4232  * @invert: inverts the result if x < y or x > y.
4233  *
4234  * Compare 2 string for their normalized values.
4235  * @x is a string with whitespace of "preserve", @y is
4236  * a string with a whitespace of "replace". I.e. @x could
4237  * be an "xsd:string" and @y an "xsd:normalizedString".
4238  *
4239  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4240  * case of error
4241  */
4242 static int
xmlSchemaComparePreserveReplaceStrings(const xmlChar * x,const xmlChar * y,int invert)4243 xmlSchemaComparePreserveReplaceStrings(const xmlChar *x,
4244 				       const xmlChar *y,
4245 				       int invert)
4246 {
4247     int tmp;
4248 
4249     while ((*x != 0) && (*y != 0)) {
4250 	if (IS_WSP_REPLACE_CH(*y)) {
4251 	    if (! IS_WSP_SPACE_CH(*x)) {
4252 		if ((*x - 0x20) < 0) {
4253 		    if (invert)
4254 			return(1);
4255 		    else
4256 			return(-1);
4257 		} else {
4258 		    if (invert)
4259 			return(-1);
4260 		    else
4261 			return(1);
4262 		}
4263 	    }
4264 	} else {
4265 	    tmp = *x - *y;
4266 	    if (tmp < 0) {
4267 		if (invert)
4268 		    return(1);
4269 		else
4270 		    return(-1);
4271 	    }
4272 	    if (tmp > 0) {
4273 		if (invert)
4274 		    return(-1);
4275 		else
4276 		    return(1);
4277 	    }
4278 	}
4279 	x++;
4280 	y++;
4281     }
4282     if (*x != 0) {
4283 	if (invert)
4284 	    return(-1);
4285 	else
4286 	    return(1);
4287     }
4288     if (*y != 0) {
4289 	if (invert)
4290 	    return(1);
4291 	else
4292 	    return(-1);
4293     }
4294     return(0);
4295 }
4296 
4297 /**
4298  * xmlSchemaComparePreserveCollapseStrings:
4299  * @x:  a first string value
4300  * @y:  a second string value
4301  *
4302  * Compare 2 string for their normalized values.
4303  * @x is a string with whitespace of "preserve", @y is
4304  * a string with a whitespace of "collapse". I.e. @x could
4305  * be an "xsd:string" and @y an "xsd:normalizedString".
4306  *
4307  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4308  * case of error
4309  */
4310 static int
xmlSchemaComparePreserveCollapseStrings(const xmlChar * x,const xmlChar * y,int invert)4311 xmlSchemaComparePreserveCollapseStrings(const xmlChar *x,
4312 				        const xmlChar *y,
4313 					int invert)
4314 {
4315     int tmp;
4316 
4317     /*
4318     * Skip leading blank chars of the collapsed string.
4319     */
4320     while IS_WSP_BLANK_CH(*y)
4321 	y++;
4322 
4323     while ((*x != 0) && (*y != 0)) {
4324 	if IS_WSP_BLANK_CH(*y) {
4325 	    if (! IS_WSP_SPACE_CH(*x)) {
4326 		/*
4327 		* The yv character would have been replaced to 0x20.
4328 		*/
4329 		if ((*x - 0x20) < 0) {
4330 		    if (invert)
4331 			return(1);
4332 		    else
4333 			return(-1);
4334 		} else {
4335 		    if (invert)
4336 			return(-1);
4337 		    else
4338 			return(1);
4339 		}
4340 	    }
4341 	    x++;
4342 	    y++;
4343 	    /*
4344 	    * Skip contiguous blank chars of the collapsed string.
4345 	    */
4346 	    while IS_WSP_BLANK_CH(*y)
4347 		y++;
4348 	} else {
4349 	    tmp = *x++ - *y++;
4350 	    if (tmp < 0) {
4351 		if (invert)
4352 		    return(1);
4353 		else
4354 		    return(-1);
4355 	    }
4356 	    if (tmp > 0) {
4357 		if (invert)
4358 		    return(-1);
4359 		else
4360 		    return(1);
4361 	    }
4362 	}
4363     }
4364     if (*x != 0) {
4365 	 if (invert)
4366 	     return(-1);
4367 	 else
4368 	     return(1);
4369     }
4370     if (*y != 0) {
4371 	/*
4372 	* Skip trailing blank chars of the collapsed string.
4373 	*/
4374 	while IS_WSP_BLANK_CH(*y)
4375 	    y++;
4376 	if (*y != 0) {
4377 	    if (invert)
4378 		return(1);
4379 	    else
4380 		return(-1);
4381 	}
4382     }
4383     return(0);
4384 }
4385 
4386 /**
4387  * xmlSchemaComparePreserveCollapseStrings:
4388  * @x:  a first string value
4389  * @y:  a second string value
4390  *
4391  * Compare 2 string for their normalized values.
4392  * @x is a string with whitespace of "preserve", @y is
4393  * a string with a whitespace of "collapse". I.e. @x could
4394  * be an "xsd:string" and @y an "xsd:normalizedString".
4395  *
4396  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4397  * case of error
4398  */
4399 static int
xmlSchemaCompareReplaceCollapseStrings(const xmlChar * x,const xmlChar * y,int invert)4400 xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x,
4401 				       const xmlChar *y,
4402 				       int invert)
4403 {
4404     int tmp;
4405 
4406     /*
4407     * Skip leading blank chars of the collapsed string.
4408     */
4409     while IS_WSP_BLANK_CH(*y)
4410 	y++;
4411 
4412     while ((*x != 0) && (*y != 0)) {
4413 	if IS_WSP_BLANK_CH(*y) {
4414 	    if (! IS_WSP_BLANK_CH(*x)) {
4415 		/*
4416 		* The yv character would have been replaced to 0x20.
4417 		*/
4418 		if ((*x - 0x20) < 0) {
4419 		    if (invert)
4420 			return(1);
4421 		    else
4422 			return(-1);
4423 		} else {
4424 		    if (invert)
4425 			return(-1);
4426 		    else
4427 			return(1);
4428 		}
4429 	    }
4430 	    x++;
4431 	    y++;
4432 	    /*
4433 	    * Skip contiguous blank chars of the collapsed string.
4434 	    */
4435 	    while IS_WSP_BLANK_CH(*y)
4436 		y++;
4437 	} else {
4438 	    if IS_WSP_BLANK_CH(*x) {
4439 		/*
4440 		* The xv character would have been replaced to 0x20.
4441 		*/
4442 		if ((0x20 - *y) < 0) {
4443 		    if (invert)
4444 			return(1);
4445 		    else
4446 			return(-1);
4447 		} else {
4448 		    if (invert)
4449 			return(-1);
4450 		    else
4451 			return(1);
4452 		}
4453 	    }
4454 	    tmp = *x++ - *y++;
4455 	    if (tmp < 0)
4456 		return(-1);
4457 	    if (tmp > 0)
4458 		return(1);
4459 	}
4460     }
4461     if (*x != 0) {
4462 	 if (invert)
4463 	     return(-1);
4464 	 else
4465 	     return(1);
4466     }
4467     if (*y != 0) {
4468 	/*
4469 	* Skip trailing blank chars of the collapsed string.
4470 	*/
4471 	while IS_WSP_BLANK_CH(*y)
4472 	    y++;
4473 	if (*y != 0) {
4474 	    if (invert)
4475 		return(1);
4476 	    else
4477 		return(-1);
4478 	}
4479     }
4480     return(0);
4481 }
4482 
4483 
4484 /**
4485  * xmlSchemaCompareReplacedStrings:
4486  * @x:  a first string value
4487  * @y:  a second string value
4488  *
4489  * Compare 2 string for their normalized values.
4490  *
4491  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4492  * case of error
4493  */
4494 static int
xmlSchemaCompareReplacedStrings(const xmlChar * x,const xmlChar * y)4495 xmlSchemaCompareReplacedStrings(const xmlChar *x,
4496 				const xmlChar *y)
4497 {
4498     int tmp;
4499 
4500     while ((*x != 0) && (*y != 0)) {
4501 	if IS_WSP_BLANK_CH(*y) {
4502 	    if (! IS_WSP_BLANK_CH(*x)) {
4503 		if ((*x - 0x20) < 0)
4504     		    return(-1);
4505 		else
4506 		    return(1);
4507 	    }
4508 	} else {
4509 	    if IS_WSP_BLANK_CH(*x) {
4510 		if ((0x20 - *y) < 0)
4511     		    return(-1);
4512 		else
4513 		    return(1);
4514 	    }
4515 	    tmp = *x - *y;
4516 	    if (tmp < 0)
4517     		return(-1);
4518 	    if (tmp > 0)
4519     		return(1);
4520 	}
4521 	x++;
4522 	y++;
4523     }
4524     if (*x != 0)
4525         return(1);
4526     if (*y != 0)
4527         return(-1);
4528     return(0);
4529 }
4530 
4531 /**
4532  * xmlSchemaCompareNormStrings:
4533  * @x:  a first string value
4534  * @y:  a second string value
4535  *
4536  * Compare 2 string for their normalized values.
4537  *
4538  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4539  * case of error
4540  */
4541 static int
xmlSchemaCompareNormStrings(const xmlChar * x,const xmlChar * y)4542 xmlSchemaCompareNormStrings(const xmlChar *x,
4543 			    const xmlChar *y) {
4544     int tmp;
4545 
4546     while (IS_BLANK_CH(*x)) x++;
4547     while (IS_BLANK_CH(*y)) y++;
4548     while ((*x != 0) && (*y != 0)) {
4549 	if (IS_BLANK_CH(*x)) {
4550 	    if (!IS_BLANK_CH(*y)) {
4551 		tmp = *x - *y;
4552 		return(tmp);
4553 	    }
4554 	    while (IS_BLANK_CH(*x)) x++;
4555 	    while (IS_BLANK_CH(*y)) y++;
4556 	} else {
4557 	    tmp = *x++ - *y++;
4558 	    if (tmp < 0)
4559 		return(-1);
4560 	    if (tmp > 0)
4561 		return(1);
4562 	}
4563     }
4564     if (*x != 0) {
4565 	while (IS_BLANK_CH(*x)) x++;
4566 	if (*x != 0)
4567 	    return(1);
4568     }
4569     if (*y != 0) {
4570 	while (IS_BLANK_CH(*y)) y++;
4571 	if (*y != 0)
4572 	    return(-1);
4573     }
4574     return(0);
4575 }
4576 
4577 /**
4578  * xmlSchemaCompareFloats:
4579  * @x:  a first float or double value
4580  * @y:  a second float or double value
4581  *
4582  * Compare 2 values
4583  *
4584  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4585  * case of error
4586  */
4587 static int
xmlSchemaCompareFloats(xmlSchemaValPtr x,xmlSchemaValPtr y)4588 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
4589     double d1, d2;
4590 
4591     if ((x == NULL) || (y == NULL))
4592 	return(-2);
4593 
4594     /*
4595      * Cast everything to doubles.
4596      */
4597     if (x->type == XML_SCHEMAS_DOUBLE)
4598 	d1 = x->value.d;
4599     else if (x->type == XML_SCHEMAS_FLOAT)
4600 	d1 = x->value.f;
4601     else
4602 	return(-2);
4603 
4604     if (y->type == XML_SCHEMAS_DOUBLE)
4605 	d2 = y->value.d;
4606     else if (y->type == XML_SCHEMAS_FLOAT)
4607 	d2 = y->value.f;
4608     else
4609 	return(-2);
4610 
4611     /*
4612      * Check for special cases.
4613      */
4614     if (xmlXPathIsNaN(d1)) {
4615 	if (xmlXPathIsNaN(d2))
4616 	    return(0);
4617 	return(1);
4618     }
4619     if (xmlXPathIsNaN(d2))
4620 	return(-1);
4621     if (d1 == xmlXPathPINF) {
4622 	if (d2 == xmlXPathPINF)
4623 	    return(0);
4624         return(1);
4625     }
4626     if (d2 == xmlXPathPINF)
4627         return(-1);
4628     if (d1 == xmlXPathNINF) {
4629 	if (d2 == xmlXPathNINF)
4630 	    return(0);
4631         return(-1);
4632     }
4633     if (d2 == xmlXPathNINF)
4634         return(1);
4635 
4636     /*
4637      * basic tests, the last one we should have equality, but
4638      * portability is more important than speed and handling
4639      * NaN or Inf in a portable way is always a challenge, so ...
4640      */
4641     if (d1 < d2)
4642 	return(-1);
4643     if (d1 > d2)
4644 	return(1);
4645     if (d1 == d2)
4646 	return(0);
4647     return(2);
4648 }
4649 
4650 /**
4651  * xmlSchemaCompareValues:
4652  * @x:  a first value
4653  * @xvalue: the first value as a string (optional)
4654  * @xwtsp: the whitespace type
4655  * @y:  a second value
4656  * @xvalue: the second value as a string (optional)
4657  * @ywtsp: the whitespace type
4658  *
4659  * Compare 2 values
4660  *
4661  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not
4662  * comparable and -2 in case of error
4663  */
4664 static int
xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,xmlSchemaValPtr x,const xmlChar * xvalue,xmlSchemaWhitespaceValueType xws,xmlSchemaValType ytype,xmlSchemaValPtr y,const xmlChar * yvalue,xmlSchemaWhitespaceValueType yws)4665 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
4666 			       xmlSchemaValPtr x,
4667 			       const xmlChar *xvalue,
4668 			       xmlSchemaWhitespaceValueType xws,
4669 			       xmlSchemaValType ytype,
4670 			       xmlSchemaValPtr y,
4671 			       const xmlChar *yvalue,
4672 			       xmlSchemaWhitespaceValueType yws)
4673 {
4674     switch (xtype) {
4675 	case XML_SCHEMAS_UNKNOWN:
4676 	case XML_SCHEMAS_ANYTYPE:
4677 	    return(-2);
4678         case XML_SCHEMAS_INTEGER:
4679         case XML_SCHEMAS_NPINTEGER:
4680         case XML_SCHEMAS_NINTEGER:
4681         case XML_SCHEMAS_NNINTEGER:
4682         case XML_SCHEMAS_PINTEGER:
4683         case XML_SCHEMAS_INT:
4684         case XML_SCHEMAS_UINT:
4685         case XML_SCHEMAS_LONG:
4686         case XML_SCHEMAS_ULONG:
4687         case XML_SCHEMAS_SHORT:
4688         case XML_SCHEMAS_USHORT:
4689         case XML_SCHEMAS_BYTE:
4690         case XML_SCHEMAS_UBYTE:
4691 	case XML_SCHEMAS_DECIMAL:
4692 	    if ((x == NULL) || (y == NULL))
4693 		return(-2);
4694 	    if (ytype == xtype)
4695 		return(xmlSchemaCompareDecimals(x, y));
4696 	    if ((ytype == XML_SCHEMAS_DECIMAL) ||
4697 		(ytype == XML_SCHEMAS_INTEGER) ||
4698 		(ytype == XML_SCHEMAS_NPINTEGER) ||
4699 		(ytype == XML_SCHEMAS_NINTEGER) ||
4700 		(ytype == XML_SCHEMAS_NNINTEGER) ||
4701 		(ytype == XML_SCHEMAS_PINTEGER) ||
4702 		(ytype == XML_SCHEMAS_INT) ||
4703 		(ytype == XML_SCHEMAS_UINT) ||
4704 		(ytype == XML_SCHEMAS_LONG) ||
4705 		(ytype == XML_SCHEMAS_ULONG) ||
4706 		(ytype == XML_SCHEMAS_SHORT) ||
4707 		(ytype == XML_SCHEMAS_USHORT) ||
4708 		(ytype == XML_SCHEMAS_BYTE) ||
4709 		(ytype == XML_SCHEMAS_UBYTE))
4710 		return(xmlSchemaCompareDecimals(x, y));
4711 	    return(-2);
4712         case XML_SCHEMAS_DURATION:
4713 	    if ((x == NULL) || (y == NULL))
4714 		return(-2);
4715 	    if (ytype == XML_SCHEMAS_DURATION)
4716                 return(xmlSchemaCompareDurations(x, y));
4717             return(-2);
4718         case XML_SCHEMAS_TIME:
4719         case XML_SCHEMAS_GDAY:
4720         case XML_SCHEMAS_GMONTH:
4721         case XML_SCHEMAS_GMONTHDAY:
4722         case XML_SCHEMAS_GYEAR:
4723         case XML_SCHEMAS_GYEARMONTH:
4724         case XML_SCHEMAS_DATE:
4725         case XML_SCHEMAS_DATETIME:
4726 	    if ((x == NULL) || (y == NULL))
4727 		return(-2);
4728             if ((ytype == XML_SCHEMAS_DATETIME)  ||
4729                 (ytype == XML_SCHEMAS_TIME)      ||
4730                 (ytype == XML_SCHEMAS_GDAY)      ||
4731                 (ytype == XML_SCHEMAS_GMONTH)    ||
4732                 (ytype == XML_SCHEMAS_GMONTHDAY) ||
4733                 (ytype == XML_SCHEMAS_GYEAR)     ||
4734                 (ytype == XML_SCHEMAS_DATE)      ||
4735                 (ytype == XML_SCHEMAS_GYEARMONTH))
4736                 return (xmlSchemaCompareDates(x, y));
4737             return (-2);
4738 	/*
4739 	* Note that we will support comparison of string types against
4740 	* anySimpleType as well.
4741 	*/
4742 	case XML_SCHEMAS_ANYSIMPLETYPE:
4743 	case XML_SCHEMAS_STRING:
4744         case XML_SCHEMAS_NORMSTRING:
4745         case XML_SCHEMAS_TOKEN:
4746         case XML_SCHEMAS_LANGUAGE:
4747         case XML_SCHEMAS_NMTOKEN:
4748         case XML_SCHEMAS_NAME:
4749         case XML_SCHEMAS_NCNAME:
4750         case XML_SCHEMAS_ID:
4751         case XML_SCHEMAS_IDREF:
4752         case XML_SCHEMAS_ENTITY:
4753         case XML_SCHEMAS_ANYURI:
4754 	{
4755 	    const xmlChar *xv, *yv;
4756 
4757 	    if (x == NULL)
4758 		xv = xvalue;
4759 	    else
4760 		xv = x->value.str;
4761 	    if (y == NULL)
4762 		yv = yvalue;
4763 	    else
4764 		yv = y->value.str;
4765 	    /*
4766 	    * TODO: Compare those against QName.
4767 	    */
4768 	    if (ytype == XML_SCHEMAS_QNAME) {
4769 		TODO
4770 		if (y == NULL)
4771 		    return(-2);
4772 		return (-2);
4773 	    }
4774             if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) ||
4775 		(ytype == XML_SCHEMAS_STRING) ||
4776 		(ytype == XML_SCHEMAS_NORMSTRING) ||
4777                 (ytype == XML_SCHEMAS_TOKEN) ||
4778                 (ytype == XML_SCHEMAS_LANGUAGE) ||
4779                 (ytype == XML_SCHEMAS_NMTOKEN) ||
4780                 (ytype == XML_SCHEMAS_NAME) ||
4781                 (ytype == XML_SCHEMAS_NCNAME) ||
4782                 (ytype == XML_SCHEMAS_ID) ||
4783                 (ytype == XML_SCHEMAS_IDREF) ||
4784                 (ytype == XML_SCHEMAS_ENTITY) ||
4785                 (ytype == XML_SCHEMAS_ANYURI)) {
4786 
4787 		if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) {
4788 
4789 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) {
4790 			/* TODO: What about x < y or x > y. */
4791 			if (xmlStrEqual(xv, yv))
4792 			    return (0);
4793 			else
4794 			    return (2);
4795 		    } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4796 			return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0));
4797 		    else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4798 			return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0));
4799 
4800 		} else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) {
4801 
4802 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
4803 			return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1));
4804 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4805 			return (xmlSchemaCompareReplacedStrings(xv, yv));
4806 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4807 			return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0));
4808 
4809 		} else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
4810 
4811 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
4812 			return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1));
4813 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4814 			return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1));
4815 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4816 			return (xmlSchemaCompareNormStrings(xv, yv));
4817 		} else
4818 		    return (-2);
4819 
4820 	    }
4821             return (-2);
4822 	}
4823         case XML_SCHEMAS_QNAME:
4824 	case XML_SCHEMAS_NOTATION:
4825 	    if ((x == NULL) || (y == NULL))
4826 		return(-2);
4827             if ((ytype == XML_SCHEMAS_QNAME) ||
4828 		(ytype == XML_SCHEMAS_NOTATION)) {
4829 		if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
4830 		    (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
4831 		    return(0);
4832 		return(2);
4833 	    }
4834 	    return (-2);
4835         case XML_SCHEMAS_FLOAT:
4836         case XML_SCHEMAS_DOUBLE:
4837 	    if ((x == NULL) || (y == NULL))
4838 		return(-2);
4839             if ((ytype == XML_SCHEMAS_FLOAT) ||
4840                 (ytype == XML_SCHEMAS_DOUBLE))
4841                 return (xmlSchemaCompareFloats(x, y));
4842             return (-2);
4843         case XML_SCHEMAS_BOOLEAN:
4844 	    if ((x == NULL) || (y == NULL))
4845 		return(-2);
4846             if (ytype == XML_SCHEMAS_BOOLEAN) {
4847 		if (x->value.b == y->value.b)
4848 		    return(0);
4849 		if (x->value.b == 0)
4850 		    return(-1);
4851 		return(1);
4852 	    }
4853 	    return (-2);
4854         case XML_SCHEMAS_HEXBINARY:
4855 	    if ((x == NULL) || (y == NULL))
4856 		return(-2);
4857             if (ytype == XML_SCHEMAS_HEXBINARY) {
4858 	        if (x->value.hex.total == y->value.hex.total) {
4859 		    int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
4860 		    if (ret > 0)
4861 			return(1);
4862 		    else if (ret == 0)
4863 			return(0);
4864 		}
4865 		else if (x->value.hex.total > y->value.hex.total)
4866 		    return(1);
4867 
4868 		return(-1);
4869             }
4870             return (-2);
4871         case XML_SCHEMAS_BASE64BINARY:
4872 	    if ((x == NULL) || (y == NULL))
4873 		return(-2);
4874             if (ytype == XML_SCHEMAS_BASE64BINARY) {
4875                 if (x->value.base64.total == y->value.base64.total) {
4876                     int ret = xmlStrcmp(x->value.base64.str,
4877 		                        y->value.base64.str);
4878                     if (ret > 0)
4879                         return(1);
4880                     else if (ret == 0)
4881                         return(0);
4882 		    else
4883 		        return(-1);
4884                 }
4885                 else if (x->value.base64.total > y->value.base64.total)
4886                     return(1);
4887                 else
4888                     return(-1);
4889             }
4890             return (-2);
4891         case XML_SCHEMAS_IDREFS:
4892         case XML_SCHEMAS_ENTITIES:
4893         case XML_SCHEMAS_NMTOKENS:
4894 	    TODO
4895 	    break;
4896     }
4897     return -2;
4898 }
4899 
4900 /**
4901  * xmlSchemaCompareValues:
4902  * @x:  a first value
4903  * @y:  a second value
4904  *
4905  * Compare 2 values
4906  *
4907  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4908  * case of error
4909  */
4910 int
xmlSchemaCompareValues(xmlSchemaValPtr x,xmlSchemaValPtr y)4911 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
4912     xmlSchemaWhitespaceValueType xws, yws;
4913 
4914     if ((x == NULL) || (y == NULL))
4915         return(-2);
4916     if (x->type == XML_SCHEMAS_STRING)
4917 	xws = XML_SCHEMA_WHITESPACE_PRESERVE;
4918     else if (x->type == XML_SCHEMAS_NORMSTRING)
4919         xws = XML_SCHEMA_WHITESPACE_REPLACE;
4920     else
4921         xws = XML_SCHEMA_WHITESPACE_COLLAPSE;
4922 
4923     if (y->type == XML_SCHEMAS_STRING)
4924 	yws = XML_SCHEMA_WHITESPACE_PRESERVE;
4925     else if (x->type == XML_SCHEMAS_NORMSTRING)
4926         yws = XML_SCHEMA_WHITESPACE_REPLACE;
4927     else
4928         yws = XML_SCHEMA_WHITESPACE_COLLAPSE;
4929 
4930     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
4931 	y, NULL, yws));
4932 }
4933 
4934 /**
4935  * xmlSchemaCompareValuesWhtsp:
4936  * @x:  a first value
4937  * @xws: the whitespace value of x
4938  * @y:  a second value
4939  * @yws: the whitespace value of y
4940  *
4941  * Compare 2 values
4942  *
4943  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4944  * case of error
4945  */
4946 int
xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,xmlSchemaWhitespaceValueType xws,xmlSchemaValPtr y,xmlSchemaWhitespaceValueType yws)4947 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,
4948 			    xmlSchemaWhitespaceValueType xws,
4949 			    xmlSchemaValPtr y,
4950 			    xmlSchemaWhitespaceValueType yws)
4951 {
4952     if ((x == NULL) || (y == NULL))
4953 	return(-2);
4954     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
4955 	y, NULL, yws));
4956 }
4957 
4958 /**
4959  * xmlSchemaCompareValuesWhtspExt:
4960  * @x:  a first value
4961  * @xws: the whitespace value of x
4962  * @y:  a second value
4963  * @yws: the whitespace value of y
4964  *
4965  * Compare 2 values
4966  *
4967  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4968  * case of error
4969  */
4970 static int
xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,xmlSchemaValPtr x,const xmlChar * xvalue,xmlSchemaWhitespaceValueType xws,xmlSchemaValType ytype,xmlSchemaValPtr y,const xmlChar * yvalue,xmlSchemaWhitespaceValueType yws)4971 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,
4972 			       xmlSchemaValPtr x,
4973 			       const xmlChar *xvalue,
4974 			       xmlSchemaWhitespaceValueType xws,
4975 			       xmlSchemaValType ytype,
4976 			       xmlSchemaValPtr y,
4977 			       const xmlChar *yvalue,
4978 			       xmlSchemaWhitespaceValueType yws)
4979 {
4980     return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y,
4981 	yvalue, yws));
4982 }
4983 
4984 /**
4985  * xmlSchemaNormLen:
4986  * @value:  a string
4987  *
4988  * Computes the UTF8 length of the normalized value of the string
4989  *
4990  * Returns the length or -1 in case of error.
4991  */
4992 static int
xmlSchemaNormLen(const xmlChar * value)4993 xmlSchemaNormLen(const xmlChar *value) {
4994     const xmlChar *utf;
4995     int ret = 0;
4996 
4997     if (value == NULL)
4998 	return(-1);
4999     utf = value;
5000     while (IS_BLANK_CH(*utf)) utf++;
5001     while (*utf != 0) {
5002 	if (utf[0] & 0x80) {
5003 	    if ((utf[1] & 0xc0) != 0x80)
5004 		return(-1);
5005 	    if ((utf[0] & 0xe0) == 0xe0) {
5006 		if ((utf[2] & 0xc0) != 0x80)
5007 		    return(-1);
5008 		if ((utf[0] & 0xf0) == 0xf0) {
5009 		    if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
5010 			return(-1);
5011 		    utf += 4;
5012 		} else {
5013 		    utf += 3;
5014 		}
5015 	    } else {
5016 		utf += 2;
5017 	    }
5018 	} else if (IS_BLANK_CH(*utf)) {
5019 	    while (IS_BLANK_CH(*utf)) utf++;
5020 	    if (*utf == 0)
5021 		break;
5022 	} else {
5023 	    utf++;
5024 	}
5025 	ret++;
5026     }
5027     return(ret);
5028 }
5029 
5030 /**
5031  * xmlSchemaGetFacetValueAsULong:
5032  * @facet: an schemas type facet
5033  *
5034  * Extract the value of a facet
5035  *
5036  * Returns the value as a long
5037  */
5038 unsigned long
xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)5039 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
5040 {
5041     /*
5042     * TODO: Check if this is a decimal.
5043     */
5044     if (facet == NULL)
5045         return 0;
5046     return ((unsigned long) facet->val->value.decimal.lo);
5047 }
5048 
5049 /**
5050  * xmlSchemaValidateListSimpleTypeFacet:
5051  * @facet:  the facet to check
5052  * @value:  the lexical repr of the value to validate
5053  * @actualLen:  the number of list items
5054  * @expectedLen: the resulting expected number of list items
5055  *
5056  * Checks the value of a list simple type against a facet.
5057  *
5058  * Returns 0 if the value is valid, a positive error code
5059  * number otherwise and -1 in case of an internal error.
5060  */
5061 int
xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,const xmlChar * value,unsigned long actualLen,unsigned long * expectedLen)5062 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,
5063 				     const xmlChar *value,
5064 				     unsigned long actualLen,
5065 				     unsigned long *expectedLen)
5066 {
5067     if (facet == NULL)
5068         return(-1);
5069     /*
5070     * TODO: Check if this will work with large numbers.
5071     * (compare value.decimal.mi and value.decimal.hi as well?).
5072     */
5073     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5074 	if (actualLen != facet->val->value.decimal.lo) {
5075 	    if (expectedLen != NULL)
5076 		*expectedLen = facet->val->value.decimal.lo;
5077 	    return (XML_SCHEMAV_CVC_LENGTH_VALID);
5078 	}
5079     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5080 	if (actualLen < facet->val->value.decimal.lo) {
5081 	    if (expectedLen != NULL)
5082 		*expectedLen = facet->val->value.decimal.lo;
5083 	    return (XML_SCHEMAV_CVC_MINLENGTH_VALID);
5084 	}
5085     } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
5086 	if (actualLen > facet->val->value.decimal.lo) {
5087 	    if (expectedLen != NULL)
5088 		*expectedLen = facet->val->value.decimal.lo;
5089 	    return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5090 	}
5091     } else
5092 	/*
5093 	* NOTE: That we can pass NULL as xmlSchemaValPtr to
5094 	* xmlSchemaValidateFacet, since the remaining facet types
5095 	* are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
5096 	*/
5097 	return(xmlSchemaValidateFacet(NULL, facet, value, NULL));
5098     return (0);
5099 }
5100 
5101 /**
5102  * xmlSchemaValidateLengthFacet:
5103  * @type:  the built-in type
5104  * @facet:  the facet to check
5105  * @value:  the lexical repr. of the value to be validated
5106  * @val:  the precomputed value
5107  * @ws: the whitespace type of the value
5108  * @length: the actual length of the value
5109  *
5110  * Checka a value against a "length", "minLength" and "maxLength"
5111  * facet; sets @length to the computed length of @value.
5112  *
5113  * Returns 0 if the value is valid, a positive error code
5114  * otherwise and -1 in case of an internal or API error.
5115  */
5116 static int
xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length,xmlSchemaWhitespaceValueType ws)5117 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
5118 				     xmlSchemaValType valType,
5119 				     const xmlChar *value,
5120 				     xmlSchemaValPtr val,
5121 				     unsigned long *length,
5122 				     xmlSchemaWhitespaceValueType ws)
5123 {
5124     unsigned int len = 0;
5125 
5126     if ((length == NULL) || (facet == NULL))
5127         return (-1);
5128     *length = 0;
5129     if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
5130 	(facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
5131 	(facet->type != XML_SCHEMA_FACET_MINLENGTH))
5132 	return (-1);
5133 
5134     /*
5135     * TODO: length, maxLength and minLength must be of type
5136     * nonNegativeInteger only. Check if decimal is used somehow.
5137     */
5138     if ((facet->val == NULL) ||
5139 	((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5140 	 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5141 	(facet->val->value.decimal.frac != 0)) {
5142 	return(-1);
5143     }
5144     if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5145 	len = val->value.hex.total;
5146     else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5147 	len = val->value.base64.total;
5148     else {
5149 	switch (valType) {
5150 	    case XML_SCHEMAS_STRING:
5151 	    case XML_SCHEMAS_NORMSTRING:
5152 		if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5153 		    /*
5154 		    * This is to ensure API compatibility with the old
5155 		    * xmlSchemaValidateLengthFacet(). Anyway, this was and
5156 		    * is not the correct handling.
5157 		    * TODO: Get rid of this case somehow.
5158 		    */
5159 		    if (valType == XML_SCHEMAS_STRING)
5160 			len = xmlUTF8Strlen(value);
5161 		    else
5162 			len = xmlSchemaNormLen(value);
5163 		} else if (value != NULL) {
5164 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5165 			len = xmlSchemaNormLen(value);
5166 		    else
5167 		    /*
5168 		    * Should be OK for "preserve" as well.
5169 		    */
5170 		    len = xmlUTF8Strlen(value);
5171 		}
5172 		break;
5173 	    case XML_SCHEMAS_IDREF:
5174 	    case XML_SCHEMAS_TOKEN:
5175 	    case XML_SCHEMAS_LANGUAGE:
5176 	    case XML_SCHEMAS_NMTOKEN:
5177 	    case XML_SCHEMAS_NAME:
5178 	    case XML_SCHEMAS_NCNAME:
5179 	    case XML_SCHEMAS_ID:
5180 		/*
5181 		* FIXME: What exactly to do with anyURI?
5182 		*/
5183 	    case XML_SCHEMAS_ANYURI:
5184 		if (value != NULL)
5185 		    len = xmlSchemaNormLen(value);
5186 		break;
5187 	    case XML_SCHEMAS_QNAME:
5188  	    case XML_SCHEMAS_NOTATION:
5189  		/*
5190 		* For QName and NOTATION, those facets are
5191 		* deprecated and should be ignored.
5192  		*/
5193 		return (0);
5194 	    default:
5195 		TODO
5196 	}
5197     }
5198     *length = (unsigned long) len;
5199     /*
5200     * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
5201     */
5202     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5203 	if (len != facet->val->value.decimal.lo)
5204 	    return(XML_SCHEMAV_CVC_LENGTH_VALID);
5205     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5206 	if (len < facet->val->value.decimal.lo)
5207 	    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
5208     } else {
5209 	if (len > facet->val->value.decimal.lo)
5210 	    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5211     }
5212 
5213     return (0);
5214 }
5215 
5216 /**
5217  * xmlSchemaValidateLengthFacet:
5218  * @type:  the built-in type
5219  * @facet:  the facet to check
5220  * @value:  the lexical repr. of the value to be validated
5221  * @val:  the precomputed value
5222  * @length: the actual length of the value
5223  *
5224  * Checka a value against a "length", "minLength" and "maxLength"
5225  * facet; sets @length to the computed length of @value.
5226  *
5227  * Returns 0 if the value is valid, a positive error code
5228  * otherwise and -1 in case of an internal or API error.
5229  */
5230 int
xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,xmlSchemaFacetPtr facet,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length)5231 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,
5232 			     xmlSchemaFacetPtr facet,
5233 			     const xmlChar *value,
5234 			     xmlSchemaValPtr val,
5235 			     unsigned long *length)
5236 {
5237     if (type == NULL)
5238         return(-1);
5239     return (xmlSchemaValidateLengthFacetInternal(facet,
5240 	type->builtInType, value, val, length,
5241 	XML_SCHEMA_WHITESPACE_UNKNOWN));
5242 }
5243 
5244 /**
5245  * xmlSchemaValidateLengthFacetWhtsp:
5246  * @facet:  the facet to check
5247  * @valType:  the built-in type
5248  * @value:  the lexical repr. of the value to be validated
5249  * @val:  the precomputed value
5250  * @ws: the whitespace type of the value
5251  * @length: the actual length of the value
5252  *
5253  * Checka a value against a "length", "minLength" and "maxLength"
5254  * facet; sets @length to the computed length of @value.
5255  *
5256  * Returns 0 if the value is valid, a positive error code
5257  * otherwise and -1 in case of an internal or API error.
5258  */
5259 int
xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length,xmlSchemaWhitespaceValueType ws)5260 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
5261 				  xmlSchemaValType valType,
5262 				  const xmlChar *value,
5263 				  xmlSchemaValPtr val,
5264 				  unsigned long *length,
5265 				  xmlSchemaWhitespaceValueType ws)
5266 {
5267     return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val,
5268 	length, ws));
5269 }
5270 
5271 /**
5272  * xmlSchemaValidateFacetInternal:
5273  * @facet:  the facet to check
5274  * @fws: the whitespace type of the facet's value
5275  * @valType: the built-in type of the value
5276  * @value:  the lexical repr of the value to validate
5277  * @val:  the precomputed value
5278  * @ws: the whitespace type of the value
5279  *
5280  * Check a value against a facet condition
5281  *
5282  * Returns 0 if the element is schemas valid, a positive error code
5283  *     number otherwise and -1 in case of internal or API error.
5284  */
5285 static int
xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,xmlSchemaWhitespaceValueType fws,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws)5286 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
5287 			       xmlSchemaWhitespaceValueType fws,
5288 			       xmlSchemaValType valType,
5289 			       const xmlChar *value,
5290 			       xmlSchemaValPtr val,
5291 			       xmlSchemaWhitespaceValueType ws)
5292 {
5293     int ret;
5294 
5295     if (facet == NULL)
5296 	return(-1);
5297 
5298     switch (facet->type) {
5299 	case XML_SCHEMA_FACET_PATTERN:
5300 	    /*
5301 	    * NOTE that for patterns, the @value needs to be the normalized
5302 	    * value, *not* the lexical initial value or the canonical value.
5303 	    */
5304 	    if (value == NULL)
5305 		return(-1);
5306 	    ret = xmlRegexpExec(facet->regexp, value);
5307 	    if (ret == 1)
5308 		return(0);
5309 	    if (ret == 0)
5310 		return(XML_SCHEMAV_CVC_PATTERN_VALID);
5311 	    return(ret);
5312 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5313 	    ret = xmlSchemaCompareValues(val, facet->val);
5314 	    if (ret == -2)
5315 		return(-1);
5316 	    if (ret == -1)
5317 		return(0);
5318 	    return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID);
5319 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
5320 	    ret = xmlSchemaCompareValues(val, facet->val);
5321 	    if (ret == -2)
5322 		return(-1);
5323 	    if ((ret == -1) || (ret == 0))
5324 		return(0);
5325 	    return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID);
5326 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
5327 	    ret = xmlSchemaCompareValues(val, facet->val);
5328 	    if (ret == -2)
5329 		return(-1);
5330 	    if (ret == 1)
5331 		return(0);
5332 	    return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID);
5333 	case XML_SCHEMA_FACET_MININCLUSIVE:
5334 	    ret = xmlSchemaCompareValues(val, facet->val);
5335 	    if (ret == -2)
5336 		return(-1);
5337 	    if ((ret == 1) || (ret == 0))
5338 		return(0);
5339 	    return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID);
5340 	case XML_SCHEMA_FACET_WHITESPACE:
5341 	    /* TODO whitespaces */
5342 	    /*
5343 	    * NOTE: Whitespace should be handled to normalize
5344 	    * the value to be validated against a the facets;
5345 	    * not to normalize the value in-between.
5346 	    */
5347 	    return(0);
5348 	case  XML_SCHEMA_FACET_ENUMERATION:
5349 	    if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5350 		/*
5351 		* This is to ensure API compatibility with the old
5352 		* xmlSchemaValidateFacet().
5353 		* TODO: Get rid of this case.
5354 		*/
5355 		if ((facet->value != NULL) &&
5356 		    (xmlStrEqual(facet->value, value)))
5357 		    return(0);
5358 	    } else {
5359 		ret = xmlSchemaCompareValuesWhtspExt(facet->val->type,
5360 		    facet->val, facet->value, fws, valType, val,
5361 		    value, ws);
5362 		if (ret == -2)
5363 		    return(-1);
5364 		if (ret == 0)
5365 		    return(0);
5366 	    }
5367 	    return(XML_SCHEMAV_CVC_ENUMERATION_VALID);
5368 	case XML_SCHEMA_FACET_LENGTH:
5369 	    /*
5370 	    * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
5371 	    * then any {value} is facet-valid."
5372 	    */
5373 	    if ((valType == XML_SCHEMAS_QNAME) ||
5374 		(valType == XML_SCHEMAS_NOTATION))
5375 		return (0);
5376 	    /* No break on purpose. */
5377 	case XML_SCHEMA_FACET_MAXLENGTH:
5378 	case XML_SCHEMA_FACET_MINLENGTH: {
5379 	    unsigned int len = 0;
5380 
5381 	    if ((valType == XML_SCHEMAS_QNAME) ||
5382 		(valType == XML_SCHEMAS_NOTATION))
5383 		return (0);
5384 	    /*
5385 	    * TODO: length, maxLength and minLength must be of type
5386 	    * nonNegativeInteger only. Check if decimal is used somehow.
5387 	    */
5388 	    if ((facet->val == NULL) ||
5389 		((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5390 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5391 		(facet->val->value.decimal.frac != 0)) {
5392 		return(-1);
5393 	    }
5394 	    if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5395 		len = val->value.hex.total;
5396 	    else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5397 		len = val->value.base64.total;
5398 	    else {
5399 		switch (valType) {
5400 		    case XML_SCHEMAS_STRING:
5401 		    case XML_SCHEMAS_NORMSTRING:
5402 			if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5403 			    /*
5404 			    * This is to ensure API compatibility with the old
5405 			    * xmlSchemaValidateFacet(). Anyway, this was and
5406 			    * is not the correct handling.
5407 			    * TODO: Get rid of this case somehow.
5408 			    */
5409 			    if (valType == XML_SCHEMAS_STRING)
5410 				len = xmlUTF8Strlen(value);
5411 			    else
5412 				len = xmlSchemaNormLen(value);
5413 			} else if (value != NULL) {
5414 			    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5415 				len = xmlSchemaNormLen(value);
5416 			    else
5417 				/*
5418 				* Should be OK for "preserve" as well.
5419 				*/
5420 				len = xmlUTF8Strlen(value);
5421 			}
5422 			break;
5423 	    	    case XML_SCHEMAS_IDREF:
5424 		    case XML_SCHEMAS_TOKEN:
5425 		    case XML_SCHEMAS_LANGUAGE:
5426 		    case XML_SCHEMAS_NMTOKEN:
5427 		    case XML_SCHEMAS_NAME:
5428 		    case XML_SCHEMAS_NCNAME:
5429 		    case XML_SCHEMAS_ID:
5430 		    case XML_SCHEMAS_ANYURI:
5431 			if (value != NULL)
5432 		    	    len = xmlSchemaNormLen(value);
5433 		    	break;
5434 		    default:
5435 		        TODO
5436 	    	}
5437 	    }
5438 	    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5439 		if (len != facet->val->value.decimal.lo)
5440 		    return(XML_SCHEMAV_CVC_LENGTH_VALID);
5441 	    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5442 		if (len < facet->val->value.decimal.lo)
5443 		    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
5444 	    } else {
5445 		if (len > facet->val->value.decimal.lo)
5446 		    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5447 	    }
5448 	    break;
5449 	}
5450 	case XML_SCHEMA_FACET_TOTALDIGITS:
5451 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
5452 
5453 	    if ((facet->val == NULL) ||
5454 		((facet->val->type != XML_SCHEMAS_PINTEGER) &&
5455 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5456 		(facet->val->value.decimal.frac != 0)) {
5457 		return(-1);
5458 	    }
5459 	    if ((val == NULL) ||
5460 		((val->type != XML_SCHEMAS_DECIMAL) &&
5461 		 (val->type != XML_SCHEMAS_INTEGER) &&
5462 		 (val->type != XML_SCHEMAS_NPINTEGER) &&
5463 		 (val->type != XML_SCHEMAS_NINTEGER) &&
5464 		 (val->type != XML_SCHEMAS_NNINTEGER) &&
5465 		 (val->type != XML_SCHEMAS_PINTEGER) &&
5466 		 (val->type != XML_SCHEMAS_INT) &&
5467 		 (val->type != XML_SCHEMAS_UINT) &&
5468 		 (val->type != XML_SCHEMAS_LONG) &&
5469 		 (val->type != XML_SCHEMAS_ULONG) &&
5470 		 (val->type != XML_SCHEMAS_SHORT) &&
5471 		 (val->type != XML_SCHEMAS_USHORT) &&
5472 		 (val->type != XML_SCHEMAS_BYTE) &&
5473 		 (val->type != XML_SCHEMAS_UBYTE))) {
5474 		return(-1);
5475 	    }
5476 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
5477 	        if (val->value.decimal.total > facet->val->value.decimal.lo)
5478 	            return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID);
5479 
5480 	    } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
5481 	        if (val->value.decimal.frac > facet->val->value.decimal.lo)
5482 		    return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID);
5483 	    }
5484 	    break;
5485 	default:
5486 	    TODO
5487     }
5488     return(0);
5489 
5490 }
5491 
5492 /**
5493  * xmlSchemaValidateFacet:
5494  * @base:  the base type
5495  * @facet:  the facet to check
5496  * @value:  the lexical repr of the value to validate
5497  * @val:  the precomputed value
5498  *
5499  * Check a value against a facet condition
5500  *
5501  * Returns 0 if the element is schemas valid, a positive error code
5502  *     number otherwise and -1 in case of internal or API error.
5503  */
5504 int
xmlSchemaValidateFacet(xmlSchemaTypePtr base,xmlSchemaFacetPtr facet,const xmlChar * value,xmlSchemaValPtr val)5505 xmlSchemaValidateFacet(xmlSchemaTypePtr base,
5506 	               xmlSchemaFacetPtr facet,
5507 	               const xmlChar *value,
5508 		       xmlSchemaValPtr val)
5509 {
5510     /*
5511     * This tries to ensure API compatibility regarding the old
5512     * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
5513     * xmlSchemaValidateFacetWhtsp().
5514     */
5515     if (val != NULL)
5516 	return(xmlSchemaValidateFacetInternal(facet,
5517 	    XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val,
5518 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
5519     else if (base != NULL)
5520 	return(xmlSchemaValidateFacetInternal(facet,
5521 	    XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val,
5522 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
5523     return(-1);
5524 }
5525 
5526 /**
5527  * xmlSchemaValidateFacetWhtsp:
5528  * @facet:  the facet to check
5529  * @fws: the whitespace type of the facet's value
5530  * @valType: the built-in type of the value
5531  * @value:  the lexical (or normalized for pattern) repr of the value to validate
5532  * @val:  the precomputed value
5533  * @ws: the whitespace type of the value
5534  *
5535  * Check a value against a facet condition. This takes value normalization
5536  * according to the specified whitespace types into account.
5537  * Note that @value needs to be the *normalized* value if the facet
5538  * is of type "pattern".
5539  *
5540  * Returns 0 if the element is schemas valid, a positive error code
5541  *     number otherwise and -1 in case of internal or API error.
5542  */
5543 int
xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,xmlSchemaWhitespaceValueType fws,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws)5544 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,
5545 			    xmlSchemaWhitespaceValueType fws,
5546 			    xmlSchemaValType valType,
5547 			    const xmlChar *value,
5548 			    xmlSchemaValPtr val,
5549 			    xmlSchemaWhitespaceValueType ws)
5550 {
5551      return(xmlSchemaValidateFacetInternal(facet, fws, valType,
5552 	 value, val, ws));
5553 }
5554 
5555 #if 0
5556 #ifndef DBL_DIG
5557 #define DBL_DIG 16
5558 #endif
5559 #ifndef DBL_EPSILON
5560 #define DBL_EPSILON 1E-9
5561 #endif
5562 
5563 #define INTEGER_DIGITS DBL_DIG
5564 #define FRACTION_DIGITS (DBL_DIG + 1)
5565 #define EXPONENT_DIGITS (3 + 2)
5566 
5567 /**
5568  * xmlXPathFormatNumber:
5569  * @number:     number to format
5570  * @buffer:     output buffer
5571  * @buffersize: size of output buffer
5572  *
5573  * Convert the number into a string representation.
5574  */
5575 static void
5576 xmlSchemaFormatFloat(double number, char buffer[], int buffersize)
5577 {
5578     switch (xmlXPathIsInf(number)) {
5579     case 1:
5580 	if (buffersize > (int)sizeof("INF"))
5581 	    snprintf(buffer, buffersize, "INF");
5582 	break;
5583     case -1:
5584 	if (buffersize > (int)sizeof("-INF"))
5585 	    snprintf(buffer, buffersize, "-INF");
5586 	break;
5587     default:
5588 	if (xmlXPathIsNaN(number)) {
5589 	    if (buffersize > (int)sizeof("NaN"))
5590 		snprintf(buffer, buffersize, "NaN");
5591 	} else if (number == 0) {
5592 	    snprintf(buffer, buffersize, "0.0E0");
5593 	} else {
5594 	    /* 3 is sign, decimal point, and terminating zero */
5595 	    char work[DBL_DIG + EXPONENT_DIGITS + 3];
5596 	    int integer_place, fraction_place;
5597 	    char *ptr;
5598 	    char *after_fraction;
5599 	    double absolute_value;
5600 	    int size;
5601 
5602 	    absolute_value = fabs(number);
5603 
5604 	    /*
5605 	     * Result is in work, and after_fraction points
5606 	     * just past the fractional part.
5607 	     * Use scientific notation
5608 	    */
5609 	    integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
5610 	    fraction_place = DBL_DIG - 1;
5611 	    snprintf(work, sizeof(work),"%*.*e",
5612 		integer_place, fraction_place, number);
5613 	    after_fraction = strchr(work + DBL_DIG, 'e');
5614 	    /* Remove fractional trailing zeroes */
5615 	    ptr = after_fraction;
5616 	    while (*(--ptr) == '0')
5617 		;
5618 	    if (*ptr != '.')
5619 	        ptr++;
5620 	    while ((*ptr++ = *after_fraction++) != 0);
5621 
5622 	    /* Finally copy result back to caller */
5623 	    size = strlen(work) + 1;
5624 	    if (size > buffersize) {
5625 		work[buffersize - 1] = 0;
5626 		size = buffersize;
5627 	    }
5628 	    memmove(buffer, work, size);
5629 	}
5630 	break;
5631     }
5632 }
5633 #endif
5634 
5635 /**
5636  * xmlSchemaGetCanonValue:
5637  * @val: the precomputed value
5638  * @retValue: the returned value
5639  *
5640  * Get a the cononical lexical representation of the value.
5641  * The caller has to FREE the returned retValue.
5642  *
5643  * WARNING: Some value types are not supported yet, resulting
5644  * in a @retValue of "???".
5645  *
5646  * TODO: XML Schema 1.0 does not define canonical representations
5647  * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay,
5648  * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1.
5649  *
5650  *
5651  * Returns 0 if the value could be built, 1 if the value type is
5652  * not supported yet and -1 in case of API errors.
5653  */
5654 int
xmlSchemaGetCanonValue(xmlSchemaValPtr val,const xmlChar ** retValue)5655 xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
5656 {
5657     if ((retValue == NULL) || (val == NULL))
5658 	return (-1);
5659     *retValue = NULL;
5660     switch (val->type) {
5661 	case XML_SCHEMAS_STRING:
5662 	    if (val->value.str == NULL)
5663 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5664 	    else
5665 		*retValue =
5666 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5667 	    break;
5668 	case XML_SCHEMAS_NORMSTRING:
5669 	    if (val->value.str == NULL)
5670 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5671 	    else {
5672 		*retValue = xmlSchemaWhiteSpaceReplace(
5673 		    (const xmlChar *) val->value.str);
5674 		if ((*retValue) == NULL)
5675 		    *retValue = BAD_CAST xmlStrdup(
5676 			(const xmlChar *) val->value.str);
5677 	    }
5678 	    break;
5679 	case XML_SCHEMAS_TOKEN:
5680 	case XML_SCHEMAS_LANGUAGE:
5681 	case XML_SCHEMAS_NMTOKEN:
5682 	case XML_SCHEMAS_NAME:
5683 	case XML_SCHEMAS_NCNAME:
5684 	case XML_SCHEMAS_ID:
5685 	case XML_SCHEMAS_IDREF:
5686 	case XML_SCHEMAS_ENTITY:
5687 	case XML_SCHEMAS_NOTATION: /* Unclear */
5688 	case XML_SCHEMAS_ANYURI:   /* Unclear */
5689 	    if (val->value.str == NULL)
5690 		return (-1);
5691 	    *retValue =
5692 		BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str);
5693 	    if (*retValue == NULL)
5694 		*retValue =
5695 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5696 	    break;
5697 	case XML_SCHEMAS_QNAME:
5698 	    /* TODO: Unclear in XML Schema 1.0. */
5699 	    if (val->value.qname.uri == NULL) {
5700 		*retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name);
5701 		return (0);
5702 	    } else {
5703 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "{");
5704 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5705 		    BAD_CAST val->value.qname.uri);
5706 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5707 		    BAD_CAST "}");
5708 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5709 		    BAD_CAST val->value.qname.uri);
5710 	    }
5711 	    break;
5712 	case XML_SCHEMAS_DECIMAL:
5713 	    /*
5714 	    * TODO: Lookout for a more simple implementation.
5715 	    */
5716 	    if ((val->value.decimal.total == 1) &&
5717 		(val->value.decimal.lo == 0)) {
5718 		*retValue = xmlStrdup(BAD_CAST "0.0");
5719 	    } else {
5720 		xmlSchemaValDecimal dec = val->value.decimal;
5721 		int bufsize;
5722 		char *buf = NULL, *offs;
5723 
5724 		/* Add room for the decimal point as well. */
5725 		bufsize = dec.total + 2;
5726 		if (dec.sign)
5727 		    bufsize++;
5728 		/* Add room for leading/trailing zero. */
5729 		if ((dec.frac == 0) || (dec.frac == dec.total))
5730 		    bufsize++;
5731 		buf = xmlMalloc(bufsize);
5732 		if (buf == NULL)
5733 		    return(-1);
5734 		offs = buf;
5735 		if (dec.sign)
5736 		    *offs++ = '-';
5737 		if (dec.frac == dec.total) {
5738 		    *offs++ = '0';
5739 		    *offs++ = '.';
5740 		}
5741 		if (dec.hi != 0)
5742 		    snprintf(offs, bufsize - (offs - buf),
5743 			"%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5744 		else if (dec.mi != 0)
5745 		    snprintf(offs, bufsize - (offs - buf),
5746 			"%lu%lu", dec.mi, dec.lo);
5747 		else
5748 		    snprintf(offs, bufsize - (offs - buf),
5749 			"%lu", dec.lo);
5750 
5751 		if (dec.frac != 0) {
5752 		    if (dec.frac != dec.total) {
5753 			int diff = dec.total - dec.frac;
5754 			/*
5755 			* Insert the decimal point.
5756 			*/
5757 			memmove(offs + diff + 1, offs + diff, dec.frac +1);
5758 			offs[diff] = '.';
5759 		    } else {
5760 			unsigned int i = 0;
5761 			/*
5762 			* Insert missing zeroes behind the decimal point.
5763 			*/
5764 			while (*(offs + i) != 0)
5765 			    i++;
5766 			if (i < dec.total) {
5767 			    memmove(offs + (dec.total - i), offs, i +1);
5768 			    memset(offs, '0', dec.total - i);
5769 			}
5770 		    }
5771 		} else {
5772 		    /*
5773 		    * Append decimal point and zero.
5774 		    */
5775 		    offs = buf + bufsize - 1;
5776 		    *offs-- = 0;
5777 		    *offs-- = '0';
5778 		    *offs-- = '.';
5779 		}
5780 		*retValue = BAD_CAST buf;
5781 	    }
5782 	    break;
5783 	case XML_SCHEMAS_INTEGER:
5784         case XML_SCHEMAS_PINTEGER:
5785         case XML_SCHEMAS_NPINTEGER:
5786         case XML_SCHEMAS_NINTEGER:
5787         case XML_SCHEMAS_NNINTEGER:
5788 	case XML_SCHEMAS_LONG:
5789         case XML_SCHEMAS_BYTE:
5790         case XML_SCHEMAS_SHORT:
5791         case XML_SCHEMAS_INT:
5792 	case XML_SCHEMAS_UINT:
5793         case XML_SCHEMAS_ULONG:
5794         case XML_SCHEMAS_USHORT:
5795         case XML_SCHEMAS_UBYTE:
5796 	    if ((val->value.decimal.total == 1) &&
5797 		(val->value.decimal.lo == 0))
5798 		*retValue = xmlStrdup(BAD_CAST "0");
5799 	    else {
5800 		xmlSchemaValDecimal dec = val->value.decimal;
5801 		int bufsize = dec.total + 1;
5802 
5803 		/* Add room for the decimal point as well. */
5804 		if (dec.sign)
5805 		    bufsize++;
5806 		*retValue = xmlMalloc(bufsize);
5807 		if (*retValue == NULL)
5808 		    return(-1);
5809 		if (dec.hi != 0) {
5810 		    if (dec.sign)
5811 			snprintf((char *) *retValue, bufsize,
5812 			    "-%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5813 		    else
5814 			snprintf((char *) *retValue, bufsize,
5815 			    "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5816 		} else if (dec.mi != 0) {
5817 		    if (dec.sign)
5818 			snprintf((char *) *retValue, bufsize,
5819 			    "-%lu%lu", dec.mi, dec.lo);
5820 		    else
5821 			snprintf((char *) *retValue, bufsize,
5822 			    "%lu%lu", dec.mi, dec.lo);
5823 		} else {
5824 		    if (dec.sign)
5825 			snprintf((char *) *retValue, bufsize, "-%lu", dec.lo);
5826 		    else
5827 			snprintf((char *) *retValue, bufsize, "%lu", dec.lo);
5828 		}
5829 	    }
5830 	    break;
5831 	case XML_SCHEMAS_BOOLEAN:
5832 	    if (val->value.b)
5833 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "true");
5834 	    else
5835 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "false");
5836 	    break;
5837 	case XML_SCHEMAS_DURATION: {
5838 		char buf[100];
5839 		unsigned long year;
5840 		unsigned long mon, day, hour = 0, min = 0;
5841 		double sec = 0, left;
5842 
5843 		/* TODO: Unclear in XML Schema 1.0 */
5844 		/*
5845 		* TODO: This results in a normalized output of the value
5846 		* - which is NOT conformant to the spec -
5847 		* since the exact values of each property are not
5848 		* recoverable. Think about extending the structure to
5849 		* provide a field for every property.
5850 		*/
5851 		year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12);
5852 		mon = labs(val->value.dur.mon) - 12 * year;
5853 
5854 		day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400);
5855 		left = fabs(val->value.dur.sec) - day * 86400;
5856 		if (left > 0) {
5857 		    hour = (unsigned long) FQUOTIENT(left, 3600);
5858 		    left = left - (hour * 3600);
5859 		    if (left > 0) {
5860 			min = (unsigned long) FQUOTIENT(left, 60);
5861 			sec = left - (min * 60);
5862 		    }
5863 		}
5864 		if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0))
5865 		    snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS",
5866 			year, mon, day, hour, min, sec);
5867 		else
5868 		    snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
5869 			year, mon, day, hour, min, sec);
5870 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5871 	    }
5872 	    break;
5873 	case XML_SCHEMAS_GYEAR: {
5874 		char buf[30];
5875 		/* TODO: Unclear in XML Schema 1.0 */
5876 		/* TODO: What to do with the timezone? */
5877 		snprintf(buf, 30, "%04ld", val->value.date.year);
5878 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5879 	    }
5880 	    break;
5881 	case XML_SCHEMAS_GMONTH: {
5882 		/* TODO: Unclear in XML Schema 1.0 */
5883 		/* TODO: What to do with the timezone? */
5884 		*retValue = xmlMalloc(6);
5885 		if (*retValue == NULL)
5886 		    return(-1);
5887 		snprintf((char *) *retValue, 6, "--%02u",
5888 		    val->value.date.mon);
5889 	    }
5890 	    break;
5891         case XML_SCHEMAS_GDAY: {
5892 		/* TODO: Unclear in XML Schema 1.0 */
5893 		/* TODO: What to do with the timezone? */
5894 		*retValue = xmlMalloc(6);
5895 		if (*retValue == NULL)
5896 		    return(-1);
5897 		snprintf((char *) *retValue, 6, "---%02u",
5898 		    val->value.date.day);
5899 	    }
5900 	    break;
5901         case XML_SCHEMAS_GMONTHDAY: {
5902 		/* TODO: Unclear in XML Schema 1.0 */
5903 		/* TODO: What to do with the timezone? */
5904 		*retValue = xmlMalloc(8);
5905 		if (*retValue == NULL)
5906 		    return(-1);
5907 		snprintf((char *) *retValue, 8, "--%02u-%02u",
5908 		    val->value.date.mon, val->value.date.day);
5909 	    }
5910 	    break;
5911         case XML_SCHEMAS_GYEARMONTH: {
5912 		char buf[35];
5913 		/* TODO: Unclear in XML Schema 1.0 */
5914 		/* TODO: What to do with the timezone? */
5915 		if (val->value.date.year < 0)
5916 		    snprintf(buf, 35, "-%04ld-%02u",
5917 			labs(val->value.date.year),
5918 			val->value.date.mon);
5919 		else
5920 		    snprintf(buf, 35, "%04ld-%02u",
5921 			val->value.date.year, val->value.date.mon);
5922 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5923 	    }
5924 	    break;
5925 	case XML_SCHEMAS_TIME:
5926 	    {
5927 		char buf[30];
5928 
5929 		if (val->value.date.tz_flag) {
5930 		    xmlSchemaValPtr norm;
5931 
5932 		    norm = xmlSchemaDateNormalize(val, 0);
5933 		    if (norm == NULL)
5934 			return (-1);
5935 		    /*
5936 		    * TODO: Check if "%.14g" is portable.
5937 		    */
5938 		    snprintf(buf, 30,
5939 			"%02u:%02u:%02.14gZ",
5940 			norm->value.date.hour,
5941 			norm->value.date.min,
5942 			norm->value.date.sec);
5943 		    xmlSchemaFreeValue(norm);
5944 		} else {
5945 		    snprintf(buf, 30,
5946 			"%02u:%02u:%02.14g",
5947 			val->value.date.hour,
5948 			val->value.date.min,
5949 			val->value.date.sec);
5950 		}
5951 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5952 	    }
5953 	    break;
5954         case XML_SCHEMAS_DATE:
5955 	    {
5956 		char buf[30];
5957 
5958 		if (val->value.date.tz_flag) {
5959 		    xmlSchemaValPtr norm;
5960 
5961 		    norm = xmlSchemaDateNormalize(val, 0);
5962 		    if (norm == NULL)
5963 			return (-1);
5964 		    /*
5965 		    * TODO: Append the canonical value of the
5966 		    * recoverable timezone and not "Z".
5967 		    */
5968 		    snprintf(buf, 30,
5969 			"%04ld:%02u:%02uZ",
5970 			norm->value.date.year, norm->value.date.mon,
5971 			norm->value.date.day);
5972 		    xmlSchemaFreeValue(norm);
5973 		} else {
5974 		    snprintf(buf, 30,
5975 			"%04ld:%02u:%02u",
5976 			val->value.date.year, val->value.date.mon,
5977 			val->value.date.day);
5978 		}
5979 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5980 	    }
5981 	    break;
5982         case XML_SCHEMAS_DATETIME:
5983 	    {
5984 		char buf[50];
5985 
5986 		if (val->value.date.tz_flag) {
5987 		    xmlSchemaValPtr norm;
5988 
5989 		    norm = xmlSchemaDateNormalize(val, 0);
5990 		    if (norm == NULL)
5991 			return (-1);
5992 		    /*
5993 		    * TODO: Check if "%.14g" is portable.
5994 		    */
5995 		    snprintf(buf, 50,
5996 			"%04ld:%02u:%02uT%02u:%02u:%02.14gZ",
5997 			norm->value.date.year, norm->value.date.mon,
5998 			norm->value.date.day, norm->value.date.hour,
5999 			norm->value.date.min, norm->value.date.sec);
6000 		    xmlSchemaFreeValue(norm);
6001 		} else {
6002 		    snprintf(buf, 50,
6003 			"%04ld:%02u:%02uT%02u:%02u:%02.14g",
6004 			val->value.date.year, val->value.date.mon,
6005 			val->value.date.day, val->value.date.hour,
6006 			val->value.date.min, val->value.date.sec);
6007 		}
6008 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6009 	    }
6010 	    break;
6011 	case XML_SCHEMAS_HEXBINARY:
6012 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str);
6013 	    break;
6014 	case XML_SCHEMAS_BASE64BINARY:
6015 	    /*
6016 	    * TODO: Is the following spec piece implemented?:
6017 	    * SPEC: "Note: For some values the canonical form defined
6018 	    * above does not conform to [RFC 2045], which requires breaking
6019 	    * with linefeeds at appropriate intervals."
6020 	    */
6021 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str);
6022 	    break;
6023 	case XML_SCHEMAS_FLOAT: {
6024 		char buf[30];
6025 		/*
6026 		* |m| < 16777216, -149 <= e <= 104.
6027 		* TODO: Handle, NaN, INF, -INF. The format is not
6028 		* yet conformant. The c type float does not cover
6029 		* the whole range.
6030 		*/
6031 		snprintf(buf, 30, "%01.14e", val->value.f);
6032 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6033 	    }
6034 	    break;
6035 	case XML_SCHEMAS_DOUBLE: {
6036 		char buf[40];
6037 		/* |m| < 9007199254740992, -1075 <= e <= 970 */
6038 		/*
6039 		* TODO: Handle, NaN, INF, -INF. The format is not
6040 		* yet conformant. The c type float does not cover
6041 		* the whole range.
6042 		*/
6043 		snprintf(buf, 40, "%01.14e", val->value.d);
6044 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6045 	    }
6046 	    break;
6047 	default:
6048 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST "???");
6049 	    return (1);
6050     }
6051     if (*retValue == NULL)
6052 	return(-1);
6053     return (0);
6054 }
6055 
6056 /**
6057  * xmlSchemaGetCanonValueWhtsp:
6058  * @val: the precomputed value
6059  * @retValue: the returned value
6060  * @ws: the whitespace type of the value
6061  *
6062  * Get a the cononical representation of the value.
6063  * The caller has to free the returned @retValue.
6064  *
6065  * Returns 0 if the value could be built, 1 if the value type is
6066  * not supported yet and -1 in case of API errors.
6067  */
6068 int
xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,const xmlChar ** retValue,xmlSchemaWhitespaceValueType ws)6069 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,
6070 			    const xmlChar **retValue,
6071 			    xmlSchemaWhitespaceValueType ws)
6072 {
6073     if ((retValue == NULL) || (val == NULL))
6074 	return (-1);
6075     if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) ||
6076 	(ws > XML_SCHEMA_WHITESPACE_COLLAPSE))
6077 	return (-1);
6078 
6079     *retValue = NULL;
6080     switch (val->type) {
6081 	case XML_SCHEMAS_STRING:
6082 	    if (val->value.str == NULL)
6083 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6084 	    else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6085 		*retValue = xmlSchemaCollapseString(val->value.str);
6086 	    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
6087 		*retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6088 	    if ((*retValue) == NULL)
6089 		*retValue = BAD_CAST xmlStrdup(val->value.str);
6090 	    break;
6091 	case XML_SCHEMAS_NORMSTRING:
6092 	    if (val->value.str == NULL)
6093 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6094 	    else {
6095 		if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6096 		    *retValue = xmlSchemaCollapseString(val->value.str);
6097 		else
6098 		    *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6099 		if ((*retValue) == NULL)
6100 		    *retValue = BAD_CAST xmlStrdup(val->value.str);
6101 	    }
6102 	    break;
6103 	default:
6104 	    return (xmlSchemaGetCanonValue(val, retValue));
6105     }
6106     return (0);
6107 }
6108 
6109 /**
6110  * xmlSchemaGetValType:
6111  * @val: a schemas value
6112  *
6113  * Accessor for the type of a value
6114  *
6115  * Returns the xmlSchemaValType of the value
6116  */
6117 xmlSchemaValType
xmlSchemaGetValType(xmlSchemaValPtr val)6118 xmlSchemaGetValType(xmlSchemaValPtr val)
6119 {
6120     if (val == NULL)
6121         return(XML_SCHEMAS_UNKNOWN);
6122     return (val->type);
6123 }
6124 
6125 #define bottom_xmlschemastypes
6126 #include "elfgcchack.h"
6127 #endif /* LIBXML_SCHEMAS_ENABLED */
6128