Annotation of embedaddon/libxml2/xmlschemastypes.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>