ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

xmlschemastypes.c
Go to the documentation of this file.
00001 /*
00002  * schemastypes.c : implementation of the XML Schema Datatypes
00003  *             definition and validity checking
00004  *
00005  * See Copyright for the status of this software.
00006  *
00007  * Daniel Veillard <veillard@redhat.com>
00008  */
00009 
00010 #define IN_LIBXML
00011 #include "libxml.h"
00012 
00013 #ifdef LIBXML_SCHEMAS_ENABLED
00014 
00015 #include <string.h>
00016 #include <libxml/xmlmemory.h>
00017 #include <libxml/parser.h>
00018 #include <libxml/parserInternals.h>
00019 #include <libxml/hash.h>
00020 #include <libxml/valid.h>
00021 #include <libxml/xpath.h>
00022 #include <libxml/uri.h>
00023 
00024 #include <libxml/xmlschemas.h>
00025 #include <libxml/schemasInternals.h>
00026 #include <libxml/xmlschemastypes.h>
00027 
00028 #ifdef HAVE_MATH_H
00029 #include <math.h>
00030 #endif
00031 #ifdef HAVE_FLOAT_H
00032 #include <float.h>
00033 #endif
00034 
00035 #define DEBUG
00036 
00037 #ifndef LIBXML_XPATH_ENABLED
00038 extern double xmlXPathNAN;
00039 extern double xmlXPathPINF;
00040 extern double xmlXPathNINF;
00041 #endif
00042 
00043 #define TODO                                \
00044     xmlGenericError(xmlGenericErrorContext,             \
00045         "Unimplemented block at %s:%d\n",               \
00046             __FILE__, __LINE__);
00047 
00048 #define XML_SCHEMAS_NAMESPACE_NAME \
00049     (const xmlChar *)"http://www.w3.org/2001/XMLSchema"
00050 
00051 #define IS_WSP_REPLACE_CH(c)    ((((c) == 0x9) || ((c) == 0xa)) || \
00052                  ((c) == 0xd))
00053 
00054 #define IS_WSP_SPACE_CH(c)  ((c) == 0x20)
00055 
00056 #define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c)
00057 
00058 /* Date value */
00059 typedef struct _xmlSchemaValDate xmlSchemaValDate;
00060 typedef xmlSchemaValDate *xmlSchemaValDatePtr;
00061 struct _xmlSchemaValDate {
00062     long        year;
00063     unsigned int    mon :4; /* 1 <=  mon    <= 12   */
00064     unsigned int    day :5; /* 1 <=  day    <= 31   */
00065     unsigned int    hour    :5; /* 0 <=  hour   <= 23   */
00066     unsigned int    min :6; /* 0 <=  min    <= 59   */
00067     double      sec;
00068     unsigned int    tz_flag :1; /* is tzo explicitely set? */
00069     signed int      tzo :12;    /* -1440 <= tzo <= 1440;
00070                        currently only -840 to +840 are needed */
00071 };
00072 
00073 /* Duration value */
00074 typedef struct _xmlSchemaValDuration xmlSchemaValDuration;
00075 typedef xmlSchemaValDuration *xmlSchemaValDurationPtr;
00076 struct _xmlSchemaValDuration {
00077     long            mon;        /* mon stores years also */
00078     long            day;
00079     double      sec;            /* sec stores min and hour also */
00080 };
00081 
00082 typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal;
00083 typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr;
00084 struct _xmlSchemaValDecimal {
00085     /* would use long long but not portable */
00086     unsigned long lo;
00087     unsigned long mi;
00088     unsigned long hi;
00089     unsigned int extra;
00090     unsigned int sign:1;
00091     unsigned int frac:7;
00092     unsigned int total:8;
00093 };
00094 
00095 typedef struct _xmlSchemaValQName xmlSchemaValQName;
00096 typedef xmlSchemaValQName *xmlSchemaValQNamePtr;
00097 struct _xmlSchemaValQName {
00098     xmlChar *name;
00099     xmlChar *uri;
00100 };
00101 
00102 typedef struct _xmlSchemaValHex xmlSchemaValHex;
00103 typedef xmlSchemaValHex *xmlSchemaValHexPtr;
00104 struct _xmlSchemaValHex {
00105     xmlChar     *str;
00106     unsigned int total;
00107 };
00108 
00109 typedef struct _xmlSchemaValBase64 xmlSchemaValBase64;
00110 typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr;
00111 struct _xmlSchemaValBase64 {
00112     xmlChar     *str;
00113     unsigned int total;
00114 };
00115 
00116 struct _xmlSchemaVal {
00117     xmlSchemaValType type;
00118     struct _xmlSchemaVal *next;
00119     union {
00120     xmlSchemaValDecimal     decimal;
00121         xmlSchemaValDate        date;
00122         xmlSchemaValDuration    dur;
00123     xmlSchemaValQName   qname;
00124     xmlSchemaValHex     hex;
00125     xmlSchemaValBase64  base64;
00126     float           f;
00127     double          d;
00128     int         b;
00129     xmlChar                *str;
00130     } value;
00131 };
00132 
00133 static int xmlSchemaTypesInitialized = 0;
00134 static xmlHashTablePtr xmlSchemaTypesBank = NULL;
00135 
00136 /*
00137  * Basic types
00138  */
00139 static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL;
00140 static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL;
00141 static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL;
00142 static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL;
00143 static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL;
00144 static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL;
00145 static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL;
00146 static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL;
00147 static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL;
00148 static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL;
00149 static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL;
00150 static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL;
00151 static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL;
00152 static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL;
00153 static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL;
00154 static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL;
00155 static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL;
00156 static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL;
00157 static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL;
00158 
00159 /*
00160  * Derived types
00161  */
00162 static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL;
00163 static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL;
00164 static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL;
00165 static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL;
00166 static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL;
00167 static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL;
00168 static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL;
00169 static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL;
00170 static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL;
00171 static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL;
00172 static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL;
00173 static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL;
00174 static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL;
00175 static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL;
00176 static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL;
00177 static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL;
00178 static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL;
00179 static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL;
00180 static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL;
00181 static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL;
00182 static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL;
00183 static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL;
00184 static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL;
00185 static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL;
00186 static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL;
00187 static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL;
00188 static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL;
00189 
00190 /************************************************************************
00191  *                                  *
00192  *          Datatype error handlers             *
00193  *                                  *
00194  ************************************************************************/
00201 static void
00202 xmlSchemaTypeErrMemory(xmlNodePtr node, const char *extra)
00203 {
00204     __xmlSimpleError(XML_FROM_DATATYPE, XML_ERR_NO_MEMORY, node, NULL, extra);
00205 }
00206 
00207 /************************************************************************
00208  *                                  *
00209  *          Base types support              *
00210  *                                  *
00211  ************************************************************************/
00212 
00221 static xmlSchemaValPtr
00222 xmlSchemaNewValue(xmlSchemaValType type) {
00223     xmlSchemaValPtr value;
00224 
00225     value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
00226     if (value == NULL) {
00227     return(NULL);
00228     }
00229     memset(value, 0, sizeof(xmlSchemaVal));
00230     value->type = type;
00231     return(value);
00232 }
00233 
00234 static xmlSchemaFacetPtr
00235 xmlSchemaNewMinLengthFacet(int value)
00236 {
00237     xmlSchemaFacetPtr ret;
00238 
00239     ret = xmlSchemaNewFacet();
00240     if (ret == NULL) {
00241         return(NULL);
00242     }
00243     ret->type = XML_SCHEMA_FACET_MINLENGTH;
00244     ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER);
00245     ret->val->value.decimal.lo = value;
00246     return (ret);
00247 }
00248 
00249 /*
00250  * xmlSchemaInitBasicType:
00251  * @name:  the type name
00252  * @type:  the value type associated
00253  *
00254  * Initialize one primitive built-in type
00255  */
00256 static xmlSchemaTypePtr
00257 xmlSchemaInitBasicType(const char *name, xmlSchemaValType type, 
00258                xmlSchemaTypePtr baseType) {
00259     xmlSchemaTypePtr ret;
00260 
00261     ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
00262     if (ret == NULL) {
00263         xmlSchemaTypeErrMemory(NULL, "could not initialize basic types");
00264     return(NULL);
00265     }
00266     memset(ret, 0, sizeof(xmlSchemaType));
00267     ret->name = (const xmlChar *)name;
00268     ret->targetNamespace = XML_SCHEMAS_NAMESPACE_NAME;
00269     ret->type = XML_SCHEMA_TYPE_BASIC;
00270     ret->baseType = baseType;   
00271     ret->contentType = XML_SCHEMA_CONTENT_BASIC;
00272     /*
00273     * Primitive types.
00274     */
00275     switch (type) {     
00276     case XML_SCHEMAS_STRING:            
00277     case XML_SCHEMAS_DECIMAL:    
00278     case XML_SCHEMAS_DATE:    
00279     case XML_SCHEMAS_DATETIME:    
00280     case XML_SCHEMAS_TIME:    
00281     case XML_SCHEMAS_GYEAR:    
00282     case XML_SCHEMAS_GYEARMONTH:    
00283     case XML_SCHEMAS_GMONTH:    
00284     case XML_SCHEMAS_GMONTHDAY:    
00285     case XML_SCHEMAS_GDAY:    
00286     case XML_SCHEMAS_DURATION:    
00287     case XML_SCHEMAS_FLOAT:    
00288     case XML_SCHEMAS_DOUBLE:    
00289     case XML_SCHEMAS_BOOLEAN:    
00290     case XML_SCHEMAS_ANYURI:    
00291     case XML_SCHEMAS_HEXBINARY:    
00292     case XML_SCHEMAS_BASE64BINARY:  
00293     case XML_SCHEMAS_QNAME: 
00294     case XML_SCHEMAS_NOTATION:  
00295         ret->flags |= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE;
00296         break;
00297     default:
00298         break;
00299     }
00300     /*
00301     * Set variety.
00302     */
00303     switch (type) {
00304     case XML_SCHEMAS_ANYTYPE:
00305     case XML_SCHEMAS_ANYSIMPLETYPE:
00306         break;
00307     case XML_SCHEMAS_IDREFS:
00308     case XML_SCHEMAS_NMTOKENS:
00309     case XML_SCHEMAS_ENTITIES:
00310         ret->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
00311         ret->facets = xmlSchemaNewMinLengthFacet(1);
00312         ret->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;      
00313         break;
00314     default:
00315         ret->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
00316         break;
00317     }
00318     xmlHashAddEntry2(xmlSchemaTypesBank, ret->name,
00319                  XML_SCHEMAS_NAMESPACE_NAME, ret);
00320     ret->builtInType = type;
00321     return(ret);
00322 }
00323 
00324 /*
00325 * WARNING: Those type reside normally in xmlschemas.c but are
00326 * redefined here locally in oder of being able to use them for xs:anyType-
00327 * TODO: Remove those definition if we move the types to a header file.
00328 * TODO: Always keep those structs up-to-date with the originals.
00329 */
00330 #define UNBOUNDED (1 << 30)
00331 
00332 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
00333 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
00334 struct _xmlSchemaTreeItem {
00335     xmlSchemaTypeType type;
00336     xmlSchemaAnnotPtr annot;
00337     xmlSchemaTreeItemPtr next;
00338     xmlSchemaTreeItemPtr children;
00339 };
00340 
00341 typedef struct _xmlSchemaParticle xmlSchemaParticle;
00342 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
00343 struct _xmlSchemaParticle {
00344     xmlSchemaTypeType type;
00345     xmlSchemaAnnotPtr annot;
00346     xmlSchemaTreeItemPtr next;
00347     xmlSchemaTreeItemPtr children;
00348     int minOccurs;
00349     int maxOccurs;
00350     xmlNodePtr node;
00351 };
00352 
00353 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
00354 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
00355 struct _xmlSchemaModelGroup {
00356     xmlSchemaTypeType type;
00357     xmlSchemaAnnotPtr annot;
00358     xmlSchemaTreeItemPtr next;
00359     xmlSchemaTreeItemPtr children;
00360     xmlNodePtr node;
00361 };
00362 
00363 static xmlSchemaParticlePtr
00364 xmlSchemaAddParticle(void)
00365 {
00366     xmlSchemaParticlePtr ret = NULL;
00367 
00368     ret = (xmlSchemaParticlePtr)
00369     xmlMalloc(sizeof(xmlSchemaParticle));
00370     if (ret == NULL) {
00371     xmlSchemaTypeErrMemory(NULL, "allocating particle component");
00372     return (NULL);
00373     }
00374     memset(ret, 0, sizeof(xmlSchemaParticle));
00375     ret->type = XML_SCHEMA_TYPE_PARTICLE;
00376     ret->minOccurs = 1;
00377     ret->maxOccurs = 1;
00378     return (ret);
00379 }
00380 
00381 /*
00382  * xmlSchemaInitTypes:
00383  *
00384  * Initialize the default XML Schemas type library
00385  */
00386 void
00387 xmlSchemaInitTypes(void)
00388 {
00389     if (xmlSchemaTypesInitialized != 0)
00390         return;
00391     xmlSchemaTypesBank = xmlHashCreate(40);
00392 
00393     
00394     /*
00395     * 3.4.7 Built-in Complex Type Definition
00396     */
00397     xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType",
00398                                                      XML_SCHEMAS_ANYTYPE, 
00399                              NULL);
00400     xmlSchemaTypeAnyTypeDef->baseType = xmlSchemaTypeAnyTypeDef;
00401     xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;
00402     /*
00403     * Init the content type.
00404     */
00405     xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED;    
00406     {
00407     xmlSchemaParticlePtr particle;
00408     xmlSchemaModelGroupPtr sequence;
00409     xmlSchemaWildcardPtr wild;
00410     /* First particle. */
00411     particle = xmlSchemaAddParticle();
00412     if (particle == NULL)
00413         return;
00414     xmlSchemaTypeAnyTypeDef->subtypes = (xmlSchemaTypePtr) particle;
00415     /* Sequence model group. */
00416     sequence = (xmlSchemaModelGroupPtr)
00417         xmlMalloc(sizeof(xmlSchemaModelGroup));
00418     if (sequence == NULL) {
00419         xmlSchemaTypeErrMemory(NULL, "allocating model group component");
00420         return;
00421     }
00422     memset(sequence, 0, sizeof(xmlSchemaModelGroup));
00423     sequence->type = XML_SCHEMA_TYPE_SEQUENCE;  
00424     particle->children = (xmlSchemaTreeItemPtr) sequence;
00425     /* Second particle. */
00426     particle = xmlSchemaAddParticle();
00427     if (particle == NULL)
00428         return;
00429     particle->minOccurs = 0;
00430     particle->maxOccurs = UNBOUNDED;
00431     sequence->children = (xmlSchemaTreeItemPtr) particle;
00432     /* The wildcard */
00433     wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
00434     if (wild == NULL) {
00435         xmlSchemaTypeErrMemory(NULL, "allocating wildcard component");
00436         return;
00437     }
00438     memset(wild, 0, sizeof(xmlSchemaWildcard));
00439     wild->type = XML_SCHEMA_TYPE_ANY;
00440     wild->any = 1;  
00441     wild->processContents = XML_SCHEMAS_ANY_LAX;    
00442     particle->children = (xmlSchemaTreeItemPtr) wild;    
00443     /*
00444     * Create the attribute wildcard.
00445     */
00446     wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
00447     if (wild == NULL) {
00448         xmlSchemaTypeErrMemory(NULL, "could not create an attribute "
00449         "wildcard on anyType");
00450         return;
00451     }
00452     memset(wild, 0, sizeof(xmlSchemaWildcard));
00453     wild->any = 1;
00454     wild->processContents = XML_SCHEMAS_ANY_LAX;    
00455     xmlSchemaTypeAnyTypeDef->attributeWildcard = wild;
00456     }
00457     xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType", 
00458                                                            XML_SCHEMAS_ANYSIMPLETYPE,
00459                                xmlSchemaTypeAnyTypeDef);
00460     /*
00461     * primitive datatypes
00462     */
00463     xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string",
00464                                                     XML_SCHEMAS_STRING,
00465                             xmlSchemaTypeAnySimpleTypeDef);
00466     xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal",
00467                                                      XML_SCHEMAS_DECIMAL,
00468                              xmlSchemaTypeAnySimpleTypeDef);
00469     xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date",
00470                                                   XML_SCHEMAS_DATE,
00471                           xmlSchemaTypeAnySimpleTypeDef);
00472     xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime",
00473                                                       XML_SCHEMAS_DATETIME,
00474                               xmlSchemaTypeAnySimpleTypeDef);
00475     xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time",
00476                                                   XML_SCHEMAS_TIME,
00477                           xmlSchemaTypeAnySimpleTypeDef);
00478     xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear",
00479                                                    XML_SCHEMAS_GYEAR,
00480                            xmlSchemaTypeAnySimpleTypeDef);
00481     xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth",
00482                                                         XML_SCHEMAS_GYEARMONTH,
00483                             xmlSchemaTypeAnySimpleTypeDef);
00484     xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth",
00485                                                     XML_SCHEMAS_GMONTH,
00486                             xmlSchemaTypeAnySimpleTypeDef);
00487     xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay",
00488                                                        XML_SCHEMAS_GMONTHDAY,
00489                                xmlSchemaTypeAnySimpleTypeDef);
00490     xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay",
00491                                                   XML_SCHEMAS_GDAY,
00492                           xmlSchemaTypeAnySimpleTypeDef);
00493     xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration",
00494                                                       XML_SCHEMAS_DURATION,
00495                               xmlSchemaTypeAnySimpleTypeDef);
00496     xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float",
00497                                                    XML_SCHEMAS_FLOAT,
00498                            xmlSchemaTypeAnySimpleTypeDef);
00499     xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double",
00500                                                     XML_SCHEMAS_DOUBLE,
00501                             xmlSchemaTypeAnySimpleTypeDef);
00502     xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean",
00503                                                      XML_SCHEMAS_BOOLEAN,
00504                              xmlSchemaTypeAnySimpleTypeDef);
00505     xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI",
00506                                                     XML_SCHEMAS_ANYURI,
00507                             xmlSchemaTypeAnySimpleTypeDef);
00508     xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary",
00509                                                      XML_SCHEMAS_HEXBINARY,
00510                              xmlSchemaTypeAnySimpleTypeDef);
00511     xmlSchemaTypeBase64BinaryDef
00512         = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY,
00513     xmlSchemaTypeAnySimpleTypeDef);
00514     xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION",
00515                                                     XML_SCHEMAS_NOTATION,
00516                             xmlSchemaTypeAnySimpleTypeDef);    
00517     xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName",
00518                                                    XML_SCHEMAS_QNAME,
00519                            xmlSchemaTypeAnySimpleTypeDef);
00520 
00521     /*
00522      * derived datatypes
00523      */
00524     xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer",
00525                                                      XML_SCHEMAS_INTEGER,
00526                              xmlSchemaTypeDecimalDef);
00527     xmlSchemaTypeNonPositiveIntegerDef =
00528         xmlSchemaInitBasicType("nonPositiveInteger",
00529                                XML_SCHEMAS_NPINTEGER,
00530                    xmlSchemaTypeIntegerDef);
00531     xmlSchemaTypeNegativeIntegerDef =
00532         xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER,
00533     xmlSchemaTypeNonPositiveIntegerDef);
00534     xmlSchemaTypeLongDef =
00535         xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG,
00536     xmlSchemaTypeIntegerDef);
00537     xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT,
00538     xmlSchemaTypeLongDef);
00539     xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short",
00540                                                    XML_SCHEMAS_SHORT,
00541                            xmlSchemaTypeIntDef);
00542     xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte",
00543                                                   XML_SCHEMAS_BYTE,
00544                           xmlSchemaTypeShortDef);
00545     xmlSchemaTypeNonNegativeIntegerDef =
00546         xmlSchemaInitBasicType("nonNegativeInteger",
00547                                XML_SCHEMAS_NNINTEGER,
00548                    xmlSchemaTypeIntegerDef);
00549     xmlSchemaTypeUnsignedLongDef =
00550         xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG,
00551     xmlSchemaTypeNonNegativeIntegerDef);
00552     xmlSchemaTypeUnsignedIntDef =
00553         xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT,
00554     xmlSchemaTypeUnsignedLongDef);
00555     xmlSchemaTypeUnsignedShortDef =
00556         xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT,
00557     xmlSchemaTypeUnsignedIntDef);
00558     xmlSchemaTypeUnsignedByteDef =
00559         xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE,
00560     xmlSchemaTypeUnsignedShortDef);
00561     xmlSchemaTypePositiveIntegerDef =
00562         xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER,
00563     xmlSchemaTypeNonNegativeIntegerDef);
00564     xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString",
00565                                                         XML_SCHEMAS_NORMSTRING,
00566                             xmlSchemaTypeStringDef);
00567     xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token",
00568                                                    XML_SCHEMAS_TOKEN,
00569                            xmlSchemaTypeNormStringDef);
00570     xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language",
00571                                                       XML_SCHEMAS_LANGUAGE,
00572                               xmlSchemaTypeTokenDef);
00573     xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name",
00574                                                   XML_SCHEMAS_NAME,
00575                           xmlSchemaTypeTokenDef);
00576     xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN",
00577                                                      XML_SCHEMAS_NMTOKEN,
00578                              xmlSchemaTypeTokenDef);
00579     xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName",
00580                                                     XML_SCHEMAS_NCNAME,
00581                             xmlSchemaTypeNameDef);
00582     xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID,
00583                             xmlSchemaTypeNCNameDef);
00584     xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF",
00585                                                    XML_SCHEMAS_IDREF,
00586                            xmlSchemaTypeNCNameDef);        
00587     xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY",
00588                                                     XML_SCHEMAS_ENTITY,
00589                             xmlSchemaTypeNCNameDef);
00590     /*
00591     * Derived list types.
00592     */
00593     /* ENTITIES */
00594     xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES",
00595                                                       XML_SCHEMAS_ENTITIES,
00596                               xmlSchemaTypeAnySimpleTypeDef);
00597     xmlSchemaTypeEntitiesDef->subtypes = xmlSchemaTypeEntityDef;
00598     /* IDREFS */
00599     xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS",
00600                                                     XML_SCHEMAS_IDREFS,
00601                             xmlSchemaTypeAnySimpleTypeDef);
00602     xmlSchemaTypeIdrefsDef->subtypes = xmlSchemaTypeIdrefDef;
00603 
00604     /* NMTOKENS */
00605     xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS",
00606                                                       XML_SCHEMAS_NMTOKENS,
00607                               xmlSchemaTypeAnySimpleTypeDef);
00608     xmlSchemaTypeNmtokensDef->subtypes = xmlSchemaTypeNmtokenDef;
00609 
00610     xmlSchemaTypesInitialized = 1;
00611 }
00612 
00618 void    
00619 xmlSchemaCleanupTypes(void) {
00620     if (xmlSchemaTypesInitialized == 0)
00621     return;
00622     /*
00623     * Free xs:anyType.
00624     */
00625     {
00626     xmlSchemaParticlePtr particle;
00627     /* Attribute wildcard. */
00628     xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard);
00629     /* Content type. */
00630     particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes;
00631     /* Wildcard. */
00632     xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) 
00633         particle->children->children->children);
00634     xmlFree((xmlSchemaParticlePtr) particle->children->children);
00635     /* Sequence model group. */
00636     xmlFree((xmlSchemaModelGroupPtr) particle->children);
00637     xmlFree((xmlSchemaParticlePtr) particle);
00638     xmlSchemaTypeAnyTypeDef->subtypes = NULL;   
00639     }
00640     xmlHashFree(xmlSchemaTypesBank, (xmlHashDeallocator) xmlSchemaFreeType);
00641     xmlSchemaTypesInitialized = 0;
00642 }
00643 
00655 int
00656 xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type, int facetType)
00657 {
00658     if (type == NULL)
00659     return (-1);
00660     if (type->type != XML_SCHEMA_TYPE_BASIC)
00661     return (-1);
00662     switch (type->builtInType) {
00663     case XML_SCHEMAS_BOOLEAN:
00664         if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
00665         (facetType == XML_SCHEMA_FACET_WHITESPACE))
00666         return (1);
00667         else
00668         return (0); 
00669     case XML_SCHEMAS_STRING:
00670     case XML_SCHEMAS_NOTATION:
00671     case XML_SCHEMAS_QNAME:
00672     case XML_SCHEMAS_ANYURI:        
00673     case XML_SCHEMAS_BASE64BINARY:    
00674     case XML_SCHEMAS_HEXBINARY:
00675         if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
00676         (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
00677         (facetType == XML_SCHEMA_FACET_MAXLENGTH) ||
00678         (facetType == XML_SCHEMA_FACET_PATTERN) ||
00679         (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
00680         (facetType == XML_SCHEMA_FACET_WHITESPACE))
00681         return (1);
00682         else
00683         return (0);
00684     case XML_SCHEMAS_DECIMAL:
00685         if ((facetType == XML_SCHEMA_FACET_TOTALDIGITS) ||
00686         (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) ||
00687         (facetType == XML_SCHEMA_FACET_PATTERN) ||
00688         (facetType == XML_SCHEMA_FACET_WHITESPACE) ||
00689         (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
00690         (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
00691         (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
00692         (facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
00693         (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
00694         return (1);
00695         else
00696         return (0); 
00697     case XML_SCHEMAS_TIME:
00698     case XML_SCHEMAS_GDAY: 
00699     case XML_SCHEMAS_GMONTH:
00700     case XML_SCHEMAS_GMONTHDAY: 
00701     case XML_SCHEMAS_GYEAR: 
00702     case XML_SCHEMAS_GYEARMONTH:
00703     case XML_SCHEMAS_DATE:
00704     case XML_SCHEMAS_DATETIME:
00705     case XML_SCHEMAS_DURATION:
00706     case XML_SCHEMAS_FLOAT:
00707     case XML_SCHEMAS_DOUBLE:
00708         if ((facetType == XML_SCHEMA_FACET_PATTERN) ||
00709         (facetType == XML_SCHEMA_FACET_ENUMERATION) ||
00710         (facetType == XML_SCHEMA_FACET_WHITESPACE) ||
00711         (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) ||
00712         (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) ||
00713         (facetType == XML_SCHEMA_FACET_MININCLUSIVE) ||
00714         (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE))
00715         return (1);
00716         else
00717         return (0);                      
00718     default:
00719         break;
00720     }
00721     return (0);
00722 }
00723 
00733 xmlSchemaTypePtr
00734 xmlSchemaGetBuiltInType(xmlSchemaValType type)
00735 {
00736     if (xmlSchemaTypesInitialized == 0)
00737     xmlSchemaInitTypes();
00738     switch (type) {
00739     
00740     case XML_SCHEMAS_ANYSIMPLETYPE:
00741         return (xmlSchemaTypeAnySimpleTypeDef);
00742     case XML_SCHEMAS_STRING:
00743         return (xmlSchemaTypeStringDef);
00744     case XML_SCHEMAS_NORMSTRING:
00745         return (xmlSchemaTypeNormStringDef);
00746     case XML_SCHEMAS_DECIMAL:
00747         return (xmlSchemaTypeDecimalDef);
00748     case XML_SCHEMAS_TIME:
00749         return (xmlSchemaTypeTimeDef);
00750     case XML_SCHEMAS_GDAY:
00751         return (xmlSchemaTypeGDayDef);
00752     case XML_SCHEMAS_GMONTH:
00753         return (xmlSchemaTypeGMonthDef);
00754     case XML_SCHEMAS_GMONTHDAY:
00755             return (xmlSchemaTypeGMonthDayDef);
00756     case XML_SCHEMAS_GYEAR:
00757         return (xmlSchemaTypeGYearDef);
00758     case XML_SCHEMAS_GYEARMONTH:
00759         return (xmlSchemaTypeGYearMonthDef);
00760     case XML_SCHEMAS_DATE:
00761         return (xmlSchemaTypeDateDef);
00762     case XML_SCHEMAS_DATETIME:
00763         return (xmlSchemaTypeDatetimeDef);
00764     case XML_SCHEMAS_DURATION:
00765         return (xmlSchemaTypeDurationDef);
00766     case XML_SCHEMAS_FLOAT:
00767         return (xmlSchemaTypeFloatDef);
00768     case XML_SCHEMAS_DOUBLE:
00769         return (xmlSchemaTypeDoubleDef);
00770     case XML_SCHEMAS_BOOLEAN:
00771         return (xmlSchemaTypeBooleanDef);
00772     case XML_SCHEMAS_TOKEN:
00773         return (xmlSchemaTypeTokenDef);
00774     case XML_SCHEMAS_LANGUAGE:
00775         return (xmlSchemaTypeLanguageDef);
00776     case XML_SCHEMAS_NMTOKEN:
00777         return (xmlSchemaTypeNmtokenDef);
00778     case XML_SCHEMAS_NMTOKENS:
00779         return (xmlSchemaTypeNmtokensDef);
00780     case XML_SCHEMAS_NAME:
00781         return (xmlSchemaTypeNameDef);
00782     case XML_SCHEMAS_QNAME:
00783         return (xmlSchemaTypeQNameDef);
00784     case XML_SCHEMAS_NCNAME:
00785         return (xmlSchemaTypeNCNameDef);
00786     case XML_SCHEMAS_ID:
00787         return (xmlSchemaTypeIdDef);
00788     case XML_SCHEMAS_IDREF:
00789         return (xmlSchemaTypeIdrefDef);
00790     case XML_SCHEMAS_IDREFS:
00791         return (xmlSchemaTypeIdrefsDef);
00792     case XML_SCHEMAS_ENTITY:
00793         return (xmlSchemaTypeEntityDef);
00794     case XML_SCHEMAS_ENTITIES:
00795         return (xmlSchemaTypeEntitiesDef);
00796     case XML_SCHEMAS_NOTATION:
00797         return (xmlSchemaTypeNotationDef);
00798     case XML_SCHEMAS_ANYURI:
00799         return (xmlSchemaTypeAnyURIDef);
00800     case XML_SCHEMAS_INTEGER:
00801         return (xmlSchemaTypeIntegerDef);
00802     case XML_SCHEMAS_NPINTEGER:
00803         return (xmlSchemaTypeNonPositiveIntegerDef);
00804     case XML_SCHEMAS_NINTEGER:
00805         return (xmlSchemaTypeNegativeIntegerDef);
00806     case XML_SCHEMAS_NNINTEGER:
00807         return (xmlSchemaTypeNonNegativeIntegerDef);
00808     case XML_SCHEMAS_PINTEGER:
00809         return (xmlSchemaTypePositiveIntegerDef);
00810     case XML_SCHEMAS_INT:
00811         return (xmlSchemaTypeIntDef);
00812     case XML_SCHEMAS_UINT:
00813         return (xmlSchemaTypeUnsignedIntDef);
00814     case XML_SCHEMAS_LONG:
00815         return (xmlSchemaTypeLongDef);
00816     case XML_SCHEMAS_ULONG:
00817         return (xmlSchemaTypeUnsignedLongDef);
00818     case XML_SCHEMAS_SHORT:
00819         return (xmlSchemaTypeShortDef);
00820     case XML_SCHEMAS_USHORT:
00821         return (xmlSchemaTypeUnsignedShortDef);
00822     case XML_SCHEMAS_BYTE:
00823         return (xmlSchemaTypeByteDef);
00824     case XML_SCHEMAS_UBYTE:
00825         return (xmlSchemaTypeUnsignedByteDef);
00826     case XML_SCHEMAS_HEXBINARY:
00827         return (xmlSchemaTypeHexBinaryDef);
00828     case XML_SCHEMAS_BASE64BINARY:
00829         return (xmlSchemaTypeBase64BinaryDef);
00830     case XML_SCHEMAS_ANYTYPE:
00831         return (xmlSchemaTypeAnyTypeDef);       
00832     default:
00833         return (NULL);
00834     }
00835 }
00836 
00846 int
00847 xmlSchemaValueAppend(xmlSchemaValPtr prev, xmlSchemaValPtr cur) {
00848 
00849     if ((prev == NULL) || (cur == NULL))
00850     return (-1);
00851     prev->next = cur;
00852     return (0);
00853 }
00854 
00864 xmlSchemaValPtr
00865 xmlSchemaValueGetNext(xmlSchemaValPtr cur) {
00866 
00867     if (cur == NULL)
00868     return (NULL);
00869     return (cur->next);
00870 }
00871 
00881 const xmlChar *
00882 xmlSchemaValueGetAsString(xmlSchemaValPtr val)
00883 {    
00884     if (val == NULL)
00885     return (NULL);
00886     switch (val->type) {
00887     case XML_SCHEMAS_STRING:
00888     case XML_SCHEMAS_NORMSTRING:
00889     case XML_SCHEMAS_ANYSIMPLETYPE:
00890     case XML_SCHEMAS_TOKEN:
00891         case XML_SCHEMAS_LANGUAGE:
00892         case XML_SCHEMAS_NMTOKEN:
00893         case XML_SCHEMAS_NAME:
00894         case XML_SCHEMAS_NCNAME:
00895         case XML_SCHEMAS_ID:
00896         case XML_SCHEMAS_IDREF:
00897         case XML_SCHEMAS_ENTITY:
00898         case XML_SCHEMAS_ANYURI:
00899         return (BAD_CAST val->value.str);
00900     default:
00901         break;
00902     }
00903     return (NULL);
00904 }
00905 
00914 int
00915 xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val)
00916 {    
00917     if ((val == NULL) || (val->type != XML_SCHEMAS_BOOLEAN))
00918     return (0);
00919     return (val->value.b);
00920 }
00921 
00935 xmlSchemaValPtr
00936 xmlSchemaNewStringValue(xmlSchemaValType type,
00937             const xmlChar *value)
00938 {
00939     xmlSchemaValPtr val;
00940 
00941     if (type != XML_SCHEMAS_STRING)
00942     return(NULL);
00943     val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal));
00944     if (val == NULL) {
00945     return(NULL);
00946     }
00947     memset(val, 0, sizeof(xmlSchemaVal));
00948     val->type = type;
00949     val->value.str = (xmlChar *) value;
00950     return(val);
00951 }
00952 
00963 xmlSchemaValPtr
00964 xmlSchemaNewNOTATIONValue(const xmlChar *name,
00965               const xmlChar *ns)
00966 {
00967     xmlSchemaValPtr val;
00968 
00969     val = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
00970     if (val == NULL)
00971     return (NULL);
00972 
00973     val->value.qname.name = (xmlChar *)name;
00974     if (ns != NULL)
00975     val->value.qname.uri = (xmlChar *)ns;
00976     return(val);
00977 }
00978 
00989 xmlSchemaValPtr
00990 xmlSchemaNewQNameValue(const xmlChar *namespaceName,
00991                const xmlChar *localName)
00992 {
00993     xmlSchemaValPtr val;
00994 
00995     val = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
00996     if (val == NULL)
00997     return (NULL);
00998 
00999     val->value.qname.name = (xmlChar *) localName;
01000     val->value.qname.uri = (xmlChar *) namespaceName;
01001     return(val);
01002 }
01003 
01010 void    
01011 xmlSchemaFreeValue(xmlSchemaValPtr value) {
01012     xmlSchemaValPtr prev;
01013 
01014     while (value != NULL) { 
01015     switch (value->type) {
01016         case XML_SCHEMAS_STRING:
01017         case XML_SCHEMAS_NORMSTRING:
01018         case XML_SCHEMAS_TOKEN:
01019         case XML_SCHEMAS_LANGUAGE:
01020         case XML_SCHEMAS_NMTOKEN:
01021         case XML_SCHEMAS_NMTOKENS:
01022         case XML_SCHEMAS_NAME:
01023         case XML_SCHEMAS_NCNAME:
01024         case XML_SCHEMAS_ID:
01025         case XML_SCHEMAS_IDREF:
01026         case XML_SCHEMAS_IDREFS:
01027         case XML_SCHEMAS_ENTITY:
01028         case XML_SCHEMAS_ENTITIES:        
01029         case XML_SCHEMAS_ANYURI:
01030         case XML_SCHEMAS_ANYSIMPLETYPE:
01031         if (value->value.str != NULL)
01032             xmlFree(value->value.str);
01033         break;
01034         case XML_SCHEMAS_NOTATION:
01035         case XML_SCHEMAS_QNAME:
01036         if (value->value.qname.uri != NULL)
01037             xmlFree(value->value.qname.uri);
01038         if (value->value.qname.name != NULL)
01039             xmlFree(value->value.qname.name);
01040         break;
01041         case XML_SCHEMAS_HEXBINARY:
01042         if (value->value.hex.str != NULL)
01043             xmlFree(value->value.hex.str);
01044         break;
01045         case XML_SCHEMAS_BASE64BINARY:
01046         if (value->value.base64.str != NULL)
01047             xmlFree(value->value.base64.str);
01048         break;
01049         default:
01050         break;
01051     }
01052     prev = value;
01053     value = value->next;
01054     xmlFree(prev);
01055     }    
01056 }
01057 
01067 xmlSchemaTypePtr
01068 xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) {
01069     if (xmlSchemaTypesInitialized == 0)
01070     xmlSchemaInitTypes();
01071     if (name == NULL)
01072     return(NULL);
01073     return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns));
01074 }
01075 
01085 xmlSchemaTypePtr
01086 xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type)
01087 {
01088     if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_BASIC))
01089     return (NULL);
01090     switch (type->builtInType) {
01091     case XML_SCHEMAS_NMTOKENS: 
01092         return (xmlSchemaTypeNmtokenDef );
01093     case XML_SCHEMAS_IDREFS: 
01094         return (xmlSchemaTypeIdrefDef);
01095     case XML_SCHEMAS_ENTITIES:
01096         return (xmlSchemaTypeEntityDef);
01097     default:
01098         return (NULL);
01099     }
01100 }
01101 
01102 /****************************************************************
01103  *                              *
01104  *      Convenience macros and functions        *
01105  *                              *
01106  ****************************************************************/
01107 
01108 #define IS_TZO_CHAR(c)                      \
01109     ((c == 0) || (c == 'Z') || (c == '+') || (c == '-'))
01110 
01111 #define VALID_YEAR(yr)          (yr != 0)
01112 #define VALID_MONTH(mon)        ((mon >= 1) && (mon <= 12))
01113 /* VALID_DAY should only be used when month is unknown */
01114 #define VALID_DAY(day)          ((day >= 1) && (day <= 31))
01115 #define VALID_HOUR(hr)          ((hr >= 0) && (hr <= 23))
01116 #define VALID_MIN(min)          ((min >= 0) && (min <= 59))
01117 #define VALID_SEC(sec)          ((sec >= 0) && (sec < 60))
01118 #define VALID_TZO(tzo)          ((tzo > -840) && (tzo < 840))
01119 #define IS_LEAP(y)                      \
01120     (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))
01121 
01122 static const unsigned int daysInMonth[12] =
01123     { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
01124 static const unsigned int daysInMonthLeap[12] =
01125     { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
01126 
01127 #define MAX_DAYINMONTH(yr,mon)                                  \
01128         (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1])
01129 
01130 #define VALID_MDAY(dt)                      \
01131     (IS_LEAP(dt->year) ?                        \
01132         (dt->day <= daysInMonthLeap[dt->mon - 1]) :         \
01133         (dt->day <= daysInMonth[dt->mon - 1]))
01134 
01135 #define VALID_DATE(dt)                      \
01136     (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt))
01137 
01138 #define VALID_TIME(dt)                      \
01139     (VALID_HOUR(dt->hour) && VALID_MIN(dt->min) &&      \
01140      VALID_SEC(dt->sec) && VALID_TZO(dt->tzo))
01141 
01142 #define VALID_DATETIME(dt)                  \
01143     (VALID_DATE(dt) && VALID_TIME(dt))
01144 
01145 #define SECS_PER_MIN            (60)
01146 #define SECS_PER_HOUR           (60 * SECS_PER_MIN)
01147 #define SECS_PER_DAY            (24 * SECS_PER_HOUR)
01148 
01149 static const long dayInYearByMonth[12] =
01150     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
01151 static const long dayInLeapYearByMonth[12] =
01152     { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
01153 
01154 #define DAY_IN_YEAR(day, month, year)               \
01155         ((IS_LEAP(year) ?                   \
01156                 dayInLeapYearByMonth[month - 1] :       \
01157                 dayInYearByMonth[month - 1]) + day)
01158 
01159 #ifdef DEBUG
01160 #define DEBUG_DATE(dt)                                                  \
01161     xmlGenericError(xmlGenericErrorContext,                             \
01162         "type=%o %04ld-%02u-%02uT%02u:%02u:%03f",                       \
01163         dt->type,dt->value.date.year,dt->value.date.mon,                \
01164         dt->value.date.day,dt->value.date.hour,dt->value.date.min,      \
01165         dt->value.date.sec);                                            \
01166     if (dt->value.date.tz_flag)                                         \
01167         if (dt->value.date.tzo != 0)                                    \
01168             xmlGenericError(xmlGenericErrorContext,                     \
01169                 "%+05d\n",dt->value.date.tzo);                          \
01170         else                                                            \
01171             xmlGenericError(xmlGenericErrorContext, "Z\n");             \
01172     else                                                                \
01173         xmlGenericError(xmlGenericErrorContext,"\n")
01174 #else
01175 #define DEBUG_DATE(dt)
01176 #endif
01177 
01190 static int
01191 _xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) {
01192     const xmlChar *cur = *str, *firstChar;
01193     int isneg = 0, digcnt = 0;
01194 
01195     if (((*cur < '0') || (*cur > '9')) &&
01196     (*cur != '-') && (*cur != '+'))
01197     return -1;
01198 
01199     if (*cur == '-') {
01200     isneg = 1;
01201     cur++;
01202     }
01203 
01204     firstChar = cur;
01205 
01206     while ((*cur >= '0') && (*cur <= '9')) {
01207     dt->year = dt->year * 10 + (*cur - '0');
01208     cur++;
01209     digcnt++;
01210     }
01211 
01212     /* year must be at least 4 digits (CCYY); over 4
01213      * digits cannot have a leading zero. */
01214     if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0')))
01215     return 1;
01216 
01217     if (isneg)
01218     dt->year = - dt->year;
01219 
01220     if (!VALID_YEAR(dt->year))
01221     return 2;
01222 
01223     *str = cur;
01224     return 0;
01225 }
01226 
01238 #define PARSE_2_DIGITS(num, cur, invalid)           \
01239     if ((cur[0] < '0') || (cur[0] > '9') ||         \
01240         (cur[1] < '0') || (cur[1] > '9'))           \
01241         invalid = 1;                    \
01242     else                            \
01243         num = (cur[0] - '0') * 10 + (cur[1] - '0');     \
01244     cur += 2;
01245 
01258 #define PARSE_FLOAT(num, cur, invalid)              \
01259     PARSE_2_DIGITS(num, cur, invalid);          \
01260     if (!invalid && (*cur == '.')) {            \
01261         double mult = 1;                        \
01262         cur++;                      \
01263         if ((*cur < '0') || (*cur > '9'))           \
01264         invalid = 1;                    \
01265         while ((*cur >= '0') && (*cur <= '9')) {        \
01266         mult /= 10;                 \
01267         num += (*cur - '0') * mult;         \
01268         cur++;                      \
01269         }                           \
01270     }
01271 
01283 static int
01284 _xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) {
01285     const xmlChar *cur = *str;
01286     int ret = 0;
01287     unsigned int value = 0;
01288 
01289     PARSE_2_DIGITS(value, cur, ret);
01290     if (ret != 0)
01291     return ret;
01292 
01293     if (!VALID_MONTH(value))
01294     return 2;
01295 
01296     dt->mon = value;
01297 
01298     *str = cur;
01299     return 0;
01300 }
01301 
01313 static int
01314 _xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) {
01315     const xmlChar *cur = *str;
01316     int ret = 0;
01317     unsigned int value = 0;
01318 
01319     PARSE_2_DIGITS(value, cur, ret);
01320     if (ret != 0)
01321     return ret;
01322 
01323     if (!VALID_DAY(value))
01324     return 2;
01325 
01326     dt->day = value;
01327     *str = cur;
01328     return 0;
01329 }
01330 
01343 static int
01344 _xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) {
01345     const xmlChar *cur = *str;    
01346     int ret = 0;
01347     int value = 0;
01348 
01349     PARSE_2_DIGITS(value, cur, ret);
01350     if (ret != 0)
01351     return ret;    
01352     if (*cur != ':')
01353     return 1;
01354     if (!VALID_HOUR(value))
01355     return 2;
01356     cur++;
01357 
01358     /* the ':' insures this string is xs:time */
01359     dt->hour = value;
01360 
01361     PARSE_2_DIGITS(value, cur, ret);
01362     if (ret != 0)
01363     return ret;
01364     if (!VALID_MIN(value))
01365     return 2;
01366     dt->min = value;
01367 
01368     if (*cur != ':')
01369     return 1;
01370     cur++;
01371 
01372     PARSE_FLOAT(dt->sec, cur, ret);
01373     if (ret != 0)
01374     return ret;
01375 
01376     if ((!VALID_SEC(dt->sec)) || (!VALID_TZO(dt->tzo)))
01377     return 2;
01378 
01379     *str = cur;
01380     return 0;
01381 }
01382 
01394 static int
01395 _xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) {
01396     const xmlChar *cur;
01397     int ret = 0;
01398 
01399     if (str == NULL)
01400     return -1;
01401     cur = *str;
01402 
01403     switch (*cur) {
01404     case 0:
01405     dt->tz_flag = 0;
01406     dt->tzo = 0;
01407     break;
01408 
01409     case 'Z':
01410     dt->tz_flag = 1;
01411     dt->tzo = 0;
01412     cur++;
01413     break;
01414 
01415     case '+':
01416     case '-': {
01417     int isneg = 0, tmp = 0;
01418     isneg = (*cur == '-');
01419 
01420     cur++;
01421 
01422     PARSE_2_DIGITS(tmp, cur, ret);
01423     if (ret != 0)
01424         return ret;
01425     if (!VALID_HOUR(tmp))
01426         return 2;
01427 
01428     if (*cur != ':')
01429         return 1;
01430     cur++;
01431 
01432     dt->tzo = tmp * 60;
01433 
01434     PARSE_2_DIGITS(tmp, cur, ret);
01435     if (ret != 0)
01436         return ret;
01437     if (!VALID_MIN(tmp))
01438         return 2;
01439 
01440     dt->tzo += tmp;
01441     if (isneg)
01442         dt->tzo = - dt->tzo;
01443 
01444     if (!VALID_TZO(dt->tzo))
01445         return 2;
01446 
01447     dt->tz_flag = 1;
01448     break;
01449       }
01450     default:
01451     return 1;
01452     }
01453 
01454     *str = cur;
01455     return 0;
01456 }
01457 
01466 static int
01467 _xmlSchemaBase64Decode (const xmlChar ch) {
01468     if (('A' <= ch) && (ch <= 'Z')) return ch - 'A';
01469     if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26;
01470     if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52;
01471     if ('+' == ch) return 62;
01472     if ('/' == ch) return 63;
01473     if ('=' == ch) return 64;
01474     return -1;
01475 }
01476 
01477 /****************************************************************
01478  *                              *
01479  *  XML Schema Dates/Times Datatypes Handling       *
01480  *                              *
01481  ****************************************************************/
01482 
01494 #define PARSE_DIGITS(num, cur, num_type)                    \
01495     if ((*cur < '0') || (*cur > '9'))           \
01496         num_type = -1;                  \
01497         else                                                    \
01498         while ((*cur >= '0') && (*cur <= '9')) {        \
01499             num = num * 10 + (*cur - '0');              \
01500             cur++;                                          \
01501             }
01502 
01516 #define PARSE_NUM(num, cur, num_type)               \
01517         num = 0;                                                \
01518     PARSE_DIGITS(num, cur, num_type);                   \
01519     if (!num_type && (*cur == '.')) {           \
01520         double mult = 1;                        \
01521         cur++;                      \
01522         if ((*cur < '0') || (*cur > '9'))           \
01523         num_type = -1;                  \
01524             else                                                \
01525                 num_type = 1;                                   \
01526         while ((*cur >= '0') && (*cur <= '9')) {        \
01527         mult /= 10;                 \
01528         num += (*cur - '0') * mult;         \
01529         cur++;                      \
01530         }                           \
01531     }
01532 
01545 static int
01546 xmlSchemaValidateDates (xmlSchemaValType type,
01547                     const xmlChar *dateTime, xmlSchemaValPtr *val,
01548             int collapse) {
01549     xmlSchemaValPtr dt;
01550     int ret;
01551     const xmlChar *cur = dateTime;
01552 
01553 #define RETURN_TYPE_IF_VALID(t)                 \
01554     if (IS_TZO_CHAR(*cur)) {                    \
01555     ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); \
01556     if (ret == 0) {                     \
01557         if (*cur != 0)                  \
01558         goto error;                 \
01559         dt->type = t;                   \
01560         goto done;                      \
01561     }                           \
01562     }
01563 
01564     if (dateTime == NULL)
01565     return -1;
01566 
01567     if (collapse)
01568     while IS_WSP_BLANK_CH(*cur) cur++;
01569 
01570     if ((*cur != '-') && (*cur < '0') && (*cur > '9'))
01571     return 1;
01572 
01573     dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN);
01574     if (dt == NULL)
01575     return -1;
01576 
01577     if ((cur[0] == '-') && (cur[1] == '-')) {
01578     /*
01579      * It's an incomplete date (xs:gMonthDay, xs:gMonth or
01580      * xs:gDay)
01581      */
01582     cur += 2;
01583 
01584     /* is it an xs:gDay? */
01585     if (*cur == '-') {
01586         if (type == XML_SCHEMAS_GMONTH)
01587         goto error;
01588       ++cur;
01589         ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
01590         if (ret != 0)
01591         goto error;
01592 
01593         RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY);
01594 
01595         goto error;
01596     }
01597 
01598     /*
01599      * it should be an xs:gMonthDay or xs:gMonth
01600      */
01601     ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
01602     if (ret != 0)
01603         goto error;
01604 
01605         /*
01606          * a '-' char could indicate this type is xs:gMonthDay or
01607          * a negative time zone offset. Check for xs:gMonthDay first.
01608          * Also the first three char's of a negative tzo (-MM:SS) can
01609          * appear to be a valid day; so even if the day portion
01610          * of the xs:gMonthDay verifies, we must insure it was not
01611          * a tzo.
01612          */
01613         if (*cur == '-') {
01614             const xmlChar *rewnd = cur;
01615             cur++;
01616 
01617         ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
01618             if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) {
01619 
01620                 /*
01621                  * we can use the VALID_MDAY macro to validate the month
01622                  * and day because the leap year test will flag year zero
01623                  * as a leap year (even though zero is an invalid year).
01624          * FUTURE TODO: Zero will become valid in XML Schema 1.1
01625          * probably.
01626                  */
01627                 if (VALID_MDAY((&(dt->value.date)))) {
01628 
01629                 RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
01630 
01631                     goto error;
01632                 }
01633             }
01634 
01635             /*
01636              * not xs:gMonthDay so rewind and check if just xs:gMonth
01637              * with an optional time zone.
01638              */
01639             cur = rewnd;
01640         }
01641 
01642     RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
01643 
01644     goto error;
01645     }
01646 
01647     /*
01648      * It's a right-truncated date or an xs:time.
01649      * Try to parse an xs:time then fallback on right-truncated dates.
01650      */
01651     if ((*cur >= '0') && (*cur <= '9')) {
01652     ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
01653     if (ret == 0) {
01654         /* it's an xs:time */
01655         RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME);
01656     }
01657     }
01658 
01659     /* fallback on date parsing */
01660     cur = dateTime;
01661 
01662     ret = _xmlSchemaParseGYear(&(dt->value.date), &cur);
01663     if (ret != 0)
01664     goto error;
01665 
01666     /* is it an xs:gYear? */
01667     RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR);
01668 
01669     if (*cur != '-')
01670     goto error;
01671     cur++;
01672 
01673     ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur);
01674     if (ret != 0)
01675     goto error;
01676 
01677     /* is it an xs:gYearMonth? */
01678     RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH);
01679 
01680     if (*cur != '-')
01681     goto error;
01682     cur++;
01683 
01684     ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
01685     if ((ret != 0) || !VALID_DATE((&(dt->value.date))))
01686     goto error;
01687 
01688     /* is it an xs:date? */
01689     RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE);
01690 
01691     if (*cur != 'T')
01692     goto error;
01693     cur++;
01694 
01695     /* it should be an xs:dateTime */
01696     ret = _xmlSchemaParseTime(&(dt->value.date), &cur);
01697     if (ret != 0)
01698     goto error;
01699 
01700     ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur);
01701     if (collapse)
01702     while IS_WSP_BLANK_CH(*cur) cur++;
01703     if ((ret != 0) || (*cur != 0) || (!(VALID_DATETIME((&(dt->value.date))))))
01704     goto error;
01705 
01706 
01707     dt->type = XML_SCHEMAS_DATETIME;
01708 
01709 done:
01710 #if 1
01711     if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
01712         goto error;
01713 #else
01714     /*
01715      * insure the parsed type is equal to or less significant (right
01716      * truncated) than the desired type.
01717      */
01718     if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) {
01719 
01720         /* time only matches time */
01721         if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME))
01722             goto error;
01723 
01724         if ((type == XML_SCHEMAS_DATETIME) &&
01725             ((dt->type != XML_SCHEMAS_DATE) ||
01726              (dt->type != XML_SCHEMAS_GYEARMONTH) ||
01727              (dt->type != XML_SCHEMAS_GYEAR)))
01728             goto error;
01729 
01730         if ((type == XML_SCHEMAS_DATE) &&
01731             ((dt->type != XML_SCHEMAS_GYEAR) ||
01732              (dt->type != XML_SCHEMAS_GYEARMONTH)))
01733             goto error;
01734 
01735         if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
01736             goto error;
01737 
01738         if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
01739             goto error;
01740     }
01741 #endif
01742 
01743     if (val != NULL)
01744         *val = dt;
01745     else
01746     xmlSchemaFreeValue(dt);
01747 
01748     return 0;
01749 
01750 error:
01751     if (dt != NULL)
01752     xmlSchemaFreeValue(dt);
01753     return 1;
01754 }
01755 
01768 static int
01769 xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
01770                        const xmlChar *duration, xmlSchemaValPtr *val,
01771                int collapse) {
01772     const xmlChar  *cur = duration;
01773     xmlSchemaValPtr dur;
01774     int isneg = 0;
01775     unsigned int seq = 0;
01776     double         num;
01777     int            num_type = 0;  /* -1 = invalid, 0 = int, 1 = floating */
01778     const xmlChar  desig[]  = {'Y', 'M', 'D', 'H', 'M', 'S'};
01779     const double   multi[]  = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
01780 
01781     if (duration == NULL)
01782     return -1;
01783 
01784     if (collapse)
01785     while IS_WSP_BLANK_CH(*cur) cur++;
01786 
01787     if (*cur == '-') {
01788         isneg = 1;
01789         cur++;
01790     }
01791 
01792     /* duration must start with 'P' (after sign) */
01793     if (*cur++ != 'P')
01794     return 1;
01795 
01796     if (*cur == 0)
01797     return 1;
01798 
01799     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
01800     if (dur == NULL)
01801     return -1;
01802 
01803     while (*cur != 0) {
01804 
01805         /* input string should be empty or invalid date/time item */
01806         if (seq >= sizeof(desig))
01807             goto error;
01808 
01809         /* T designator must be present for time items */
01810         if (*cur == 'T') {
01811             if (seq <= 3) {
01812                 seq = 3;
01813                 cur++;
01814             } else
01815                 return 1;
01816         } else if (seq == 3)
01817             goto error;
01818 
01819         /* parse the number portion of the item */
01820         PARSE_NUM(num, cur, num_type);
01821 
01822         if ((num_type == -1) || (*cur == 0))
01823             goto error;
01824 
01825         /* update duration based on item type */
01826         while (seq < sizeof(desig)) {
01827             if (*cur == desig[seq]) {
01828 
01829                 /* verify numeric type; only seconds can be float */
01830                 if ((num_type != 0) && (seq < (sizeof(desig)-1)))
01831                     goto error;
01832 
01833                 switch (seq) {
01834                     case 0:
01835                         dur->value.dur.mon = (long)num * 12;
01836                         break;
01837                     case 1:
01838                         dur->value.dur.mon += (long)num;
01839                         break;
01840                     default:
01841                         /* convert to seconds using multiplier */
01842                         dur->value.dur.sec += num * multi[seq];
01843                         seq++;
01844                         break;
01845                 }
01846 
01847                 break;          /* exit loop */
01848             }
01849             /* no date designators found? */
01850             if ((++seq == 3) || (seq == 6))
01851                 goto error;
01852         }
01853     cur++;
01854     if (collapse)
01855         while IS_WSP_BLANK_CH(*cur) cur++;        
01856     }
01857 
01858     if (isneg) {
01859         dur->value.dur.mon = -dur->value.dur.mon;
01860         dur->value.dur.day = -dur->value.dur.day;
01861         dur->value.dur.sec = -dur->value.dur.sec;
01862     }
01863 
01864     if (val != NULL)
01865         *val = dur;
01866     else
01867     xmlSchemaFreeValue(dur);
01868 
01869     return 0;
01870 
01871 error:
01872     if (dur != NULL)
01873     xmlSchemaFreeValue(dur);
01874     return 1;
01875 }
01876 
01885 static xmlChar *
01886 xmlSchemaStrip(const xmlChar *value) {
01887     const xmlChar *start = value, *end, *f;
01888 
01889     if (value == NULL) return(NULL);
01890     while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
01891     end = start;
01892     while (*end != 0) end++;
01893     f = end;
01894     end--;
01895     while ((end > start) && (IS_BLANK_CH(*end))) end--;
01896     end++;
01897     if ((start == value) && (f == end)) return(NULL);
01898     return(xmlStrndup(start, end - start));
01899 }
01900 
01909 xmlChar *
01910 xmlSchemaWhiteSpaceReplace(const xmlChar *value) {
01911     const xmlChar *cur = value;    
01912     xmlChar *ret = NULL, *mcur; 
01913 
01914     if (value == NULL) 
01915     return(NULL);
01916     
01917     while ((*cur != 0) && 
01918     (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) {
01919     cur++;
01920     }
01921     if (*cur == 0)
01922     return (NULL);
01923     ret = xmlStrdup(value);
01924     /* TODO FIXME: I guess gcc will bark at this. */
01925     mcur = (xmlChar *)  (ret + (cur - value));
01926     do {
01927     if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) )
01928         *mcur = ' ';
01929     mcur++;
01930     } while (*mcur != 0);       
01931     return(ret);
01932 }
01933 
01942 xmlChar *
01943 xmlSchemaCollapseString(const xmlChar *value) {
01944     const xmlChar *start = value, *end, *f;
01945     xmlChar *g;
01946     int col = 0;
01947 
01948     if (value == NULL) return(NULL);
01949     while ((*start != 0) && (IS_BLANK_CH(*start))) start++;
01950     end = start;
01951     while (*end != 0) {
01952     if ((*end == ' ') && (IS_BLANK_CH(end[1]))) {
01953         col = end - start;
01954         break;
01955     } else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) {
01956         col = end - start;
01957         break;
01958     }
01959     end++;
01960     }
01961     if (col == 0) {
01962     f = end;
01963     end--;
01964     while ((end > start) && (IS_BLANK_CH(*end))) end--;
01965     end++;
01966     if ((start == value) && (f == end)) return(NULL);
01967     return(xmlStrndup(start, end - start));
01968     }
01969     start = xmlStrdup(start);
01970     if (start == NULL) return(NULL);
01971     g = (xmlChar *) (start + col);
01972     end = g;
01973     while (*end != 0) {
01974     if (IS_BLANK_CH(*end)) {
01975         end++;
01976         while (IS_BLANK_CH(*end)) end++;
01977         if (*end != 0)
01978         *g++ = ' ';
01979     } else
01980         *g++ = *end++;
01981     }
01982     *g = 0;
01983     return((xmlChar *) start);
01984 }
01985 
01999 static int
02000 xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value,
02001                        xmlSchemaValPtr *ret, xmlNodePtr node) {
02002     xmlChar *val, *cur, *endval;
02003     int nb_values = 0;
02004     int tmp = 0;
02005 
02006     if (value == NULL) {
02007     return(-1);
02008     }
02009     val = xmlStrdup(value);
02010     if (val == NULL) {
02011     return(-1);
02012     }
02013     if (ret != NULL) {
02014         *ret = NULL;
02015     }
02016     cur = val;
02017     /*
02018      * Split the list
02019      */
02020     while (IS_BLANK_CH(*cur)) *cur++ = 0;
02021     while (*cur != 0) {
02022     if (IS_BLANK_CH(*cur)) {
02023         *cur = 0;
02024         cur++;
02025         while (IS_BLANK_CH(*cur)) *cur++ = 0;
02026     } else {
02027         nb_values++;
02028         cur++;
02029         while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++;
02030     }
02031     }
02032     if (nb_values == 0) {
02033     xmlFree(val);
02034     return(nb_values);
02035     }
02036     endval = cur;
02037     cur = val;
02038     while ((*cur == 0) && (cur != endval)) cur++;
02039     while (cur != endval) {
02040     tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node);
02041     if (tmp != 0)
02042         break;
02043     while (*cur != 0) cur++;
02044     while ((*cur == 0) && (cur != endval)) cur++;
02045     }
02046     /* TODO what return value ? c.f. bug #158628
02047     if (ret != NULL) {
02048     TODO
02049     } */
02050     xmlFree(val);
02051     if (tmp == 0)
02052     return(nb_values);
02053     return(-1);
02054 }
02055 
02068 static int
02069 xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo,
02070                    unsigned long *lmi, unsigned long *lhi) {
02071     unsigned long lo = 0, mi = 0, hi = 0;
02072     const xmlChar *tmp, *cur = *str;
02073     int ret = 0, i = 0;
02074 
02075     if (!((*cur >= '0') && (*cur <= '9'))) 
02076         return(-2);
02077 
02078     while (*cur == '0') {        /* ignore leading zeroes */
02079         cur++;
02080     }
02081     tmp = cur;
02082     while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) {
02083         i++;tmp++;ret++;
02084     }
02085     if (i > 24) {
02086         *str = tmp;
02087         return(-1);
02088     }
02089     while (i > 16) {
02090         hi = hi * 10 + (*cur++ - '0');
02091         i--;
02092     }
02093     while (i > 8) {
02094         mi = mi * 10 + (*cur++ - '0');
02095         i--;
02096     }
02097     while (i > 0) {
02098         lo = lo * 10 + (*cur++ - '0');
02099         i--;
02100     }
02101 
02102     *str = cur;
02103     *llo = lo;
02104     *lmi = mi;
02105     *lhi = hi;
02106     return(ret);
02107 }
02108 
02124 static int
02125 xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value,
02126                        xmlSchemaValPtr * val, xmlNodePtr node, int flags,
02127                xmlSchemaWhitespaceValueType ws,
02128                int normOnTheFly, int applyNorm, int createStringValue)
02129 {
02130     xmlSchemaValPtr v;
02131     xmlChar *norm = NULL;
02132     int ret = 0;
02133 
02134     if (xmlSchemaTypesInitialized == 0)
02135         xmlSchemaInitTypes();
02136     if (type == NULL)
02137         return (-1);
02138 
02139     /*
02140      * validating a non existant text node is similar to validating
02141      * an empty one.
02142      */
02143     if (value == NULL)
02144         value = BAD_CAST "";
02145 
02146     if (val != NULL)
02147         *val = NULL;
02148     if ((flags == 0) && (value != NULL)) {
02149 
02150         if ((type->builtInType != XML_SCHEMAS_STRING) &&
02151       (type->builtInType != XML_SCHEMAS_ANYTYPE) && 
02152       (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) {
02153         if (type->builtInType == XML_SCHEMAS_NORMSTRING)
02154         norm = xmlSchemaWhiteSpaceReplace(value);
02155             else
02156         norm = xmlSchemaCollapseString(value);
02157             if (norm != NULL)
02158                 value = norm;
02159         }
02160     }
02161 
02162     switch (type->builtInType) {
02163         case XML_SCHEMAS_UNKNOWN:            
02164             goto error;
02165     case XML_SCHEMAS_ANYTYPE:
02166     case XML_SCHEMAS_ANYSIMPLETYPE:
02167         if ((createStringValue) && (val != NULL)) {
02168         v = xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE);
02169         if (v != NULL) {
02170             v->value.str = xmlStrdup(value);
02171             *val = v;
02172         } else {
02173             goto error;
02174         }       
02175         }
02176         goto return0;
02177         case XML_SCHEMAS_STRING:        
02178         if (! normOnTheFly) {
02179         const xmlChar *cur = value;
02180 
02181         if (ws == XML_SCHEMA_WHITESPACE_REPLACE) {
02182             while (*cur != 0) {
02183             if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
02184                 goto return1;
02185             } else {
02186                 cur++;
02187             }
02188             }
02189         } else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
02190             while (*cur != 0) {
02191             if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
02192                 goto return1;
02193             } else if IS_WSP_SPACE_CH(*cur) {
02194                 cur++;
02195                 if IS_WSP_SPACE_CH(*cur)
02196                 goto return1;
02197             } else {
02198                 cur++;
02199             }
02200             }
02201         }
02202         }
02203         if (createStringValue && (val != NULL)) {
02204         if (applyNorm) {
02205             if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
02206             norm = xmlSchemaCollapseString(value);
02207             else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
02208             norm = xmlSchemaWhiteSpaceReplace(value);
02209             if (norm != NULL)
02210             value = norm;
02211         }
02212         v = xmlSchemaNewValue(XML_SCHEMAS_STRING);
02213         if (v != NULL) {
02214             v->value.str = xmlStrdup(value);
02215             *val = v;
02216         } else {
02217             goto error;
02218         }
02219         }
02220             goto return0;
02221         case XML_SCHEMAS_NORMSTRING:{
02222         if (normOnTheFly) {
02223             if (applyNorm) {
02224             if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
02225                 norm = xmlSchemaCollapseString(value);
02226             else
02227                 norm = xmlSchemaWhiteSpaceReplace(value);
02228             if (norm != NULL)
02229                 value = norm;
02230             }
02231         } else {
02232             const xmlChar *cur = value;
02233             while (*cur != 0) {
02234             if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
02235                 goto return1;
02236             } else {
02237                 cur++;
02238             }
02239             }
02240         }
02241                 if (val != NULL) {
02242                     v = xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING);
02243                     if (v != NULL) {
02244                         v->value.str = xmlStrdup(value);
02245                         *val = v;
02246                     } else {
02247                         goto error;
02248                     }
02249                 }
02250                 goto return0;
02251             }
02252         case XML_SCHEMAS_DECIMAL:{
02253                 const xmlChar *cur = value;
02254                 unsigned int len, neg, integ, hasLeadingZeroes;
02255         xmlChar cval[25];
02256         xmlChar *cptr = cval;       
02257 
02258                 if ((cur == NULL) || (*cur == 0))
02259                     goto return1;
02260 
02261         /*
02262         * xs:decimal has a whitespace-facet value of 'collapse'.
02263         */
02264         if (normOnTheFly)
02265             while IS_WSP_BLANK_CH(*cur) cur++;
02266 
02267         /*
02268         * First we handle an optional sign.
02269         */
02270         neg = 0;
02271                 if (*cur == '-') {
02272             neg = 1;
02273                     cur++;
02274         } else if (*cur == '+')
02275                     cur++;
02276         /*
02277         * Disallow: "", "-", "- "
02278         */
02279         if (*cur == 0)
02280             goto return1;
02281         /*
02282          * Next we "pre-parse" the number, in preparation for calling
02283          * the common routine xmlSchemaParseUInt.  We get rid of any
02284          * leading zeroes (because we have reserved only 25 chars),
02285          * and note the position of a decimal point.
02286          */
02287         len = 0;
02288         integ = ~0u;
02289         hasLeadingZeroes = 0;
02290         /*
02291         * Skip leading zeroes.
02292         */
02293         while (*cur == '0') {
02294             cur++;
02295             hasLeadingZeroes = 1;
02296         }
02297         if (*cur != 0) {
02298             do {
02299             if ((*cur >= '0') && (*cur <= '9')) {
02300                 *cptr++ = *cur++;
02301                 len++;
02302             } else if (*cur == '.') {
02303                 cur++;
02304                 integ = len;
02305                 do {
02306                 if ((*cur >= '0') && (*cur <= '9')) {
02307                     *cptr++ = *cur++;
02308                     len++;
02309                 } else
02310                     break;
02311                 } while (len < 24);
02312                 /*
02313                 * Disallow "." but allow "00."
02314                 */
02315                 if ((len == 0) && (!hasLeadingZeroes))
02316                 goto return1;
02317                 break;
02318             } else
02319                 break;
02320             } while (len < 24);
02321         }
02322         if (normOnTheFly)
02323             while IS_WSP_BLANK_CH(*cur) cur++;
02324         if (*cur != 0)
02325             goto return1; /* error if any extraneous chars */
02326                 if (val != NULL) {
02327                     v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL);
02328                     if (v != NULL) {
02329             /*
02330             * Now evaluate the significant digits of the number
02331             */
02332             if (len != 0) {
02333                 
02334                 if (integ != ~0u) {
02335                 /*
02336                 * Get rid of trailing zeroes in the
02337                 * fractional part.
02338                 */
02339                 while ((len != integ) && (*(cptr-1) == '0')) {
02340                     cptr--;
02341                     len--;
02342                 }
02343                 }
02344                 /*
02345                 * Terminate the (preparsed) string.
02346                 */
02347                 if (len != 0) {
02348                 *cptr = 0;
02349                 cptr = cval;
02350 
02351                 xmlSchemaParseUInt((const xmlChar **)&cptr,
02352                     &v->value.decimal.lo,
02353                     &v->value.decimal.mi,
02354                     &v->value.decimal.hi);
02355                 }
02356             }
02357             /*
02358             * Set the total digits to 1 if a zero value.
02359             */
02360                         v->value.decimal.sign = neg;
02361             if (len == 0) {
02362                 /* Speedup for zero values. */
02363                 v->value.decimal.total = 1;
02364             } else {
02365                 v->value.decimal.total = len;
02366                 if (integ == ~0u)
02367                 v->value.decimal.frac = 0;
02368                 else
02369                 v->value.decimal.frac = len - integ;
02370             }
02371                         *val = v;
02372                     }
02373                 }
02374                 goto return0;
02375             }
02376         case XML_SCHEMAS_TIME:
02377         case XML_SCHEMAS_GDAY:
02378         case XML_SCHEMAS_GMONTH:
02379         case XML_SCHEMAS_GMONTHDAY:
02380         case XML_SCHEMAS_GYEAR:
02381         case XML_SCHEMAS_GYEARMONTH:
02382         case XML_SCHEMAS_DATE:
02383         case XML_SCHEMAS_DATETIME:
02384             ret = xmlSchemaValidateDates(type->builtInType, value, val,
02385         normOnTheFly);
02386             break;
02387         case XML_SCHEMAS_DURATION:
02388             ret = xmlSchemaValidateDuration(type, value, val,
02389         normOnTheFly);
02390             break;
02391         case XML_SCHEMAS_FLOAT:
02392         case XML_SCHEMAS_DOUBLE: {
02393                 const xmlChar *cur = value;
02394                 int neg = 0;
02395                 int digits_before = 0;
02396                 int digits_after = 0;
02397 
02398         if (normOnTheFly)
02399             while IS_WSP_BLANK_CH(*cur) cur++;
02400 
02401                 if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) {
02402                     cur += 3;
02403                     if (*cur != 0)
02404                         goto return1;
02405                     if (val != NULL) {
02406                         if (type == xmlSchemaTypeFloatDef) {
02407                             v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
02408                             if (v != NULL) {
02409                                 v->value.f = (float) xmlXPathNAN;
02410                             } else {
02411                                 xmlSchemaFreeValue(v);
02412                                 goto error;
02413                             }
02414                         } else {
02415                             v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
02416                             if (v != NULL) {
02417                                 v->value.d = xmlXPathNAN;
02418                             } else {
02419                                 xmlSchemaFreeValue(v);
02420                                 goto error;
02421                             }
02422                         }
02423                         *val = v;
02424                     }
02425                     goto return0;
02426                 }
02427                 if (*cur == '-') {
02428                     neg = 1;
02429                     cur++;
02430                 }
02431                 if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) {
02432                     cur += 3;
02433                     if (*cur != 0)
02434                         goto return1;
02435                     if (val != NULL) {
02436                         if (type == xmlSchemaTypeFloatDef) {
02437                             v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
02438                             if (v != NULL) {
02439                                 if (neg)
02440                                     v->value.f = (float) xmlXPathNINF;
02441                                 else
02442                                     v->value.f = (float) xmlXPathPINF;
02443                             } else {
02444                                 xmlSchemaFreeValue(v);
02445                                 goto error;
02446                             }
02447                         } else {
02448                             v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
02449                             if (v != NULL) {
02450                                 if (neg)
02451                                     v->value.d = xmlXPathNINF;
02452                                 else
02453                                     v->value.d = xmlXPathPINF;
02454                             } else {
02455                                 xmlSchemaFreeValue(v);
02456                                 goto error;
02457                             }
02458                         }
02459                         *val = v;
02460                     }
02461                     goto return0;
02462                 }
02463                 if ((neg == 0) && (*cur == '+'))
02464                     cur++;
02465                 if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-'))
02466                     goto return1;
02467                 while ((*cur >= '0') && (*cur <= '9')) {
02468                     cur++;
02469                     digits_before++;
02470                 }
02471                 if (*cur == '.') {
02472                     cur++;
02473                     while ((*cur >= '0') && (*cur <= '9')) {
02474                         cur++;
02475                         digits_after++;
02476                     }
02477                 }
02478                 if ((digits_before == 0) && (digits_after == 0))
02479                     goto return1;
02480                 if ((*cur == 'e') || (*cur == 'E')) {
02481                     cur++;
02482                     if ((*cur == '-') || (*cur == '+'))
02483                         cur++;
02484                     while ((*cur >= '0') && (*cur <= '9'))
02485                         cur++;
02486                 }
02487         if (normOnTheFly)
02488             while IS_WSP_BLANK_CH(*cur) cur++;
02489 
02490                 if (*cur != 0)
02491                     goto return1;
02492                 if (val != NULL) {
02493                     if (type == xmlSchemaTypeFloatDef) {
02494                         v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT);
02495                         if (v != NULL) {
02496                 /*
02497                 * TODO: sscanf seems not to give the correct
02498                 * value for extremely high/low values.
02499                 * E.g. "1E-149" results in zero.
02500                 */
02501                             if (sscanf((const char *) value, "%f",
02502                                  &(v->value.f)) == 1) {
02503                                 *val = v;
02504                             } else {
02505                                 xmlSchemaFreeValue(v);
02506                                 goto return1;
02507                             }
02508                         } else {
02509                             goto error;
02510                         }
02511                     } else {
02512                         v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE);
02513                         if (v != NULL) {
02514                 /*
02515                 * TODO: sscanf seems not to give the correct
02516                 * value for extremely high/low values.
02517                 */
02518                             if (sscanf((const char *) value, "%lf",
02519                                  &(v->value.d)) == 1) {
02520                                 *val = v;
02521                             } else {
02522                                 xmlSchemaFreeValue(v);
02523                                 goto return1;
02524                             }
02525                         } else {
02526                             goto error;
02527                         }
02528                     }
02529                 }
02530                 goto return0;
02531             }
02532         case XML_SCHEMAS_BOOLEAN:{
02533                 const xmlChar *cur = value;
02534 
02535         if (normOnTheFly) {
02536             while IS_WSP_BLANK_CH(*cur) cur++;
02537             if (*cur == '0') {
02538             ret = 0;
02539             cur++;
02540             } else if (*cur == '1') {
02541             ret = 1;
02542             cur++;
02543             } else if (*cur == 't') {
02544             cur++;
02545             if ((*cur++ == 'r') && (*cur++ == 'u') &&
02546                 (*cur++ == 'e')) {
02547                 ret = 1;
02548             } else
02549                 goto return1;
02550             } else if (*cur == 'f') {
02551             cur++;
02552             if ((*cur++ == 'a') && (*cur++ == 'l') &&
02553                 (*cur++ == 's') && (*cur++ == 'e')) {
02554                 ret = 0;
02555             } else
02556                 goto return1;
02557             } else
02558             goto return1;
02559             if (*cur != 0) {
02560             while IS_WSP_BLANK_CH(*cur) cur++;
02561             if (*cur != 0)
02562                 goto return1;
02563             }
02564         } else {
02565             if ((cur[0] == '0') && (cur[1] == 0))
02566             ret = 0;
02567             else if ((cur[0] == '1') && (cur[1] == 0))
02568             ret = 1;
02569             else if ((cur[0] == 't') && (cur[1] == 'r')
02570             && (cur[2] == 'u') && (cur[3] == 'e')
02571             && (cur[4] == 0))
02572             ret = 1;
02573             else if ((cur[0] == 'f') && (cur[1] == 'a')
02574             && (cur[2] == 'l') && (cur[3] == 's')
02575             && (cur[4] == 'e') && (cur[5] == 0))
02576             ret = 0;
02577             else
02578             goto return1;
02579         }
02580                 if (val != NULL) {
02581                     v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN);
02582                     if (v != NULL) {
02583                         v->value.b = ret;
02584                         *val = v;
02585                     } else {
02586                         goto error;
02587                     }
02588                 }
02589                 goto return0;
02590             }
02591         case XML_SCHEMAS_TOKEN:{
02592                 const xmlChar *cur = value;
02593 
02594         if (! normOnTheFly) {
02595             while (*cur != 0) {
02596             if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
02597                 goto return1;
02598             } else if (*cur == ' ') {
02599                 cur++;
02600                 if (*cur == 0)
02601                 goto return1;
02602                 if (*cur == ' ')
02603                 goto return1;
02604             } else {
02605                 cur++;
02606             }
02607             }           
02608         }                
02609                 if (val != NULL) {
02610                     v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN);
02611                     if (v != NULL) {
02612                         v->value.str = xmlStrdup(value);
02613                         *val = v;
02614                     } else {
02615                         goto error;
02616                     }
02617                 }
02618                 goto return0;
02619             }
02620         case XML_SCHEMAS_LANGUAGE:
02621         if (normOnTheFly) {         
02622         norm = xmlSchemaCollapseString(value);
02623         if (norm != NULL)
02624             value = norm;
02625         }
02626             if (xmlCheckLanguageID(value) == 1) {
02627                 if (val != NULL) {
02628                     v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE);
02629                     if (v != NULL) {
02630                         v->value.str = xmlStrdup(value);
02631                         *val = v;
02632                     } else {
02633                         goto error;
02634                     }
02635                 }
02636                 goto return0;
02637             }
02638             goto return1;
02639         case XML_SCHEMAS_NMTOKEN:
02640             if (xmlValidateNMToken(value, 1) == 0) {
02641                 if (val != NULL) {
02642                     v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN);
02643                     if (v != NULL) {
02644                         v->value.str = xmlStrdup(value);
02645                         *val = v;
02646                     } else {
02647                         goto error;
02648                     }
02649                 }
02650                 goto return0;
02651             }
02652             goto return1;
02653         case XML_SCHEMAS_NMTOKENS:
02654             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef,
02655                                              value, val, node);
02656             if (ret > 0)
02657                 ret = 0;
02658             else
02659                 ret = 1;
02660             goto done;
02661         case XML_SCHEMAS_NAME:
02662             ret = xmlValidateName(value, 1);
02663             if ((ret == 0) && (val != NULL) && (value != NULL)) {
02664         v = xmlSchemaNewValue(XML_SCHEMAS_NAME);
02665         if (v != NULL) {
02666              const xmlChar *start = value, *end;
02667              while (IS_BLANK_CH(*start)) start++;
02668              end = start;
02669              while ((*end != 0) && (!IS_BLANK_CH(*end))) end++;
02670              v->value.str = xmlStrndup(start, end - start);
02671             *val = v;
02672         } else {
02673             goto error;
02674         }
02675             }
02676             goto done;
02677         case XML_SCHEMAS_QNAME:{
02678                 const xmlChar *uri = NULL;
02679                 xmlChar *local = NULL;
02680 
02681                 ret = xmlValidateQName(value, 1);
02682         if (ret != 0)
02683             goto done;
02684                 if (node != NULL) {
02685                     xmlChar *prefix;
02686             xmlNsPtr ns;
02687 
02688                     local = xmlSplitQName2(value, &prefix);
02689             ns = xmlSearchNs(node->doc, node, prefix);
02690             if ((ns == NULL) && (prefix != NULL)) {
02691             xmlFree(prefix);
02692             if (local != NULL)
02693                 xmlFree(local);
02694             goto return1;
02695             }
02696             if (ns != NULL)
02697             uri = ns->href;
02698                     if (prefix != NULL)
02699                         xmlFree(prefix);
02700                 }
02701                 if (val != NULL) {
02702                     v = xmlSchemaNewValue(XML_SCHEMAS_QNAME);
02703                     if (v == NULL) {
02704             if (local != NULL)
02705                 xmlFree(local);
02706             goto error;
02707             }
02708             if (local != NULL)
02709             v->value.qname.name = local;
02710             else
02711             v->value.qname.name = xmlStrdup(value);
02712             if (uri != NULL)
02713             v->value.qname.uri = xmlStrdup(uri);
02714             *val = v;
02715                 } else
02716             if (local != NULL)
02717             xmlFree(local);
02718                 goto done;
02719             }
02720         case XML_SCHEMAS_NCNAME:
02721             ret = xmlValidateNCName(value, 1);
02722             if ((ret == 0) && (val != NULL)) {
02723                 v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME);
02724                 if (v != NULL) {
02725                     v->value.str = xmlStrdup(value);
02726                     *val = v;
02727                 } else {
02728                     goto error;
02729                 }
02730             }
02731             goto done;
02732         case XML_SCHEMAS_ID:
02733             ret = xmlValidateNCName(value, 1);
02734             if ((ret == 0) && (val != NULL)) {
02735                 v = xmlSchemaNewValue(XML_SCHEMAS_ID);
02736                 if (v != NULL) {
02737                     v->value.str = xmlStrdup(value);
02738                     *val = v;
02739                 } else {
02740                     goto error;
02741                 }
02742             }
02743             if ((ret == 0) && (node != NULL) &&
02744                 (node->type == XML_ATTRIBUTE_NODE)) {
02745                 xmlAttrPtr attr = (xmlAttrPtr) node;
02746 
02747                 /*
02748                  * NOTE: the IDness might have already be declared in the DTD
02749                  */
02750                 if (attr->atype != XML_ATTRIBUTE_ID) {
02751                     xmlIDPtr res;
02752                     xmlChar *strip;
02753 
02754                     strip = xmlSchemaStrip(value);
02755                     if (strip != NULL) {
02756                         res = xmlAddID(NULL, node->doc, strip, attr);
02757                         xmlFree(strip);
02758                     } else
02759                         res = xmlAddID(NULL, node->doc, value, attr);
02760                     if (res == NULL) {
02761                         ret = 2;
02762                     } else {
02763                         attr->atype = XML_ATTRIBUTE_ID;
02764                     }
02765                 }
02766             }
02767             goto done;
02768         case XML_SCHEMAS_IDREF:
02769             ret = xmlValidateNCName(value, 1);
02770             if ((ret == 0) && (val != NULL)) {
02771         v = xmlSchemaNewValue(XML_SCHEMAS_IDREF);
02772         if (v == NULL)
02773             goto error;
02774         v->value.str = xmlStrdup(value);
02775         *val = v;
02776             }
02777             if ((ret == 0) && (node != NULL) &&
02778                 (node->type == XML_ATTRIBUTE_NODE)) {
02779                 xmlAttrPtr attr = (xmlAttrPtr) node;
02780                 xmlChar *strip;
02781 
02782                 strip = xmlSchemaStrip(value);
02783                 if (strip != NULL) {
02784                     xmlAddRef(NULL, node->doc, strip, attr);
02785                     xmlFree(strip);
02786                 } else
02787                     xmlAddRef(NULL, node->doc, value, attr);
02788                 attr->atype = XML_ATTRIBUTE_IDREF;
02789             }
02790             goto done;
02791         case XML_SCHEMAS_IDREFS:
02792             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef,
02793                                              value, val, node);
02794             if (ret < 0)
02795                 ret = 2;
02796             else
02797                 ret = 0;
02798             if ((ret == 0) && (node != NULL) &&
02799                 (node->type == XML_ATTRIBUTE_NODE)) {
02800                 xmlAttrPtr attr = (xmlAttrPtr) node;
02801 
02802                 attr->atype = XML_ATTRIBUTE_IDREFS;
02803             }
02804             goto done;
02805         case XML_SCHEMAS_ENTITY:{
02806                 xmlChar *strip;
02807 
02808                 ret = xmlValidateNCName(value, 1);
02809                 if ((node == NULL) || (node->doc == NULL))
02810                     ret = 3;
02811                 if (ret == 0) {
02812                     xmlEntityPtr ent;
02813 
02814                     strip = xmlSchemaStrip(value);
02815                     if (strip != NULL) {
02816                         ent = xmlGetDocEntity(node->doc, strip);
02817                         xmlFree(strip);
02818                     } else {
02819                         ent = xmlGetDocEntity(node->doc, value);
02820                     }
02821                     if ((ent == NULL) ||
02822                         (ent->etype !=
02823                          XML_EXTERNAL_GENERAL_UNPARSED_ENTITY))
02824                         ret = 4;
02825                 }
02826                 if ((ret == 0) && (val != NULL)) {
02827                     TODO;
02828                 }
02829                 if ((ret == 0) && (node != NULL) &&
02830                     (node->type == XML_ATTRIBUTE_NODE)) {
02831                     xmlAttrPtr attr = (xmlAttrPtr) node;
02832 
02833                     attr->atype = XML_ATTRIBUTE_ENTITY;
02834                 }
02835                 goto done;
02836             }
02837         case XML_SCHEMAS_ENTITIES:
02838             if ((node == NULL) || (node->doc == NULL))
02839                 goto return3;
02840             ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef,
02841                                              value, val, node);
02842             if (ret <= 0)
02843                 ret = 1;
02844             else
02845                 ret = 0;
02846             if ((ret == 0) && (node != NULL) &&
02847                 (node->type == XML_ATTRIBUTE_NODE)) {
02848                 xmlAttrPtr attr = (xmlAttrPtr) node;
02849 
02850                 attr->atype = XML_ATTRIBUTE_ENTITIES;
02851             }
02852             goto done;
02853         case XML_SCHEMAS_NOTATION:{
02854                 xmlChar *uri = NULL;
02855                 xmlChar *local = NULL;
02856 
02857                 ret = xmlValidateQName(value, 1);
02858                 if ((ret == 0) && (node != NULL)) {
02859                     xmlChar *prefix;
02860 
02861                     local = xmlSplitQName2(value, &prefix);
02862                     if (prefix != NULL) {
02863                         xmlNsPtr ns;
02864 
02865                         ns = xmlSearchNs(node->doc, node, prefix);
02866                         if (ns == NULL)
02867                             ret = 1;
02868                         else if (val != NULL)
02869                             uri = xmlStrdup(ns->href);
02870                     }
02871                     if ((local != NULL) && ((val == NULL) || (ret != 0)))
02872                         xmlFree(local);
02873                     if (prefix != NULL)
02874                         xmlFree(prefix);
02875                 }
02876                 if ((node == NULL) || (node->doc == NULL))
02877                     ret = 3;
02878                 if (ret == 0) {
02879                     ret = xmlValidateNotationUse(NULL, node->doc, value);
02880                     if (ret == 1)
02881                         ret = 0;
02882                     else
02883                         ret = 1;
02884                 }
02885                 if ((ret == 0) && (val != NULL)) {
02886                     v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION);
02887                     if (v != NULL) {
02888                         if (local != NULL)
02889                             v->value.qname.name = local;
02890                         else
02891                             v->value.qname.name = xmlStrdup(value);
02892                         if (uri != NULL)
02893                             v->value.qname.uri = uri;
02894 
02895                         *val = v;
02896                     } else {
02897                         if (local != NULL)
02898                             xmlFree(local);
02899                         if (uri != NULL)
02900                             xmlFree(uri);
02901                         goto error;
02902                     }
02903                 }
02904                 goto done;
02905             }
02906         case XML_SCHEMAS_ANYURI:{       
02907                 if (*value != 0) {
02908             xmlURIPtr uri;
02909             xmlChar *tmpval, *cur;
02910             if (normOnTheFly) {         
02911             norm = xmlSchemaCollapseString(value);
02912             if (norm != NULL)
02913                 value = norm;
02914             }
02915             tmpval = xmlStrdup(value);
02916             for (cur = tmpval; *cur; ++cur) {
02917             if (*cur < 32 || *cur >= 127 || *cur == ' ' ||
02918                 *cur == '<' || *cur == '>' || *cur == '"' ||
02919                 *cur == '{' || *cur == '}' || *cur == '|' ||
02920                 *cur == '\\' || *cur == '^' || *cur == '`' ||
02921                 *cur == '\'')
02922                 *cur = '_';
02923             }
02924                     uri = xmlParseURI((const char *) tmpval);
02925             xmlFree(tmpval);
02926                     if (uri == NULL)
02927                         goto return1;
02928                     xmlFreeURI(uri);
02929                 }
02930 
02931                 if (val != NULL) {
02932                     v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI);
02933                     if (v == NULL)
02934                         goto error;
02935                     v->value.str = xmlStrdup(value);
02936                     *val = v;
02937                 }
02938                 goto return0;
02939             }
02940         case XML_SCHEMAS_HEXBINARY:{
02941                 const xmlChar *cur = value, *start;
02942                 xmlChar *base;
02943                 int total, i = 0;
02944 
02945                 if (cur == NULL)
02946                     goto return1;
02947 
02948         if (normOnTheFly)
02949             while IS_WSP_BLANK_CH(*cur) cur++;
02950 
02951         start = cur;
02952                 while (((*cur >= '0') && (*cur <= '9')) ||
02953                        ((*cur >= 'A') && (*cur <= 'F')) ||
02954                        ((*cur >= 'a') && (*cur <= 'f'))) {
02955                     i++;
02956                     cur++;
02957                 }
02958         if (normOnTheFly)
02959             while IS_WSP_BLANK_CH(*cur) cur++;
02960 
02961                 if (*cur != 0)
02962                     goto return1;
02963                 if ((i % 2) != 0)
02964                     goto return1;
02965 
02966                 if (val != NULL) {
02967 
02968                     v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY);
02969                     if (v == NULL)
02970                         goto error;
02971             /*
02972             * Copy only the normalized piece.
02973             * CRITICAL TODO: Check this.
02974             */
02975                     cur = xmlStrndup(start, i);
02976                     if (cur == NULL) {
02977                 xmlSchemaTypeErrMemory(node, "allocating hexbin data");
02978                         xmlFree(v);
02979                         goto return1;
02980                     }
02981 
02982                     total = i / 2;      /* number of octets */
02983 
02984                     base = (xmlChar *) cur;
02985                     while (i-- > 0) {
02986                         if (*base >= 'a')
02987                             *base = *base - ('a' - 'A');
02988                         base++;
02989                     }
02990 
02991                     v->value.hex.str = (xmlChar *) cur;
02992                     v->value.hex.total = total;
02993                     *val = v;
02994                 }
02995                 goto return0;
02996             }
02997         case XML_SCHEMAS_BASE64BINARY:{
02998                 /* ISSUE:
02999                  * 
03000                  * Ignore all stray characters? (yes, currently)
03001                  * Worry about long lines? (no, currently)
03002                  * 
03003                  * rfc2045.txt:
03004                  * 
03005                  * "The encoded output stream must be represented in lines of
03006                  * no more than 76 characters each.  All line breaks or other
03007                  * characters not found in Table 1 must be ignored by decoding
03008                  * software.  In base64 data, characters other than those in
03009                  * Table 1, line breaks, and other white space probably
03010                  * indicate a transmission error, about which a warning
03011                  * message or even a message rejection might be appropriate
03012                  * under some circumstances." */
03013                 const xmlChar *cur = value;
03014                 xmlChar *base;
03015                 int total, i = 0, pad = 0;
03016 
03017                 if (cur == NULL)
03018                     goto return1;
03019 
03020                 for (; *cur; ++cur) {
03021                     int decc;
03022 
03023                     decc = _xmlSchemaBase64Decode(*cur);
03024                     if (decc < 0) ;
03025                     else if (decc < 64)
03026                         i++;
03027                     else
03028                         break;
03029                 }
03030                 for (; *cur; ++cur) {
03031                     int decc;
03032 
03033                     decc = _xmlSchemaBase64Decode(*cur);
03034                     if (decc < 0) ;
03035                     else if (decc < 64)
03036                         goto return1;
03037                     if (decc == 64)
03038                         pad++;
03039                 }
03040 
03041                 /* rfc2045.txt: "Special processing is performed if fewer than
03042                  * 24 bits are available at the end of the data being encoded.
03043                  * A full encoding quantum is always completed at the end of a
03044                  * body.  When fewer than 24 input bits are available in an
03045                  * input group, zero bits are added (on the right) to form an
03046                  * integral number of 6-bit groups.  Padding at the end of the
03047                  * data is performed using the "=" character.  Since all
03048                  * base64 input is an integral number of octets, only the
03049                  * following cases can arise: (1) the final quantum of
03050                  * encoding input is an integral multiple of 24 bits; here,
03051                  * the final unit of encoded output will be an integral
03052                  * multiple ofindent: Standard input:701: Warning:old style
03053          * assignment ambiguity in "=*".  Assuming "= *" 4 characters
03054          * with no "=" padding, (2) the final
03055                  * quantum of encoding input is exactly 8 bits; here, the
03056                  * final unit of encoded output will be two characters
03057                  * followed by two "=" padding characters, or (3) the final
03058                  * quantum of encoding input is exactly 16 bits; here, the
03059                  * final unit of encoded output will be three characters
03060                  * followed by one "=" padding character." */
03061 
03062                 total = 3 * (i / 4);
03063                 if (pad == 0) {
03064                     if (i % 4 != 0)
03065                         goto return1;
03066                 } else if (pad == 1) {
03067                     int decc;
03068 
03069                     if (i % 4 != 3)
03070                         goto return1;
03071                     for (decc = _xmlSchemaBase64Decode(*cur);
03072                          (decc < 0) || (decc > 63);
03073                          decc = _xmlSchemaBase64Decode(*cur))
03074                         --cur;
03075                     /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/
03076                     /* 00111100 -> 0x3c */
03077                     if (decc & ~0x3c)
03078                         goto return1;
03079                     total += 2;
03080                 } else if (pad == 2) {
03081                     int decc;
03082 
03083                     if (i % 4 != 2)
03084                         goto return1;
03085                     for (decc = _xmlSchemaBase64Decode(*cur);
03086                          (decc < 0) || (decc > 63);
03087                          decc = _xmlSchemaBase64Decode(*cur))
03088                         --cur;
03089                     /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */
03090                     /* 00110000 -> 0x30 */
03091                     if (decc & ~0x30)
03092                         goto return1;
03093                     total += 1;
03094                 } else
03095                     goto return1;
03096 
03097                 if (val != NULL) {
03098                     v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY);
03099                     if (v == NULL)
03100                         goto error;
03101                     base =
03102                         (xmlChar *) xmlMallocAtomic((i + pad + 1) *
03103                                                     sizeof(xmlChar));
03104                     if (base == NULL) {
03105                 xmlSchemaTypeErrMemory(node, "allocating base64 data");
03106                         xmlFree(v);
03107                         goto return1;
03108                     }
03109                     v->value.base64.str = base;
03110                     for (cur = value; *cur; ++cur)
03111                         if (_xmlSchemaBase64Decode(*cur) >= 0) {
03112                             *base = *cur;
03113                             ++base;
03114                         }
03115                     *base = 0;
03116                     v->value.base64.total = total;
03117                     *val = v;
03118                 }
03119                 goto return0;
03120             }
03121         case XML_SCHEMAS_INTEGER:
03122         case XML_SCHEMAS_PINTEGER:
03123         case XML_SCHEMAS_NPINTEGER:
03124         case XML_SCHEMAS_NINTEGER:
03125         case XML_SCHEMAS_NNINTEGER:{
03126                 const xmlChar *cur = value;
03127                 unsigned long lo, mi, hi;
03128                 int sign = 0;
03129 
03130                 if (cur == NULL)
03131                     goto return1;
03132         if (normOnTheFly)
03133             while IS_WSP_BLANK_CH(*cur) cur++;
03134                 if (*cur == '-') {
03135                     sign = 1;
03136                     cur++;
03137                 } else if (*cur == '+')
03138                     cur++;
03139                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
03140                 if (ret < 0)
03141                     goto return1;
03142         if (normOnTheFly)
03143             while IS_WSP_BLANK_CH(*cur) cur++;
03144                 if (*cur != 0)
03145                     goto return1;
03146                 if (type->builtInType == XML_SCHEMAS_NPINTEGER) {
03147                     if ((sign == 0) &&
03148                         ((hi != 0) || (mi != 0) || (lo != 0)))
03149                         goto return1;
03150                 } else if (type->builtInType == XML_SCHEMAS_PINTEGER) {
03151                     if (sign == 1)
03152                         goto return1;
03153                     if ((hi == 0) && (mi == 0) && (lo == 0))
03154                         goto return1;
03155                 } else if (type->builtInType == XML_SCHEMAS_NINTEGER) {
03156                     if (sign == 0)
03157                         goto return1;
03158                     if ((hi == 0) && (mi == 0) && (lo == 0))
03159                         goto return1;
03160                 } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) {
03161                     if ((sign == 1) &&
03162                         ((hi != 0) || (mi != 0) || (lo != 0)))
03163                         goto return1;
03164                 }
03165                 if (val != NULL) {
03166                     v = xmlSchemaNewValue(type->builtInType);
03167                     if (v != NULL) {
03168             if (ret == 0)
03169                 ret++;
03170                         v->value.decimal.lo = lo;
03171                         v->value.decimal.mi = mi;
03172                         v->value.decimal.hi = hi;
03173                         v->value.decimal.sign = sign;
03174                         v->value.decimal.frac = 0;
03175                         v->value.decimal.total = ret;
03176                         *val = v;
03177                     }
03178                 }
03179                 goto return0;
03180             }
03181         case XML_SCHEMAS_LONG:
03182         case XML_SCHEMAS_BYTE:
03183         case XML_SCHEMAS_SHORT:
03184         case XML_SCHEMAS_INT:{
03185                 const xmlChar *cur = value;
03186                 unsigned long lo, mi, hi;
03187                 int sign = 0;
03188 
03189                 if (cur == NULL)
03190                     goto return1;
03191                 if (*cur == '-') {
03192                     sign = 1;
03193                     cur++;
03194                 } else if (*cur == '+')
03195                     cur++;
03196                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
03197                 if (ret < 0)
03198                     goto return1;
03199                 if (*cur != 0)
03200                     goto return1;
03201                 if (type->builtInType == XML_SCHEMAS_LONG) {
03202                     if (hi >= 922) {
03203                         if (hi > 922)
03204                             goto return1;
03205                         if (mi >= 33720368) {
03206                             if (mi > 33720368)
03207                                 goto return1;
03208                             if ((sign == 0) && (lo > 54775807))
03209                                 goto return1;
03210                             if ((sign == 1) && (lo > 54775808))
03211                                 goto return1;
03212                         }
03213                     }
03214                 } else if (type->builtInType == XML_SCHEMAS_INT) {
03215                     if (hi != 0)
03216                         goto return1;
03217                     if (mi >= 21) {
03218                         if (mi > 21)
03219                             goto return1;
03220                         if ((sign == 0) && (lo > 47483647))
03221                             goto return1;
03222                         if ((sign == 1) && (lo > 47483648))
03223                             goto return1;
03224                     }
03225                 } else if (type->builtInType == XML_SCHEMAS_SHORT) {
03226                     if ((mi != 0) || (hi != 0))
03227                         goto return1;
03228                     if ((sign == 1) && (lo > 32768))
03229                         goto return1;
03230                     if ((sign == 0) && (lo > 32767))
03231                         goto return1;
03232                 } else if (type->builtInType == XML_SCHEMAS_BYTE) {
03233                     if ((mi != 0) || (hi != 0))
03234                         goto return1;
03235                     if ((sign == 1) && (lo > 128))
03236                         goto return1;
03237                     if ((sign == 0) && (lo > 127))
03238                         goto return1;
03239                 }
03240                 if (val != NULL) {
03241                     v = xmlSchemaNewValue(type->builtInType);
03242                     if (v != NULL) {
03243                         v->value.decimal.lo = lo;
03244                         v->value.decimal.mi = mi;
03245                         v->value.decimal.hi = hi;
03246                         v->value.decimal.sign = sign;
03247                         v->value.decimal.frac = 0;
03248                         v->value.decimal.total = ret;
03249                         *val = v;
03250                     }
03251                 }
03252                 goto return0;
03253             }
03254         case XML_SCHEMAS_UINT:
03255         case XML_SCHEMAS_ULONG:
03256         case XML_SCHEMAS_USHORT:
03257         case XML_SCHEMAS_UBYTE:{
03258                 const xmlChar *cur = value;
03259                 unsigned long lo, mi, hi;
03260 
03261                 if (cur == NULL)
03262                     goto return1;
03263                 ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi);
03264                 if (ret < 0)
03265                     goto return1;
03266                 if (*cur != 0)
03267                     goto return1;
03268                 if (type->builtInType == XML_SCHEMAS_ULONG) {
03269                     if (hi >= 1844) {
03270                         if (hi > 1844)
03271                             goto return1;
03272                         if (mi >= 67440737) {
03273                             if (mi > 67440737)
03274                                 goto return1;
03275                             if (lo > 9551615)
03276                                 goto return1;
03277                         }
03278                     }
03279                 } else if (type->builtInType == XML_SCHEMAS_UINT) {
03280                     if (hi != 0)
03281                         goto return1;
03282                     if (mi >= 42) {
03283                         if (mi > 42)
03284                             goto return1;
03285                         if (lo > 94967295)
03286                             goto return1;
03287                     }
03288                 } else if (type->builtInType == XML_SCHEMAS_USHORT) {
03289                     if ((mi != 0) || (hi != 0))
03290                         goto return1;
03291                     if (lo > 65535)
03292                         goto return1;
03293                 } else if (type->builtInType == XML_SCHEMAS_UBYTE) {
03294                     if ((mi != 0) || (hi != 0))
03295                         goto return1;
03296                     if (lo > 255)
03297                         goto return1;
03298                 }
03299                 if (val != NULL) {
03300                     v = xmlSchemaNewValue(type->builtInType);
03301                     if (v != NULL) {
03302                         v->value.decimal.lo = lo;
03303                         v->value.decimal.mi = mi;
03304                         v->value.decimal.hi = hi;
03305                         v->value.decimal.sign = 0;
03306                         v->value.decimal.frac = 0;
03307                         v->value.decimal.total = ret;
03308                         *val = v;
03309                     }
03310                 }
03311                 goto return0;
03312             }
03313     }
03314 
03315   done:
03316     if (norm != NULL)
03317         xmlFree(norm);
03318     return (ret);
03319   return3:
03320     if (norm != NULL)
03321         xmlFree(norm);
03322     return (3);
03323   return1:
03324     if (norm != NULL)
03325         xmlFree(norm);
03326     return (1);
03327   return0:
03328     if (norm != NULL)
03329         xmlFree(norm);
03330     return (0);
03331   error:
03332     if (norm != NULL)
03333         xmlFree(norm);
03334     return (-1);
03335 }
03336 
03350 int
03351 xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value,
03352                        xmlSchemaValPtr *val, xmlNodePtr node) {
03353     return(xmlSchemaValAtomicType(type, value, val, node, 0,
03354     XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 1, 0));
03355 }
03356 
03371 int
03372 xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value,
03373                  xmlSchemaValPtr *val, xmlNodePtr node) {
03374     return(xmlSchemaValAtomicType(type, value, val, node, 1,
03375     XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 0, 1));
03376 }
03377 
03390 int
03391 xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value,
03392                             xmlSchemaValPtr *val) {
03393     return(xmlSchemaValPredefTypeNode(type, value, val, NULL));
03394 }
03395 
03405 static int
03406 xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y)
03407 {
03408     xmlSchemaValPtr swp;
03409     int order = 1, integx, integy, dlen;
03410     unsigned long hi, mi, lo;
03411 
03412     /*
03413      * First test: If x is -ve and not zero
03414      */
03415     if ((x->value.decimal.sign) && 
03416     ((x->value.decimal.lo != 0) ||
03417      (x->value.decimal.mi != 0) ||
03418      (x->value.decimal.hi != 0))) {
03419     /*
03420      * Then if y is -ve and not zero reverse the compare
03421      */
03422     if ((y->value.decimal.sign) &&
03423         ((y->value.decimal.lo != 0) ||
03424          (y->value.decimal.mi != 0) ||
03425          (y->value.decimal.hi != 0)))
03426         order = -1;
03427     /*
03428      * Otherwise (y >= 0) we have the answer
03429      */
03430     else
03431         return (-1);
03432     /*
03433      * If x is not -ve and y is -ve we have the answer
03434      */
03435     } else if ((y->value.decimal.sign) &&
03436            ((y->value.decimal.lo != 0) ||
03437         (y->value.decimal.mi != 0) ||
03438         (y->value.decimal.hi != 0))) {
03439         return (1);
03440     }
03441     /*
03442      * If it's not simply determined by a difference in sign,
03443      * then we need to compare the actual values of the two nums.
03444      * To do this, we start by looking at the integral parts.
03445      * If the number of integral digits differ, then we have our
03446      * answer.
03447      */
03448     integx = x->value.decimal.total - x->value.decimal.frac;
03449     integy = y->value.decimal.total - y->value.decimal.frac;
03450     /*
03451     * NOTE: We changed the "total" for values like "0.1"
03452     *   (or "-0.1" or ".1") to be 1, which was 2 previously.
03453     *   Therefore the special case, when such values are
03454     *   compared with 0, needs to be handled separately;
03455     *   otherwise a zero would be recognized incorrectly as
03456     *   greater than those values. This has the nice side effect
03457     *   that we gain an overall optimized comparison with zeroes.
03458     * Note that a "0" has a "total" of 1 already.
03459     */
03460     if (integx == 1) {
03461     if (x->value.decimal.lo == 0) {
03462         if (integy != 1)
03463         return -order;
03464         else if (y->value.decimal.lo != 0)
03465         return -order;
03466         else
03467         return(0);
03468     }
03469     }
03470     if (integy == 1) {
03471     if (y->value.decimal.lo == 0) {
03472         if (integx != 1)
03473         return order;
03474         else if (x->value.decimal.lo != 0)
03475         return order;
03476         else
03477         return(0);
03478     }
03479     }
03480 
03481     if (integx > integy)
03482     return order;
03483     else if (integy > integx)
03484     return -order;
03485 
03486     /*
03487      * If the number of integral digits is the same for both numbers,
03488      * then things get a little more complicated.  We need to "normalize"
03489      * the numbers in order to properly compare them.  To do this, we
03490      * look at the total length of each number (length => number of
03491      * significant digits), and divide the "shorter" by 10 (decreasing
03492      * the length) until they are of equal length.
03493      */
03494     dlen = x->value.decimal.total - y->value.decimal.total;
03495     if (dlen < 0) { /* y has more digits than x */
03496     swp = x;
03497     hi = y->value.decimal.hi;
03498     mi = y->value.decimal.mi;
03499     lo = y->value.decimal.lo;
03500     dlen = -dlen;
03501     order = -order;
03502     } else {        /* x has more digits than y */
03503     swp = y;
03504     hi = x->value.decimal.hi;
03505     mi = x->value.decimal.mi;
03506     lo = x->value.decimal.lo;
03507     }
03508     while (dlen > 8) {  /* in effect, right shift by 10**8 */
03509     lo = mi;
03510     mi = hi;
03511     hi = 0;
03512     dlen -= 8;
03513     }
03514     while (dlen > 0) {
03515     unsigned long rem1, rem2;
03516     rem1 = (hi % 10) * 100000000L;
03517     hi = hi / 10;
03518     rem2 = (mi % 10) * 100000000L;
03519     mi = (mi + rem1) / 10;
03520     lo = (lo + rem2) / 10;
03521     dlen--;
03522     }
03523     if (hi > swp->value.decimal.hi) {
03524     return order;
03525     } else if (hi == swp->value.decimal.hi) {
03526     if (mi > swp->value.decimal.mi) {
03527         return order;
03528     } else if (mi == swp->value.decimal.mi) {
03529         if (lo > swp->value.decimal.lo) {
03530         return order;
03531         } else if (lo == swp->value.decimal.lo) {
03532         if (x->value.decimal.total == y->value.decimal.total) {
03533             return 0;
03534         } else {
03535             return order;
03536         }
03537         }
03538     }
03539     }
03540     return -order;
03541 }
03542 
03553 static int
03554 xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y)
03555 {
03556     long carry, mon, day;
03557     double sec;
03558     int invert = 1;
03559     long xmon, xday, myear, minday, maxday;
03560     static const long dayRange [2][12] = {
03561         { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, },
03562         { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} };
03563 
03564     if ((x == NULL) || (y == NULL))
03565         return -2;
03566 
03567     /* months */
03568     mon = x->value.dur.mon - y->value.dur.mon;
03569 
03570     /* seconds */
03571     sec = x->value.dur.sec - y->value.dur.sec;
03572     carry = (long)sec / SECS_PER_DAY;
03573     sec -= (double)(carry * SECS_PER_DAY);
03574 
03575     /* days */
03576     day = x->value.dur.day - y->value.dur.day + carry;
03577 
03578     /* easy test */
03579     if (mon == 0) {
03580         if (day == 0)
03581             if (sec == 0.0)
03582                 return 0;
03583             else if (sec < 0.0)
03584                 return -1;
03585             else
03586                 return 1;
03587         else if (day < 0)
03588             return -1;
03589         else
03590             return 1;
03591     }
03592 
03593     if (mon > 0) {
03594         if ((day >= 0) && (sec >= 0.0))
03595             return 1;
03596         else {
03597             xmon = mon;
03598             xday = -day;
03599         }
03600     } else if ((day <= 0) && (sec <= 0.0)) {
03601         return -1;
03602     } else {
03603     invert = -1;
03604         xmon = -mon;
03605         xday = day;
03606     }
03607 
03608     myear = xmon / 12;
03609     if (myear == 0) {
03610     minday = 0;
03611     maxday = 0;
03612     } else {
03613     maxday = 366 * ((myear + 3) / 4) +
03614              365 * ((myear - 1) % 4);
03615     minday = maxday - 1;
03616     }
03617 
03618     xmon = xmon % 12;
03619     minday += dayRange[0][xmon];
03620     maxday += dayRange[1][xmon];
03621 
03622     if ((maxday == minday) && (maxday == xday))
03623     return(0); /* can this really happen ? */
03624     if (maxday < xday)
03625         return(-invert);
03626     if (minday > xday)
03627         return(invert);
03628 
03629     /* indeterminate */
03630     return 2;
03631 }
03632 
03633 /*
03634  * macros for adding date/times and durations
03635  */
03636 #define FQUOTIENT(a,b)                  (floor(((double)a/(double)b)))
03637 #define MODULO(a,b)                     (a - FQUOTIENT(a,b) * b)
03638 #define FQUOTIENT_RANGE(a,low,high)     (FQUOTIENT((a-low),(high-low)))
03639 #define MODULO_RANGE(a,low,high)        ((MODULO((a-low),(high-low)))+low)
03640 
03650 static xmlSchemaValPtr
03651 xmlSchemaDupVal (xmlSchemaValPtr v)
03652 {
03653     xmlSchemaValPtr ret = xmlSchemaNewValue(v->type);
03654     if (ret == NULL)
03655         return NULL;
03656     
03657     memcpy(ret, v, sizeof(xmlSchemaVal));
03658     ret->next = NULL;
03659     return ret;
03660 }
03661 
03670 xmlSchemaValPtr
03671 xmlSchemaCopyValue(xmlSchemaValPtr val)
03672 {
03673     xmlSchemaValPtr ret = NULL, prev = NULL, cur;
03674 
03675     /*
03676     * Copy the string values.
03677     */
03678     while (val != NULL) {
03679     switch (val->type) {
03680         case XML_SCHEMAS_ANYTYPE:
03681         case XML_SCHEMAS_IDREFS:
03682         case XML_SCHEMAS_ENTITIES:
03683         case XML_SCHEMAS_NMTOKENS:
03684         xmlSchemaFreeValue(ret);
03685         return (NULL);
03686         case XML_SCHEMAS_ANYSIMPLETYPE:
03687         case XML_SCHEMAS_STRING:
03688         case XML_SCHEMAS_NORMSTRING:
03689         case XML_SCHEMAS_TOKEN:
03690         case XML_SCHEMAS_LANGUAGE:
03691         case XML_SCHEMAS_NAME:
03692         case XML_SCHEMAS_NCNAME:
03693         case XML_SCHEMAS_ID:
03694         case XML_SCHEMAS_IDREF:
03695         case XML_SCHEMAS_ENTITY:
03696         case XML_SCHEMAS_NMTOKEN:
03697         case XML_SCHEMAS_ANYURI:
03698         cur = xmlSchemaDupVal(val);
03699         if (val->value.str != NULL)
03700             cur->value.str = xmlStrdup(BAD_CAST val->value.str);
03701         break;
03702         case XML_SCHEMAS_QNAME:        
03703         case XML_SCHEMAS_NOTATION:
03704         cur = xmlSchemaDupVal(val);
03705         if (val->value.qname.name != NULL)
03706             cur->value.qname.name =
03707                     xmlStrdup(BAD_CAST val->value.qname.name);
03708         if (val->value.qname.uri != NULL)
03709             cur->value.qname.uri =
03710                     xmlStrdup(BAD_CAST val->value.qname.uri);
03711         break;
03712         case XML_SCHEMAS_HEXBINARY:
03713         cur = xmlSchemaDupVal(val);
03714         if (val->value.hex.str != NULL)
03715             cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str);
03716         break;
03717         case XML_SCHEMAS_BASE64BINARY:
03718         cur = xmlSchemaDupVal(val);
03719         if (val->value.base64.str != NULL)
03720             cur->value.base64.str =
03721                     xmlStrdup(BAD_CAST val->value.base64.str);
03722         break;
03723         default:
03724         cur = xmlSchemaDupVal(val);
03725         break;
03726     }
03727     if (ret == NULL)
03728         ret = cur;
03729     else
03730         prev->next = cur;
03731     prev = cur;
03732     val = val->next;
03733     }
03734     return (ret);
03735 }
03736 
03749 static xmlSchemaValPtr
03750 _xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur)
03751 {
03752     xmlSchemaValPtr ret, tmp;
03753     long carry, tempdays, temp;
03754     xmlSchemaValDatePtr r, d;
03755     xmlSchemaValDurationPtr u;
03756 
03757     if ((dt == NULL) || (dur == NULL))
03758         return NULL;
03759 
03760     ret = xmlSchemaNewValue(dt->type);
03761     if (ret == NULL)
03762         return NULL;
03763 
03764     /* make a copy so we don't alter the original value */
03765     tmp = xmlSchemaDupVal(dt);
03766     if (tmp == NULL) {
03767         xmlSchemaFreeValue(ret);
03768         return NULL;
03769     }
03770 
03771     r = &(ret->value.date);
03772     d = &(tmp->value.date);
03773     u = &(dur->value.dur);
03774 
03775     /* normalization */
03776     if (d->mon == 0)
03777         d->mon = 1;
03778 
03779     /* normalize for time zone offset */
03780     u->sec -= (d->tzo * 60);
03781     d->tzo = 0;
03782 
03783     /* normalization */
03784     if (d->day == 0)
03785         d->day = 1;
03786 
03787     /* month */
03788     carry  = d->mon + u->mon;
03789     r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13);
03790     carry  = (long) FQUOTIENT_RANGE(carry, 1, 13);
03791 
03792     /* year (may be modified later) */
03793     r->year = d->year + carry;
03794     if (r->year == 0) {
03795         if (d->year > 0)
03796             r->year--;
03797         else
03798             r->year++;
03799     }
03800 
03801     /* time zone */
03802     r->tzo     = d->tzo;
03803     r->tz_flag = d->tz_flag;
03804 
03805     /* seconds */
03806     r->sec = d->sec + u->sec;
03807     carry  = (long) FQUOTIENT((long)r->sec, 60);
03808     if (r->sec != 0.0) {
03809         r->sec = MODULO(r->sec, 60.0);
03810     }
03811 
03812     /* minute */
03813     carry += d->min;
03814     r->min = (unsigned int) MODULO(carry, 60);
03815     carry  = (long) FQUOTIENT(carry, 60);
03816 
03817     /* hours */
03818     carry  += d->hour;
03819     r->hour = (unsigned int) MODULO(carry, 24);
03820     carry   = (long)FQUOTIENT(carry, 24);
03821 
03822     /*
03823      * days
03824      * Note we use tempdays because the temporary values may need more
03825      * than 5 bits
03826      */
03827     if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) &&
03828                   (d->day > MAX_DAYINMONTH(r->year, r->mon)))
03829         tempdays = MAX_DAYINMONTH(r->year, r->mon);
03830     else if (d->day < 1)
03831         tempdays = 1;
03832     else
03833         tempdays = d->day;
03834 
03835     tempdays += u->day + carry;
03836 
03837     while (1) {
03838         if (tempdays < 1) {
03839             long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13);
03840             long tyr  = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13);
03841             if (tyr == 0)
03842                 tyr--;
03843         /*
03844          * Coverity detected an overrun in daysInMonth 
03845          * of size 12 at position 12 with index variable "((r)->mon - 1)"
03846          */
03847         if (tmon < 0)
03848             tmon = 0;
03849         if (tmon > 12)
03850             tmon = 12;
03851             tempdays += MAX_DAYINMONTH(tyr, tmon);
03852             carry = -1;
03853         } else if (tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) {
03854             tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon);
03855             carry = 1;
03856         } else
03857             break;
03858 
03859         temp = r->mon + carry;
03860         r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13);
03861         r->year = r->year + (unsigned int) FQUOTIENT_RANGE(temp, 1, 13);
03862         if (r->year == 0) {
03863             if (temp < 1)
03864                 r->year--;
03865             else
03866                 r->year++;
03867     }
03868     }
03869     
03870     r->day = tempdays;
03871 
03872     /*
03873      * adjust the date/time type to the date values
03874      */
03875     if (ret->type != XML_SCHEMAS_DATETIME) {
03876         if ((r->hour) || (r->min) || (r->sec))
03877             ret->type = XML_SCHEMAS_DATETIME;
03878         else if (ret->type != XML_SCHEMAS_DATE) {
03879             if ((r->mon != 1) && (r->day != 1))
03880                 ret->type = XML_SCHEMAS_DATE;
03881             else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1))
03882                 ret->type = XML_SCHEMAS_GYEARMONTH;
03883         }
03884     }
03885 
03886     xmlSchemaFreeValue(tmp);
03887 
03888     return ret;
03889 }
03890 
03901 static xmlSchemaValPtr
03902 xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset)
03903 {
03904     xmlSchemaValPtr dur, ret;
03905 
03906     if (dt == NULL)
03907         return NULL;
03908 
03909     if (((dt->type != XML_SCHEMAS_TIME) &&
03910          (dt->type != XML_SCHEMAS_DATETIME) &&
03911      (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0))
03912         return xmlSchemaDupVal(dt);
03913 
03914     dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION);
03915     if (dur == NULL)
03916         return NULL;
03917 
03918     dur->value.date.sec -= offset;
03919 
03920     ret = _xmlSchemaDateAdd(dt, dur);
03921     if (ret == NULL)
03922         return NULL;
03923 
03924     xmlSchemaFreeValue(dur);
03925 
03926     /* ret->value.date.tzo = 0; */
03927     return ret;
03928 }
03929 
03941 static long
03942 _xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt)
03943 {
03944     long ret;
03945     int mon;
03946 
03947     mon = dt->value.date.mon;
03948     if (mon <= 0) mon = 1; /* normalization */
03949 
03950     if (dt->value.date.year <= 0)
03951         ret = (dt->value.date.year * 365) +
03952               (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+
03953                ((dt->value.date.year+1)/400)) +
03954               DAY_IN_YEAR(0, mon, dt->value.date.year);
03955     else
03956         ret = ((dt->value.date.year-1) * 365) +
03957               (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+
03958                ((dt->value.date.year-1)/400)) +
03959               DAY_IN_YEAR(0, mon, dt->value.date.year);
03960 
03961     return ret;
03962 }
03963 
03972 #define TIME_TO_NUMBER(dt)                              \
03973     ((double)((dt->value.date.hour * SECS_PER_HOUR) +   \
03974               (dt->value.date.min * SECS_PER_MIN) + \
03975               (dt->value.date.tzo * SECS_PER_MIN)) +    \
03976                dt->value.date.sec)
03977 
03988 static int
03989 xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y)
03990 {
03991     unsigned char xmask, ymask, xor_mask, and_mask;
03992     xmlSchemaValPtr p1, p2, q1, q2;
03993     long p1d, p2d, q1d, q2d;
03994 
03995     if ((x == NULL) || (y == NULL))
03996         return -2;
03997 
03998     if (x->value.date.tz_flag) {
03999 
04000         if (!y->value.date.tz_flag) {
04001             p1 = xmlSchemaDateNormalize(x, 0);
04002             p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
04003             /* normalize y + 14:00 */
04004             q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR));
04005 
04006             q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
04007             if (p1d < q1d) {
04008         xmlSchemaFreeValue(p1);
04009         xmlSchemaFreeValue(q1);
04010                 return -1;
04011         } else if (p1d == q1d) {
04012                 double sec;
04013 
04014                 sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
04015                 if (sec < 0.0) {
04016             xmlSchemaFreeValue(p1);
04017             xmlSchemaFreeValue(q1);
04018                     return -1;
04019         } else {
04020             int ret = 0;
04021                     /* normalize y - 14:00 */
04022                     q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR));
04023                     q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day;
04024                     if (p1d > q2d)
04025                         ret = 1;
04026                     else if (p1d == q2d) {
04027                         sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2);
04028                         if (sec > 0.0)
04029                             ret = 1;
04030                         else
04031                             ret = 2; /* indeterminate */
04032                     }
04033             xmlSchemaFreeValue(p1);
04034             xmlSchemaFreeValue(q1);
04035             xmlSchemaFreeValue(q2);
04036             if (ret != 0)
04037                 return(ret);
04038                 }
04039             } else {
04040         xmlSchemaFreeValue(p1);
04041         xmlSchemaFreeValue(q1);
04042         }
04043         }
04044     } else if (y->value.date.tz_flag) {
04045         q1 = xmlSchemaDateNormalize(y, 0);
04046         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
04047 
04048         /* normalize x - 14:00 */
04049         p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR));
04050         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
04051 
04052         if (p1d < q1d) {
04053         xmlSchemaFreeValue(p1);
04054         xmlSchemaFreeValue(q1);
04055             return -1;
04056     } else if (p1d == q1d) {
04057             double sec;
04058 
04059             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
04060             if (sec < 0.0) {
04061         xmlSchemaFreeValue(p1);
04062         xmlSchemaFreeValue(q1);
04063                 return -1;
04064         } else {
04065             int ret = 0;
04066                 /* normalize x + 14:00 */
04067                 p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR));
04068                 p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day;
04069 
04070                 if (p2d > q1d) {
04071                     ret = 1;
04072         } else if (p2d == q1d) {
04073                     sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1);
04074                     if (sec > 0.0)
04075                         ret = 1;
04076                     else
04077                         ret = 2; /* indeterminate */
04078                 }
04079         xmlSchemaFreeValue(p1);
04080         xmlSchemaFreeValue(q1);
04081         xmlSchemaFreeValue(p2);
04082         if (ret != 0)
04083             return(ret);
04084             }
04085     } else {
04086         xmlSchemaFreeValue(p1);
04087         xmlSchemaFreeValue(q1);
04088         }
04089     }
04090 
04091     /*
04092      * if the same type then calculate the difference
04093      */
04094     if (x->type == y->type) {
04095         int ret = 0;
04096         q1 = xmlSchemaDateNormalize(y, 0);
04097         q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day;
04098 
04099         p1 = xmlSchemaDateNormalize(x, 0);
04100         p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day;
04101 
04102         if (p1d < q1d) {
04103             ret = -1;
04104     } else if (p1d > q1d) {
04105             ret = 1;
04106     } else {
04107             double sec;
04108 
04109             sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1);
04110             if (sec < 0.0)
04111                 ret = -1;
04112             else if (sec > 0.0)
04113                 ret = 1;
04114             
04115         }
04116     xmlSchemaFreeValue(p1);
04117     xmlSchemaFreeValue(q1);
04118         return(ret);
04119     }
04120 
04121     switch (x->type) {
04122         case XML_SCHEMAS_DATETIME:
04123             xmask = 0xf;
04124             break;
04125         case XML_SCHEMAS_DATE:
04126             xmask = 0x7;
04127             break;
04128         case XML_SCHEMAS_GYEAR:
04129             xmask = 0x1;
04130             break;
04131         case XML_SCHEMAS_GMONTH:
04132             xmask = 0x2;
04133             break;
04134         case XML_SCHEMAS_GDAY:
04135             xmask = 0x3;
04136             break;
04137         case XML_SCHEMAS_GYEARMONTH:
04138             xmask = 0x3;
04139             break;
04140         case XML_SCHEMAS_GMONTHDAY:
04141             xmask = 0x6;
04142             break;
04143         case XML_SCHEMAS_TIME:
04144             xmask = 0x8;
04145             break;
04146         default:
04147             xmask = 0;
04148             break;
04149     }
04150 
04151     switch (y->type) {
04152         case XML_SCHEMAS_DATETIME:
04153             ymask = 0xf;
04154             break;
04155         case XML_SCHEMAS_DATE:
04156             ymask = 0x7;
04157             break;
04158         case XML_SCHEMAS_GYEAR:
04159             ymask = 0x1;
04160             break;
04161         case XML_SCHEMAS_GMONTH:
04162             ymask = 0x2;
04163             break;
04164         case XML_SCHEMAS_GDAY:
04165             ymask = 0x3;
04166             break;
04167         case XML_SCHEMAS_GYEARMONTH:
04168             ymask = 0x3;
04169             break;
04170         case XML_SCHEMAS_GMONTHDAY:
04171             ymask = 0x6;
04172             break;
04173         case XML_SCHEMAS_TIME:
04174             ymask = 0x8;
04175             break;
04176         default:
04177             ymask = 0;
04178             break;
04179     }
04180 
04181     xor_mask = xmask ^ ymask;           /* mark type differences */
04182     and_mask = xmask & ymask;           /* mark field specification */
04183 
04184     /* year */
04185     if (xor_mask & 1)
04186         return 2; /* indeterminate */
04187     else if (and_mask & 1) {
04188         if (x->value.date.year < y->value.date.year)
04189             return -1;
04190         else if (x->value.date.year > y->value.date.year)
04191             return 1;
04192     }
04193 
04194     /* month */
04195     if (xor_mask & 2)
04196         return 2; /* indeterminate */
04197     else if (and_mask & 2) {
04198         if (x->value.date.mon < y->value.date.mon)
04199             return -1;
04200         else if (x->value.date.mon > y->value.date.mon)
04201             return 1;
04202     }
04203 
04204     /* day */
04205     if (xor_mask & 4)
04206         return 2; /* indeterminate */
04207     else if (and_mask & 4) {
04208         if (x->value.date.day < y->value.date.day)
04209             return -1;
04210         else if (x->value.date.day > y->value.date.day)
04211             return 1;
04212     }
04213 
04214     /* time */
04215     if (xor_mask & 8)
04216         return 2; /* indeterminate */
04217     else if (and_mask & 8) {
04218         if (x->value.date.hour < y->value.date.hour)
04219             return -1;
04220         else if (x->value.date.hour > y->value.date.hour)
04221             return 1;
04222         else if (x->value.date.min < y->value.date.min)
04223             return -1;
04224         else if (x->value.date.min > y->value.date.min)
04225             return 1;
04226         else if (x->value.date.sec < y->value.date.sec)
04227             return -1;
04228         else if (x->value.date.sec > y->value.date.sec)
04229             return 1;
04230     }
04231 
04232     return 0;
04233 }
04234 
04249 static int
04250 xmlSchemaComparePreserveReplaceStrings(const xmlChar *x,
04251                        const xmlChar *y,
04252                        int invert)
04253 {
04254     int tmp;
04255     
04256     while ((*x != 0) && (*y != 0)) {
04257     if (IS_WSP_REPLACE_CH(*y)) {
04258         if (! IS_WSP_SPACE_CH(*x)) {
04259         if ((*x - 0x20) < 0) {
04260             if (invert)
04261             return(1);
04262             else
04263             return(-1);
04264         } else {
04265             if (invert)
04266             return(-1);
04267             else
04268             return(1);
04269         }
04270         }       
04271     } else {
04272         tmp = *x - *y;
04273         if (tmp < 0) {
04274         if (invert)
04275             return(1);
04276         else
04277             return(-1);
04278         }
04279         if (tmp > 0) {
04280         if (invert)
04281             return(-1);
04282         else
04283             return(1);
04284         }
04285     }
04286     x++;
04287     y++;
04288     }
04289     if (*x != 0) {
04290     if (invert)
04291         return(-1);
04292     else
04293         return(1);
04294     }
04295     if (*y != 0) {
04296     if (invert)
04297         return(1);
04298     else
04299         return(-1);
04300     }
04301     return(0);
04302 }
04303 
04317 static int
04318 xmlSchemaComparePreserveCollapseStrings(const xmlChar *x,
04319                         const xmlChar *y,
04320                     int invert)
04321 {
04322     int tmp;
04323 
04324     /* 
04325     * Skip leading blank chars of the collapsed string.
04326     */
04327     while IS_WSP_BLANK_CH(*y)
04328     y++;
04329 
04330     while ((*x != 0) && (*y != 0)) {
04331     if IS_WSP_BLANK_CH(*y) {
04332         if (! IS_WSP_SPACE_CH(*x)) {
04333         /*
04334         * The yv character would have been replaced to 0x20.
04335         */
04336         if ((*x - 0x20) < 0) {
04337             if (invert)
04338             return(1);
04339             else
04340             return(-1);
04341         } else {
04342             if (invert)
04343             return(-1);
04344             else
04345             return(1);
04346         }
04347         }
04348         x++;
04349         y++;
04350         /*
04351         * Skip contiguous blank chars of the collapsed string.
04352         */
04353         while IS_WSP_BLANK_CH(*y)
04354         y++;
04355     } else {
04356         tmp = *x++ - *y++;
04357         if (tmp < 0) {
04358         if (invert)
04359             return(1);
04360         else
04361             return(-1);
04362         }
04363         if (tmp > 0) {
04364         if (invert)
04365             return(-1);
04366         else
04367             return(1);
04368         }
04369     }
04370     }
04371     if (*x != 0) {
04372      if (invert)
04373          return(-1);
04374      else
04375          return(1);
04376     }
04377     if (*y != 0) {
04378     /*
04379     * Skip trailing blank chars of the collapsed string.
04380     */
04381     while IS_WSP_BLANK_CH(*y)
04382         y++;
04383     if (*y != 0) {
04384         if (invert)
04385         return(1);
04386         else
04387         return(-1);
04388     }
04389     }
04390     return(0);
04391 }
04392 
04406 static int
04407 xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x,
04408                        const xmlChar *y,
04409                        int invert)
04410 {
04411     int tmp;
04412 
04413     /* 
04414     * Skip leading blank chars of the collapsed string.
04415     */
04416     while IS_WSP_BLANK_CH(*y)
04417     y++;
04418     
04419     while ((*x != 0) && (*y != 0)) {
04420     if IS_WSP_BLANK_CH(*y) {
04421         if (! IS_WSP_BLANK_CH(*x)) {
04422         /*
04423         * The yv character would have been replaced to 0x20.
04424         */
04425         if ((*x - 0x20) < 0) {
04426             if (invert)
04427             return(1);
04428             else
04429             return(-1);
04430         } else {
04431             if (invert)
04432             return(-1);
04433             else
04434             return(1);
04435         }
04436         }
04437         x++;
04438         y++;        
04439         /* 
04440         * Skip contiguous blank chars of the collapsed string.
04441         */
04442         while IS_WSP_BLANK_CH(*y)
04443         y++;
04444     } else {
04445         if IS_WSP_BLANK_CH(*x) {
04446         /*
04447         * The xv character would have been replaced to 0x20.
04448         */
04449         if ((0x20 - *y) < 0) {
04450             if (invert)
04451             return(1);
04452             else
04453             return(-1);
04454         } else {
04455             if (invert)
04456             return(-1);
04457             else
04458             return(1);
04459         }
04460         }
04461         tmp = *x++ - *y++;
04462         if (tmp < 0)
04463         return(-1);
04464         if (tmp > 0)
04465         return(1);
04466     }
04467     }
04468     if (*x != 0) {
04469      if (invert)
04470          return(-1);
04471      else
04472          return(1);
04473     }   
04474     if (*y != 0) {
04475     /*
04476     * Skip trailing blank chars of the collapsed string.
04477     */
04478     while IS_WSP_BLANK_CH(*y)
04479         y++;
04480     if (*y != 0) {
04481         if (invert)
04482         return(1);
04483         else
04484         return(-1);
04485     }
04486     }
04487     return(0);
04488 }
04489 
04490 
04501 static int
04502 xmlSchemaCompareReplacedStrings(const xmlChar *x,
04503                 const xmlChar *y)
04504 {
04505     int tmp;
04506    
04507     while ((*x != 0) && (*y != 0)) {
04508     if IS_WSP_BLANK_CH(*y) {
04509         if (! IS_WSP_BLANK_CH(*x)) {
04510         if ((*x - 0x20) < 0)
04511                 return(-1);
04512         else
04513             return(1);
04514         }       
04515     } else {
04516         if IS_WSP_BLANK_CH(*x) {
04517         if ((0x20 - *y) < 0)
04518                 return(-1);
04519         else
04520             return(1);
04521         }
04522         tmp = *x - *y;
04523         if (tmp < 0)
04524             return(-1);
04525         if (tmp > 0)
04526             return(1);
04527     }
04528     x++;
04529     y++;
04530     }
04531     if (*x != 0)
04532         return(1);
04533     if (*y != 0)
04534         return(-1);
04535     return(0);
04536 }
04537 
04548 static int
04549 xmlSchemaCompareNormStrings(const xmlChar *x,
04550                 const xmlChar *y) {
04551     int tmp;
04552     
04553     while (IS_BLANK_CH(*x)) x++;
04554     while (IS_BLANK_CH(*y)) y++;
04555     while ((*x != 0) && (*y != 0)) {
04556     if (IS_BLANK_CH(*x)) {
04557         if (!IS_BLANK_CH(*y)) {
04558         tmp = *x - *y;
04559         return(tmp);
04560         }
04561         while (IS_BLANK_CH(*x)) x++;
04562         while (IS_BLANK_CH(*y)) y++;
04563     } else {
04564         tmp = *x++ - *y++;
04565         if (tmp < 0)
04566         return(-1);
04567         if (tmp > 0)
04568         return(1);
04569     }
04570     }
04571     if (*x != 0) {
04572     while (IS_BLANK_CH(*x)) x++;
04573     if (*x != 0)
04574         return(1);
04575     }
04576     if (*y != 0) {
04577     while (IS_BLANK_CH(*y)) y++;
04578     if (*y != 0)
04579         return(-1);
04580     }
04581     return(0);
04582 }
04583 
04594 static int
04595 xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) {
04596     double d1, d2;
04597 
04598     if ((x == NULL) || (y == NULL))
04599     return(-2);
04600 
04601     /*
04602      * Cast everything to doubles.
04603      */
04604     if (x->type == XML_SCHEMAS_DOUBLE)
04605     d1 = x->value.d;
04606     else if (x->type == XML_SCHEMAS_FLOAT)
04607     d1 = x->value.f;
04608     else
04609     return(-2);
04610 
04611     if (y->type == XML_SCHEMAS_DOUBLE)
04612     d2 = y->value.d;
04613     else if (y->type == XML_SCHEMAS_FLOAT)
04614     d2 = y->value.f;
04615     else
04616     return(-2);
04617 
04618     /*
04619      * Check for special cases.
04620      */
04621     if (xmlXPathIsNaN(d1)) {
04622     if (xmlXPathIsNaN(d2))
04623         return(0);
04624     return(1);
04625     }
04626     if (xmlXPathIsNaN(d2))
04627     return(-1);
04628     if (d1 == xmlXPathPINF) {
04629     if (d2 == xmlXPathPINF)
04630         return(0);
04631         return(1);
04632     }
04633     if (d2 == xmlXPathPINF)
04634         return(-1);
04635     if (d1 == xmlXPathNINF) {
04636     if (d2 == xmlXPathNINF)
04637         return(0);
04638         return(-1);
04639     }
04640     if (d2 == xmlXPathNINF)
04641         return(1);
04642 
04643     /*
04644      * basic tests, the last one we should have equality, but
04645      * portability is more important than speed and handling
04646      * NaN or Inf in a portable way is always a challenge, so ...
04647      */
04648     if (d1 < d2)
04649     return(-1);
04650     if (d1 > d2)
04651     return(1);
04652     if (d1 == d2)
04653     return(0);
04654     return(2);
04655 }
04656 
04671 static int
04672 xmlSchemaCompareValuesInternal(xmlSchemaValType xtype,
04673                    xmlSchemaValPtr x,
04674                    const xmlChar *xvalue,
04675                    xmlSchemaWhitespaceValueType xws,
04676                    xmlSchemaValType ytype,
04677                    xmlSchemaValPtr y,
04678                    const xmlChar *yvalue,
04679                    xmlSchemaWhitespaceValueType yws)
04680 {
04681     switch (xtype) {
04682     case XML_SCHEMAS_UNKNOWN:
04683     case XML_SCHEMAS_ANYTYPE:
04684         return(-2);
04685         case XML_SCHEMAS_INTEGER:
04686         case XML_SCHEMAS_NPINTEGER:
04687         case XML_SCHEMAS_NINTEGER:
04688         case XML_SCHEMAS_NNINTEGER:
04689         case XML_SCHEMAS_PINTEGER:
04690         case XML_SCHEMAS_INT:
04691         case XML_SCHEMAS_UINT:
04692         case XML_SCHEMAS_LONG:
04693         case XML_SCHEMAS_ULONG:
04694         case XML_SCHEMAS_SHORT:
04695         case XML_SCHEMAS_USHORT:
04696         case XML_SCHEMAS_BYTE:
04697         case XML_SCHEMAS_UBYTE:
04698     case XML_SCHEMAS_DECIMAL:
04699         if ((x == NULL) || (y == NULL))
04700         return(-2);
04701         if (ytype == xtype)
04702         return(xmlSchemaCompareDecimals(x, y));
04703         if ((ytype == XML_SCHEMAS_DECIMAL) ||
04704         (ytype == XML_SCHEMAS_INTEGER) ||
04705         (ytype == XML_SCHEMAS_NPINTEGER) ||
04706         (ytype == XML_SCHEMAS_NINTEGER) ||
04707         (ytype == XML_SCHEMAS_NNINTEGER) ||
04708         (ytype == XML_SCHEMAS_PINTEGER) ||
04709         (ytype == XML_SCHEMAS_INT) ||
04710         (ytype == XML_SCHEMAS_UINT) ||
04711         (ytype == XML_SCHEMAS_LONG) ||
04712         (ytype == XML_SCHEMAS_ULONG) ||
04713         (ytype == XML_SCHEMAS_SHORT) ||
04714         (ytype == XML_SCHEMAS_USHORT) ||
04715         (ytype == XML_SCHEMAS_BYTE) ||
04716         (ytype == XML_SCHEMAS_UBYTE))
04717         return(xmlSchemaCompareDecimals(x, y));
04718         return(-2);
04719         case XML_SCHEMAS_DURATION:
04720         if ((x == NULL) || (y == NULL))
04721         return(-2);
04722         if (ytype == XML_SCHEMAS_DURATION)
04723                 return(xmlSchemaCompareDurations(x, y));
04724             return(-2);
04725         case XML_SCHEMAS_TIME:
04726         case XML_SCHEMAS_GDAY:
04727         case XML_SCHEMAS_GMONTH:
04728         case XML_SCHEMAS_GMONTHDAY:
04729         case XML_SCHEMAS_GYEAR:
04730         case XML_SCHEMAS_GYEARMONTH:
04731         case XML_SCHEMAS_DATE:
04732         case XML_SCHEMAS_DATETIME:
04733         if ((x == NULL) || (y == NULL))
04734         return(-2);
04735             if ((ytype == XML_SCHEMAS_DATETIME)  ||
04736                 (ytype == XML_SCHEMAS_TIME)      ||
04737                 (ytype == XML_SCHEMAS_GDAY)      ||
04738                 (ytype == XML_SCHEMAS_GMONTH)    ||
04739                 (ytype == XML_SCHEMAS_GMONTHDAY) ||
04740                 (ytype == XML_SCHEMAS_GYEAR)     ||
04741                 (ytype == XML_SCHEMAS_DATE)      ||
04742                 (ytype == XML_SCHEMAS_GYEARMONTH))
04743                 return (xmlSchemaCompareDates(x, y));
04744             return (-2);
04745     /* 
04746     * Note that we will support comparison of string types against
04747     * anySimpleType as well.
04748     */
04749     case XML_SCHEMAS_ANYSIMPLETYPE:
04750     case XML_SCHEMAS_STRING:
04751         case XML_SCHEMAS_NORMSTRING:        
04752         case XML_SCHEMAS_TOKEN:
04753         case XML_SCHEMAS_LANGUAGE:
04754         case XML_SCHEMAS_NMTOKEN:
04755         case XML_SCHEMAS_NAME:
04756         case XML_SCHEMAS_NCNAME:
04757         case XML_SCHEMAS_ID:
04758         case XML_SCHEMAS_IDREF:
04759         case XML_SCHEMAS_ENTITY:
04760         case XML_SCHEMAS_ANYURI:
04761     {
04762         const xmlChar *xv, *yv;
04763 
04764         if (x == NULL)
04765         xv = xvalue;
04766         else
04767         xv = x->value.str;
04768         if (y == NULL)
04769         yv = yvalue;
04770         else
04771         yv = y->value.str;
04772         /*
04773         * TODO: Compare those against QName.
04774         */
04775         if (ytype == XML_SCHEMAS_QNAME) {       
04776         TODO
04777         if (y == NULL)
04778             return(-2);    
04779         return (-2);
04780         }
04781             if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) ||
04782         (ytype == XML_SCHEMAS_STRING) ||
04783         (ytype == XML_SCHEMAS_NORMSTRING) ||
04784                 (ytype == XML_SCHEMAS_TOKEN) ||
04785                 (ytype == XML_SCHEMAS_LANGUAGE) ||
04786                 (ytype == XML_SCHEMAS_NMTOKEN) ||
04787                 (ytype == XML_SCHEMAS_NAME) ||
04788                 (ytype == XML_SCHEMAS_NCNAME) ||
04789                 (ytype == XML_SCHEMAS_ID) ||
04790                 (ytype == XML_SCHEMAS_IDREF) ||
04791                 (ytype == XML_SCHEMAS_ENTITY) ||
04792                 (ytype == XML_SCHEMAS_ANYURI)) {
04793 
04794         if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) {
04795 
04796             if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) {
04797             /* TODO: What about x < y or x > y. */
04798             if (xmlStrEqual(xv, yv))
04799                 return (0);
04800             else 
04801                 return (2);
04802             } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
04803             return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0));
04804             else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
04805             return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0));
04806 
04807         } else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) {
04808 
04809             if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
04810             return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1));
04811             if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
04812             return (xmlSchemaCompareReplacedStrings(xv, yv));
04813             if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
04814             return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0));
04815 
04816         } else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) {
04817 
04818             if (yws == XML_SCHEMA_WHITESPACE_PRESERVE)
04819             return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1));
04820             if (yws == XML_SCHEMA_WHITESPACE_REPLACE)
04821             return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1));
04822             if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE)
04823             return (xmlSchemaCompareNormStrings(xv, yv));
04824         } else
04825             return (-2);
04826                 
04827         }
04828             return (-2);
04829     }
04830         case XML_SCHEMAS_QNAME:
04831     case XML_SCHEMAS_NOTATION:
04832         if ((x == NULL) || (y == NULL))
04833         return(-2);
04834             if ((ytype == XML_SCHEMAS_QNAME) ||
04835         (ytype == XML_SCHEMAS_NOTATION)) {
04836         if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) &&
04837             (xmlStrEqual(x->value.qname.uri, y->value.qname.uri)))
04838             return(0);
04839         return(2);
04840         }
04841         return (-2);
04842         case XML_SCHEMAS_FLOAT:
04843         case XML_SCHEMAS_DOUBLE:
04844         if ((x == NULL) || (y == NULL))
04845         return(-2);
04846             if ((ytype == XML_SCHEMAS_FLOAT) ||
04847                 (ytype == XML_SCHEMAS_DOUBLE))
04848                 return (xmlSchemaCompareFloats(x, y));
04849             return (-2);
04850         case XML_SCHEMAS_BOOLEAN:
04851         if ((x == NULL) || (y == NULL))
04852         return(-2);
04853             if (ytype == XML_SCHEMAS_BOOLEAN) {
04854         if (x->value.b == y->value.b)
04855             return(0);
04856         if (x->value.b == 0)
04857             return(-1);
04858         return(1);
04859         }
04860         return (-2);
04861         case XML_SCHEMAS_HEXBINARY:
04862         if ((x == NULL) || (y == NULL))
04863         return(-2);
04864             if (ytype == XML_SCHEMAS_HEXBINARY) {
04865             if (x->value.hex.total == y->value.hex.total) {
04866             int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str);
04867             if (ret > 0)
04868             return(1);
04869             else if (ret == 0)
04870             return(0);
04871         }
04872         else if (x->value.hex.total > y->value.hex.total)
04873             return(1);
04874 
04875         return(-1);
04876             }
04877             return (-2);
04878         case XML_SCHEMAS_BASE64BINARY:
04879         if ((x == NULL) || (y == NULL))
04880         return(-2);
04881             if (ytype == XML_SCHEMAS_BASE64BINARY) {
04882                 if (x->value.base64.total == y->value.base64.total) {
04883                     int ret = xmlStrcmp(x->value.base64.str,
04884                                 y->value.base64.str);
04885                     if (ret > 0)
04886                         return(1);
04887                     else if (ret == 0)
04888                         return(0);
04889             else
04890                 return(-1);
04891                 }
04892                 else if (x->value.base64.total > y->value.base64.total)
04893                     return(1);
04894                 else
04895                     return(-1);
04896             }
04897             return (-2);    
04898         case XML_SCHEMAS_IDREFS:
04899         case XML_SCHEMAS_ENTITIES:
04900         case XML_SCHEMAS_NMTOKENS:
04901         TODO
04902         break;
04903     }
04904     return -2;
04905 }
04906 
04917 int
04918 xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) {
04919     xmlSchemaWhitespaceValueType xws, yws;
04920 
04921     if ((x == NULL) || (y == NULL))
04922         return(-2);
04923     if (x->type == XML_SCHEMAS_STRING)
04924     xws = XML_SCHEMA_WHITESPACE_PRESERVE;
04925     else if (x->type == XML_SCHEMAS_NORMSTRING)
04926         xws = XML_SCHEMA_WHITESPACE_REPLACE;
04927     else
04928         xws = XML_SCHEMA_WHITESPACE_COLLAPSE;
04929 
04930     if (y->type == XML_SCHEMAS_STRING)
04931     yws = XML_SCHEMA_WHITESPACE_PRESERVE;
04932     else if (x->type == XML_SCHEMAS_NORMSTRING)
04933         yws = XML_SCHEMA_WHITESPACE_REPLACE;
04934     else
04935         yws = XML_SCHEMA_WHITESPACE_COLLAPSE;
04936 
04937     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
04938     y, NULL, yws));
04939 }
04940 
04953 int
04954 xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x,
04955                 xmlSchemaWhitespaceValueType xws,
04956                 xmlSchemaValPtr y,
04957                 xmlSchemaWhitespaceValueType yws)
04958 {
04959     if ((x == NULL) || (y == NULL))
04960     return(-2);
04961     return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type,
04962     y, NULL, yws));
04963 }
04964 
04977 static int
04978 xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype,
04979                    xmlSchemaValPtr x,
04980                    const xmlChar *xvalue,
04981                    xmlSchemaWhitespaceValueType xws,
04982                    xmlSchemaValType ytype,
04983                    xmlSchemaValPtr y,
04984                    const xmlChar *yvalue,
04985                    xmlSchemaWhitespaceValueType yws)
04986 {
04987     return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y,
04988     yvalue, yws));
04989 }
04990 
04999 static int
05000 xmlSchemaNormLen(const xmlChar *value) {
05001     const xmlChar *utf;
05002     int ret = 0;
05003 
05004     if (value == NULL)
05005     return(-1);
05006     utf = value;
05007     while (IS_BLANK_CH(*utf)) utf++;
05008     while (*utf != 0) {
05009     if (utf[0] & 0x80) {
05010         if ((utf[1] & 0xc0) != 0x80)
05011         return(-1);
05012         if ((utf[0] & 0xe0) == 0xe0) {
05013         if ((utf[2] & 0xc0) != 0x80)
05014             return(-1);
05015         if ((utf[0] & 0xf0) == 0xf0) {
05016             if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
05017             return(-1);
05018             utf += 4;
05019         } else {
05020             utf += 3;
05021         }
05022         } else {
05023         utf += 2;
05024         }
05025     } else if (IS_BLANK_CH(*utf)) {
05026         while (IS_BLANK_CH(*utf)) utf++;
05027         if (*utf == 0)
05028         break;
05029     } else {
05030         utf++;
05031     }
05032     ret++;
05033     }
05034     return(ret);
05035 }
05036 
05045 unsigned long
05046 xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet)
05047 {
05048     /*
05049     * TODO: Check if this is a decimal.
05050     */
05051     if (facet == NULL)
05052         return 0;
05053     return ((unsigned long) facet->val->value.decimal.lo);
05054 }
05055 
05068 int
05069 xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet,
05070                      const xmlChar *value,
05071                      unsigned long actualLen,
05072                      unsigned long *expectedLen)
05073 {
05074     if (facet == NULL)
05075         return(-1);
05076     /*
05077     * TODO: Check if this will work with large numbers.
05078     * (compare value.decimal.mi and value.decimal.hi as well?).
05079     */
05080     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
05081     if (actualLen != facet->val->value.decimal.lo) {
05082         if (expectedLen != NULL)
05083         *expectedLen = facet->val->value.decimal.lo;
05084         return (XML_SCHEMAV_CVC_LENGTH_VALID);
05085     }   
05086     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
05087     if (actualLen < facet->val->value.decimal.lo) {
05088         if (expectedLen != NULL)
05089         *expectedLen = facet->val->value.decimal.lo;
05090         return (XML_SCHEMAV_CVC_MINLENGTH_VALID);
05091     }
05092     } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) {
05093     if (actualLen > facet->val->value.decimal.lo) {
05094         if (expectedLen != NULL)
05095         *expectedLen = facet->val->value.decimal.lo;
05096         return (XML_SCHEMAV_CVC_MAXLENGTH_VALID);
05097     }
05098     } else
05099     /* 
05100     * NOTE: That we can pass NULL as xmlSchemaValPtr to 
05101     * xmlSchemaValidateFacet, since the remaining facet types
05102     * are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION. 
05103     */
05104     return(xmlSchemaValidateFacet(NULL, facet, value, NULL));   
05105     return (0);
05106 }
05107 
05123 static int
05124 xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet,
05125                      xmlSchemaTypeType valType,
05126                      const xmlChar *value,
05127                      xmlSchemaValPtr val,                    
05128                      unsigned long *length,
05129                      xmlSchemaWhitespaceValueType ws)  
05130 {
05131     unsigned int len = 0;
05132 
05133     if ((length == NULL) || (facet == NULL))
05134         return (-1);
05135     *length = 0;
05136     if ((facet->type != XML_SCHEMA_FACET_LENGTH) &&
05137     (facet->type != XML_SCHEMA_FACET_MAXLENGTH) &&
05138     (facet->type != XML_SCHEMA_FACET_MINLENGTH))
05139     return (-1);
05140     
05141     /*
05142     * TODO: length, maxLength and minLength must be of type
05143     * nonNegativeInteger only. Check if decimal is used somehow.
05144     */
05145     if ((facet->val == NULL) ||
05146     ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
05147      (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
05148     (facet->val->value.decimal.frac != 0)) {
05149     return(-1);
05150     }
05151     if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
05152     len = val->value.hex.total;
05153     else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
05154     len = val->value.base64.total;
05155     else {
05156     switch (valType) {
05157         case XML_SCHEMAS_STRING:
05158         case XML_SCHEMAS_NORMSTRING:
05159         if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
05160             /*
05161             * This is to ensure API compatibility with the old
05162             * xmlSchemaValidateLengthFacet(). Anyway, this was and
05163             * is not the correct handling.
05164             * TODO: Get rid of this case somehow.
05165             */
05166             if (valType == XML_SCHEMAS_STRING)
05167             len = xmlUTF8Strlen(value);
05168             else
05169             len = xmlSchemaNormLen(value);
05170         } else if (value != NULL) {
05171             if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
05172             len = xmlSchemaNormLen(value);
05173             else
05174             /* 
05175             * Should be OK for "preserve" as well.
05176             */
05177             len = xmlUTF8Strlen(value);
05178         }
05179         break;
05180         case XML_SCHEMAS_IDREF:
05181         case XML_SCHEMAS_TOKEN:
05182         case XML_SCHEMAS_LANGUAGE:
05183         case XML_SCHEMAS_NMTOKEN:
05184         case XML_SCHEMAS_NAME:
05185         case XML_SCHEMAS_NCNAME:
05186         case XML_SCHEMAS_ID:        
05187         /*
05188         * FIXME: What exactly to do with anyURI?
05189         */
05190         case XML_SCHEMAS_ANYURI:
05191         if (value != NULL)
05192             len = xmlSchemaNormLen(value);
05193         break;
05194         case XML_SCHEMAS_QNAME:
05195         case XML_SCHEMAS_NOTATION:
05196         /*
05197         * For QName and NOTATION, those facets are
05198         * deprecated and should be ignored.
05199         */
05200         return (0);
05201         default:
05202         TODO
05203     }
05204     }
05205     *length = (unsigned long) len;
05206     /*
05207     * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi".
05208     */
05209     if (facet->type == XML_SCHEMA_FACET_LENGTH) {
05210     if (len != facet->val->value.decimal.lo)
05211         return(XML_SCHEMAV_CVC_LENGTH_VALID);
05212     } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
05213     if (len < facet->val->value.decimal.lo)
05214         return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
05215     } else {
05216     if (len > facet->val->value.decimal.lo)
05217         return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
05218     }
05219     
05220     return (0);
05221 }
05222 
05237 int
05238 xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type, 
05239                  xmlSchemaFacetPtr facet,
05240                  const xmlChar *value,
05241                  xmlSchemaValPtr val,
05242                  unsigned long *length)  
05243 {
05244     if (type == NULL)
05245         return(-1);
05246     return (xmlSchemaValidateLengthFacetInternal(facet,
05247     type->builtInType, value, val, length,
05248     XML_SCHEMA_WHITESPACE_UNKNOWN));
05249 }
05250 
05266 int
05267 xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet,
05268                   xmlSchemaValType valType,
05269                   const xmlChar *value,
05270                   xmlSchemaValPtr val,
05271                   unsigned long *length,
05272                   xmlSchemaWhitespaceValueType ws)
05273 {
05274     return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val,
05275     length, ws));
05276 }
05277 
05292 static int
05293 xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet,
05294                    xmlSchemaWhitespaceValueType fws,
05295                    xmlSchemaValType valType,                   
05296                    const xmlChar *value,
05297                    xmlSchemaValPtr val,
05298                    xmlSchemaWhitespaceValueType ws)
05299 {
05300     int ret;
05301 
05302     if (facet == NULL)
05303     return(-1);
05304 
05305     switch (facet->type) {
05306     case XML_SCHEMA_FACET_PATTERN:
05307         /* 
05308         * NOTE that for patterns, the @value needs to be the normalized
05309         * value, *not* the lexical initial value or the canonical value.
05310         */
05311         if (value == NULL)
05312         return(-1);
05313         ret = xmlRegexpExec(facet->regexp, value);
05314         if (ret == 1)
05315         return(0);
05316         if (ret == 0)
05317         return(XML_SCHEMAV_CVC_PATTERN_VALID);
05318         return(ret);
05319     case XML_SCHEMA_FACET_MAXEXCLUSIVE:
05320         ret = xmlSchemaCompareValues(val, facet->val);
05321         if (ret == -2)
05322         return(-1);
05323         if (ret == -1)
05324         return(0);
05325         return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID);
05326     case XML_SCHEMA_FACET_MAXINCLUSIVE:
05327         ret = xmlSchemaCompareValues(val, facet->val);
05328         if (ret == -2)
05329         return(-1);
05330         if ((ret == -1) || (ret == 0))
05331         return(0);
05332         return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID);
05333     case XML_SCHEMA_FACET_MINEXCLUSIVE:
05334         ret = xmlSchemaCompareValues(val, facet->val);
05335         if (ret == -2)
05336         return(-1);
05337         if (ret == 1)
05338         return(0);
05339         return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID);
05340     case XML_SCHEMA_FACET_MININCLUSIVE:
05341         ret = xmlSchemaCompareValues(val, facet->val);
05342         if (ret == -2)
05343         return(-1);
05344         if ((ret == 1) || (ret == 0))
05345         return(0);
05346         return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID);
05347     case XML_SCHEMA_FACET_WHITESPACE:
05348         /* TODO whitespaces */
05349         /*
05350         * NOTE: Whitespace should be handled to normalize
05351         * the value to be validated against a the facets;
05352         * not to normalize the value in-between.
05353         */
05354         return(0);
05355     case  XML_SCHEMA_FACET_ENUMERATION:
05356         if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
05357         /*
05358         * This is to ensure API compatibility with the old
05359         * xmlSchemaValidateFacet().
05360         * TODO: Get rid of this case.
05361         */
05362         if ((facet->value != NULL) &&
05363             (xmlStrEqual(facet->value, value)))
05364             return(0);
05365         } else {
05366         ret = xmlSchemaCompareValuesWhtspExt(facet->val->type,
05367             facet->val, facet->value, fws, valType, val,
05368             value, ws);
05369         if (ret == -2)
05370             return(-1);
05371         if (ret == 0)
05372             return(0);
05373         }
05374         return(XML_SCHEMAV_CVC_ENUMERATION_VALID);
05375     case XML_SCHEMA_FACET_LENGTH:
05376         /*
05377         * SPEC (1.3) "if {primitive type definition} is QName or NOTATION,
05378         * then any {value} is facet-valid."
05379         */
05380         if ((valType == XML_SCHEMAS_QNAME) ||
05381         (valType == XML_SCHEMAS_NOTATION))
05382         return (0);
05383         /* No break on purpose. */
05384     case XML_SCHEMA_FACET_MAXLENGTH:
05385     case XML_SCHEMA_FACET_MINLENGTH: {
05386         unsigned int len = 0;
05387 
05388         if ((valType == XML_SCHEMAS_QNAME) ||
05389         (valType == XML_SCHEMAS_NOTATION))
05390         return (0);
05391         /*
05392         * TODO: length, maxLength and minLength must be of type
05393         * nonNegativeInteger only. Check if decimal is used somehow.
05394         */
05395         if ((facet->val == NULL) ||
05396         ((facet->val->type != XML_SCHEMAS_DECIMAL) &&
05397          (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
05398         (facet->val->value.decimal.frac != 0)) {
05399         return(-1);
05400         }
05401         if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY))
05402         len = val->value.hex.total;
05403         else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY))
05404         len = val->value.base64.total;
05405         else {
05406         switch (valType) {
05407             case XML_SCHEMAS_STRING:
05408             case XML_SCHEMAS_NORMSTRING:            
05409             if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) {
05410                 /*
05411                 * This is to ensure API compatibility with the old
05412                 * xmlSchemaValidateFacet(). Anyway, this was and
05413                 * is not the correct handling.
05414                 * TODO: Get rid of this case somehow.
05415                 */
05416                 if (valType == XML_SCHEMAS_STRING)
05417                 len = xmlUTF8Strlen(value);
05418                 else
05419                 len = xmlSchemaNormLen(value);
05420             } else if (value != NULL) {
05421                 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
05422                 len = xmlSchemaNormLen(value);
05423                 else
05424                 /* 
05425                 * Should be OK for "preserve" as well.
05426                 */
05427                 len = xmlUTF8Strlen(value);
05428             }
05429             break;
05430                 case XML_SCHEMAS_IDREF:         
05431             case XML_SCHEMAS_TOKEN:
05432             case XML_SCHEMAS_LANGUAGE:
05433             case XML_SCHEMAS_NMTOKEN:
05434             case XML_SCHEMAS_NAME:
05435             case XML_SCHEMAS_NCNAME:
05436             case XML_SCHEMAS_ID:
05437             case XML_SCHEMAS_ANYURI:
05438             if (value != NULL)
05439                     len = xmlSchemaNormLen(value);
05440                 break;         
05441             default:
05442                 TODO
05443             }
05444         }
05445         if (facet->type == XML_SCHEMA_FACET_LENGTH) {
05446         if (len != facet->val->value.decimal.lo)
05447             return(XML_SCHEMAV_CVC_LENGTH_VALID);
05448         } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) {
05449         if (len < facet->val->value.decimal.lo)
05450             return(XML_SCHEMAV_CVC_MINLENGTH_VALID);
05451         } else {
05452         if (len > facet->val->value.decimal.lo)
05453             return(XML_SCHEMAV_CVC_MAXLENGTH_VALID);
05454         }
05455         break;
05456     }
05457     case XML_SCHEMA_FACET_TOTALDIGITS:
05458     case XML_SCHEMA_FACET_FRACTIONDIGITS:
05459 
05460         if ((facet->val == NULL) ||
05461         ((facet->val->type != XML_SCHEMAS_PINTEGER) &&
05462          (facet->val->type != XML_SCHEMAS_NNINTEGER)) ||
05463         (facet->val->value.decimal.frac != 0)) {
05464         return(-1);
05465         }
05466         if ((val == NULL) ||
05467         ((val->type != XML_SCHEMAS_DECIMAL) &&
05468          (val->type != XML_SCHEMAS_INTEGER) &&
05469          (val->type != XML_SCHEMAS_NPINTEGER) &&
05470          (val->type != XML_SCHEMAS_NINTEGER) &&
05471          (val->type != XML_SCHEMAS_NNINTEGER) &&
05472          (val->type != XML_SCHEMAS_PINTEGER) &&
05473          (val->type != XML_SCHEMAS_INT) &&
05474          (val->type != XML_SCHEMAS_UINT) &&
05475          (val->type != XML_SCHEMAS_LONG) &&
05476          (val->type != XML_SCHEMAS_ULONG) &&
05477          (val->type != XML_SCHEMAS_SHORT) &&
05478          (val->type != XML_SCHEMAS_USHORT) &&
05479          (val->type != XML_SCHEMAS_BYTE) &&
05480          (val->type != XML_SCHEMAS_UBYTE))) {
05481         return(-1);
05482         }
05483         if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
05484             if (val->value.decimal.total > facet->val->value.decimal.lo)
05485                 return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID);
05486 
05487         } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) {
05488             if (val->value.decimal.frac > facet->val->value.decimal.lo)
05489             return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID);
05490         }
05491         break;
05492     default:
05493         TODO
05494     }
05495     return(0);
05496 
05497 }
05498 
05511 int
05512 xmlSchemaValidateFacet(xmlSchemaTypePtr base,
05513                    xmlSchemaFacetPtr facet,
05514                    const xmlChar *value,
05515                xmlSchemaValPtr val)
05516 {
05517     /*
05518     * This tries to ensure API compatibility regarding the old
05519     * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and
05520     * xmlSchemaValidateFacetWhtsp().
05521     */
05522     if (val != NULL)
05523     return(xmlSchemaValidateFacetInternal(facet,
05524         XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val,
05525         XML_SCHEMA_WHITESPACE_UNKNOWN));
05526     else if (base != NULL)
05527     return(xmlSchemaValidateFacetInternal(facet,
05528         XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val,
05529         XML_SCHEMA_WHITESPACE_UNKNOWN));
05530     return(-1);
05531 }
05532 
05550 int
05551 xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet,
05552                 xmlSchemaWhitespaceValueType fws,
05553                 xmlSchemaValType valType,               
05554                 const xmlChar *value,
05555                 xmlSchemaValPtr val,
05556                 xmlSchemaWhitespaceValueType ws)
05557 {
05558      return(xmlSchemaValidateFacetInternal(facet, fws, valType,
05559      value, val, ws));
05560 }
05561 
05562 #if 0
05563 #ifndef DBL_DIG
05564 #define DBL_DIG 16
05565 #endif
05566 #ifndef DBL_EPSILON
05567 #define DBL_EPSILON 1E-9
05568 #endif
05569 
05570 #define INTEGER_DIGITS DBL_DIG
05571 #define FRACTION_DIGITS (DBL_DIG + 1)
05572 #define EXPONENT_DIGITS (3 + 2)
05573 
05582 static void
05583 xmlSchemaFormatFloat(double number, char buffer[], int buffersize)
05584 {
05585     switch (xmlXPathIsInf(number)) {
05586     case 1:
05587     if (buffersize > (int)sizeof("INF"))
05588         snprintf(buffer, buffersize, "INF");
05589     break;
05590     case -1:
05591     if (buffersize > (int)sizeof("-INF"))
05592         snprintf(buffer, buffersize, "-INF");
05593     break;
05594     default:
05595     if (xmlXPathIsNaN(number)) {
05596         if (buffersize > (int)sizeof("NaN"))
05597         snprintf(buffer, buffersize, "NaN");
05598     } else if (number == 0) {
05599         snprintf(buffer, buffersize, "0.0E0");
05600     } else {
05601         /* 3 is sign, decimal point, and terminating zero */
05602         char work[DBL_DIG + EXPONENT_DIGITS + 3];
05603         int integer_place, fraction_place;
05604         char *ptr;
05605         char *after_fraction;
05606         double absolute_value;
05607         int size;
05608 
05609         absolute_value = fabs(number);
05610 
05611         /*
05612          * Result is in work, and after_fraction points
05613          * just past the fractional part.
05614          * Use scientific notation 
05615         */
05616         integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
05617         fraction_place = DBL_DIG - 1;
05618         snprintf(work, sizeof(work),"%*.*e",
05619         integer_place, fraction_place, number);
05620         after_fraction = strchr(work + DBL_DIG, 'e');       
05621         /* Remove fractional trailing zeroes */
05622         ptr = after_fraction;
05623         while (*(--ptr) == '0')
05624         ;
05625         if (*ptr != '.')
05626             ptr++;
05627         while ((*ptr++ = *after_fraction++) != 0);
05628 
05629         /* Finally copy result back to caller */
05630         size = strlen(work) + 1;
05631         if (size > buffersize) {
05632         work[buffersize - 1] = 0;
05633         size = buffersize;
05634         }
05635         memmove(buffer, work, size);
05636     }
05637     break;
05638     }
05639 }
05640 #endif
05641 
05661 int
05662 xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue)
05663 {
05664     if ((retValue == NULL) || (val == NULL))
05665     return (-1);
05666     *retValue = NULL;
05667     switch (val->type) {
05668     case XML_SCHEMAS_STRING:
05669         if (val->value.str == NULL)
05670         *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
05671         else
05672         *retValue = 
05673             BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
05674         break;
05675     case XML_SCHEMAS_NORMSTRING:
05676         if (val->value.str == NULL)
05677         *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
05678         else {
05679         *retValue = xmlSchemaWhiteSpaceReplace(
05680             (const xmlChar *) val->value.str);
05681         if ((*retValue) == NULL)
05682             *retValue = BAD_CAST xmlStrdup(
05683             (const xmlChar *) val->value.str);
05684         }
05685         break;
05686     case XML_SCHEMAS_TOKEN:
05687     case XML_SCHEMAS_LANGUAGE:
05688     case XML_SCHEMAS_NMTOKEN:
05689     case XML_SCHEMAS_NAME:  
05690     case XML_SCHEMAS_NCNAME:
05691     case XML_SCHEMAS_ID:
05692     case XML_SCHEMAS_IDREF:
05693     case XML_SCHEMAS_ENTITY:
05694     case XML_SCHEMAS_NOTATION: /* Unclear */
05695     case XML_SCHEMAS_ANYURI:   /* Unclear */
05696         if (val->value.str == NULL)
05697         return (-1);
05698         *retValue = 
05699         BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str);
05700         if (*retValue == NULL)
05701         *retValue = 
05702             BAD_CAST xmlStrdup((const xmlChar *) val->value.str);
05703         break;
05704     case XML_SCHEMAS_QNAME:
05705         /* TODO: Unclear in XML Schema 1.0. */
05706         if (val->value.qname.uri == NULL) {
05707         *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name);
05708         return (0);
05709         } else {
05710         *retValue = BAD_CAST xmlStrdup(BAD_CAST "{");
05711         *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
05712             BAD_CAST val->value.qname.uri);
05713         *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
05714             BAD_CAST "}");
05715         *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue),
05716             BAD_CAST val->value.qname.uri);
05717         }
05718         break;
05719     case XML_SCHEMAS_DECIMAL:
05720         /*
05721         * TODO: Lookout for a more simple implementation.
05722         */
05723         if ((val->value.decimal.total == 1) && 
05724         (val->value.decimal.lo == 0)) {
05725         *retValue = xmlStrdup(BAD_CAST "0.0");
05726         } else {
05727         xmlSchemaValDecimal dec = val->value.decimal;
05728         int bufsize;
05729         char *buf = NULL, *offs;
05730 
05731         /* Add room for the decimal point as well. */
05732         bufsize = dec.total + 2;
05733         if (dec.sign)
05734             bufsize++;
05735         /* Add room for leading/trailing zero. */
05736         if ((dec.frac == 0) || (dec.frac == dec.total))
05737             bufsize++;
05738         buf = xmlMalloc(bufsize);
05739         if (buf == NULL)
05740             return(-1);
05741         offs = buf;
05742         if (dec.sign)
05743             *offs++ = '-';
05744         if (dec.frac == dec.total) {
05745             *offs++ = '0';
05746             *offs++ = '.';
05747         }
05748         if (dec.hi != 0)
05749             snprintf(offs, bufsize - (offs - buf),
05750             "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
05751         else if (dec.mi != 0)
05752             snprintf(offs, bufsize - (offs - buf),
05753             "%lu%lu", dec.mi, dec.lo);
05754         else
05755             snprintf(offs, bufsize - (offs - buf),
05756             "%lu", dec.lo);
05757             
05758         if (dec.frac != 0) {
05759             if (dec.frac != dec.total) {
05760             int diff = dec.total - dec.frac;
05761             /*
05762             * Insert the decimal point.
05763             */
05764             memmove(offs + diff + 1, offs + diff, dec.frac +1);
05765             offs[diff] = '.';
05766             } else {
05767             unsigned int i = 0;
05768             /*
05769             * Insert missing zeroes behind the decimal point.
05770             */          
05771             while (*(offs + i) != 0)
05772                 i++;
05773             if (i < dec.total) {
05774                 memmove(offs + (dec.total - i), offs, i +1);
05775                 memset(offs, '0', dec.total - i);
05776             }
05777             }
05778         } else {
05779             /*
05780             * Append decimal point and zero.
05781             */
05782             offs = buf + bufsize - 1;
05783             *offs-- = 0;
05784             *offs-- = '0';
05785             *offs-- = '.';
05786         }
05787         *retValue = BAD_CAST buf;
05788         }
05789         break;
05790     case XML_SCHEMAS_INTEGER:
05791         case XML_SCHEMAS_PINTEGER:
05792         case XML_SCHEMAS_NPINTEGER:
05793         case XML_SCHEMAS_NINTEGER:
05794         case XML_SCHEMAS_NNINTEGER:
05795     case XML_SCHEMAS_LONG:
05796         case XML_SCHEMAS_BYTE:
05797         case XML_SCHEMAS_SHORT:
05798         case XML_SCHEMAS_INT:
05799     case XML_SCHEMAS_UINT:
05800         case XML_SCHEMAS_ULONG:
05801         case XML_SCHEMAS_USHORT:
05802         case XML_SCHEMAS_UBYTE:
05803         if ((val->value.decimal.total == 1) &&
05804         (val->value.decimal.lo == 0))
05805         *retValue = xmlStrdup(BAD_CAST "0");
05806         else {
05807         xmlSchemaValDecimal dec = val->value.decimal;
05808         int bufsize = dec.total + 1;
05809 
05810         /* Add room for the decimal point as well. */
05811         if (dec.sign)
05812             bufsize++;
05813         *retValue = xmlMalloc(bufsize);
05814         if (*retValue == NULL)
05815             return(-1);
05816         if (dec.hi != 0) {
05817             if (dec.sign)
05818             snprintf((char *) *retValue, bufsize,
05819                 "-%lu%lu%lu", dec.hi, dec.mi, dec.lo);
05820             else
05821             snprintf((char *) *retValue, bufsize,
05822                 "%lu%lu%lu", dec.hi, dec.mi, dec.lo);
05823         } else if (dec.mi != 0) {
05824             if (dec.sign)
05825             snprintf((char *) *retValue, bufsize,
05826                 "-%lu%lu", dec.mi, dec.lo);
05827             else
05828             snprintf((char *) *retValue, bufsize,
05829                 "%lu%lu", dec.mi, dec.lo);
05830         } else {
05831             if (dec.sign)
05832             snprintf((char *) *retValue, bufsize, "-%lu", dec.lo);
05833             else
05834             snprintf((char *) *retValue, bufsize, "%lu", dec.lo);
05835         }
05836         }
05837         break;
05838     case XML_SCHEMAS_BOOLEAN:
05839         if (val->value.b)
05840         *retValue = BAD_CAST xmlStrdup(BAD_CAST "true");
05841         else
05842         *retValue = BAD_CAST xmlStrdup(BAD_CAST "false");
05843         break;
05844     case XML_SCHEMAS_DURATION: {
05845         char buf[100];
05846         unsigned long year;
05847         unsigned long mon, day, hour = 0, min = 0;
05848         double sec = 0, left;
05849 
05850         /* TODO: Unclear in XML Schema 1.0 */
05851         /*
05852         * TODO: This results in a normalized output of the value
05853         * - which is NOT conformant to the spec -
05854         * since the exact values of each property are not
05855         * recoverable. Think about extending the structure to
05856         * provide a field for every property.
05857         */
05858         year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12);
05859         mon = labs(val->value.dur.mon) - 12 * year;
05860 
05861         day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400);
05862         left = fabs(val->value.dur.sec) - day * 86400;
05863         if (left > 0) {
05864             hour = (unsigned long) FQUOTIENT(left, 3600);
05865             left = left - (hour * 3600);
05866             if (left > 0) {
05867             min = (unsigned long) FQUOTIENT(left, 60);
05868             sec = left - (min * 60);
05869             }
05870         }
05871         if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0))
05872             snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS",
05873             year, mon, day, hour, min, sec);
05874         else
05875             snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS",
05876             year, mon, day, hour, min, sec);
05877         *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
05878         }
05879         break;
05880     case XML_SCHEMAS_GYEAR: {
05881         char buf[30];
05882         /* TODO: Unclear in XML Schema 1.0 */
05883         /* TODO: What to do with the timezone? */
05884         snprintf(buf, 30, "%04ld", val->value.date.year);
05885         *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
05886         }
05887         break;
05888     case XML_SCHEMAS_GMONTH: {
05889         /* TODO: Unclear in XML Schema 1.0 */
05890         /* TODO: What to do with the timezone? */
05891         *retValue = xmlMalloc(6);
05892         if (*retValue == NULL)
05893             return(-1);
05894         snprintf((char *) *retValue, 6, "--%02u",
05895             val->value.date.mon);
05896         }
05897         break;
05898         case XML_SCHEMAS_GDAY: {
05899         /* TODO: Unclear in XML Schema 1.0 */
05900         /* TODO: What to do with the timezone? */
05901         *retValue = xmlMalloc(6);
05902         if (*retValue == NULL)
05903             return(-1);
05904         snprintf((char *) *retValue, 6, "---%02u",
05905             val->value.date.day);
05906         }
05907         break;        
05908         case XML_SCHEMAS_GMONTHDAY: {
05909         /* TODO: Unclear in XML Schema 1.0 */
05910         /* TODO: What to do with the timezone? */
05911         *retValue = xmlMalloc(8);
05912         if (*retValue == NULL)
05913             return(-1);
05914         snprintf((char *) *retValue, 8, "--%02u-%02u",
05915             val->value.date.mon, val->value.date.day);
05916         }
05917         break;
05918         case XML_SCHEMAS_GYEARMONTH: {
05919         char buf[35];
05920         /* TODO: Unclear in XML Schema 1.0 */
05921         /* TODO: What to do with the timezone? */
05922         if (val->value.date.year < 0)
05923             snprintf(buf, 35, "-%04ld-%02u",
05924             labs(val->value.date.year), 
05925             val->value.date.mon);
05926         else
05927             snprintf(buf, 35, "%04ld-%02u",
05928             val->value.date.year, val->value.date.mon);
05929         *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
05930         }
05931         break;      
05932     case XML_SCHEMAS_TIME:
05933         {
05934         char buf[30];
05935 
05936         if (val->value.date.tz_flag) {
05937             xmlSchemaValPtr norm;
05938 
05939             norm = xmlSchemaDateNormalize(val, 0);
05940             if (norm == NULL)
05941             return (-1);
05942             /* 
05943             * TODO: Check if "%.14g" is portable.           
05944             */
05945             snprintf(buf, 30,
05946             "%02u:%02u:%02.14gZ",
05947             norm->value.date.hour,
05948             norm->value.date.min,
05949             norm->value.date.sec);
05950             xmlSchemaFreeValue(norm);
05951         } else {
05952             snprintf(buf, 30,
05953             "%02u:%02u:%02.14g",
05954             val->value.date.hour,
05955             val->value.date.min,
05956             val->value.date.sec);
05957         }
05958         *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
05959         }       
05960         break;
05961         case XML_SCHEMAS_DATE:
05962         {
05963         char buf[30];
05964 
05965         if (val->value.date.tz_flag) {
05966             xmlSchemaValPtr norm;
05967 
05968             norm = xmlSchemaDateNormalize(val, 0);
05969             if (norm == NULL)
05970             return (-1);
05971             /*
05972             * TODO: Append the canonical value of the
05973             * recoverable timezone and not "Z".
05974             */
05975             snprintf(buf, 30,
05976             "%04ld:%02u:%02uZ",
05977             norm->value.date.year, norm->value.date.mon,
05978             norm->value.date.day);
05979             xmlSchemaFreeValue(norm);
05980         } else {
05981             snprintf(buf, 30,
05982             "%04ld:%02u:%02u",
05983             val->value.date.year, val->value.date.mon,
05984             val->value.date.day);
05985         }
05986         *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
05987         }       
05988         break;
05989         case XML_SCHEMAS_DATETIME:
05990         {
05991         char buf[50];
05992 
05993         if (val->value.date.tz_flag) {
05994             xmlSchemaValPtr norm;
05995 
05996             norm = xmlSchemaDateNormalize(val, 0);
05997             if (norm == NULL)
05998             return (-1);
05999             /*
06000             * TODO: Check if "%.14g" is portable.
06001             */
06002             snprintf(buf, 50,
06003             "%04ld:%02u:%02uT%02u:%02u:%02.14gZ",
06004             norm->value.date.year, norm->value.date.mon,
06005             norm->value.date.day, norm->value.date.hour,
06006             norm->value.date.min, norm->value.date.sec);
06007             xmlSchemaFreeValue(norm);
06008         } else {
06009             snprintf(buf, 50,
06010             "%04ld:%02u:%02uT%02u:%02u:%02.14g",
06011             val->value.date.year, val->value.date.mon,
06012             val->value.date.day, val->value.date.hour,
06013             val->value.date.min, val->value.date.sec);
06014         }
06015         *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
06016         }
06017         break;
06018     case XML_SCHEMAS_HEXBINARY:
06019         *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str);
06020         break;
06021     case XML_SCHEMAS_BASE64BINARY:
06022         /*
06023         * TODO: Is the following spec piece implemented?:
06024         * SPEC: "Note: For some values the canonical form defined
06025         * above does not conform to [RFC 2045], which requires breaking
06026         * with linefeeds at appropriate intervals."
06027         */
06028         *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str);
06029         break;
06030     case XML_SCHEMAS_FLOAT: {
06031         char buf[30];       
06032         /* 
06033         * |m| < 16777216, -149 <= e <= 104.
06034         * TODO: Handle, NaN, INF, -INF. The format is not
06035         * yet conformant. The c type float does not cover
06036         * the whole range.
06037         */
06038         snprintf(buf, 30, "%01.14e", val->value.f);
06039         *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
06040         }
06041         break;
06042     case XML_SCHEMAS_DOUBLE: {
06043         char buf[40];
06044         /* |m| < 9007199254740992, -1075 <= e <= 970 */
06045         /*
06046         * TODO: Handle, NaN, INF, -INF. The format is not
06047         * yet conformant. The c type float does not cover
06048         * the whole range.
06049         */
06050         snprintf(buf, 40, "%01.14e", val->value.d);
06051         *retValue = BAD_CAST xmlStrdup(BAD_CAST buf);
06052         }
06053         break;  
06054     default:
06055         *retValue = BAD_CAST xmlStrdup(BAD_CAST "???");
06056         return (1);
06057     }
06058     if (*retValue == NULL)
06059     return(-1);
06060     return (0);
06061 }
06062 
06075 int
06076 xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val,
06077                 const xmlChar **retValue,
06078                 xmlSchemaWhitespaceValueType ws)
06079 {
06080     if ((retValue == NULL) || (val == NULL))
06081     return (-1);
06082     if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) ||
06083     (ws > XML_SCHEMA_WHITESPACE_COLLAPSE))
06084     return (-1);
06085 
06086     *retValue = NULL;
06087     switch (val->type) {
06088     case XML_SCHEMAS_STRING:
06089         if (val->value.str == NULL)
06090         *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
06091         else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
06092         *retValue = xmlSchemaCollapseString(val->value.str);
06093         else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
06094         *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
06095         if ((*retValue) == NULL)
06096         *retValue = BAD_CAST xmlStrdup(val->value.str);
06097         break;
06098     case XML_SCHEMAS_NORMSTRING:
06099         if (val->value.str == NULL)
06100         *retValue = BAD_CAST xmlStrdup(BAD_CAST "");
06101         else {
06102         if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
06103             *retValue = xmlSchemaCollapseString(val->value.str);
06104         else
06105             *retValue = xmlSchemaWhiteSpaceReplace(val->value.str);
06106         if ((*retValue) == NULL)
06107             *retValue = BAD_CAST xmlStrdup(val->value.str);
06108         }
06109         break;
06110     default:
06111         return (xmlSchemaGetCanonValue(val, retValue));
06112     }    
06113     return (0);
06114 }
06115 
06124 xmlSchemaValType
06125 xmlSchemaGetValType(xmlSchemaValPtr val)
06126 {
06127     if (val == NULL)
06128         return(XML_SCHEMAS_UNKNOWN);
06129     return (val->type);
06130 }
06131 
06132 #define bottom_xmlschemastypes
06133 #include "elfgcchack.h"
06134 #endif /* LIBXML_SCHEMAS_ENABLED */

Generated on Sat May 26 2012 04:33:53 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.