• 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 explicitly 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 validation
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 existent 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 ((norm == NULL) && (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 of indent: 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         /* FIXME: This doesn't take leap year exceptions every 100/400 years
3632            into account. */
3633 	maxday = 365 * myear + (myear + 3) / 4;
3634         /* FIXME: Needs to be calculated separately */
3635 	minday = maxday - 1;
3636     }
3637 
3638     xmon = xmon % 12;
3639     minday += dayRange[0][xmon];
3640     maxday += dayRange[1][xmon];
3641 
3642     if ((maxday == minday) && (maxday == xday))
3643 	return(0); /* can this really happen ? */
3644     if (maxday < xday)
3645         return(-invert);
3646     if (minday > xday)
3647         return(invert);
3648 
3649     /* indeterminate */
3650     return 2;
3651 }
3652 
3653 /*
3654  * macros for adding date/times and durations
3655  */
3656 #define FQUOTIENT(a,b)                  (floor(((double)a/(double)b)))
3657 #define MODULO(a,b)                     (a - FQUOTIENT(a,b) * b)
3658 #define FQUOTIENT_RANGE(a,low,high)     (FQUOTIENT((a-low),(high-low)))
3659 #define MODULO_RANGE(a,low,high)        ((MODULO((a-low),(high-low)))+low)
3660 
3661 /**
3662  * xmlSchemaDupVal:
3663  * @v: the #xmlSchemaValPtr value to duplicate
3664  *
3665  * Makes a copy of @v. The calling program is responsible for freeing
3666  * the returned value.
3667  *
3668  * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error.
3669  */
3670 static xmlSchemaValPtr
xmlSchemaDupVal(xmlSchemaValPtr v)3671 xmlSchemaDupVal (xmlSchemaValPtr v)
3672 {
3673     xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
3674     if (ret == NULL)
3675         return NULL;
3676 
3677     memcpy(ret, v, sizeof(xmlSchemaVal));
3678     ret->next = NULL;
3679     return ret;
3680 }
3681 
3682 /**
3683  * xmlSchemaCopyValue:
3684  * @val:  the precomputed value to be copied
3685  *
3686  * Copies the precomputed value. This duplicates any string within.
3687  *
3688  * Returns the copy or NULL if a copy for a data-type is not implemented.
3689  */
3690 xmlSchemaValPtr
xmlSchemaCopyValue(xmlSchemaValPtr val)3691 xmlSchemaCopyValue(xmlSchemaValPtr val)
3692 {
3693     xmlSchemaValPtr ret = NULL, prev = NULL, cur;
3694 
3695     /*
3696     * Copy the string values.
3697     */
3698     while (val != NULL) {
3699 	switch (val->type) {
3700 	    case XML_SCHEMAS_ANYTYPE:
3701 	    case XML_SCHEMAS_IDREFS:
3702 	    case XML_SCHEMAS_ENTITIES:
3703 	    case XML_SCHEMAS_NMTOKENS:
3704 		xmlSchemaFreeValue(ret);
3705 		return (NULL);
3706 	    case XML_SCHEMAS_ANYSIMPLETYPE:
3707 	    case XML_SCHEMAS_STRING:
3708 	    case XML_SCHEMAS_NORMSTRING:
3709 	    case XML_SCHEMAS_TOKEN:
3710 	    case XML_SCHEMAS_LANGUAGE:
3711 	    case XML_SCHEMAS_NAME:
3712 	    case XML_SCHEMAS_NCNAME:
3713 	    case XML_SCHEMAS_ID:
3714 	    case XML_SCHEMAS_IDREF:
3715 	    case XML_SCHEMAS_ENTITY:
3716 	    case XML_SCHEMAS_NMTOKEN:
3717 	    case XML_SCHEMAS_ANYURI:
3718 		cur = xmlSchemaDupVal(val);
3719 		if (val->value.str != NULL)
3720 		    cur->value.str = xmlStrdup(BAD_CAST val->value.str);
3721 		break;
3722 	    case XML_SCHEMAS_QNAME:
3723 	    case XML_SCHEMAS_NOTATION:
3724 		cur = xmlSchemaDupVal(val);
3725 		if (val->value.qname.name != NULL)
3726 		    cur->value.qname.name =
3727                     xmlStrdup(BAD_CAST val->value.qname.name);
3728 		if (val->value.qname.uri != NULL)
3729 		    cur->value.qname.uri =
3730                     xmlStrdup(BAD_CAST val->value.qname.uri);
3731 		break;
3732 	    case XML_SCHEMAS_HEXBINARY:
3733 		cur = xmlSchemaDupVal(val);
3734 		if (val->value.hex.str != NULL)
3735 		    cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str);
3736 		break;
3737 	    case XML_SCHEMAS_BASE64BINARY:
3738 		cur = xmlSchemaDupVal(val);
3739 		if (val->value.base64.str != NULL)
3740 		    cur->value.base64.str =
3741                     xmlStrdup(BAD_CAST val->value.base64.str);
3742 		break;
3743 	    default:
3744 		cur = xmlSchemaDupVal(val);
3745 		break;
3746 	}
3747 	if (ret == NULL)
3748 	    ret = cur;
3749 	else
3750 	    prev->next = cur;
3751 	prev = cur;
3752 	val = val->next;
3753     }
3754     return (ret);
3755 }
3756 
3757 /**
3758  * _xmlSchemaDateAdd:
3759  * @dt: an #xmlSchemaValPtr
3760  * @dur: an #xmlSchemaValPtr of type #XS_DURATION
3761  *
3762  * Compute a new date/time from @dt and @dur. This function assumes @dt
3763  * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
3764  * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as
3765  * @dt. The calling program is responsible for freeing the returned value.
3766  *
3767  * Returns a pointer to a new #xmlSchemaVal or NULL if error.
3768  */
3769 static xmlSchemaValPtr
_xmlSchemaDateAdd(xmlSchemaValPtr dt,xmlSchemaValPtr dur)3770 _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
3771 {
3772     xmlSchemaValPtr ret, tmp;
3773     long carry, tempdays, temp;
3774     xmlSchemaValDatePtr r, d;
3775     xmlSchemaValDurationPtr u;
3776 
3777     if ((dt == NULL) || (dur == NULL))
3778         return NULL;
3779 
3780     ret = xmlSchemaNewValue(dt->type);
3781     if (ret == NULL)
3782         return NULL;
3783 
3784     /* make a copy so we don't alter the original value */
3785     tmp = xmlSchemaDupVal(dt);
3786     if (tmp == NULL) {
3787         xmlSchemaFreeValue(ret);
3788         return NULL;
3789     }
3790 
3791     r = &(ret->value.date);
3792     d = &(tmp->value.date);
3793     u = &(dur->value.dur);
3794 
3795     /* normalization */
3796     if (d->mon == 0)
3797         d->mon = 1;
3798 
3799     /* normalize for time zone offset */
3800     u->sec -= (d->tzo * 60);
3801     d->tzo = 0;
3802 
3803     /* normalization */
3804     if (d->day == 0)
3805         d->day = 1;
3806 
3807     /* month */
3808     carry  = d->mon + u->mon;
3809     r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13);
3810     carry  = (long) FQUOTIENT_RANGE(carry, 1, 13);
3811 
3812     /* year (may be modified later) */
3813     r->year = d->year + carry;
3814     if (r->year == 0) {
3815         if (d->year > 0)
3816             r->year--;
3817         else
3818             r->year++;
3819     }
3820 
3821     /* time zone */
3822     r->tzo     = d->tzo;
3823     r->tz_flag = d->tz_flag;
3824 
3825     /* seconds */
3826     r->sec = d->sec + u->sec;
3827     carry  = (long) FQUOTIENT((long)r->sec, 60);
3828     if (r->sec != 0.0) {
3829         r->sec = MODULO(r->sec, 60.0);
3830     }
3831 
3832     /* minute */
3833     carry += d->min;
3834     r->min = (unsigned int) MODULO(carry, 60);
3835     carry  = (long) FQUOTIENT(carry, 60);
3836 
3837     /* hours */
3838     carry  += d->hour;
3839     r->hour = (unsigned int) MODULO(carry, 24);
3840     carry   = (long)FQUOTIENT(carry, 24);
3841 
3842     /*
3843      * days
3844      * Note we use tempdays because the temporary values may need more
3845      * than 5 bits
3846      */
3847     if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
3848                   (d->day > MAX_DAYINMONTH(r->year, r->mon)))
3849         tempdays = MAX_DAYINMONTH(r->year, r->mon);
3850     else if (d->day < 1)
3851         tempdays = 1;
3852     else
3853         tempdays = d->day;
3854 
3855     tempdays += u->day + carry;
3856 
3857     while (1) {
3858         if (tempdays < 1) {
3859             long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13);
3860             long tyr  = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13);
3861             if (tyr == 0)
3862                 tyr--;
3863 	    /*
3864 	     * Coverity detected an overrun in daysInMonth
3865 	     * of size 12 at position 12 with index variable "((r)->mon - 1)"
3866 	     */
3867 	    if (tmon < 1)
3868 	        tmon = 1;
3869 	    if (tmon > 12)
3870 	        tmon = 12;
3871             tempdays += MAX_DAYINMONTH(tyr, tmon);
3872             carry = -1;
3873         } else if (VALID_YEAR(r->year) && VALID_MONTH(r->mon) &&
3874                    tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) {
3875             tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
3876             carry = 1;
3877         } else
3878             break;
3879 
3880         temp = r->mon + carry;
3881         r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13);
3882         r->year = r->year + (long) FQUOTIENT_RANGE(temp, 1, 13);
3883         if (r->year == 0) {
3884             if (temp < 1)
3885                 r->year--;
3886             else
3887                 r->year++;
3888 	}
3889     }
3890 
3891     r->day = tempdays;
3892 
3893     /*
3894      * adjust the date/time type to the date values
3895      */
3896     if (ret->type != XML_SCHEMAS_DATETIME) {
3897         if ((r->hour) || (r->min) || (r->sec))
3898             ret->type = XML_SCHEMAS_DATETIME;
3899         else if (ret->type != XML_SCHEMAS_DATE) {
3900             if ((r->mon != 1) && (r->day != 1))
3901                 ret->type = XML_SCHEMAS_DATE;
3902             else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
3903                 ret->type = XML_SCHEMAS_GYEARMONTH;
3904         }
3905     }
3906 
3907     xmlSchemaFreeValue(tmp);
3908 
3909     return ret;
3910 }
3911 
3912 /**
3913  * xmlSchemaDateNormalize:
3914  * @dt: an #xmlSchemaValPtr of a date/time type value.
3915  * @offset: number of seconds to adjust @dt by.
3916  *
3917  * Normalize @dt to GMT time. The @offset parameter is subtracted from
3918  * the return value is a time-zone offset is present on @dt.
3919  *
3920  * Returns a normalized copy of @dt or NULL if error.
3921  */
3922 static xmlSchemaValPtr
xmlSchemaDateNormalize(xmlSchemaValPtr dt,double offset)3923 xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
3924 {
3925     xmlSchemaValPtr dur, ret;
3926 
3927     if (dt == NULL)
3928         return NULL;
3929 
3930     if (((dt->type != XML_SCHEMAS_TIME) &&
3931          (dt->type != XML_SCHEMAS_DATETIME) &&
3932 	 (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0))
3933         return xmlSchemaDupVal(dt);
3934 
3935     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
3936     if (dur == NULL)
3937         return NULL;
3938 
3939     dur->value.date.sec -= offset;
3940 
3941     ret = _xmlSchemaDateAdd(dt, dur);
3942     if (ret == NULL)
3943         return NULL;
3944 
3945     xmlSchemaFreeValue(dur);
3946 
3947     /* ret->value.date.tzo = 0; */
3948     return ret;
3949 }
3950 
3951 /**
3952  * _xmlSchemaDateCastYMToDays:
3953  * @dt: an #xmlSchemaValPtr
3954  *
3955  * Convert mon and year of @dt to total number of days. Take the
3956  * number of years since (or before) 1 AD and add the number of leap
3957  * years. This is a function  because negative
3958  * years must be handled a little differently and there is no zero year.
3959  *
3960  * Returns number of days.
3961  */
3962 static long
_xmlSchemaDateCastYMToDays(const xmlSchemaValPtr dt)3963 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
3964 {
3965     long ret;
3966     int mon;
3967 
3968     mon = dt->value.date.mon;
3969     if (mon <= 0) mon = 1; /* normalization */
3970 
3971     if (dt->value.date.year <= 0)
3972         ret = (dt->value.date.year * 365) +
3973               (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
3974                ((dt->value.date.year+1)/400)) +
3975               DAY_IN_YEAR(0, mon, dt->value.date.year);
3976     else
3977         ret = ((dt->value.date.year-1) * 365) +
3978               (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
3979                ((dt->value.date.year-1)/400)) +
3980               DAY_IN_YEAR(0, mon, dt->value.date.year);
3981 
3982     return ret;
3983 }
3984 
3985 /**
3986  * TIME_TO_NUMBER:
3987  * @dt:  an #xmlSchemaValPtr
3988  *
3989  * Calculates the number of seconds in the time portion of @dt.
3990  *
3991  * Returns seconds.
3992  */
3993 #define TIME_TO_NUMBER(dt)                              \
3994     ((double)((dt->value.date.hour * SECS_PER_HOUR) +   \
3995               (dt->value.date.min * SECS_PER_MIN) +	\
3996               (dt->value.date.tzo * SECS_PER_MIN)) +	\
3997                dt->value.date.sec)
3998 
3999 /**
4000  * xmlSchemaCompareDates:
4001  * @x:  a first date/time value
4002  * @y:  a second date/time value
4003  *
4004  * Compare 2 date/times
4005  *
4006  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4007  * case of error
4008  */
4009 static int
xmlSchemaCompareDates(xmlSchemaValPtr x,xmlSchemaValPtr y)4010 xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
4011 {
4012     unsigned char xmask, ymask, xor_mask, and_mask;
4013     xmlSchemaValPtr p1, p2, q1, q2;
4014     long p1d, p2d, q1d, q2d;
4015 
4016     if ((x == NULL) || (y == NULL))
4017         return -2;
4018 
4019     if (x->value.date.tz_flag) {
4020 
4021         if (!y->value.date.tz_flag) {
4022             p1 = xmlSchemaDateNormalize(x, 0);
4023             p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4024             /* normalize y + 14:00 */
4025             q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
4026 
4027             q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4028             if (p1d < q1d) {
4029 		xmlSchemaFreeValue(p1);
4030 		xmlSchemaFreeValue(q1);
4031                 return -1;
4032 	    } else if (p1d == q1d) {
4033                 double sec;
4034 
4035                 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4036                 if (sec < 0.0) {
4037 		    xmlSchemaFreeValue(p1);
4038 		    xmlSchemaFreeValue(q1);
4039                     return -1;
4040 		} else {
4041 		    int ret = 0;
4042                     /* normalize y - 14:00 */
4043                     q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
4044                     q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
4045                     if (p1d > q2d)
4046                         ret = 1;
4047                     else if (p1d == q2d) {
4048                         sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
4049                         if (sec > 0.0)
4050                             ret = 1;
4051                         else
4052                             ret = 2; /* indeterminate */
4053                     }
4054 		    xmlSchemaFreeValue(p1);
4055 		    xmlSchemaFreeValue(q1);
4056 		    xmlSchemaFreeValue(q2);
4057 		    if (ret != 0)
4058 		        return(ret);
4059                 }
4060             } else {
4061 		xmlSchemaFreeValue(p1);
4062 		xmlSchemaFreeValue(q1);
4063 	    }
4064         }
4065     } else if (y->value.date.tz_flag) {
4066         q1 = xmlSchemaDateNormalize(y, 0);
4067         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4068 
4069         /* normalize x - 14:00 */
4070         p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
4071         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4072 
4073         if (p1d < q1d) {
4074 	    xmlSchemaFreeValue(p1);
4075 	    xmlSchemaFreeValue(q1);
4076             return -1;
4077 	} else if (p1d == q1d) {
4078             double sec;
4079 
4080             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4081             if (sec < 0.0) {
4082 		xmlSchemaFreeValue(p1);
4083 		xmlSchemaFreeValue(q1);
4084                 return -1;
4085 	    } else {
4086 	        int ret = 0;
4087                 /* normalize x + 14:00 */
4088                 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
4089                 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
4090 
4091                 if (p2d > q1d) {
4092                     ret = 1;
4093 		} else if (p2d == q1d) {
4094                     sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
4095                     if (sec > 0.0)
4096                         ret = 1;
4097                     else
4098                         ret = 2; /* indeterminate */
4099                 }
4100 		xmlSchemaFreeValue(p1);
4101 		xmlSchemaFreeValue(q1);
4102 		xmlSchemaFreeValue(p2);
4103 		if (ret != 0)
4104 		    return(ret);
4105             }
4106 	} else {
4107 	    xmlSchemaFreeValue(p1);
4108 	    xmlSchemaFreeValue(q1);
4109         }
4110     }
4111 
4112     /*
4113      * if the same type then calculate the difference
4114      */
4115     if (x->type == y->type) {
4116         int ret = 0;
4117         q1 = xmlSchemaDateNormalize(y, 0);
4118         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
4119 
4120         p1 = xmlSchemaDateNormalize(x, 0);
4121         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
4122 
4123         if (p1d < q1d) {
4124             ret = -1;
4125 	} else if (p1d > q1d) {
4126             ret = 1;
4127 	} else {
4128             double sec;
4129 
4130             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
4131             if (sec < 0.0)
4132                 ret = -1;
4133             else if (sec > 0.0)
4134                 ret = 1;
4135 
4136         }
4137 	xmlSchemaFreeValue(p1);
4138 	xmlSchemaFreeValue(q1);
4139         return(ret);
4140     }
4141 
4142     switch (x->type) {
4143         case XML_SCHEMAS_DATETIME:
4144             xmask = 0xf;
4145             break;
4146         case XML_SCHEMAS_DATE:
4147             xmask = 0x7;
4148             break;
4149         case XML_SCHEMAS_GYEAR:
4150             xmask = 0x1;
4151             break;
4152         case XML_SCHEMAS_GMONTH:
4153             xmask = 0x2;
4154             break;
4155         case XML_SCHEMAS_GDAY:
4156             xmask = 0x3;
4157             break;
4158         case XML_SCHEMAS_GYEARMONTH:
4159             xmask = 0x3;
4160             break;
4161         case XML_SCHEMAS_GMONTHDAY:
4162             xmask = 0x6;
4163             break;
4164         case XML_SCHEMAS_TIME:
4165             xmask = 0x8;
4166             break;
4167         default:
4168             xmask = 0;
4169             break;
4170     }
4171 
4172     switch (y->type) {
4173         case XML_SCHEMAS_DATETIME:
4174             ymask = 0xf;
4175             break;
4176         case XML_SCHEMAS_DATE:
4177             ymask = 0x7;
4178             break;
4179         case XML_SCHEMAS_GYEAR:
4180             ymask = 0x1;
4181             break;
4182         case XML_SCHEMAS_GMONTH:
4183             ymask = 0x2;
4184             break;
4185         case XML_SCHEMAS_GDAY:
4186             ymask = 0x3;
4187             break;
4188         case XML_SCHEMAS_GYEARMONTH:
4189             ymask = 0x3;
4190             break;
4191         case XML_SCHEMAS_GMONTHDAY:
4192             ymask = 0x6;
4193             break;
4194         case XML_SCHEMAS_TIME:
4195             ymask = 0x8;
4196             break;
4197         default:
4198             ymask = 0;
4199             break;
4200     }
4201 
4202     xor_mask = xmask ^ ymask;           /* mark type differences */
4203     and_mask = xmask & ymask;           /* mark field specification */
4204 
4205     /* year */
4206     if (xor_mask & 1)
4207         return 2; /* indeterminate */
4208     else if (and_mask & 1) {
4209         if (x->value.date.year < y->value.date.year)
4210             return -1;
4211         else if (x->value.date.year > y->value.date.year)
4212             return 1;
4213     }
4214 
4215     /* month */
4216     if (xor_mask & 2)
4217         return 2; /* indeterminate */
4218     else if (and_mask & 2) {
4219         if (x->value.date.mon < y->value.date.mon)
4220             return -1;
4221         else if (x->value.date.mon > y->value.date.mon)
4222             return 1;
4223     }
4224 
4225     /* day */
4226     if (xor_mask & 4)
4227         return 2; /* indeterminate */
4228     else if (and_mask & 4) {
4229         if (x->value.date.day < y->value.date.day)
4230             return -1;
4231         else if (x->value.date.day > y->value.date.day)
4232             return 1;
4233     }
4234 
4235     /* time */
4236     if (xor_mask & 8)
4237         return 2; /* indeterminate */
4238     else if (and_mask & 8) {
4239         if (x->value.date.hour < y->value.date.hour)
4240             return -1;
4241         else if (x->value.date.hour > y->value.date.hour)
4242             return 1;
4243         else if (x->value.date.min < y->value.date.min)
4244             return -1;
4245         else if (x->value.date.min > y->value.date.min)
4246             return 1;
4247         else if (x->value.date.sec < y->value.date.sec)
4248             return -1;
4249         else if (x->value.date.sec > y->value.date.sec)
4250             return 1;
4251     }
4252 
4253     return 0;
4254 }
4255 
4256 /**
4257  * xmlSchemaComparePreserveReplaceStrings:
4258  * @x:  a first string value
4259  * @y:  a second string value
4260  * @invert: inverts the result if x < y or x > y.
4261  *
4262  * Compare 2 string for their normalized values.
4263  * @x is a string with whitespace of "preserve", @y is
4264  * a string with a whitespace of "replace". I.e. @x could
4265  * be an "xsd:string" and @y an "xsd:normalizedString".
4266  *
4267  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4268  * case of error
4269  */
4270 static int
xmlSchemaComparePreserveReplaceStrings(const xmlChar * x,const xmlChar * y,int invert)4271 xmlSchemaComparePreserveReplaceStrings(const xmlChar *x,
4272 				       const xmlChar *y,
4273 				       int invert)
4274 {
4275     int tmp;
4276 
4277     while ((*x != 0) && (*y != 0)) {
4278 	if (IS_WSP_REPLACE_CH(*y)) {
4279 	    if (! IS_WSP_SPACE_CH(*x)) {
4280 		if ((*x - 0x20) < 0) {
4281 		    if (invert)
4282 			return(1);
4283 		    else
4284 			return(-1);
4285 		} else {
4286 		    if (invert)
4287 			return(-1);
4288 		    else
4289 			return(1);
4290 		}
4291 	    }
4292 	} else {
4293 	    tmp = *x - *y;
4294 	    if (tmp < 0) {
4295 		if (invert)
4296 		    return(1);
4297 		else
4298 		    return(-1);
4299 	    }
4300 	    if (tmp > 0) {
4301 		if (invert)
4302 		    return(-1);
4303 		else
4304 		    return(1);
4305 	    }
4306 	}
4307 	x++;
4308 	y++;
4309     }
4310     if (*x != 0) {
4311 	if (invert)
4312 	    return(-1);
4313 	else
4314 	    return(1);
4315     }
4316     if (*y != 0) {
4317 	if (invert)
4318 	    return(1);
4319 	else
4320 	    return(-1);
4321     }
4322     return(0);
4323 }
4324 
4325 /**
4326  * xmlSchemaComparePreserveCollapseStrings:
4327  * @x:  a first string value
4328  * @y:  a second string value
4329  *
4330  * Compare 2 string for their normalized values.
4331  * @x is a string with whitespace of "preserve", @y is
4332  * a string with a whitespace of "collapse". I.e. @x could
4333  * be an "xsd:string" and @y an "xsd:normalizedString".
4334  *
4335  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4336  * case of error
4337  */
4338 static int
xmlSchemaComparePreserveCollapseStrings(const xmlChar * x,const xmlChar * y,int invert)4339 xmlSchemaComparePreserveCollapseStrings(const xmlChar *x,
4340 				        const xmlChar *y,
4341 					int invert)
4342 {
4343     int tmp;
4344 
4345     /*
4346     * Skip leading blank chars of the collapsed string.
4347     */
4348     while IS_WSP_BLANK_CH(*y)
4349 	y++;
4350 
4351     while ((*x != 0) && (*y != 0)) {
4352 	if IS_WSP_BLANK_CH(*y) {
4353 	    if (! IS_WSP_SPACE_CH(*x)) {
4354 		/*
4355 		* The yv character would have been replaced to 0x20.
4356 		*/
4357 		if ((*x - 0x20) < 0) {
4358 		    if (invert)
4359 			return(1);
4360 		    else
4361 			return(-1);
4362 		} else {
4363 		    if (invert)
4364 			return(-1);
4365 		    else
4366 			return(1);
4367 		}
4368 	    }
4369 	    x++;
4370 	    y++;
4371 	    /*
4372 	    * Skip contiguous blank chars of the collapsed string.
4373 	    */
4374 	    while IS_WSP_BLANK_CH(*y)
4375 		y++;
4376 	} else {
4377 	    tmp = *x++ - *y++;
4378 	    if (tmp < 0) {
4379 		if (invert)
4380 		    return(1);
4381 		else
4382 		    return(-1);
4383 	    }
4384 	    if (tmp > 0) {
4385 		if (invert)
4386 		    return(-1);
4387 		else
4388 		    return(1);
4389 	    }
4390 	}
4391     }
4392     if (*x != 0) {
4393 	 if (invert)
4394 	     return(-1);
4395 	 else
4396 	     return(1);
4397     }
4398     if (*y != 0) {
4399 	/*
4400 	* Skip trailing blank chars of the collapsed string.
4401 	*/
4402 	while IS_WSP_BLANK_CH(*y)
4403 	    y++;
4404 	if (*y != 0) {
4405 	    if (invert)
4406 		return(1);
4407 	    else
4408 		return(-1);
4409 	}
4410     }
4411     return(0);
4412 }
4413 
4414 /**
4415  * xmlSchemaComparePreserveCollapseStrings:
4416  * @x:  a first string value
4417  * @y:  a second string value
4418  *
4419  * Compare 2 string for their normalized values.
4420  * @x is a string with whitespace of "preserve", @y is
4421  * a string with a whitespace of "collapse". I.e. @x could
4422  * be an "xsd:string" and @y an "xsd:normalizedString".
4423  *
4424  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4425  * case of error
4426  */
4427 static int
xmlSchemaCompareReplaceCollapseStrings(const xmlChar * x,const xmlChar * y,int invert)4428 xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x,
4429 				       const xmlChar *y,
4430 				       int invert)
4431 {
4432     int tmp;
4433 
4434     /*
4435     * Skip leading blank chars of the collapsed string.
4436     */
4437     while IS_WSP_BLANK_CH(*y)
4438 	y++;
4439 
4440     while ((*x != 0) && (*y != 0)) {
4441 	if IS_WSP_BLANK_CH(*y) {
4442 	    if (! IS_WSP_BLANK_CH(*x)) {
4443 		/*
4444 		* The yv character would have been replaced to 0x20.
4445 		*/
4446 		if ((*x - 0x20) < 0) {
4447 		    if (invert)
4448 			return(1);
4449 		    else
4450 			return(-1);
4451 		} else {
4452 		    if (invert)
4453 			return(-1);
4454 		    else
4455 			return(1);
4456 		}
4457 	    }
4458 	    x++;
4459 	    y++;
4460 	    /*
4461 	    * Skip contiguous blank chars of the collapsed string.
4462 	    */
4463 	    while IS_WSP_BLANK_CH(*y)
4464 		y++;
4465 	} else {
4466 	    if IS_WSP_BLANK_CH(*x) {
4467 		/*
4468 		* The xv character would have been replaced to 0x20.
4469 		*/
4470 		if ((0x20 - *y) < 0) {
4471 		    if (invert)
4472 			return(1);
4473 		    else
4474 			return(-1);
4475 		} else {
4476 		    if (invert)
4477 			return(-1);
4478 		    else
4479 			return(1);
4480 		}
4481 	    }
4482 	    tmp = *x++ - *y++;
4483 	    if (tmp < 0)
4484 		return(-1);
4485 	    if (tmp > 0)
4486 		return(1);
4487 	}
4488     }
4489     if (*x != 0) {
4490 	 if (invert)
4491 	     return(-1);
4492 	 else
4493 	     return(1);
4494     }
4495     if (*y != 0) {
4496 	/*
4497 	* Skip trailing blank chars of the collapsed string.
4498 	*/
4499 	while IS_WSP_BLANK_CH(*y)
4500 	    y++;
4501 	if (*y != 0) {
4502 	    if (invert)
4503 		return(1);
4504 	    else
4505 		return(-1);
4506 	}
4507     }
4508     return(0);
4509 }
4510 
4511 
4512 /**
4513  * xmlSchemaCompareReplacedStrings:
4514  * @x:  a first string value
4515  * @y:  a second string value
4516  *
4517  * Compare 2 string for their normalized values.
4518  *
4519  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4520  * case of error
4521  */
4522 static int
xmlSchemaCompareReplacedStrings(const xmlChar * x,const xmlChar * y)4523 xmlSchemaCompareReplacedStrings(const xmlChar *x,
4524 				const xmlChar *y)
4525 {
4526     int tmp;
4527 
4528     while ((*x != 0) && (*y != 0)) {
4529 	if IS_WSP_BLANK_CH(*y) {
4530 	    if (! IS_WSP_BLANK_CH(*x)) {
4531 		if ((*x - 0x20) < 0)
4532 		    return(-1);
4533 		else
4534 		    return(1);
4535 	    }
4536 	} else {
4537 	    if IS_WSP_BLANK_CH(*x) {
4538 		if ((0x20 - *y) < 0)
4539 		    return(-1);
4540 		else
4541 		    return(1);
4542 	    }
4543 	    tmp = *x - *y;
4544 	    if (tmp < 0)
4545 		return(-1);
4546 	    if (tmp > 0)
4547 		return(1);
4548 	}
4549 	x++;
4550 	y++;
4551     }
4552     if (*x != 0)
4553         return(1);
4554     if (*y != 0)
4555         return(-1);
4556     return(0);
4557 }
4558 
4559 /**
4560  * xmlSchemaCompareNormStrings:
4561  * @x:  a first string value
4562  * @y:  a second string value
4563  *
4564  * Compare 2 string for their normalized values.
4565  *
4566  * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
4567  * case of error
4568  */
4569 static int
xmlSchemaCompareNormStrings(const xmlChar * x,const xmlChar * y)4570 xmlSchemaCompareNormStrings(const xmlChar *x,
4571 			    const xmlChar *y) {
4572     int tmp;
4573 
4574     while (IS_BLANK_CH(*x)) x++;
4575     while (IS_BLANK_CH(*y)) y++;
4576     while ((*x != 0) && (*y != 0)) {
4577 	if (IS_BLANK_CH(*x)) {
4578 	    if (!IS_BLANK_CH(*y)) {
4579 		tmp = *x - *y;
4580 		return(tmp);
4581 	    }
4582 	    while (IS_BLANK_CH(*x)) x++;
4583 	    while (IS_BLANK_CH(*y)) y++;
4584 	} else {
4585 	    tmp = *x++ - *y++;
4586 	    if (tmp < 0)
4587 		return(-1);
4588 	    if (tmp > 0)
4589 		return(1);
4590 	}
4591     }
4592     if (*x != 0) {
4593 	while (IS_BLANK_CH(*x)) x++;
4594 	if (*x != 0)
4595 	    return(1);
4596     }
4597     if (*y != 0) {
4598 	while (IS_BLANK_CH(*y)) y++;
4599 	if (*y != 0)
4600 	    return(-1);
4601     }
4602     return(0);
4603 }
4604 
4605 /**
4606  * xmlSchemaCompareFloats:
4607  * @x:  a first float or double value
4608  * @y:  a second float or double value
4609  *
4610  * Compare 2 values
4611  *
4612  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4613  * case of error
4614  */
4615 static int
xmlSchemaCompareFloats(xmlSchemaValPtr x,xmlSchemaValPtr y)4616 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
4617     double d1, d2;
4618 
4619     if ((x == NULL) || (y == NULL))
4620 	return(-2);
4621 
4622     /*
4623      * Cast everything to doubles.
4624      */
4625     if (x->type == XML_SCHEMAS_DOUBLE)
4626 	d1 = x->value.d;
4627     else if (x->type == XML_SCHEMAS_FLOAT)
4628 	d1 = x->value.f;
4629     else
4630 	return(-2);
4631 
4632     if (y->type == XML_SCHEMAS_DOUBLE)
4633 	d2 = y->value.d;
4634     else if (y->type == XML_SCHEMAS_FLOAT)
4635 	d2 = y->value.f;
4636     else
4637 	return(-2);
4638 
4639     /*
4640      * Check for special cases.
4641      */
4642     if (xmlXPathIsNaN(d1)) {
4643 	if (xmlXPathIsNaN(d2))
4644 	    return(0);
4645 	return(1);
4646     }
4647     if (xmlXPathIsNaN(d2))
4648 	return(-1);
4649     if (d1 == xmlXPathPINF) {
4650 	if (d2 == xmlXPathPINF)
4651 	    return(0);
4652         return(1);
4653     }
4654     if (d2 == xmlXPathPINF)
4655         return(-1);
4656     if (d1 == xmlXPathNINF) {
4657 	if (d2 == xmlXPathNINF)
4658 	    return(0);
4659         return(-1);
4660     }
4661     if (d2 == xmlXPathNINF)
4662         return(1);
4663 
4664     /*
4665      * basic tests, the last one we should have equality, but
4666      * portability is more important than speed and handling
4667      * NaN or Inf in a portable way is always a challenge, so ...
4668      */
4669     if (d1 < d2)
4670 	return(-1);
4671     if (d1 > d2)
4672 	return(1);
4673     if (d1 == d2)
4674 	return(0);
4675     return(2);
4676 }
4677 
4678 /**
4679  * xmlSchemaCompareValues:
4680  * @x:  a first value
4681  * @xvalue: the first value as a string (optional)
4682  * @xwtsp: the whitespace type
4683  * @y:  a second value
4684  * @xvalue: the second value as a string (optional)
4685  * @ywtsp: the whitespace type
4686  *
4687  * Compare 2 values
4688  *
4689  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not
4690  * comparable and -2 in case of error
4691  */
4692 static int
xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,xmlSchemaValPtr x,const xmlChar * xvalue,xmlSchemaWhitespaceValueType xws,xmlSchemaValType ytype,xmlSchemaValPtr y,const xmlChar * yvalue,xmlSchemaWhitespaceValueType yws)4693 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
4694 			       xmlSchemaValPtr x,
4695 			       const xmlChar *xvalue,
4696 			       xmlSchemaWhitespaceValueType xws,
4697 			       xmlSchemaValType ytype,
4698 			       xmlSchemaValPtr y,
4699 			       const xmlChar *yvalue,
4700 			       xmlSchemaWhitespaceValueType yws)
4701 {
4702     switch (xtype) {
4703 	case XML_SCHEMAS_UNKNOWN:
4704 	case XML_SCHEMAS_ANYTYPE:
4705 	    return(-2);
4706         case XML_SCHEMAS_INTEGER:
4707         case XML_SCHEMAS_NPINTEGER:
4708         case XML_SCHEMAS_NINTEGER:
4709         case XML_SCHEMAS_NNINTEGER:
4710         case XML_SCHEMAS_PINTEGER:
4711         case XML_SCHEMAS_INT:
4712         case XML_SCHEMAS_UINT:
4713         case XML_SCHEMAS_LONG:
4714         case XML_SCHEMAS_ULONG:
4715         case XML_SCHEMAS_SHORT:
4716         case XML_SCHEMAS_USHORT:
4717         case XML_SCHEMAS_BYTE:
4718         case XML_SCHEMAS_UBYTE:
4719 	case XML_SCHEMAS_DECIMAL:
4720 	    if ((x == NULL) || (y == NULL))
4721 		return(-2);
4722 	    if (ytype == xtype)
4723 		return(xmlSchemaCompareDecimals(x, y));
4724 	    if ((ytype == XML_SCHEMAS_DECIMAL) ||
4725 		(ytype == XML_SCHEMAS_INTEGER) ||
4726 		(ytype == XML_SCHEMAS_NPINTEGER) ||
4727 		(ytype == XML_SCHEMAS_NINTEGER) ||
4728 		(ytype == XML_SCHEMAS_NNINTEGER) ||
4729 		(ytype == XML_SCHEMAS_PINTEGER) ||
4730 		(ytype == XML_SCHEMAS_INT) ||
4731 		(ytype == XML_SCHEMAS_UINT) ||
4732 		(ytype == XML_SCHEMAS_LONG) ||
4733 		(ytype == XML_SCHEMAS_ULONG) ||
4734 		(ytype == XML_SCHEMAS_SHORT) ||
4735 		(ytype == XML_SCHEMAS_USHORT) ||
4736 		(ytype == XML_SCHEMAS_BYTE) ||
4737 		(ytype == XML_SCHEMAS_UBYTE))
4738 		return(xmlSchemaCompareDecimals(x, y));
4739 	    return(-2);
4740         case XML_SCHEMAS_DURATION:
4741 	    if ((x == NULL) || (y == NULL))
4742 		return(-2);
4743 	    if (ytype == XML_SCHEMAS_DURATION)
4744                 return(xmlSchemaCompareDurations(x, y));
4745             return(-2);
4746         case XML_SCHEMAS_TIME:
4747         case XML_SCHEMAS_GDAY:
4748         case XML_SCHEMAS_GMONTH:
4749         case XML_SCHEMAS_GMONTHDAY:
4750         case XML_SCHEMAS_GYEAR:
4751         case XML_SCHEMAS_GYEARMONTH:
4752         case XML_SCHEMAS_DATE:
4753         case XML_SCHEMAS_DATETIME:
4754 	    if ((x == NULL) || (y == NULL))
4755 		return(-2);
4756             if ((ytype == XML_SCHEMAS_DATETIME)  ||
4757                 (ytype == XML_SCHEMAS_TIME)      ||
4758                 (ytype == XML_SCHEMAS_GDAY)      ||
4759                 (ytype == XML_SCHEMAS_GMONTH)    ||
4760                 (ytype == XML_SCHEMAS_GMONTHDAY) ||
4761                 (ytype == XML_SCHEMAS_GYEAR)     ||
4762                 (ytype == XML_SCHEMAS_DATE)      ||
4763                 (ytype == XML_SCHEMAS_GYEARMONTH))
4764                 return (xmlSchemaCompareDates(x, y));
4765             return (-2);
4766 	/*
4767 	* Note that we will support comparison of string types against
4768 	* anySimpleType as well.
4769 	*/
4770 	case XML_SCHEMAS_ANYSIMPLETYPE:
4771 	case XML_SCHEMAS_STRING:
4772         case XML_SCHEMAS_NORMSTRING:
4773         case XML_SCHEMAS_TOKEN:
4774         case XML_SCHEMAS_LANGUAGE:
4775         case XML_SCHEMAS_NMTOKEN:
4776         case XML_SCHEMAS_NAME:
4777         case XML_SCHEMAS_NCNAME:
4778         case XML_SCHEMAS_ID:
4779         case XML_SCHEMAS_IDREF:
4780         case XML_SCHEMAS_ENTITY:
4781         case XML_SCHEMAS_ANYURI:
4782 	{
4783 	    const xmlChar *xv, *yv;
4784 
4785 	    if (x == NULL)
4786 		xv = xvalue;
4787 	    else
4788 		xv = x->value.str;
4789 	    if (y == NULL)
4790 		yv = yvalue;
4791 	    else
4792 		yv = y->value.str;
4793 	    /*
4794 	    * TODO: Compare those against QName.
4795 	    */
4796 	    if (ytype == XML_SCHEMAS_QNAME) {
4797 		TODO
4798 		if (y == NULL)
4799 		    return(-2);
4800 		return (-2);
4801 	    }
4802             if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) ||
4803 		(ytype == XML_SCHEMAS_STRING) ||
4804 		(ytype == XML_SCHEMAS_NORMSTRING) ||
4805                 (ytype == XML_SCHEMAS_TOKEN) ||
4806                 (ytype == XML_SCHEMAS_LANGUAGE) ||
4807                 (ytype == XML_SCHEMAS_NMTOKEN) ||
4808                 (ytype == XML_SCHEMAS_NAME) ||
4809                 (ytype == XML_SCHEMAS_NCNAME) ||
4810                 (ytype == XML_SCHEMAS_ID) ||
4811                 (ytype == XML_SCHEMAS_IDREF) ||
4812                 (ytype == XML_SCHEMAS_ENTITY) ||
4813                 (ytype == XML_SCHEMAS_ANYURI)) {
4814 
4815 		if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) {
4816 
4817 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) {
4818 			/* TODO: What about x < y or x > y. */
4819 			if (xmlStrEqual(xv, yv))
4820 			    return (0);
4821 			else
4822 			    return (2);
4823 		    } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4824 			return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0));
4825 		    else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4826 			return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0));
4827 
4828 		} else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) {
4829 
4830 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
4831 			return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1));
4832 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4833 			return (xmlSchemaCompareReplacedStrings(xv, yv));
4834 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4835 			return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0));
4836 
4837 		} else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
4838 
4839 		    if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
4840 			return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1));
4841 		    if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
4842 			return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1));
4843 		    if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
4844 			return (xmlSchemaCompareNormStrings(xv, yv));
4845 		} else
4846 		    return (-2);
4847 
4848 	    }
4849             return (-2);
4850 	}
4851         case XML_SCHEMAS_QNAME:
4852 	case XML_SCHEMAS_NOTATION:
4853 	    if ((x == NULL) || (y == NULL))
4854 		return(-2);
4855             if ((ytype == XML_SCHEMAS_QNAME) ||
4856 		(ytype == XML_SCHEMAS_NOTATION)) {
4857 		if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
4858 		    (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
4859 		    return(0);
4860 		return(2);
4861 	    }
4862 	    return (-2);
4863         case XML_SCHEMAS_FLOAT:
4864         case XML_SCHEMAS_DOUBLE:
4865 	    if ((x == NULL) || (y == NULL))
4866 		return(-2);
4867             if ((ytype == XML_SCHEMAS_FLOAT) ||
4868                 (ytype == XML_SCHEMAS_DOUBLE))
4869                 return (xmlSchemaCompareFloats(x, y));
4870             return (-2);
4871         case XML_SCHEMAS_BOOLEAN:
4872 	    if ((x == NULL) || (y == NULL))
4873 		return(-2);
4874             if (ytype == XML_SCHEMAS_BOOLEAN) {
4875 		if (x->value.b == y->value.b)
4876 		    return(0);
4877 		if (x->value.b == 0)
4878 		    return(-1);
4879 		return(1);
4880 	    }
4881 	    return (-2);
4882         case XML_SCHEMAS_HEXBINARY:
4883 	    if ((x == NULL) || (y == NULL))
4884 		return(-2);
4885             if (ytype == XML_SCHEMAS_HEXBINARY) {
4886 	        if (x->value.hex.total == y->value.hex.total) {
4887 		    int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
4888 		    if (ret > 0)
4889 			return(1);
4890 		    else if (ret == 0)
4891 			return(0);
4892 		}
4893 		else if (x->value.hex.total > y->value.hex.total)
4894 		    return(1);
4895 
4896 		return(-1);
4897             }
4898             return (-2);
4899         case XML_SCHEMAS_BASE64BINARY:
4900 	    if ((x == NULL) || (y == NULL))
4901 		return(-2);
4902             if (ytype == XML_SCHEMAS_BASE64BINARY) {
4903                 if (x->value.base64.total == y->value.base64.total) {
4904                     int ret = xmlStrcmp(x->value.base64.str,
4905 		                        y->value.base64.str);
4906                     if (ret > 0)
4907                         return(1);
4908                     else if (ret == 0)
4909                         return(0);
4910 		    else
4911 		        return(-1);
4912                 }
4913                 else if (x->value.base64.total > y->value.base64.total)
4914                     return(1);
4915                 else
4916                     return(-1);
4917             }
4918             return (-2);
4919         case XML_SCHEMAS_IDREFS:
4920         case XML_SCHEMAS_ENTITIES:
4921         case XML_SCHEMAS_NMTOKENS:
4922 	    TODO
4923 	    break;
4924     }
4925     return -2;
4926 }
4927 
4928 /**
4929  * xmlSchemaCompareValues:
4930  * @x:  a first value
4931  * @y:  a second value
4932  *
4933  * Compare 2 values
4934  *
4935  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4936  * case of error
4937  */
4938 int
xmlSchemaCompareValues(xmlSchemaValPtr x,xmlSchemaValPtr y)4939 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
4940     xmlSchemaWhitespaceValueType xws, yws;
4941 
4942     if ((x == NULL) || (y == NULL))
4943         return(-2);
4944     if (x->type == XML_SCHEMAS_STRING)
4945 	xws = XML_SCHEMA_WHITESPACE_PRESERVE;
4946     else if (x->type == XML_SCHEMAS_NORMSTRING)
4947         xws = XML_SCHEMA_WHITESPACE_REPLACE;
4948     else
4949         xws = XML_SCHEMA_WHITESPACE_COLLAPSE;
4950 
4951     if (y->type == XML_SCHEMAS_STRING)
4952 	yws = XML_SCHEMA_WHITESPACE_PRESERVE;
4953     else if (y->type == XML_SCHEMAS_NORMSTRING)
4954         yws = XML_SCHEMA_WHITESPACE_REPLACE;
4955     else
4956         yws = XML_SCHEMA_WHITESPACE_COLLAPSE;
4957 
4958     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
4959 	y, NULL, yws));
4960 }
4961 
4962 /**
4963  * xmlSchemaCompareValuesWhtsp:
4964  * @x:  a first value
4965  * @xws: the whitespace value of x
4966  * @y:  a second value
4967  * @yws: the whitespace value of y
4968  *
4969  * Compare 2 values
4970  *
4971  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4972  * case of error
4973  */
4974 int
xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,xmlSchemaWhitespaceValueType xws,xmlSchemaValPtr y,xmlSchemaWhitespaceValueType yws)4975 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,
4976 			    xmlSchemaWhitespaceValueType xws,
4977 			    xmlSchemaValPtr y,
4978 			    xmlSchemaWhitespaceValueType yws)
4979 {
4980     if ((x == NULL) || (y == NULL))
4981 	return(-2);
4982     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
4983 	y, NULL, yws));
4984 }
4985 
4986 /**
4987  * xmlSchemaCompareValuesWhtspExt:
4988  * @x:  a first value
4989  * @xws: the whitespace value of x
4990  * @y:  a second value
4991  * @yws: the whitespace value of y
4992  *
4993  * Compare 2 values
4994  *
4995  * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
4996  * case of error
4997  */
4998 static int
xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,xmlSchemaValPtr x,const xmlChar * xvalue,xmlSchemaWhitespaceValueType xws,xmlSchemaValType ytype,xmlSchemaValPtr y,const xmlChar * yvalue,xmlSchemaWhitespaceValueType yws)4999 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,
5000 			       xmlSchemaValPtr x,
5001 			       const xmlChar *xvalue,
5002 			       xmlSchemaWhitespaceValueType xws,
5003 			       xmlSchemaValType ytype,
5004 			       xmlSchemaValPtr y,
5005 			       const xmlChar *yvalue,
5006 			       xmlSchemaWhitespaceValueType yws)
5007 {
5008     return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y,
5009 	yvalue, yws));
5010 }
5011 
5012 /**
5013  * xmlSchemaNormLen:
5014  * @value:  a string
5015  *
5016  * Computes the UTF8 length of the normalized value of the string
5017  *
5018  * Returns the length or -1 in case of error.
5019  */
5020 static int
xmlSchemaNormLen(const xmlChar * value)5021 xmlSchemaNormLen(const xmlChar *value) {
5022     const xmlChar *utf;
5023     int ret = 0;
5024 
5025     if (value == NULL)
5026 	return(-1);
5027     utf = value;
5028     while (IS_BLANK_CH(*utf)) utf++;
5029     while (*utf != 0) {
5030 	if (utf[0] & 0x80) {
5031 	    if ((utf[1] & 0xc0) != 0x80)
5032 		return(-1);
5033 	    if ((utf[0] & 0xe0) == 0xe0) {
5034 		if ((utf[2] & 0xc0) != 0x80)
5035 		    return(-1);
5036 		if ((utf[0] & 0xf0) == 0xf0) {
5037 		    if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
5038 			return(-1);
5039 		    utf += 4;
5040 		} else {
5041 		    utf += 3;
5042 		}
5043 	    } else {
5044 		utf += 2;
5045 	    }
5046 	} else if (IS_BLANK_CH(*utf)) {
5047 	    while (IS_BLANK_CH(*utf)) utf++;
5048 	    if (*utf == 0)
5049 		break;
5050 	} else {
5051 	    utf++;
5052 	}
5053 	ret++;
5054     }
5055     return(ret);
5056 }
5057 
5058 /**
5059  * xmlSchemaGetFacetValueAsULong:
5060  * @facet: an schemas type facet
5061  *
5062  * Extract the value of a facet
5063  *
5064  * Returns the value as a long
5065  */
5066 unsigned long
xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)5067 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
5068 {
5069     /*
5070     * TODO: Check if this is a decimal.
5071     */
5072     if (facet == NULL)
5073         return 0;
5074     return ((unsigned long) facet->val->value.decimal.lo);
5075 }
5076 
5077 /**
5078  * xmlSchemaValidateListSimpleTypeFacet:
5079  * @facet:  the facet to check
5080  * @value:  the lexical repr of the value to validate
5081  * @actualLen:  the number of list items
5082  * @expectedLen: the resulting expected number of list items
5083  *
5084  * Checks the value of a list simple type against a facet.
5085  *
5086  * Returns 0 if the value is valid, a positive error code
5087  * number otherwise and -1 in case of an internal error.
5088  */
5089 int
xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,const xmlChar * value,unsigned long actualLen,unsigned long * expectedLen)5090 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,
5091 				     const xmlChar *value,
5092 				     unsigned long actualLen,
5093 				     unsigned long *expectedLen)
5094 {
5095     if (facet == NULL)
5096         return(-1);
5097     /*
5098     * TODO: Check if this will work with large numbers.
5099     * (compare value.decimal.mi and value.decimal.hi as well?).
5100     */
5101     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5102 	if (actualLen != facet->val->value.decimal.lo) {
5103 	    if (expectedLen != NULL)
5104 		*expectedLen = facet->val->value.decimal.lo;
5105 	    return (XML_SCHEMAV_CVC_LENGTH_VALID);
5106 	}
5107     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5108 	if (actualLen < facet->val->value.decimal.lo) {
5109 	    if (expectedLen != NULL)
5110 		*expectedLen = facet->val->value.decimal.lo;
5111 	    return (XML_SCHEMAV_CVC_MINLENGTH_VALID);
5112 	}
5113     } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
5114 	if (actualLen > facet->val->value.decimal.lo) {
5115 	    if (expectedLen != NULL)
5116 		*expectedLen = facet->val->value.decimal.lo;
5117 	    return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5118 	}
5119     } else
5120 	/*
5121 	* NOTE: That we can pass NULL as xmlSchemaValPtr to
5122 	* xmlSchemaValidateFacet, since the remaining facet types
5123 	* are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
5124 	*/
5125 	return(xmlSchemaValidateFacet(NULL, facet, value, NULL));
5126     return (0);
5127 }
5128 
5129 /**
5130  * xmlSchemaValidateLengthFacet:
5131  * @type:  the built-in type
5132  * @facet:  the facet to check
5133  * @value:  the lexical repr. of the value to be validated
5134  * @val:  the precomputed value
5135  * @ws: the whitespace type of the value
5136  * @length: the actual length of the value
5137  *
5138  * Checka a value against a "length", "minLength" and "maxLength"
5139  * facet; sets @length to the computed length of @value.
5140  *
5141  * Returns 0 if the value is valid, a positive error code
5142  * otherwise and -1 in case of an internal or API error.
5143  */
5144 static int
xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length,xmlSchemaWhitespaceValueType ws)5145 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
5146 				     xmlSchemaValType valType,
5147 				     const xmlChar *value,
5148 				     xmlSchemaValPtr val,
5149 				     unsigned long *length,
5150 				     xmlSchemaWhitespaceValueType ws)
5151 {
5152     unsigned int len = 0;
5153 
5154     if ((length == NULL) || (facet == NULL))
5155         return (-1);
5156     *length = 0;
5157     if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
5158 	(facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
5159 	(facet->type != XML_SCHEMA_FACET_MINLENGTH))
5160 	return (-1);
5161 
5162     /*
5163     * TODO: length, maxLength and minLength must be of type
5164     * nonNegativeInteger only. Check if decimal is used somehow.
5165     */
5166     if ((facet->val == NULL) ||
5167 	((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5168 	 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5169 	(facet->val->value.decimal.frac != 0)) {
5170 	return(-1);
5171     }
5172     if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5173 	len = val->value.hex.total;
5174     else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5175 	len = val->value.base64.total;
5176     else {
5177 	switch (valType) {
5178 	    case XML_SCHEMAS_STRING:
5179 	    case XML_SCHEMAS_NORMSTRING:
5180 		if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5181 		    /*
5182 		    * This is to ensure API compatibility with the old
5183 		    * xmlSchemaValidateLengthFacet(). Anyway, this was and
5184 		    * is not the correct handling.
5185 		    * TODO: Get rid of this case somehow.
5186 		    */
5187 		    if (valType == XML_SCHEMAS_STRING)
5188 			len = xmlUTF8Strlen(value);
5189 		    else
5190 			len = xmlSchemaNormLen(value);
5191 		} else if (value != NULL) {
5192 		    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5193 			len = xmlSchemaNormLen(value);
5194 		    else
5195 		    /*
5196 		    * Should be OK for "preserve" as well.
5197 		    */
5198 		    len = xmlUTF8Strlen(value);
5199 		}
5200 		break;
5201 	    case XML_SCHEMAS_IDREF:
5202 	    case XML_SCHEMAS_TOKEN:
5203 	    case XML_SCHEMAS_LANGUAGE:
5204 	    case XML_SCHEMAS_NMTOKEN:
5205 	    case XML_SCHEMAS_NAME:
5206 	    case XML_SCHEMAS_NCNAME:
5207 	    case XML_SCHEMAS_ID:
5208 		/*
5209 		* FIXME: What exactly to do with anyURI?
5210 		*/
5211 	    case XML_SCHEMAS_ANYURI:
5212 		if (value != NULL)
5213 		    len = xmlSchemaNormLen(value);
5214 		break;
5215 	    case XML_SCHEMAS_QNAME:
5216 	    case XML_SCHEMAS_NOTATION:
5217 		/*
5218 		* For QName and NOTATION, those facets are
5219 		* deprecated and should be ignored.
5220 		*/
5221 		return (0);
5222 	    default:
5223 		TODO
5224 	}
5225     }
5226     *length = (unsigned long) len;
5227     /*
5228     * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
5229     */
5230     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5231 	if (len != facet->val->value.decimal.lo)
5232 	    return(XML_SCHEMAV_CVC_LENGTH_VALID);
5233     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5234 	if (len < facet->val->value.decimal.lo)
5235 	    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
5236     } else {
5237 	if (len > facet->val->value.decimal.lo)
5238 	    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5239     }
5240 
5241     return (0);
5242 }
5243 
5244 /**
5245  * xmlSchemaValidateLengthFacet:
5246  * @type:  the built-in type
5247  * @facet:  the facet to check
5248  * @value:  the lexical repr. of the value to be validated
5249  * @val:  the precomputed value
5250  * @length: the actual length of the value
5251  *
5252  * Checka a value against a "length", "minLength" and "maxLength"
5253  * facet; sets @length to the computed length of @value.
5254  *
5255  * Returns 0 if the value is valid, a positive error code
5256  * otherwise and -1 in case of an internal or API error.
5257  */
5258 int
xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,xmlSchemaFacetPtr facet,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length)5259 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,
5260 			     xmlSchemaFacetPtr facet,
5261 			     const xmlChar *value,
5262 			     xmlSchemaValPtr val,
5263 			     unsigned long *length)
5264 {
5265     if (type == NULL)
5266         return(-1);
5267     return (xmlSchemaValidateLengthFacetInternal(facet,
5268 	type->builtInType, value, val, length,
5269 	XML_SCHEMA_WHITESPACE_UNKNOWN));
5270 }
5271 
5272 /**
5273  * xmlSchemaValidateLengthFacetWhtsp:
5274  * @facet:  the facet to check
5275  * @valType:  the built-in type
5276  * @value:  the lexical repr. of the value to be validated
5277  * @val:  the precomputed value
5278  * @ws: the whitespace type of the value
5279  * @length: the actual length of the value
5280  *
5281  * Checka a value against a "length", "minLength" and "maxLength"
5282  * facet; sets @length to the computed length of @value.
5283  *
5284  * Returns 0 if the value is valid, a positive error code
5285  * otherwise and -1 in case of an internal or API error.
5286  */
5287 int
xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,unsigned long * length,xmlSchemaWhitespaceValueType ws)5288 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
5289 				  xmlSchemaValType valType,
5290 				  const xmlChar *value,
5291 				  xmlSchemaValPtr val,
5292 				  unsigned long *length,
5293 				  xmlSchemaWhitespaceValueType ws)
5294 {
5295     return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val,
5296 	length, ws));
5297 }
5298 
5299 /**
5300  * xmlSchemaValidateFacetInternal:
5301  * @facet:  the facet to check
5302  * @fws: the whitespace type of the facet's value
5303  * @valType: the built-in type of the value
5304  * @value:  the lexical repr of the value to validate
5305  * @val:  the precomputed value
5306  * @ws: the whitespace type of the value
5307  *
5308  * Check a value against a facet condition
5309  *
5310  * Returns 0 if the element is schemas valid, a positive error code
5311  *     number otherwise and -1 in case of internal or API error.
5312  */
5313 static int
xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,xmlSchemaWhitespaceValueType fws,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws)5314 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
5315 			       xmlSchemaWhitespaceValueType fws,
5316 			       xmlSchemaValType valType,
5317 			       const xmlChar *value,
5318 			       xmlSchemaValPtr val,
5319 			       xmlSchemaWhitespaceValueType ws)
5320 {
5321     int ret;
5322     int stringType;
5323 
5324     if (facet == NULL)
5325 	return(-1);
5326 
5327     switch (facet->type) {
5328 	case XML_SCHEMA_FACET_PATTERN:
5329 	    /*
5330 	    * NOTE that for patterns, the @value needs to be the normalized
5331 	    * value, *not* the lexical initial value or the canonical value.
5332 	    */
5333 	    if (value == NULL)
5334 		return(-1);
5335 	    /*
5336 	    * If string-derived type, regexp must be tested on the value space of
5337 	    * the datatype.
5338 	    * See https://www.w3.org/TR/xmlschema-2/#rf-pattern
5339 	    */
5340 	    stringType = val && ((val->type >= XML_SCHEMAS_STRING && val->type <= XML_SCHEMAS_NORMSTRING)
5341 			      || (val->type >= XML_SCHEMAS_TOKEN && val->type <= XML_SCHEMAS_NCNAME));
5342 	    ret = xmlRegexpExec(facet->regexp,
5343 	                        (stringType && val->value.str) ? val->value.str : value);
5344 	    if (ret == 1)
5345 		return(0);
5346 	    if (ret == 0)
5347 		return(XML_SCHEMAV_CVC_PATTERN_VALID);
5348 	    return(ret);
5349 	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
5350 	    ret = xmlSchemaCompareValues(val, facet->val);
5351 	    if (ret == -2)
5352 		return(-1);
5353 	    if (ret == -1)
5354 		return(0);
5355 	    return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID);
5356 	case XML_SCHEMA_FACET_MAXINCLUSIVE:
5357 	    ret = xmlSchemaCompareValues(val, facet->val);
5358 	    if (ret == -2)
5359 		return(-1);
5360 	    if ((ret == -1) || (ret == 0))
5361 		return(0);
5362 	    return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID);
5363 	case XML_SCHEMA_FACET_MINEXCLUSIVE:
5364 	    ret = xmlSchemaCompareValues(val, facet->val);
5365 	    if (ret == -2)
5366 		return(-1);
5367 	    if (ret == 1)
5368 		return(0);
5369 	    return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID);
5370 	case XML_SCHEMA_FACET_MININCLUSIVE:
5371 	    ret = xmlSchemaCompareValues(val, facet->val);
5372 	    if (ret == -2)
5373 		return(-1);
5374 	    if ((ret == 1) || (ret == 0))
5375 		return(0);
5376 	    return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID);
5377 	case XML_SCHEMA_FACET_WHITESPACE:
5378 	    /* TODO whitespaces */
5379 	    /*
5380 	    * NOTE: Whitespace should be handled to normalize
5381 	    * the value to be validated against a the facets;
5382 	    * not to normalize the value in-between.
5383 	    */
5384 	    return(0);
5385 	case  XML_SCHEMA_FACET_ENUMERATION:
5386 	    if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5387 		/*
5388 		* This is to ensure API compatibility with the old
5389 		* xmlSchemaValidateFacet().
5390 		* TODO: Get rid of this case.
5391 		*/
5392 		if ((facet->value != NULL) &&
5393 		    (xmlStrEqual(facet->value, value)))
5394 		    return(0);
5395 	    } else {
5396 		ret = xmlSchemaCompareValuesWhtspExt(facet->val->type,
5397 		    facet->val, facet->value, fws, valType, val,
5398 		    value, ws);
5399 		if (ret == -2)
5400 		    return(-1);
5401 		if (ret == 0)
5402 		    return(0);
5403 	    }
5404 	    return(XML_SCHEMAV_CVC_ENUMERATION_VALID);
5405 	case XML_SCHEMA_FACET_LENGTH:
5406 	    /*
5407 	    * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
5408 	    * then any {value} is facet-valid."
5409 	    */
5410 	    if ((valType == XML_SCHEMAS_QNAME) ||
5411 		(valType == XML_SCHEMAS_NOTATION))
5412 		return (0);
5413             /* Falls through. */
5414 	case XML_SCHEMA_FACET_MAXLENGTH:
5415 	case XML_SCHEMA_FACET_MINLENGTH: {
5416 	    unsigned int len = 0;
5417 
5418 	    if ((valType == XML_SCHEMAS_QNAME) ||
5419 		(valType == XML_SCHEMAS_NOTATION))
5420 		return (0);
5421 	    /*
5422 	    * TODO: length, maxLength and minLength must be of type
5423 	    * nonNegativeInteger only. Check if decimal is used somehow.
5424 	    */
5425 	    if ((facet->val == NULL) ||
5426 		((facet->val->type != XML_SCHEMAS_DECIMAL) &&
5427 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5428 		(facet->val->value.decimal.frac != 0)) {
5429 		return(-1);
5430 	    }
5431 	    if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
5432 		len = val->value.hex.total;
5433 	    else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
5434 		len = val->value.base64.total;
5435 	    else {
5436 		switch (valType) {
5437 		    case XML_SCHEMAS_STRING:
5438 		    case XML_SCHEMAS_NORMSTRING:
5439 			if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
5440 			    /*
5441 			    * This is to ensure API compatibility with the old
5442 			    * xmlSchemaValidateFacet(). Anyway, this was and
5443 			    * is not the correct handling.
5444 			    * TODO: Get rid of this case somehow.
5445 			    */
5446 			    if (valType == XML_SCHEMAS_STRING)
5447 				len = xmlUTF8Strlen(value);
5448 			    else
5449 				len = xmlSchemaNormLen(value);
5450 			} else if (value != NULL) {
5451 			    if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
5452 				len = xmlSchemaNormLen(value);
5453 			    else
5454 				/*
5455 				* Should be OK for "preserve" as well.
5456 				*/
5457 				len = xmlUTF8Strlen(value);
5458 			}
5459 			break;
5460 		    case XML_SCHEMAS_IDREF:
5461 		    case XML_SCHEMAS_TOKEN:
5462 		    case XML_SCHEMAS_LANGUAGE:
5463 		    case XML_SCHEMAS_NMTOKEN:
5464 		    case XML_SCHEMAS_NAME:
5465 		    case XML_SCHEMAS_NCNAME:
5466 		    case XML_SCHEMAS_ID:
5467 		    case XML_SCHEMAS_ANYURI:
5468 			if (value != NULL)
5469 			    len = xmlSchemaNormLen(value);
5470 			break;
5471 		    default:
5472 		        TODO
5473 		}
5474 	    }
5475 	    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
5476 		if (len != facet->val->value.decimal.lo)
5477 		    return(XML_SCHEMAV_CVC_LENGTH_VALID);
5478 	    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
5479 		if (len < facet->val->value.decimal.lo)
5480 		    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
5481 	    } else {
5482 		if (len > facet->val->value.decimal.lo)
5483 		    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
5484 	    }
5485 	    break;
5486 	}
5487 	case XML_SCHEMA_FACET_TOTALDIGITS:
5488 	case XML_SCHEMA_FACET_FRACTIONDIGITS:
5489 
5490 	    if ((facet->val == NULL) ||
5491 		((facet->val->type != XML_SCHEMAS_PINTEGER) &&
5492 		 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
5493 		(facet->val->value.decimal.frac != 0)) {
5494 		return(-1);
5495 	    }
5496 	    if ((val == NULL) ||
5497 		((val->type != XML_SCHEMAS_DECIMAL) &&
5498 		 (val->type != XML_SCHEMAS_INTEGER) &&
5499 		 (val->type != XML_SCHEMAS_NPINTEGER) &&
5500 		 (val->type != XML_SCHEMAS_NINTEGER) &&
5501 		 (val->type != XML_SCHEMAS_NNINTEGER) &&
5502 		 (val->type != XML_SCHEMAS_PINTEGER) &&
5503 		 (val->type != XML_SCHEMAS_INT) &&
5504 		 (val->type != XML_SCHEMAS_UINT) &&
5505 		 (val->type != XML_SCHEMAS_LONG) &&
5506 		 (val->type != XML_SCHEMAS_ULONG) &&
5507 		 (val->type != XML_SCHEMAS_SHORT) &&
5508 		 (val->type != XML_SCHEMAS_USHORT) &&
5509 		 (val->type != XML_SCHEMAS_BYTE) &&
5510 		 (val->type != XML_SCHEMAS_UBYTE))) {
5511 		return(-1);
5512 	    }
5513 	    if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
5514 	        if (val->value.decimal.total > facet->val->value.decimal.lo)
5515 	            return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID);
5516 
5517 	    } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
5518 	        if (val->value.decimal.frac > facet->val->value.decimal.lo)
5519 		    return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID);
5520 	    }
5521 	    break;
5522 	default:
5523 	    TODO
5524     }
5525     return(0);
5526 
5527 }
5528 
5529 /**
5530  * xmlSchemaValidateFacet:
5531  * @base:  the base type
5532  * @facet:  the facet to check
5533  * @value:  the lexical repr of the value to validate
5534  * @val:  the precomputed value
5535  *
5536  * Check a value against a facet condition
5537  *
5538  * Returns 0 if the element is schemas valid, a positive error code
5539  *     number otherwise and -1 in case of internal or API error.
5540  */
5541 int
xmlSchemaValidateFacet(xmlSchemaTypePtr base,xmlSchemaFacetPtr facet,const xmlChar * value,xmlSchemaValPtr val)5542 xmlSchemaValidateFacet(xmlSchemaTypePtr base,
5543 	               xmlSchemaFacetPtr facet,
5544 	               const xmlChar *value,
5545 		       xmlSchemaValPtr val)
5546 {
5547     /*
5548     * This tries to ensure API compatibility regarding the old
5549     * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
5550     * xmlSchemaValidateFacetWhtsp().
5551     */
5552     if (val != NULL)
5553 	return(xmlSchemaValidateFacetInternal(facet,
5554 	    XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val,
5555 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
5556     else if (base != NULL)
5557 	return(xmlSchemaValidateFacetInternal(facet,
5558 	    XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val,
5559 	    XML_SCHEMA_WHITESPACE_UNKNOWN));
5560     return(-1);
5561 }
5562 
5563 /**
5564  * xmlSchemaValidateFacetWhtsp:
5565  * @facet:  the facet to check
5566  * @fws: the whitespace type of the facet's value
5567  * @valType: the built-in type of the value
5568  * @value:  the lexical (or normalized for pattern) repr of the value to validate
5569  * @val:  the precomputed value
5570  * @ws: the whitespace type of the value
5571  *
5572  * Check a value against a facet condition. This takes value normalization
5573  * according to the specified whitespace types into account.
5574  * Note that @value needs to be the *normalized* value if the facet
5575  * is of type "pattern".
5576  *
5577  * Returns 0 if the element is schemas valid, a positive error code
5578  *     number otherwise and -1 in case of internal or API error.
5579  */
5580 int
xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,xmlSchemaWhitespaceValueType fws,xmlSchemaValType valType,const xmlChar * value,xmlSchemaValPtr val,xmlSchemaWhitespaceValueType ws)5581 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,
5582 			    xmlSchemaWhitespaceValueType fws,
5583 			    xmlSchemaValType valType,
5584 			    const xmlChar *value,
5585 			    xmlSchemaValPtr val,
5586 			    xmlSchemaWhitespaceValueType ws)
5587 {
5588      return(xmlSchemaValidateFacetInternal(facet, fws, valType,
5589 	 value, val, ws));
5590 }
5591 
5592 #if 0
5593 #ifndef DBL_DIG
5594 #define DBL_DIG 16
5595 #endif
5596 #ifndef DBL_EPSILON
5597 #define DBL_EPSILON 1E-9
5598 #endif
5599 
5600 #define INTEGER_DIGITS DBL_DIG
5601 #define FRACTION_DIGITS (DBL_DIG + 1)
5602 #define EXPONENT_DIGITS (3 + 2)
5603 
5604 /**
5605  * xmlXPathFormatNumber:
5606  * @number:     number to format
5607  * @buffer:     output buffer
5608  * @buffersize: size of output buffer
5609  *
5610  * Convert the number into a string representation.
5611  */
5612 static void
5613 xmlSchemaFormatFloat(double number, char buffer[], int buffersize)
5614 {
5615     switch (xmlXPathIsInf(number)) {
5616     case 1:
5617 	if (buffersize > (int)sizeof("INF"))
5618 	    snprintf(buffer, buffersize, "INF");
5619 	break;
5620     case -1:
5621 	if (buffersize > (int)sizeof("-INF"))
5622 	    snprintf(buffer, buffersize, "-INF");
5623 	break;
5624     default:
5625 	if (xmlXPathIsNaN(number)) {
5626 	    if (buffersize > (int)sizeof("NaN"))
5627 		snprintf(buffer, buffersize, "NaN");
5628 	} else if (number == 0) {
5629 	    snprintf(buffer, buffersize, "0.0E0");
5630 	} else {
5631 	    /* 3 is sign, decimal point, and terminating zero */
5632 	    char work[DBL_DIG + EXPONENT_DIGITS + 3];
5633 	    int integer_place, fraction_place;
5634 	    char *ptr;
5635 	    char *after_fraction;
5636 	    double absolute_value;
5637 	    int size;
5638 
5639 	    absolute_value = fabs(number);
5640 
5641 	    /*
5642 	     * Result is in work, and after_fraction points
5643 	     * just past the fractional part.
5644 	     * Use scientific notation
5645 	    */
5646 	    integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
5647 	    fraction_place = DBL_DIG - 1;
5648 	    snprintf(work, sizeof(work),"%*.*e",
5649 		integer_place, fraction_place, number);
5650 	    after_fraction = strchr(work + DBL_DIG, 'e');
5651 	    /* Remove fractional trailing zeroes */
5652 	    ptr = after_fraction;
5653 	    while (*(--ptr) == '0')
5654 		;
5655 	    if (*ptr != '.')
5656 	        ptr++;
5657 	    while ((*ptr++ = *after_fraction++) != 0);
5658 
5659 	    /* Finally copy result back to caller */
5660 	    size = strlen(work) + 1;
5661 	    if (size > buffersize) {
5662 		work[buffersize - 1] = 0;
5663 		size = buffersize;
5664 	    }
5665 	    memmove(buffer, work, size);
5666 	}
5667 	break;
5668     }
5669 }
5670 #endif
5671 
5672 /**
5673  * xmlSchemaGetCanonValue:
5674  * @val: the precomputed value
5675  * @retValue: the returned value
5676  *
5677  * Get the canonical lexical representation of the value.
5678  * The caller has to FREE the returned retValue.
5679  *
5680  * WARNING: Some value types are not supported yet, resulting
5681  * in a @retValue of "???".
5682  *
5683  * TODO: XML Schema 1.0 does not define canonical representations
5684  * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay,
5685  * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1.
5686  *
5687  *
5688  * Returns 0 if the value could be built, 1 if the value type is
5689  * not supported yet and -1 in case of API errors.
5690  */
5691 int
xmlSchemaGetCanonValue(xmlSchemaValPtr val,const xmlChar ** retValue)5692 xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
5693 {
5694     if ((retValue == NULL) || (val == NULL))
5695 	return (-1);
5696     *retValue = NULL;
5697     switch (val->type) {
5698 	case XML_SCHEMAS_STRING:
5699 	    if (val->value.str == NULL)
5700 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5701 	    else
5702 		*retValue =
5703 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5704 	    break;
5705 	case XML_SCHEMAS_NORMSTRING:
5706 	    if (val->value.str == NULL)
5707 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
5708 	    else {
5709 		*retValue = xmlSchemaWhiteSpaceReplace(
5710 		    (const xmlChar *) val->value.str);
5711 		if ((*retValue) == NULL)
5712 		    *retValue = BAD_CAST xmlStrdup(
5713 			(const xmlChar *) val->value.str);
5714 	    }
5715 	    break;
5716 	case XML_SCHEMAS_TOKEN:
5717 	case XML_SCHEMAS_LANGUAGE:
5718 	case XML_SCHEMAS_NMTOKEN:
5719 	case XML_SCHEMAS_NAME:
5720 	case XML_SCHEMAS_NCNAME:
5721 	case XML_SCHEMAS_ID:
5722 	case XML_SCHEMAS_IDREF:
5723 	case XML_SCHEMAS_ENTITY:
5724 	case XML_SCHEMAS_NOTATION: /* Unclear */
5725 	case XML_SCHEMAS_ANYURI:   /* Unclear */
5726 	    if (val->value.str == NULL)
5727 		return (-1);
5728 	    *retValue =
5729 		BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str);
5730 	    if (*retValue == NULL)
5731 		*retValue =
5732 		    BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
5733 	    break;
5734 	case XML_SCHEMAS_QNAME:
5735 	    /* TODO: Unclear in XML Schema 1.0. */
5736 	    if (val->value.qname.uri == NULL) {
5737 		*retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name);
5738 		return (0);
5739 	    } else {
5740 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "{");
5741 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5742 		    BAD_CAST val->value.qname.uri);
5743 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5744 		    BAD_CAST "}");
5745 		*retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
5746 		    BAD_CAST val->value.qname.uri);
5747 	    }
5748 	    break;
5749 	case XML_SCHEMAS_DECIMAL:
5750 	    /*
5751 	    * TODO: Lookout for a more simple implementation.
5752 	    */
5753 	    if ((val->value.decimal.total == 1) &&
5754 		(val->value.decimal.lo == 0)) {
5755 		*retValue = xmlStrdup(BAD_CAST "0.0");
5756 	    } else {
5757 		xmlSchemaValDecimal dec = val->value.decimal;
5758 		int bufsize;
5759 		char *buf = NULL, *offs;
5760 
5761 		/* Add room for the decimal point as well. */
5762 		bufsize = dec.total + 2;
5763 		if (dec.sign)
5764 		    bufsize++;
5765 		/* Add room for leading/trailing zero. */
5766 		if ((dec.frac == 0) || (dec.frac == dec.total))
5767 		    bufsize++;
5768 		buf = xmlMalloc(bufsize);
5769 		if (buf == NULL)
5770 		    return(-1);
5771 		offs = buf;
5772 		if (dec.sign)
5773 		    *offs++ = '-';
5774 		if (dec.frac == dec.total) {
5775 		    *offs++ = '0';
5776 		    *offs++ = '.';
5777 		}
5778 		if (dec.hi != 0)
5779 		    snprintf(offs, bufsize - (offs - buf),
5780 			"%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5781 		else if (dec.mi != 0)
5782 		    snprintf(offs, bufsize - (offs - buf),
5783 			"%lu%lu", dec.mi, dec.lo);
5784 		else
5785 		    snprintf(offs, bufsize - (offs - buf),
5786 			"%lu", dec.lo);
5787 
5788 		if (dec.frac != 0) {
5789 		    if (dec.frac != dec.total) {
5790 			int diff = dec.total - dec.frac;
5791 			/*
5792 			* Insert the decimal point.
5793 			*/
5794 			memmove(offs + diff + 1, offs + diff, dec.frac +1);
5795 			offs[diff] = '.';
5796 		    } else {
5797 			unsigned int i = 0;
5798 			/*
5799 			* Insert missing zeroes behind the decimal point.
5800 			*/
5801 			while (*(offs + i) != 0)
5802 			    i++;
5803 			if (i < dec.total) {
5804 			    memmove(offs + (dec.total - i), offs, i +1);
5805 			    memset(offs, '0', dec.total - i);
5806 			}
5807 		    }
5808 		} else {
5809 		    /*
5810 		    * Append decimal point and zero.
5811 		    */
5812 		    offs = buf + bufsize - 1;
5813 		    *offs-- = 0;
5814 		    *offs-- = '0';
5815 		    *offs-- = '.';
5816 		}
5817 		*retValue = BAD_CAST buf;
5818 	    }
5819 	    break;
5820 	case XML_SCHEMAS_INTEGER:
5821         case XML_SCHEMAS_PINTEGER:
5822         case XML_SCHEMAS_NPINTEGER:
5823         case XML_SCHEMAS_NINTEGER:
5824         case XML_SCHEMAS_NNINTEGER:
5825 	case XML_SCHEMAS_LONG:
5826         case XML_SCHEMAS_BYTE:
5827         case XML_SCHEMAS_SHORT:
5828         case XML_SCHEMAS_INT:
5829 	case XML_SCHEMAS_UINT:
5830         case XML_SCHEMAS_ULONG:
5831         case XML_SCHEMAS_USHORT:
5832         case XML_SCHEMAS_UBYTE:
5833 	    if ((val->value.decimal.total == 1) &&
5834 		(val->value.decimal.lo == 0))
5835 		*retValue = xmlStrdup(BAD_CAST "0");
5836 	    else {
5837 		xmlSchemaValDecimal dec = val->value.decimal;
5838 		int bufsize = dec.total + 1;
5839 
5840 		/* Add room for the decimal point as well. */
5841 		if (dec.sign)
5842 		    bufsize++;
5843 		*retValue = xmlMalloc(bufsize);
5844 		if (*retValue == NULL)
5845 		    return(-1);
5846 		if (dec.hi != 0) {
5847 		    if (dec.sign)
5848 			snprintf((char *) *retValue, bufsize,
5849 			    "-%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5850 		    else
5851 			snprintf((char *) *retValue, bufsize,
5852 			    "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
5853 		} else if (dec.mi != 0) {
5854 		    if (dec.sign)
5855 			snprintf((char *) *retValue, bufsize,
5856 			    "-%lu%lu", dec.mi, dec.lo);
5857 		    else
5858 			snprintf((char *) *retValue, bufsize,
5859 			    "%lu%lu", dec.mi, dec.lo);
5860 		} else {
5861 		    if (dec.sign)
5862 			snprintf((char *) *retValue, bufsize, "-%lu", dec.lo);
5863 		    else
5864 			snprintf((char *) *retValue, bufsize, "%lu", dec.lo);
5865 		}
5866 	    }
5867 	    break;
5868 	case XML_SCHEMAS_BOOLEAN:
5869 	    if (val->value.b)
5870 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "true");
5871 	    else
5872 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "false");
5873 	    break;
5874 	case XML_SCHEMAS_DURATION: {
5875 		char buf[100];
5876 		unsigned long year;
5877 		unsigned long mon, day, hour = 0, min = 0;
5878 		double sec = 0, left;
5879 
5880 		/* TODO: Unclear in XML Schema 1.0 */
5881 		/*
5882 		* TODO: This results in a normalized output of the value
5883 		* - which is NOT conformant to the spec -
5884 		* since the exact values of each property are not
5885 		* recoverable. Think about extending the structure to
5886 		* provide a field for every property.
5887 		*/
5888 		year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12);
5889 		mon = labs(val->value.dur.mon) - 12 * year;
5890 
5891 		day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400);
5892 		left = fabs(val->value.dur.sec) - day * 86400;
5893 		if (left > 0) {
5894 		    hour = (unsigned long) FQUOTIENT(left, 3600);
5895 		    left = left - (hour * 3600);
5896 		    if (left > 0) {
5897 			min = (unsigned long) FQUOTIENT(left, 60);
5898 			sec = left - (min * 60);
5899 		    }
5900 		}
5901 		if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0))
5902 		    snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS",
5903 			year, mon, day, hour, min, sec);
5904 		else
5905 		    snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
5906 			year, mon, day, hour, min, sec);
5907 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5908 	    }
5909 	    break;
5910 	case XML_SCHEMAS_GYEAR: {
5911 		char buf[30];
5912 		/* TODO: Unclear in XML Schema 1.0 */
5913 		/* TODO: What to do with the timezone? */
5914 		snprintf(buf, 30, "%04ld", val->value.date.year);
5915 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5916 	    }
5917 	    break;
5918 	case XML_SCHEMAS_GMONTH: {
5919 		/* TODO: Unclear in XML Schema 1.0 */
5920 		/* TODO: What to do with the timezone? */
5921 		*retValue = xmlMalloc(6);
5922 		if (*retValue == NULL)
5923 		    return(-1);
5924 		snprintf((char *) *retValue, 6, "--%02u",
5925 		    val->value.date.mon);
5926 	    }
5927 	    break;
5928         case XML_SCHEMAS_GDAY: {
5929 		/* TODO: Unclear in XML Schema 1.0 */
5930 		/* TODO: What to do with the timezone? */
5931 		*retValue = xmlMalloc(6);
5932 		if (*retValue == NULL)
5933 		    return(-1);
5934 		snprintf((char *) *retValue, 6, "---%02u",
5935 		    val->value.date.day);
5936 	    }
5937 	    break;
5938         case XML_SCHEMAS_GMONTHDAY: {
5939 		/* TODO: Unclear in XML Schema 1.0 */
5940 		/* TODO: What to do with the timezone? */
5941 		*retValue = xmlMalloc(8);
5942 		if (*retValue == NULL)
5943 		    return(-1);
5944 		snprintf((char *) *retValue, 8, "--%02u-%02u",
5945 		    val->value.date.mon, val->value.date.day);
5946 	    }
5947 	    break;
5948         case XML_SCHEMAS_GYEARMONTH: {
5949 		char buf[35];
5950 		/* TODO: Unclear in XML Schema 1.0 */
5951 		/* TODO: What to do with the timezone? */
5952 		if (val->value.date.year < 0)
5953 		    snprintf(buf, 35, "-%04ld-%02u",
5954 			labs(val->value.date.year),
5955 			val->value.date.mon);
5956 		else
5957 		    snprintf(buf, 35, "%04ld-%02u",
5958 			val->value.date.year, val->value.date.mon);
5959 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5960 	    }
5961 	    break;
5962 	case XML_SCHEMAS_TIME:
5963 	    {
5964 		char buf[30];
5965 
5966 		if (val->value.date.tz_flag) {
5967 		    xmlSchemaValPtr norm;
5968 
5969 		    norm = xmlSchemaDateNormalize(val, 0);
5970 		    if (norm == NULL)
5971 			return (-1);
5972 		    /*
5973 		    * TODO: Check if "%.14g" is portable.
5974 		    */
5975 		    snprintf(buf, 30,
5976 			"%02u:%02u:%02.14gZ",
5977 			norm->value.date.hour,
5978 			norm->value.date.min,
5979 			norm->value.date.sec);
5980 		    xmlSchemaFreeValue(norm);
5981 		} else {
5982 		    snprintf(buf, 30,
5983 			"%02u:%02u:%02.14g",
5984 			val->value.date.hour,
5985 			val->value.date.min,
5986 			val->value.date.sec);
5987 		}
5988 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
5989 	    }
5990 	    break;
5991         case XML_SCHEMAS_DATE:
5992 	    {
5993 		char buf[30];
5994 
5995 		if (val->value.date.tz_flag) {
5996 		    xmlSchemaValPtr norm;
5997 
5998 		    norm = xmlSchemaDateNormalize(val, 0);
5999 		    if (norm == NULL)
6000 			return (-1);
6001 		    /*
6002 		    * TODO: Append the canonical value of the
6003 		    * recoverable timezone and not "Z".
6004 		    */
6005 		    snprintf(buf, 30,
6006 			"%04ld:%02u:%02uZ",
6007 			norm->value.date.year, norm->value.date.mon,
6008 			norm->value.date.day);
6009 		    xmlSchemaFreeValue(norm);
6010 		} else {
6011 		    snprintf(buf, 30,
6012 			"%04ld:%02u:%02u",
6013 			val->value.date.year, val->value.date.mon,
6014 			val->value.date.day);
6015 		}
6016 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6017 	    }
6018 	    break;
6019         case XML_SCHEMAS_DATETIME:
6020 	    {
6021 		char buf[50];
6022 
6023 		if (val->value.date.tz_flag) {
6024 		    xmlSchemaValPtr norm;
6025 
6026 		    norm = xmlSchemaDateNormalize(val, 0);
6027 		    if (norm == NULL)
6028 			return (-1);
6029 		    /*
6030 		    * TODO: Check if "%.14g" is portable.
6031 		    */
6032 		    snprintf(buf, 50,
6033 			"%04ld:%02u:%02uT%02u:%02u:%02.14gZ",
6034 			norm->value.date.year, norm->value.date.mon,
6035 			norm->value.date.day, norm->value.date.hour,
6036 			norm->value.date.min, norm->value.date.sec);
6037 		    xmlSchemaFreeValue(norm);
6038 		} else {
6039 		    snprintf(buf, 50,
6040 			"%04ld:%02u:%02uT%02u:%02u:%02.14g",
6041 			val->value.date.year, val->value.date.mon,
6042 			val->value.date.day, val->value.date.hour,
6043 			val->value.date.min, val->value.date.sec);
6044 		}
6045 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6046 	    }
6047 	    break;
6048 	case XML_SCHEMAS_HEXBINARY:
6049 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str);
6050 	    break;
6051 	case XML_SCHEMAS_BASE64BINARY:
6052 	    /*
6053 	    * TODO: Is the following spec piece implemented?:
6054 	    * SPEC: "Note: For some values the canonical form defined
6055 	    * above does not conform to [RFC 2045], which requires breaking
6056 	    * with linefeeds at appropriate intervals."
6057 	    */
6058 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str);
6059 	    break;
6060 	case XML_SCHEMAS_FLOAT: {
6061 		char buf[30];
6062 		/*
6063 		* |m| < 16777216, -149 <= e <= 104.
6064 		* TODO: Handle, NaN, INF, -INF. The format is not
6065 		* yet conformant. The c type float does not cover
6066 		* the whole range.
6067 		*/
6068 		snprintf(buf, 30, "%01.14e", val->value.f);
6069 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6070 	    }
6071 	    break;
6072 	case XML_SCHEMAS_DOUBLE: {
6073 		char buf[40];
6074 		/* |m| < 9007199254740992, -1075 <= e <= 970 */
6075 		/*
6076 		* TODO: Handle, NaN, INF, -INF. The format is not
6077 		* yet conformant. The c type float does not cover
6078 		* the whole range.
6079 		*/
6080 		snprintf(buf, 40, "%01.14e", val->value.d);
6081 		*retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
6082 	    }
6083 	    break;
6084 	default:
6085 	    *retValue = BAD_CAST xmlStrdup(BAD_CAST "???");
6086 	    return (1);
6087     }
6088     if (*retValue == NULL)
6089 	return(-1);
6090     return (0);
6091 }
6092 
6093 /**
6094  * xmlSchemaGetCanonValueWhtsp:
6095  * @val: the precomputed value
6096  * @retValue: the returned value
6097  * @ws: the whitespace type of the value
6098  *
6099  * Get the canonical representation of the value.
6100  * The caller has to free the returned @retValue.
6101  *
6102  * Returns 0 if the value could be built, 1 if the value type is
6103  * not supported yet and -1 in case of API errors.
6104  */
6105 int
xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,const xmlChar ** retValue,xmlSchemaWhitespaceValueType ws)6106 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,
6107 			    const xmlChar **retValue,
6108 			    xmlSchemaWhitespaceValueType ws)
6109 {
6110     if ((retValue == NULL) || (val == NULL))
6111 	return (-1);
6112     if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) ||
6113 	(ws > XML_SCHEMA_WHITESPACE_COLLAPSE))
6114 	return (-1);
6115 
6116     *retValue = NULL;
6117     switch (val->type) {
6118 	case XML_SCHEMAS_STRING:
6119 	    if (val->value.str == NULL)
6120 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6121 	    else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6122 		*retValue = xmlSchemaCollapseString(val->value.str);
6123 	    else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
6124 		*retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6125 	    if ((*retValue) == NULL)
6126 		*retValue = BAD_CAST xmlStrdup(val->value.str);
6127 	    break;
6128 	case XML_SCHEMAS_NORMSTRING:
6129 	    if (val->value.str == NULL)
6130 		*retValue = BAD_CAST xmlStrdup(BAD_CAST "");
6131 	    else {
6132 		if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
6133 		    *retValue = xmlSchemaCollapseString(val->value.str);
6134 		else
6135 		    *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
6136 		if ((*retValue) == NULL)
6137 		    *retValue = BAD_CAST xmlStrdup(val->value.str);
6138 	    }
6139 	    break;
6140 	default:
6141 	    return (xmlSchemaGetCanonValue(val, retValue));
6142     }
6143     return (0);
6144 }
6145 
6146 /**
6147  * xmlSchemaGetValType:
6148  * @val: a schemas value
6149  *
6150  * Accessor for the type of a value
6151  *
6152  * Returns the xmlSchemaValType of the value
6153  */
6154 xmlSchemaValType
xmlSchemaGetValType(xmlSchemaValPtr val)6155 xmlSchemaGetValType(xmlSchemaValPtr val)
6156 {
6157     if (val == NULL)
6158         return(XML_SCHEMAS_UNKNOWN);
6159     return (val->type);
6160 }
6161 
6162 #define bottom_xmlschemastypes
6163 #include "elfgcchack.h"
6164 #endif /* LIBXML_SCHEMAS_ENABLED */
6165