diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2017-05-03 15:21:49 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2017-05-03 15:21:49 (GMT) |
commit | 4b8453f0303492a1de2dcf854555f6429fac550e (patch) | |
tree | 54abb57f4c5191452cadcac2f12feacbfc1f3218 /libxml2/xmlschemastypes.c | |
parent | 7617e7a38edce33eab6ca4259b416b339e07ea29 (diff) | |
download | blt-4b8453f0303492a1de2dcf854555f6429fac550e.zip blt-4b8453f0303492a1de2dcf854555f6429fac550e.tar.gz blt-4b8453f0303492a1de2dcf854555f6429fac550e.tar.bz2 |
reinstall libxml2/libxslt
Diffstat (limited to 'libxml2/xmlschemastypes.c')
-rw-r--r-- | libxml2/xmlschemastypes.c | 6152 |
1 files changed, 0 insertions, 6152 deletions
diff --git a/libxml2/xmlschemastypes.c b/libxml2/xmlschemastypes.c deleted file mode 100644 index 5f38599..0000000 --- a/libxml2/xmlschemastypes.c +++ /dev/null @@ -1,6152 +0,0 @@ -/* - * schemastypes.c : implementation of the XML Schema Datatypes - * definition and validity checking - * - * See Copyright for the status of this software. - * - * Daniel Veillard <veillard@redhat.com> - */ - -#define IN_LIBXML -#include "libxml.h" - -#ifdef LIBXML_SCHEMAS_ENABLED - -#include <string.h> -#include <libxml/xmlmemory.h> -#include <libxml/parser.h> -#include <libxml/parserInternals.h> -#include <libxml/hash.h> -#include <libxml/valid.h> -#include <libxml/xpath.h> -#include <libxml/uri.h> - -#include <libxml/xmlschemas.h> -#include <libxml/schemasInternals.h> -#include <libxml/xmlschemastypes.h> - -#ifdef HAVE_MATH_H -#include <math.h> -#endif -#ifdef HAVE_FLOAT_H -#include <float.h> -#endif - -#define DEBUG - -#ifndef LIBXML_XPATH_ENABLED -extern double xmlXPathNAN; -extern double xmlXPathPINF; -extern double xmlXPathNINF; -#endif - -#define TODO \ - xmlGenericError(xmlGenericErrorContext, \ - "Unimplemented block at %s:%d\n", \ - __FILE__, __LINE__); - -#define XML_SCHEMAS_NAMESPACE_NAME \ - (const xmlChar *)"http://www.w3.org/2001/XMLSchema" - -#define IS_WSP_REPLACE_CH(c) ((((c) == 0x9) || ((c) == 0xa)) || \ - ((c) == 0xd)) - -#define IS_WSP_SPACE_CH(c) ((c) == 0x20) - -#define IS_WSP_BLANK_CH(c) IS_BLANK_CH(c) - -/* Date value */ -typedef struct _xmlSchemaValDate xmlSchemaValDate; -typedef xmlSchemaValDate *xmlSchemaValDatePtr; -struct _xmlSchemaValDate { - long year; - unsigned int mon :4; /* 1 <= mon <= 12 */ - unsigned int day :5; /* 1 <= day <= 31 */ - unsigned int hour :5; /* 0 <= hour <= 24 */ - unsigned int min :6; /* 0 <= min <= 59 */ - double sec; - unsigned int tz_flag :1; /* is tzo explicitely set? */ - signed int tzo :12; /* -1440 <= tzo <= 1440; - currently only -840 to +840 are needed */ -}; - -/* Duration value */ -typedef struct _xmlSchemaValDuration xmlSchemaValDuration; -typedef xmlSchemaValDuration *xmlSchemaValDurationPtr; -struct _xmlSchemaValDuration { - long mon; /* mon stores years also */ - long day; - double sec; /* sec stores min and hour also */ -}; - -typedef struct _xmlSchemaValDecimal xmlSchemaValDecimal; -typedef xmlSchemaValDecimal *xmlSchemaValDecimalPtr; -struct _xmlSchemaValDecimal { - /* would use long long but not portable */ - unsigned long lo; - unsigned long mi; - unsigned long hi; - unsigned int extra; - unsigned int sign:1; - unsigned int frac:7; - unsigned int total:8; -}; - -typedef struct _xmlSchemaValQName xmlSchemaValQName; -typedef xmlSchemaValQName *xmlSchemaValQNamePtr; -struct _xmlSchemaValQName { - xmlChar *name; - xmlChar *uri; -}; - -typedef struct _xmlSchemaValHex xmlSchemaValHex; -typedef xmlSchemaValHex *xmlSchemaValHexPtr; -struct _xmlSchemaValHex { - xmlChar *str; - unsigned int total; -}; - -typedef struct _xmlSchemaValBase64 xmlSchemaValBase64; -typedef xmlSchemaValBase64 *xmlSchemaValBase64Ptr; -struct _xmlSchemaValBase64 { - xmlChar *str; - unsigned int total; -}; - -struct _xmlSchemaVal { - xmlSchemaValType type; - struct _xmlSchemaVal *next; - union { - xmlSchemaValDecimal decimal; - xmlSchemaValDate date; - xmlSchemaValDuration dur; - xmlSchemaValQName qname; - xmlSchemaValHex hex; - xmlSchemaValBase64 base64; - float f; - double d; - int b; - xmlChar *str; - } value; -}; - -static int xmlSchemaTypesInitialized = 0; -static xmlHashTablePtr xmlSchemaTypesBank = NULL; - -/* - * Basic types - */ -static xmlSchemaTypePtr xmlSchemaTypeStringDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeAnyTypeDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeAnySimpleTypeDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeDecimalDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeDatetimeDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeDateDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeTimeDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeGYearDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeGYearMonthDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeGDayDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeGMonthDayDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeGMonthDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeDurationDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeFloatDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeBooleanDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeDoubleDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeHexBinaryDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeBase64BinaryDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeAnyURIDef = NULL; - -/* - * Derived types - */ -static xmlSchemaTypePtr xmlSchemaTypePositiveIntegerDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeNonPositiveIntegerDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeNegativeIntegerDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeNonNegativeIntegerDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeIntegerDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeLongDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeIntDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeShortDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeByteDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeUnsignedLongDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeUnsignedIntDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeUnsignedShortDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeUnsignedByteDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeNormStringDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeTokenDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeLanguageDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeNameDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeQNameDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeNCNameDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeIdDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeIdrefDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeIdrefsDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeEntityDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeEntitiesDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeNotationDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeNmtokenDef = NULL; -static xmlSchemaTypePtr xmlSchemaTypeNmtokensDef = NULL; - -/************************************************************************ - * * - * Datatype error handlers * - * * - ************************************************************************/ -/** - * xmlSchemaTypeErrMemory: - * @extra: extra informations - * - * Handle an out of memory condition - */ -static void -xmlSchemaTypeErrMemory(xmlNodePtr node, const char *extra) -{ - __xmlSimpleError(XML_FROM_DATATYPE, XML_ERR_NO_MEMORY, node, NULL, extra); -} - -/************************************************************************ - * * - * Base types support * - * * - ************************************************************************/ - -/** - * xmlSchemaNewValue: - * @type: the value type - * - * Allocate a new simple type value - * - * Returns a pointer to the new value or NULL in case of error - */ -static xmlSchemaValPtr -xmlSchemaNewValue(xmlSchemaValType type) { - xmlSchemaValPtr value; - - value = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal)); - if (value == NULL) { - return(NULL); - } - memset(value, 0, sizeof(xmlSchemaVal)); - value->type = type; - return(value); -} - -static xmlSchemaFacetPtr -xmlSchemaNewMinLengthFacet(int value) -{ - xmlSchemaFacetPtr ret; - - ret = xmlSchemaNewFacet(); - if (ret == NULL) { - return(NULL); - } - ret->type = XML_SCHEMA_FACET_MINLENGTH; - ret->val = xmlSchemaNewValue(XML_SCHEMAS_NNINTEGER); - if (ret->val == NULL) { - xmlFree(ret); - return(NULL); - } - ret->val->value.decimal.lo = value; - return (ret); -} - -/* - * xmlSchemaInitBasicType: - * @name: the type name - * @type: the value type associated - * - * Initialize one primitive built-in type - */ -static xmlSchemaTypePtr -xmlSchemaInitBasicType(const char *name, xmlSchemaValType type, - xmlSchemaTypePtr baseType) { - xmlSchemaTypePtr ret; - - ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType)); - if (ret == NULL) { - xmlSchemaTypeErrMemory(NULL, "could not initialize basic types"); - return(NULL); - } - memset(ret, 0, sizeof(xmlSchemaType)); - ret->name = (const xmlChar *)name; - ret->targetNamespace = XML_SCHEMAS_NAMESPACE_NAME; - ret->type = XML_SCHEMA_TYPE_BASIC; - ret->baseType = baseType; - ret->contentType = XML_SCHEMA_CONTENT_BASIC; - /* - * Primitive types. - */ - switch (type) { - case XML_SCHEMAS_STRING: - case XML_SCHEMAS_DECIMAL: - case XML_SCHEMAS_DATE: - case XML_SCHEMAS_DATETIME: - case XML_SCHEMAS_TIME: - case XML_SCHEMAS_GYEAR: - case XML_SCHEMAS_GYEARMONTH: - case XML_SCHEMAS_GMONTH: - case XML_SCHEMAS_GMONTHDAY: - case XML_SCHEMAS_GDAY: - case XML_SCHEMAS_DURATION: - case XML_SCHEMAS_FLOAT: - case XML_SCHEMAS_DOUBLE: - case XML_SCHEMAS_BOOLEAN: - case XML_SCHEMAS_ANYURI: - case XML_SCHEMAS_HEXBINARY: - case XML_SCHEMAS_BASE64BINARY: - case XML_SCHEMAS_QNAME: - case XML_SCHEMAS_NOTATION: - ret->flags |= XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE; - break; - default: - break; - } - /* - * Set variety. - */ - switch (type) { - case XML_SCHEMAS_ANYTYPE: - case XML_SCHEMAS_ANYSIMPLETYPE: - break; - case XML_SCHEMAS_IDREFS: - case XML_SCHEMAS_NMTOKENS: - case XML_SCHEMAS_ENTITIES: - ret->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST; - ret->facets = xmlSchemaNewMinLengthFacet(1); - ret->flags |= XML_SCHEMAS_TYPE_HAS_FACETS; - break; - default: - ret->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC; - break; - } - xmlHashAddEntry2(xmlSchemaTypesBank, ret->name, - XML_SCHEMAS_NAMESPACE_NAME, ret); - ret->builtInType = type; - return(ret); -} - -/* -* WARNING: Those type reside normally in xmlschemas.c but are -* redefined here locally in oder of being able to use them for xs:anyType- -* TODO: Remove those definition if we move the types to a header file. -* TODO: Always keep those structs up-to-date with the originals. -*/ -#define UNBOUNDED (1 << 30) - -typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem; -typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr; -struct _xmlSchemaTreeItem { - xmlSchemaTypeType type; - xmlSchemaAnnotPtr annot; - xmlSchemaTreeItemPtr next; - xmlSchemaTreeItemPtr children; -}; - -typedef struct _xmlSchemaParticle xmlSchemaParticle; -typedef xmlSchemaParticle *xmlSchemaParticlePtr; -struct _xmlSchemaParticle { - xmlSchemaTypeType type; - xmlSchemaAnnotPtr annot; - xmlSchemaTreeItemPtr next; - xmlSchemaTreeItemPtr children; - int minOccurs; - int maxOccurs; - xmlNodePtr node; -}; - -typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup; -typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr; -struct _xmlSchemaModelGroup { - xmlSchemaTypeType type; - xmlSchemaAnnotPtr annot; - xmlSchemaTreeItemPtr next; - xmlSchemaTreeItemPtr children; - xmlNodePtr node; -}; - -static xmlSchemaParticlePtr -xmlSchemaAddParticle(void) -{ - xmlSchemaParticlePtr ret = NULL; - - ret = (xmlSchemaParticlePtr) - xmlMalloc(sizeof(xmlSchemaParticle)); - if (ret == NULL) { - xmlSchemaTypeErrMemory(NULL, "allocating particle component"); - return (NULL); - } - memset(ret, 0, sizeof(xmlSchemaParticle)); - ret->type = XML_SCHEMA_TYPE_PARTICLE; - ret->minOccurs = 1; - ret->maxOccurs = 1; - return (ret); -} - -/* - * xmlSchemaInitTypes: - * - * Initialize the default XML Schemas type library - */ -void -xmlSchemaInitTypes(void) -{ - if (xmlSchemaTypesInitialized != 0) - return; - xmlSchemaTypesBank = xmlHashCreate(40); - - - /* - * 3.4.7 Built-in Complex Type Definition - */ - xmlSchemaTypeAnyTypeDef = xmlSchemaInitBasicType("anyType", - XML_SCHEMAS_ANYTYPE, - NULL); - xmlSchemaTypeAnyTypeDef->baseType = xmlSchemaTypeAnyTypeDef; - xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED; - /* - * Init the content type. - */ - xmlSchemaTypeAnyTypeDef->contentType = XML_SCHEMA_CONTENT_MIXED; - { - xmlSchemaParticlePtr particle; - xmlSchemaModelGroupPtr sequence; - xmlSchemaWildcardPtr wild; - /* First particle. */ - particle = xmlSchemaAddParticle(); - if (particle == NULL) - return; - xmlSchemaTypeAnyTypeDef->subtypes = (xmlSchemaTypePtr) particle; - /* Sequence model group. */ - sequence = (xmlSchemaModelGroupPtr) - xmlMalloc(sizeof(xmlSchemaModelGroup)); - if (sequence == NULL) { - xmlSchemaTypeErrMemory(NULL, "allocating model group component"); - return; - } - memset(sequence, 0, sizeof(xmlSchemaModelGroup)); - sequence->type = XML_SCHEMA_TYPE_SEQUENCE; - particle->children = (xmlSchemaTreeItemPtr) sequence; - /* Second particle. */ - particle = xmlSchemaAddParticle(); - if (particle == NULL) - return; - particle->minOccurs = 0; - particle->maxOccurs = UNBOUNDED; - sequence->children = (xmlSchemaTreeItemPtr) particle; - /* The wildcard */ - wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); - if (wild == NULL) { - xmlSchemaTypeErrMemory(NULL, "allocating wildcard component"); - return; - } - memset(wild, 0, sizeof(xmlSchemaWildcard)); - wild->type = XML_SCHEMA_TYPE_ANY; - wild->any = 1; - wild->processContents = XML_SCHEMAS_ANY_LAX; - particle->children = (xmlSchemaTreeItemPtr) wild; - /* - * Create the attribute wildcard. - */ - wild = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard)); - if (wild == NULL) { - xmlSchemaTypeErrMemory(NULL, "could not create an attribute " - "wildcard on anyType"); - return; - } - memset(wild, 0, sizeof(xmlSchemaWildcard)); - wild->any = 1; - wild->processContents = XML_SCHEMAS_ANY_LAX; - xmlSchemaTypeAnyTypeDef->attributeWildcard = wild; - } - xmlSchemaTypeAnySimpleTypeDef = xmlSchemaInitBasicType("anySimpleType", - XML_SCHEMAS_ANYSIMPLETYPE, - xmlSchemaTypeAnyTypeDef); - /* - * primitive datatypes - */ - xmlSchemaTypeStringDef = xmlSchemaInitBasicType("string", - XML_SCHEMAS_STRING, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeDecimalDef = xmlSchemaInitBasicType("decimal", - XML_SCHEMAS_DECIMAL, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeDateDef = xmlSchemaInitBasicType("date", - XML_SCHEMAS_DATE, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeDatetimeDef = xmlSchemaInitBasicType("dateTime", - XML_SCHEMAS_DATETIME, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeTimeDef = xmlSchemaInitBasicType("time", - XML_SCHEMAS_TIME, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeGYearDef = xmlSchemaInitBasicType("gYear", - XML_SCHEMAS_GYEAR, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeGYearMonthDef = xmlSchemaInitBasicType("gYearMonth", - XML_SCHEMAS_GYEARMONTH, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeGMonthDef = xmlSchemaInitBasicType("gMonth", - XML_SCHEMAS_GMONTH, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeGMonthDayDef = xmlSchemaInitBasicType("gMonthDay", - XML_SCHEMAS_GMONTHDAY, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeGDayDef = xmlSchemaInitBasicType("gDay", - XML_SCHEMAS_GDAY, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeDurationDef = xmlSchemaInitBasicType("duration", - XML_SCHEMAS_DURATION, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeFloatDef = xmlSchemaInitBasicType("float", - XML_SCHEMAS_FLOAT, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeDoubleDef = xmlSchemaInitBasicType("double", - XML_SCHEMAS_DOUBLE, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeBooleanDef = xmlSchemaInitBasicType("boolean", - XML_SCHEMAS_BOOLEAN, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeAnyURIDef = xmlSchemaInitBasicType("anyURI", - XML_SCHEMAS_ANYURI, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeHexBinaryDef = xmlSchemaInitBasicType("hexBinary", - XML_SCHEMAS_HEXBINARY, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeBase64BinaryDef - = xmlSchemaInitBasicType("base64Binary", XML_SCHEMAS_BASE64BINARY, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeNotationDef = xmlSchemaInitBasicType("NOTATION", - XML_SCHEMAS_NOTATION, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeQNameDef = xmlSchemaInitBasicType("QName", - XML_SCHEMAS_QNAME, - xmlSchemaTypeAnySimpleTypeDef); - - /* - * derived datatypes - */ - xmlSchemaTypeIntegerDef = xmlSchemaInitBasicType("integer", - XML_SCHEMAS_INTEGER, - xmlSchemaTypeDecimalDef); - xmlSchemaTypeNonPositiveIntegerDef = - xmlSchemaInitBasicType("nonPositiveInteger", - XML_SCHEMAS_NPINTEGER, - xmlSchemaTypeIntegerDef); - xmlSchemaTypeNegativeIntegerDef = - xmlSchemaInitBasicType("negativeInteger", XML_SCHEMAS_NINTEGER, - xmlSchemaTypeNonPositiveIntegerDef); - xmlSchemaTypeLongDef = - xmlSchemaInitBasicType("long", XML_SCHEMAS_LONG, - xmlSchemaTypeIntegerDef); - xmlSchemaTypeIntDef = xmlSchemaInitBasicType("int", XML_SCHEMAS_INT, - xmlSchemaTypeLongDef); - xmlSchemaTypeShortDef = xmlSchemaInitBasicType("short", - XML_SCHEMAS_SHORT, - xmlSchemaTypeIntDef); - xmlSchemaTypeByteDef = xmlSchemaInitBasicType("byte", - XML_SCHEMAS_BYTE, - xmlSchemaTypeShortDef); - xmlSchemaTypeNonNegativeIntegerDef = - xmlSchemaInitBasicType("nonNegativeInteger", - XML_SCHEMAS_NNINTEGER, - xmlSchemaTypeIntegerDef); - xmlSchemaTypeUnsignedLongDef = - xmlSchemaInitBasicType("unsignedLong", XML_SCHEMAS_ULONG, - xmlSchemaTypeNonNegativeIntegerDef); - xmlSchemaTypeUnsignedIntDef = - xmlSchemaInitBasicType("unsignedInt", XML_SCHEMAS_UINT, - xmlSchemaTypeUnsignedLongDef); - xmlSchemaTypeUnsignedShortDef = - xmlSchemaInitBasicType("unsignedShort", XML_SCHEMAS_USHORT, - xmlSchemaTypeUnsignedIntDef); - xmlSchemaTypeUnsignedByteDef = - xmlSchemaInitBasicType("unsignedByte", XML_SCHEMAS_UBYTE, - xmlSchemaTypeUnsignedShortDef); - xmlSchemaTypePositiveIntegerDef = - xmlSchemaInitBasicType("positiveInteger", XML_SCHEMAS_PINTEGER, - xmlSchemaTypeNonNegativeIntegerDef); - xmlSchemaTypeNormStringDef = xmlSchemaInitBasicType("normalizedString", - XML_SCHEMAS_NORMSTRING, - xmlSchemaTypeStringDef); - xmlSchemaTypeTokenDef = xmlSchemaInitBasicType("token", - XML_SCHEMAS_TOKEN, - xmlSchemaTypeNormStringDef); - xmlSchemaTypeLanguageDef = xmlSchemaInitBasicType("language", - XML_SCHEMAS_LANGUAGE, - xmlSchemaTypeTokenDef); - xmlSchemaTypeNameDef = xmlSchemaInitBasicType("Name", - XML_SCHEMAS_NAME, - xmlSchemaTypeTokenDef); - xmlSchemaTypeNmtokenDef = xmlSchemaInitBasicType("NMTOKEN", - XML_SCHEMAS_NMTOKEN, - xmlSchemaTypeTokenDef); - xmlSchemaTypeNCNameDef = xmlSchemaInitBasicType("NCName", - XML_SCHEMAS_NCNAME, - xmlSchemaTypeNameDef); - xmlSchemaTypeIdDef = xmlSchemaInitBasicType("ID", XML_SCHEMAS_ID, - xmlSchemaTypeNCNameDef); - xmlSchemaTypeIdrefDef = xmlSchemaInitBasicType("IDREF", - XML_SCHEMAS_IDREF, - xmlSchemaTypeNCNameDef); - xmlSchemaTypeEntityDef = xmlSchemaInitBasicType("ENTITY", - XML_SCHEMAS_ENTITY, - xmlSchemaTypeNCNameDef); - /* - * Derived list types. - */ - /* ENTITIES */ - xmlSchemaTypeEntitiesDef = xmlSchemaInitBasicType("ENTITIES", - XML_SCHEMAS_ENTITIES, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeEntitiesDef->subtypes = xmlSchemaTypeEntityDef; - /* IDREFS */ - xmlSchemaTypeIdrefsDef = xmlSchemaInitBasicType("IDREFS", - XML_SCHEMAS_IDREFS, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeIdrefsDef->subtypes = xmlSchemaTypeIdrefDef; - - /* NMTOKENS */ - xmlSchemaTypeNmtokensDef = xmlSchemaInitBasicType("NMTOKENS", - XML_SCHEMAS_NMTOKENS, - xmlSchemaTypeAnySimpleTypeDef); - xmlSchemaTypeNmtokensDef->subtypes = xmlSchemaTypeNmtokenDef; - - xmlSchemaTypesInitialized = 1; -} - -/** - * xmlSchemaCleanupTypes: - * - * Cleanup the default XML Schemas type library - */ -void -xmlSchemaCleanupTypes(void) { - if (xmlSchemaTypesInitialized == 0) - return; - /* - * Free xs:anyType. - */ - { - xmlSchemaParticlePtr particle; - /* Attribute wildcard. */ - xmlSchemaFreeWildcard(xmlSchemaTypeAnyTypeDef->attributeWildcard); - /* Content type. */ - particle = (xmlSchemaParticlePtr) xmlSchemaTypeAnyTypeDef->subtypes; - /* Wildcard. */ - xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) - particle->children->children->children); - xmlFree((xmlSchemaParticlePtr) particle->children->children); - /* Sequence model group. */ - xmlFree((xmlSchemaModelGroupPtr) particle->children); - xmlFree((xmlSchemaParticlePtr) particle); - xmlSchemaTypeAnyTypeDef->subtypes = NULL; - } - xmlHashFree(xmlSchemaTypesBank, (xmlHashDeallocator) xmlSchemaFreeType); - xmlSchemaTypesInitialized = 0; -} - -/** - * xmlSchemaIsBuiltInTypeFacet: - * @type: the built-in type - * @facetType: the facet type - * - * Evaluates if a specific facet can be - * used in conjunction with a type. - * - * Returns 1 if the facet can be used with the given built-in type, - * 0 otherwise and -1 in case the type is not a built-in type. - */ -int -xmlSchemaIsBuiltInTypeFacet(xmlSchemaTypePtr type, int facetType) -{ - if (type == NULL) - return (-1); - if (type->type != XML_SCHEMA_TYPE_BASIC) - return (-1); - switch (type->builtInType) { - case XML_SCHEMAS_BOOLEAN: - if ((facetType == XML_SCHEMA_FACET_PATTERN) || - (facetType == XML_SCHEMA_FACET_WHITESPACE)) - return (1); - else - return (0); - case XML_SCHEMAS_STRING: - case XML_SCHEMAS_NOTATION: - case XML_SCHEMAS_QNAME: - case XML_SCHEMAS_ANYURI: - case XML_SCHEMAS_BASE64BINARY: - case XML_SCHEMAS_HEXBINARY: - if ((facetType == XML_SCHEMA_FACET_LENGTH) || - (facetType == XML_SCHEMA_FACET_MINLENGTH) || - (facetType == XML_SCHEMA_FACET_MAXLENGTH) || - (facetType == XML_SCHEMA_FACET_PATTERN) || - (facetType == XML_SCHEMA_FACET_ENUMERATION) || - (facetType == XML_SCHEMA_FACET_WHITESPACE)) - return (1); - else - return (0); - case XML_SCHEMAS_DECIMAL: - if ((facetType == XML_SCHEMA_FACET_TOTALDIGITS) || - (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) || - (facetType == XML_SCHEMA_FACET_PATTERN) || - (facetType == XML_SCHEMA_FACET_WHITESPACE) || - (facetType == XML_SCHEMA_FACET_ENUMERATION) || - (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) || - (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) || - (facetType == XML_SCHEMA_FACET_MININCLUSIVE) || - (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE)) - return (1); - else - return (0); - case XML_SCHEMAS_TIME: - case XML_SCHEMAS_GDAY: - case XML_SCHEMAS_GMONTH: - case XML_SCHEMAS_GMONTHDAY: - case XML_SCHEMAS_GYEAR: - case XML_SCHEMAS_GYEARMONTH: - case XML_SCHEMAS_DATE: - case XML_SCHEMAS_DATETIME: - case XML_SCHEMAS_DURATION: - case XML_SCHEMAS_FLOAT: - case XML_SCHEMAS_DOUBLE: - if ((facetType == XML_SCHEMA_FACET_PATTERN) || - (facetType == XML_SCHEMA_FACET_ENUMERATION) || - (facetType == XML_SCHEMA_FACET_WHITESPACE) || - (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) || - (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) || - (facetType == XML_SCHEMA_FACET_MININCLUSIVE) || - (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE)) - return (1); - else - return (0); - default: - break; - } - return (0); -} - -/** - * xmlSchemaGetBuiltInType: - * @type: the type of the built in type - * - * Gives you the type struct for a built-in - * type by its type id. - * - * Returns the type if found, NULL otherwise. - */ -xmlSchemaTypePtr -xmlSchemaGetBuiltInType(xmlSchemaValType type) -{ - if (xmlSchemaTypesInitialized == 0) - xmlSchemaInitTypes(); - switch (type) { - - case XML_SCHEMAS_ANYSIMPLETYPE: - return (xmlSchemaTypeAnySimpleTypeDef); - case XML_SCHEMAS_STRING: - return (xmlSchemaTypeStringDef); - case XML_SCHEMAS_NORMSTRING: - return (xmlSchemaTypeNormStringDef); - case XML_SCHEMAS_DECIMAL: - return (xmlSchemaTypeDecimalDef); - case XML_SCHEMAS_TIME: - return (xmlSchemaTypeTimeDef); - case XML_SCHEMAS_GDAY: - return (xmlSchemaTypeGDayDef); - case XML_SCHEMAS_GMONTH: - return (xmlSchemaTypeGMonthDef); - case XML_SCHEMAS_GMONTHDAY: - return (xmlSchemaTypeGMonthDayDef); - case XML_SCHEMAS_GYEAR: - return (xmlSchemaTypeGYearDef); - case XML_SCHEMAS_GYEARMONTH: - return (xmlSchemaTypeGYearMonthDef); - case XML_SCHEMAS_DATE: - return (xmlSchemaTypeDateDef); - case XML_SCHEMAS_DATETIME: - return (xmlSchemaTypeDatetimeDef); - case XML_SCHEMAS_DURATION: - return (xmlSchemaTypeDurationDef); - case XML_SCHEMAS_FLOAT: - return (xmlSchemaTypeFloatDef); - case XML_SCHEMAS_DOUBLE: - return (xmlSchemaTypeDoubleDef); - case XML_SCHEMAS_BOOLEAN: - return (xmlSchemaTypeBooleanDef); - case XML_SCHEMAS_TOKEN: - return (xmlSchemaTypeTokenDef); - case XML_SCHEMAS_LANGUAGE: - return (xmlSchemaTypeLanguageDef); - case XML_SCHEMAS_NMTOKEN: - return (xmlSchemaTypeNmtokenDef); - case XML_SCHEMAS_NMTOKENS: - return (xmlSchemaTypeNmtokensDef); - case XML_SCHEMAS_NAME: - return (xmlSchemaTypeNameDef); - case XML_SCHEMAS_QNAME: - return (xmlSchemaTypeQNameDef); - case XML_SCHEMAS_NCNAME: - return (xmlSchemaTypeNCNameDef); - case XML_SCHEMAS_ID: - return (xmlSchemaTypeIdDef); - case XML_SCHEMAS_IDREF: - return (xmlSchemaTypeIdrefDef); - case XML_SCHEMAS_IDREFS: - return (xmlSchemaTypeIdrefsDef); - case XML_SCHEMAS_ENTITY: - return (xmlSchemaTypeEntityDef); - case XML_SCHEMAS_ENTITIES: - return (xmlSchemaTypeEntitiesDef); - case XML_SCHEMAS_NOTATION: - return (xmlSchemaTypeNotationDef); - case XML_SCHEMAS_ANYURI: - return (xmlSchemaTypeAnyURIDef); - case XML_SCHEMAS_INTEGER: - return (xmlSchemaTypeIntegerDef); - case XML_SCHEMAS_NPINTEGER: - return (xmlSchemaTypeNonPositiveIntegerDef); - case XML_SCHEMAS_NINTEGER: - return (xmlSchemaTypeNegativeIntegerDef); - case XML_SCHEMAS_NNINTEGER: - return (xmlSchemaTypeNonNegativeIntegerDef); - case XML_SCHEMAS_PINTEGER: - return (xmlSchemaTypePositiveIntegerDef); - case XML_SCHEMAS_INT: - return (xmlSchemaTypeIntDef); - case XML_SCHEMAS_UINT: - return (xmlSchemaTypeUnsignedIntDef); - case XML_SCHEMAS_LONG: - return (xmlSchemaTypeLongDef); - case XML_SCHEMAS_ULONG: - return (xmlSchemaTypeUnsignedLongDef); - case XML_SCHEMAS_SHORT: - return (xmlSchemaTypeShortDef); - case XML_SCHEMAS_USHORT: - return (xmlSchemaTypeUnsignedShortDef); - case XML_SCHEMAS_BYTE: - return (xmlSchemaTypeByteDef); - case XML_SCHEMAS_UBYTE: - return (xmlSchemaTypeUnsignedByteDef); - case XML_SCHEMAS_HEXBINARY: - return (xmlSchemaTypeHexBinaryDef); - case XML_SCHEMAS_BASE64BINARY: - return (xmlSchemaTypeBase64BinaryDef); - case XML_SCHEMAS_ANYTYPE: - return (xmlSchemaTypeAnyTypeDef); - default: - return (NULL); - } -} - -/** - * xmlSchemaValueAppend: - * @prev: the value - * @cur: the value to be appended - * - * Appends a next sibling to a list of computed values. - * - * Returns 0 if succeeded and -1 on API errors. - */ -int -xmlSchemaValueAppend(xmlSchemaValPtr prev, xmlSchemaValPtr cur) { - - if ((prev == NULL) || (cur == NULL)) - return (-1); - prev->next = cur; - return (0); -} - -/** - * xmlSchemaValueGetNext: - * @cur: the value - * - * Accessor for the next sibling of a list of computed values. - * - * Returns the next value or NULL if there was none, or on - * API errors. - */ -xmlSchemaValPtr -xmlSchemaValueGetNext(xmlSchemaValPtr cur) { - - if (cur == NULL) - return (NULL); - return (cur->next); -} - -/** - * xmlSchemaValueGetAsString: - * @val: the value - * - * Accessor for the string value of a computed value. - * - * Returns the string value or NULL if there was none, or on - * API errors. - */ -const xmlChar * -xmlSchemaValueGetAsString(xmlSchemaValPtr val) -{ - if (val == NULL) - return (NULL); - switch (val->type) { - case XML_SCHEMAS_STRING: - case XML_SCHEMAS_NORMSTRING: - case XML_SCHEMAS_ANYSIMPLETYPE: - case XML_SCHEMAS_TOKEN: - case XML_SCHEMAS_LANGUAGE: - case XML_SCHEMAS_NMTOKEN: - case XML_SCHEMAS_NAME: - case XML_SCHEMAS_NCNAME: - case XML_SCHEMAS_ID: - case XML_SCHEMAS_IDREF: - case XML_SCHEMAS_ENTITY: - case XML_SCHEMAS_ANYURI: - return (BAD_CAST val->value.str); - default: - break; - } - return (NULL); -} - -/** - * xmlSchemaValueGetAsBoolean: - * @val: the value - * - * Accessor for the boolean value of a computed value. - * - * Returns 1 if true and 0 if false, or in case of an error. Hmm. - */ -int -xmlSchemaValueGetAsBoolean(xmlSchemaValPtr val) -{ - if ((val == NULL) || (val->type != XML_SCHEMAS_BOOLEAN)) - return (0); - return (val->value.b); -} - -/** - * xmlSchemaNewStringValue: - * @type: the value type - * @value: the value - * - * Allocate a new simple type value. The type can be - * of XML_SCHEMAS_STRING. - * WARNING: This one is intended to be expanded for other - * string based types. We need this for anySimpleType as well. - * The given value is consumed and freed with the struct. - * - * Returns a pointer to the new value or NULL in case of error - */ -xmlSchemaValPtr -xmlSchemaNewStringValue(xmlSchemaValType type, - const xmlChar *value) -{ - xmlSchemaValPtr val; - - if (type != XML_SCHEMAS_STRING) - return(NULL); - val = (xmlSchemaValPtr) xmlMalloc(sizeof(xmlSchemaVal)); - if (val == NULL) { - return(NULL); - } - memset(val, 0, sizeof(xmlSchemaVal)); - val->type = type; - val->value.str = (xmlChar *) value; - return(val); -} - -/** - * xmlSchemaNewNOTATIONValue: - * @name: the notation name - * @ns: the notation namespace name or NULL - * - * Allocate a new NOTATION value. - * The given values are consumed and freed with the struct. - * - * Returns a pointer to the new value or NULL in case of error - */ -xmlSchemaValPtr -xmlSchemaNewNOTATIONValue(const xmlChar *name, - const xmlChar *ns) -{ - xmlSchemaValPtr val; - - val = xmlSchemaNewValue(XML_SCHEMAS_NOTATION); - if (val == NULL) - return (NULL); - - val->value.qname.name = (xmlChar *)name; - if (ns != NULL) - val->value.qname.uri = (xmlChar *)ns; - return(val); -} - -/** - * xmlSchemaNewQNameValue: - * @namespaceName: the namespace name - * @localName: the local name - * - * Allocate a new QName value. - * The given values are consumed and freed with the struct. - * - * Returns a pointer to the new value or NULL in case of an error. - */ -xmlSchemaValPtr -xmlSchemaNewQNameValue(const xmlChar *namespaceName, - const xmlChar *localName) -{ - xmlSchemaValPtr val; - - val = xmlSchemaNewValue(XML_SCHEMAS_QNAME); - if (val == NULL) - return (NULL); - - val->value.qname.name = (xmlChar *) localName; - val->value.qname.uri = (xmlChar *) namespaceName; - return(val); -} - -/** - * xmlSchemaFreeValue: - * @value: the value to free - * - * Cleanup the default XML Schemas type library - */ -void -xmlSchemaFreeValue(xmlSchemaValPtr value) { - xmlSchemaValPtr prev; - - while (value != NULL) { - switch (value->type) { - case XML_SCHEMAS_STRING: - case XML_SCHEMAS_NORMSTRING: - case XML_SCHEMAS_TOKEN: - case XML_SCHEMAS_LANGUAGE: - case XML_SCHEMAS_NMTOKEN: - case XML_SCHEMAS_NMTOKENS: - case XML_SCHEMAS_NAME: - case XML_SCHEMAS_NCNAME: - case XML_SCHEMAS_ID: - case XML_SCHEMAS_IDREF: - case XML_SCHEMAS_IDREFS: - case XML_SCHEMAS_ENTITY: - case XML_SCHEMAS_ENTITIES: - case XML_SCHEMAS_ANYURI: - case XML_SCHEMAS_ANYSIMPLETYPE: - if (value->value.str != NULL) - xmlFree(value->value.str); - break; - case XML_SCHEMAS_NOTATION: - case XML_SCHEMAS_QNAME: - if (value->value.qname.uri != NULL) - xmlFree(value->value.qname.uri); - if (value->value.qname.name != NULL) - xmlFree(value->value.qname.name); - break; - case XML_SCHEMAS_HEXBINARY: - if (value->value.hex.str != NULL) - xmlFree(value->value.hex.str); - break; - case XML_SCHEMAS_BASE64BINARY: - if (value->value.base64.str != NULL) - xmlFree(value->value.base64.str); - break; - default: - break; - } - prev = value; - value = value->next; - xmlFree(prev); - } -} - -/** - * xmlSchemaGetPredefinedType: - * @name: the type name - * @ns: the URI of the namespace usually "http://www.w3.org/2001/XMLSchema" - * - * Lookup a type in the default XML Schemas type library - * - * Returns the type if found, NULL otherwise - */ -xmlSchemaTypePtr -xmlSchemaGetPredefinedType(const xmlChar *name, const xmlChar *ns) { - if (xmlSchemaTypesInitialized == 0) - xmlSchemaInitTypes(); - if (name == NULL) - return(NULL); - return((xmlSchemaTypePtr) xmlHashLookup2(xmlSchemaTypesBank, name, ns)); -} - -/** - * xmlSchemaGetBuiltInListSimpleTypeItemType: - * @type: the built-in simple type. - * - * Lookup function - * - * Returns the item type of @type as defined by the built-in datatype - * hierarchy of XML Schema Part 2: Datatypes, or NULL in case of an error. - */ -xmlSchemaTypePtr -xmlSchemaGetBuiltInListSimpleTypeItemType(xmlSchemaTypePtr type) -{ - if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_BASIC)) - return (NULL); - switch (type->builtInType) { - case XML_SCHEMAS_NMTOKENS: - return (xmlSchemaTypeNmtokenDef ); - case XML_SCHEMAS_IDREFS: - return (xmlSchemaTypeIdrefDef); - case XML_SCHEMAS_ENTITIES: - return (xmlSchemaTypeEntityDef); - default: - return (NULL); - } -} - -/**************************************************************** - * * - * Convenience macros and functions * - * * - ****************************************************************/ - -#define IS_TZO_CHAR(c) \ - ((c == 0) || (c == 'Z') || (c == '+') || (c == '-')) - -#define VALID_YEAR(yr) (yr != 0) -#define VALID_MONTH(mon) ((mon >= 1) && (mon <= 12)) -/* VALID_DAY should only be used when month is unknown */ -#define VALID_DAY(day) ((day >= 1) && (day <= 31)) -#define VALID_HOUR(hr) ((hr >= 0) && (hr <= 23)) -#define VALID_MIN(min) ((min >= 0) && (min <= 59)) -#define VALID_SEC(sec) ((sec >= 0) && (sec < 60)) -#define VALID_TZO(tzo) ((tzo > -840) && (tzo < 840)) -#define IS_LEAP(y) \ - (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)) - -static const unsigned int daysInMonth[12] = - { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; -static const unsigned int daysInMonthLeap[12] = - { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -#define MAX_DAYINMONTH(yr,mon) \ - (IS_LEAP(yr) ? daysInMonthLeap[mon - 1] : daysInMonth[mon - 1]) - -#define VALID_MDAY(dt) \ - (IS_LEAP(dt->year) ? \ - (dt->day <= daysInMonthLeap[dt->mon - 1]) : \ - (dt->day <= daysInMonth[dt->mon - 1])) - -#define VALID_DATE(dt) \ - (VALID_YEAR(dt->year) && VALID_MONTH(dt->mon) && VALID_MDAY(dt)) - -#define VALID_END_OF_DAY(dt) \ - ((dt)->hour == 24 && (dt)->min == 0 && (dt)->sec == 0) - -#define VALID_TIME(dt) \ - (((VALID_HOUR(dt->hour) && VALID_MIN(dt->min) && \ - VALID_SEC(dt->sec)) || VALID_END_OF_DAY(dt)) && \ - VALID_TZO(dt->tzo)) - -#define VALID_DATETIME(dt) \ - (VALID_DATE(dt) && VALID_TIME(dt)) - -#define SECS_PER_MIN (60) -#define SECS_PER_HOUR (60 * SECS_PER_MIN) -#define SECS_PER_DAY (24 * SECS_PER_HOUR) - -static const long dayInYearByMonth[12] = - { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; -static const long dayInLeapYearByMonth[12] = - { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; - -#define DAY_IN_YEAR(day, month, year) \ - ((IS_LEAP(year) ? \ - dayInLeapYearByMonth[month - 1] : \ - dayInYearByMonth[month - 1]) + day) - -#ifdef DEBUG -#define DEBUG_DATE(dt) \ - xmlGenericError(xmlGenericErrorContext, \ - "type=%o %04ld-%02u-%02uT%02u:%02u:%03f", \ - dt->type,dt->value.date.year,dt->value.date.mon, \ - dt->value.date.day,dt->value.date.hour,dt->value.date.min, \ - dt->value.date.sec); \ - if (dt->value.date.tz_flag) \ - if (dt->value.date.tzo != 0) \ - xmlGenericError(xmlGenericErrorContext, \ - "%+05d\n",dt->value.date.tzo); \ - else \ - xmlGenericError(xmlGenericErrorContext, "Z\n"); \ - else \ - xmlGenericError(xmlGenericErrorContext,"\n") -#else -#define DEBUG_DATE(dt) -#endif - -/** - * _xmlSchemaParseGYear: - * @dt: pointer to a date structure - * @str: pointer to the string to analyze - * - * Parses a xs:gYear without time zone and fills in the appropriate - * field of the @dt structure. @str is updated to point just after the - * xs:gYear. It is supposed that @dt->year is big enough to contain - * the year. - * - * Returns 0 or the error code - */ -static int -_xmlSchemaParseGYear (xmlSchemaValDatePtr dt, const xmlChar **str) { - const xmlChar *cur = *str, *firstChar; - int isneg = 0, digcnt = 0; - - if (((*cur < '0') || (*cur > '9')) && - (*cur != '-') && (*cur != '+')) - return -1; - - if (*cur == '-') { - isneg = 1; - cur++; - } - - firstChar = cur; - - while ((*cur >= '0') && (*cur <= '9')) { - dt->year = dt->year * 10 + (*cur - '0'); - cur++; - digcnt++; - } - - /* year must be at least 4 digits (CCYY); over 4 - * digits cannot have a leading zero. */ - if ((digcnt < 4) || ((digcnt > 4) && (*firstChar == '0'))) - return 1; - - if (isneg) - dt->year = - dt->year; - - if (!VALID_YEAR(dt->year)) - return 2; - - *str = cur; - return 0; -} - -/** - * PARSE_2_DIGITS: - * @num: the integer to fill in - * @cur: an #xmlChar * - * @invalid: an integer - * - * Parses a 2-digits integer and updates @num with the value. @cur is - * updated to point just after the integer. - * In case of error, @invalid is set to %TRUE, values of @num and - * @cur are undefined. - */ -#define PARSE_2_DIGITS(num, cur, invalid) \ - if ((cur[0] < '0') || (cur[0] > '9') || \ - (cur[1] < '0') || (cur[1] > '9')) \ - invalid = 1; \ - else \ - num = (cur[0] - '0') * 10 + (cur[1] - '0'); \ - cur += 2; - -/** - * PARSE_FLOAT: - * @num: the double to fill in - * @cur: an #xmlChar * - * @invalid: an integer - * - * Parses a float and updates @num with the value. @cur is - * updated to point just after the float. The float must have a - * 2-digits integer part and may or may not have a decimal part. - * In case of error, @invalid is set to %TRUE, values of @num and - * @cur are undefined. - */ -#define PARSE_FLOAT(num, cur, invalid) \ - PARSE_2_DIGITS(num, cur, invalid); \ - if (!invalid && (*cur == '.')) { \ - double mult = 1; \ - cur++; \ - if ((*cur < '0') || (*cur > '9')) \ - invalid = 1; \ - while ((*cur >= '0') && (*cur <= '9')) { \ - mult /= 10; \ - num += (*cur - '0') * mult; \ - cur++; \ - } \ - } - -/** - * _xmlSchemaParseGMonth: - * @dt: pointer to a date structure - * @str: pointer to the string to analyze - * - * Parses a xs:gMonth without time zone and fills in the appropriate - * field of the @dt structure. @str is updated to point just after the - * xs:gMonth. - * - * Returns 0 or the error code - */ -static int -_xmlSchemaParseGMonth (xmlSchemaValDatePtr dt, const xmlChar **str) { - const xmlChar *cur = *str; - int ret = 0; - unsigned int value = 0; - - PARSE_2_DIGITS(value, cur, ret); - if (ret != 0) - return ret; - - if (!VALID_MONTH(value)) - return 2; - - dt->mon = value; - - *str = cur; - return 0; -} - -/** - * _xmlSchemaParseGDay: - * @dt: pointer to a date structure - * @str: pointer to the string to analyze - * - * Parses a xs:gDay without time zone and fills in the appropriate - * field of the @dt structure. @str is updated to point just after the - * xs:gDay. - * - * Returns 0 or the error code - */ -static int -_xmlSchemaParseGDay (xmlSchemaValDatePtr dt, const xmlChar **str) { - const xmlChar *cur = *str; - int ret = 0; - unsigned int value = 0; - - PARSE_2_DIGITS(value, cur, ret); - if (ret != 0) - return ret; - - if (!VALID_DAY(value)) - return 2; - - dt->day = value; - *str = cur; - return 0; -} - -/** - * _xmlSchemaParseTime: - * @dt: pointer to a date structure - * @str: pointer to the string to analyze - * - * Parses a xs:time without time zone and fills in the appropriate - * fields of the @dt structure. @str is updated to point just after the - * xs:time. - * In case of error, values of @dt fields are undefined. - * - * Returns 0 or the error code - */ -static int -_xmlSchemaParseTime (xmlSchemaValDatePtr dt, const xmlChar **str) { - const xmlChar *cur = *str; - int ret = 0; - int value = 0; - - PARSE_2_DIGITS(value, cur, ret); - if (ret != 0) - return ret; - if (*cur != ':') - return 1; - if (!VALID_HOUR(value) && value != 24 /* Allow end-of-day hour */) - return 2; - cur++; - - /* the ':' insures this string is xs:time */ - dt->hour = value; - - PARSE_2_DIGITS(value, cur, ret); - if (ret != 0) - return ret; - if (!VALID_MIN(value)) - return 2; - dt->min = value; - - if (*cur != ':') - return 1; - cur++; - - PARSE_FLOAT(dt->sec, cur, ret); - if (ret != 0) - return ret; - - if (!VALID_TIME(dt)) - return 2; - - *str = cur; - return 0; -} - -/** - * _xmlSchemaParseTimeZone: - * @dt: pointer to a date structure - * @str: pointer to the string to analyze - * - * Parses a time zone without time zone and fills in the appropriate - * field of the @dt structure. @str is updated to point just after the - * time zone. - * - * Returns 0 or the error code - */ -static int -_xmlSchemaParseTimeZone (xmlSchemaValDatePtr dt, const xmlChar **str) { - const xmlChar *cur; - int ret = 0; - - if (str == NULL) - return -1; - cur = *str; - - switch (*cur) { - case 0: - dt->tz_flag = 0; - dt->tzo = 0; - break; - - case 'Z': - dt->tz_flag = 1; - dt->tzo = 0; - cur++; - break; - - case '+': - case '-': { - int isneg = 0, tmp = 0; - isneg = (*cur == '-'); - - cur++; - - PARSE_2_DIGITS(tmp, cur, ret); - if (ret != 0) - return ret; - if (!VALID_HOUR(tmp)) - return 2; - - if (*cur != ':') - return 1; - cur++; - - dt->tzo = tmp * 60; - - PARSE_2_DIGITS(tmp, cur, ret); - if (ret != 0) - return ret; - if (!VALID_MIN(tmp)) - return 2; - - dt->tzo += tmp; - if (isneg) - dt->tzo = - dt->tzo; - - if (!VALID_TZO(dt->tzo)) - return 2; - - dt->tz_flag = 1; - break; - } - default: - return 1; - } - - *str = cur; - return 0; -} - -/** - * _xmlSchemaBase64Decode: - * @ch: a character - * - * Converts a base64 encoded character to its base 64 value. - * - * Returns 0-63 (value), 64 (pad), or -1 (not recognized) - */ -static int -_xmlSchemaBase64Decode (const xmlChar ch) { - if (('A' <= ch) && (ch <= 'Z')) return ch - 'A'; - if (('a' <= ch) && (ch <= 'z')) return ch - 'a' + 26; - if (('0' <= ch) && (ch <= '9')) return ch - '0' + 52; - if ('+' == ch) return 62; - if ('/' == ch) return 63; - if ('=' == ch) return 64; - return -1; -} - -/**************************************************************** - * * - * XML Schema Dates/Times Datatypes Handling * - * * - ****************************************************************/ - -/** - * PARSE_DIGITS: - * @num: the integer to fill in - * @cur: an #xmlChar * - * @num_type: an integer flag - * - * Parses a digits integer and updates @num with the value. @cur is - * updated to point just after the integer. - * In case of error, @num_type is set to -1, values of @num and - * @cur are undefined. - */ -#define PARSE_DIGITS(num, cur, num_type) \ - if ((*cur < '0') || (*cur > '9')) \ - num_type = -1; \ - else \ - while ((*cur >= '0') && (*cur <= '9')) { \ - num = num * 10 + (*cur - '0'); \ - cur++; \ - } - -/** - * PARSE_NUM: - * @num: the double to fill in - * @cur: an #xmlChar * - * @num_type: an integer flag - * - * Parses a float or integer and updates @num with the value. @cur is - * updated to point just after the number. If the number is a float, - * then it must have an integer part and a decimal part; @num_type will - * be set to 1. If there is no decimal part, @num_type is set to zero. - * In case of error, @num_type is set to -1, values of @num and - * @cur are undefined. - */ -#define PARSE_NUM(num, cur, num_type) \ - num = 0; \ - PARSE_DIGITS(num, cur, num_type); \ - if (!num_type && (*cur == '.')) { \ - double mult = 1; \ - cur++; \ - if ((*cur < '0') || (*cur > '9')) \ - num_type = -1; \ - else \ - num_type = 1; \ - while ((*cur >= '0') && (*cur <= '9')) { \ - mult /= 10; \ - num += (*cur - '0') * mult; \ - cur++; \ - } \ - } - -/** - * xmlSchemaValidateDates: - * @type: the expected type or XML_SCHEMAS_UNKNOWN - * @dateTime: string to analyze - * @val: the return computed value - * - * Check that @dateTime conforms to the lexical space of one of the date types. - * if true a value is computed and returned in @val. - * - * Returns 0 if this validates, a positive error code number otherwise - * and -1 in case of internal or API error. - */ -static int -xmlSchemaValidateDates (xmlSchemaValType type, - const xmlChar *dateTime, xmlSchemaValPtr *val, - int collapse) { - xmlSchemaValPtr dt; - int ret; - const xmlChar *cur = dateTime; - -#define RETURN_TYPE_IF_VALID(t) \ - if (IS_TZO_CHAR(*cur)) { \ - ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); \ - if (ret == 0) { \ - if (*cur != 0) \ - goto error; \ - dt->type = t; \ - goto done; \ - } \ - } - - if (dateTime == NULL) - return -1; - - if (collapse) - while IS_WSP_BLANK_CH(*cur) cur++; - - if ((*cur != '-') && (*cur < '0') && (*cur > '9')) - return 1; - - dt = xmlSchemaNewValue(XML_SCHEMAS_UNKNOWN); - if (dt == NULL) - return -1; - - if ((cur[0] == '-') && (cur[1] == '-')) { - /* - * It's an incomplete date (xs:gMonthDay, xs:gMonth or - * xs:gDay) - */ - cur += 2; - - /* is it an xs:gDay? */ - if (*cur == '-') { - if (type == XML_SCHEMAS_GMONTH) - goto error; - ++cur; - ret = _xmlSchemaParseGDay(&(dt->value.date), &cur); - if (ret != 0) - goto error; - - RETURN_TYPE_IF_VALID(XML_SCHEMAS_GDAY); - - goto error; - } - - /* - * it should be an xs:gMonthDay or xs:gMonth - */ - ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur); - if (ret != 0) - goto error; - - /* - * a '-' char could indicate this type is xs:gMonthDay or - * a negative time zone offset. Check for xs:gMonthDay first. - * Also the first three char's of a negative tzo (-MM:SS) can - * appear to be a valid day; so even if the day portion - * of the xs:gMonthDay verifies, we must insure it was not - * a tzo. - */ - if (*cur == '-') { - const xmlChar *rewnd = cur; - cur++; - - ret = _xmlSchemaParseGDay(&(dt->value.date), &cur); - if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) { - - /* - * we can use the VALID_MDAY macro to validate the month - * and day because the leap year test will flag year zero - * as a leap year (even though zero is an invalid year). - * FUTURE TODO: Zero will become valid in XML Schema 1.1 - * probably. - */ - if (VALID_MDAY((&(dt->value.date)))) { - - RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY); - - goto error; - } - } - - /* - * not xs:gMonthDay so rewind and check if just xs:gMonth - * with an optional time zone. - */ - cur = rewnd; - } - - RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH); - - goto error; - } - - /* - * It's a right-truncated date or an xs:time. - * Try to parse an xs:time then fallback on right-truncated dates. - */ - if ((*cur >= '0') && (*cur <= '9')) { - ret = _xmlSchemaParseTime(&(dt->value.date), &cur); - if (ret == 0) { - /* it's an xs:time */ - RETURN_TYPE_IF_VALID(XML_SCHEMAS_TIME); - } - } - - /* fallback on date parsing */ - cur = dateTime; - - ret = _xmlSchemaParseGYear(&(dt->value.date), &cur); - if (ret != 0) - goto error; - - /* is it an xs:gYear? */ - RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEAR); - - if (*cur != '-') - goto error; - cur++; - - ret = _xmlSchemaParseGMonth(&(dt->value.date), &cur); - if (ret != 0) - goto error; - - /* is it an xs:gYearMonth? */ - RETURN_TYPE_IF_VALID(XML_SCHEMAS_GYEARMONTH); - - if (*cur != '-') - goto error; - cur++; - - ret = _xmlSchemaParseGDay(&(dt->value.date), &cur); - if ((ret != 0) || !VALID_DATE((&(dt->value.date)))) - goto error; - - /* is it an xs:date? */ - RETURN_TYPE_IF_VALID(XML_SCHEMAS_DATE); - - if (*cur != 'T') - goto error; - cur++; - - /* it should be an xs:dateTime */ - ret = _xmlSchemaParseTime(&(dt->value.date), &cur); - if (ret != 0) - goto error; - - ret = _xmlSchemaParseTimeZone(&(dt->value.date), &cur); - if (collapse) - while IS_WSP_BLANK_CH(*cur) cur++; - if ((ret != 0) || (*cur != 0) || (!(VALID_DATETIME((&(dt->value.date)))))) - goto error; - - - dt->type = XML_SCHEMAS_DATETIME; - -done: -#if 1 - if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) - goto error; -#else - /* - * insure the parsed type is equal to or less significant (right - * truncated) than the desired type. - */ - if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) { - - /* time only matches time */ - if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME)) - goto error; - - if ((type == XML_SCHEMAS_DATETIME) && - ((dt->type != XML_SCHEMAS_DATE) || - (dt->type != XML_SCHEMAS_GYEARMONTH) || - (dt->type != XML_SCHEMAS_GYEAR))) - goto error; - - if ((type == XML_SCHEMAS_DATE) && - ((dt->type != XML_SCHEMAS_GYEAR) || - (dt->type != XML_SCHEMAS_GYEARMONTH))) - goto error; - - if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR)) - goto error; - - if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH)) - goto error; - } -#endif - - if (val != NULL) - *val = dt; - else - xmlSchemaFreeValue(dt); - - return 0; - -error: - if (dt != NULL) - xmlSchemaFreeValue(dt); - return 1; -} - -/** - * xmlSchemaValidateDuration: - * @type: the predefined type - * @duration: string to analyze - * @val: the return computed value - * - * Check that @duration conforms to the lexical space of the duration type. - * if true a value is computed and returned in @val. - * - * Returns 0 if this validates, a positive error code number otherwise - * and -1 in case of internal or API error. - */ -static int -xmlSchemaValidateDuration (xmlSchemaTypePtr type ATTRIBUTE_UNUSED, - const xmlChar *duration, xmlSchemaValPtr *val, - int collapse) { - const xmlChar *cur = duration; - xmlSchemaValPtr dur; - int isneg = 0; - unsigned int seq = 0; - double num; - int num_type = 0; /* -1 = invalid, 0 = int, 1 = floating */ - const xmlChar desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'}; - const double multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0}; - - if (duration == NULL) - return -1; - - if (collapse) - while IS_WSP_BLANK_CH(*cur) cur++; - - if (*cur == '-') { - isneg = 1; - cur++; - } - - /* duration must start with 'P' (after sign) */ - if (*cur++ != 'P') - return 1; - - if (*cur == 0) - return 1; - - dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION); - if (dur == NULL) - return -1; - - while (*cur != 0) { - - /* input string should be empty or invalid date/time item */ - if (seq >= sizeof(desig)) - goto error; - - /* T designator must be present for time items */ - if (*cur == 'T') { - if (seq <= 3) { - seq = 3; - cur++; - } else - return 1; - } else if (seq == 3) - goto error; - - /* parse the number portion of the item */ - PARSE_NUM(num, cur, num_type); - - if ((num_type == -1) || (*cur == 0)) - goto error; - - /* update duration based on item type */ - while (seq < sizeof(desig)) { - if (*cur == desig[seq]) { - - /* verify numeric type; only seconds can be float */ - if ((num_type != 0) && (seq < (sizeof(desig)-1))) - goto error; - - switch (seq) { - case 0: - dur->value.dur.mon = (long)num * 12; - break; - case 1: - dur->value.dur.mon += (long)num; - break; - default: - /* convert to seconds using multiplier */ - dur->value.dur.sec += num * multi[seq]; - seq++; - break; - } - - break; /* exit loop */ - } - /* no date designators found? */ - if ((++seq == 3) || (seq == 6)) - goto error; - } - cur++; - if (collapse) - while IS_WSP_BLANK_CH(*cur) cur++; - } - - if (isneg) { - dur->value.dur.mon = -dur->value.dur.mon; - dur->value.dur.day = -dur->value.dur.day; - dur->value.dur.sec = -dur->value.dur.sec; - } - - if (val != NULL) - *val = dur; - else - xmlSchemaFreeValue(dur); - - return 0; - -error: - if (dur != NULL) - xmlSchemaFreeValue(dur); - return 1; -} - -/** - * xmlSchemaStrip: - * @value: a value - * - * Removes the leading and ending spaces of a string - * - * Returns the new string or NULL if no change was required. - */ -static xmlChar * -xmlSchemaStrip(const xmlChar *value) { - const xmlChar *start = value, *end, *f; - - if (value == NULL) return(NULL); - while ((*start != 0) && (IS_BLANK_CH(*start))) start++; - end = start; - while (*end != 0) end++; - f = end; - end--; - while ((end > start) && (IS_BLANK_CH(*end))) end--; - end++; - if ((start == value) && (f == end)) return(NULL); - return(xmlStrndup(start, end - start)); -} - -/** - * xmlSchemaWhiteSpaceReplace: - * @value: a value - * - * Replaces 0xd, 0x9 and 0xa with a space. - * - * Returns the new string or NULL if no change was required. - */ -xmlChar * -xmlSchemaWhiteSpaceReplace(const xmlChar *value) { - const xmlChar *cur = value; - xmlChar *ret = NULL, *mcur; - - if (value == NULL) - return(NULL); - - while ((*cur != 0) && - (((*cur) != 0xd) && ((*cur) != 0x9) && ((*cur) != 0xa))) { - cur++; - } - if (*cur == 0) - return (NULL); - ret = xmlStrdup(value); - /* TODO FIXME: I guess gcc will bark at this. */ - mcur = (xmlChar *) (ret + (cur - value)); - do { - if ( ((*mcur) == 0xd) || ((*mcur) == 0x9) || ((*mcur) == 0xa) ) - *mcur = ' '; - mcur++; - } while (*mcur != 0); - return(ret); -} - -/** - * xmlSchemaCollapseString: - * @value: a value - * - * Removes and normalize white spaces in the string - * - * Returns the new string or NULL if no change was required. - */ -xmlChar * -xmlSchemaCollapseString(const xmlChar *value) { - const xmlChar *start = value, *end, *f; - xmlChar *g; - int col = 0; - - if (value == NULL) return(NULL); - while ((*start != 0) && (IS_BLANK_CH(*start))) start++; - end = start; - while (*end != 0) { - if ((*end == ' ') && (IS_BLANK_CH(end[1]))) { - col = end - start; - break; - } else if ((*end == 0xa) || (*end == 0x9) || (*end == 0xd)) { - col = end - start; - break; - } - end++; - } - if (col == 0) { - f = end; - end--; - while ((end > start) && (IS_BLANK_CH(*end))) end--; - end++; - if ((start == value) && (f == end)) return(NULL); - return(xmlStrndup(start, end - start)); - } - start = xmlStrdup(start); - if (start == NULL) return(NULL); - g = (xmlChar *) (start + col); - end = g; - while (*end != 0) { - if (IS_BLANK_CH(*end)) { - end++; - while (IS_BLANK_CH(*end)) end++; - if (*end != 0) - *g++ = ' '; - } else - *g++ = *end++; - } - *g = 0; - return((xmlChar *) start); -} - -/** - * xmlSchemaValAtomicListNode: - * @type: the predefined atomic type for a token in the list - * @value: the list value to check - * @ret: the return computed value - * @node: the node containing the value - * - * Check that a value conforms to the lexical space of the predefined - * list type. if true a value is computed and returned in @ret. - * - * Returns the number of items if this validates, a negative error code - * number otherwise - */ -static int -xmlSchemaValAtomicListNode(xmlSchemaTypePtr type, const xmlChar *value, - xmlSchemaValPtr *ret, xmlNodePtr node) { - xmlChar *val, *cur, *endval; - int nb_values = 0; - int tmp = 0; - - if (value == NULL) { - return(-1); - } - val = xmlStrdup(value); - if (val == NULL) { - return(-1); - } - if (ret != NULL) { - *ret = NULL; - } - cur = val; - /* - * Split the list - */ - while (IS_BLANK_CH(*cur)) *cur++ = 0; - while (*cur != 0) { - if (IS_BLANK_CH(*cur)) { - *cur = 0; - cur++; - while (IS_BLANK_CH(*cur)) *cur++ = 0; - } else { - nb_values++; - cur++; - while ((*cur != 0) && (!IS_BLANK_CH(*cur))) cur++; - } - } - if (nb_values == 0) { - xmlFree(val); - return(nb_values); - } - endval = cur; - cur = val; - while ((*cur == 0) && (cur != endval)) cur++; - while (cur != endval) { - tmp = xmlSchemaValPredefTypeNode(type, cur, NULL, node); - if (tmp != 0) - break; - while (*cur != 0) cur++; - while ((*cur == 0) && (cur != endval)) cur++; - } - /* TODO what return value ? c.f. bug #158628 - if (ret != NULL) { - TODO - } */ - xmlFree(val); - if (tmp == 0) - return(nb_values); - return(-1); -} - -/** - * xmlSchemaParseUInt: - * @str: pointer to the string R/W - * @llo: pointer to the low result - * @lmi: pointer to the mid result - * @lhi: pointer to the high result - * - * Parse an unsigned long into 3 fields. - * - * Returns the number of significant digits in the number or - * -1 if overflow of the capacity and -2 if it's not a number. - */ -static int -xmlSchemaParseUInt(const xmlChar **str, unsigned long *llo, - unsigned long *lmi, unsigned long *lhi) { - unsigned long lo = 0, mi = 0, hi = 0; - const xmlChar *tmp, *cur = *str; - int ret = 0, i = 0; - - if (!((*cur >= '0') && (*cur <= '9'))) - return(-2); - - while (*cur == '0') { /* ignore leading zeroes */ - cur++; - } - tmp = cur; - while ((*tmp != 0) && (*tmp >= '0') && (*tmp <= '9')) { - i++;tmp++;ret++; - } - if (i > 24) { - *str = tmp; - return(-1); - } - while (i > 16) { - hi = hi * 10 + (*cur++ - '0'); - i--; - } - while (i > 8) { - mi = mi * 10 + (*cur++ - '0'); - i--; - } - while (i > 0) { - lo = lo * 10 + (*cur++ - '0'); - i--; - } - - *str = cur; - *llo = lo; - *lmi = mi; - *lhi = hi; - return(ret); -} - -/** - * xmlSchemaValAtomicType: - * @type: the predefined type - * @value: the value to check - * @val: the return computed value - * @node: the node containing the value - * flags: flags to control the vlidation - * - * Check that a value conforms to the lexical space of the atomic type. - * if true a value is computed and returned in @val. - * This checks the value space for list types as well (IDREFS, NMTOKENS). - * - * Returns 0 if this validates, a positive error code number otherwise - * and -1 in case of internal or API error. - */ -static int -xmlSchemaValAtomicType(xmlSchemaTypePtr type, const xmlChar * value, - xmlSchemaValPtr * val, xmlNodePtr node, int flags, - xmlSchemaWhitespaceValueType ws, - int normOnTheFly, int applyNorm, int createStringValue) -{ - xmlSchemaValPtr v; - xmlChar *norm = NULL; - int ret = 0; - - if (xmlSchemaTypesInitialized == 0) - xmlSchemaInitTypes(); - if (type == NULL) - return (-1); - - /* - * validating a non existant text node is similar to validating - * an empty one. - */ - if (value == NULL) - value = BAD_CAST ""; - - if (val != NULL) - *val = NULL; - if ((flags == 0) && (value != NULL)) { - - if ((type->builtInType != XML_SCHEMAS_STRING) && - (type->builtInType != XML_SCHEMAS_ANYTYPE) && - (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE)) { - if (type->builtInType == XML_SCHEMAS_NORMSTRING) - norm = xmlSchemaWhiteSpaceReplace(value); - else - norm = xmlSchemaCollapseString(value); - if (norm != NULL) - value = norm; - } - } - - switch (type->builtInType) { - case XML_SCHEMAS_UNKNOWN: - goto error; - case XML_SCHEMAS_ANYTYPE: - case XML_SCHEMAS_ANYSIMPLETYPE: - if ((createStringValue) && (val != NULL)) { - v = xmlSchemaNewValue(XML_SCHEMAS_ANYSIMPLETYPE); - if (v != NULL) { - v->value.str = xmlStrdup(value); - *val = v; - } else { - goto error; - } - } - goto return0; - case XML_SCHEMAS_STRING: - if (! normOnTheFly) { - const xmlChar *cur = value; - - if (ws == XML_SCHEMA_WHITESPACE_REPLACE) { - while (*cur != 0) { - if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { - goto return1; - } else { - cur++; - } - } - } else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) { - while (*cur != 0) { - if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { - goto return1; - } else if IS_WSP_SPACE_CH(*cur) { - cur++; - if IS_WSP_SPACE_CH(*cur) - goto return1; - } else { - cur++; - } - } - } - } - if (createStringValue && (val != NULL)) { - if (applyNorm) { - if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) - norm = xmlSchemaCollapseString(value); - else if (ws == XML_SCHEMA_WHITESPACE_REPLACE) - norm = xmlSchemaWhiteSpaceReplace(value); - if (norm != NULL) - value = norm; - } - v = xmlSchemaNewValue(XML_SCHEMAS_STRING); - if (v != NULL) { - v->value.str = xmlStrdup(value); - *val = v; - } else { - goto error; - } - } - goto return0; - case XML_SCHEMAS_NORMSTRING:{ - if (normOnTheFly) { - if (applyNorm) { - if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) - norm = xmlSchemaCollapseString(value); - else - norm = xmlSchemaWhiteSpaceReplace(value); - if (norm != NULL) - value = norm; - } - } else { - const xmlChar *cur = value; - while (*cur != 0) { - if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { - goto return1; - } else { - cur++; - } - } - } - if (val != NULL) { - v = xmlSchemaNewValue(XML_SCHEMAS_NORMSTRING); - if (v != NULL) { - v->value.str = xmlStrdup(value); - *val = v; - } else { - goto error; - } - } - goto return0; - } - case XML_SCHEMAS_DECIMAL:{ - const xmlChar *cur = value; - unsigned int len, neg, integ, hasLeadingZeroes; - xmlChar cval[25]; - xmlChar *cptr = cval; - - if ((cur == NULL) || (*cur == 0)) - goto return1; - - /* - * xs:decimal has a whitespace-facet value of 'collapse'. - */ - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - - /* - * First we handle an optional sign. - */ - neg = 0; - if (*cur == '-') { - neg = 1; - cur++; - } else if (*cur == '+') - cur++; - /* - * Disallow: "", "-", "- " - */ - if (*cur == 0) - goto return1; - /* - * Next we "pre-parse" the number, in preparation for calling - * the common routine xmlSchemaParseUInt. We get rid of any - * leading zeroes (because we have reserved only 25 chars), - * and note the position of a decimal point. - */ - len = 0; - integ = ~0u; - hasLeadingZeroes = 0; - /* - * Skip leading zeroes. - */ - while (*cur == '0') { - cur++; - hasLeadingZeroes = 1; - } - if (*cur != 0) { - do { - if ((*cur >= '0') && (*cur <= '9')) { - *cptr++ = *cur++; - len++; - } else if (*cur == '.') { - cur++; - integ = len; - do { - if ((*cur >= '0') && (*cur <= '9')) { - *cptr++ = *cur++; - len++; - } else - break; - } while (len < 24); - /* - * Disallow "." but allow "00." - */ - if ((len == 0) && (!hasLeadingZeroes)) - goto return1; - break; - } else - break; - } while (len < 24); - } - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - if (*cur != 0) - goto return1; /* error if any extraneous chars */ - if (val != NULL) { - v = xmlSchemaNewValue(XML_SCHEMAS_DECIMAL); - if (v != NULL) { - /* - * Now evaluate the significant digits of the number - */ - if (len != 0) { - - if (integ != ~0u) { - /* - * Get rid of trailing zeroes in the - * fractional part. - */ - while ((len != integ) && (*(cptr-1) == '0')) { - cptr--; - len--; - } - } - /* - * Terminate the (preparsed) string. - */ - if (len != 0) { - *cptr = 0; - cptr = cval; - - xmlSchemaParseUInt((const xmlChar **)&cptr, - &v->value.decimal.lo, - &v->value.decimal.mi, - &v->value.decimal.hi); - } - } - /* - * Set the total digits to 1 if a zero value. - */ - v->value.decimal.sign = neg; - if (len == 0) { - /* Speedup for zero values. */ - v->value.decimal.total = 1; - } else { - v->value.decimal.total = len; - if (integ == ~0u) - v->value.decimal.frac = 0; - else - v->value.decimal.frac = len - integ; - } - *val = v; - } - } - goto return0; - } - case XML_SCHEMAS_TIME: - case XML_SCHEMAS_GDAY: - case XML_SCHEMAS_GMONTH: - case XML_SCHEMAS_GMONTHDAY: - case XML_SCHEMAS_GYEAR: - case XML_SCHEMAS_GYEARMONTH: - case XML_SCHEMAS_DATE: - case XML_SCHEMAS_DATETIME: - ret = xmlSchemaValidateDates(type->builtInType, value, val, - normOnTheFly); - break; - case XML_SCHEMAS_DURATION: - ret = xmlSchemaValidateDuration(type, value, val, - normOnTheFly); - break; - case XML_SCHEMAS_FLOAT: - case XML_SCHEMAS_DOUBLE: { - const xmlChar *cur = value; - int neg = 0; - int digits_before = 0; - int digits_after = 0; - - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - - if ((cur[0] == 'N') && (cur[1] == 'a') && (cur[2] == 'N')) { - cur += 3; - if (*cur != 0) - goto return1; - if (val != NULL) { - if (type == xmlSchemaTypeFloatDef) { - v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT); - if (v != NULL) { - v->value.f = (float) xmlXPathNAN; - } else { - xmlSchemaFreeValue(v); - goto error; - } - } else { - v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE); - if (v != NULL) { - v->value.d = xmlXPathNAN; - } else { - xmlSchemaFreeValue(v); - goto error; - } - } - *val = v; - } - goto return0; - } - if (*cur == '-') { - neg = 1; - cur++; - } - if ((cur[0] == 'I') && (cur[1] == 'N') && (cur[2] == 'F')) { - cur += 3; - if (*cur != 0) - goto return1; - if (val != NULL) { - if (type == xmlSchemaTypeFloatDef) { - v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT); - if (v != NULL) { - if (neg) - v->value.f = (float) xmlXPathNINF; - else - v->value.f = (float) xmlXPathPINF; - } else { - xmlSchemaFreeValue(v); - goto error; - } - } else { - v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE); - if (v != NULL) { - if (neg) - v->value.d = xmlXPathNINF; - else - v->value.d = xmlXPathPINF; - } else { - xmlSchemaFreeValue(v); - goto error; - } - } - *val = v; - } - goto return0; - } - if ((neg == 0) && (*cur == '+')) - cur++; - if ((cur[0] == 0) || (cur[0] == '+') || (cur[0] == '-')) - goto return1; - while ((*cur >= '0') && (*cur <= '9')) { - cur++; - digits_before++; - } - if (*cur == '.') { - cur++; - while ((*cur >= '0') && (*cur <= '9')) { - cur++; - digits_after++; - } - } - if ((digits_before == 0) && (digits_after == 0)) - goto return1; - if ((*cur == 'e') || (*cur == 'E')) { - cur++; - if ((*cur == '-') || (*cur == '+')) - cur++; - while ((*cur >= '0') && (*cur <= '9')) - cur++; - } - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - - if (*cur != 0) - goto return1; - if (val != NULL) { - if (type == xmlSchemaTypeFloatDef) { - v = xmlSchemaNewValue(XML_SCHEMAS_FLOAT); - if (v != NULL) { - /* - * TODO: sscanf seems not to give the correct - * value for extremely high/low values. - * E.g. "1E-149" results in zero. - */ - if (sscanf((const char *) value, "%f", - &(v->value.f)) == 1) { - *val = v; - } else { - xmlSchemaFreeValue(v); - goto return1; - } - } else { - goto error; - } - } else { - v = xmlSchemaNewValue(XML_SCHEMAS_DOUBLE); - if (v != NULL) { - /* - * TODO: sscanf seems not to give the correct - * value for extremely high/low values. - */ - if (sscanf((const char *) value, "%lf", - &(v->value.d)) == 1) { - *val = v; - } else { - xmlSchemaFreeValue(v); - goto return1; - } - } else { - goto error; - } - } - } - goto return0; - } - case XML_SCHEMAS_BOOLEAN:{ - const xmlChar *cur = value; - - if (normOnTheFly) { - while IS_WSP_BLANK_CH(*cur) cur++; - if (*cur == '0') { - ret = 0; - cur++; - } else if (*cur == '1') { - ret = 1; - cur++; - } else if (*cur == 't') { - cur++; - if ((*cur++ == 'r') && (*cur++ == 'u') && - (*cur++ == 'e')) { - ret = 1; - } else - goto return1; - } else if (*cur == 'f') { - cur++; - if ((*cur++ == 'a') && (*cur++ == 'l') && - (*cur++ == 's') && (*cur++ == 'e')) { - ret = 0; - } else - goto return1; - } else - goto return1; - if (*cur != 0) { - while IS_WSP_BLANK_CH(*cur) cur++; - if (*cur != 0) - goto return1; - } - } else { - if ((cur[0] == '0') && (cur[1] == 0)) - ret = 0; - else if ((cur[0] == '1') && (cur[1] == 0)) - ret = 1; - else if ((cur[0] == 't') && (cur[1] == 'r') - && (cur[2] == 'u') && (cur[3] == 'e') - && (cur[4] == 0)) - ret = 1; - else if ((cur[0] == 'f') && (cur[1] == 'a') - && (cur[2] == 'l') && (cur[3] == 's') - && (cur[4] == 'e') && (cur[5] == 0)) - ret = 0; - else - goto return1; - } - if (val != NULL) { - v = xmlSchemaNewValue(XML_SCHEMAS_BOOLEAN); - if (v != NULL) { - v->value.b = ret; - *val = v; - } else { - goto error; - } - } - goto return0; - } - case XML_SCHEMAS_TOKEN:{ - const xmlChar *cur = value; - - if (! normOnTheFly) { - while (*cur != 0) { - if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) { - goto return1; - } else if (*cur == ' ') { - cur++; - if (*cur == 0) - goto return1; - if (*cur == ' ') - goto return1; - } else { - cur++; - } - } - } - if (val != NULL) { - v = xmlSchemaNewValue(XML_SCHEMAS_TOKEN); - if (v != NULL) { - v->value.str = xmlStrdup(value); - *val = v; - } else { - goto error; - } - } - goto return0; - } - case XML_SCHEMAS_LANGUAGE: - if (normOnTheFly) { - norm = xmlSchemaCollapseString(value); - if (norm != NULL) - value = norm; - } - if (xmlCheckLanguageID(value) == 1) { - if (val != NULL) { - v = xmlSchemaNewValue(XML_SCHEMAS_LANGUAGE); - if (v != NULL) { - v->value.str = xmlStrdup(value); - *val = v; - } else { - goto error; - } - } - goto return0; - } - goto return1; - case XML_SCHEMAS_NMTOKEN: - if (xmlValidateNMToken(value, 1) == 0) { - if (val != NULL) { - v = xmlSchemaNewValue(XML_SCHEMAS_NMTOKEN); - if (v != NULL) { - v->value.str = xmlStrdup(value); - *val = v; - } else { - goto error; - } - } - goto return0; - } - goto return1; - case XML_SCHEMAS_NMTOKENS: - ret = xmlSchemaValAtomicListNode(xmlSchemaTypeNmtokenDef, - value, val, node); - if (ret > 0) - ret = 0; - else - ret = 1; - goto done; - case XML_SCHEMAS_NAME: - ret = xmlValidateName(value, 1); - if ((ret == 0) && (val != NULL) && (value != NULL)) { - v = xmlSchemaNewValue(XML_SCHEMAS_NAME); - if (v != NULL) { - const xmlChar *start = value, *end; - while (IS_BLANK_CH(*start)) start++; - end = start; - while ((*end != 0) && (!IS_BLANK_CH(*end))) end++; - v->value.str = xmlStrndup(start, end - start); - *val = v; - } else { - goto error; - } - } - goto done; - case XML_SCHEMAS_QNAME:{ - const xmlChar *uri = NULL; - xmlChar *local = NULL; - - ret = xmlValidateQName(value, 1); - if (ret != 0) - goto done; - if (node != NULL) { - xmlChar *prefix; - xmlNsPtr ns; - - local = xmlSplitQName2(value, &prefix); - ns = xmlSearchNs(node->doc, node, prefix); - if ((ns == NULL) && (prefix != NULL)) { - xmlFree(prefix); - if (local != NULL) - xmlFree(local); - goto return1; - } - if (ns != NULL) - uri = ns->href; - if (prefix != NULL) - xmlFree(prefix); - } - if (val != NULL) { - v = xmlSchemaNewValue(XML_SCHEMAS_QNAME); - if (v == NULL) { - if (local != NULL) - xmlFree(local); - goto error; - } - if (local != NULL) - v->value.qname.name = local; - else - v->value.qname.name = xmlStrdup(value); - if (uri != NULL) - v->value.qname.uri = xmlStrdup(uri); - *val = v; - } else - if (local != NULL) - xmlFree(local); - goto done; - } - case XML_SCHEMAS_NCNAME: - ret = xmlValidateNCName(value, 1); - if ((ret == 0) && (val != NULL)) { - v = xmlSchemaNewValue(XML_SCHEMAS_NCNAME); - if (v != NULL) { - v->value.str = xmlStrdup(value); - *val = v; - } else { - goto error; - } - } - goto done; - case XML_SCHEMAS_ID: - ret = xmlValidateNCName(value, 1); - if ((ret == 0) && (val != NULL)) { - v = xmlSchemaNewValue(XML_SCHEMAS_ID); - if (v != NULL) { - v->value.str = xmlStrdup(value); - *val = v; - } else { - goto error; - } - } - if ((ret == 0) && (node != NULL) && - (node->type == XML_ATTRIBUTE_NODE)) { - xmlAttrPtr attr = (xmlAttrPtr) node; - - /* - * NOTE: the IDness might have already be declared in the DTD - */ - if (attr->atype != XML_ATTRIBUTE_ID) { - xmlIDPtr res; - xmlChar *strip; - - strip = xmlSchemaStrip(value); - if (strip != NULL) { - res = xmlAddID(NULL, node->doc, strip, attr); - xmlFree(strip); - } else - res = xmlAddID(NULL, node->doc, value, attr); - if (res == NULL) { - ret = 2; - } else { - attr->atype = XML_ATTRIBUTE_ID; - } - } - } - goto done; - case XML_SCHEMAS_IDREF: - ret = xmlValidateNCName(value, 1); - if ((ret == 0) && (val != NULL)) { - v = xmlSchemaNewValue(XML_SCHEMAS_IDREF); - if (v == NULL) - goto error; - v->value.str = xmlStrdup(value); - *val = v; - } - if ((ret == 0) && (node != NULL) && - (node->type == XML_ATTRIBUTE_NODE)) { - xmlAttrPtr attr = (xmlAttrPtr) node; - xmlChar *strip; - - strip = xmlSchemaStrip(value); - if (strip != NULL) { - xmlAddRef(NULL, node->doc, strip, attr); - xmlFree(strip); - } else - xmlAddRef(NULL, node->doc, value, attr); - attr->atype = XML_ATTRIBUTE_IDREF; - } - goto done; - case XML_SCHEMAS_IDREFS: - ret = xmlSchemaValAtomicListNode(xmlSchemaTypeIdrefDef, - value, val, node); - if (ret < 0) - ret = 2; - else - ret = 0; - if ((ret == 0) && (node != NULL) && - (node->type == XML_ATTRIBUTE_NODE)) { - xmlAttrPtr attr = (xmlAttrPtr) node; - - attr->atype = XML_ATTRIBUTE_IDREFS; - } - goto done; - case XML_SCHEMAS_ENTITY:{ - xmlChar *strip; - - ret = xmlValidateNCName(value, 1); - if ((node == NULL) || (node->doc == NULL)) - ret = 3; - if (ret == 0) { - xmlEntityPtr ent; - - strip = xmlSchemaStrip(value); - if (strip != NULL) { - ent = xmlGetDocEntity(node->doc, strip); - xmlFree(strip); - } else { - ent = xmlGetDocEntity(node->doc, value); - } - if ((ent == NULL) || - (ent->etype != - XML_EXTERNAL_GENERAL_UNPARSED_ENTITY)) - ret = 4; - } - if ((ret == 0) && (val != NULL)) { - TODO; - } - if ((ret == 0) && (node != NULL) && - (node->type == XML_ATTRIBUTE_NODE)) { - xmlAttrPtr attr = (xmlAttrPtr) node; - - attr->atype = XML_ATTRIBUTE_ENTITY; - } - goto done; - } - case XML_SCHEMAS_ENTITIES: - if ((node == NULL) || (node->doc == NULL)) - goto return3; - ret = xmlSchemaValAtomicListNode(xmlSchemaTypeEntityDef, - value, val, node); - if (ret <= 0) - ret = 1; - else - ret = 0; - if ((ret == 0) && (node != NULL) && - (node->type == XML_ATTRIBUTE_NODE)) { - xmlAttrPtr attr = (xmlAttrPtr) node; - - attr->atype = XML_ATTRIBUTE_ENTITIES; - } - goto done; - case XML_SCHEMAS_NOTATION:{ - xmlChar *uri = NULL; - xmlChar *local = NULL; - - ret = xmlValidateQName(value, 1); - if ((ret == 0) && (node != NULL)) { - xmlChar *prefix; - - local = xmlSplitQName2(value, &prefix); - if (prefix != NULL) { - xmlNsPtr ns; - - ns = xmlSearchNs(node->doc, node, prefix); - if (ns == NULL) - ret = 1; - else if (val != NULL) - uri = xmlStrdup(ns->href); - } - if ((local != NULL) && ((val == NULL) || (ret != 0))) - xmlFree(local); - if (prefix != NULL) - xmlFree(prefix); - } - if ((node == NULL) || (node->doc == NULL)) - ret = 3; - if (ret == 0) { - ret = xmlValidateNotationUse(NULL, node->doc, value); - if (ret == 1) - ret = 0; - else - ret = 1; - } - if ((ret == 0) && (val != NULL)) { - v = xmlSchemaNewValue(XML_SCHEMAS_NOTATION); - if (v != NULL) { - if (local != NULL) - v->value.qname.name = local; - else - v->value.qname.name = xmlStrdup(value); - if (uri != NULL) - v->value.qname.uri = uri; - - *val = v; - } else { - if (local != NULL) - xmlFree(local); - if (uri != NULL) - xmlFree(uri); - goto error; - } - } - goto done; - } - case XML_SCHEMAS_ANYURI:{ - if (*value != 0) { - xmlURIPtr uri; - xmlChar *tmpval, *cur; - if (normOnTheFly) { - norm = xmlSchemaCollapseString(value); - if (norm != NULL) - value = norm; - } - tmpval = xmlStrdup(value); - for (cur = tmpval; *cur; ++cur) { - if (*cur < 32 || *cur >= 127 || *cur == ' ' || - *cur == '<' || *cur == '>' || *cur == '"' || - *cur == '{' || *cur == '}' || *cur == '|' || - *cur == '\\' || *cur == '^' || *cur == '`' || - *cur == '\'') - *cur = '_'; - } - uri = xmlParseURI((const char *) tmpval); - xmlFree(tmpval); - if (uri == NULL) - goto return1; - xmlFreeURI(uri); - } - - if (val != NULL) { - v = xmlSchemaNewValue(XML_SCHEMAS_ANYURI); - if (v == NULL) - goto error; - v->value.str = xmlStrdup(value); - *val = v; - } - goto return0; - } - case XML_SCHEMAS_HEXBINARY:{ - const xmlChar *cur = value, *start; - xmlChar *base; - int total, i = 0; - - if (cur == NULL) - goto return1; - - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - - start = cur; - while (((*cur >= '0') && (*cur <= '9')) || - ((*cur >= 'A') && (*cur <= 'F')) || - ((*cur >= 'a') && (*cur <= 'f'))) { - i++; - cur++; - } - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - - if (*cur != 0) - goto return1; - if ((i % 2) != 0) - goto return1; - - if (val != NULL) { - - v = xmlSchemaNewValue(XML_SCHEMAS_HEXBINARY); - if (v == NULL) - goto error; - /* - * Copy only the normalized piece. - * CRITICAL TODO: Check this. - */ - cur = xmlStrndup(start, i); - if (cur == NULL) { - xmlSchemaTypeErrMemory(node, "allocating hexbin data"); - xmlFree(v); - goto return1; - } - - total = i / 2; /* number of octets */ - - base = (xmlChar *) cur; - while (i-- > 0) { - if (*base >= 'a') - *base = *base - ('a' - 'A'); - base++; - } - - v->value.hex.str = (xmlChar *) cur; - v->value.hex.total = total; - *val = v; - } - goto return0; - } - case XML_SCHEMAS_BASE64BINARY:{ - /* ISSUE: - * - * Ignore all stray characters? (yes, currently) - * Worry about long lines? (no, currently) - * - * rfc2045.txt: - * - * "The encoded output stream must be represented in lines of - * no more than 76 characters each. All line breaks or other - * characters not found in Table 1 must be ignored by decoding - * software. In base64 data, characters other than those in - * Table 1, line breaks, and other white space probably - * indicate a transmission error, about which a warning - * message or even a message rejection might be appropriate - * under some circumstances." */ - const xmlChar *cur = value; - xmlChar *base; - int total, i = 0, pad = 0; - - if (cur == NULL) - goto return1; - - for (; *cur; ++cur) { - int decc; - - decc = _xmlSchemaBase64Decode(*cur); - if (decc < 0) ; - else if (decc < 64) - i++; - else - break; - } - for (; *cur; ++cur) { - int decc; - - decc = _xmlSchemaBase64Decode(*cur); - if (decc < 0) ; - else if (decc < 64) - goto return1; - if (decc == 64) - pad++; - } - - /* rfc2045.txt: "Special processing is performed if fewer than - * 24 bits are available at the end of the data being encoded. - * A full encoding quantum is always completed at the end of a - * body. When fewer than 24 input bits are available in an - * input group, zero bits are added (on the right) to form an - * integral number of 6-bit groups. Padding at the end of the - * data is performed using the "=" character. Since all - * base64 input is an integral number of octets, only the - * following cases can arise: (1) the final quantum of - * encoding input is an integral multiple of 24 bits; here, - * the final unit of encoded output will be an integral - * multiple ofindent: Standard input:701: Warning:old style - * assignment ambiguity in "=*". Assuming "= *" 4 characters - * with no "=" padding, (2) the final - * quantum of encoding input is exactly 8 bits; here, the - * final unit of encoded output will be two characters - * followed by two "=" padding characters, or (3) the final - * quantum of encoding input is exactly 16 bits; here, the - * final unit of encoded output will be three characters - * followed by one "=" padding character." */ - - total = 3 * (i / 4); - if (pad == 0) { - if (i % 4 != 0) - goto return1; - } else if (pad == 1) { - int decc; - - if (i % 4 != 3) - goto return1; - for (decc = _xmlSchemaBase64Decode(*cur); - (decc < 0) || (decc > 63); - decc = _xmlSchemaBase64Decode(*cur)) - --cur; - /* 16bits in 24bits means 2 pad bits: nnnnnn nnmmmm mmmm00*/ - /* 00111100 -> 0x3c */ - if (decc & ~0x3c) - goto return1; - total += 2; - } else if (pad == 2) { - int decc; - - if (i % 4 != 2) - goto return1; - for (decc = _xmlSchemaBase64Decode(*cur); - (decc < 0) || (decc > 63); - decc = _xmlSchemaBase64Decode(*cur)) - --cur; - /* 8bits in 12bits means 4 pad bits: nnnnnn nn0000 */ - /* 00110000 -> 0x30 */ - if (decc & ~0x30) - goto return1; - total += 1; - } else - goto return1; - - if (val != NULL) { - v = xmlSchemaNewValue(XML_SCHEMAS_BASE64BINARY); - if (v == NULL) - goto error; - base = - (xmlChar *) xmlMallocAtomic((i + pad + 1) * - sizeof(xmlChar)); - if (base == NULL) { - xmlSchemaTypeErrMemory(node, "allocating base64 data"); - xmlFree(v); - goto return1; - } - v->value.base64.str = base; - for (cur = value; *cur; ++cur) - if (_xmlSchemaBase64Decode(*cur) >= 0) { - *base = *cur; - ++base; - } - *base = 0; - v->value.base64.total = total; - *val = v; - } - goto return0; - } - case XML_SCHEMAS_INTEGER: - case XML_SCHEMAS_PINTEGER: - case XML_SCHEMAS_NPINTEGER: - case XML_SCHEMAS_NINTEGER: - case XML_SCHEMAS_NNINTEGER:{ - const xmlChar *cur = value; - unsigned long lo, mi, hi; - int sign = 0; - - if (cur == NULL) - goto return1; - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - if (*cur == '-') { - sign = 1; - cur++; - } else if (*cur == '+') - cur++; - ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); - if (ret < 0) - goto return1; - if (normOnTheFly) - while IS_WSP_BLANK_CH(*cur) cur++; - if (*cur != 0) - goto return1; - if (type->builtInType == XML_SCHEMAS_NPINTEGER) { - if ((sign == 0) && - ((hi != 0) || (mi != 0) || (lo != 0))) - goto return1; - } else if (type->builtInType == XML_SCHEMAS_PINTEGER) { - if (sign == 1) - goto return1; - if ((hi == 0) && (mi == 0) && (lo == 0)) - goto return1; - } else if (type->builtInType == XML_SCHEMAS_NINTEGER) { - if (sign == 0) - goto return1; - if ((hi == 0) && (mi == 0) && (lo == 0)) - goto return1; - } else if (type->builtInType == XML_SCHEMAS_NNINTEGER) { - if ((sign == 1) && - ((hi != 0) || (mi != 0) || (lo != 0))) - goto return1; - } - if (val != NULL) { - v = xmlSchemaNewValue(type->builtInType); - if (v != NULL) { - if (ret == 0) - ret++; - v->value.decimal.lo = lo; - v->value.decimal.mi = mi; - v->value.decimal.hi = hi; - v->value.decimal.sign = sign; - v->value.decimal.frac = 0; - v->value.decimal.total = ret; - *val = v; - } - } - goto return0; - } - case XML_SCHEMAS_LONG: - case XML_SCHEMAS_BYTE: - case XML_SCHEMAS_SHORT: - case XML_SCHEMAS_INT:{ - const xmlChar *cur = value; - unsigned long lo, mi, hi; - int sign = 0; - - if (cur == NULL) - goto return1; - if (*cur == '-') { - sign = 1; - cur++; - } else if (*cur == '+') - cur++; - ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); - if (ret < 0) - goto return1; - if (*cur != 0) - goto return1; - if (type->builtInType == XML_SCHEMAS_LONG) { - if (hi >= 922) { - if (hi > 922) - goto return1; - if (mi >= 33720368) { - if (mi > 33720368) - goto return1; - if ((sign == 0) && (lo > 54775807)) - goto return1; - if ((sign == 1) && (lo > 54775808)) - goto return1; - } - } - } else if (type->builtInType == XML_SCHEMAS_INT) { - if (hi != 0) - goto return1; - if (mi >= 21) { - if (mi > 21) - goto return1; - if ((sign == 0) && (lo > 47483647)) - goto return1; - if ((sign == 1) && (lo > 47483648)) - goto return1; - } - } else if (type->builtInType == XML_SCHEMAS_SHORT) { - if ((mi != 0) || (hi != 0)) - goto return1; - if ((sign == 1) && (lo > 32768)) - goto return1; - if ((sign == 0) && (lo > 32767)) - goto return1; - } else if (type->builtInType == XML_SCHEMAS_BYTE) { - if ((mi != 0) || (hi != 0)) - goto return1; - if ((sign == 1) && (lo > 128)) - goto return1; - if ((sign == 0) && (lo > 127)) - goto return1; - } - if (val != NULL) { - v = xmlSchemaNewValue(type->builtInType); - if (v != NULL) { - v->value.decimal.lo = lo; - v->value.decimal.mi = mi; - v->value.decimal.hi = hi; - v->value.decimal.sign = sign; - v->value.decimal.frac = 0; - v->value.decimal.total = ret; - *val = v; - } - } - goto return0; - } - case XML_SCHEMAS_UINT: - case XML_SCHEMAS_ULONG: - case XML_SCHEMAS_USHORT: - case XML_SCHEMAS_UBYTE:{ - const xmlChar *cur = value; - unsigned long lo, mi, hi; - - if (cur == NULL) - goto return1; - ret = xmlSchemaParseUInt(&cur, &lo, &mi, &hi); - if (ret < 0) - goto return1; - if (*cur != 0) - goto return1; - if (type->builtInType == XML_SCHEMAS_ULONG) { - if (hi >= 1844) { - if (hi > 1844) - goto return1; - if (mi >= 67440737) { - if (mi > 67440737) - goto return1; - if (lo > 9551615) - goto return1; - } - } - } else if (type->builtInType == XML_SCHEMAS_UINT) { - if (hi != 0) - goto return1; - if (mi >= 42) { - if (mi > 42) - goto return1; - if (lo > 94967295) - goto return1; - } - } else if (type->builtInType == XML_SCHEMAS_USHORT) { - if ((mi != 0) || (hi != 0)) - goto return1; - if (lo > 65535) - goto return1; - } else if (type->builtInType == XML_SCHEMAS_UBYTE) { - if ((mi != 0) || (hi != 0)) - goto return1; - if (lo > 255) - goto return1; - } - if (val != NULL) { - v = xmlSchemaNewValue(type->builtInType); - if (v != NULL) { - v->value.decimal.lo = lo; - v->value.decimal.mi = mi; - v->value.decimal.hi = hi; - v->value.decimal.sign = 0; - v->value.decimal.frac = 0; - v->value.decimal.total = ret; - *val = v; - } - } - goto return0; - } - } - - done: - if (norm != NULL) - xmlFree(norm); - return (ret); - return3: - if (norm != NULL) - xmlFree(norm); - return (3); - return1: - if (norm != NULL) - xmlFree(norm); - return (1); - return0: - if (norm != NULL) - xmlFree(norm); - return (0); - error: - if (norm != NULL) - xmlFree(norm); - return (-1); -} - -/** - * xmlSchemaValPredefTypeNode: - * @type: the predefined type - * @value: the value to check - * @val: the return computed value - * @node: the node containing the value - * - * Check that a value conforms to the lexical space of the predefined type. - * if true a value is computed and returned in @val. - * - * Returns 0 if this validates, a positive error code number otherwise - * and -1 in case of internal or API error. - */ -int -xmlSchemaValPredefTypeNode(xmlSchemaTypePtr type, const xmlChar *value, - xmlSchemaValPtr *val, xmlNodePtr node) { - return(xmlSchemaValAtomicType(type, value, val, node, 0, - XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 1, 0)); -} - -/** - * xmlSchemaValPredefTypeNodeNoNorm: - * @type: the predefined type - * @value: the value to check - * @val: the return computed value - * @node: the node containing the value - * - * Check that a value conforms to the lexical space of the predefined type. - * if true a value is computed and returned in @val. - * This one does apply any normalization to the value. - * - * Returns 0 if this validates, a positive error code number otherwise - * and -1 in case of internal or API error. - */ -int -xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value, - xmlSchemaValPtr *val, xmlNodePtr node) { - return(xmlSchemaValAtomicType(type, value, val, node, 1, - XML_SCHEMA_WHITESPACE_UNKNOWN, 1, 0, 1)); -} - -/** - * xmlSchemaValidatePredefinedType: - * @type: the predefined type - * @value: the value to check - * @val: the return computed value - * - * Check that a value conforms to the lexical space of the predefined type. - * if true a value is computed and returned in @val. - * - * Returns 0 if this validates, a positive error code number otherwise - * and -1 in case of internal or API error. - */ -int -xmlSchemaValidatePredefinedType(xmlSchemaTypePtr type, const xmlChar *value, - xmlSchemaValPtr *val) { - return(xmlSchemaValPredefTypeNode(type, value, val, NULL)); -} - -/** - * xmlSchemaCompareDecimals: - * @x: a first decimal value - * @y: a second decimal value - * - * Compare 2 decimals - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y and -2 in case of error - */ -static int -xmlSchemaCompareDecimals(xmlSchemaValPtr x, xmlSchemaValPtr y) -{ - xmlSchemaValPtr swp; - int order = 1, integx, integy, dlen; - unsigned long hi, mi, lo; - - /* - * First test: If x is -ve and not zero - */ - if ((x->value.decimal.sign) && - ((x->value.decimal.lo != 0) || - (x->value.decimal.mi != 0) || - (x->value.decimal.hi != 0))) { - /* - * Then if y is -ve and not zero reverse the compare - */ - if ((y->value.decimal.sign) && - ((y->value.decimal.lo != 0) || - (y->value.decimal.mi != 0) || - (y->value.decimal.hi != 0))) - order = -1; - /* - * Otherwise (y >= 0) we have the answer - */ - else - return (-1); - /* - * If x is not -ve and y is -ve we have the answer - */ - } else if ((y->value.decimal.sign) && - ((y->value.decimal.lo != 0) || - (y->value.decimal.mi != 0) || - (y->value.decimal.hi != 0))) { - return (1); - } - /* - * If it's not simply determined by a difference in sign, - * then we need to compare the actual values of the two nums. - * To do this, we start by looking at the integral parts. - * If the number of integral digits differ, then we have our - * answer. - */ - integx = x->value.decimal.total - x->value.decimal.frac; - integy = y->value.decimal.total - y->value.decimal.frac; - /* - * NOTE: We changed the "total" for values like "0.1" - * (or "-0.1" or ".1") to be 1, which was 2 previously. - * Therefore the special case, when such values are - * compared with 0, needs to be handled separately; - * otherwise a zero would be recognized incorrectly as - * greater than those values. This has the nice side effect - * that we gain an overall optimized comparison with zeroes. - * Note that a "0" has a "total" of 1 already. - */ - if (integx == 1) { - if (x->value.decimal.lo == 0) { - if (integy != 1) - return -order; - else if (y->value.decimal.lo != 0) - return -order; - else - return(0); - } - } - if (integy == 1) { - if (y->value.decimal.lo == 0) { - if (integx != 1) - return order; - else if (x->value.decimal.lo != 0) - return order; - else - return(0); - } - } - - if (integx > integy) - return order; - else if (integy > integx) - return -order; - - /* - * If the number of integral digits is the same for both numbers, - * then things get a little more complicated. We need to "normalize" - * the numbers in order to properly compare them. To do this, we - * look at the total length of each number (length => number of - * significant digits), and divide the "shorter" by 10 (decreasing - * the length) until they are of equal length. - */ - dlen = x->value.decimal.total - y->value.decimal.total; - if (dlen < 0) { /* y has more digits than x */ - swp = x; - hi = y->value.decimal.hi; - mi = y->value.decimal.mi; - lo = y->value.decimal.lo; - dlen = -dlen; - order = -order; - } else { /* x has more digits than y */ - swp = y; - hi = x->value.decimal.hi; - mi = x->value.decimal.mi; - lo = x->value.decimal.lo; - } - while (dlen > 8) { /* in effect, right shift by 10**8 */ - lo = mi; - mi = hi; - hi = 0; - dlen -= 8; - } - while (dlen > 0) { - unsigned long rem1, rem2; - rem1 = (hi % 10) * 100000000L; - hi = hi / 10; - rem2 = (mi % 10) * 100000000L; - mi = (mi + rem1) / 10; - lo = (lo + rem2) / 10; - dlen--; - } - if (hi > swp->value.decimal.hi) { - return order; - } else if (hi == swp->value.decimal.hi) { - if (mi > swp->value.decimal.mi) { - return order; - } else if (mi == swp->value.decimal.mi) { - if (lo > swp->value.decimal.lo) { - return order; - } else if (lo == swp->value.decimal.lo) { - if (x->value.decimal.total == y->value.decimal.total) { - return 0; - } else { - return order; - } - } - } - } - return -order; -} - -/** - * xmlSchemaCompareDurations: - * @x: a first duration value - * @y: a second duration value - * - * Compare 2 durations - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in - * case of error - */ -static int -xmlSchemaCompareDurations(xmlSchemaValPtr x, xmlSchemaValPtr y) -{ - long carry, mon, day; - double sec; - int invert = 1; - long xmon, xday, myear, minday, maxday; - static const long dayRange [2][12] = { - { 0, 28, 59, 89, 120, 150, 181, 212, 242, 273, 303, 334, }, - { 0, 31, 62, 92, 123, 153, 184, 215, 245, 276, 306, 337} }; - - if ((x == NULL) || (y == NULL)) - return -2; - - /* months */ - mon = x->value.dur.mon - y->value.dur.mon; - - /* seconds */ - sec = x->value.dur.sec - y->value.dur.sec; - carry = (long)(sec / SECS_PER_DAY); - sec -= ((double)carry) * SECS_PER_DAY; - - /* days */ - day = x->value.dur.day - y->value.dur.day + carry; - - /* easy test */ - if (mon == 0) { - if (day == 0) - if (sec == 0.0) - return 0; - else if (sec < 0.0) - return -1; - else - return 1; - else if (day < 0) - return -1; - else - return 1; - } - - if (mon > 0) { - if ((day >= 0) && (sec >= 0.0)) - return 1; - else { - xmon = mon; - xday = -day; - } - } else if ((day <= 0) && (sec <= 0.0)) { - return -1; - } else { - invert = -1; - xmon = -mon; - xday = day; - } - - myear = xmon / 12; - if (myear == 0) { - minday = 0; - maxday = 0; - } else { - maxday = 366 * ((myear + 3) / 4) + - 365 * ((myear - 1) % 4); - minday = maxday - 1; - } - - xmon = xmon % 12; - minday += dayRange[0][xmon]; - maxday += dayRange[1][xmon]; - - if ((maxday == minday) && (maxday == xday)) - return(0); /* can this really happen ? */ - if (maxday < xday) - return(-invert); - if (minday > xday) - return(invert); - - /* indeterminate */ - return 2; -} - -/* - * macros for adding date/times and durations - */ -#define FQUOTIENT(a,b) (floor(((double)a/(double)b))) -#define MODULO(a,b) (a - FQUOTIENT(a,b) * b) -#define FQUOTIENT_RANGE(a,low,high) (FQUOTIENT((a-low),(high-low))) -#define MODULO_RANGE(a,low,high) ((MODULO((a-low),(high-low)))+low) - -/** - * xmlSchemaDupVal: - * @v: the #xmlSchemaValPtr value to duplicate - * - * Makes a copy of @v. The calling program is responsible for freeing - * the returned value. - * - * returns a pointer to a duplicated #xmlSchemaValPtr or NULL if error. - */ -static xmlSchemaValPtr -xmlSchemaDupVal (xmlSchemaValPtr v) -{ - xmlSchemaValPtr ret = xmlSchemaNewValue(v->type); - if (ret == NULL) - return NULL; - - memcpy(ret, v, sizeof(xmlSchemaVal)); - ret->next = NULL; - return ret; -} - -/** - * xmlSchemaCopyValue: - * @val: the precomputed value to be copied - * - * Copies the precomputed value. This duplicates any string within. - * - * Returns the copy or NULL if a copy for a data-type is not implemented. - */ -xmlSchemaValPtr -xmlSchemaCopyValue(xmlSchemaValPtr val) -{ - xmlSchemaValPtr ret = NULL, prev = NULL, cur; - - /* - * Copy the string values. - */ - while (val != NULL) { - switch (val->type) { - case XML_SCHEMAS_ANYTYPE: - case XML_SCHEMAS_IDREFS: - case XML_SCHEMAS_ENTITIES: - case XML_SCHEMAS_NMTOKENS: - xmlSchemaFreeValue(ret); - return (NULL); - case XML_SCHEMAS_ANYSIMPLETYPE: - case XML_SCHEMAS_STRING: - case XML_SCHEMAS_NORMSTRING: - case XML_SCHEMAS_TOKEN: - case XML_SCHEMAS_LANGUAGE: - case XML_SCHEMAS_NAME: - case XML_SCHEMAS_NCNAME: - case XML_SCHEMAS_ID: - case XML_SCHEMAS_IDREF: - case XML_SCHEMAS_ENTITY: - case XML_SCHEMAS_NMTOKEN: - case XML_SCHEMAS_ANYURI: - cur = xmlSchemaDupVal(val); - if (val->value.str != NULL) - cur->value.str = xmlStrdup(BAD_CAST val->value.str); - break; - case XML_SCHEMAS_QNAME: - case XML_SCHEMAS_NOTATION: - cur = xmlSchemaDupVal(val); - if (val->value.qname.name != NULL) - cur->value.qname.name = - xmlStrdup(BAD_CAST val->value.qname.name); - if (val->value.qname.uri != NULL) - cur->value.qname.uri = - xmlStrdup(BAD_CAST val->value.qname.uri); - break; - case XML_SCHEMAS_HEXBINARY: - cur = xmlSchemaDupVal(val); - if (val->value.hex.str != NULL) - cur->value.hex.str = xmlStrdup(BAD_CAST val->value.hex.str); - break; - case XML_SCHEMAS_BASE64BINARY: - cur = xmlSchemaDupVal(val); - if (val->value.base64.str != NULL) - cur->value.base64.str = - xmlStrdup(BAD_CAST val->value.base64.str); - break; - default: - cur = xmlSchemaDupVal(val); - break; - } - if (ret == NULL) - ret = cur; - else - prev->next = cur; - prev = cur; - val = val->next; - } - return (ret); -} - -/** - * _xmlSchemaDateAdd: - * @dt: an #xmlSchemaValPtr - * @dur: an #xmlSchemaValPtr of type #XS_DURATION - * - * Compute a new date/time from @dt and @dur. This function assumes @dt - * is either #XML_SCHEMAS_DATETIME, #XML_SCHEMAS_DATE, #XML_SCHEMAS_GYEARMONTH, - * or #XML_SCHEMAS_GYEAR. The returned #xmlSchemaVal is the same type as - * @dt. The calling program is responsible for freeing the returned value. - * - * Returns a pointer to a new #xmlSchemaVal or NULL if error. - */ -static xmlSchemaValPtr -_xmlSchemaDateAdd (xmlSchemaValPtr dt, xmlSchemaValPtr dur) -{ - xmlSchemaValPtr ret, tmp; - long carry, tempdays, temp; - xmlSchemaValDatePtr r, d; - xmlSchemaValDurationPtr u; - - if ((dt == NULL) || (dur == NULL)) - return NULL; - - ret = xmlSchemaNewValue(dt->type); - if (ret == NULL) - return NULL; - - /* make a copy so we don't alter the original value */ - tmp = xmlSchemaDupVal(dt); - if (tmp == NULL) { - xmlSchemaFreeValue(ret); - return NULL; - } - - r = &(ret->value.date); - d = &(tmp->value.date); - u = &(dur->value.dur); - - /* normalization */ - if (d->mon == 0) - d->mon = 1; - - /* normalize for time zone offset */ - u->sec -= (d->tzo * 60); - d->tzo = 0; - - /* normalization */ - if (d->day == 0) - d->day = 1; - - /* month */ - carry = d->mon + u->mon; - r->mon = (unsigned int) MODULO_RANGE(carry, 1, 13); - carry = (long) FQUOTIENT_RANGE(carry, 1, 13); - - /* year (may be modified later) */ - r->year = d->year + carry; - if (r->year == 0) { - if (d->year > 0) - r->year--; - else - r->year++; - } - - /* time zone */ - r->tzo = d->tzo; - r->tz_flag = d->tz_flag; - - /* seconds */ - r->sec = d->sec + u->sec; - carry = (long) FQUOTIENT((long)r->sec, 60); - if (r->sec != 0.0) { - r->sec = MODULO(r->sec, 60.0); - } - - /* minute */ - carry += d->min; - r->min = (unsigned int) MODULO(carry, 60); - carry = (long) FQUOTIENT(carry, 60); - - /* hours */ - carry += d->hour; - r->hour = (unsigned int) MODULO(carry, 24); - carry = (long)FQUOTIENT(carry, 24); - - /* - * days - * Note we use tempdays because the temporary values may need more - * than 5 bits - */ - if ((VALID_YEAR(r->year)) && (VALID_MONTH(r->mon)) && - (d->day > MAX_DAYINMONTH(r->year, r->mon))) - tempdays = MAX_DAYINMONTH(r->year, r->mon); - else if (d->day < 1) - tempdays = 1; - else - tempdays = d->day; - - tempdays += u->day + carry; - - while (1) { - if (tempdays < 1) { - long tmon = (long) MODULO_RANGE((int)r->mon-1, 1, 13); - long tyr = r->year + (long)FQUOTIENT_RANGE((int)r->mon-1, 1, 13); - if (tyr == 0) - tyr--; - /* - * Coverity detected an overrun in daysInMonth - * of size 12 at position 12 with index variable "((r)->mon - 1)" - */ - if (tmon < 1) - tmon = 1; - if (tmon > 12) - tmon = 12; - tempdays += MAX_DAYINMONTH(tyr, tmon); - carry = -1; - } else if (VALID_YEAR(r->year) && VALID_MONTH(r->mon) && - tempdays > (long) MAX_DAYINMONTH(r->year, r->mon)) { - tempdays = tempdays - MAX_DAYINMONTH(r->year, r->mon); - carry = 1; - } else - break; - - temp = r->mon + carry; - r->mon = (unsigned int) MODULO_RANGE(temp, 1, 13); - r->year = r->year + (unsigned int) FQUOTIENT_RANGE(temp, 1, 13); - if (r->year == 0) { - if (temp < 1) - r->year--; - else - r->year++; - } - } - - r->day = tempdays; - - /* - * adjust the date/time type to the date values - */ - if (ret->type != XML_SCHEMAS_DATETIME) { - if ((r->hour) || (r->min) || (r->sec)) - ret->type = XML_SCHEMAS_DATETIME; - else if (ret->type != XML_SCHEMAS_DATE) { - if ((r->mon != 1) && (r->day != 1)) - ret->type = XML_SCHEMAS_DATE; - else if ((ret->type != XML_SCHEMAS_GYEARMONTH) && (r->mon != 1)) - ret->type = XML_SCHEMAS_GYEARMONTH; - } - } - - xmlSchemaFreeValue(tmp); - - return ret; -} - -/** - * xmlSchemaDateNormalize: - * @dt: an #xmlSchemaValPtr of a date/time type value. - * @offset: number of seconds to adjust @dt by. - * - * Normalize @dt to GMT time. The @offset parameter is subtracted from - * the return value is a time-zone offset is present on @dt. - * - * Returns a normalized copy of @dt or NULL if error. - */ -static xmlSchemaValPtr -xmlSchemaDateNormalize (xmlSchemaValPtr dt, double offset) -{ - xmlSchemaValPtr dur, ret; - - if (dt == NULL) - return NULL; - - if (((dt->type != XML_SCHEMAS_TIME) && - (dt->type != XML_SCHEMAS_DATETIME) && - (dt->type != XML_SCHEMAS_DATE)) || (dt->value.date.tzo == 0)) - return xmlSchemaDupVal(dt); - - dur = xmlSchemaNewValue(XML_SCHEMAS_DURATION); - if (dur == NULL) - return NULL; - - dur->value.date.sec -= offset; - - ret = _xmlSchemaDateAdd(dt, dur); - if (ret == NULL) - return NULL; - - xmlSchemaFreeValue(dur); - - /* ret->value.date.tzo = 0; */ - return ret; -} - -/** - * _xmlSchemaDateCastYMToDays: - * @dt: an #xmlSchemaValPtr - * - * Convert mon and year of @dt to total number of days. Take the - * number of years since (or before) 1 AD and add the number of leap - * years. This is a function because negative - * years must be handled a little differently and there is no zero year. - * - * Returns number of days. - */ -static long -_xmlSchemaDateCastYMToDays (const xmlSchemaValPtr dt) -{ - long ret; - int mon; - - mon = dt->value.date.mon; - if (mon <= 0) mon = 1; /* normalization */ - - if (dt->value.date.year <= 0) - ret = (dt->value.date.year * 365) + - (((dt->value.date.year+1)/4)-((dt->value.date.year+1)/100)+ - ((dt->value.date.year+1)/400)) + - DAY_IN_YEAR(0, mon, dt->value.date.year); - else - ret = ((dt->value.date.year-1) * 365) + - (((dt->value.date.year-1)/4)-((dt->value.date.year-1)/100)+ - ((dt->value.date.year-1)/400)) + - DAY_IN_YEAR(0, mon, dt->value.date.year); - - return ret; -} - -/** - * TIME_TO_NUMBER: - * @dt: an #xmlSchemaValPtr - * - * Calculates the number of seconds in the time portion of @dt. - * - * Returns seconds. - */ -#define TIME_TO_NUMBER(dt) \ - ((double)((dt->value.date.hour * SECS_PER_HOUR) + \ - (dt->value.date.min * SECS_PER_MIN) + \ - (dt->value.date.tzo * SECS_PER_MIN)) + \ - dt->value.date.sec) - -/** - * xmlSchemaCompareDates: - * @x: a first date/time value - * @y: a second date/time value - * - * Compare 2 date/times - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in - * case of error - */ -static int -xmlSchemaCompareDates (xmlSchemaValPtr x, xmlSchemaValPtr y) -{ - unsigned char xmask, ymask, xor_mask, and_mask; - xmlSchemaValPtr p1, p2, q1, q2; - long p1d, p2d, q1d, q2d; - - if ((x == NULL) || (y == NULL)) - return -2; - - if (x->value.date.tz_flag) { - - if (!y->value.date.tz_flag) { - p1 = xmlSchemaDateNormalize(x, 0); - p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day; - /* normalize y + 14:00 */ - q1 = xmlSchemaDateNormalize(y, (14 * SECS_PER_HOUR)); - - q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day; - if (p1d < q1d) { - xmlSchemaFreeValue(p1); - xmlSchemaFreeValue(q1); - return -1; - } else if (p1d == q1d) { - double sec; - - sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1); - if (sec < 0.0) { - xmlSchemaFreeValue(p1); - xmlSchemaFreeValue(q1); - return -1; - } else { - int ret = 0; - /* normalize y - 14:00 */ - q2 = xmlSchemaDateNormalize(y, -(14 * SECS_PER_HOUR)); - q2d = _xmlSchemaDateCastYMToDays(q2) + q2->value.date.day; - if (p1d > q2d) - ret = 1; - else if (p1d == q2d) { - sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q2); - if (sec > 0.0) - ret = 1; - else - ret = 2; /* indeterminate */ - } - xmlSchemaFreeValue(p1); - xmlSchemaFreeValue(q1); - xmlSchemaFreeValue(q2); - if (ret != 0) - return(ret); - } - } else { - xmlSchemaFreeValue(p1); - xmlSchemaFreeValue(q1); - } - } - } else if (y->value.date.tz_flag) { - q1 = xmlSchemaDateNormalize(y, 0); - q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day; - - /* normalize x - 14:00 */ - p1 = xmlSchemaDateNormalize(x, -(14 * SECS_PER_HOUR)); - p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day; - - if (p1d < q1d) { - xmlSchemaFreeValue(p1); - xmlSchemaFreeValue(q1); - return -1; - } else if (p1d == q1d) { - double sec; - - sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1); - if (sec < 0.0) { - xmlSchemaFreeValue(p1); - xmlSchemaFreeValue(q1); - return -1; - } else { - int ret = 0; - /* normalize x + 14:00 */ - p2 = xmlSchemaDateNormalize(x, (14 * SECS_PER_HOUR)); - p2d = _xmlSchemaDateCastYMToDays(p2) + p2->value.date.day; - - if (p2d > q1d) { - ret = 1; - } else if (p2d == q1d) { - sec = TIME_TO_NUMBER(p2) - TIME_TO_NUMBER(q1); - if (sec > 0.0) - ret = 1; - else - ret = 2; /* indeterminate */ - } - xmlSchemaFreeValue(p1); - xmlSchemaFreeValue(q1); - xmlSchemaFreeValue(p2); - if (ret != 0) - return(ret); - } - } else { - xmlSchemaFreeValue(p1); - xmlSchemaFreeValue(q1); - } - } - - /* - * if the same type then calculate the difference - */ - if (x->type == y->type) { - int ret = 0; - q1 = xmlSchemaDateNormalize(y, 0); - q1d = _xmlSchemaDateCastYMToDays(q1) + q1->value.date.day; - - p1 = xmlSchemaDateNormalize(x, 0); - p1d = _xmlSchemaDateCastYMToDays(p1) + p1->value.date.day; - - if (p1d < q1d) { - ret = -1; - } else if (p1d > q1d) { - ret = 1; - } else { - double sec; - - sec = TIME_TO_NUMBER(p1) - TIME_TO_NUMBER(q1); - if (sec < 0.0) - ret = -1; - else if (sec > 0.0) - ret = 1; - - } - xmlSchemaFreeValue(p1); - xmlSchemaFreeValue(q1); - return(ret); - } - - switch (x->type) { - case XML_SCHEMAS_DATETIME: - xmask = 0xf; - break; - case XML_SCHEMAS_DATE: - xmask = 0x7; - break; - case XML_SCHEMAS_GYEAR: - xmask = 0x1; - break; - case XML_SCHEMAS_GMONTH: - xmask = 0x2; - break; - case XML_SCHEMAS_GDAY: - xmask = 0x3; - break; - case XML_SCHEMAS_GYEARMONTH: - xmask = 0x3; - break; - case XML_SCHEMAS_GMONTHDAY: - xmask = 0x6; - break; - case XML_SCHEMAS_TIME: - xmask = 0x8; - break; - default: - xmask = 0; - break; - } - - switch (y->type) { - case XML_SCHEMAS_DATETIME: - ymask = 0xf; - break; - case XML_SCHEMAS_DATE: - ymask = 0x7; - break; - case XML_SCHEMAS_GYEAR: - ymask = 0x1; - break; - case XML_SCHEMAS_GMONTH: - ymask = 0x2; - break; - case XML_SCHEMAS_GDAY: - ymask = 0x3; - break; - case XML_SCHEMAS_GYEARMONTH: - ymask = 0x3; - break; - case XML_SCHEMAS_GMONTHDAY: - ymask = 0x6; - break; - case XML_SCHEMAS_TIME: - ymask = 0x8; - break; - default: - ymask = 0; - break; - } - - xor_mask = xmask ^ ymask; /* mark type differences */ - and_mask = xmask & ymask; /* mark field specification */ - - /* year */ - if (xor_mask & 1) - return 2; /* indeterminate */ - else if (and_mask & 1) { - if (x->value.date.year < y->value.date.year) - return -1; - else if (x->value.date.year > y->value.date.year) - return 1; - } - - /* month */ - if (xor_mask & 2) - return 2; /* indeterminate */ - else if (and_mask & 2) { - if (x->value.date.mon < y->value.date.mon) - return -1; - else if (x->value.date.mon > y->value.date.mon) - return 1; - } - - /* day */ - if (xor_mask & 4) - return 2; /* indeterminate */ - else if (and_mask & 4) { - if (x->value.date.day < y->value.date.day) - return -1; - else if (x->value.date.day > y->value.date.day) - return 1; - } - - /* time */ - if (xor_mask & 8) - return 2; /* indeterminate */ - else if (and_mask & 8) { - if (x->value.date.hour < y->value.date.hour) - return -1; - else if (x->value.date.hour > y->value.date.hour) - return 1; - else if (x->value.date.min < y->value.date.min) - return -1; - else if (x->value.date.min > y->value.date.min) - return 1; - else if (x->value.date.sec < y->value.date.sec) - return -1; - else if (x->value.date.sec > y->value.date.sec) - return 1; - } - - return 0; -} - -/** - * xmlSchemaComparePreserveReplaceStrings: - * @x: a first string value - * @y: a second string value - * @invert: inverts the result if x < y or x > y. - * - * Compare 2 string for their normalized values. - * @x is a string with whitespace of "preserve", @y is - * a string with a whitespace of "replace". I.e. @x could - * be an "xsd:string" and @y an "xsd:normalizedString". - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in - * case of error - */ -static int -xmlSchemaComparePreserveReplaceStrings(const xmlChar *x, - const xmlChar *y, - int invert) -{ - int tmp; - - while ((*x != 0) && (*y != 0)) { - if (IS_WSP_REPLACE_CH(*y)) { - if (! IS_WSP_SPACE_CH(*x)) { - if ((*x - 0x20) < 0) { - if (invert) - return(1); - else - return(-1); - } else { - if (invert) - return(-1); - else - return(1); - } - } - } else { - tmp = *x - *y; - if (tmp < 0) { - if (invert) - return(1); - else - return(-1); - } - if (tmp > 0) { - if (invert) - return(-1); - else - return(1); - } - } - x++; - y++; - } - if (*x != 0) { - if (invert) - return(-1); - else - return(1); - } - if (*y != 0) { - if (invert) - return(1); - else - return(-1); - } - return(0); -} - -/** - * xmlSchemaComparePreserveCollapseStrings: - * @x: a first string value - * @y: a second string value - * - * Compare 2 string for their normalized values. - * @x is a string with whitespace of "preserve", @y is - * a string with a whitespace of "collapse". I.e. @x could - * be an "xsd:string" and @y an "xsd:normalizedString". - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in - * case of error - */ -static int -xmlSchemaComparePreserveCollapseStrings(const xmlChar *x, - const xmlChar *y, - int invert) -{ - int tmp; - - /* - * Skip leading blank chars of the collapsed string. - */ - while IS_WSP_BLANK_CH(*y) - y++; - - while ((*x != 0) && (*y != 0)) { - if IS_WSP_BLANK_CH(*y) { - if (! IS_WSP_SPACE_CH(*x)) { - /* - * The yv character would have been replaced to 0x20. - */ - if ((*x - 0x20) < 0) { - if (invert) - return(1); - else - return(-1); - } else { - if (invert) - return(-1); - else - return(1); - } - } - x++; - y++; - /* - * Skip contiguous blank chars of the collapsed string. - */ - while IS_WSP_BLANK_CH(*y) - y++; - } else { - tmp = *x++ - *y++; - if (tmp < 0) { - if (invert) - return(1); - else - return(-1); - } - if (tmp > 0) { - if (invert) - return(-1); - else - return(1); - } - } - } - if (*x != 0) { - if (invert) - return(-1); - else - return(1); - } - if (*y != 0) { - /* - * Skip trailing blank chars of the collapsed string. - */ - while IS_WSP_BLANK_CH(*y) - y++; - if (*y != 0) { - if (invert) - return(1); - else - return(-1); - } - } - return(0); -} - -/** - * xmlSchemaComparePreserveCollapseStrings: - * @x: a first string value - * @y: a second string value - * - * Compare 2 string for their normalized values. - * @x is a string with whitespace of "preserve", @y is - * a string with a whitespace of "collapse". I.e. @x could - * be an "xsd:string" and @y an "xsd:normalizedString". - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in - * case of error - */ -static int -xmlSchemaCompareReplaceCollapseStrings(const xmlChar *x, - const xmlChar *y, - int invert) -{ - int tmp; - - /* - * Skip leading blank chars of the collapsed string. - */ - while IS_WSP_BLANK_CH(*y) - y++; - - while ((*x != 0) && (*y != 0)) { - if IS_WSP_BLANK_CH(*y) { - if (! IS_WSP_BLANK_CH(*x)) { - /* - * The yv character would have been replaced to 0x20. - */ - if ((*x - 0x20) < 0) { - if (invert) - return(1); - else - return(-1); - } else { - if (invert) - return(-1); - else - return(1); - } - } - x++; - y++; - /* - * Skip contiguous blank chars of the collapsed string. - */ - while IS_WSP_BLANK_CH(*y) - y++; - } else { - if IS_WSP_BLANK_CH(*x) { - /* - * The xv character would have been replaced to 0x20. - */ - if ((0x20 - *y) < 0) { - if (invert) - return(1); - else - return(-1); - } else { - if (invert) - return(-1); - else - return(1); - } - } - tmp = *x++ - *y++; - if (tmp < 0) - return(-1); - if (tmp > 0) - return(1); - } - } - if (*x != 0) { - if (invert) - return(-1); - else - return(1); - } - if (*y != 0) { - /* - * Skip trailing blank chars of the collapsed string. - */ - while IS_WSP_BLANK_CH(*y) - y++; - if (*y != 0) { - if (invert) - return(1); - else - return(-1); - } - } - return(0); -} - - -/** - * xmlSchemaCompareReplacedStrings: - * @x: a first string value - * @y: a second string value - * - * Compare 2 string for their normalized values. - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in - * case of error - */ -static int -xmlSchemaCompareReplacedStrings(const xmlChar *x, - const xmlChar *y) -{ - int tmp; - - while ((*x != 0) && (*y != 0)) { - if IS_WSP_BLANK_CH(*y) { - if (! IS_WSP_BLANK_CH(*x)) { - if ((*x - 0x20) < 0) - return(-1); - else - return(1); - } - } else { - if IS_WSP_BLANK_CH(*x) { - if ((0x20 - *y) < 0) - return(-1); - else - return(1); - } - tmp = *x - *y; - if (tmp < 0) - return(-1); - if (tmp > 0) - return(1); - } - x++; - y++; - } - if (*x != 0) - return(1); - if (*y != 0) - return(-1); - return(0); -} - -/** - * xmlSchemaCompareNormStrings: - * @x: a first string value - * @y: a second string value - * - * Compare 2 string for their normalized values. - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, and -2 in - * case of error - */ -static int -xmlSchemaCompareNormStrings(const xmlChar *x, - const xmlChar *y) { - int tmp; - - while (IS_BLANK_CH(*x)) x++; - while (IS_BLANK_CH(*y)) y++; - while ((*x != 0) && (*y != 0)) { - if (IS_BLANK_CH(*x)) { - if (!IS_BLANK_CH(*y)) { - tmp = *x - *y; - return(tmp); - } - while (IS_BLANK_CH(*x)) x++; - while (IS_BLANK_CH(*y)) y++; - } else { - tmp = *x++ - *y++; - if (tmp < 0) - return(-1); - if (tmp > 0) - return(1); - } - } - if (*x != 0) { - while (IS_BLANK_CH(*x)) x++; - if (*x != 0) - return(1); - } - if (*y != 0) { - while (IS_BLANK_CH(*y)) y++; - if (*y != 0) - return(-1); - } - return(0); -} - -/** - * xmlSchemaCompareFloats: - * @x: a first float or double value - * @y: a second float or double value - * - * Compare 2 values - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in - * case of error - */ -static int -xmlSchemaCompareFloats(xmlSchemaValPtr x, xmlSchemaValPtr y) { - double d1, d2; - - if ((x == NULL) || (y == NULL)) - return(-2); - - /* - * Cast everything to doubles. - */ - if (x->type == XML_SCHEMAS_DOUBLE) - d1 = x->value.d; - else if (x->type == XML_SCHEMAS_FLOAT) - d1 = x->value.f; - else - return(-2); - - if (y->type == XML_SCHEMAS_DOUBLE) - d2 = y->value.d; - else if (y->type == XML_SCHEMAS_FLOAT) - d2 = y->value.f; - else - return(-2); - - /* - * Check for special cases. - */ - if (xmlXPathIsNaN(d1)) { - if (xmlXPathIsNaN(d2)) - return(0); - return(1); - } - if (xmlXPathIsNaN(d2)) - return(-1); - if (d1 == xmlXPathPINF) { - if (d2 == xmlXPathPINF) - return(0); - return(1); - } - if (d2 == xmlXPathPINF) - return(-1); - if (d1 == xmlXPathNINF) { - if (d2 == xmlXPathNINF) - return(0); - return(-1); - } - if (d2 == xmlXPathNINF) - return(1); - - /* - * basic tests, the last one we should have equality, but - * portability is more important than speed and handling - * NaN or Inf in a portable way is always a challenge, so ... - */ - if (d1 < d2) - return(-1); - if (d1 > d2) - return(1); - if (d1 == d2) - return(0); - return(2); -} - -/** - * xmlSchemaCompareValues: - * @x: a first value - * @xvalue: the first value as a string (optional) - * @xwtsp: the whitespace type - * @y: a second value - * @xvalue: the second value as a string (optional) - * @ywtsp: the whitespace type - * - * Compare 2 values - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, 3 if not - * comparable and -2 in case of error - */ -static int -xmlSchemaCompareValuesInternal(xmlSchemaValType xtype, - xmlSchemaValPtr x, - const xmlChar *xvalue, - xmlSchemaWhitespaceValueType xws, - xmlSchemaValType ytype, - xmlSchemaValPtr y, - const xmlChar *yvalue, - xmlSchemaWhitespaceValueType yws) -{ - switch (xtype) { - case XML_SCHEMAS_UNKNOWN: - case XML_SCHEMAS_ANYTYPE: - return(-2); - case XML_SCHEMAS_INTEGER: - case XML_SCHEMAS_NPINTEGER: - case XML_SCHEMAS_NINTEGER: - case XML_SCHEMAS_NNINTEGER: - case XML_SCHEMAS_PINTEGER: - case XML_SCHEMAS_INT: - case XML_SCHEMAS_UINT: - case XML_SCHEMAS_LONG: - case XML_SCHEMAS_ULONG: - case XML_SCHEMAS_SHORT: - case XML_SCHEMAS_USHORT: - case XML_SCHEMAS_BYTE: - case XML_SCHEMAS_UBYTE: - case XML_SCHEMAS_DECIMAL: - if ((x == NULL) || (y == NULL)) - return(-2); - if (ytype == xtype) - return(xmlSchemaCompareDecimals(x, y)); - if ((ytype == XML_SCHEMAS_DECIMAL) || - (ytype == XML_SCHEMAS_INTEGER) || - (ytype == XML_SCHEMAS_NPINTEGER) || - (ytype == XML_SCHEMAS_NINTEGER) || - (ytype == XML_SCHEMAS_NNINTEGER) || - (ytype == XML_SCHEMAS_PINTEGER) || - (ytype == XML_SCHEMAS_INT) || - (ytype == XML_SCHEMAS_UINT) || - (ytype == XML_SCHEMAS_LONG) || - (ytype == XML_SCHEMAS_ULONG) || - (ytype == XML_SCHEMAS_SHORT) || - (ytype == XML_SCHEMAS_USHORT) || - (ytype == XML_SCHEMAS_BYTE) || - (ytype == XML_SCHEMAS_UBYTE)) - return(xmlSchemaCompareDecimals(x, y)); - return(-2); - case XML_SCHEMAS_DURATION: - if ((x == NULL) || (y == NULL)) - return(-2); - if (ytype == XML_SCHEMAS_DURATION) - return(xmlSchemaCompareDurations(x, y)); - return(-2); - case XML_SCHEMAS_TIME: - case XML_SCHEMAS_GDAY: - case XML_SCHEMAS_GMONTH: - case XML_SCHEMAS_GMONTHDAY: - case XML_SCHEMAS_GYEAR: - case XML_SCHEMAS_GYEARMONTH: - case XML_SCHEMAS_DATE: - case XML_SCHEMAS_DATETIME: - if ((x == NULL) || (y == NULL)) - return(-2); - if ((ytype == XML_SCHEMAS_DATETIME) || - (ytype == XML_SCHEMAS_TIME) || - (ytype == XML_SCHEMAS_GDAY) || - (ytype == XML_SCHEMAS_GMONTH) || - (ytype == XML_SCHEMAS_GMONTHDAY) || - (ytype == XML_SCHEMAS_GYEAR) || - (ytype == XML_SCHEMAS_DATE) || - (ytype == XML_SCHEMAS_GYEARMONTH)) - return (xmlSchemaCompareDates(x, y)); - return (-2); - /* - * Note that we will support comparison of string types against - * anySimpleType as well. - */ - case XML_SCHEMAS_ANYSIMPLETYPE: - case XML_SCHEMAS_STRING: - case XML_SCHEMAS_NORMSTRING: - case XML_SCHEMAS_TOKEN: - case XML_SCHEMAS_LANGUAGE: - case XML_SCHEMAS_NMTOKEN: - case XML_SCHEMAS_NAME: - case XML_SCHEMAS_NCNAME: - case XML_SCHEMAS_ID: - case XML_SCHEMAS_IDREF: - case XML_SCHEMAS_ENTITY: - case XML_SCHEMAS_ANYURI: - { - const xmlChar *xv, *yv; - - if (x == NULL) - xv = xvalue; - else - xv = x->value.str; - if (y == NULL) - yv = yvalue; - else - yv = y->value.str; - /* - * TODO: Compare those against QName. - */ - if (ytype == XML_SCHEMAS_QNAME) { - TODO - if (y == NULL) - return(-2); - return (-2); - } - if ((ytype == XML_SCHEMAS_ANYSIMPLETYPE) || - (ytype == XML_SCHEMAS_STRING) || - (ytype == XML_SCHEMAS_NORMSTRING) || - (ytype == XML_SCHEMAS_TOKEN) || - (ytype == XML_SCHEMAS_LANGUAGE) || - (ytype == XML_SCHEMAS_NMTOKEN) || - (ytype == XML_SCHEMAS_NAME) || - (ytype == XML_SCHEMAS_NCNAME) || - (ytype == XML_SCHEMAS_ID) || - (ytype == XML_SCHEMAS_IDREF) || - (ytype == XML_SCHEMAS_ENTITY) || - (ytype == XML_SCHEMAS_ANYURI)) { - - if (xws == XML_SCHEMA_WHITESPACE_PRESERVE) { - - if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) { - /* TODO: What about x < y or x > y. */ - if (xmlStrEqual(xv, yv)) - return (0); - else - return (2); - } else if (yws == XML_SCHEMA_WHITESPACE_REPLACE) - return (xmlSchemaComparePreserveReplaceStrings(xv, yv, 0)); - else if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE) - return (xmlSchemaComparePreserveCollapseStrings(xv, yv, 0)); - - } else if (xws == XML_SCHEMA_WHITESPACE_REPLACE) { - - if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) - return (xmlSchemaComparePreserveReplaceStrings(yv, xv, 1)); - if (yws == XML_SCHEMA_WHITESPACE_REPLACE) - return (xmlSchemaCompareReplacedStrings(xv, yv)); - if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE) - return (xmlSchemaCompareReplaceCollapseStrings(xv, yv, 0)); - - } else if (xws == XML_SCHEMA_WHITESPACE_COLLAPSE) { - - if (yws == XML_SCHEMA_WHITESPACE_PRESERVE) - return (xmlSchemaComparePreserveCollapseStrings(yv, xv, 1)); - if (yws == XML_SCHEMA_WHITESPACE_REPLACE) - return (xmlSchemaCompareReplaceCollapseStrings(yv, xv, 1)); - if (yws == XML_SCHEMA_WHITESPACE_COLLAPSE) - return (xmlSchemaCompareNormStrings(xv, yv)); - } else - return (-2); - - } - return (-2); - } - case XML_SCHEMAS_QNAME: - case XML_SCHEMAS_NOTATION: - if ((x == NULL) || (y == NULL)) - return(-2); - if ((ytype == XML_SCHEMAS_QNAME) || - (ytype == XML_SCHEMAS_NOTATION)) { - if ((xmlStrEqual(x->value.qname.name, y->value.qname.name)) && - (xmlStrEqual(x->value.qname.uri, y->value.qname.uri))) - return(0); - return(2); - } - return (-2); - case XML_SCHEMAS_FLOAT: - case XML_SCHEMAS_DOUBLE: - if ((x == NULL) || (y == NULL)) - return(-2); - if ((ytype == XML_SCHEMAS_FLOAT) || - (ytype == XML_SCHEMAS_DOUBLE)) - return (xmlSchemaCompareFloats(x, y)); - return (-2); - case XML_SCHEMAS_BOOLEAN: - if ((x == NULL) || (y == NULL)) - return(-2); - if (ytype == XML_SCHEMAS_BOOLEAN) { - if (x->value.b == y->value.b) - return(0); - if (x->value.b == 0) - return(-1); - return(1); - } - return (-2); - case XML_SCHEMAS_HEXBINARY: - if ((x == NULL) || (y == NULL)) - return(-2); - if (ytype == XML_SCHEMAS_HEXBINARY) { - if (x->value.hex.total == y->value.hex.total) { - int ret = xmlStrcmp(x->value.hex.str, y->value.hex.str); - if (ret > 0) - return(1); - else if (ret == 0) - return(0); - } - else if (x->value.hex.total > y->value.hex.total) - return(1); - - return(-1); - } - return (-2); - case XML_SCHEMAS_BASE64BINARY: - if ((x == NULL) || (y == NULL)) - return(-2); - if (ytype == XML_SCHEMAS_BASE64BINARY) { - if (x->value.base64.total == y->value.base64.total) { - int ret = xmlStrcmp(x->value.base64.str, - y->value.base64.str); - if (ret > 0) - return(1); - else if (ret == 0) - return(0); - else - return(-1); - } - else if (x->value.base64.total > y->value.base64.total) - return(1); - else - return(-1); - } - return (-2); - case XML_SCHEMAS_IDREFS: - case XML_SCHEMAS_ENTITIES: - case XML_SCHEMAS_NMTOKENS: - TODO - break; - } - return -2; -} - -/** - * xmlSchemaCompareValues: - * @x: a first value - * @y: a second value - * - * Compare 2 values - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in - * case of error - */ -int -xmlSchemaCompareValues(xmlSchemaValPtr x, xmlSchemaValPtr y) { - xmlSchemaWhitespaceValueType xws, yws; - - if ((x == NULL) || (y == NULL)) - return(-2); - if (x->type == XML_SCHEMAS_STRING) - xws = XML_SCHEMA_WHITESPACE_PRESERVE; - else if (x->type == XML_SCHEMAS_NORMSTRING) - xws = XML_SCHEMA_WHITESPACE_REPLACE; - else - xws = XML_SCHEMA_WHITESPACE_COLLAPSE; - - if (y->type == XML_SCHEMAS_STRING) - yws = XML_SCHEMA_WHITESPACE_PRESERVE; - else if (y->type == XML_SCHEMAS_NORMSTRING) - yws = XML_SCHEMA_WHITESPACE_REPLACE; - else - yws = XML_SCHEMA_WHITESPACE_COLLAPSE; - - return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type, - y, NULL, yws)); -} - -/** - * xmlSchemaCompareValuesWhtsp: - * @x: a first value - * @xws: the whitespace value of x - * @y: a second value - * @yws: the whitespace value of y - * - * Compare 2 values - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in - * case of error - */ -int -xmlSchemaCompareValuesWhtsp(xmlSchemaValPtr x, - xmlSchemaWhitespaceValueType xws, - xmlSchemaValPtr y, - xmlSchemaWhitespaceValueType yws) -{ - if ((x == NULL) || (y == NULL)) - return(-2); - return(xmlSchemaCompareValuesInternal(x->type, x, NULL, xws, y->type, - y, NULL, yws)); -} - -/** - * xmlSchemaCompareValuesWhtspExt: - * @x: a first value - * @xws: the whitespace value of x - * @y: a second value - * @yws: the whitespace value of y - * - * Compare 2 values - * - * Returns -1 if x < y, 0 if x == y, 1 if x > y, 2 if x <> y, and -2 in - * case of error - */ -static int -xmlSchemaCompareValuesWhtspExt(xmlSchemaValType xtype, - xmlSchemaValPtr x, - const xmlChar *xvalue, - xmlSchemaWhitespaceValueType xws, - xmlSchemaValType ytype, - xmlSchemaValPtr y, - const xmlChar *yvalue, - xmlSchemaWhitespaceValueType yws) -{ - return(xmlSchemaCompareValuesInternal(xtype, x, xvalue, xws, ytype, y, - yvalue, yws)); -} - -/** - * xmlSchemaNormLen: - * @value: a string - * - * Computes the UTF8 length of the normalized value of the string - * - * Returns the length or -1 in case of error. - */ -static int -xmlSchemaNormLen(const xmlChar *value) { - const xmlChar *utf; - int ret = 0; - - if (value == NULL) - return(-1); - utf = value; - while (IS_BLANK_CH(*utf)) utf++; - while (*utf != 0) { - if (utf[0] & 0x80) { - if ((utf[1] & 0xc0) != 0x80) - return(-1); - if ((utf[0] & 0xe0) == 0xe0) { - if ((utf[2] & 0xc0) != 0x80) - return(-1); - if ((utf[0] & 0xf0) == 0xf0) { - if ((utf[0] & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80) - return(-1); - utf += 4; - } else { - utf += 3; - } - } else { - utf += 2; - } - } else if (IS_BLANK_CH(*utf)) { - while (IS_BLANK_CH(*utf)) utf++; - if (*utf == 0) - break; - } else { - utf++; - } - ret++; - } - return(ret); -} - -/** - * xmlSchemaGetFacetValueAsULong: - * @facet: an schemas type facet - * - * Extract the value of a facet - * - * Returns the value as a long - */ -unsigned long -xmlSchemaGetFacetValueAsULong(xmlSchemaFacetPtr facet) -{ - /* - * TODO: Check if this is a decimal. - */ - if (facet == NULL) - return 0; - return ((unsigned long) facet->val->value.decimal.lo); -} - -/** - * xmlSchemaValidateListSimpleTypeFacet: - * @facet: the facet to check - * @value: the lexical repr of the value to validate - * @actualLen: the number of list items - * @expectedLen: the resulting expected number of list items - * - * Checks the value of a list simple type against a facet. - * - * Returns 0 if the value is valid, a positive error code - * number otherwise and -1 in case of an internal error. - */ -int -xmlSchemaValidateListSimpleTypeFacet(xmlSchemaFacetPtr facet, - const xmlChar *value, - unsigned long actualLen, - unsigned long *expectedLen) -{ - if (facet == NULL) - return(-1); - /* - * TODO: Check if this will work with large numbers. - * (compare value.decimal.mi and value.decimal.hi as well?). - */ - if (facet->type == XML_SCHEMA_FACET_LENGTH) { - if (actualLen != facet->val->value.decimal.lo) { - if (expectedLen != NULL) - *expectedLen = facet->val->value.decimal.lo; - return (XML_SCHEMAV_CVC_LENGTH_VALID); - } - } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { - if (actualLen < facet->val->value.decimal.lo) { - if (expectedLen != NULL) - *expectedLen = facet->val->value.decimal.lo; - return (XML_SCHEMAV_CVC_MINLENGTH_VALID); - } - } else if (facet->type == XML_SCHEMA_FACET_MAXLENGTH) { - if (actualLen > facet->val->value.decimal.lo) { - if (expectedLen != NULL) - *expectedLen = facet->val->value.decimal.lo; - return (XML_SCHEMAV_CVC_MAXLENGTH_VALID); - } - } else - /* - * NOTE: That we can pass NULL as xmlSchemaValPtr to - * xmlSchemaValidateFacet, since the remaining facet types - * are: XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION. - */ - return(xmlSchemaValidateFacet(NULL, facet, value, NULL)); - return (0); -} - -/** - * xmlSchemaValidateLengthFacet: - * @type: the built-in type - * @facet: the facet to check - * @value: the lexical repr. of the value to be validated - * @val: the precomputed value - * @ws: the whitespace type of the value - * @length: the actual length of the value - * - * Checka a value against a "length", "minLength" and "maxLength" - * facet; sets @length to the computed length of @value. - * - * Returns 0 if the value is valid, a positive error code - * otherwise and -1 in case of an internal or API error. - */ -static int -xmlSchemaValidateLengthFacetInternal(xmlSchemaFacetPtr facet, - xmlSchemaValType valType, - const xmlChar *value, - xmlSchemaValPtr val, - unsigned long *length, - xmlSchemaWhitespaceValueType ws) -{ - unsigned int len = 0; - - if ((length == NULL) || (facet == NULL)) - return (-1); - *length = 0; - if ((facet->type != XML_SCHEMA_FACET_LENGTH) && - (facet->type != XML_SCHEMA_FACET_MAXLENGTH) && - (facet->type != XML_SCHEMA_FACET_MINLENGTH)) - return (-1); - - /* - * TODO: length, maxLength and minLength must be of type - * nonNegativeInteger only. Check if decimal is used somehow. - */ - if ((facet->val == NULL) || - ((facet->val->type != XML_SCHEMAS_DECIMAL) && - (facet->val->type != XML_SCHEMAS_NNINTEGER)) || - (facet->val->value.decimal.frac != 0)) { - return(-1); - } - if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY)) - len = val->value.hex.total; - else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY)) - len = val->value.base64.total; - else { - switch (valType) { - case XML_SCHEMAS_STRING: - case XML_SCHEMAS_NORMSTRING: - if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) { - /* - * This is to ensure API compatibility with the old - * xmlSchemaValidateLengthFacet(). Anyway, this was and - * is not the correct handling. - * TODO: Get rid of this case somehow. - */ - if (valType == XML_SCHEMAS_STRING) - len = xmlUTF8Strlen(value); - else - len = xmlSchemaNormLen(value); - } else if (value != NULL) { - if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) - len = xmlSchemaNormLen(value); - else - /* - * Should be OK for "preserve" as well. - */ - len = xmlUTF8Strlen(value); - } - break; - case XML_SCHEMAS_IDREF: - case XML_SCHEMAS_TOKEN: - case XML_SCHEMAS_LANGUAGE: - case XML_SCHEMAS_NMTOKEN: - case XML_SCHEMAS_NAME: - case XML_SCHEMAS_NCNAME: - case XML_SCHEMAS_ID: - /* - * FIXME: What exactly to do with anyURI? - */ - case XML_SCHEMAS_ANYURI: - if (value != NULL) - len = xmlSchemaNormLen(value); - break; - case XML_SCHEMAS_QNAME: - case XML_SCHEMAS_NOTATION: - /* - * For QName and NOTATION, those facets are - * deprecated and should be ignored. - */ - return (0); - default: - TODO - } - } - *length = (unsigned long) len; - /* - * TODO: Return the whole expected value, i.e. "lo", "mi" and "hi". - */ - if (facet->type == XML_SCHEMA_FACET_LENGTH) { - if (len != facet->val->value.decimal.lo) - return(XML_SCHEMAV_CVC_LENGTH_VALID); - } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { - if (len < facet->val->value.decimal.lo) - return(XML_SCHEMAV_CVC_MINLENGTH_VALID); - } else { - if (len > facet->val->value.decimal.lo) - return(XML_SCHEMAV_CVC_MAXLENGTH_VALID); - } - - return (0); -} - -/** - * xmlSchemaValidateLengthFacet: - * @type: the built-in type - * @facet: the facet to check - * @value: the lexical repr. of the value to be validated - * @val: the precomputed value - * @length: the actual length of the value - * - * Checka a value against a "length", "minLength" and "maxLength" - * facet; sets @length to the computed length of @value. - * - * Returns 0 if the value is valid, a positive error code - * otherwise and -1 in case of an internal or API error. - */ -int -xmlSchemaValidateLengthFacet(xmlSchemaTypePtr type, - xmlSchemaFacetPtr facet, - const xmlChar *value, - xmlSchemaValPtr val, - unsigned long *length) -{ - if (type == NULL) - return(-1); - return (xmlSchemaValidateLengthFacetInternal(facet, - type->builtInType, value, val, length, - XML_SCHEMA_WHITESPACE_UNKNOWN)); -} - -/** - * xmlSchemaValidateLengthFacetWhtsp: - * @facet: the facet to check - * @valType: the built-in type - * @value: the lexical repr. of the value to be validated - * @val: the precomputed value - * @ws: the whitespace type of the value - * @length: the actual length of the value - * - * Checka a value against a "length", "minLength" and "maxLength" - * facet; sets @length to the computed length of @value. - * - * Returns 0 if the value is valid, a positive error code - * otherwise and -1 in case of an internal or API error. - */ -int -xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet, - xmlSchemaValType valType, - const xmlChar *value, - xmlSchemaValPtr val, - unsigned long *length, - xmlSchemaWhitespaceValueType ws) -{ - return (xmlSchemaValidateLengthFacetInternal(facet, valType, value, val, - length, ws)); -} - -/** - * xmlSchemaValidateFacetInternal: - * @facet: the facet to check - * @fws: the whitespace type of the facet's value - * @valType: the built-in type of the value - * @value: the lexical repr of the value to validate - * @val: the precomputed value - * @ws: the whitespace type of the value - * - * Check a value against a facet condition - * - * Returns 0 if the element is schemas valid, a positive error code - * number otherwise and -1 in case of internal or API error. - */ -static int -xmlSchemaValidateFacetInternal(xmlSchemaFacetPtr facet, - xmlSchemaWhitespaceValueType fws, - xmlSchemaValType valType, - const xmlChar *value, - xmlSchemaValPtr val, - xmlSchemaWhitespaceValueType ws) -{ - int ret; - int stringType; - - if (facet == NULL) - return(-1); - - switch (facet->type) { - case XML_SCHEMA_FACET_PATTERN: - /* - * NOTE that for patterns, the @value needs to be the normalized - * value, *not* the lexical initial value or the canonical value. - */ - if (value == NULL) - return(-1); - /* - * If string-derived type, regexp must be tested on the value space of - * the datatype. - * See https://www.w3.org/TR/xmlschema-2/#rf-pattern - */ - stringType = val && ((val->type >= XML_SCHEMAS_STRING && val->type <= XML_SCHEMAS_NORMSTRING) - || (val->type >= XML_SCHEMAS_TOKEN && val->type <= XML_SCHEMAS_NCNAME)); - ret = xmlRegexpExec(facet->regexp, - (stringType && val->value.str) ? val->value.str : value); - if (ret == 1) - return(0); - if (ret == 0) - return(XML_SCHEMAV_CVC_PATTERN_VALID); - return(ret); - case XML_SCHEMA_FACET_MAXEXCLUSIVE: - ret = xmlSchemaCompareValues(val, facet->val); - if (ret == -2) - return(-1); - if (ret == -1) - return(0); - return(XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID); - case XML_SCHEMA_FACET_MAXINCLUSIVE: - ret = xmlSchemaCompareValues(val, facet->val); - if (ret == -2) - return(-1); - if ((ret == -1) || (ret == 0)) - return(0); - return(XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID); - case XML_SCHEMA_FACET_MINEXCLUSIVE: - ret = xmlSchemaCompareValues(val, facet->val); - if (ret == -2) - return(-1); - if (ret == 1) - return(0); - return(XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID); - case XML_SCHEMA_FACET_MININCLUSIVE: - ret = xmlSchemaCompareValues(val, facet->val); - if (ret == -2) - return(-1); - if ((ret == 1) || (ret == 0)) - return(0); - return(XML_SCHEMAV_CVC_MININCLUSIVE_VALID); - case XML_SCHEMA_FACET_WHITESPACE: - /* TODO whitespaces */ - /* - * NOTE: Whitespace should be handled to normalize - * the value to be validated against a the facets; - * not to normalize the value in-between. - */ - return(0); - case XML_SCHEMA_FACET_ENUMERATION: - if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) { - /* - * This is to ensure API compatibility with the old - * xmlSchemaValidateFacet(). - * TODO: Get rid of this case. - */ - if ((facet->value != NULL) && - (xmlStrEqual(facet->value, value))) - return(0); - } else { - ret = xmlSchemaCompareValuesWhtspExt(facet->val->type, - facet->val, facet->value, fws, valType, val, - value, ws); - if (ret == -2) - return(-1); - if (ret == 0) - return(0); - } - return(XML_SCHEMAV_CVC_ENUMERATION_VALID); - case XML_SCHEMA_FACET_LENGTH: - /* - * SPEC (1.3) "if {primitive type definition} is QName or NOTATION, - * then any {value} is facet-valid." - */ - if ((valType == XML_SCHEMAS_QNAME) || - (valType == XML_SCHEMAS_NOTATION)) - return (0); - /* No break on purpose. */ - case XML_SCHEMA_FACET_MAXLENGTH: - case XML_SCHEMA_FACET_MINLENGTH: { - unsigned int len = 0; - - if ((valType == XML_SCHEMAS_QNAME) || - (valType == XML_SCHEMAS_NOTATION)) - return (0); - /* - * TODO: length, maxLength and minLength must be of type - * nonNegativeInteger only. Check if decimal is used somehow. - */ - if ((facet->val == NULL) || - ((facet->val->type != XML_SCHEMAS_DECIMAL) && - (facet->val->type != XML_SCHEMAS_NNINTEGER)) || - (facet->val->value.decimal.frac != 0)) { - return(-1); - } - if ((val != NULL) && (val->type == XML_SCHEMAS_HEXBINARY)) - len = val->value.hex.total; - else if ((val != NULL) && (val->type == XML_SCHEMAS_BASE64BINARY)) - len = val->value.base64.total; - else { - switch (valType) { - case XML_SCHEMAS_STRING: - case XML_SCHEMAS_NORMSTRING: - if (ws == XML_SCHEMA_WHITESPACE_UNKNOWN) { - /* - * This is to ensure API compatibility with the old - * xmlSchemaValidateFacet(). Anyway, this was and - * is not the correct handling. - * TODO: Get rid of this case somehow. - */ - if (valType == XML_SCHEMAS_STRING) - len = xmlUTF8Strlen(value); - else - len = xmlSchemaNormLen(value); - } else if (value != NULL) { - if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) - len = xmlSchemaNormLen(value); - else - /* - * Should be OK for "preserve" as well. - */ - len = xmlUTF8Strlen(value); - } - break; - case XML_SCHEMAS_IDREF: - case XML_SCHEMAS_TOKEN: - case XML_SCHEMAS_LANGUAGE: - case XML_SCHEMAS_NMTOKEN: - case XML_SCHEMAS_NAME: - case XML_SCHEMAS_NCNAME: - case XML_SCHEMAS_ID: - case XML_SCHEMAS_ANYURI: - if (value != NULL) - len = xmlSchemaNormLen(value); - break; - default: - TODO - } - } - if (facet->type == XML_SCHEMA_FACET_LENGTH) { - if (len != facet->val->value.decimal.lo) - return(XML_SCHEMAV_CVC_LENGTH_VALID); - } else if (facet->type == XML_SCHEMA_FACET_MINLENGTH) { - if (len < facet->val->value.decimal.lo) - return(XML_SCHEMAV_CVC_MINLENGTH_VALID); - } else { - if (len > facet->val->value.decimal.lo) - return(XML_SCHEMAV_CVC_MAXLENGTH_VALID); - } - break; - } - case XML_SCHEMA_FACET_TOTALDIGITS: - case XML_SCHEMA_FACET_FRACTIONDIGITS: - - if ((facet->val == NULL) || - ((facet->val->type != XML_SCHEMAS_PINTEGER) && - (facet->val->type != XML_SCHEMAS_NNINTEGER)) || - (facet->val->value.decimal.frac != 0)) { - return(-1); - } - if ((val == NULL) || - ((val->type != XML_SCHEMAS_DECIMAL) && - (val->type != XML_SCHEMAS_INTEGER) && - (val->type != XML_SCHEMAS_NPINTEGER) && - (val->type != XML_SCHEMAS_NINTEGER) && - (val->type != XML_SCHEMAS_NNINTEGER) && - (val->type != XML_SCHEMAS_PINTEGER) && - (val->type != XML_SCHEMAS_INT) && - (val->type != XML_SCHEMAS_UINT) && - (val->type != XML_SCHEMAS_LONG) && - (val->type != XML_SCHEMAS_ULONG) && - (val->type != XML_SCHEMAS_SHORT) && - (val->type != XML_SCHEMAS_USHORT) && - (val->type != XML_SCHEMAS_BYTE) && - (val->type != XML_SCHEMAS_UBYTE))) { - return(-1); - } - if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) { - if (val->value.decimal.total > facet->val->value.decimal.lo) - return(XML_SCHEMAV_CVC_TOTALDIGITS_VALID); - - } else if (facet->type == XML_SCHEMA_FACET_FRACTIONDIGITS) { - if (val->value.decimal.frac > facet->val->value.decimal.lo) - return(XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID); - } - break; - default: - TODO - } - return(0); - -} - -/** - * xmlSchemaValidateFacet: - * @base: the base type - * @facet: the facet to check - * @value: the lexical repr of the value to validate - * @val: the precomputed value - * - * Check a value against a facet condition - * - * Returns 0 if the element is schemas valid, a positive error code - * number otherwise and -1 in case of internal or API error. - */ -int -xmlSchemaValidateFacet(xmlSchemaTypePtr base, - xmlSchemaFacetPtr facet, - const xmlChar *value, - xmlSchemaValPtr val) -{ - /* - * This tries to ensure API compatibility regarding the old - * xmlSchemaValidateFacet() and the new xmlSchemaValidateFacetInternal() and - * xmlSchemaValidateFacetWhtsp(). - */ - if (val != NULL) - return(xmlSchemaValidateFacetInternal(facet, - XML_SCHEMA_WHITESPACE_UNKNOWN, val->type, value, val, - XML_SCHEMA_WHITESPACE_UNKNOWN)); - else if (base != NULL) - return(xmlSchemaValidateFacetInternal(facet, - XML_SCHEMA_WHITESPACE_UNKNOWN, base->builtInType, value, val, - XML_SCHEMA_WHITESPACE_UNKNOWN)); - return(-1); -} - -/** - * xmlSchemaValidateFacetWhtsp: - * @facet: the facet to check - * @fws: the whitespace type of the facet's value - * @valType: the built-in type of the value - * @value: the lexical (or normalized for pattern) repr of the value to validate - * @val: the precomputed value - * @ws: the whitespace type of the value - * - * Check a value against a facet condition. This takes value normalization - * according to the specified whitespace types into account. - * Note that @value needs to be the *normalized* value if the facet - * is of type "pattern". - * - * Returns 0 if the element is schemas valid, a positive error code - * number otherwise and -1 in case of internal or API error. - */ -int -xmlSchemaValidateFacetWhtsp(xmlSchemaFacetPtr facet, - xmlSchemaWhitespaceValueType fws, - xmlSchemaValType valType, - const xmlChar *value, - xmlSchemaValPtr val, - xmlSchemaWhitespaceValueType ws) -{ - return(xmlSchemaValidateFacetInternal(facet, fws, valType, - value, val, ws)); -} - -#if 0 -#ifndef DBL_DIG -#define DBL_DIG 16 -#endif -#ifndef DBL_EPSILON -#define DBL_EPSILON 1E-9 -#endif - -#define INTEGER_DIGITS DBL_DIG -#define FRACTION_DIGITS (DBL_DIG + 1) -#define EXPONENT_DIGITS (3 + 2) - -/** - * xmlXPathFormatNumber: - * @number: number to format - * @buffer: output buffer - * @buffersize: size of output buffer - * - * Convert the number into a string representation. - */ -static void -xmlSchemaFormatFloat(double number, char buffer[], int buffersize) -{ - switch (xmlXPathIsInf(number)) { - case 1: - if (buffersize > (int)sizeof("INF")) - snprintf(buffer, buffersize, "INF"); - break; - case -1: - if (buffersize > (int)sizeof("-INF")) - snprintf(buffer, buffersize, "-INF"); - break; - default: - if (xmlXPathIsNaN(number)) { - if (buffersize > (int)sizeof("NaN")) - snprintf(buffer, buffersize, "NaN"); - } else if (number == 0) { - snprintf(buffer, buffersize, "0.0E0"); - } else { - /* 3 is sign, decimal point, and terminating zero */ - char work[DBL_DIG + EXPONENT_DIGITS + 3]; - int integer_place, fraction_place; - char *ptr; - char *after_fraction; - double absolute_value; - int size; - - absolute_value = fabs(number); - - /* - * Result is in work, and after_fraction points - * just past the fractional part. - * Use scientific notation - */ - integer_place = DBL_DIG + EXPONENT_DIGITS + 1; - fraction_place = DBL_DIG - 1; - snprintf(work, sizeof(work),"%*.*e", - integer_place, fraction_place, number); - after_fraction = strchr(work + DBL_DIG, 'e'); - /* Remove fractional trailing zeroes */ - ptr = after_fraction; - while (*(--ptr) == '0') - ; - if (*ptr != '.') - ptr++; - while ((*ptr++ = *after_fraction++) != 0); - - /* Finally copy result back to caller */ - size = strlen(work) + 1; - if (size > buffersize) { - work[buffersize - 1] = 0; - size = buffersize; - } - memmove(buffer, work, size); - } - break; - } -} -#endif - -/** - * xmlSchemaGetCanonValue: - * @val: the precomputed value - * @retValue: the returned value - * - * Get the canonical lexical representation of the value. - * The caller has to FREE the returned retValue. - * - * WARNING: Some value types are not supported yet, resulting - * in a @retValue of "???". - * - * TODO: XML Schema 1.0 does not define canonical representations - * for: duration, gYearMonth, gYear, gMonthDay, gMonth, gDay, - * anyURI, QName, NOTATION. This will be fixed in XML Schema 1.1. - * - * - * Returns 0 if the value could be built, 1 if the value type is - * not supported yet and -1 in case of API errors. - */ -int -xmlSchemaGetCanonValue(xmlSchemaValPtr val, const xmlChar **retValue) -{ - if ((retValue == NULL) || (val == NULL)) - return (-1); - *retValue = NULL; - switch (val->type) { - case XML_SCHEMAS_STRING: - if (val->value.str == NULL) - *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); - else - *retValue = - BAD_CAST xmlStrdup((const xmlChar *) val->value.str); - break; - case XML_SCHEMAS_NORMSTRING: - if (val->value.str == NULL) - *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); - else { - *retValue = xmlSchemaWhiteSpaceReplace( - (const xmlChar *) val->value.str); - if ((*retValue) == NULL) - *retValue = BAD_CAST xmlStrdup( - (const xmlChar *) val->value.str); - } - break; - case XML_SCHEMAS_TOKEN: - case XML_SCHEMAS_LANGUAGE: - case XML_SCHEMAS_NMTOKEN: - case XML_SCHEMAS_NAME: - case XML_SCHEMAS_NCNAME: - case XML_SCHEMAS_ID: - case XML_SCHEMAS_IDREF: - case XML_SCHEMAS_ENTITY: - case XML_SCHEMAS_NOTATION: /* Unclear */ - case XML_SCHEMAS_ANYURI: /* Unclear */ - if (val->value.str == NULL) - return (-1); - *retValue = - BAD_CAST xmlSchemaCollapseString(BAD_CAST val->value.str); - if (*retValue == NULL) - *retValue = - BAD_CAST xmlStrdup((const xmlChar *) val->value.str); - break; - case XML_SCHEMAS_QNAME: - /* TODO: Unclear in XML Schema 1.0. */ - if (val->value.qname.uri == NULL) { - *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.qname.name); - return (0); - } else { - *retValue = BAD_CAST xmlStrdup(BAD_CAST "{"); - *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue), - BAD_CAST val->value.qname.uri); - *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue), - BAD_CAST "}"); - *retValue = BAD_CAST xmlStrcat((xmlChar *) (*retValue), - BAD_CAST val->value.qname.uri); - } - break; - case XML_SCHEMAS_DECIMAL: - /* - * TODO: Lookout for a more simple implementation. - */ - if ((val->value.decimal.total == 1) && - (val->value.decimal.lo == 0)) { - *retValue = xmlStrdup(BAD_CAST "0.0"); - } else { - xmlSchemaValDecimal dec = val->value.decimal; - int bufsize; - char *buf = NULL, *offs; - - /* Add room for the decimal point as well. */ - bufsize = dec.total + 2; - if (dec.sign) - bufsize++; - /* Add room for leading/trailing zero. */ - if ((dec.frac == 0) || (dec.frac == dec.total)) - bufsize++; - buf = xmlMalloc(bufsize); - if (buf == NULL) - return(-1); - offs = buf; - if (dec.sign) - *offs++ = '-'; - if (dec.frac == dec.total) { - *offs++ = '0'; - *offs++ = '.'; - } - if (dec.hi != 0) - snprintf(offs, bufsize - (offs - buf), - "%lu%lu%lu", dec.hi, dec.mi, dec.lo); - else if (dec.mi != 0) - snprintf(offs, bufsize - (offs - buf), - "%lu%lu", dec.mi, dec.lo); - else - snprintf(offs, bufsize - (offs - buf), - "%lu", dec.lo); - - if (dec.frac != 0) { - if (dec.frac != dec.total) { - int diff = dec.total - dec.frac; - /* - * Insert the decimal point. - */ - memmove(offs + diff + 1, offs + diff, dec.frac +1); - offs[diff] = '.'; - } else { - unsigned int i = 0; - /* - * Insert missing zeroes behind the decimal point. - */ - while (*(offs + i) != 0) - i++; - if (i < dec.total) { - memmove(offs + (dec.total - i), offs, i +1); - memset(offs, '0', dec.total - i); - } - } - } else { - /* - * Append decimal point and zero. - */ - offs = buf + bufsize - 1; - *offs-- = 0; - *offs-- = '0'; - *offs-- = '.'; - } - *retValue = BAD_CAST buf; - } - break; - case XML_SCHEMAS_INTEGER: - case XML_SCHEMAS_PINTEGER: - case XML_SCHEMAS_NPINTEGER: - case XML_SCHEMAS_NINTEGER: - case XML_SCHEMAS_NNINTEGER: - case XML_SCHEMAS_LONG: - case XML_SCHEMAS_BYTE: - case XML_SCHEMAS_SHORT: - case XML_SCHEMAS_INT: - case XML_SCHEMAS_UINT: - case XML_SCHEMAS_ULONG: - case XML_SCHEMAS_USHORT: - case XML_SCHEMAS_UBYTE: - if ((val->value.decimal.total == 1) && - (val->value.decimal.lo == 0)) - *retValue = xmlStrdup(BAD_CAST "0"); - else { - xmlSchemaValDecimal dec = val->value.decimal; - int bufsize = dec.total + 1; - - /* Add room for the decimal point as well. */ - if (dec.sign) - bufsize++; - *retValue = xmlMalloc(bufsize); - if (*retValue == NULL) - return(-1); - if (dec.hi != 0) { - if (dec.sign) - snprintf((char *) *retValue, bufsize, - "-%lu%lu%lu", dec.hi, dec.mi, dec.lo); - else - snprintf((char *) *retValue, bufsize, - "%lu%lu%lu", dec.hi, dec.mi, dec.lo); - } else if (dec.mi != 0) { - if (dec.sign) - snprintf((char *) *retValue, bufsize, - "-%lu%lu", dec.mi, dec.lo); - else - snprintf((char *) *retValue, bufsize, - "%lu%lu", dec.mi, dec.lo); - } else { - if (dec.sign) - snprintf((char *) *retValue, bufsize, "-%lu", dec.lo); - else - snprintf((char *) *retValue, bufsize, "%lu", dec.lo); - } - } - break; - case XML_SCHEMAS_BOOLEAN: - if (val->value.b) - *retValue = BAD_CAST xmlStrdup(BAD_CAST "true"); - else - *retValue = BAD_CAST xmlStrdup(BAD_CAST "false"); - break; - case XML_SCHEMAS_DURATION: { - char buf[100]; - unsigned long year; - unsigned long mon, day, hour = 0, min = 0; - double sec = 0, left; - - /* TODO: Unclear in XML Schema 1.0 */ - /* - * TODO: This results in a normalized output of the value - * - which is NOT conformant to the spec - - * since the exact values of each property are not - * recoverable. Think about extending the structure to - * provide a field for every property. - */ - year = (unsigned long) FQUOTIENT(labs(val->value.dur.mon), 12); - mon = labs(val->value.dur.mon) - 12 * year; - - day = (unsigned long) FQUOTIENT(fabs(val->value.dur.sec), 86400); - left = fabs(val->value.dur.sec) - day * 86400; - if (left > 0) { - hour = (unsigned long) FQUOTIENT(left, 3600); - left = left - (hour * 3600); - if (left > 0) { - min = (unsigned long) FQUOTIENT(left, 60); - sec = left - (min * 60); - } - } - if ((val->value.dur.mon < 0) || (val->value.dur.sec < 0)) - snprintf(buf, 100, "P%luY%luM%luDT%luH%luM%.14gS", - year, mon, day, hour, min, sec); - else - snprintf(buf, 100, "-P%luY%luM%luDT%luH%luM%.14gS", - year, mon, day, hour, min, sec); - *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); - } - break; - case XML_SCHEMAS_GYEAR: { - char buf[30]; - /* TODO: Unclear in XML Schema 1.0 */ - /* TODO: What to do with the timezone? */ - snprintf(buf, 30, "%04ld", val->value.date.year); - *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); - } - break; - case XML_SCHEMAS_GMONTH: { - /* TODO: Unclear in XML Schema 1.0 */ - /* TODO: What to do with the timezone? */ - *retValue = xmlMalloc(6); - if (*retValue == NULL) - return(-1); - snprintf((char *) *retValue, 6, "--%02u", - val->value.date.mon); - } - break; - case XML_SCHEMAS_GDAY: { - /* TODO: Unclear in XML Schema 1.0 */ - /* TODO: What to do with the timezone? */ - *retValue = xmlMalloc(6); - if (*retValue == NULL) - return(-1); - snprintf((char *) *retValue, 6, "---%02u", - val->value.date.day); - } - break; - case XML_SCHEMAS_GMONTHDAY: { - /* TODO: Unclear in XML Schema 1.0 */ - /* TODO: What to do with the timezone? */ - *retValue = xmlMalloc(8); - if (*retValue == NULL) - return(-1); - snprintf((char *) *retValue, 8, "--%02u-%02u", - val->value.date.mon, val->value.date.day); - } - break; - case XML_SCHEMAS_GYEARMONTH: { - char buf[35]; - /* TODO: Unclear in XML Schema 1.0 */ - /* TODO: What to do with the timezone? */ - if (val->value.date.year < 0) - snprintf(buf, 35, "-%04ld-%02u", - labs(val->value.date.year), - val->value.date.mon); - else - snprintf(buf, 35, "%04ld-%02u", - val->value.date.year, val->value.date.mon); - *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); - } - break; - case XML_SCHEMAS_TIME: - { - char buf[30]; - - if (val->value.date.tz_flag) { - xmlSchemaValPtr norm; - - norm = xmlSchemaDateNormalize(val, 0); - if (norm == NULL) - return (-1); - /* - * TODO: Check if "%.14g" is portable. - */ - snprintf(buf, 30, - "%02u:%02u:%02.14gZ", - norm->value.date.hour, - norm->value.date.min, - norm->value.date.sec); - xmlSchemaFreeValue(norm); - } else { - snprintf(buf, 30, - "%02u:%02u:%02.14g", - val->value.date.hour, - val->value.date.min, - val->value.date.sec); - } - *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); - } - break; - case XML_SCHEMAS_DATE: - { - char buf[30]; - - if (val->value.date.tz_flag) { - xmlSchemaValPtr norm; - - norm = xmlSchemaDateNormalize(val, 0); - if (norm == NULL) - return (-1); - /* - * TODO: Append the canonical value of the - * recoverable timezone and not "Z". - */ - snprintf(buf, 30, - "%04ld:%02u:%02uZ", - norm->value.date.year, norm->value.date.mon, - norm->value.date.day); - xmlSchemaFreeValue(norm); - } else { - snprintf(buf, 30, - "%04ld:%02u:%02u", - val->value.date.year, val->value.date.mon, - val->value.date.day); - } - *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); - } - break; - case XML_SCHEMAS_DATETIME: - { - char buf[50]; - - if (val->value.date.tz_flag) { - xmlSchemaValPtr norm; - - norm = xmlSchemaDateNormalize(val, 0); - if (norm == NULL) - return (-1); - /* - * TODO: Check if "%.14g" is portable. - */ - snprintf(buf, 50, - "%04ld:%02u:%02uT%02u:%02u:%02.14gZ", - norm->value.date.year, norm->value.date.mon, - norm->value.date.day, norm->value.date.hour, - norm->value.date.min, norm->value.date.sec); - xmlSchemaFreeValue(norm); - } else { - snprintf(buf, 50, - "%04ld:%02u:%02uT%02u:%02u:%02.14g", - val->value.date.year, val->value.date.mon, - val->value.date.day, val->value.date.hour, - val->value.date.min, val->value.date.sec); - } - *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); - } - break; - case XML_SCHEMAS_HEXBINARY: - *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.hex.str); - break; - case XML_SCHEMAS_BASE64BINARY: - /* - * TODO: Is the following spec piece implemented?: - * SPEC: "Note: For some values the canonical form defined - * above does not conform to [RFC 2045], which requires breaking - * with linefeeds at appropriate intervals." - */ - *retValue = BAD_CAST xmlStrdup(BAD_CAST val->value.base64.str); - break; - case XML_SCHEMAS_FLOAT: { - char buf[30]; - /* - * |m| < 16777216, -149 <= e <= 104. - * TODO: Handle, NaN, INF, -INF. The format is not - * yet conformant. The c type float does not cover - * the whole range. - */ - snprintf(buf, 30, "%01.14e", val->value.f); - *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); - } - break; - case XML_SCHEMAS_DOUBLE: { - char buf[40]; - /* |m| < 9007199254740992, -1075 <= e <= 970 */ - /* - * TODO: Handle, NaN, INF, -INF. The format is not - * yet conformant. The c type float does not cover - * the whole range. - */ - snprintf(buf, 40, "%01.14e", val->value.d); - *retValue = BAD_CAST xmlStrdup(BAD_CAST buf); - } - break; - default: - *retValue = BAD_CAST xmlStrdup(BAD_CAST "???"); - return (1); - } - if (*retValue == NULL) - return(-1); - return (0); -} - -/** - * xmlSchemaGetCanonValueWhtsp: - * @val: the precomputed value - * @retValue: the returned value - * @ws: the whitespace type of the value - * - * Get the canonical representation of the value. - * The caller has to free the returned @retValue. - * - * Returns 0 if the value could be built, 1 if the value type is - * not supported yet and -1 in case of API errors. - */ -int -xmlSchemaGetCanonValueWhtsp(xmlSchemaValPtr val, - const xmlChar **retValue, - xmlSchemaWhitespaceValueType ws) -{ - if ((retValue == NULL) || (val == NULL)) - return (-1); - if ((ws == XML_SCHEMA_WHITESPACE_UNKNOWN) || - (ws > XML_SCHEMA_WHITESPACE_COLLAPSE)) - return (-1); - - *retValue = NULL; - switch (val->type) { - case XML_SCHEMAS_STRING: - if (val->value.str == NULL) - *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); - else if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) - *retValue = xmlSchemaCollapseString(val->value.str); - else if (ws == XML_SCHEMA_WHITESPACE_REPLACE) - *retValue = xmlSchemaWhiteSpaceReplace(val->value.str); - if ((*retValue) == NULL) - *retValue = BAD_CAST xmlStrdup(val->value.str); - break; - case XML_SCHEMAS_NORMSTRING: - if (val->value.str == NULL) - *retValue = BAD_CAST xmlStrdup(BAD_CAST ""); - else { - if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE) - *retValue = xmlSchemaCollapseString(val->value.str); - else - *retValue = xmlSchemaWhiteSpaceReplace(val->value.str); - if ((*retValue) == NULL) - *retValue = BAD_CAST xmlStrdup(val->value.str); - } - break; - default: - return (xmlSchemaGetCanonValue(val, retValue)); - } - return (0); -} - -/** - * xmlSchemaGetValType: - * @val: a schemas value - * - * Accessor for the type of a value - * - * Returns the xmlSchemaValType of the value - */ -xmlSchemaValType -xmlSchemaGetValType(xmlSchemaValPtr val) -{ - if (val == NULL) - return(XML_SCHEMAS_UNKNOWN); - return (val->type); -} - -#define bottom_xmlschemastypes -#include "elfgcchack.h" -#endif /* LIBXML_SCHEMAS_ENABLED */ |