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