File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libxml2 / xmlschemastypes.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 19:53:28 2014 UTC (10 years ago) by misho
Branches: libxml2, MAIN
CVS tags: v2_9_1p0, v2_9_1, HEAD
libxml2 2.9.1

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

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