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