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