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