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