source: trunk/third/libxml2/xmlschemastypes.c @ 21532

Revision 21532, 124.2 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21531, which included commits to RCS files with non-trunk default branches.
Line 
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
32#define DEBUG
33
34#ifndef LIBXML_XPATH_ENABLED
35extern double xmlXPathNAN;
36extern double xmlXPathPINF;
37extern double xmlXPathNINF;
38#endif
39
40#define TODO                                                            \
41    xmlGenericError(xmlGenericErrorContext,                             \
42            "Unimplemented block at %s:%d\n",                           \
43            __FILE__, __LINE__);
44
45#define XML_SCHEMAS_NAMESPACE_NAME \
46    (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
47
48
49static unsigned long powten[10] = {
50    1, 10, 100, 1000, 10000, 100000, 1000000, 10000000L,
51    100000000L, 1000000000L
52};
53
54
55/* Date value */
56typedef struct _xmlSchemaValDate xmlSchemaValDate;
57typedef xmlSchemaValDate *xmlSchemaValDatePtr;
58struct _xmlSchemaValDate {
59    long                year;
60    unsigned int        mon     :4;     /* 1 <=  mon    <= 12   */
61    unsigned int        day     :5;     /* 1 <=  day    <= 31   */
62    unsigned int        hour    :5;     /* 0 <=  hour   <= 23   */
63    unsigned int        min     :6;     /* 0 <=  min    <= 59   */
64    double              sec;
65    unsigned int        tz_flag :1;     /* is tzo explicitely set? */
66    int                 tzo     :11;    /* -1440 <= tzo <= 1440 */
67};
68
69/* Duration value */
70typedef struct _xmlSchemaValDuration xmlSchemaValDuration;
71typedef xmlSchemaValDuration *xmlSchemaValDurationPtr;
72struct _xmlSchemaValDuration {
73    long                mon;            /* mon stores years also */
74    long                day;
75    double              sec;            /* sec stores min and hour also */
76};
77
78typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
79typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
80struct _xmlSchemaValDecimal {
81    /* would use long long but not portable */
82    unsigned long lo;
83    unsigned long mi;
84    unsigned long hi;
85    unsigned int extra;
86    unsigned int sign:1;
87    unsigned int frac:7;
88    unsigned int total:8;
89};
90
91typedef struct _xmlSchemaValQName xmlSchemaValQName;
92typedef xmlSchemaValQName *xmlSchemaValQNamePtr;
93struct _xmlSchemaValQName {
94    xmlChar *name;
95    xmlChar *uri;
96};
97
98typedef struct _xmlSchemaValHex xmlSchemaValHex;
99typedef xmlSchemaValHex *xmlSchemaValHexPtr;
100struct _xmlSchemaValHex {
101    xmlChar     *str;
102    unsigned int total;
103};
104
105typedef struct _xmlSchemaValBase64 xmlSchemaValBase64;
106typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr;
107struct _xmlSchemaValBase64 {
108    xmlChar     *str;
109    unsigned int total;
110};
111
112struct _xmlSchemaVal {
113    xmlSchemaValType type;
114    union {
115        xmlSchemaValDecimal     decimal;
116        xmlSchemaValDate        date;
117        xmlSchemaValDuration    dur;
118        xmlSchemaValQName       qname;
119        xmlSchemaValHex         hex;
120        xmlSchemaValBase64      base64;
121        float                   f;
122        double                  d;
123        int                     b;
124        xmlChar                *str;
125    } value;
126};
127
128static int xmlSchemaTypesInitialized = 0;
129static xmlHashTablePtr xmlSchemaTypesBank = NULL;
130
131/*
132 * Basic types
133 */
134static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL;
135static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL;
136static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL;
137static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL;
138static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL;
139static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL;
140static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL;
141static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL;
142static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL;
143static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL;
144static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL;
145static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL;
146static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL;
147static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
148static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
149static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
150static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
151static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL;
152static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
153
154/*
155 * Derived types
156 */
157static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL;
158static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL;
159static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL;
160static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL;
161static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL;
162static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL;
163static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL;
164static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL;
165static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL;
166static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL;
167static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL;
168static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL;
169static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL;
170static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL;
171static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL;
172static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL;
173static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
174static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
175static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL;
176static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL;
177static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL;
178static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL;
179static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL;
180static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL;
181static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL;
182static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL;
183static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
184
185/************************************************************************
186 *                                                                      *
187 *                      Datatype error handlers                         *
188 *                                                                      *
189 ************************************************************************/
190/**
191 * xmlSchemaTypeErrMemory:
192 * @extra:  extra informations
193 *
194 * Handle an out of memory condition
195 */
196static void
197xmlSchemaTypeErrMemory(xmlNodePtr node, const char *extra)
198{
199    __xmlSimpleError(XML_FROM_DATATYPE, XML_ERR_NO_MEMORY, node, NULL, extra);
200}
201
202/************************************************************************
203 *                                                                      *
204 *                      Base types support                              *
205 *                                                                      *
206 ************************************************************************/
207/*
208 * xmlSchemaInitBasicType:
209 * @name:  the type name
210 * @type:  the value type associated
211 *
212 * Initialize one primitive built-in type
213 */
214static xmlSchemaTypePtr
215xmlSchemaInitBasicType(const char *name, xmlSchemaValType type,
216                       xmlSchemaTypePtr baseType) {
217    xmlSchemaTypePtr ret;
218
219    ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
220    if (ret == NULL) {
221        xmlSchemaTypeErrMemory(NULL, "could not initialize basic types");
222        return(NULL);
223    }
224    memset(ret, 0, sizeof(xmlSchemaType));
225    ret->name = (const xmlChar *)name;
226    ret->type = XML_SCHEMA_TYPE_BASIC;
227    ret->baseType = baseType;
228    /*
229    * Hack to reflect the variety.
230    */
231    if ((type == XML_SCHEMAS_IDREFS) ||
232        (type == XML_SCHEMAS_NMTOKENS) ||
233        (type == XML_SCHEMAS_ENTITIES))
234        ret->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
235    else if ((type != XML_SCHEMAS_ANYTYPE) &&
236        (type != XML_SCHEMAS_ANYSIMPLETYPE))
237        ret->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
238    ret->contentType = XML_SCHEMA_CONTENT_BASIC;
239    switch (type) {
240        case XML_SCHEMAS_STRING:           
241        case XML_SCHEMAS_DECIMAL:   
242        case XML_SCHEMAS_DATE:   
243        case XML_SCHEMAS_DATETIME:   
244        case XML_SCHEMAS_TIME:   
245        case XML_SCHEMAS_GYEAR:   
246        case XML_SCHEMAS_GYEARMONTH:   
247        case XML_SCHEMAS_GMONTH:   
248        case XML_SCHEMAS_GMONTHDAY:   
249        case XML_SCHEMAS_GDAY:   
250        case XML_SCHEMAS_DURATION:   
251        case XML_SCHEMAS_FLOAT:   
252        case XML_SCHEMAS_DOUBLE:   
253        case XML_SCHEMAS_BOOLEAN:   
254        case XML_SCHEMAS_ANYURI:   
255        case XML_SCHEMAS_HEXBINARY:   
256        case XML_SCHEMAS_BASE64BINARY: 
257        case XML_SCHEMAS_QNAME:
258        case XML_SCHEMAS_NOTATION:     
259            ret->flags |= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE;
260        default:
261        break;
262    }
263
264    xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
265                     XML_SCHEMAS_NAMESPACE_NAME, ret);
266    ret->builtInType = type;
267    return(ret);
268}
269
270/*
271 * xmlSchemaInitTypes:
272 *
273 * Initialize the default XML Schemas type library
274 */
275void
276xmlSchemaInitTypes(void)
277{
278    if (xmlSchemaTypesInitialized != 0)
279        return;
280    xmlSchemaTypesBank = xmlHashCreate(40);
281
282   
283    /*
284    * 3.4.7 Built-in Complex Type Definition
285    */
286    xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
287                                                     XML_SCHEMAS_ANYTYPE,
288                                                     NULL);
289    xmlSchemaTypeAnyTypeDef->baseType = xmlSchemaTypeAnyTypeDef;
290    xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
291    {
292        xmlSchemaWildcardPtr wild;
293
294        wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
295        if (wild == NULL) {
296            xmlSchemaTypeErrMemory(NULL, "could not create an attribute wildcard on anyType");
297            return;
298        }
299        memset(wild, 0, sizeof(xmlSchemaWildcard));
300        wild->any = 1;
301        wild->processContents = XML_SCHEMAS_ANY_LAX;
302        wild->minOccurs = 1;
303        wild->maxOccurs = 1;
304        xmlSchemaTypeAnyTypeDef->attributeWildcard = wild;
305    }
306    xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType",
307                                                           XML_SCHEMAS_ANYSIMPLETYPE,
308                                                           xmlSchemaTypeAnyTypeDef);
309    /*
310    * primitive datatypes
311    */
312    xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
313                                                    XML_SCHEMAS_STRING,
314                                                    xmlSchemaTypeAnySimpleTypeDef);
315    xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
316                                                     XML_SCHEMAS_DECIMAL,
317                                                     xmlSchemaTypeAnySimpleTypeDef);
318    xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
319                                                  XML_SCHEMAS_DATE,
320                                                  xmlSchemaTypeAnySimpleTypeDef);
321    xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
322                                                      XML_SCHEMAS_DATETIME,
323                                                      xmlSchemaTypeAnySimpleTypeDef);
324    xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
325                                                  XML_SCHEMAS_TIME,
326                                                  xmlSchemaTypeAnySimpleTypeDef);
327    xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
328                                                   XML_SCHEMAS_GYEAR,
329                                                   xmlSchemaTypeAnySimpleTypeDef);
330    xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
331                                                        XML_SCHEMAS_GYEARMONTH,
332                                                        xmlSchemaTypeAnySimpleTypeDef);
333    xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
334                                                    XML_SCHEMAS_GMONTH,
335                                                    xmlSchemaTypeAnySimpleTypeDef);
336    xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
337                                                       XML_SCHEMAS_GMONTHDAY,
338                                                       xmlSchemaTypeAnySimpleTypeDef);
339    xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
340                                                  XML_SCHEMAS_GDAY,
341                                                  xmlSchemaTypeAnySimpleTypeDef);
342    xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
343                                                      XML_SCHEMAS_DURATION,
344                                                      xmlSchemaTypeAnySimpleTypeDef);
345    xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
346                                                   XML_SCHEMAS_FLOAT,
347                                                   xmlSchemaTypeAnySimpleTypeDef);
348    xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
349                                                    XML_SCHEMAS_DOUBLE,
350                                                    xmlSchemaTypeAnySimpleTypeDef);
351    xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
352                                                     XML_SCHEMAS_BOOLEAN,
353                                                     xmlSchemaTypeAnySimpleTypeDef);
354    xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
355                                                    XML_SCHEMAS_ANYURI,
356                                                    xmlSchemaTypeAnySimpleTypeDef);
357    xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
358                                                     XML_SCHEMAS_HEXBINARY,
359                                                     xmlSchemaTypeAnySimpleTypeDef);
360    xmlSchemaTypeBase64BinaryDef
361        = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY,
362        xmlSchemaTypeAnySimpleTypeDef);
363    xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
364                                                    XML_SCHEMAS_NOTATION,
365                                                    xmlSchemaTypeAnySimpleTypeDef);   
366    xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
367                                                   XML_SCHEMAS_QNAME,
368                                                   xmlSchemaTypeAnySimpleTypeDef);
369
370    /*
371     * derived datatypes
372     */
373    xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
374                                                     XML_SCHEMAS_INTEGER,
375                                                     xmlSchemaTypeDecimalDef);
376    xmlSchemaTypeNonPositiveIntegerDef =
377        xmlSchemaInitBasicType("nonPositiveInteger",
378                               XML_SCHEMAS_NPINTEGER,
379                               xmlSchemaTypeIntegerDef);
380    xmlSchemaTypeNegativeIntegerDef =
381        xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER,
382        xmlSchemaTypeNonPositiveIntegerDef);
383    xmlSchemaTypeLongDef =
384        xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG,
385        xmlSchemaTypeIntegerDef);
386    xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT,
387        xmlSchemaTypeLongDef);
388    xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
389                                                   XML_SCHEMAS_SHORT,
390                                                   xmlSchemaTypeIntDef);
391    xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
392                                                  XML_SCHEMAS_BYTE,
393                                                  xmlSchemaTypeShortDef);
394    xmlSchemaTypeNonNegativeIntegerDef =
395        xmlSchemaInitBasicType("nonNegativeInteger",
396                               XML_SCHEMAS_NNINTEGER,
397                               xmlSchemaTypeIntegerDef);
398    xmlSchemaTypeUnsignedLongDef =
399        xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG,
400        xmlSchemaTypeNonNegativeIntegerDef);
401    xmlSchemaTypeUnsignedIntDef =
402        xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT,
403        xmlSchemaTypeUnsignedLongDef);
404    xmlSchemaTypeUnsignedShortDef =
405        xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT,
406        xmlSchemaTypeUnsignedIntDef);
407    xmlSchemaTypeUnsignedByteDef =
408        xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE,
409        xmlSchemaTypeUnsignedShortDef);
410    xmlSchemaTypePositiveIntegerDef =
411        xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER,
412        xmlSchemaTypeNonNegativeIntegerDef);
413    xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
414                                                        XML_SCHEMAS_NORMSTRING,
415                                                        xmlSchemaTypeStringDef);
416    xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
417                                                   XML_SCHEMAS_TOKEN,
418                                                   xmlSchemaTypeNormStringDef);
419    xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
420                                                      XML_SCHEMAS_LANGUAGE,
421                                                      xmlSchemaTypeTokenDef);
422    xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
423                                                  XML_SCHEMAS_NAME,
424                                                  xmlSchemaTypeTokenDef);
425    xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
426                                                     XML_SCHEMAS_NMTOKEN,
427                                                     xmlSchemaTypeTokenDef);               
428    xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
429                                                    XML_SCHEMAS_NCNAME,
430                                                    xmlSchemaTypeNameDef);
431    xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID,
432        xmlSchemaTypeNCNameDef);
433    xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
434                                                   XML_SCHEMAS_IDREF,
435                                                   xmlSchemaTypeNCNameDef);
436    xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
437                                                    XML_SCHEMAS_IDREFS,
438                                                    xmlSchemaTypeIdrefDef);   
439    xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
440                                                      XML_SCHEMAS_NMTOKENS,
441                                                      xmlSchemaTypeNmtokenDef);
442    xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
443                                                    XML_SCHEMAS_ENTITY,
444                                                    xmlSchemaTypeNCNameDef);
445    xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
446                                                      XML_SCHEMAS_ENTITIES,
447                                                      xmlSchemaTypeNCNameDef);
448    xmlSchemaTypesInitialized = 1;
449}
450
451/**
452 * xmlSchemaCleanupTypes:
453 *
454 * Cleanup the default XML Schemas type library
455 */
456void   
457xmlSchemaCleanupTypes(void) {
458    if (xmlSchemaTypesInitialized == 0)
459        return;
460    xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard);
461    xmlHashFree(xmlSchemaTypesBank, (xmlHashDeallocator) xmlSchemaFreeType);
462    xmlSchemaTypesInitialized = 0;
463}
464
465/**
466 * xmlSchemaIsBuiltInTypeFacet:
467 * @type: the built-in type
468 * @facetType:  the facet type
469 *
470 * Evaluates if a specific facet can be
471 * used in conjunction with a type.
472 *
473 * Returns 1 if the facet can be used with the given built-in type,
474 * 0 otherwise and -1 in case the type is not a built-in type.
475 */
476int
477xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type, int facetType)
478{
479    if (type == NULL)
480        return (-1);
481    if (type->type != XML_SCHEMA_TYPE_BASIC)
482        return (-1);
483    switch (type->builtInType) {
484        case XML_SCHEMAS_BOOLEAN:
485            if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
486                (facetType == XML_SCHEMA_FACET_WHITESPACE))
487                return (1);
488            else
489                return (0);     
490        case XML_SCHEMAS_STRING:
491        case XML_SCHEMAS_NOTATION:
492        case XML_SCHEMAS_QNAME:
493        case XML_SCHEMAS_ANYURI:           
494        case XML_SCHEMAS_BASE64BINARY:   
495        case XML_SCHEMAS_HEXBINARY:
496            if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
497                (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
498                (facetType == XML_SCHEMA_FACET_MAXLENGTH) ||
499                (facetType == XML_SCHEMA_FACET_PATTERN) ||
500                (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
501                (facetType == XML_SCHEMA_FACET_WHITESPACE))
502                return (1);
503            else
504                return (0);
505        case XML_SCHEMAS_DECIMAL:
506            if ((facetType == XML_SCHEMA_FACET_TOTALDIGITS) ||
507                (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) ||
508                (facetType == XML_SCHEMA_FACET_PATTERN) ||
509                (facetType == XML_SCHEMA_FACET_WHITESPACE) ||
510                (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
511                (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
512                (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
513                (facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
514                (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
515                return (1);
516            else
517                return (0);
518        case XML_SCHEMAS_TIME:
519        case XML_SCHEMAS_GDAY:
520        case XML_SCHEMAS_GMONTH:
521        case XML_SCHEMAS_GMONTHDAY:
522        case XML_SCHEMAS_GYEAR:
523        case XML_SCHEMAS_GYEARMONTH:
524        case XML_SCHEMAS_DATE:
525        case XML_SCHEMAS_DATETIME:
526        case XML_SCHEMAS_DURATION:
527        case XML_SCHEMAS_FLOAT:
528        case XML_SCHEMAS_DOUBLE:
529            if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
530                (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
531                (facetType == XML_SCHEMA_FACET_WHITESPACE) ||
532                (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
533                (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
534                (facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
535                (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
536                return (1);
537            else
538                return (0);                                     
539        default:
540            break;
541    }
542    return (0);
543}
544
545/**
546 * xmlSchemaGetBuiltInType:
547 * @type:  the type of the built in type
548 *
549 * Gives you the type struct for a built-in
550 * type by its type id.
551 *
552 * Returns the type if found, NULL otherwise.
553 */
554xmlSchemaTypePtr
555xmlSchemaGetBuiltInType(xmlSchemaValType type)
556{
557    if (xmlSchemaTypesInitialized == 0)
558        xmlSchemaInitTypes();
559    switch (type) {
560       
561        case XML_SCHEMAS_ANYSIMPLETYPE:
562            return (xmlSchemaTypeAnySimpleTypeDef);
563        case XML_SCHEMAS_STRING:
564            return (xmlSchemaTypeStringDef);
565        case XML_SCHEMAS_NORMSTRING:
566            return (xmlSchemaTypeNormStringDef);
567        case XML_SCHEMAS_DECIMAL:
568            return (xmlSchemaTypeDecimalDef);
569        case XML_SCHEMAS_TIME:
570            return (xmlSchemaTypeTimeDef);
571        case XML_SCHEMAS_GDAY:
572            return (xmlSchemaTypeGDayDef);
573        case XML_SCHEMAS_GMONTH:
574            return (xmlSchemaTypeGMonthDef);
575        case XML_SCHEMAS_GMONTHDAY:
576            return (xmlSchemaTypeGMonthDayDef);
577        case XML_SCHEMAS_GYEAR:
578            return (xmlSchemaTypeGYearDef);
579        case XML_SCHEMAS_GYEARMONTH:
580            return (xmlSchemaTypeGYearMonthDef);
581        case XML_SCHEMAS_DATE:
582            return (xmlSchemaTypeDateDef);
583        case XML_SCHEMAS_DATETIME:
584            return (xmlSchemaTypeDatetimeDef);
585        case XML_SCHEMAS_DURATION:
586            return (xmlSchemaTypeDurationDef);
587        case XML_SCHEMAS_FLOAT:
588            return (xmlSchemaTypeFloatDef);
589        case XML_SCHEMAS_DOUBLE:
590            return (xmlSchemaTypeDoubleDef);
591        case XML_SCHEMAS_BOOLEAN:
592            return (xmlSchemaTypeBooleanDef);
593        case XML_SCHEMAS_TOKEN:
594            return (xmlSchemaTypeTokenDef);
595        case XML_SCHEMAS_LANGUAGE:
596            return (xmlSchemaTypeLanguageDef);
597        case XML_SCHEMAS_NMTOKEN:
598            return (xmlSchemaTypeNmtokenDef);
599        case XML_SCHEMAS_NMTOKENS:
600            return (xmlSchemaTypeNmtokensDef);
601        case XML_SCHEMAS_NAME:
602            return (xmlSchemaTypeNameDef);
603        case XML_SCHEMAS_QNAME:
604            return (xmlSchemaTypeQNameDef);
605        case XML_SCHEMAS_NCNAME:
606            return (xmlSchemaTypeNCNameDef);
607        case XML_SCHEMAS_ID:
608            return (xmlSchemaTypeIdDef);
609        case XML_SCHEMAS_IDREF:
610            return (xmlSchemaTypeIdrefDef);
611        case XML_SCHEMAS_IDREFS:
612            return (xmlSchemaTypeIdrefsDef);
613        case XML_SCHEMAS_ENTITY:
614            return (xmlSchemaTypeEntityDef);
615        case XML_SCHEMAS_ENTITIES:
616            return (xmlSchemaTypeEntitiesDef);
617        case XML_SCHEMAS_NOTATION:
618            return (xmlSchemaTypeNotationDef);
619        case XML_SCHEMAS_ANYURI:
620            return (xmlSchemaTypeAnyURIDef);
621        case XML_SCHEMAS_INTEGER:
622            return (xmlSchemaTypeIntegerDef);
623        case XML_SCHEMAS_NPINTEGER:
624            return (xmlSchemaTypeNonPositiveIntegerDef);
625        case XML_SCHEMAS_NINTEGER:
626            return (xmlSchemaTypeNegativeIntegerDef);
627        case XML_SCHEMAS_NNINTEGER:
628            return (xmlSchemaTypeNonNegativeIntegerDef);
629        case XML_SCHEMAS_PINTEGER:
630            return (xmlSchemaTypePositiveIntegerDef);
631        case XML_SCHEMAS_INT:
632            return (xmlSchemaTypeIntDef);
633        case XML_SCHEMAS_UINT:
634            return (xmlSchemaTypeUnsignedIntDef);
635        case XML_SCHEMAS_LONG:
636            return (xmlSchemaTypeLongDef);
637        case XML_SCHEMAS_ULONG:
638            return (xmlSchemaTypeUnsignedLongDef);
639        case XML_SCHEMAS_SHORT:
640            return (xmlSchemaTypeShortDef);
641        case XML_SCHEMAS_USHORT:
642            return (xmlSchemaTypeUnsignedShortDef);
643        case XML_SCHEMAS_BYTE:
644            return (xmlSchemaTypeByteDef);
645        case XML_SCHEMAS_UBYTE:
646            return (xmlSchemaTypeUnsignedByteDef);
647        case XML_SCHEMAS_HEXBINARY:
648            return (xmlSchemaTypeHexBinaryDef);
649        case XML_SCHEMAS_BASE64BINARY:
650            return (xmlSchemaTypeBase64BinaryDef);
651        case XML_SCHEMAS_ANYTYPE:
652            return (xmlSchemaTypeAnyTypeDef);       
653        default:
654            return (NULL);
655    }
656}
657
658/**
659 * xmlSchemaNewValue:
660 * @type:  the value type
661 *
662 * Allocate a new simple type value
663 *
664 * Returns a pointer to the new value or NULL in case of error
665 */
666static xmlSchemaValPtr
667xmlSchemaNewValue(xmlSchemaValType type) {
668    xmlSchemaValPtr value;
669
670    value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
671    if (value == NULL) {
672        return(NULL);
673    }
674    memset(value, 0, sizeof(xmlSchemaVal));
675    value->type = type;
676    return(value);
677}
678
679/**
680 * xmlSchemaFreeValue:
681 * @value:  the value to free
682 *
683 * Cleanup the default XML Schemas type library
684 */
685void   
686xmlSchemaFreeValue(xmlSchemaValPtr value) {
687    if (value == NULL)
688        return;
689    switch (value->type) {
690        case XML_SCHEMAS_STRING:
691        case XML_SCHEMAS_NORMSTRING:
692        case XML_SCHEMAS_TOKEN:
693        case XML_SCHEMAS_LANGUAGE:
694        case XML_SCHEMAS_NMTOKEN:
695        case XML_SCHEMAS_NMTOKENS:
696        case XML_SCHEMAS_NAME:
697        case XML_SCHEMAS_NCNAME:
698        case XML_SCHEMAS_ID:
699        case XML_SCHEMAS_IDREF:
700        case XML_SCHEMAS_IDREFS:
701        case XML_SCHEMAS_ENTITY:
702        case XML_SCHEMAS_ENTITIES:
703        case XML_SCHEMAS_NOTATION:
704        case XML_SCHEMAS_ANYURI:
705            if (value->value.str != NULL)
706                xmlFree(value->value.str);
707            break;
708        case XML_SCHEMAS_QNAME:
709            if (value->value.qname.uri != NULL)
710                xmlFree(value->value.qname.uri);
711            if (value->value.qname.name != NULL)
712                xmlFree(value->value.qname.name);
713            break;
714        case XML_SCHEMAS_HEXBINARY:
715            if (value->value.hex.str != NULL)
716                xmlFree(value->value.hex.str);
717            break;
718        case XML_SCHEMAS_BASE64BINARY:
719            if (value->value.base64.str != NULL)
720                xmlFree(value->value.base64.str);
721            break;
722        default:
723            break;
724    }
725    xmlFree(value);
726}
727
728/**
729 * xmlSchemaGetPredefinedType:
730 * @name: the type name
731 * @ns:  the URI of the namespace usually "http://www.w3.org/2001/XMLSchema"
732 *
733 * Lookup a type in the default XML Schemas type library
734 *
735 * Returns the type if found, NULL otherwise
736 */
737xmlSchemaTypePtr
738xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
739    if (xmlSchemaTypesInitialized == 0)
740        xmlSchemaInitTypes();
741    if (name == NULL)
742        return(NULL);
743    return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
744}
745
746/**
747 * xmlSchemaGetBuiltInListSimpleTypeItemType:
748 * @type: the built-in simple type.
749 *
750 * Lookup function
751 *
752 * Returns the item type of @type as defined by the built-in datatype
753 * hierarchy of XML Schema Part 2: Datatypes, or NULL in case of an error.
754 */
755xmlSchemaTypePtr
756xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type)
757{
758    if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_BASIC))
759        return (NULL);
760    switch (type->builtInType) {
761        case XML_SCHEMAS_NMTOKENS:
762            return (xmlSchemaTypeNmtokenDef );
763        case XML_SCHEMAS_IDREFS:
764            return (xmlSchemaTypeIdrefDef);
765        case XML_SCHEMAS_ENTITIES:
766            return (xmlSchemaTypeEntityDef);
767        default:
768            return (NULL);
769    }
770}
771
772/****************************************************************
773 *                                                              *
774 *              Convenience macros and functions                *
775 *                                                              *
776 ****************************************************************/
777
778#define IS_TZO_CHAR(c)                                          \
779        ((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
780
781#define VALID_YEAR(yr)          (yr != 0)
782#define VALID_MONTH(mon)        ((mon >= 1) && (mon <= 12))
783/* VALID_DAY should only be used when month is unknown */
784#define VALID_DAY(day)          ((day >= 1) && (day <= 31))
785#define VALID_HOUR(hr)          ((hr >= 0) && (hr <= 23))
786#define VALID_MIN(min)          ((min >= 0) && (min <= 59))
787#define VALID_SEC(sec)          ((sec >= 0) && (sec < 60))
788#define VALID_TZO(tzo)          ((tzo > -1440) && (tzo < 1440))
789#define IS_LEAP(y)                                              \
790        (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
791
792static const unsigned int daysInMonth[12] =
793        { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
794static const unsigned int daysInMonthLeap[12] =
795        { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
796
797#define MAX_DAYINMONTH(yr,mon)                                  \
798        (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
799
800#define VALID_MDAY(dt)                                          \
801        (IS_LEAP(dt->year) ?                                    \
802            (dt->day <= daysInMonthLeap[dt->mon - 1]) :         \
803            (dt->day <= daysInMonth[dt->mon - 1]))
804
805#define VALID_DATE(dt)                                          \
806        (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
807
808#define VALID_TIME(dt)                                          \
809        (VALID_HOUR(dt->hour) && VALID_MIN(dt->min) &&          \
810         VALID_SEC(dt->sec) && VALID_TZO(dt->tzo))
811
812#define VALID_DATETIME(dt)                                      \
813        (VALID_DATE(dt) && VALID_TIME(dt))
814
815#define SECS_PER_MIN            (60)
816#define SECS_PER_HOUR           (60 * SECS_PER_MIN)
817#define SECS_PER_DAY            (24 * SECS_PER_HOUR)
818
819static const long dayInYearByMonth[12] =
820        { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
821static const long dayInLeapYearByMonth[12] =
822        { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
823
824#define DAY_IN_YEAR(day, month, year)                           \
825        ((IS_LEAP(year) ?                                       \
826                dayInLeapYearByMonth[month - 1] :               \
827                dayInYearByMonth[month - 1]) + day)
828
829#ifdef DEBUG
830#define DEBUG_DATE(dt)                                                  \
831    xmlGenericError(xmlGenericErrorContext,                             \
832        "type=%o %04ld-%02u-%02uT%02u:%02u:%03f",                       \
833        dt->type,dt->value.date.year,dt->value.date.mon,                \
834        dt->value.date.day,dt->value.date.hour,dt->value.date.min,      \
835        dt->value.date.sec);                                            \
836    if (dt->value.date.tz_flag)                                         \
837        if (dt->value.date.tzo != 0)                                    \
838            xmlGenericError(xmlGenericErrorContext,                     \
839                "%+05d\n",dt->value.date.tzo);                          \
840        else                                                            \
841            xmlGenericError(xmlGenericErrorContext, "Z\n");             \
842    else                                                                \
843        xmlGenericError(xmlGenericErrorContext,"\n")
844#else
845#define DEBUG_DATE(dt)
846#endif
847
848/**
849 * _xmlSchemaParseGYear:
850 * @dt:  pointer to a date structure
851 * @str: pointer to the string to analyze
852 *
853 * Parses a xs:gYear without time zone and fills in the appropriate
854 * field of the @dt structure. @str is updated to point just after the
855 * xs:gYear. It is supposed that @dt->year is big enough to contain
856 * the year.
857 *
858 * Returns 0 or the error code
859 */
860static int
861_xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
862    const xmlChar *cur = *str, *firstChar;
863    int isneg = 0, digcnt = 0;
864
865    if (((*cur < '0') || (*cur > '9')) &&
866        (*cur != '-') && (*cur != '+'))
867        return -1;
868
869    if (*cur == '-') {
870        isneg = 1;
871        cur++;
872    }
873
874    firstChar = cur;
875
876    while ((*cur >= '0') && (*cur <= '9')) {
877        dt->year = dt->year * 10 + (*cur - '0');
878        cur++;
879        digcnt++;
880    }
881
882    /* year must be at least 4 digits (CCYY); over 4
883     * digits cannot have a leading zero. */
884    if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0')))
885        return 1;
886
887    if (isneg)
888        dt->year = - dt->year;
889
890    if (!VALID_YEAR(dt->year))
891        return 2;
892
893    *str = cur;
894    return 0;
895}
896
897/**
898 * PARSE_2_DIGITS:
899 * @num:  the integer to fill in
900 * @cur:  an #xmlChar *
901 * @invalid: an integer
902 *
903 * Parses a 2-digits integer and updates @num with the value. @cur is
904 * updated to point just after the integer.
905 * In case of error, @invalid is set to %TRUE, values of @num and
906 * @cur are undefined.
907 */
908#define PARSE_2_DIGITS(num, cur, invalid)                       \
909        if ((cur[0] < '0') || (cur[0] > '9') ||                 \
910            (cur[1] < '0') || (cur[1] > '9'))                   \
911            invalid = 1;                                        \
912        else                                                    \
913            num = (cur[0] - '0') * 10 + (cur[1] - '0');         \
914        cur += 2;
915
916/**
917 * PARSE_FLOAT:
918 * @num:  the double to fill in
919 * @cur:  an #xmlChar *
920 * @invalid: an integer
921 *
922 * Parses a float and updates @num with the value. @cur is
923 * updated to point just after the float. The float must have a
924 * 2-digits integer part and may or may not have a decimal part.
925 * In case of error, @invalid is set to %TRUE, values of @num and
926 * @cur are undefined.
927 */
928#define PARSE_FLOAT(num, cur, invalid)                          \
929        PARSE_2_DIGITS(num, cur, invalid);                      \
930        if (!invalid && (*cur == '.')) {                        \
931            double mult = 1;                                    \
932            cur++;                                              \
933            if ((*cur < '0') || (*cur > '9'))                   \
934                invalid = 1;                                    \
935            while ((*cur >= '0') && (*cur <= '9')) {            \
936                mult /= 10;                                     \
937                num += (*cur - '0') * mult;                     \
938                cur++;                                          \
939            }                                                   \
940        }
941
942/**
943 * _xmlSchemaParseGMonth:
944 * @dt:  pointer to a date structure
945 * @str: pointer to the string to analyze
946 *
947 * Parses a xs:gMonth without time zone and fills in the appropriate
948 * field of the @dt structure. @str is updated to point just after the
949 * xs:gMonth.
950 *
951 * Returns 0 or the error code
952 */
953static int
954_xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) {
955    const xmlChar *cur = *str;
956    int ret = 0;
957
958    PARSE_2_DIGITS(dt->mon, cur, ret);
959    if (ret != 0)
960        return ret;
961
962    if (!VALID_MONTH(dt->mon))
963        return 2;
964
965    *str = cur;
966    return 0;
967}
968
969/**
970 * _xmlSchemaParseGDay:
971 * @dt:  pointer to a date structure
972 * @str: pointer to the string to analyze
973 *
974 * Parses a xs:gDay without time zone and fills in the appropriate
975 * field of the @dt structure. @str is updated to point just after the
976 * xs:gDay.
977 *
978 * Returns 0 or the error code
979 */
980static int
981_xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) {
982    const xmlChar *cur = *str;
983    int ret = 0;
984
985    PARSE_2_DIGITS(dt->day, cur, ret);
986    if (ret != 0)
987        return ret;
988
989    if (!VALID_DAY(dt->day))
990        return 2;
991
992    *str = cur;
993    return 0;
994}
995
996/**
997 * _xmlSchemaParseTime:
998 * @dt:  pointer to a date structure
999 * @str: pointer to the string to analyze
1000 *
1001 * Parses a xs:time without time zone and fills in the appropriate
1002 * fields of the @dt structure. @str is updated to point just after the
1003 * xs:time.
1004 * In case of error, values of @dt fields are undefined.
1005 *
1006 * Returns 0 or the error code
1007 */
1008static int
1009_xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) {
1010    const xmlChar *cur = *str;
1011    unsigned int hour = 0; /* use temp var in case str is not xs:time */
1012    int ret = 0;
1013
1014    PARSE_2_DIGITS(hour, cur, ret);
1015    if (ret != 0)
1016        return ret;
1017
1018    if (*cur != ':')
1019        return 1;
1020    cur++;
1021
1022    /* the ':' insures this string is xs:time */
1023    dt->hour = hour;
1024
1025    PARSE_2_DIGITS(dt->min, cur, ret);
1026    if (ret != 0)
1027        return ret;
1028
1029    if (*cur != ':')
1030        return 1;
1031    cur++;
1032
1033    PARSE_FLOAT(dt->sec, cur, ret);
1034    if (ret != 0)
1035        return ret;
1036
1037    if (!VALID_TIME(dt))
1038        return 2;
1039
1040    *str = cur;
1041    return 0;
1042}
1043
1044/**
1045 * _xmlSchemaParseTimeZone:
1046 * @dt:  pointer to a date structure
1047 * @str: pointer to the string to analyze
1048 *
1049 * Parses a time zone without time zone and fills in the appropriate
1050 * field of the @dt structure. @str is updated to point just after the
1051 * time zone.
1052 *
1053 * Returns 0 or the error code
1054 */
1055static int
1056_xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
1057    const xmlChar *cur = *str;
1058    int ret = 0;
1059
1060    if (str == NULL)
1061        return -1;
1062
1063    switch (*cur) {
1064    case 0:
1065        dt->tz_flag = 0;
1066        dt->tzo = 0;
1067        break;
1068
1069    case 'Z':
1070        dt->tz_flag = 1;
1071        dt->tzo = 0;
1072        cur++;
1073        break;
1074
1075    case '+':
1076    case '-': {
1077        int isneg = 0, tmp = 0;
1078        isneg = (*cur == '-');
1079
1080        cur++;
1081
1082        PARSE_2_DIGITS(tmp, cur, ret);
1083        if (ret != 0)
1084            return ret;
1085        if (!VALID_HOUR(tmp))
1086            return 2;
1087
1088        if (*cur != ':')
1089            return 1;
1090        cur++;
1091
1092        dt->tzo = tmp * 60;
1093
1094        PARSE_2_DIGITS(tmp, cur, ret);
1095        if (ret != 0)
1096            return ret;
1097        if (!VALID_MIN(tmp))
1098            return 2;
1099
1100        dt->tzo += tmp;
1101        if (isneg)
1102            dt->tzo = - dt->tzo;
1103
1104        if (!VALID_TZO(dt->tzo))
1105            return 2;
1106
1107        dt->tz_flag = 1;
1108        break;
1109      }
1110    default:
1111        return 1;
1112    }
1113
1114    *str = cur;
1115    return 0;
1116}
1117
1118/**
1119 * _xmlSchemaBase64Decode:
1120 * @ch: a character
1121 *
1122 * Converts a base64 encoded character to its base 64 value.
1123 *
1124 * Returns 0-63 (value), 64 (pad), or -1 (not recognized)
1125 */
1126static int
1127_xmlSchemaBase64Decode (const xmlChar ch) {
1128    if (('A' <= ch) && (ch <= 'Z')) return ch - 'A';
1129    if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26;
1130    if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52;
1131    if ('+' == ch) return 62;
1132    if ('/' == ch) return 63;
1133    if ('=' == ch) return 64;
1134    return -1;
1135}
1136
1137/****************************************************************
1138 *                                                              *
1139 *      XML Schema Dates/Times Datatypes Handling               *
1140 *                                                              *
1141 ****************************************************************/
1142
1143/**
1144 * PARSE_DIGITS:
1145 * @num:  the integer to fill in
1146 * @cur:  an #xmlChar *
1147 * @num_type: an integer flag
1148 *
1149 * Parses a digits integer and updates @num with the value. @cur is
1150 * updated to point just after the integer.
1151 * In case of error, @num_type is set to -1, values of @num and
1152 * @cur are undefined.
1153 */
1154#define PARSE_DIGITS(num, cur, num_type)                        \
1155        if ((*cur < '0') || (*cur > '9'))                       \
1156            num_type = -1;                                      \
1157        else                                                    \
1158            while ((*cur >= '0') && (*cur <= '9')) {            \
1159                num = num * 10 + (*cur - '0');                  \
1160                cur++;                                          \
1161            }
1162
1163/**
1164 * PARSE_NUM:
1165 * @num:  the double to fill in
1166 * @cur:  an #xmlChar *
1167 * @num_type: an integer flag
1168 *
1169 * Parses a float or integer and updates @num with the value. @cur is
1170 * updated to point just after the number. If the number is a float,
1171 * then it must have an integer part and a decimal part; @num_type will
1172 * be set to 1. If there is no decimal part, @num_type is set to zero.
1173 * In case of error, @num_type is set to -1, values of @num and
1174 * @cur are undefined.
1175 */
1176#define PARSE_NUM(num, cur, num_type)                           \
1177        num = 0;                                                \
1178        PARSE_DIGITS(num, cur, num_type);                       \
1179        if (!num_type && (*cur == '.')) {                       \
1180            double mult = 1;                                    \
1181            cur++;                                              \
1182            if ((*cur < '0') || (*cur > '9'))                   \
1183                num_type = -1;                                  \
1184            else                                                \
1185                num_type = 1;                                   \
1186            while ((*cur >= '0') && (*cur <= '9')) {            \
1187                mult /= 10;                                     \
1188                num += (*cur - '0') * mult;                     \
1189                cur++;                                          \
1190            }                                                   \
1191        }
1192
1193/**
1194 * xmlSchemaValidateDates:
1195 * @type: the expected type or XML_SCHEMAS_UNKNOWN
1196 * @dateTime:  string to analyze
1197 * @val:  the return computed value
1198 *
1199 * Check that @dateTime conforms to the lexical space of one of the date types.
1200 * if true a value is computed and returned in @val.
1201 *
1202 * Returns 0 if this validates, a positive error code number otherwise
1203 *         and -1 in case of internal or API error.
1204 */
1205static int
1206xmlSchemaValidateDates (xmlSchemaValType type,
1207                        const xmlChar *dateTime, xmlSchemaValPtr *val) {
1208    xmlSchemaValPtr dt;
1209    int ret;
1210    const xmlChar *cur = dateTime;
1211
1212#define RETURN_TYPE_IF_VALID(t)                                 \
1213    if (IS_TZO_CHAR(*cur)) {                                    \
1214        ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); \
1215        if (ret == 0) {                                         \
1216            if (*cur != 0)                                      \
1217                goto error;                                     \
1218            dt->type = t;                                       \
1219            goto done;                                          \
1220        }                                                       \
1221    }
1222
1223    if (dateTime == NULL)
1224        return -1;
1225
1226    if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
1227        return 1;
1228
1229    dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN);
1230    if (dt == NULL)
1231        return -1;
1232
1233    if ((cur[0] == '-') && (cur[1] == '-')) {
1234        /*
1235         * It's an incomplete date (xs:gMonthDay, xs:gMonth or
1236         * xs:gDay)
1237         */
1238        cur += 2;
1239
1240        /* is it an xs:gDay? */
1241        if (*cur == '-') {
1242            if (type == XML_SCHEMAS_GMONTH)
1243                goto error;
1244          ++cur;
1245            ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1246            if (ret != 0)
1247                goto error;
1248
1249            RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY);
1250
1251            goto error;
1252        }
1253
1254        /*
1255         * it should be an xs:gMonthDay or xs:gMonth
1256         */
1257        ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1258        if (ret != 0)
1259            goto error;
1260
1261        /*
1262         * a '-' char could indicate this type is xs:gMonthDay or
1263         * a negative time zone offset. Check for xs:gMonthDay first.
1264         * Also the first three char's of a negative tzo (-MM:SS) can
1265         * appear to be a valid day; so even if the day portion
1266         * of the xs:gMonthDay verifies, we must insure it was not
1267         * a tzo.
1268         */
1269        if (*cur == '-') {
1270            const xmlChar *rewnd = cur;
1271            cur++;
1272
1273            ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1274            if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) {
1275
1276                /*
1277                 * we can use the VALID_MDAY macro to validate the month
1278                 * and day because the leap year test will flag year zero
1279                 * as a leap year (even though zero is an invalid year).
1280                 */
1281                if (VALID_MDAY((&(dt->value.date)))) {
1282
1283                    RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
1284
1285                    goto error;
1286                }
1287            }
1288
1289            /*
1290             * not xs:gMonthDay so rewind and check if just xs:gMonth
1291             * with an optional time zone.
1292             */
1293            cur = rewnd;
1294        }
1295
1296        RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
1297
1298        goto error;
1299    }
1300
1301    /*
1302     * It's a right-truncated date or an xs:time.
1303     * Try to parse an xs:time then fallback on right-truncated dates.
1304     */
1305    if ((*cur >= '0') && (*cur <= '9')) {
1306        ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1307        if (ret == 0) {
1308            /* it's an xs:time */
1309            RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME);
1310        }
1311    }
1312
1313    /* fallback on date parsing */
1314    cur = dateTime;
1315
1316    ret = _xmlSchemaParseGYear(&(dt->value.date), &cur);
1317    if (ret != 0)
1318        goto error;
1319
1320    /* is it an xs:gYear? */
1321    RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR);
1322
1323    if (*cur != '-')
1324        goto error;
1325    cur++;
1326
1327    ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
1328    if (ret != 0)
1329        goto error;
1330
1331    /* is it an xs:gYearMonth? */
1332    RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH);
1333
1334    if (*cur != '-')
1335        goto error;
1336    cur++;
1337
1338    ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
1339    if ((ret != 0) || !VALID_DATE((&(dt->value.date))))
1340        goto error;
1341
1342    /* is it an xs:date? */
1343    RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE);
1344
1345    if (*cur != 'T')
1346        goto error;
1347    cur++;
1348
1349    /* it should be an xs:dateTime */
1350    ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
1351    if (ret != 0)
1352        goto error;
1353
1354    ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);
1355    if ((ret != 0) || (*cur != 0) || !VALID_DATETIME((&(dt->value.date))))
1356        goto error;
1357
1358
1359    dt->type = XML_SCHEMAS_DATETIME;
1360
1361done:
1362#if 1
1363    if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
1364        goto error;
1365#else
1366    /*
1367     * insure the parsed type is equal to or less significant (right
1368     * truncated) than the desired type.
1369     */
1370    if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) {
1371
1372        /* time only matches time */
1373        if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME))
1374            goto error;
1375
1376        if ((type == XML_SCHEMAS_DATETIME) &&
1377            ((dt->type != XML_SCHEMAS_DATE) ||
1378             (dt->type != XML_SCHEMAS_GYEARMONTH) ||
1379             (dt->type != XML_SCHEMAS_GYEAR)))
1380            goto error;
1381
1382        if ((type == XML_SCHEMAS_DATE) &&
1383            ((dt->type != XML_SCHEMAS_GYEAR) ||
1384             (dt->type != XML_SCHEMAS_GYEARMONTH)))
1385            goto error;
1386
1387        if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
1388            goto error;
1389
1390        if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
1391            goto error;
1392    }
1393#endif
1394
1395    if (val != NULL)
1396        *val = dt;
1397    else
1398        xmlSchemaFreeValue(dt);
1399
1400    return 0;
1401
1402error:
1403    if (dt != NULL)
1404        xmlSchemaFreeValue(dt);
1405    return 1;
1406}
1407
1408/**
1409 * xmlSchemaValidateDuration:
1410 * @type: the predefined type
1411 * @duration:  string to analyze
1412 * @val:  the return computed value
1413 *
1414 * Check that @duration conforms to the lexical space of the duration type.
1415 * if true a value is computed and returned in @val.
1416 *
1417 * Returns 0 if this validates, a positive error code number otherwise
1418 *         and -1 in case of internal or API error.
1419 */
1420static int
1421xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1422                           const xmlChar *duration, xmlSchemaValPtr *val) {
1423    const xmlChar  *cur = duration;
1424    xmlSchemaValPtr dur;
1425    int isneg = 0;
1426    unsigned int seq = 0;
1427    double         num;
1428    int            num_type = 0;  /* -1 = invalid, 0 = int, 1 = floating */
1429    const xmlChar  desig[]  = {'Y', 'M', 'D', 'H', 'M', 'S'};
1430    const double   multi[]  = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
1431
1432    if (duration == NULL)
1433        return -1;
1434
1435    if (*cur == '-') {
1436        isneg = 1;
1437        cur++;
1438    }
1439
1440    /* duration must start with 'P' (after sign) */
1441    if (*cur++ != 'P')
1442        return 1;
1443
1444    if (*cur == 0)
1445        return 1;
1446
1447    dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
1448    if (dur == NULL)
1449        return -1;
1450
1451    while (*cur != 0) {
1452
1453        /* input string should be empty or invalid date/time item */
1454        if (seq >= sizeof(desig))
1455            goto error;
1456
1457        /* T designator must be present for time items */
1458        if (*cur == 'T') {
1459            if (seq <= 3) {
1460                seq = 3;
1461                cur++;
1462            } else
1463                return 1;
1464        } else if (seq == 3)
1465            goto error;
1466
1467        /* parse the number portion of the item */
1468        PARSE_NUM(num, cur, num_type);
1469
1470        if ((num_type == -1) || (*cur == 0))
1471            goto error;
1472
1473        /* update duration based on item type */
1474        while (seq < sizeof(desig)) {
1475            if (*cur == desig[seq]) {
1476
1477                /* verify numeric type; only seconds can be float */
1478                if ((num_type != 0) && (seq < (sizeof(desig)-1)))
1479                    goto error;
1480
1481                switch (seq) {
1482                    case 0:
1483                        dur->value.dur.mon = (long)num * 12;
1484                        break;
1485                    case 1:
1486                        dur->value.dur.mon += (long)num;
1487                        break;
1488                    default:
1489                        /* convert to seconds using multiplier */
1490                        dur->value.dur.sec += num * multi[seq];
1491                        seq++;
1492                        break;
1493                }
1494
1495                break;          /* exit loop */
1496            }
1497            /* no date designators found? */
1498            if (++seq == 3)
1499                goto error;
1500        }
1501        cur++;
1502    }
1503
1504    if (isneg) {
1505        dur->value.dur.mon = -dur->value.dur.mon;
1506        dur->value.dur.day = -dur->value.dur.day;
1507        dur->value.dur.sec = -dur->value.dur.sec;
1508    }
1509
1510    if (val != NULL)
1511        *val = dur;
1512    else
1513        xmlSchemaFreeValue(dur);
1514
1515    return 0;
1516
1517error:
1518    if (dur != NULL)
1519        xmlSchemaFreeValue(dur);
1520    return 1;
1521}
1522
1523/**
1524 * xmlSchemaStrip:
1525 * @value: a value
1526 *
1527 * Removes the leading and ending spaces of a string
1528 *
1529 * Returns the new string or NULL if no change was required.
1530 */
1531static xmlChar *
1532xmlSchemaStrip(const xmlChar *value) {
1533    const xmlChar *start = value, *end, *f;
1534
1535    if (value == NULL) return(NULL);
1536    while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
1537    end = start;
1538    while (*end != 0) end++;
1539    f = end;
1540    end--;
1541    while ((end > start) && (IS_BLANK_CH(*end))) end--;
1542    end++;
1543    if ((start == value) && (f == end)) return(NULL);
1544    return(xmlStrndup(start, end - start));
1545}
1546
1547/**
1548 * xmlSchemaWhiteSpaceReplace:
1549 * @value: a value
1550 *
1551 * Replaces 0xd, 0x9 and 0xa with a space.
1552 *
1553 * Returns the new string or NULL if no change was required.
1554 */
1555xmlChar *
1556xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
1557    const xmlChar *cur = value;   
1558    xmlChar *ret = NULL, *mcur;
1559
1560    if (value == NULL)
1561        return(NULL);
1562   
1563    while ((*cur != 0) &&
1564        (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
1565        cur++;
1566    }
1567    if (*cur == 0)
1568        return (NULL);
1569    ret = xmlStrdup(value);
1570    /* TODO FIXME: I guess gcc will bark at this. */
1571    mcur = (xmlChar *)  (ret + (cur - value));
1572    do {
1573        if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
1574            *mcur = ' ';
1575        mcur++;
1576    } while (*mcur != 0);           
1577    return(ret);
1578}
1579
1580/**
1581 * xmlSchemaCollapseString:
1582 * @value: a value
1583 *
1584 * Removes and normalize white spaces in the string
1585 *
1586 * Returns the new string or NULL if no change was required.
1587 */
1588xmlChar *
1589xmlSchemaCollapseString(const xmlChar *value) {
1590    const xmlChar *start = value, *end, *f;
1591    xmlChar *g;
1592    int col = 0;
1593
1594    if (value == NULL) return(NULL);
1595    while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
1596    end = start;
1597    while (*end != 0) {
1598        if ((*end == ' ') && (IS_BLANK_CH(end[1]))) {
1599            col = end - start;
1600            break;
1601        } else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) {
1602            col = end - start;
1603            break;
1604        }
1605        end++;
1606    }
1607    if (col == 0) {
1608        f = end;
1609        end--;
1610        while ((end > start) && (IS_BLANK_CH(*end))) end--;
1611        end++;
1612        if ((start == value) && (f == end)) return(NULL);
1613        return(xmlStrndup(start, end - start));
1614    }
1615    start = xmlStrdup(start);
1616    if (start == NULL) return(NULL);
1617    g = (xmlChar *) (start + col);
1618    end = g;
1619    while (*end != 0) {
1620        if (IS_BLANK_CH(*end)) {
1621            end++;
1622            while (IS_BLANK_CH(*end)) end++;
1623            if (*end != 0)
1624                *g++ = ' ';
1625        } else
1626            *g++ = *end++;
1627    }
1628    *g = 0;
1629    return((xmlChar *) start);
1630}
1631
1632/**
1633 * xmlSchemaValAtomicListNode:
1634 * @type: the predefined atomic type for a token in the list
1635 * @value: the list value to check
1636 * @ret:  the return computed value
1637 * @node:  the node containing the value
1638 *
1639 * Check that a value conforms to the lexical space of the predefined
1640 * list type. if true a value is computed and returned in @ret.
1641 *
1642 * Returns the number of items if this validates, a negative error code
1643 *         number otherwise
1644 */
1645static int
1646xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
1647                           xmlSchemaValPtr *ret, xmlNodePtr node) {
1648    xmlChar *val, *cur, *endval;
1649    int nb_values = 0;
1650    int tmp = 0;
1651
1652    if (value == NULL) {
1653        return(-1);
1654    }
1655    val = xmlStrdup(value);
1656    if (val == NULL) {
1657        return(-1);
1658    }
1659    if (ret != NULL) {
1660        *ret = NULL;
1661    }
1662    cur = val;
1663    /*
1664     * Split the list
1665     */
1666    while (IS_BLANK_CH(*cur)) *cur++ = 0;
1667    while (*cur != 0) {
1668        if (IS_BLANK_CH(*cur)) {
1669            *cur = 0;
1670            cur++;
1671            while (IS_BLANK_CH(*cur)) *cur++ = 0;
1672        } else {
1673            nb_values++;
1674            cur++;
1675            while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
1676        }
1677    }
1678    if (nb_values == 0) {
1679        xmlFree(val);
1680        return(nb_values);
1681    }
1682    endval = cur;
1683    cur = val;
1684    while ((*cur == 0) && (cur != endval)) cur++;
1685    while (cur != endval) {
1686        tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node);
1687        if (tmp != 0)
1688            break;
1689        while (*cur != 0) cur++;
1690        while ((*cur == 0) && (cur != endval)) cur++;
1691    }
1692    /* TODO what return value ? c.f. bug #158628
1693    if (ret != NULL) {
1694        TODO
1695    } */
1696    xmlFree(val);
1697    if (tmp == 0)
1698        return(nb_values);
1699    return(-1);
1700}
1701
1702/**
1703 * xmlSchemaParseUInt:
1704 * @str: pointer to the string R/W
1705 * @llo: pointer to the low result
1706 * @lmi: pointer to the mid result
1707 * @lhi: pointer to the high result
1708 *
1709 * Parse an unsigned long into 3 fields.
1710 *
1711 * Returns the number of chars parsed or -1 if overflow of the capacity
1712 */
1713static int
1714xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
1715                   unsigned long *lmi, unsigned long *lhi) {
1716    unsigned long lo = 0, mi = 0, hi = 0;
1717    const xmlChar *tmp, *cur = *str;
1718    int ret = 0, i = 0;
1719
1720    while (*cur == '0') {
1721        ret++;
1722        cur++;
1723    }
1724    tmp = cur;
1725    while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
1726        i++;tmp++;ret++;
1727    }
1728    if (i > 24) {
1729        *str = tmp;
1730        return(-1);
1731    }
1732    while (i > 16) {
1733        hi = hi * 10 + (*cur++ - '0');
1734        i--;
1735    }
1736    while (i > 8) {
1737        mi = mi * 10 + (*cur++ - '0');
1738        i--;
1739    }
1740    while (i > 0) {
1741        lo = lo * 10 + (*cur++ - '0');
1742        i--;
1743    }
1744
1745    *str = cur;
1746    *llo = lo;
1747    *lmi = mi;
1748    *lhi = hi;
1749    return(ret);
1750}
1751
1752/**
1753 * xmlSchemaValAtomicType:
1754 * @type: the predefined type
1755 * @value: the value to check
1756 * @val:  the return computed value
1757 * @node:  the node containing the value
1758 * flags:  flags to control the vlidation
1759 *
1760 * Check that a value conforms to the lexical space of the atomic type.
1761 * if true a value is computed and returned in @val.
1762 * This checks the value space for list types as well (IDREFS, NMTOKENS).
1763 *
1764 * Returns 0 if this validates, a positive error code number otherwise
1765 *         and -1 in case of internal or API error.
1766 */
1767static int
1768xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
1769                       xmlSchemaValPtr * val, xmlNodePtr node, int flags)
1770{
1771    xmlSchemaValPtr v;
1772    xmlChar *norm = NULL;
1773    int ret = 0;
1774
1775    if (xmlSchemaTypesInitialized == 0)
1776        xmlSchemaInitTypes();
1777    if (type == NULL)
1778        return (-1);
1779
1780    /*
1781     * validating a non existant text node is similar to validating
1782     * an empty one.
1783     */
1784    if (value == NULL)
1785        value = BAD_CAST "";
1786
1787    if (val != NULL)
1788        *val = NULL;
1789    if ((flags == 0) && (value != NULL)) {
1790
1791        if ((type->builtInType != XML_SCHEMAS_STRING) &&
1792          (type->builtInType != XML_SCHEMAS_ANYTYPE) &&
1793          (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
1794            if (type->builtInType == XML_SCHEMAS_NORMSTRING)
1795                norm = xmlSchemaWhiteSpaceReplace(value);
1796            else
1797                norm = xmlSchemaCollapseString(value);
1798            if (norm != NULL)
1799                value = norm;
1800        }
1801    }
1802
1803    switch (type->builtInType) {
1804        case XML_SCHEMAS_UNKNOWN:           
1805            goto error;
1806        case XML_SCHEMAS_ANYTYPE:
1807        case XML_SCHEMAS_ANYSIMPLETYPE:
1808            goto return0;
1809        case XML_SCHEMAS_STRING:
1810            goto return0;
1811        case XML_SCHEMAS_NORMSTRING:{
1812                const xmlChar *cur = value;
1813
1814                while (*cur != 0) {
1815                    if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
1816                        goto return1;
1817                    } else {
1818                        cur++;
1819                    }
1820                }
1821                if (val != NULL) {
1822                    v = xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING);
1823                    if (v != NULL) {
1824                        v->value.str = xmlStrdup(value);
1825                        *val = v;
1826                    } else {
1827                        goto error;
1828                    }
1829                }
1830                goto return0;
1831            }
1832        case XML_SCHEMAS_DECIMAL:{
1833                const xmlChar *cur = value, *tmp;
1834                unsigned int frac = 0, len, neg = 0;
1835                unsigned long base = 0;
1836
1837                if (cur == NULL)
1838                    goto return1;
1839                if (*cur == '+')
1840                    cur++;
1841                else if (*cur == '-') {
1842                    neg = 1;
1843                    cur++;
1844                }
1845                tmp = cur;
1846                while ((*cur >= '0') && (*cur <= '9')) {
1847                    base = base * 10 + (*cur - '0');
1848                    cur++;
1849                }
1850                len = cur - tmp;
1851                if (*cur == '.') {
1852                    cur++;
1853                    tmp = cur;
1854                    while ((*cur >= '0') && (*cur <= '9')) {
1855                        base = base * 10 + (*cur - '0');
1856                        cur++;
1857                    }
1858                    frac = cur - tmp;
1859                }
1860                if (*cur != 0)
1861                    goto return1;
1862                if (val != NULL) {
1863                    v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
1864                    if (v != NULL) {
1865                        v->value.decimal.lo = base;
1866                        v->value.decimal.sign = neg;
1867                        v->value.decimal.frac = frac;
1868                        v->value.decimal.total = frac + len;
1869                        *val = v;
1870                    }
1871                }
1872                goto return0;
1873            }
1874        case XML_SCHEMAS_TIME:
1875        case XML_SCHEMAS_GDAY:
1876        case XML_SCHEMAS_GMONTH:
1877        case XML_SCHEMAS_GMONTHDAY:
1878        case XML_SCHEMAS_GYEAR:
1879        case XML_SCHEMAS_GYEARMONTH:
1880        case XML_SCHEMAS_DATE:
1881        case XML_SCHEMAS_DATETIME:
1882            ret = xmlSchemaValidateDates(type->builtInType, value, val);
1883            break;
1884        case XML_SCHEMAS_DURATION:
1885            ret = xmlSchemaValidateDuration(type, value, val);
1886            break;
1887        case XML_SCHEMAS_FLOAT:
1888        case XML_SCHEMAS_DOUBLE:{
1889                const xmlChar *cur = value;
1890                int neg = 0;
1891
1892                if (cur == NULL)
1893                    goto return1;
1894                if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
1895                    cur += 3;
1896                    if (*cur != 0)
1897                        goto return1;
1898                    if (val != NULL) {
1899                        if (type == xmlSchemaTypeFloatDef) {
1900                            v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
1901                            if (v != NULL) {
1902                                v->value.f = (float) xmlXPathNAN;
1903                            } else {
1904                                xmlSchemaFreeValue(v);
1905                                goto error;
1906                            }
1907                        } else {
1908                            v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
1909                            if (v != NULL) {
1910                                v->value.d = xmlXPathNAN;
1911                            } else {
1912                                xmlSchemaFreeValue(v);
1913                                goto error;
1914                            }
1915                        }
1916                        *val = v;
1917                    }
1918                    goto return0;
1919                }
1920                if (*cur == '-') {
1921                    neg = 1;
1922                    cur++;
1923                }
1924                if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
1925                    cur += 3;
1926                    if (*cur != 0)
1927                        goto return1;
1928                    if (val != NULL) {
1929                        if (type == xmlSchemaTypeFloatDef) {
1930                            v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
1931                            if (v != NULL) {
1932                                if (neg)
1933                                    v->value.f = (float) xmlXPathNINF;
1934                                else
1935                                    v->value.f = (float) xmlXPathPINF;
1936                            } else {
1937                                xmlSchemaFreeValue(v);
1938                                goto error;
1939                            }
1940                        } else {
1941                            v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
1942                            if (v != NULL) {
1943                                if (neg)
1944                                    v->value.d = xmlXPathNINF;
1945                                else
1946                                    v->value.d = xmlXPathPINF;
1947                            } else {
1948                                xmlSchemaFreeValue(v);
1949                                goto error;
1950                            }
1951                        }
1952                        *val = v;
1953                    }
1954                    goto return0;
1955                }
1956                if ((neg == 0) && (*cur == '+'))
1957                    cur++;
1958                if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
1959                    goto return1;
1960                while ((*cur >= '0') && (*cur <= '9')) {
1961                    cur++;
1962                }
1963                if (*cur == '.') {
1964                    cur++;
1965                    while ((*cur >= '0') && (*cur <= '9'))
1966                        cur++;
1967                }
1968                if ((*cur == 'e') || (*cur == 'E')) {
1969                    cur++;
1970                    if ((*cur == '-') || (*cur == '+'))
1971                        cur++;
1972                    while ((*cur >= '0') && (*cur <= '9'))
1973                        cur++;
1974                }
1975                if (*cur != 0)
1976                    goto return1;
1977                if (val != NULL) {
1978                    if (type == xmlSchemaTypeFloatDef) {
1979                        v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
1980                        if (v != NULL) {
1981                            if (sscanf((const char *) value, "%f",
1982                                 &(v->value.f)) == 1) {
1983                                *val = v;                               
1984                            } else {
1985                                xmlSchemaFreeValue(v);
1986                                goto return1;
1987                            }
1988                        } else {
1989                            goto error;
1990                        }
1991                    } else {
1992                        v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
1993                        if (v != NULL) {
1994                            if (sscanf((const char *) value, "%lf",
1995                                 &(v->value.d)) == 1) {
1996                                *val = v;
1997                            } else {
1998                                xmlSchemaFreeValue(v);
1999                                goto return1;
2000                            }
2001                        } else {
2002                            goto error;
2003                        }
2004                    }
2005                }
2006                goto return0;
2007            }
2008        case XML_SCHEMAS_BOOLEAN:{
2009                const xmlChar *cur = value;
2010
2011                if ((cur[0] == '0') && (cur[1] == 0))
2012                    ret = 0;
2013                else if ((cur[0] == '1') && (cur[1] == 0))
2014                    ret = 1;
2015                else if ((cur[0] == 't') && (cur[1] == 'r')
2016                         && (cur[2] == 'u') && (cur[3] == 'e')
2017                         && (cur[4] == 0))
2018                    ret = 1;
2019                else if ((cur[0] == 'f') && (cur[1] == 'a')
2020                         && (cur[2] == 'l') && (cur[3] == 's')
2021                         && (cur[4] == 'e') && (cur[5] == 0))
2022                    ret = 0;
2023                else
2024                    goto return1;
2025                if (val != NULL) {
2026                    v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
2027                    if (v != NULL) {
2028                        v->value.b = ret;
2029                        *val = v;
2030                    } else {
2031                        goto error;
2032                    }
2033                }
2034                goto return0;
2035            }
2036        case XML_SCHEMAS_TOKEN:{
2037                const xmlChar *cur = value;
2038
2039                if (IS_BLANK_CH(*cur))
2040                    goto return1;
2041
2042                while (*cur != 0) {
2043                    if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
2044                        goto return1;
2045                    } else if (*cur == ' ') {
2046                        cur++;
2047                        if (*cur == 0)
2048                            goto return1;
2049                        if (*cur == ' ')
2050                            goto return1;
2051                    } else {
2052                        cur++;
2053                    }
2054                }
2055                if (val != NULL) {
2056                    v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
2057                    if (v != NULL) {
2058                        v->value.str = xmlStrdup(value);
2059                        *val = v;
2060                    } else {
2061                        goto error;
2062                    }
2063                }
2064                goto return0;
2065            }
2066        case XML_SCHEMAS_LANGUAGE:
2067            if (xmlCheckLanguageID(value) == 1) {
2068                if (val != NULL) {
2069                    v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
2070                    if (v != NULL) {
2071                        v->value.str = xmlStrdup(value);
2072                        *val = v;
2073                    } else {
2074                        goto error;
2075                    }
2076                }
2077                goto return0;
2078            }
2079            goto return1;
2080        case XML_SCHEMAS_NMTOKEN:
2081            if (xmlValidateNMToken(value, 1) == 0) {
2082                if (val != NULL) {
2083                    v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
2084                    if (v != NULL) {
2085                        v->value.str = xmlStrdup(value);
2086                        *val = v;
2087                    } else {
2088                        goto error;
2089                    }
2090                }
2091                goto return0;
2092            }
2093            goto return1;
2094        case XML_SCHEMAS_NMTOKENS:
2095            ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
2096                                             value, val, node);
2097            if (ret > 0)
2098                ret = 0;
2099            else
2100                ret = 1;
2101            goto done;
2102        case XML_SCHEMAS_NAME:
2103            ret = xmlValidateName(value, 1);
2104            if ((ret == 0) && (val != NULL) && (value != NULL)) {
2105                v = xmlSchemaNewValue(XML_SCHEMAS_NAME);
2106                if (v != NULL) {
2107                     const xmlChar *start = value, *end;
2108                     while (IS_BLANK_CH(*start)) start++;
2109                     end = start;
2110                     while ((*end != 0) && (!IS_BLANK_CH(*end))) end++;
2111                     v->value.str = xmlStrndup(start, end - start);
2112                    *val = v;
2113                } else {
2114                    goto error;
2115                }
2116            }
2117            goto done;
2118        case XML_SCHEMAS_QNAME:{
2119                xmlChar *uri = NULL;
2120                xmlChar *local = NULL;
2121
2122                ret = xmlValidateQName(value, 1);
2123                if ((ret == 0) && (node != NULL)) {
2124                    xmlChar *prefix;
2125
2126                    local = xmlSplitQName2(value, &prefix);
2127                    if (prefix != NULL) {
2128                        xmlNsPtr ns;
2129
2130                        ns = xmlSearchNs(node->doc, node, prefix);
2131                        if (ns == NULL)
2132                            ret = 1;
2133                        else if (val != NULL)
2134                            uri = xmlStrdup(ns->href);
2135                    }
2136                    if ((local != NULL) && ((val == NULL) || (ret != 0)))
2137                        xmlFree(local);
2138                    if (prefix != NULL)
2139                        xmlFree(prefix);
2140                }
2141                if ((ret == 0) && (val != NULL)) {
2142                    v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
2143                    if (v != NULL) {
2144                        if (local != NULL)
2145                            v->value.qname.name = local;
2146                        else
2147                            v->value.qname.name = xmlStrdup(value);
2148                        if (uri != NULL)
2149                            v->value.qname.uri = uri;
2150
2151                        *val = v;
2152                    } else {
2153                        if (local != NULL)
2154                            xmlFree(local);
2155                        if (uri != NULL)
2156                            xmlFree(uri);
2157                        goto error;
2158                    }
2159                }
2160                goto done;
2161            }
2162        case XML_SCHEMAS_NCNAME:
2163            ret = xmlValidateNCName(value, 1);
2164            if ((ret == 0) && (val != NULL)) {
2165                v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
2166                if (v != NULL) {
2167                    v->value.str = xmlStrdup(value);
2168                    *val = v;
2169                } else {
2170                    goto error;
2171                }
2172            }
2173            goto done;
2174        case XML_SCHEMAS_ID:
2175            ret = xmlValidateNCName(value, 1);
2176            if ((ret == 0) && (val != NULL)) {
2177                v = xmlSchemaNewValue(XML_SCHEMAS_ID);
2178                if (v != NULL) {
2179                    v->value.str = xmlStrdup(value);
2180                    *val = v;
2181                } else {
2182                    goto error;
2183                }
2184            }
2185            if ((ret == 0) && (node != NULL) &&
2186                (node->type == XML_ATTRIBUTE_NODE)) {
2187                xmlAttrPtr attr = (xmlAttrPtr) node;
2188
2189                /*
2190                 * NOTE: the IDness might have already be declared in the DTD
2191                 */
2192                if (attr->atype != XML_ATTRIBUTE_ID) {
2193                    xmlIDPtr res;
2194                    xmlChar *strip;
2195
2196                    strip = xmlSchemaStrip(value);
2197                    if (strip != NULL) {
2198                        res = xmlAddID(NULL, node->doc, strip, attr);
2199                        xmlFree(strip);
2200                    } else
2201                        res = xmlAddID(NULL, node->doc, value, attr);
2202                    if (res == NULL) {
2203                        ret = 2;
2204                    } else {
2205                        attr->atype = XML_ATTRIBUTE_ID;
2206                    }
2207                }
2208            }
2209            goto done;
2210        case XML_SCHEMAS_IDREF:
2211            ret = xmlValidateNCName(value, 1);
2212            if ((ret == 0) && (val != NULL)) {
2213                TODO;
2214            }
2215            if ((ret == 0) && (node != NULL) &&
2216                (node->type == XML_ATTRIBUTE_NODE)) {
2217                xmlAttrPtr attr = (xmlAttrPtr) node;
2218                xmlChar *strip;
2219
2220                strip = xmlSchemaStrip(value);
2221                if (strip != NULL) {
2222                    xmlAddRef(NULL, node->doc, strip, attr);
2223                    xmlFree(strip);
2224                } else
2225                    xmlAddRef(NULL, node->doc, value, attr);
2226                attr->atype = XML_ATTRIBUTE_IDREF;
2227            }
2228            goto done;
2229        case XML_SCHEMAS_IDREFS:
2230            ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
2231                                             value, val, node);
2232            if (ret < 0)
2233                ret = 2;
2234            else
2235                ret = 0;
2236            if ((ret == 0) && (node != NULL) &&
2237                (node->type == XML_ATTRIBUTE_NODE)) {
2238                xmlAttrPtr attr = (xmlAttrPtr) node;
2239
2240                attr->atype = XML_ATTRIBUTE_IDREFS;
2241            }
2242            goto done;
2243        case XML_SCHEMAS_ENTITY:{
2244                xmlChar *strip;
2245
2246                ret = xmlValidateNCName(value, 1);
2247                if ((node == NULL) || (node->doc == NULL))
2248                    ret = 3;
2249                if (ret == 0) {
2250                    xmlEntityPtr ent;
2251
2252                    strip = xmlSchemaStrip(value);
2253                    if (strip != NULL) {
2254                        ent = xmlGetDocEntity(node->doc, strip);
2255                        xmlFree(strip);
2256                    } else {
2257                        ent = xmlGetDocEntity(node->doc, value);
2258                    }
2259                    if ((ent == NULL) ||
2260                        (ent->etype !=
2261                         XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
2262                        ret = 4;
2263                }
2264                if ((ret == 0) && (val != NULL)) {
2265                    TODO;
2266                }
2267                if ((ret == 0) && (node != NULL) &&
2268                    (node->type == XML_ATTRIBUTE_NODE)) {
2269                    xmlAttrPtr attr = (xmlAttrPtr) node;
2270
2271                    attr->atype = XML_ATTRIBUTE_ENTITY;
2272                }
2273                goto done;
2274            }
2275        case XML_SCHEMAS_ENTITIES:
2276            if ((node == NULL) || (node->doc == NULL))
2277                goto return3;
2278            ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
2279                                             value, val, node);
2280            if (ret <= 0)
2281                ret = 1;
2282            else
2283                ret = 0;
2284            if ((ret == 0) && (node != NULL) &&
2285                (node->type == XML_ATTRIBUTE_NODE)) {
2286                xmlAttrPtr attr = (xmlAttrPtr) node;
2287
2288                attr->atype = XML_ATTRIBUTE_ENTITIES;
2289            }
2290            goto done;
2291        case XML_SCHEMAS_NOTATION:{
2292                xmlChar *uri = NULL;
2293                xmlChar *local = NULL;
2294
2295                ret = xmlValidateQName(value, 1);
2296                if ((ret == 0) && (node != NULL)) {
2297                    xmlChar *prefix;
2298
2299                    local = xmlSplitQName2(value, &prefix);
2300                    if (prefix != NULL) {
2301                        xmlNsPtr ns;
2302
2303                        ns = xmlSearchNs(node->doc, node, prefix);
2304                        if (ns == NULL)
2305                            ret = 1;
2306                        else if (val != NULL)
2307                            uri = xmlStrdup(ns->href);
2308                    }
2309                    if ((local != NULL) && ((val == NULL) || (ret != 0)))
2310                        xmlFree(local);
2311                    if (prefix != NULL)
2312                        xmlFree(prefix);
2313                }
2314                if ((node == NULL) || (node->doc == NULL))
2315                    ret = 3;
2316                if (ret == 0) {
2317                    ret = xmlValidateNotationUse(NULL, node->doc, value);
2318                    if (ret == 1)
2319                        ret = 0;
2320                    else
2321                        ret = 1;
2322                }
2323                if ((ret == 0) && (val != NULL)) {
2324                    v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
2325                    if (v != NULL) {
2326                        if (local != NULL)
2327                            v->value.qname.name = local;
2328                        else
2329                            v->value.qname.name = xmlStrdup(value);
2330                        if (uri != NULL)
2331                            v->value.qname.uri = uri;
2332
2333                        *val = v;
2334                    } else {
2335                        if (local != NULL)
2336                            xmlFree(local);
2337                        if (uri != NULL)
2338                            xmlFree(uri);
2339                        goto error;
2340                    }
2341                }
2342                goto done;
2343            }
2344        case XML_SCHEMAS_ANYURI:{
2345                if (*value != 0) {
2346                    xmlURIPtr uri = xmlParseURI((const char *) value);
2347                    if (uri == NULL)
2348                        goto return1;
2349                    xmlFreeURI(uri);
2350                }
2351
2352                if (val != NULL) {
2353                    v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI);
2354                    if (v == NULL)
2355                        goto error;
2356                    v->value.str = xmlStrdup(value);
2357                    *val = v;
2358                }
2359                goto return0;
2360            }
2361        case XML_SCHEMAS_HEXBINARY:{
2362                const xmlChar *cur = value;
2363                xmlChar *base;
2364                int total, i = 0;
2365
2366                if (cur == NULL)
2367                    goto return1;
2368
2369                while (((*cur >= '0') && (*cur <= '9')) ||
2370                       ((*cur >= 'A') && (*cur <= 'F')) ||
2371                       ((*cur >= 'a') && (*cur <= 'f'))) {
2372                    i++;
2373                    cur++;
2374                }
2375
2376                if (*cur != 0)
2377                    goto return1;
2378                if ((i % 2) != 0)
2379                    goto return1;
2380
2381                if (val != NULL) {
2382
2383                    v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
2384                    if (v == NULL)
2385                        goto error;
2386
2387                    cur = xmlStrdup(value);
2388                    if (cur == NULL) {
2389                        xmlSchemaTypeErrMemory(node, "allocating hexbin data");
2390                        xmlFree(v);
2391                        goto return1;
2392                    }
2393
2394                    total = i / 2;      /* number of octets */
2395
2396                    base = (xmlChar *) cur;
2397                    while (i-- > 0) {
2398                        if (*base >= 'a')
2399                            *base = *base - ('a' - 'A');
2400                        base++;
2401                    }
2402
2403                    v->value.hex.str = (xmlChar *) cur;
2404                    v->value.hex.total = total;
2405                    *val = v;
2406                }
2407                goto return0;
2408            }
2409        case XML_SCHEMAS_BASE64BINARY:{
2410                /* ISSUE:
2411                 *
2412                 * Ignore all stray characters? (yes, currently)
2413                 * Worry about long lines? (no, currently)
2414                 *
2415                 * rfc2045.txt:
2416                 *
2417                 * "The encoded output stream must be represented in lines of
2418                 * no more than 76 characters each.  All line breaks or other
2419                 * characters not found in Table 1 must be ignored by decoding
2420                 * software.  In base64 data, characters other than those in
2421                 * Table 1, line breaks, and other white space probably
2422                 * indicate a transmission error, about which a warning
2423                 * message or even a message rejection might be appropriate
2424                 * under some circumstances." */
2425                const xmlChar *cur = value;
2426                xmlChar *base;
2427                int total, i = 0, pad = 0;
2428
2429                if (cur == NULL)
2430                    goto return1;
2431
2432                for (; *cur; ++cur) {
2433                    int decc;
2434
2435                    decc = _xmlSchemaBase64Decode(*cur);
2436                    if (decc < 0) ;
2437                    else if (decc < 64)
2438                        i++;
2439                    else
2440                        break;
2441                }
2442                for (; *cur; ++cur) {
2443                    int decc;
2444
2445                    decc = _xmlSchemaBase64Decode(*cur);
2446                    if (decc < 0) ;
2447                    else if (decc < 64)
2448                        goto return1;
2449                    if (decc == 64)
2450                        pad++;
2451                }
2452
2453                /* rfc2045.txt: "Special processing is performed if fewer than
2454                 * 24 bits are available at the end of the data being encoded.
2455                 * A full encoding quantum is always completed at the end of a
2456                 * body.  When fewer than 24 input bits are available in an
2457                 * input group, zero bits are added (on the right) to form an
2458                 * integral number of 6-bit groups.  Padding at the end of the
2459                 * data is performed using the "=" character.  Since all
2460                 * base64 input is an integral number of octets, only the
2461                 * following cases can arise: (1) the final quantum of
2462                 * encoding input is an integral multiple of 24 bits; here,
2463                 * the final unit of encoded output will be an integral
2464                 * multiple ofindent: Standard input:701: Warning:old style
2465                 * assignment ambiguity in "=*".  Assuming "= *" 4 characters
2466                 * with no "=" padding, (2) the final
2467                 * quantum of encoding input is exactly 8 bits; here, the
2468                 * final unit of encoded output will be two characters
2469                 * followed by two "=" padding characters, or (3) the final
2470                 * quantum of encoding input is exactly 16 bits; here, the
2471                 * final unit of encoded output will be three characters
2472                 * followed by one "=" padding character." */
2473
2474                total = 3 * (i / 4);
2475                if (pad == 0) {
2476                    if (i % 4 != 0)
2477                        goto return1;
2478                } else if (pad == 1) {
2479                    int decc;
2480
2481                    if (i % 4 != 3)
2482                        goto return1;
2483                    for (decc = _xmlSchemaBase64Decode(*cur);
2484                         (decc < 0) || (decc > 63);
2485                         decc = _xmlSchemaBase64Decode(*cur))
2486                        --cur;
2487                    /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
2488                    /* 00111100 -> 0x3c */
2489                    if (decc & ~0x3c)
2490                        goto return1;
2491                    total += 2;
2492                } else if (pad == 2) {
2493                    int decc;
2494
2495                    if (i % 4 != 2)
2496                        goto return1;
2497                    for (decc = _xmlSchemaBase64Decode(*cur);
2498                         (decc < 0) || (decc > 63);
2499                         decc = _xmlSchemaBase64Decode(*cur))
2500                        --cur;
2501                    /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
2502                    /* 00110000 -> 0x30 */
2503                    if (decc & ~0x30)
2504                        goto return1;
2505                    total += 1;
2506                } else
2507                    goto return1;
2508
2509                if (val != NULL) {
2510                    v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
2511                    if (v == NULL)
2512                        goto error;
2513                    base =
2514                        (xmlChar *) xmlMallocAtomic((i + pad + 1) *
2515                                                    sizeof(xmlChar));
2516                    if (base == NULL) {
2517                        xmlSchemaTypeErrMemory(node, "allocating base64 data");
2518                        xmlFree(v);
2519                        goto return1;
2520                    }
2521                    v->value.base64.str = base;
2522                    for (cur = value; *cur; ++cur)
2523                        if (_xmlSchemaBase64Decode(*cur) >= 0) {
2524                            *base = *cur;
2525                            ++base;
2526                        }
2527                    *base = 0;
2528                    v->value.base64.total = total;
2529                    *val = v;
2530                }
2531                goto return0;
2532            }
2533        case XML_SCHEMAS_INTEGER:
2534        case XML_SCHEMAS_PINTEGER:
2535        case XML_SCHEMAS_NPINTEGER:
2536        case XML_SCHEMAS_NINTEGER:
2537        case XML_SCHEMAS_NNINTEGER:{
2538                const xmlChar *cur = value;
2539                unsigned long lo, mi, hi;
2540                int sign = 0;
2541
2542                if (cur == NULL)
2543                    goto return1;
2544                if (*cur == '-') {
2545                    sign = 1;
2546                    cur++;
2547                } else if (*cur == '+')
2548                    cur++;
2549                ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
2550                if (ret == 0)
2551                    goto return1;
2552                if (*cur != 0)
2553                    goto return1;
2554                if (type->builtInType == XML_SCHEMAS_NPINTEGER) {
2555                    if ((sign == 0) &&
2556                        ((hi != 0) || (mi != 0) || (lo != 0)))
2557                        goto return1;
2558                } else if (type->builtInType == XML_SCHEMAS_PINTEGER) {
2559                    if (sign == 1)
2560                        goto return1;
2561                    if ((hi == 0) && (mi == 0) && (lo == 0))
2562                        goto return1;
2563                } else if (type->builtInType == XML_SCHEMAS_NINTEGER) {
2564                    if (sign == 0)
2565                        goto return1;
2566                    if ((hi == 0) && (mi == 0) && (lo == 0))
2567                        goto return1;
2568                } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) {
2569                    if ((sign == 1) &&
2570                        ((hi != 0) || (mi != 0) || (lo != 0)))
2571                        goto return1;
2572                }
2573                /*
2574                 * We can store a value only if no overflow occured
2575                 */
2576                if ((ret > 0) && (val != NULL)) {
2577                    v = xmlSchemaNewValue(type->builtInType);
2578                    if (v != NULL) {
2579                        v->value.decimal.lo = lo;
2580                        v->value.decimal.mi = lo;
2581                        v->value.decimal.hi = lo;
2582                        v->value.decimal.sign = sign;
2583                        v->value.decimal.frac = 0;
2584                        v->value.decimal.total = cur - value;
2585                        *val = v;
2586                    }
2587                }
2588                goto return0;
2589            }
2590        case XML_SCHEMAS_LONG:
2591        case XML_SCHEMAS_BYTE:
2592        case XML_SCHEMAS_SHORT:
2593        case XML_SCHEMAS_INT:{
2594                const xmlChar *cur = value;
2595                unsigned long lo, mi, hi;
2596                int total = 0;
2597                int sign = 0;
2598
2599                if (cur == NULL)
2600                    goto return1;
2601                if (*cur == '-') {
2602                    sign = 1;
2603                    cur++;
2604                } else if (*cur == '+')
2605                    cur++;
2606                ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
2607                if (ret <= 0)
2608                    goto return1;
2609                if (*cur != 0)
2610                    goto return1;
2611                if (type->builtInType == XML_SCHEMAS_LONG) {
2612                    if (hi >= 922) {
2613                        if (hi > 922)
2614                            goto return1;
2615                        if (mi >= 33720368) {
2616                            if (mi > 33720368)
2617                                goto return1;
2618                            if ((sign == 0) && (lo > 54775807))
2619                                goto return1;
2620                            if ((sign == 1) && (lo > 54775808))
2621                                goto return1;
2622                        }
2623                    }
2624                } else if (type->builtInType == XML_SCHEMAS_INT) {
2625                    if (hi != 0)
2626                        goto return1;
2627                    if (mi >= 21) {
2628                        if (mi > 21)
2629                            goto return1;
2630                        if ((sign == 0) && (lo > 47483647))
2631                            goto return1;
2632                        if ((sign == 1) && (lo > 47483648))
2633                            goto return1;
2634                    }
2635                } else if (type->builtInType == XML_SCHEMAS_SHORT) {
2636                    if ((mi != 0) || (hi != 0))
2637                        goto return1;
2638                    if ((sign == 1) && (lo > 32768))
2639                        goto return1;
2640                    if ((sign == 0) && (lo > 32767))
2641                        goto return1;
2642                } else if (type->builtInType == XML_SCHEMAS_BYTE) {
2643                    if ((mi != 0) || (hi != 0))
2644                        goto return1;
2645                    if ((sign == 1) && (lo > 128))
2646                        goto return1;
2647                    if ((sign == 0) && (lo > 127))
2648                        goto return1;
2649                }
2650                if (val != NULL) {
2651                    v = xmlSchemaNewValue(type->builtInType);
2652                    if (v != NULL) {
2653                        v->value.decimal.lo = lo;
2654                        v->value.decimal.mi = lo;
2655                        v->value.decimal.hi = lo;
2656                        v->value.decimal.sign = sign;
2657                        v->value.decimal.frac = 0;
2658                        v->value.decimal.total = total;
2659                        *val = v;
2660                    }
2661                }
2662                goto return0;
2663            }
2664        case XML_SCHEMAS_UINT:
2665        case XML_SCHEMAS_ULONG:
2666        case XML_SCHEMAS_USHORT:
2667        case XML_SCHEMAS_UBYTE:{
2668                const xmlChar *cur = value;
2669                unsigned long lo, mi, hi;
2670                int total = 0;
2671
2672                if (cur == NULL)
2673                    goto return1;
2674                ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
2675                if (ret <= 0)
2676                    goto return1;
2677                if (*cur != 0)
2678                    goto return1;
2679                if (type->builtInType == XML_SCHEMAS_ULONG) {
2680                    if (hi >= 1844) {
2681                        if (hi > 1844)
2682                            goto return1;
2683                        if (mi >= 67440737) {
2684                            if (mi > 67440737)
2685                                goto return1;
2686                            if (lo > 9551615)
2687                                goto return1;
2688                        }
2689                    }
2690                } else if (type->builtInType == XML_SCHEMAS_UINT) {
2691                    if (hi != 0)
2692                        goto return1;
2693                    if (mi >= 42) {
2694                        if (mi > 42)
2695                            goto return1;
2696                        if (lo > 94967295)
2697                            goto return1;
2698                    }
2699                } else if (type->builtInType == XML_SCHEMAS_USHORT) {
2700                    if ((mi != 0) || (hi != 0))
2701                        goto return1;
2702                    if (lo > 65535)
2703                        goto return1;
2704                } else if (type->builtInType == XML_SCHEMAS_UBYTE) {
2705                    if ((mi != 0) || (hi != 0))
2706                        goto return1;
2707                    if (lo > 255)
2708                        goto return1;
2709                }
2710                if (val != NULL) {
2711                    v = xmlSchemaNewValue(type->builtInType);
2712                    if (v != NULL) {
2713                        v->value.decimal.lo = lo;
2714                        v->value.decimal.mi = mi;
2715                        v->value.decimal.hi = hi;
2716                        v->value.decimal.sign = 0;
2717                        v->value.decimal.frac = 0;
2718                        v->value.decimal.total = total;
2719                        *val = v;
2720                    }
2721                }
2722                goto return0;
2723            }
2724    }
2725
2726  done:
2727    if (norm != NULL)
2728        xmlFree(norm);
2729    return (ret);
2730  return3:
2731    if (norm != NULL)
2732        xmlFree(norm);
2733    return (3);
2734  return1:
2735    if (norm != NULL)
2736        xmlFree(norm);
2737    return (1);
2738  return0:
2739    if (norm != NULL)
2740        xmlFree(norm);
2741    return (0);
2742  error:
2743    if (norm != NULL)
2744        xmlFree(norm);
2745    return (-1);
2746}
2747
2748/**
2749 * xmlSchemaValPredefTypeNode:
2750 * @type: the predefined type
2751 * @value: the value to check
2752 * @val:  the return computed value
2753 * @node:  the node containing the value
2754 *
2755 * Check that a value conforms to the lexical space of the predefined type.
2756 * if true a value is computed and returned in @val.
2757 *
2758 * Returns 0 if this validates, a positive error code number otherwise
2759 *         and -1 in case of internal or API error.
2760 */
2761int
2762xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
2763                           xmlSchemaValPtr *val, xmlNodePtr node) {
2764    return(xmlSchemaValAtomicType(type, value, val, node, 0));
2765}
2766
2767/**
2768 * xmlSchemaValPredefTypeNodeNoNorm:
2769 * @type: the predefined type
2770 * @value: the value to check
2771 * @val:  the return computed value
2772 * @node:  the node containing the value
2773 *
2774 * Check that a value conforms to the lexical space of the predefined type.
2775 * if true a value is computed and returned in @val.
2776 * This one does apply any normalization to the value.
2777 *
2778 * Returns 0 if this validates, a positive error code number otherwise
2779 *         and -1 in case of internal or API error.
2780 */
2781int
2782xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value,
2783                                 xmlSchemaValPtr *val, xmlNodePtr node) {
2784    return(xmlSchemaValAtomicType(type, value, val, node, 1));
2785}
2786
2787/**
2788 * xmlSchemaValidatePredefinedType:
2789 * @type: the predefined type
2790 * @value: the value to check
2791 * @val:  the return computed value
2792 *
2793 * Check that a value conforms to the lexical space of the predefined type.
2794 * if true a value is computed and returned in @val.
2795 *
2796 * Returns 0 if this validates, a positive error code number otherwise
2797 *         and -1 in case of internal or API error.
2798 */
2799int
2800xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
2801                                xmlSchemaValPtr *val) {
2802    return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
2803}
2804
2805/**
2806 * xmlSchemaCompareDecimals:
2807 * @x:  a first decimal value
2808 * @y:  a second decimal value
2809 *
2810 * Compare 2 decimals
2811 *
2812 * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error
2813 */
2814static int
2815xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
2816{
2817    xmlSchemaValPtr swp;
2818    int order = 1, p;
2819    unsigned long tmp;
2820
2821    if ((x->value.decimal.sign) &&
2822        ((x->value.decimal.lo != 0) ||
2823         (x->value.decimal.mi != 0) ||
2824         (x->value.decimal.hi != 0))) {
2825        if ((y->value.decimal.sign) &&
2826            ((y->value.decimal.lo != 0) ||
2827             (y->value.decimal.mi != 0) ||
2828             (y->value.decimal.hi != 0)))
2829            order = -1;
2830        else
2831            return (-1);
2832    } else if ((y->value.decimal.sign) &&
2833               ((y->value.decimal.lo != 0) ||
2834                (y->value.decimal.mi != 0) ||
2835                (y->value.decimal.hi != 0))) {
2836        return (1);
2837    }
2838    if (x->value.decimal.frac == y->value.decimal.frac) {
2839        if (x->value.decimal.hi < y->value.decimal.hi)
2840            return (-order);
2841        if (x->value.decimal.hi > y->value.decimal.hi)
2842            return (order);
2843        if (x->value.decimal.mi < y->value.decimal.mi)
2844            return (-order);
2845        if (x->value.decimal.mi > y->value.decimal.mi)
2846            return (order);
2847        if (x->value.decimal.lo < y->value.decimal.lo)
2848            return (-order);
2849        if (x->value.decimal.lo > y->value.decimal.lo)
2850            return(order);
2851        return(0);
2852    }
2853    if (y->value.decimal.frac > x->value.decimal.frac) {
2854        swp = y;
2855        y = x;
2856        x = swp;
2857        order = -order;
2858    }
2859    p = powten[x->value.decimal.frac - y->value.decimal.frac];
2860    tmp = x->value.decimal.lo / p;
2861    if (tmp > y->value.decimal.lo)
2862        return (order);
2863    if (tmp < y->value.decimal.lo)
2864        return (-order);
2865    tmp = y->value.decimal.lo * p;
2866    if (x->value.decimal.lo < tmp)
2867        return (-order);
2868    if (x->value.decimal.lo == tmp)
2869        return (0);
2870    return (order);
2871}
2872
2873/**
2874 * xmlSchemaCompareDurations:
2875 * @x:  a first duration value
2876 * @y:  a second duration value
2877 *
2878 * Compare 2 durations
2879 *
2880 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
2881 * case of error
2882 */
2883static int
2884xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
2885{
2886    long carry, mon, day;
2887    double sec;
2888    int invert = 1;
2889    long xmon, xday, myear, minday, maxday;
2890    static const long dayRange [2][12] = {
2891        { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
2892        { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
2893
2894    if ((x == NULL) || (y == NULL))
2895        return -2;
2896
2897    /* months */
2898    mon = x->value.dur.mon - y->value.dur.mon;
2899
2900    /* seconds */
2901    sec = x->value.dur.sec - y->value.dur.sec;
2902    carry = (long)sec / SECS_PER_DAY;
2903    sec -= (double)(carry * SECS_PER_DAY);
2904
2905    /* days */
2906    day = x->value.dur.day - y->value.dur.day + carry;
2907
2908    /* easy test */
2909    if (mon == 0) {
2910        if (day == 0)
2911            if (sec == 0.0)
2912                return 0;
2913            else if (sec < 0.0)
2914                return -1;
2915            else
2916                return 1;
2917        else if (day < 0)
2918            return -1;
2919        else
2920            return 1;
2921    }
2922
2923    if (mon > 0) {
2924        if ((day >= 0) && (sec >= 0.0))
2925            return 1;
2926        else {
2927            xmon = mon;
2928            xday = -day;
2929        }
2930    } else if ((day <= 0) && (sec <= 0.0)) {
2931        return -1;
2932    } else {
2933        invert = -1;
2934        xmon = -mon;
2935        xday = day;
2936    }
2937
2938    myear = xmon / 12;
2939    if (myear == 0) {
2940        minday = 0;
2941        maxday = 0;
2942    } else {
2943        maxday = 366 * ((myear + 3) / 4) +
2944                 365 * ((myear - 1) % 4);
2945        minday = maxday - 1;
2946    }
2947
2948    xmon = xmon % 12;
2949    minday += dayRange[0][xmon];
2950    maxday += dayRange[1][xmon];
2951
2952    if ((maxday == minday) && (maxday == xday))
2953        return(0); /* can this really happen ? */
2954    if (maxday < xday)
2955        return(-invert);
2956    if (minday > xday)
2957        return(invert);
2958
2959    /* indeterminate */
2960    return 2;
2961}
2962
2963/*
2964 * macros for adding date/times and durations
2965 */
2966#define FQUOTIENT(a,b)                  (floor(((double)a/(double)b)))
2967#define MODULO(a,b)                     (a - FQUOTIENT(a,b) * b)
2968#define FQUOTIENT_RANGE(a,low,high)     (FQUOTIENT((a-low),(high-low)))
2969#define MODULO_RANGE(a,low,high)        ((MODULO((a-low),(high-low)))+low)
2970
2971/**
2972 * xmlSchemaDupVal:
2973 * @v: the #xmlSchemaValPtr value to duplicate
2974 *
2975 * Makes a copy of @v. The calling program is responsible for freeing
2976 * the returned value.
2977 *
2978 * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error.
2979 */
2980static xmlSchemaValPtr
2981xmlSchemaDupVal (xmlSchemaValPtr v)
2982{
2983    xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
2984    if (ret == NULL)
2985        return NULL;
2986   
2987    memcpy(ret, v, sizeof(xmlSchemaVal));
2988    return ret;
2989}
2990
2991/**
2992 * _xmlSchemaDateAdd:
2993 * @dt: an #xmlSchemaValPtr
2994 * @dur: an #xmlSchemaValPtr of type #XS_DURATION
2995 *
2996 * Compute a new date/time from @dt and @dur. This function assumes @dt
2997 * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH,
2998 * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as
2999 * @dt. The calling program is responsible for freeing the returned value.
3000 *
3001 * Returns a pointer to a new #xmlSchemaVal or NULL if error.
3002 */
3003static xmlSchemaValPtr
3004_xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
3005{
3006    xmlSchemaValPtr ret, tmp;
3007    long carry, tempdays, temp;
3008    xmlSchemaValDatePtr r, d;
3009    xmlSchemaValDurationPtr u;
3010
3011    if ((dt == NULL) || (dur == NULL))
3012        return NULL;
3013
3014    ret = xmlSchemaNewValue(dt->type);
3015    if (ret == NULL)
3016        return NULL;
3017
3018    /* make a copy so we don't alter the original value */
3019    tmp = xmlSchemaDupVal(dt);
3020    if (tmp == NULL) {
3021        xmlSchemaFreeValue(ret);
3022        return NULL;
3023    }
3024
3025    r = &(ret->value.date);
3026    d = &(tmp->value.date);
3027    u = &(dur->value.dur);
3028
3029    /* normalization */
3030    if (d->mon == 0)
3031        d->mon = 1;
3032
3033    /* normalize for time zone offset */
3034    u->sec -= (d->tzo * 60);
3035    d->tzo = 0;
3036
3037    /* normalization */
3038    if (d->day == 0)
3039        d->day = 1;
3040
3041    /* month */
3042    carry  = d->mon + u->mon;
3043    r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13);
3044    carry  = (long) FQUOTIENT_RANGE(carry, 1, 13);
3045
3046    /* year (may be modified later) */
3047    r->year = d->year + carry;
3048    if (r->year == 0) {
3049        if (d->year > 0)
3050            r->year--;
3051        else
3052            r->year++;
3053    }
3054
3055    /* time zone */
3056    r->tzo     = d->tzo;
3057    r->tz_flag = d->tz_flag;
3058
3059    /* seconds */
3060    r->sec = d->sec + u->sec;
3061    carry  = (long) FQUOTIENT((long)r->sec, 60);
3062    if (r->sec != 0.0) {
3063        r->sec = MODULO(r->sec, 60.0);
3064    }
3065
3066    /* minute */
3067    carry += d->min;
3068    r->min = (unsigned int) MODULO(carry, 60);
3069    carry  = (long) FQUOTIENT(carry, 60);
3070
3071    /* hours */
3072    carry  += d->hour;
3073    r->hour = (unsigned int) MODULO(carry, 24);
3074    carry   = (long)FQUOTIENT(carry, 24);
3075
3076    /*
3077     * days
3078     * Note we use tempdays because the temporary values may need more
3079     * than 5 bits
3080     */
3081    if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
3082                  (d->day > MAX_DAYINMONTH(r->year, r->mon)))
3083        tempdays = MAX_DAYINMONTH(r->year, r->mon);
3084    else if (d->day < 1)
3085        tempdays = 1;
3086    else
3087        tempdays = d->day;
3088
3089    tempdays += u->day + carry;
3090
3091    while (1) {
3092        if (tempdays < 1) {
3093            long tmon = (long) MODULO_RANGE(r->mon-1, 1, 13);
3094            long tyr  = r->year + (long)FQUOTIENT_RANGE(r->mon-1, 1, 13);
3095            if (tyr == 0)
3096                tyr--;
3097            tempdays += MAX_DAYINMONTH(tyr, tmon);
3098            carry = -1;
3099        } else if (tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) {
3100            tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
3101            carry = 1;
3102        } else
3103            break;
3104
3105        temp = r->mon + carry;
3106        r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13);
3107        r->year = r->year + (unsigned int) FQUOTIENT_RANGE(temp, 1, 13);
3108        if (r->year == 0) {
3109            if (temp < 1)
3110                r->year--;
3111            else
3112                r->year++;
3113        }
3114    }
3115   
3116    r->day = tempdays;
3117
3118    /*
3119     * adjust the date/time type to the date values
3120     */
3121    if (ret->type != XML_SCHEMAS_DATETIME) {
3122        if ((r->hour) || (r->min) || (r->sec))
3123            ret->type = XML_SCHEMAS_DATETIME;
3124        else if (ret->type != XML_SCHEMAS_DATE) {
3125            if ((r->mon != 1) && (r->day != 1))
3126                ret->type = XML_SCHEMAS_DATE;
3127            else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
3128                ret->type = XML_SCHEMAS_GYEARMONTH;
3129        }
3130    }
3131
3132    xmlSchemaFreeValue(tmp);
3133
3134    return ret;
3135}
3136
3137/**
3138 * xmlSchemaDateNormalize:
3139 * @dt: an #xmlSchemaValPtr of a date/time type value.
3140 * @offset: number of seconds to adjust @dt by.
3141 *
3142 * Normalize @dt to GMT time. The @offset parameter is subtracted from
3143 * the return value is a time-zone offset is present on @dt.
3144 *
3145 * Returns a normalized copy of @dt or NULL if error.
3146 */
3147static xmlSchemaValPtr
3148xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
3149{
3150    xmlSchemaValPtr dur, ret;
3151
3152    if (dt == NULL)
3153        return NULL;
3154
3155    if (((dt->type != XML_SCHEMAS_TIME) &&
3156         (dt->type != XML_SCHEMAS_DATETIME)) || (dt->value.date.tzo == 0))
3157        return xmlSchemaDupVal(dt);
3158
3159    dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
3160    if (dur == NULL)
3161        return NULL;
3162
3163    dur->value.date.sec -= offset;
3164
3165    ret = _xmlSchemaDateAdd(dt, dur);
3166    if (ret == NULL)
3167        return NULL;
3168
3169    xmlSchemaFreeValue(dur);
3170
3171    /* ret->value.date.tzo = 0; */
3172    return ret;
3173}
3174
3175/**
3176 * _xmlSchemaDateCastYMToDays:
3177 * @dt: an #xmlSchemaValPtr
3178 *
3179 * Convert mon and year of @dt to total number of days. Take the
3180 * number of years since (or before) 1 AD and add the number of leap
3181 * years. This is a function  because negative
3182 * years must be handled a little differently and there is no zero year.
3183 *
3184 * Returns number of days.
3185 */
3186static long
3187_xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
3188{
3189    long ret;
3190    int mon;
3191
3192    mon = dt->value.date.mon;
3193    if (mon <= 0) mon = 1; /* normalization */
3194
3195    if (dt->value.date.year <= 0)
3196        ret = (dt->value.date.year * 365) +
3197              (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
3198               ((dt->value.date.year+1)/400)) +
3199              DAY_IN_YEAR(0, mon, dt->value.date.year);
3200    else
3201        ret = ((dt->value.date.year-1) * 365) +
3202              (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
3203               ((dt->value.date.year-1)/400)) +
3204              DAY_IN_YEAR(0, mon, dt->value.date.year);
3205
3206    return ret;
3207}
3208
3209/**
3210 * TIME_TO_NUMBER:
3211 * @dt:  an #xmlSchemaValPtr
3212 *
3213 * Calculates the number of seconds in the time portion of @dt.
3214 *
3215 * Returns seconds.
3216 */
3217#define TIME_TO_NUMBER(dt)                              \
3218    ((double)((dt->value.date.hour * SECS_PER_HOUR) +   \
3219              (dt->value.date.min * SECS_PER_MIN) +     \
3220              (dt->value.date.tzo * SECS_PER_MIN)) +    \
3221               dt->value.date.sec)
3222
3223/**
3224 * xmlSchemaCompareDates:
3225 * @x:  a first date/time value
3226 * @y:  a second date/time value
3227 *
3228 * Compare 2 date/times
3229 *
3230 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3231 * case of error
3232 */
3233static int
3234xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
3235{
3236    unsigned char xmask, ymask, xor_mask, and_mask;
3237    xmlSchemaValPtr p1, p2, q1, q2;
3238    long p1d, p2d, q1d, q2d;
3239
3240    if ((x == NULL) || (y == NULL))
3241        return -2;
3242
3243    if (x->value.date.tz_flag) {
3244
3245        if (!y->value.date.tz_flag) {
3246            p1 = xmlSchemaDateNormalize(x, 0);
3247            p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
3248            /* normalize y + 14:00 */
3249            q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
3250
3251            q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
3252            if (p1d < q1d) {
3253                xmlSchemaFreeValue(p1);
3254                xmlSchemaFreeValue(q1);
3255                return -1;
3256            } else if (p1d == q1d) {
3257                double sec;
3258
3259                sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
3260                if (sec < 0.0) {
3261                    xmlSchemaFreeValue(p1);
3262                    xmlSchemaFreeValue(q1);
3263                    return -1;
3264                } else {
3265                    int ret = 0;
3266                    /* normalize y - 14:00 */
3267                    q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
3268                    q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
3269                    if (p1d > q2d)
3270                        ret = 1;
3271                    else if (p1d == q2d) {
3272                        sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
3273                        if (sec > 0.0)
3274                            ret = 1;
3275                        else
3276                            ret = 2; /* indeterminate */
3277                    }
3278                    xmlSchemaFreeValue(p1);
3279                    xmlSchemaFreeValue(q1);
3280                    xmlSchemaFreeValue(q2);
3281                    if (ret != 0)
3282                        return(ret);
3283                }
3284            } else {
3285                xmlSchemaFreeValue(p1);
3286                xmlSchemaFreeValue(q1);
3287            }
3288        }
3289    } else if (y->value.date.tz_flag) {
3290        q1 = xmlSchemaDateNormalize(y, 0);
3291        q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
3292
3293        /* normalize x - 14:00 */
3294        p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
3295        p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
3296
3297        if (p1d < q1d) {
3298            xmlSchemaFreeValue(p1);
3299            xmlSchemaFreeValue(q1);
3300            return -1;
3301        } else if (p1d == q1d) {
3302            double sec;
3303
3304            sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
3305            if (sec < 0.0) {
3306                xmlSchemaFreeValue(p1);
3307                xmlSchemaFreeValue(q1);
3308                return -1;
3309            } else {
3310                int ret = 0;
3311                /* normalize x + 14:00 */
3312                p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
3313                p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
3314
3315                if (p2d > q1d) {
3316                    ret = 1;
3317                } else if (p2d == q1d) {
3318                    sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
3319                    if (sec > 0.0)
3320                        ret = 1;
3321                    else
3322                        ret = 2; /* indeterminate */
3323                }
3324                xmlSchemaFreeValue(p1);
3325                xmlSchemaFreeValue(q1);
3326                xmlSchemaFreeValue(p2);
3327                if (ret != 0)
3328                    return(ret);
3329            }
3330        } else {
3331            xmlSchemaFreeValue(p1);
3332            xmlSchemaFreeValue(q1);
3333        }
3334    }
3335
3336    /*
3337     * if the same type then calculate the difference
3338     */
3339    if (x->type == y->type) {
3340        int ret = 0;
3341        q1 = xmlSchemaDateNormalize(y, 0);
3342        q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
3343
3344        p1 = xmlSchemaDateNormalize(x, 0);
3345        p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
3346
3347        if (p1d < q1d) {
3348            ret = -1;
3349        } else if (p1d > q1d) {
3350            ret = 1;
3351        } else {
3352            double sec;
3353
3354            sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
3355            if (sec < 0.0)
3356                ret = -1;
3357            else if (sec > 0.0)
3358                ret = 1;
3359           
3360        }
3361        xmlSchemaFreeValue(p1);
3362        xmlSchemaFreeValue(q1);
3363        return(ret);
3364    }
3365
3366    switch (x->type) {
3367        case XML_SCHEMAS_DATETIME:
3368            xmask = 0xf;
3369            break;
3370        case XML_SCHEMAS_DATE:
3371            xmask = 0x7;
3372            break;
3373        case XML_SCHEMAS_GYEAR:
3374            xmask = 0x1;
3375            break;
3376        case XML_SCHEMAS_GMONTH:
3377            xmask = 0x2;
3378            break;
3379        case XML_SCHEMAS_GDAY:
3380            xmask = 0x3;
3381            break;
3382        case XML_SCHEMAS_GYEARMONTH:
3383            xmask = 0x3;
3384            break;
3385        case XML_SCHEMAS_GMONTHDAY:
3386            xmask = 0x6;
3387            break;
3388        case XML_SCHEMAS_TIME:
3389            xmask = 0x8;
3390            break;
3391        default:
3392            xmask = 0;
3393            break;
3394    }
3395
3396    switch (y->type) {
3397        case XML_SCHEMAS_DATETIME:
3398            ymask = 0xf;
3399            break;
3400        case XML_SCHEMAS_DATE:
3401            ymask = 0x7;
3402            break;
3403        case XML_SCHEMAS_GYEAR:
3404            ymask = 0x1;
3405            break;
3406        case XML_SCHEMAS_GMONTH:
3407            ymask = 0x2;
3408            break;
3409        case XML_SCHEMAS_GDAY:
3410            ymask = 0x3;
3411            break;
3412        case XML_SCHEMAS_GYEARMONTH:
3413            ymask = 0x3;
3414            break;
3415        case XML_SCHEMAS_GMONTHDAY:
3416            ymask = 0x6;
3417            break;
3418        case XML_SCHEMAS_TIME:
3419            ymask = 0x8;
3420            break;
3421        default:
3422            ymask = 0;
3423            break;
3424    }
3425
3426    xor_mask = xmask ^ ymask;           /* mark type differences */
3427    and_mask = xmask & ymask;           /* mark field specification */
3428
3429    /* year */
3430    if (xor_mask & 1)
3431        return 2; /* indeterminate */
3432    else if (and_mask & 1) {
3433        if (x->value.date.year < y->value.date.year)
3434            return -1;
3435        else if (x->value.date.year > y->value.date.year)
3436            return 1;
3437    }
3438
3439    /* month */
3440    if (xor_mask & 2)
3441        return 2; /* indeterminate */
3442    else if (and_mask & 2) {
3443        if (x->value.date.mon < y->value.date.mon)
3444            return -1;
3445        else if (x->value.date.mon > y->value.date.mon)
3446            return 1;
3447    }
3448
3449    /* day */
3450    if (xor_mask & 4)
3451        return 2; /* indeterminate */
3452    else if (and_mask & 4) {
3453        if (x->value.date.day < y->value.date.day)
3454            return -1;
3455        else if (x->value.date.day > y->value.date.day)
3456            return 1;
3457    }
3458
3459    /* time */
3460    if (xor_mask & 8)
3461        return 2; /* indeterminate */
3462    else if (and_mask & 8) {
3463        if (x->value.date.hour < y->value.date.hour)
3464            return -1;
3465        else if (x->value.date.hour > y->value.date.hour)
3466            return 1;
3467        else if (x->value.date.min < y->value.date.min)
3468            return -1;
3469        else if (x->value.date.min > y->value.date.min)
3470            return 1;
3471        else if (x->value.date.sec < y->value.date.sec)
3472            return -1;
3473        else if (x->value.date.sec > y->value.date.sec)
3474            return 1;
3475    }
3476
3477    return 0;
3478}
3479
3480/**
3481 * xmlSchemaCompareNormStrings:
3482 * @x:  a first string value
3483 * @y:  a second string value
3484 *
3485 * Compare 2 string for their normalized values.
3486 *
3487 * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in
3488 * case of error
3489 */
3490static int
3491xmlSchemaCompareNormStrings(xmlSchemaValPtr x, xmlSchemaValPtr y) {
3492    const xmlChar *utf1;
3493    const xmlChar *utf2;
3494    int tmp;
3495
3496    if ((x == NULL) || (y == NULL))
3497        return(-2);
3498    utf1 = x->value.str;
3499    utf2 = y->value.str;
3500   
3501    while (IS_BLANK_CH(*utf1)) utf1++;
3502    while (IS_BLANK_CH(*utf2)) utf2++;
3503    while ((*utf1 != 0) && (*utf2 != 0)) {
3504        if (IS_BLANK_CH(*utf1)) {
3505            if (!IS_BLANK_CH(*utf2)) {
3506                tmp = *utf1 - *utf2;
3507                return(tmp);
3508            }
3509            while (IS_BLANK_CH(*utf1)) utf1++;
3510            while (IS_BLANK_CH(*utf2)) utf2++;
3511        } else {
3512            tmp = *utf1++ - *utf2++;
3513            if (tmp < 0)
3514                return(-1);
3515            if (tmp > 0)
3516                return(1);
3517        }
3518    }
3519    if (*utf1 != 0) {
3520        while (IS_BLANK_CH(*utf1)) utf1++;
3521        if (*utf1 != 0)
3522            return(1);
3523    }
3524    if (*utf2 != 0) {
3525        while (IS_BLANK_CH(*utf2)) utf2++;
3526        if (*utf2 != 0)
3527            return(-1);
3528    }
3529    return(0);
3530}
3531
3532/**
3533 * xmlSchemaCompareFloats:
3534 * @x:  a first float or double value
3535 * @y:  a second float or double value
3536 *
3537 * Compare 2 values
3538 *
3539 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3540 * case of error
3541 */
3542static int
3543xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
3544    double d1, d2;
3545
3546    if ((x == NULL) || (y == NULL))
3547        return(-2);
3548
3549    /*
3550     * Cast everything to doubles.
3551     */
3552    if (x->type == XML_SCHEMAS_DOUBLE)
3553        d1 = x->value.d;
3554    else if (x->type == XML_SCHEMAS_FLOAT)
3555        d1 = x->value.f;
3556    else
3557        return(-2);
3558
3559    if (y->type == XML_SCHEMAS_DOUBLE)
3560        d2 = y->value.d;
3561    else if (y->type == XML_SCHEMAS_FLOAT)
3562        d2 = y->value.f;
3563    else
3564        return(-2);
3565
3566    /*
3567     * Check for special cases.
3568     */
3569    if (xmlXPathIsNaN(d1)) {
3570        if (xmlXPathIsNaN(d2))
3571            return(0);
3572        return(1);
3573    }
3574    if (xmlXPathIsNaN(d2))
3575        return(-1);
3576    if (d1 == xmlXPathPINF) {
3577        if (d2 == xmlXPathPINF)
3578            return(0);
3579        return(1);
3580    }
3581    if (d2 == xmlXPathPINF)
3582        return(-1);
3583    if (d1 == xmlXPathNINF) {
3584        if (d2 == xmlXPathNINF)
3585            return(0);
3586        return(-1);
3587    }
3588    if (d2 == xmlXPathNINF)
3589        return(1);
3590
3591    /*
3592     * basic tests, the last one we should have equality, but
3593     * portability is more important than speed and handling
3594     * NaN or Inf in a portable way is always a challenge, so ...
3595     */
3596    if (d1 < d2)
3597        return(-1);
3598    if (d1 > d2)
3599        return(1);
3600    if (d1 == d2)
3601        return(0);
3602    return(2);
3603}
3604
3605/**
3606 * xmlSchemaCompareValues:
3607 * @x:  a first value
3608 * @y:  a second value
3609 *
3610 * Compare 2 values
3611 *
3612 * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in
3613 * case of error
3614 */
3615int
3616xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
3617    if ((x == NULL) || (y == NULL))
3618        return(-2);
3619
3620    switch (x->type) {
3621        case XML_SCHEMAS_UNKNOWN:
3622        case XML_SCHEMAS_ANYTYPE:
3623        case XML_SCHEMAS_ANYSIMPLETYPE:
3624            return(-2);
3625        case XML_SCHEMAS_INTEGER:
3626        case XML_SCHEMAS_NPINTEGER:
3627        case XML_SCHEMAS_NINTEGER:
3628        case XML_SCHEMAS_NNINTEGER:
3629        case XML_SCHEMAS_PINTEGER:
3630        case XML_SCHEMAS_INT:
3631        case XML_SCHEMAS_UINT:
3632        case XML_SCHEMAS_LONG:
3633        case XML_SCHEMAS_ULONG:
3634        case XML_SCHEMAS_SHORT:
3635        case XML_SCHEMAS_USHORT:
3636        case XML_SCHEMAS_BYTE:
3637        case XML_SCHEMAS_UBYTE:
3638        case XML_SCHEMAS_DECIMAL:
3639            if (y->type == x->type)
3640                return(xmlSchemaCompareDecimals(x, y));
3641            if ((y->type == XML_SCHEMAS_DECIMAL) ||
3642                (y->type == XML_SCHEMAS_INTEGER) ||
3643                (y->type == XML_SCHEMAS_NPINTEGER) ||
3644                (y->type == XML_SCHEMAS_NINTEGER) ||
3645                (y->type == XML_SCHEMAS_NNINTEGER) ||
3646                (y->type == XML_SCHEMAS_PINTEGER) ||
3647                (y->type == XML_SCHEMAS_INT) ||
3648                (y->type == XML_SCHEMAS_UINT) ||
3649                (y->type == XML_SCHEMAS_LONG) ||
3650                (y->type == XML_SCHEMAS_ULONG) ||
3651                (y->type == XML_SCHEMAS_SHORT) ||
3652                (y->type == XML_SCHEMAS_USHORT) ||
3653                (y->type == XML_SCHEMAS_BYTE) ||
3654                (y->type == XML_SCHEMAS_UBYTE))
3655                return(xmlSchemaCompareDecimals(x, y));
3656            return(-2);
3657        case XML_SCHEMAS_DURATION:
3658            if (y->type == XML_SCHEMAS_DURATION)
3659                return(xmlSchemaCompareDurations(x, y));
3660            return(-2);
3661        case XML_SCHEMAS_TIME:
3662        case XML_SCHEMAS_GDAY:
3663        case XML_SCHEMAS_GMONTH:
3664        case XML_SCHEMAS_GMONTHDAY:
3665        case XML_SCHEMAS_GYEAR:
3666        case XML_SCHEMAS_GYEARMONTH:
3667        case XML_SCHEMAS_DATE:
3668        case XML_SCHEMAS_DATETIME:
3669            if ((y->type == XML_SCHEMAS_DATETIME)  ||
3670                (y->type == XML_SCHEMAS_TIME)      ||
3671                (y->type == XML_SCHEMAS_GDAY)      ||
3672                (y->type == XML_SCHEMAS_GMONTH)    ||
3673                (y->type == XML_SCHEMAS_GMONTHDAY) ||
3674                (y->type == XML_SCHEMAS_GYEAR)     ||
3675                (y->type == XML_SCHEMAS_DATE)      ||
3676                (y->type == XML_SCHEMAS_GYEARMONTH))
3677                return (xmlSchemaCompareDates(x, y));
3678            return (-2);
3679        case XML_SCHEMAS_NORMSTRING:
3680        case XML_SCHEMAS_TOKEN:
3681        case XML_SCHEMAS_LANGUAGE:
3682        case XML_SCHEMAS_NMTOKEN:
3683        case XML_SCHEMAS_NAME:
3684        case XML_SCHEMAS_NCNAME:
3685        case XML_SCHEMAS_ID:
3686        case XML_SCHEMAS_IDREF:
3687        case XML_SCHEMAS_ENTITY:
3688        case XML_SCHEMAS_NOTATION:
3689        case XML_SCHEMAS_ANYURI:
3690            if ((y->type == XML_SCHEMAS_NORMSTRING) ||
3691                (y->type == XML_SCHEMAS_TOKEN) ||
3692                (y->type == XML_SCHEMAS_LANGUAGE) ||
3693                (y->type == XML_SCHEMAS_NMTOKEN) ||
3694                (y->type == XML_SCHEMAS_NAME) ||
3695                (y->type == XML_SCHEMAS_QNAME) ||
3696                (y->type == XML_SCHEMAS_NCNAME) ||
3697                (y->type == XML_SCHEMAS_ID) ||
3698                (y->type == XML_SCHEMAS_IDREF) ||
3699                (y->type == XML_SCHEMAS_ENTITY) ||
3700                (y->type == XML_SCHEMAS_NOTATION) ||
3701                (y->type == XML_SCHEMAS_ANYURI))
3702                return (xmlSchemaCompareNormStrings(x, y));
3703            return (-2);
3704        case XML_SCHEMAS_QNAME:
3705            if (y->type == XML_SCHEMAS_QNAME) {
3706                if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
3707                    (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
3708                    return(0);
3709                return(2);
3710            }
3711            return (-2);
3712        case XML_SCHEMAS_FLOAT:
3713        case XML_SCHEMAS_DOUBLE:
3714            if ((y->type == XML_SCHEMAS_FLOAT) ||
3715                (y->type == XML_SCHEMAS_DOUBLE))
3716                return (xmlSchemaCompareFloats(x, y));
3717            return (-2);
3718        case XML_SCHEMAS_BOOLEAN:
3719            if (y->type == XML_SCHEMAS_BOOLEAN) {
3720                if (x->value.b == y->value.b)
3721                    return(0);
3722                if (x->value.b == 0)
3723                    return(-1);
3724                return(1);
3725            }
3726            return (-2);
3727        case XML_SCHEMAS_HEXBINARY:
3728            if (y->type == XML_SCHEMAS_HEXBINARY) {
3729                if (x->value.hex.total == y->value.hex.total) {
3730                    int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
3731                    if (ret > 0)
3732                        return(1);
3733                    else if (ret == 0)
3734                        return(0);
3735                }
3736                else if (x->value.hex.total > y->value.hex.total)
3737                    return(1);
3738
3739                return(-1);
3740            }
3741            return (-2);
3742        case XML_SCHEMAS_BASE64BINARY:
3743            if (y->type == XML_SCHEMAS_BASE64BINARY) {
3744                if (x->value.base64.total == y->value.base64.total) {
3745                    int ret = xmlStrcmp(x->value.base64.str,
3746                                        y->value.base64.str);
3747                    if (ret > 0)
3748                        return(1);
3749                    else if (ret == 0)
3750                        return(0);
3751                }
3752                else if (x->value.base64.total > y->value.base64.total)
3753                    return(1);
3754                else
3755                    return(-1);
3756            }
3757            return (-2);
3758        case XML_SCHEMAS_STRING:
3759        case XML_SCHEMAS_IDREFS:
3760        case XML_SCHEMAS_ENTITIES:
3761        case XML_SCHEMAS_NMTOKENS:
3762            TODO
3763            break;
3764    }
3765    return -2;
3766}
3767
3768/**
3769 * xmlSchemaNormLen:
3770 * @value:  a string
3771 *
3772 * Computes the UTF8 length of the normalized value of the string
3773 *
3774 * Returns the length or -1 in case of error.
3775 */
3776static int
3777xmlSchemaNormLen(const xmlChar *value) {
3778    const xmlChar *utf;
3779    int ret = 0;
3780
3781    if (value == NULL)
3782        return(-1);
3783    utf = value;
3784    while (IS_BLANK_CH(*utf)) utf++;
3785    while (*utf != 0) {
3786        if (utf[0] & 0x80) {
3787            if ((utf[1] & 0xc0) != 0x80)
3788                return(-1);
3789            if ((utf[0] & 0xe0) == 0xe0) {
3790                if ((utf[2] & 0xc0) != 0x80)
3791                    return(-1);
3792                if ((utf[0] & 0xf0) == 0xf0) {
3793                    if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
3794                        return(-1);
3795                    utf += 4;
3796                } else {
3797                    utf += 3;
3798                }
3799            } else {
3800                utf += 2;
3801            }
3802        } else if (IS_BLANK_CH(*utf)) {
3803            while (IS_BLANK_CH(*utf)) utf++;
3804            if (*utf == 0)
3805                break;
3806        } else {
3807            utf++;
3808        }
3809        ret++;
3810    }
3811    return(ret);
3812}
3813
3814/**
3815 * xmlSchemaGetFacetValueAsULong:
3816 * @facet: an schemas type facet
3817 *
3818 * Extract the value of a facet
3819 *
3820 * Returns the value as a long
3821 */
3822unsigned long
3823xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
3824{
3825    /*
3826    * TODO: Check if this is a decimal.
3827    */
3828    if (facet == NULL)
3829        return 0;
3830    return ((unsigned long) facet->val->value.decimal.lo);
3831}
3832
3833/**
3834 * xmlSchemaValidateListSimpleTypeFacet:
3835 * @facet:  the facet to check
3836 * @value:  the lexical repr of the value to validate
3837 * @actualLen:  the number of list items
3838 * @expectedLen: the resulting expected number of list items
3839 *
3840 * Checks the value of a list simple type against a facet.
3841 *
3842 * Returns 0 if the value is valid, a positive error code
3843 * number otherwise and -1 in case of an internal error.
3844 */
3845int
3846xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,
3847                                     const xmlChar *value,
3848                                     unsigned long actualLen,
3849                                     unsigned long *expectedLen)
3850{
3851    if (facet == NULL)
3852        return(-1);
3853    /*
3854    * TODO: Check if this will work with large numbers.
3855    * (compare value.decimal.mi and value.decimal.hi as well?).
3856    */
3857    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
3858        if (actualLen != facet->val->value.decimal.lo) {
3859            if (expectedLen != 0)
3860                *expectedLen = facet->val->value.decimal.lo;
3861            return (XML_SCHEMAV_CVC_LENGTH_VALID);
3862        }       
3863    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
3864        if (actualLen < facet->val->value.decimal.lo) {
3865            if (expectedLen != 0)
3866                *expectedLen = facet->val->value.decimal.lo;
3867            return (XML_SCHEMAV_CVC_MINLENGTH_VALID);
3868        }
3869    } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
3870        if (actualLen > facet->val->value.decimal.lo) {
3871            if (expectedLen != 0)
3872                *expectedLen = facet->val->value.decimal.lo;
3873            return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
3874        }
3875    } else
3876        /*
3877        * NOTE: That we can pass NULL as xmlSchemaValPtr to
3878        * xmlSchemaValidateFacet, since the remaining facet types
3879        * are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION.
3880        */
3881        return(xmlSchemaValidateFacet(NULL, facet, value, NULL));   
3882    return (0);
3883}
3884
3885/**
3886 * xmlSchemaValidateLengthFacet:
3887 * @type:  the built-in type
3888 * @facet:  the facet to check
3889 * @value:  the lexical repr. of the value to be validated
3890 * @val:  the precomputed value
3891 * @length: the actual length of the value
3892 *
3893 * Checka a value against a "length", "minLength" and "maxLength"
3894 * facet; sets @length to the computed length of @value.
3895 *
3896 * Returns 0 if the value is valid, a positive error code
3897 * otherwise and -1 in case of an internal or API error.
3898 */
3899int
3900xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type,
3901                             xmlSchemaFacetPtr facet,
3902                             const xmlChar *value,
3903                             xmlSchemaValPtr val,
3904                             unsigned long *length) 
3905{
3906    unsigned int len = 0;
3907
3908    if ((length == NULL) || (facet == NULL) || (type == NULL))
3909        return (-1);
3910    *length = 0;
3911    if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
3912        (facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
3913        (facet->type != XML_SCHEMA_FACET_MINLENGTH))
3914        return (-1);
3915       
3916    if ((facet->val == NULL) ||
3917        ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
3918         (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
3919        (facet->val->value.decimal.frac != 0)) {
3920        return(-1);
3921    }
3922    if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
3923        len = val->value.hex.total;
3924    else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
3925        len = val->value.base64.total;
3926    else {
3927        switch (type->builtInType) {
3928            case XML_SCHEMAS_IDREF:
3929            case XML_SCHEMAS_NORMSTRING:
3930            case XML_SCHEMAS_TOKEN:
3931            case XML_SCHEMAS_LANGUAGE:
3932            case XML_SCHEMAS_NMTOKEN:
3933            case XML_SCHEMAS_NAME:
3934            case XML_SCHEMAS_NCNAME:
3935            case XML_SCHEMAS_ID:
3936                len = xmlSchemaNormLen(value);
3937                break;
3938            case XML_SCHEMAS_STRING:
3939            /*
3940            * FIXME: What exactly to do with anyURI?
3941            */
3942            case XML_SCHEMAS_ANYURI:
3943                if (value != NULL)
3944                    len = xmlUTF8Strlen(value);
3945                break;
3946            default:
3947                TODO
3948        }
3949    }
3950    *length = (unsigned long) len;
3951    if (facet->type == XML_SCHEMA_FACET_LENGTH) {
3952        if (len != facet->val->value.decimal.lo)
3953            return(XML_SCHEMAV_CVC_LENGTH_VALID);
3954    } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
3955        if (len < facet->val->value.decimal.lo)
3956            return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
3957    } else {
3958        if (len > facet->val->value.decimal.lo)
3959            return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
3960    }
3961   
3962    return (0);
3963}
3964
3965/**
3966 * xmlSchemaValidateFacet:
3967 * @base:  the base type
3968 * @facet:  the facet to check
3969 * @value:  the lexical repr of the value to validate
3970 * @val:  the precomputed value
3971 *
3972 * Check a value against a facet condition
3973 *
3974 * Returns 0 if the element is schemas valid, a positive error code
3975 *     number otherwise and -1 in case of internal or API error.
3976 */
3977int
3978xmlSchemaValidateFacet(xmlSchemaTypePtr base ATTRIBUTE_UNUSED,
3979                       xmlSchemaFacetPtr facet,
3980                       const xmlChar *value, xmlSchemaValPtr val)
3981{
3982    int ret;
3983
3984    if ((facet == NULL) || (value == NULL))
3985        return(-1);
3986    switch (facet->type) {
3987        case XML_SCHEMA_FACET_PATTERN:
3988            ret = xmlRegexpExec(facet->regexp, value);
3989            if (ret == 1)
3990                return(0);
3991            if (ret == 0) {
3992                return(XML_SCHEMAV_CVC_PATTERN_VALID);
3993            }
3994            return(ret);
3995        case XML_SCHEMA_FACET_MAXEXCLUSIVE:
3996            ret = xmlSchemaCompareValues(val, facet->val);
3997            if (ret == -2) {
3998                /* TODO error code */
3999                return(-1);
4000            }
4001            if (ret == -1)
4002                return(0);
4003            /* error code */
4004            return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID);
4005        case XML_SCHEMA_FACET_MAXINCLUSIVE:
4006            ret = xmlSchemaCompareValues(val, facet->val);
4007            if (ret == -2) {
4008                /* TODO error code */
4009                return(-1);
4010            }
4011            if ((ret == -1) || (ret == 0))
4012                return(0);
4013            /* error code */
4014            return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID);
4015        case XML_SCHEMA_FACET_MINEXCLUSIVE:
4016            ret = xmlSchemaCompareValues(val, facet->val);
4017            if (ret == -2) {
4018                /* TODO error code */
4019                return(-1);
4020            }
4021            if (ret == 1)
4022                return(0);
4023            /* error code */
4024            return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID);
4025        case XML_SCHEMA_FACET_MININCLUSIVE:
4026            ret = xmlSchemaCompareValues(val, facet->val);
4027            if (ret == -2) {
4028                /* TODO error code */
4029                return(-1);
4030            }
4031            if ((ret == 1) || (ret == 0))
4032                return(0);
4033            /* error code */
4034            return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID);
4035        case XML_SCHEMA_FACET_WHITESPACE:
4036            /* TODO whitespaces */
4037            /*
4038            * NOTE: Whitespace should be handled to normalize
4039            * the value to be validated against a the facets;
4040            * not to normalize the value in-between.
4041            */
4042            return(0);
4043        case  XML_SCHEMA_FACET_ENUMERATION:
4044            if ((facet->value != NULL) &&
4045                (xmlStrEqual(facet->value, value)))
4046                return(0);
4047            return(XML_SCHEMAV_CVC_ENUMERATION_VALID);
4048        case XML_SCHEMA_FACET_LENGTH:
4049        case XML_SCHEMA_FACET_MAXLENGTH:
4050        case XML_SCHEMA_FACET_MINLENGTH: {
4051            unsigned int len = 0;
4052
4053            if ((facet->val == NULL) ||
4054                ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
4055                 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
4056                (facet->val->value.decimal.frac != 0)) {
4057                return(-1);
4058            }
4059            if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
4060                len = val->value.hex.total;
4061            else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
4062                len = val->value.base64.total;
4063            else {
4064                switch (base->builtInType) {
4065                    case XML_SCHEMAS_IDREF:
4066                    case XML_SCHEMAS_NORMSTRING:
4067                    case XML_SCHEMAS_TOKEN:
4068                    case XML_SCHEMAS_LANGUAGE:
4069                    case XML_SCHEMAS_NMTOKEN:
4070                    case XML_SCHEMAS_NAME:
4071                    case XML_SCHEMAS_NCNAME:
4072                    case XML_SCHEMAS_ID:
4073                        len = xmlSchemaNormLen(value);
4074                        break;
4075                    case XML_SCHEMAS_STRING:
4076                    /*
4077                    * FIXME: What exactly to do with anyURI?
4078                    */
4079                    case XML_SCHEMAS_ANYURI:
4080                        if (value != NULL)
4081                            len = xmlUTF8Strlen(value);
4082                        break;
4083                    default:
4084                        TODO
4085                }
4086            }
4087            if (facet->type == XML_SCHEMA_FACET_LENGTH) {
4088                if (len != facet->val->value.decimal.lo)
4089                    return(XML_SCHEMAV_CVC_LENGTH_VALID);
4090            } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
4091                if (len < facet->val->value.decimal.lo)
4092                    return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
4093            } else {
4094                if (len > facet->val->value.decimal.lo)
4095                    return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
4096            }
4097            break;
4098        }
4099        case XML_SCHEMA_FACET_TOTALDIGITS:
4100        case XML_SCHEMA_FACET_FRACTIONDIGITS:
4101
4102            if ((facet->val == NULL) ||
4103                ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
4104                 (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
4105                (facet->val->value.decimal.frac != 0)) {
4106                return(-1);
4107            }
4108            if ((val == NULL) ||
4109                ((val->type != XML_SCHEMAS_DECIMAL) &&
4110                 (val->type != XML_SCHEMAS_INTEGER) &&
4111                 (val->type != XML_SCHEMAS_NPINTEGER) &&
4112                 (val->type != XML_SCHEMAS_NINTEGER) &&
4113                 (val->type != XML_SCHEMAS_NNINTEGER) &&
4114                 (val->type != XML_SCHEMAS_PINTEGER) &&
4115                 (val->type != XML_SCHEMAS_INT) &&
4116                 (val->type != XML_SCHEMAS_UINT) &&
4117                 (val->type != XML_SCHEMAS_LONG) &&
4118                 (val->type != XML_SCHEMAS_ULONG) &&
4119                 (val->type != XML_SCHEMAS_SHORT) &&
4120                 (val->type != XML_SCHEMAS_USHORT) &&
4121                 (val->type != XML_SCHEMAS_BYTE) &&
4122                 (val->type != XML_SCHEMAS_UBYTE))) {
4123                return(-1);
4124            }
4125            if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
4126                if (val->value.decimal.total > facet->val->value.decimal.lo)
4127                    return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID);
4128
4129            } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
4130                if (val->value.decimal.frac > facet->val->value.decimal.lo)
4131                    return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID);
4132            }
4133            break;
4134        default:
4135            TODO
4136    }
4137    return(0);
4138
4139}
4140
4141#endif /* LIBXML_SCHEMAS_ENABLED */
Note: See TracBrowser for help on using the repository browser.